Merge branch 'master' into ts/type-create-screen-modal

This commit is contained in:
Adria Navarro 2025-05-07 10:41:48 +02:00 committed by GitHub
commit 647cd56912
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 105 additions and 27 deletions

View File

@ -78,15 +78,17 @@
prompt: promptText, prompt: promptText,
}) })
dispatch("reject", { code: previousContents }) dispatch("reject", { code: previousContents })
reset() reset(false)
} }
function reset() { function reset(clearPrompt: boolean = true) {
if (clearPrompt) {
promptText = ""
inputValue = ""
}
suggestedCode = null suggestedCode = null
previousContents = null previousContents = null
promptText = ""
expanded = false expanded = false
inputValue = ""
} }
</script> </script>

View File

@ -918,7 +918,9 @@ if (descriptions.length) {
describe("get", () => { describe("get", () => {
it("reads an existing row successfully", async () => { it("reads an existing row successfully", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
const res = await config.api.row.get(table._id!, existing._id!) const res = await config.api.row.get(table._id!, existing._id!)
@ -930,7 +932,7 @@ if (descriptions.length) {
it("returns 404 when row does not exist", async () => { it("returns 404 when row does not exist", async () => {
const table = await config.api.table.save(defaultTable()) const table = await config.api.table.save(defaultTable())
await config.api.row.save(table._id!, {}) await config.api.row.save(table._id!, { name: "foo" })
await config.api.row.get(table._id!, "1234567", { await config.api.row.get(table._id!, "1234567", {
status: 404, status: 404,
}) })
@ -958,8 +960,8 @@ if (descriptions.length) {
it("fetches all rows for given tableId", async () => { it("fetches all rows for given tableId", async () => {
const table = await config.api.table.save(defaultTable()) const table = await config.api.table.save(defaultTable())
const rows = await Promise.all([ const rows = await Promise.all([
config.api.row.save(table._id!, {}), config.api.row.save(table._id!, { name: "foo" }),
config.api.row.save(table._id!, {}), config.api.row.save(table._id!, { name: "bar" }),
]) ])
const res = await config.api.row.fetch(table._id!) const res = await config.api.row.fetch(table._id!)
@ -975,7 +977,9 @@ if (descriptions.length) {
describe("update", () => { describe("update", () => {
it("updates an existing row successfully", async () => { it("updates an existing row successfully", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
await expectRowUsage(0, async () => { await expectRowUsage(0, async () => {
const res = await config.api.row.save(table._id!, { const res = await config.api.row.save(table._id!, {
@ -1166,7 +1170,9 @@ if (descriptions.length) {
}) })
it("should update only the fields that are supplied", async () => { it("should update only the fields that are supplied", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
await expectRowUsage(0, async () => { await expectRowUsage(0, async () => {
const row = await config.api.row.patch(table._id!, { const row = await config.api.row.patch(table._id!, {
@ -1186,6 +1192,22 @@ if (descriptions.length) {
}) })
}) })
it("should not require the primary display", async () => {
const existing = await config.api.row.save(table._id!, {
name: "foo",
description: "bar",
})
await expectRowUsage(0, async () => {
const row = await config.api.row.patch(table._id!, {
_id: existing._id!,
_rev: existing._rev!,
tableId: table._id!,
description: "baz",
})
expect(row.description).toEqual("baz")
})
})
it("should update only the fields that are supplied and emit the correct oldRow", async () => { it("should update only the fields that are supplied and emit the correct oldRow", async () => {
let beforeRow = await config.api.row.save(table._id!, { let beforeRow = await config.api.row.save(table._id!, {
name: "test", name: "test",
@ -1213,7 +1235,9 @@ if (descriptions.length) {
}) })
it("should throw an error when given improper types", async () => { it("should throw an error when given improper types", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
await expectRowUsage(0, async () => { await expectRowUsage(0, async () => {
await config.api.row.patch( await config.api.row.patch(
@ -1289,6 +1313,7 @@ if (descriptions.length) {
description: "test", description: "test",
}) })
const { _id } = await config.api.row.save(table._id!, { const { _id } = await config.api.row.save(table._id!, {
name: "test",
relationship: [{ _id: row._id }, { _id: row2._id }], relationship: [{ _id: row._id }, { _id: row2._id }],
}) })
const relatedRow = await config.api.row.get(table._id!, _id!, { const relatedRow = await config.api.row.get(table._id!, _id!, {
@ -1440,7 +1465,9 @@ if (descriptions.length) {
}) })
it("should be able to delete a row", async () => { it("should be able to delete a row", async () => {
const createdRow = await config.api.row.save(table._id!, {}) const createdRow = await config.api.row.save(table._id!, {
name: "foo",
})
await expectRowUsage(isInternal ? -1 : 0, async () => { await expectRowUsage(isInternal ? -1 : 0, async () => {
const res = await config.api.row.bulkDelete(table._id!, { const res = await config.api.row.bulkDelete(table._id!, {
@ -1451,7 +1478,9 @@ if (descriptions.length) {
}) })
it("should be able to delete a row with ID only", async () => { it("should be able to delete a row with ID only", async () => {
const createdRow = await config.api.row.save(table._id!, {}) const createdRow = await config.api.row.save(table._id!, {
name: "foo",
})
await expectRowUsage(isInternal ? -1 : 0, async () => { await expectRowUsage(isInternal ? -1 : 0, async () => {
const res = await config.api.row.bulkDelete(table._id!, { const res = await config.api.row.bulkDelete(table._id!, {
@ -1463,8 +1492,12 @@ if (descriptions.length) {
}) })
it("should be able to bulk delete rows, including a row that doesn't exist", async () => { it("should be able to bulk delete rows, including a row that doesn't exist", async () => {
const createdRow = await config.api.row.save(table._id!, {}) const createdRow = await config.api.row.save(table._id!, {
const createdRow2 = await config.api.row.save(table._id!, {}) name: "foo",
})
const createdRow2 = await config.api.row.save(table._id!, {
name: "bar",
})
const res = await config.api.row.bulkDelete(table._id!, { const res = await config.api.row.bulkDelete(table._id!, {
rows: [createdRow, createdRow2, { _id: "9999999" }], rows: [createdRow, createdRow2, { _id: "9999999" }],
@ -1581,8 +1614,8 @@ if (descriptions.length) {
}) })
it("should be able to delete a bulk set of rows", async () => { it("should be able to delete a bulk set of rows", async () => {
const row1 = await config.api.row.save(table._id!, {}) const row1 = await config.api.row.save(table._id!, { name: "foo" })
const row2 = await config.api.row.save(table._id!, {}) const row2 = await config.api.row.save(table._id!, { name: "bar" })
await expectRowUsage(isInternal ? -2 : 0, async () => { await expectRowUsage(isInternal ? -2 : 0, async () => {
const res = await config.api.row.bulkDelete(table._id!, { const res = await config.api.row.bulkDelete(table._id!, {
@ -1596,9 +1629,9 @@ if (descriptions.length) {
it("should be able to delete a variety of row set types", async () => { it("should be able to delete a variety of row set types", async () => {
const [row1, row2, row3] = await Promise.all([ const [row1, row2, row3] = await Promise.all([
config.api.row.save(table._id!, {}), config.api.row.save(table._id!, { name: "foo" }),
config.api.row.save(table._id!, {}), config.api.row.save(table._id!, { name: "bar" }),
config.api.row.save(table._id!, {}), config.api.row.save(table._id!, { name: "baz" }),
]) ])
await expectRowUsage(isInternal ? -3 : 0, async () => { await expectRowUsage(isInternal ? -3 : 0, async () => {
@ -1612,7 +1645,7 @@ if (descriptions.length) {
}) })
it("should accept a valid row object and delete the row", async () => { it("should accept a valid row object and delete the row", async () => {
const row1 = await config.api.row.save(table._id!, {}) const row1 = await config.api.row.save(table._id!, { name: "foo" })
await expectRowUsage(isInternal ? -1 : 0, async () => { await expectRowUsage(isInternal ? -1 : 0, async () => {
const res = await config.api.row.delete( const res = await config.api.row.delete(
@ -2347,7 +2380,9 @@ if (descriptions.length) {
!isInternal && !isInternal &&
it("should allow exporting all columns", async () => { it("should allow exporting all columns", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
const res = await config.api.row.exportRows(table._id!, { const res = await config.api.row.exportRows(table._id!, {
rows: [existing._id!], rows: [existing._id!],
}) })
@ -2363,7 +2398,9 @@ if (descriptions.length) {
}) })
it("should allow exporting without filtering", async () => { it("should allow exporting without filtering", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
const res = await config.api.row.exportRows(table._id!) const res = await config.api.row.exportRows(table._id!)
const results = JSON.parse(res) const results = JSON.parse(res)
expect(results.length).toEqual(1) expect(results.length).toEqual(1)
@ -2373,7 +2410,9 @@ if (descriptions.length) {
}) })
it("should allow exporting only certain columns", async () => { it("should allow exporting only certain columns", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
const res = await config.api.row.exportRows(table._id!, { const res = await config.api.row.exportRows(table._id!, {
rows: [existing._id!], rows: [existing._id!],
columns: ["_id"], columns: ["_id"],
@ -2388,7 +2427,9 @@ if (descriptions.length) {
}) })
it("should handle single quotes in row filtering", async () => { it("should handle single quotes in row filtering", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
const res = await config.api.row.exportRows(table._id!, { const res = await config.api.row.exportRows(table._id!, {
rows: [`['${existing._id!}']`], rows: [`['${existing._id!}']`],
}) })
@ -2399,7 +2440,9 @@ if (descriptions.length) {
}) })
it("should return an error if no table is found", async () => { it("should return an error if no table is found", async () => {
const existing = await config.api.row.save(table._id!, {}) const existing = await config.api.row.save(table._id!, {
name: "foo",
})
await config.api.row.exportRows( await config.api.row.exportRows(
"1234567", "1234567",
{ rows: [existing._id!] }, { rows: [existing._id!] },

View File

@ -375,4 +375,31 @@ describe("validate", () => {
}) })
}) })
}) })
describe("primary display", () => {
const getTable = (): Table => ({
type: "table",
_id: generateTableID(),
name: "table",
sourceId: INTERNAL_TABLE_SOURCE_ID,
sourceType: TableSourceType.INTERNAL,
primaryDisplay: "foo",
schema: {
foo: {
name: "foo",
type: FieldType.STRING,
},
},
})
it("should always require primary display column", async () => {
const row = {}
const table = getTable()
const output = await validate({ source: table, row })
expect(output.valid).toBe(false)
expect(output.errors).toStrictEqual({
foo: ["can't be blank"],
})
})
})
}) })

View File

@ -206,8 +206,14 @@ export async function validate({
] ]
for (let fieldName of Object.keys(table.schema)) { for (let fieldName of Object.keys(table.schema)) {
const column = table.schema[fieldName] const column = table.schema[fieldName]
const constraints = cloneDeep(column.constraints)
const type = column.type const type = column.type
let constraints = cloneDeep(column.constraints)
// Ensure display column is required
if (table.primaryDisplay === fieldName) {
constraints = { ...constraints, presence: true }
}
// foreign keys are likely to be enriched // foreign keys are likely to be enriched
if (isForeignKey(fieldName, table)) { if (isForeignKey(fieldName, table)) {
continue continue