diff --git a/packages/server/src/sdk/app/views/index.ts b/packages/server/src/sdk/app/views/index.ts index 7e75f22060..3513df0c56 100644 --- a/packages/server/src/sdk/app/views/index.ts +++ b/packages/server/src/sdk/app/views/index.ts @@ -106,3 +106,21 @@ export function enrichSchema(view: View | ViewV2, tableSchema: TableSchema) { schema: schema, } } + +export function syncSchema(view: ViewV2, schema: TableSchema): ViewV2 { + if (view.schemaUI) { + for (const fieldName of Object.keys(view.schemaUI)) { + if (!schema[fieldName]) { + delete view.schemaUI[fieldName] + } + } + for (const fieldName of Object.keys(schema)) { + if (!view.schemaUI[fieldName]) { + view.schemaUI[fieldName] = { visible: false } + } + } + } + + view.columns = view.columns?.filter(x => schema[x]) + return view +} diff --git a/packages/server/src/sdk/app/views/tests/views.spec.ts b/packages/server/src/sdk/app/views/tests/views.spec.ts index 3b1cb84a42..1ba488a885 100644 --- a/packages/server/src/sdk/app/views/tests/views.spec.ts +++ b/packages/server/src/sdk/app/views/tests/views.spec.ts @@ -1,53 +1,54 @@ +import _ from "lodash" import { FieldType, Table, ViewV2 } from "@budibase/types" import { generator } from "@budibase/backend-core/tests" -import { enrichSchema } from ".." +import { enrichSchema, syncSchema } from ".." describe("table sdk", () => { - describe("enrichViewSchemas", () => { - const basicTable: Table = { - _id: generator.guid(), - name: "TestTable", - type: "table", - schema: { - name: { - type: FieldType.STRING, - name: "name", - visible: true, - width: 80, - order: 2, - constraints: { - type: "string", - }, - }, - description: { - type: FieldType.STRING, - name: "description", - visible: true, - width: 200, - constraints: { - type: "string", - }, - }, - id: { - type: FieldType.NUMBER, - name: "id", - visible: true, - order: 1, - constraints: { - type: "number", - }, - }, - hiddenField: { - type: FieldType.STRING, - name: "hiddenField", - visible: false, - constraints: { - type: "string", - }, + const basicTable: Table = { + _id: generator.guid(), + name: "TestTable", + type: "table", + schema: { + name: { + type: FieldType.STRING, + name: "name", + visible: true, + width: 80, + order: 2, + constraints: { + type: "string", }, }, - } + description: { + type: FieldType.STRING, + name: "description", + visible: true, + width: 200, + constraints: { + type: "string", + }, + }, + id: { + type: FieldType.NUMBER, + name: "id", + visible: true, + order: 1, + constraints: { + type: "number", + }, + }, + hiddenField: { + type: FieldType.STRING, + name: "hiddenField", + visible: false, + constraints: { + type: "string", + }, + }, + }, + } + describe("enrichViewSchemas", () => { it("should fetch the default schema if not overriden", async () => { const tableId = basicTable._id! const view: ViewV2 = { @@ -280,4 +281,178 @@ describe("table sdk", () => { ) }) }) + + describe.only("syncSchema", () => { + const basicView: ViewV2 = { + version: 2, + id: generator.guid(), + name: generator.guid(), + tableId: basicTable._id!, + } + + describe("view without schema", () => { + it("no table schema changes will not amend the view", () => { + const view = { + ...basicView, + columns: ["name", "id", "description"], + } + const result = syncSchema(_.cloneDeep(view), basicTable.schema) + expect(result).toEqual(view) + }) + + it("adding new columns will not change the view schema", () => { + const view = { + ...basicView, + columns: ["name", "id", "description"], + } + + const newTableSchema = { + ...basicTable.schema, + newField1: { + type: FieldType.STRING, + name: "newField1", + visible: true, + }, + newField2: { + type: FieldType.NUMBER, + name: "newField2", + visible: false, + }, + } + + const result = syncSchema(_.cloneDeep(view), newTableSchema) + expect(result).toEqual({ + ...view, + schemaUI: undefined, + }) + }) + + it("deleting columns will not change the view schema", () => { + const view = { + ...basicView, + columns: ["name", "id", "description"], + } + const { name, description, ...newTableSchema } = basicTable.schema + + const result = syncSchema(_.cloneDeep(view), newTableSchema) + expect(result).toEqual({ + ...view, + columns: ["id"], + schemaUI: undefined, + }) + }) + }) + + describe("view with schema", () => { + it("no table schema changes will not amend the view", () => { + const view = { + ...basicView, + columns: ["name", "id", "description"], + schemaUI: { + name: { visible: true, width: 100 }, + id: { visible: true, width: 20 }, + description: { visible: false }, + hiddenField: { visible: false }, + }, + } + const result = syncSchema(_.cloneDeep(view), basicTable.schema) + expect(result).toEqual(view) + }) + + it("adding new columns will add them as not visible to the view", () => { + const view = { + ...basicView, + columns: ["name", "id", "description"], + schemaUI: { + name: { visible: true, width: 100 }, + id: { visible: true, width: 20 }, + description: { visible: false }, + hiddenField: { visible: false }, + }, + } + + const newTableSchema = { + ...basicTable.schema, + newField1: { + type: FieldType.STRING, + name: "newField1", + visible: true, + }, + newField2: { + type: FieldType.NUMBER, + name: "newField2", + visible: false, + }, + } + + const result = syncSchema(_.cloneDeep(view), newTableSchema) + expect(result).toEqual({ + ...view, + schemaUI: { + ...view.schemaUI, + newField1: { visible: false }, + newField2: { visible: false }, + }, + }) + }) + + it("deleting columns will remove them from the UI", () => { + const view = { + ...basicView, + columns: ["name", "id", "description"], + schemaUI: { + name: { visible: true, width: 100 }, + id: { visible: true, width: 20 }, + description: { visible: false }, + hiddenField: { visible: false }, + }, + } + const { name, description, ...newTableSchema } = basicTable.schema + + const result = syncSchema(_.cloneDeep(view), newTableSchema) + expect(result).toEqual({ + ...view, + columns: ["id"], + schemaUI: { + ...view.schemaUI, + name: undefined, + description: undefined, + }, + }) + }) + + it("can handle additions and deletions at the same them UI", () => { + const view = { + ...basicView, + columns: ["name", "id", "description"], + schemaUI: { + name: { visible: true, width: 100 }, + id: { visible: true, width: 20 }, + description: { visible: false }, + hiddenField: { visible: false }, + }, + } + const { name, description, ...newTableSchema } = { + ...basicTable.schema, + newField1: { + type: FieldType.STRING, + name: "newField1", + visible: true, + }, + } as any + + const result = syncSchema(_.cloneDeep(view), newTableSchema) + expect(result).toEqual({ + ...view, + columns: ["id"], + schemaUI: { + ...view.schemaUI, + name: undefined, + description: undefined, + newField1: { visible: false }, + }, + }) + }) + }) + }) })