From c9abb0148e1d5842c45a7b34efc4e9c1cc467a64 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 20 Oct 2021 14:51:44 +0100 Subject: [PATCH 1/3] Fix view filters not accounting for invalid column names --- .../DataTable/modals/FilterModal.svelte | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/builder/src/components/backend/DataTable/modals/FilterModal.svelte b/packages/builder/src/components/backend/DataTable/modals/FilterModal.svelte index 9c6f4956b0..12e5f23814 100644 --- a/packages/builder/src/components/backend/DataTable/modals/FilterModal.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/FilterModal.svelte @@ -82,34 +82,30 @@ function isMultipleChoice(field) { return ( - (viewTable.schema[field].constraints && - viewTable.schema[field].constraints.inclusion && - viewTable.schema[field].constraints.inclusion.length) || - viewTable.schema[field].type === "boolean" + viewTable.schema[field]?.constraints?.inclusion?.length || + viewTable.schema[field]?.type === "boolean" ) } function fieldOptions(field) { - return viewTable.schema[field].type === "options" - ? viewTable.schema[field].constraints.inclusion + return viewTable.schema[field]?.type === "options" + ? viewTable.schema[field]?.constraints.inclusion : [true, false] } function isDate(field) { - return viewTable.schema[field].type === "datetime" + return viewTable.schema[field]?.type === "datetime" } function isNumber(field) { - return viewTable.schema[field].type === "number" + return viewTable.schema[field]?.type === "number" } const fieldChanged = filter => ev => { - // reset if type changed - if ( - filter.key && - ev.detail && - viewTable.schema[filter.key].type !== viewTable.schema[ev.detail].type - ) { + // Reset if type changed + const oldType = viewTable.schema[filter.key]?.type + const newType = viewTable.schema[ev.detail]?.type + if (filter.key && ev.detail && oldType !== newType) { filter.value = "" } } From 0f2b50b9f1df4245d52d5eea7c7fab0dfc3a124c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 20 Oct 2021 20:01:49 +0100 Subject: [PATCH 2/3] Keep views up to date with table schema changes --- .../server/src/api/controllers/table/utils.js | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/packages/server/src/api/controllers/table/utils.js b/packages/server/src/api/controllers/table/utils.js index fd3ea6693c..9b5f11d865 100644 --- a/packages/server/src/api/controllers/table/utils.js +++ b/packages/server/src/api/controllers/table/utils.js @@ -13,6 +13,8 @@ const { isExternalTable, breakExternalTableId, } = require("../../../integrations/utils") +const { getViews, saveView } = require("../view/utils") +const viewTemplate = require("../view/viewBuilder") exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => { let updatedRows = [] @@ -25,6 +27,7 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => { } // check for renaming of columns or deleted columns if (rename || deletedColumns.length !== 0) { + // Update all rows const rows = await db.allDocs( getRowParams(updatedTable._id, null, { include_docs: true, @@ -39,6 +42,9 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => { } return doc }) + + // Update views + await exports.checkForViewUpdates(db, updatedTable, rename, deletedColumns) delete updatedTable._rename } return { rows: updatedRows, table: updatedTable } @@ -237,4 +243,74 @@ exports.getTable = async (appId, tableId) => { } } +exports.checkForViewUpdates = async (db, table, rename, deletedColumns) => { + const views = await getViews(db) + const tableViews = views.filter(view => view.meta.tableId === table._id) + + // Check each table view to see if impacted by this table action + for (let view of tableViews) { + let needsUpdated = false + + // First check for renames, otherwise check for deletions + if (rename) { + // Update calculation field if required + if (view.meta.field === rename.old) { + view.meta.field = rename.updated + needsUpdated = true + } + + // Update group by field if required + if (view.meta.groupBy === rename.old) { + view.meta.groupBy = rename.updated + needsUpdated = true + } + + // Update filters if required + view.meta.filters?.forEach(filter => { + if (filter.key === rename.old) { + filter.key = rename.updated + needsUpdated = true + } + }) + } else if (deletedColumns?.length) { + deletedColumns.forEach(column => { + // Remove calculation statement if required + if (view.meta.field === column) { + delete view.meta.field + delete view.meta.calculation + delete view.meta.groupBy + needsUpdated = true + } + + // Remove group by field if required + if (view.meta.groupBy === column) { + delete view.meta.groupBy + needsUpdated = true + } + + // Remove filters referencing deleted field if required + if (view.meta.filters?.length) { + const initialLength = view.meta.filters.length + view.meta.filters = view.meta.filters.filter(filter => { + return filter.key !== column + }) + if (initialLength !== view.meta.filters.length) { + needsUpdated = true + } + } + }) + } + + // Update view if required + if (needsUpdated) { + const newViewTemplate = viewTemplate(view.meta) + await saveView(db, null, view.name, newViewTemplate) + if (!newViewTemplate.meta.schema) { + newViewTemplate.meta.schema = table.schema + } + table.views[view.name] = newViewTemplate.meta + } + } +} + exports.TableSaveFunctions = TableSaveFunctions From bc26925c2fc04b491009d2fdd42612dd700087d3 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 21 Oct 2021 10:24:41 +0100 Subject: [PATCH 3/3] Remove optional chaining from server --- .../server/src/api/controllers/table/utils.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/server/src/api/controllers/table/utils.js b/packages/server/src/api/controllers/table/utils.js index 9b5f11d865..65c081f90e 100644 --- a/packages/server/src/api/controllers/table/utils.js +++ b/packages/server/src/api/controllers/table/utils.js @@ -266,13 +266,15 @@ exports.checkForViewUpdates = async (db, table, rename, deletedColumns) => { } // Update filters if required - view.meta.filters?.forEach(filter => { - if (filter.key === rename.old) { - filter.key = rename.updated - needsUpdated = true - } - }) - } else if (deletedColumns?.length) { + if (view.meta.filters) { + view.meta.filters.forEach(filter => { + if (filter.key === rename.old) { + filter.key = rename.updated + needsUpdated = true + } + }) + } + } else if (deletedColumns) { deletedColumns.forEach(column => { // Remove calculation statement if required if (view.meta.field === column) { @@ -289,7 +291,7 @@ exports.checkForViewUpdates = async (db, table, rename, deletedColumns) => { } // Remove filters referencing deleted field if required - if (view.meta.filters?.length) { + if (view.meta.filters && view.meta.filters.length) { const initialLength = view.meta.filters.length view.meta.filters = view.meta.filters.filter(filter => { return filter.key !== column