diff --git a/.github/workflows/release-timely-executables.yml b/.github/workflows/release-timely-executables.yml index ab7706709c..e3c18570ae 100644 --- a/.github/workflows/release-timely-executables.yml +++ b/.github/workflows/release-timely-executables.yml @@ -62,6 +62,10 @@ jobs: ./make.sh sudo cp ./ldid /usr/local/bin + - uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Update nocodb-timely env: TAG: ${{ github.event.inputs.tag || inputs.tag }} @@ -75,11 +79,6 @@ jobs: git tag $TAG git push --tags - - - uses: actions/setup-node@v3 - with: - node-version: 16 - - name : Install dependencies and build executables run: | # install npm dependendencies diff --git a/packages/nc-gui/components/virtual-cell/components/ListItems.vue b/packages/nc-gui/components/virtual-cell/components/ListItems.vue index 711030c443..2df6f5702d 100644 --- a/packages/nc-gui/components/virtual-cell/components/ListItems.vue +++ b/packages/nc-gui/components/virtual-cell/components/ListItems.vue @@ -48,14 +48,20 @@ const saveRow = inject(SaveRowInj, () => {}) const selectedRowIndex = ref(0) +const isAltKeyDown = ref(false) + const linkRow = async (row: Record) => { if (isNew.value) { addLTARRef(row, column?.value as ColumnType) - saveRow() + saveRow!() } else { await link(row) } - vModel.value = false + if (isAltKeyDown.value) { + loadChildrenExcludedList() + } else { + vModel.value = false + } } /** reload list on modal open */ @@ -159,6 +165,27 @@ useSelectedCellKeyupListener(vModel, (e: KeyboardEvent) => { const activeRow = (vNode?: InstanceType) => { vNode?.$el?.scrollIntoView({ block: 'nearest', inline: 'nearest' }) } + +// set variable to true when alt key is pressed +const keyDownHandler = (e: KeyboardEvent) => { + isAltKeyDown.value = e.altKey +} + +// set variable to false when key is released +const keyUpHandler = (e: KeyboardEvent) => { + isAltKeyDown.value = e.altKey +} + +// add event listeners when vModel is true and remove when false +watch(vModel, (nextVal) => { + if (nextVal) { + document.addEventListener('keydown', keyDownHandler) + document.addEventListener('keyup', keyUpHandler) + } else { + document.removeEventListener('keydown', keyDownHandler) + document.removeEventListener('keyup', keyUpHandler) + } +}) diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json index 760ec39993..f7ab5bfabf 100644 --- a/packages/nc-gui/package-lock.json +++ b/packages/nc-gui/package-lock.json @@ -97,7 +97,7 @@ } }, "../nocodb-sdk": { - "version": "0.105.2", + "version": "0.105.3", "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", diff --git a/packages/nc-lib-gui/package.json b/packages/nc-lib-gui/package.json index 4b69138b3d..c8291f6ecc 100644 --- a/packages/nc-lib-gui/package.json +++ b/packages/nc-lib-gui/package.json @@ -1,6 +1,6 @@ { "name": "nc-lib-gui", - "version": "0.105.2", + "version": "0.105.3", "description": "NocoDB GUI", "author": { "name": "NocoDB", diff --git a/packages/nocodb-sdk/package-lock.json b/packages/nocodb-sdk/package-lock.json index e9169032f3..8c1bda86b4 100644 --- a/packages/nocodb-sdk/package-lock.json +++ b/packages/nocodb-sdk/package-lock.json @@ -1,12 +1,12 @@ { "name": "nocodb-sdk", - "version": "0.105.2", + "version": "0.105.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nocodb-sdk", - "version": "0.105.2", + "version": "0.105.3", "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", diff --git a/packages/nocodb-sdk/package.json b/packages/nocodb-sdk/package.json index 86e88d8bc1..ec22d9e676 100644 --- a/packages/nocodb-sdk/package.json +++ b/packages/nocodb-sdk/package.json @@ -1,6 +1,6 @@ { "name": "nocodb-sdk", - "version": "0.105.2", + "version": "0.105.3", "description": "NocoDB SDK", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index 93ae72c9ec..a72029e453 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -502,7 +502,7 @@ export interface HookType { description?: string; env?: string; type?: string; - event?: 'After' | 'Before'; + event?: 'after' | 'before'; operation?: 'insert' | 'delete' | 'update'; async?: boolean; payload?: string; diff --git a/packages/nocodb/package-lock.json b/packages/nocodb/package-lock.json index fd244d0f9b..c63e48dd18 100644 --- a/packages/nocodb/package-lock.json +++ b/packages/nocodb/package-lock.json @@ -1,12 +1,12 @@ { "name": "nocodb", - "version": "0.105.2", + "version": "0.105.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nocodb", - "version": "0.105.2", + "version": "0.105.3", "license": "AGPL-3.0-or-later", "dependencies": { "@google-cloud/storage": "^5.7.2", @@ -65,7 +65,7 @@ "mysql2": "^2.2.5", "nanoid": "^3.1.20", "nc-help": "0.2.85", - "nc-lib-gui": "0.105.2", + "nc-lib-gui": "0.105.3", "nc-plugin": "0.1.2", "ncp": "^2.0.0", "nocodb-sdk": "file:../nocodb-sdk", @@ -154,7 +154,7 @@ } }, "../nocodb-sdk": { - "version": "0.105.2", + "version": "0.105.3", "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", @@ -11257,9 +11257,9 @@ } }, "node_modules/nc-lib-gui": { - "version": "0.105.2", - "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.105.2.tgz", - "integrity": "sha512-uycep2vme3XP6PwvFjJ6wE2fpCNiaJ/ptWR7ZHwRCu500eJGdtonWc00BQf01FitQ1vKq9Cpqqi2b0hoFBLFvQ==", + "version": "0.105.3", + "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.105.3.tgz", + "integrity": "sha512-w07Y2+nBiUQYiUyURwH9nqvzzxXsz8MALU/MhmWyNe3Z0YhBvPPLLUxtG1WR3USLI925YT0BsAZTn+iSP3ooPw==", "dependencies": { "express": "^4.17.1" } @@ -27875,9 +27875,9 @@ } }, "nc-lib-gui": { - "version": "0.105.2", - "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.105.2.tgz", - "integrity": "sha512-uycep2vme3XP6PwvFjJ6wE2fpCNiaJ/ptWR7ZHwRCu500eJGdtonWc00BQf01FitQ1vKq9Cpqqi2b0hoFBLFvQ==", + "version": "0.105.3", + "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.105.3.tgz", + "integrity": "sha512-w07Y2+nBiUQYiUyURwH9nqvzzxXsz8MALU/MhmWyNe3Z0YhBvPPLLUxtG1WR3USLI925YT0BsAZTn+iSP3ooPw==", "requires": { "express": "^4.17.1" } diff --git a/packages/nocodb/package.json b/packages/nocodb/package.json index ebb9842020..87bcff9e79 100644 --- a/packages/nocodb/package.json +++ b/packages/nocodb/package.json @@ -1,6 +1,6 @@ { "name": "nocodb", - "version": "0.105.2", + "version": "0.105.3", "description": "NocoDB Backend", "main": "dist/bundle.js", "author": { @@ -105,7 +105,7 @@ "mysql2": "^2.2.5", "nanoid": "^3.1.20", "nc-help": "0.2.85", - "nc-lib-gui": "0.105.2", + "nc-lib-gui": "0.105.3", "nc-plugin": "0.1.2", "ncp": "^2.0.0", "nocodb-sdk": "file:../nocodb-sdk", diff --git a/packages/nocodb/src/lib/Noco.ts b/packages/nocodb/src/lib/Noco.ts index 6c7ead8acd..b66287a446 100644 --- a/packages/nocodb/src/lib/Noco.ts +++ b/packages/nocodb/src/lib/Noco.ts @@ -105,7 +105,7 @@ export default class Noco { constructor() { process.env.PORT = process.env.PORT || '8080'; // todo: move - process.env.NC_VERSION = '0104004'; + process.env.NC_VERSION = '0105002'; // if env variable NC_MINIMAL_DBS is set, then disable project creation with external sources if (process.env.NC_MINIMAL_DBS) { diff --git a/packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts b/packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts index 02b5c4e343..3f6a85b9c2 100644 --- a/packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts +++ b/packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts @@ -345,7 +345,16 @@ export default class SqlMgr { * @returns * @memberof SqlMgr */ - public async projectGetSqlClient(args): Promise { + public async projectGetSqlClient( + args + ): Promise< + | SnowflakeClient + | MysqlClient + | SqliteClient + | MssqlClient + | OracleClient + | PGClient + > { const func = this.projectGetSqlClient.name; log.api(`${func}:args:`, args); diff --git a/packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts b/packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts index cdf4d8f1f1..d32a40d1d0 100644 --- a/packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts +++ b/packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import { promisify } from 'util'; -import { Knex } from 'knex'; +import { Knex } from 'knex'; import glob from 'glob'; import SqlClientFactory from '../../sql-client/lib/SqlClientFactory'; @@ -754,7 +754,7 @@ export default class KnexMigratorv2 { const vm = this; const trx = sqlClient.knex.isTransaction - ? sqlClient.knex as Knex.Transaction + ? (sqlClient.knex as Knex.Transaction) : await sqlClient.knex.transaction(); try { for (const query of upStatements) { @@ -921,7 +921,7 @@ export default class KnexMigratorv2 { const vm = this; const trx = sqlClient.knex.isTransaction - ? sqlClient.knex as Knex.Transaction + ? (sqlClient.knex as Knex.Transaction) : await sqlClient.knex.transaction(); try { for (const query of downStatements) { diff --git a/packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2Tans.ts b/packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2Tans.ts index 037cf6d559..87204964a0 100644 --- a/packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2Tans.ts +++ b/packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2Tans.ts @@ -31,7 +31,16 @@ export default class KnexMigratorv2Tans extends KnexMigratorv2 { protected get metaDb(): XKnex { return this.ncMeta.knex || Noco.ncMeta.knex; } - protected async getSqlClient(base: Base): Promise { + protected async getSqlClient( + base: Base + ): Promise< + | SnowflakeClient + | MysqlClient + | SqliteClient + | MssqlClient + | OracleClient + | PGClient + > { return this.sqlClient || NcConnectionMgrv2.getSqlClient(base); } } diff --git a/packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts b/packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts index ff7861a529..ffe246a131 100644 --- a/packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts +++ b/packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts @@ -229,6 +229,8 @@ export async function populateMeta(base: Base, project: Project): Promise { const columns = (await sqlClient.columnList({ tn: table.table_name })) ?.data?.list; + mapDefaultDisplayValue(columns); + /* create nc_models and its rows if it doesn't exists */ models2[table.table_name] = await Model.insert(project.id, base.id, { table_name: table.table_name, diff --git a/packages/nocodb/src/lib/meta/helpers/mapDefaultDisplayValue.ts b/packages/nocodb/src/lib/meta/helpers/mapDefaultDisplayValue.ts index 8f12d40d13..a661f21818 100644 --- a/packages/nocodb/src/lib/meta/helpers/mapDefaultDisplayValue.ts +++ b/packages/nocodb/src/lib/meta/helpers/mapDefaultDisplayValue.ts @@ -4,31 +4,27 @@ export default function mapDefaultDisplayValue( columnsArr: Array ): void | T { if (!columnsArr.some((column) => column.pv)) { - let len = columnsArr.length; - let pkIndex = -1; - - while (len--) { - if (columnsArr[len].pk) { - pkIndex = len; - break; - } - } + const pkIndex = columnsArr.findIndex((column) => column.pk); // if PK is at the end of table if (pkIndex === columnsArr.length - 1) { if (pkIndex > 0) { columnsArr[pkIndex - 1].pv = true; return columnsArr[pkIndex - 1]; + } else if (columnsArr.length > 0) { + columnsArr[0].pv = true; + return columnsArr[0]; } - } - // pk is not at the end of table - else if (pkIndex > -1) { + // pk is not at the end of table + } else if (pkIndex > -1) { columnsArr[pkIndex + 1].pv = true; return columnsArr[pkIndex + 1]; - } - // no pk at all - else { - // todo: + // no pk at all + } else { + if (columnsArr.length > 0) { + columnsArr[0].pv = true; + return columnsArr[0]; + } } } } diff --git a/packages/nocodb/src/lib/models/Audit.ts b/packages/nocodb/src/lib/models/Audit.ts index a512f96b48..9ea8e589d2 100644 --- a/packages/nocodb/src/lib/models/Audit.ts +++ b/packages/nocodb/src/lib/models/Audit.ts @@ -2,6 +2,7 @@ import { AuditOperationTypes, AuditType } from 'nocodb-sdk'; import { MetaTable } from '../utils/globals'; import Noco from '../Noco'; import Model from './Model'; +import { extractProps } from '../meta/helpers/extractProps'; export default class Audit implements AuditType { id?: string; @@ -48,27 +49,28 @@ export default class Audit implements AuditType { return; } const insertAudit = async () => { - if (!audit.project_id && audit.fk_model_id) { - audit.project_id = ( - await Model.getByIdOrName({ id: audit.fk_model_id }, ncMeta) + const insertObj = extractProps(audit, [ + 'user', + 'ip', + 'base_id', + 'project_id', + 'row_id', + 'fk_model_id', + 'op_type', + 'op_sub_type', + 'status', + 'description', + 'details', + 'created_at', + 'updated_at', + ]); + if (!insertObj.project_id && insertObj.fk_model_id) { + insertObj.project_id = ( + await Model.getByIdOrName({ id: insertObj.fk_model_id }, ncMeta) ).project_id; } - return await ncMeta.metaInsert2(null, null, MetaTable.AUDIT, { - user: audit.user, - ip: audit.ip, - base_id: audit.base_id, - project_id: audit.project_id, - row_id: audit.row_id, - fk_model_id: audit.fk_model_id, - op_type: audit.op_type, - op_sub_type: audit.op_sub_type, - status: audit.status, - description: audit.description, - details: audit.details, - created_at: audit.created_at, - updated_at: audit.updated_at, - }); + return await ncMeta.metaInsert2(null, null, MetaTable.AUDIT, insertObj); }; if (forceAwait) { diff --git a/packages/nocodb/src/lib/models/BarcodeColumn.ts b/packages/nocodb/src/lib/models/BarcodeColumn.ts index 6f274f3f86..745de9200c 100644 --- a/packages/nocodb/src/lib/models/BarcodeColumn.ts +++ b/packages/nocodb/src/lib/models/BarcodeColumn.ts @@ -14,16 +14,17 @@ export default class BarcodeColumn { } public static async insert( - data: Partial, + barcodeColumn: Partial, ncMeta = Noco.ncMeta ) { - await ncMeta.metaInsert2(null, null, MetaTable.COL_BARCODE, { - fk_column_id: data.fk_column_id, - fk_barcode_value_column_id: data.fk_barcode_value_column_id, - barcode_format: data.barcode_format, - }); + const insertObj = extractProps(barcodeColumn, [ + 'fk_column_id', + 'fk_barcode_value_column_id', + 'barcode_format', + ]); + await ncMeta.metaInsert2(null, null, MetaTable.COL_BARCODE, insertObj); - return this.read(data.fk_column_id, ncMeta); + return this.read(barcodeColumn.fk_column_id, ncMeta); } public static async read(columnId: string, ncMeta = Noco.ncMeta) { let column = diff --git a/packages/nocodb/src/lib/models/Column.ts b/packages/nocodb/src/lib/models/Column.ts index 6d7b2d5345..154e0a4098 100644 --- a/packages/nocodb/src/lib/models/Column.ts +++ b/packages/nocodb/src/lib/models/Column.ts @@ -25,6 +25,7 @@ import addFormulaErrorIfMissingColumn from '../meta/helpers/addFormulaErrorIfMis import { NcError } from '../meta/helpers/catchError'; import QrCodeColumn from './QrCodeColumn'; import BarcodeColumn from './BarcodeColumn'; +import { extractProps } from '../meta/helpers/extractProps'; export default class Column implements ColumnType { public fk_model_id: string; @@ -85,41 +86,50 @@ export default class Column implements ColumnType { ) { if (!column.fk_model_id) NcError.badRequest('Missing model id'); - const insertObj: any = { - id: column?.id, - fk_model_id: column.fk_model_id, - column_name: column.column_name || column.cn, - title: column.title || column._cn, - uidt: column.uidt, - dt: column.dt, - np: column.np, - ns: column.ns, - clen: column.clen, - cop: column.cop, - pk: column.pk, - rqd: column.rqd, - un: column.un, - ct: column.ct, - ai: column.ai, - unique: column.unique, - cdf: column.cdf, - cc: column.cc, - csn: column.csn, - dtx: column.dtx, - dtxp: column.dtxp, - dtxs: column.dtxs, - au: column.au, - pv: column.pv, - order: column.order, - project_id: column.project_id, - base_id: column.base_id, - system: column.system, - meta: - column.meta && typeof column.meta === 'object' - ? JSON.stringify(column.meta) - : column.meta, - }; + // TODO: fix type + const insertObj = extractProps(column as any, [ + 'id', + 'fk_model_id', + 'column_name', + 'title', + 'uidt', + 'dt', + 'np', + 'ns', + 'clen', + 'cop', + 'pk', + 'rqd', + 'un', + 'ct', + 'ai', + 'unique', + 'cdf', + 'cc', + 'csn', + 'dtx', + 'dtxp', + 'dtxs', + 'au', + 'pv', + 'order', + 'project_id', + 'base_id', + 'system', + 'meta', + ]); + + if (!insertObj.column_name) { + insertObj.column_name = column.cn; + } + + if (!insertObj.title) { + insertObj.title = column._cn; + } + if (insertObj.meta && typeof insertObj.meta === 'object') { + insertObj.meta = JSON.stringify(insertObj.meta); + } if (column.validate) { if (typeof column.validate === 'string') insertObj.validate = column.validate; @@ -873,7 +883,11 @@ export default class Column implements ColumnType { ); } - static async update(colId: string, column: any, ncMeta = Noco.ncMeta) { + static async update( + colId: string, + column: Partial, + ncMeta = Noco.ncMeta + ) { const oldCol = await Column.get({ colId }, ncMeta); switch (oldCol.uidt) { @@ -965,33 +979,34 @@ export default class Column implements ColumnType { break; } } - const updateObj = { - column_name: column.column_name, - title: column.title, - uidt: column.uidt, - dt: column.dt, - np: column.np, - ns: column.ns, - clen: column.clen, - cop: column.cop, - pk: column.pk, - rqd: column.rqd, - un: column.un, - ct: column.ct, - ai: column.ai, - unique: column.unique, - cdf: column.cdf, - cc: column.cc, - csn: column.csn, - dtx: column.dtx, - dtxp: column.dtxp, - dtxs: column.dtxs, - au: column.au, - pv: column.pv, - system: column.system, - validate: null, - meta: column.meta, - }; + + const updateObj = extractProps(column, [ + 'column_name', + 'title', + 'uidt', + 'dt', + 'np', + 'ns', + 'clen', + 'cop', + 'pk', + 'rqd', + 'un', + 'ct', + 'ai', + 'unique', + 'cdf', + 'cc', + 'csn', + 'dtx', + 'dtxp', + 'dtxs', + 'au', + 'pv', + 'system', + 'validate', + 'meta', + ]); if (column.validate) { if (typeof column.validate === 'string') diff --git a/packages/nocodb/src/lib/models/Filter.ts b/packages/nocodb/src/lib/models/Filter.ts index 619b6a741d..1e6a0dfaee 100644 --- a/packages/nocodb/src/lib/models/Filter.ts +++ b/packages/nocodb/src/lib/models/Filter.ts @@ -77,29 +77,30 @@ export default class Filter { } public static async insert( - filter: Partial, + filter: Partial & { order?: number }, ncMeta = Noco.ncMeta ) { - const insertObj = { - id: filter.id, - fk_view_id: filter.fk_view_id, - fk_hook_id: filter.fk_hook_id, - fk_column_id: filter.fk_column_id, - comparison_op: filter.comparison_op, - value: filter.value, - fk_parent_id: filter.fk_parent_id, - - is_group: filter.is_group, - logical_op: filter.logical_op, - - project_id: filter.project_id, - base_id: filter.base_id, - order: await ncMeta.metaGetNextOrder(MetaTable.FILTER_EXP, { - [filter.fk_hook_id ? 'fk_hook_id' : 'fk_view_id']: filter.fk_hook_id - ? filter.fk_hook_id - : filter.fk_view_id, - }), - }; + const insertObj = extractProps(filter, [ + 'id', + 'fk_view_id', + 'fk_hook_id', + 'fk_column_id', + 'comparison_op', + 'value', + 'fk_parent_id', + 'is_group', + 'logical_op', + 'project_id', + 'base_id', + 'order', + ]); + + insertObj.order = await ncMeta.metaGetNextOrder(MetaTable.FILTER_EXP, { + [filter.fk_hook_id ? 'fk_hook_id' : 'fk_view_id']: filter.fk_hook_id + ? filter.fk_hook_id + : filter.fk_view_id, + }); + if (!(filter.project_id && filter.base_id)) { let model: { project_id?: string; base_id?: string }; if (filter.fk_view_id) { diff --git a/packages/nocodb/src/lib/models/FormView.ts b/packages/nocodb/src/lib/models/FormView.ts index 49ee5c4da2..ad155f4434 100644 --- a/packages/nocodb/src/lib/models/FormView.ts +++ b/packages/nocodb/src/lib/models/FormView.ts @@ -5,6 +5,7 @@ import { deserializeJSON, serializeJSON } from '../utils/serialize'; import FormViewColumn from './FormViewColumn'; import View from './View'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class FormView implements FormType { show: boolean; @@ -53,22 +54,25 @@ export default class FormView implements FormType { } static async insert(view: Partial, ncMeta = Noco.ncMeta) { - const insertObj = { - fk_view_id: view.fk_view_id, - project_id: view.project_id, - base_id: view.base_id, - heading: view.heading, - subheading: view.subheading, - success_msg: view.success_msg, - redirect_url: view.redirect_url, - redirect_after_secs: view.redirect_after_secs, - email: view.email, - banner_image_url: view.banner_image_url, - logo_url: view.logo_url, - submit_another_form: view.submit_another_form, - show_blank_form: view.show_blank_form, - meta: serializeJSON(view.meta), - }; + const insertObj = extractProps(view, [ + 'fk_view_id', + 'project_id', + 'base_id', + 'heading', + 'subheading', + 'success_msg', + 'redirect_url', + 'redirect_after_secs', + 'email', + 'banner_image_url', + 'logo_url', + 'submit_another_form', + 'show_blank_form', + 'meta', + ]); + if (insertObj.meta) { + insertObj.meta = serializeJSON(insertObj.meta); + } if (!(view.project_id && view.base_id)) { const viewRef = await View.get(view.fk_view_id); insertObj.project_id = viewRef.project_id; @@ -86,44 +90,35 @@ export default class FormView implements FormType { ) { // get existing cache const key = `${CacheScope.FORM_VIEW}:${formId}`; - const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); + let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); + const updateObj = extractProps(body, [ + 'heading', + 'subheading', + 'success_msg', + 'redirect_url', + 'redirect_after_secs', + 'email', + 'banner_image_url', + 'logo_url', + 'submit_another_form', + 'show_blank_form', + 'meta', + ]); + if (o) { - o.heading = body.heading; - o.subheading = body.subheading; - o.success_msg = body.success_msg; - o.redirect_url = body.redirect_url; - o.redirect_after_secs = body.redirect_after_secs; - o.email = body.email; - o.banner_image_url = body.banner_image_url; - o.logo_url = body.logo_url; - o.submit_another_form = body.submit_another_form; - o.show_blank_form = body.show_blank_form; - o.meta = body.meta; + o = { ...o, ...updateObj }; // set cache await NocoCache.set(key, o); - o.meta = serializeJSON(body.meta); } + + if (updateObj.meta) { + updateObj.meta = serializeJSON(updateObj.meta); + } + // update meta - return await ncMeta.metaUpdate( - null, - null, - MetaTable.FORM_VIEW, - { - heading: body.heading, - subheading: body.subheading, - success_msg: body.success_msg, - redirect_url: body.redirect_url, - redirect_after_secs: body.redirect_after_secs, - email: body.email, - banner_image_url: body.banner_image_url, - logo_url: body.logo_url, - submit_another_form: body.submit_another_form, - show_blank_form: body.show_blank_form, - }, - { - fk_view_id: formId, - } - ); + return await ncMeta.metaUpdate(null, null, MetaTable.FORM_VIEW, updateObj, { + fk_view_id: formId, + }); } async getColumns(ncMeta = Noco.ncMeta) { diff --git a/packages/nocodb/src/lib/models/FormViewColumn.ts b/packages/nocodb/src/lib/models/FormViewColumn.ts index 8cd3fb3efe..577d5ad5ca 100644 --- a/packages/nocodb/src/lib/models/FormViewColumn.ts +++ b/packages/nocodb/src/lib/models/FormViewColumn.ts @@ -55,27 +55,32 @@ export default class FormViewColumn implements FormColumnType { } static async insert(column: Partial, ncMeta = Noco.ncMeta) { - const insertObj: Partial = { - fk_view_id: column.fk_view_id, - fk_column_id: column.fk_column_id, - order: await ncMeta.metaGetNextOrder(MetaTable.FORM_VIEW_COLUMNS, { - fk_view_id: column.fk_view_id, - }), - show: column.show, - project_id: column.project_id, - base_id: column.base_id, - label: column.label, - help: column.help, - description: column.description, - required: column.required, - }; - - if (column.meta) { - insertObj.meta = serializeJSON(column.meta); + const insertObj = extractProps(column, [ + 'fk_view_id', + 'fk_column_id', + 'show', + 'project_id', + 'base_id', + 'label', + 'help', + 'description', + 'required', + 'meta', + ]); + + insertObj.order = await ncMeta.metaGetNextOrder( + MetaTable.FORM_VIEW_COLUMNS, + { + fk_view_id: insertObj.fk_view_id, + } + ); + + if (insertObj.meta) { + insertObj.meta = serializeJSON(insertObj.meta); } - if (!(column.project_id && column.base_id)) { - const viewRef = await View.get(column.fk_view_id, ncMeta); + if (!(insertObj.project_id && insertObj.base_id)) { + const viewRef = await View.get(insertObj.fk_view_id, ncMeta); insertObj.project_id = viewRef.project_id; insertObj.base_id = viewRef.base_id; } @@ -150,7 +155,7 @@ export default class FormViewColumn implements FormColumnType { body: Partial, ncMeta = Noco.ncMeta ) { - const insertObj = extractProps(body, [ + const updateObj = extractProps(body, [ 'label', 'help', 'description', @@ -164,13 +169,13 @@ export default class FormViewColumn implements FormColumnType { const key = `${CacheScope.FORM_VIEW_COLUMN}:${columnId}`; const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); if (o) { - Object.assign(o, insertObj); + Object.assign(o, updateObj); // set cache await NocoCache.set(key, o); } - if (insertObj.meta) { - insertObj.meta = serializeJSON(insertObj.meta); + if (updateObj.meta) { + updateObj.meta = serializeJSON(updateObj.meta); } // update meta @@ -178,7 +183,7 @@ export default class FormViewColumn implements FormColumnType { null, null, MetaTable.FORM_VIEW_COLUMNS, - insertObj, + updateObj, columnId ); } diff --git a/packages/nocodb/src/lib/models/FormulaColumn.ts b/packages/nocodb/src/lib/models/FormulaColumn.ts index 106b78934c..90e4f22c61 100644 --- a/packages/nocodb/src/lib/models/FormulaColumn.ts +++ b/packages/nocodb/src/lib/models/FormulaColumn.ts @@ -14,17 +14,18 @@ export default class FormulaColumn { } public static async insert( - data: Partial, + formulaColumn: Partial, ncMeta = Noco.ncMeta ) { - await ncMeta.metaInsert2(null, null, MetaTable.COL_FORMULA, { - fk_column_id: data.fk_column_id, - formula_raw: data.formula_raw, - formula: data.formula, - error: data.error, - }); + const insertObj = extractProps(formulaColumn, [ + 'fk_column_id', + 'formula_raw', + 'formula', + 'error', + ]); + await ncMeta.metaInsert2(null, null, MetaTable.COL_FORMULA, insertObj); - return this.read(data.fk_column_id, ncMeta); + return this.read(formulaColumn.fk_column_id, ncMeta); } public static async read(columnId: string, ncMeta = Noco.ncMeta) { let column = diff --git a/packages/nocodb/src/lib/models/GalleryView.ts b/packages/nocodb/src/lib/models/GalleryView.ts index 9c76f1de8e..2cf2f6ce8f 100644 --- a/packages/nocodb/src/lib/models/GalleryView.ts +++ b/packages/nocodb/src/lib/models/GalleryView.ts @@ -3,6 +3,7 @@ import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { GalleryColumnType, GalleryType, UITypes } from 'nocodb-sdk'; import View from './View'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class GalleryView implements GalleryType { fk_view_id?: string; @@ -51,21 +52,23 @@ export default class GalleryView implements GalleryType { .then((v) => v?.getModel(ncMeta)) .then((m) => m.getColumns(ncMeta)); - const insertObj = { - project_id: view.project_id, - base_id: view.base_id, - fk_view_id: view.fk_view_id, - fk_cover_image_col_id: - view?.fk_cover_image_col_id || - columns?.find((c) => c.uidt === UITypes.Attachment)?.id, - next_enabled: view.next_enabled, - prev_enabled: view.prev_enabled, - cover_image_idx: view.cover_image_idx, - cover_image: view.cover_image, - restrict_types: view.restrict_types, - restrict_size: view.restrict_size, - restrict_number: view.restrict_number, - }; + const insertObj = extractProps(view, [ + 'project_id', + 'base_id', + 'fk_view_id', + 'next_enabled', + 'prev_enabled', + 'cover_image_idx', + 'cover_image', + 'restrict_types', + 'restrict_size', + 'restrict_number', + ]); + + insertObj.fk_cover_image_col_id = + view?.fk_cover_image_col_id || + columns?.find((c) => c.uidt === UITypes.Attachment)?.id; + if (!(view.project_id && view.base_id)) { const viewRef = await View.get(view.fk_view_id); insertObj.project_id = viewRef.project_id; @@ -90,16 +93,19 @@ export default class GalleryView implements GalleryType { ) { // get existing cache const key = `${CacheScope.GALLERY_VIEW}:${galleryId}`; - const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); + let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); + const updateObj = extractProps(body, [ + 'next_enabled', + 'prev_enabled', + 'cover_image_idx', + 'cover_image', + 'restrict_types', + 'restrict_size', + 'restrict_number', + 'fk_cover_image_col_id', + ]); if (o) { - o.next_enabled = body.next_enabled; - o.prev_enabled = body.prev_enabled; - o.cover_image_idx = body.cover_image_idx; - o.cover_image = body.cover_image; - o.restrict_types = body.restrict_types; - o.restrict_size = body.restrict_size; - o.restrict_number = body.restrict_number; - o.fk_cover_image_col_id = body.fk_cover_image_col_id; + o = { ...o, ...updateObj }; // set cache await NocoCache.set(key, o); } @@ -108,16 +114,7 @@ export default class GalleryView implements GalleryType { null, null, MetaTable.GALLERY_VIEW, - { - next_enabled: body.next_enabled, - prev_enabled: body.prev_enabled, - cover_image_idx: body.cover_image_idx, - cover_image: body.cover_image, - restrict_types: body.restrict_types, - restrict_size: body.restrict_size, - restrict_number: body.restrict_number, - fk_cover_image_col_id: body.fk_cover_image_col_id, - }, + updateObj, { fk_view_id: galleryId, } diff --git a/packages/nocodb/src/lib/models/GalleryViewColumn.ts b/packages/nocodb/src/lib/models/GalleryViewColumn.ts index 75ca96f4f1..3ccc1e73c3 100644 --- a/packages/nocodb/src/lib/models/GalleryViewColumn.ts +++ b/packages/nocodb/src/lib/models/GalleryViewColumn.ts @@ -2,6 +2,7 @@ import Noco from '../Noco'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import View from './View'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class GalleryViewColumn { id: string; @@ -43,16 +44,20 @@ export default class GalleryViewColumn { column: Partial, ncMeta = Noco.ncMeta ) { - const insertObj = { - fk_view_id: column.fk_view_id, - fk_column_id: column.fk_column_id, - order: await ncMeta.metaGetNextOrder(MetaTable.GALLERY_VIEW_COLUMNS, { + const insertObj = extractProps(column, [ + 'fk_view_id', + 'fk_column_id', + 'show', + 'project_id', + 'base_id', + ]); + + insertObj.order = await ncMeta.metaGetNextOrder( + MetaTable.GALLERY_VIEW_COLUMNS, + { fk_view_id: column.fk_view_id, - }), - show: column.show, - project_id: column.project_id, - base_id: column.base_id, - }; + } + ); if (!(column.project_id && column.base_id)) { const viewRef = await View.get(column.fk_view_id, ncMeta); diff --git a/packages/nocodb/src/lib/models/GridView.ts b/packages/nocodb/src/lib/models/GridView.ts index 40a98b0c9e..880254261a 100644 --- a/packages/nocodb/src/lib/models/GridView.ts +++ b/packages/nocodb/src/lib/models/GridView.ts @@ -3,6 +3,7 @@ import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import GridViewColumn from './GridViewColumn'; import View from './View'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class GridView { fk_view_id: string; @@ -40,14 +41,15 @@ export default class GridView { } static async insert(view: Partial, ncMeta = Noco.ncMeta) { - const insertObj = { - fk_view_id: view.fk_view_id, - project_id: view.project_id, - base_id: view.base_id, - row_height: view.row_height, - }; - if (!(view.project_id && view.base_id)) { - const viewRef = await View.get(view.fk_view_id, ncMeta); + const insertObj = extractProps(view, [ + 'fk_view_id', + 'project_id', + 'base_id', + 'row_height', + ]); + + if (!(insertObj.project_id && insertObj.base_id)) { + const viewRef = await View.get(insertObj.fk_view_id, ncMeta); insertObj.project_id = viewRef.project_id; insertObj.base_id = viewRef.base_id; } @@ -69,23 +71,16 @@ export default class GridView { ) { // get existing cache const key = `${CacheScope.GRID_VIEW}:${viewId}`; - const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); + let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); + const updateObj = extractProps(body, ['row_height']); if (o) { - o.row_height = body.row_height; + o = { ...o, ...updateObj }; // set cache await NocoCache.set(key, o); } // update meta - return await ncMeta.metaUpdate( - null, - null, - MetaTable.GRID_VIEW, - { - row_height: body.row_height, - }, - { - fk_view_id: viewId, - } - ); + return await ncMeta.metaUpdate(null, null, MetaTable.GRID_VIEW, updateObj, { + fk_view_id: viewId, + }); } } diff --git a/packages/nocodb/src/lib/models/GridViewColumn.ts b/packages/nocodb/src/lib/models/GridViewColumn.ts index e1d0398276..f3a3385a70 100644 --- a/packages/nocodb/src/lib/models/GridViewColumn.ts +++ b/packages/nocodb/src/lib/models/GridViewColumn.ts @@ -67,18 +67,19 @@ export default class GridViewColumn implements GridColumnType { } static async insert(column: Partial, ncMeta = Noco.ncMeta) { - const insertObj = { - fk_view_id: column.fk_view_id, - fk_column_id: column.fk_column_id, - order: - column?.order ?? - (await ncMeta.metaGetNextOrder(MetaTable.GRID_VIEW_COLUMNS, { - fk_view_id: column.fk_view_id, - })), - show: column.show, - project_id: column.project_id, - base_id: column.base_id, - }; + const insertObj = extractProps(column, [ + 'fk_view_id', + 'fk_column_id', + 'show', + 'project_id', + 'base_id', + ]); + + insertObj.order = + column?.order ?? + (await ncMeta.metaGetNextOrder(MetaTable.GRID_VIEW_COLUMNS, { + fk_view_id: column.fk_view_id, + })); if (!(column.project_id && column.base_id)) { const viewRef = await View.get(column.fk_view_id, ncMeta); diff --git a/packages/nocodb/src/lib/models/Hook.ts b/packages/nocodb/src/lib/models/Hook.ts index d87aa994bf..7c32d09bbd 100644 --- a/packages/nocodb/src/lib/models/Hook.ts +++ b/packages/nocodb/src/lib/models/Hook.ts @@ -10,6 +10,7 @@ import Model from './Model'; import NocoCache from '../cache/NocoCache'; import Filter from './Filter'; import HookFilter from './HookFilter'; +import { extractProps } from '../meta/helpers/extractProps'; export default class Hook implements HookType { id?: string; @@ -18,7 +19,7 @@ export default class Hook implements HookType { description?: string; env?: string; type?: string; - event?: 'After' | 'Before'; + event?: 'after' | 'before'; operation?: 'insert' | 'delete' | 'update'; async?: boolean; payload?: string; @@ -121,32 +122,42 @@ export default class Hook implements HookType { >, ncMeta = Noco.ncMeta ) { - const insertObj = { - fk_model_id: hook.fk_model_id, - title: hook.title, - description: hook.description, - env: hook.env, - type: hook.type, - event: hook.event?.toLowerCase?.(), - operation: hook.operation?.toLowerCase?.(), - async: hook.async, - payload: !!hook.payload, - url: hook.url, - headers: hook.headers, - condition: hook.condition, - notification: - hook.notification && typeof hook.notification === 'object' - ? JSON.stringify(hook.notification) - : hook.notification, - retries: hook.retries, - retry_interval: hook.retry_interval, - timeout: hook.timeout, - active: hook.active, - project_id: hook.project_id, - base_id: hook.base_id, - created_at: hook.created_at, - updated_at: hook.updated_at, - }; + const insertObj = extractProps(hook, [ + 'fk_model_id', + 'title', + 'description', + 'env', + 'type', + 'event', + 'operation', + 'async', + 'url', + 'headers', + 'notification', + 'retries', + 'retry_interval', + 'timeout', + 'active', + 'project_id', + 'base_id', + 'created_at', + 'updated_at', + ]); + + if (insertObj.event) { + insertObj.event = insertObj.event.toLowerCase() as 'after' | 'before'; + } + + if (insertObj.operation) { + insertObj.operation = insertObj.operation.toLowerCase() as + | 'insert' + | 'delete' + | 'update'; + } + + if (insertObj.notification && typeof insertObj.notification === 'object') { + insertObj.notification = JSON.stringify(insertObj.notification); + } if (!(hook.project_id && hook.base_id)) { const model = await Model.getByIdOrName({ id: hook.fk_model_id }, ncMeta); @@ -175,27 +186,39 @@ export default class Hook implements HookType { hook: Partial, ncMeta = Noco.ncMeta ) { - const updateObj = { - title: hook.title, - description: hook.description, - env: hook.env, - type: hook.type, - event: hook.event?.toLowerCase?.(), - operation: hook.operation?.toLowerCase?.(), - async: hook.async, - payload: !!hook.payload, - url: hook.url, - headers: hook.headers, - condition: !!hook.condition, - notification: - hook.notification && typeof hook.notification === 'object' - ? JSON.stringify(hook.notification) - : hook.notification, - retries: hook.retries, - retry_interval: hook.retry_interval, - timeout: hook.timeout, - active: hook.active, - }; + const updateObj = extractProps(hook, [ + 'title', + 'description', + 'env', + 'type', + 'event', + 'operation', + 'async', + 'payload', + 'url', + 'headers', + 'condition', + 'notification', + 'retries', + 'retry_interval', + 'timeout', + 'active', + ]); + + if (updateObj.event) { + updateObj.event = updateObj.event.toLowerCase() as 'after' | 'before'; + } + + if (updateObj.operation) { + updateObj.operation = updateObj.operation.toLowerCase() as + | 'insert' + | 'delete' + | 'update'; + } + + if (updateObj.notification && typeof updateObj.notification === 'object') { + updateObj.notification = JSON.stringify(updateObj.notification); + } // get existing cache const key = `${CacheScope.HOOK}:${hookId}`; @@ -203,6 +226,7 @@ export default class Hook implements HookType { if (o) { // update data o = { ...o, ...updateObj }; + // replace notification o.notification = updateObj.notification; // set cache await NocoCache.set(key, o); diff --git a/packages/nocodb/src/lib/models/HookFilter.ts b/packages/nocodb/src/lib/models/HookFilter.ts index 956df57f8c..81167954d2 100644 --- a/packages/nocodb/src/lib/models/HookFilter.ts +++ b/packages/nocodb/src/lib/models/HookFilter.ts @@ -10,6 +10,7 @@ import { import View from './View'; import { FilterType, UITypes } from 'nocodb-sdk'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class Filter { id: string; @@ -48,20 +49,19 @@ export default class Filter { filter: Partial, ncMeta = Noco.ncMeta ) { - const insertObj = { - id: filter.id, - fk_view_id: filter.fk_view_id, - fk_column_id: filter.fk_column_id, - comparison_op: filter.comparison_op, - value: filter.value, - fk_parent_id: filter.fk_parent_id, - - is_group: filter.is_group, - logical_op: filter.logical_op, + const insertObj = extractProps(filter, [ + 'id', + 'fk_view_id', + 'fk_column_id', + 'comparison_op', + 'value', + 'fk_parent_id', + 'is_group', + 'logical_op', + 'project_id', + 'base_id', + ]); - project_id: filter.project_id, - base_id: filter.base_id, - }; if (!(filter.project_id && filter.base_id)) { const model = await Column.get({ colId: filter.fk_column_id }, ncMeta); insertObj.project_id = model.project_id; @@ -138,15 +138,14 @@ export default class Filter { } static async update(id, filter: Partial, ncMeta = Noco.ncMeta) { - const updateObj = { - fk_column_id: filter.fk_column_id, - comparison_op: filter.comparison_op, - value: filter.value, - fk_parent_id: filter.fk_parent_id, - - is_group: filter.is_group, - logical_op: filter.logical_op, - }; + const updateObj = extractProps(filter, [ + 'fk_column_id', + 'comparison_op', + 'value', + 'fk_parent_id', + 'is_group', + 'logical_op', + ]); // get existing cache const key = `${CacheScope.FILTER_EXP}:${id}`; let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); diff --git a/packages/nocodb/src/lib/models/KanbanView.ts b/packages/nocodb/src/lib/models/KanbanView.ts index 52bd2bf088..6ac1b65d09 100644 --- a/packages/nocodb/src/lib/models/KanbanView.ts +++ b/packages/nocodb/src/lib/models/KanbanView.ts @@ -3,6 +3,7 @@ import { KanbanType, UITypes } from 'nocodb-sdk'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import View from './View'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class KanbanView implements KanbanType { fk_view_id: string; @@ -63,16 +64,17 @@ export default class KanbanView implements KanbanType { .then((v) => v?.getModel(ncMeta)) .then((m) => m.getColumns(ncMeta)); - const insertObj = { - project_id: view.project_id, - base_id: view.base_id, - fk_view_id: view.fk_view_id, - fk_grp_col_id: view.fk_grp_col_id, - fk_cover_image_col_id: - view?.fk_cover_image_col_id || - columns?.find((c) => c.uidt === UITypes.Attachment)?.id, - meta: view.meta, - }; + const insertObj = extractProps(view, [ + 'project_id', + 'base_id', + 'fk_view_id', + 'fk_grp_col_id', + 'meta', + ]); + + insertObj.fk_cover_image_col_id = + view?.fk_cover_image_col_id || + columns?.find((c) => c.uidt === UITypes.Attachment)?.id; if (!(view.project_id && view.base_id)) { const viewRef = await View.get(view.fk_view_id); @@ -99,13 +101,17 @@ export default class KanbanView implements KanbanType { // get existing cache const key = `${CacheScope.KANBAN_VIEW}:${kanbanId}`; let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); - const updateObj = { - ...body, - meta: - typeof body.meta === 'string' - ? body.meta - : JSON.stringify(body.meta ?? {}), - }; + + const updateObj = extractProps(body, [ + 'title', + 'fk_cover_image_col_id', + 'meta', + ]); + + if (updateObj.meta && typeof updateObj.meta === 'object') { + updateObj.meta = JSON.stringify(updateObj.meta ?? {}); + } + if (o) { o = { ...o, ...updateObj }; // set cache diff --git a/packages/nocodb/src/lib/models/KanbanViewColumn.ts b/packages/nocodb/src/lib/models/KanbanViewColumn.ts index 87d58fe285..c86e5a2f14 100644 --- a/packages/nocodb/src/lib/models/KanbanViewColumn.ts +++ b/packages/nocodb/src/lib/models/KanbanViewColumn.ts @@ -2,6 +2,7 @@ import Noco from '../Noco'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import View from './View'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class KanbanViewColumn { id: string; @@ -40,16 +41,20 @@ export default class KanbanViewColumn { return view && new KanbanViewColumn(view); } static async insert(column: Partial, ncMeta = Noco.ncMeta) { - const insertObj = { - fk_view_id: column.fk_view_id, - fk_column_id: column.fk_column_id, - order: await ncMeta.metaGetNextOrder(MetaTable.KANBAN_VIEW_COLUMNS, { + const insertObj = extractProps(column, [ + 'fk_view_id', + 'fk_column_id', + 'show', + 'project_id', + 'base_id', + ]); + + insertObj.order = await ncMeta.metaGetNextOrder( + MetaTable.KANBAN_VIEW_COLUMNS, + { fk_view_id: column.fk_view_id, - }), - show: column.show, - project_id: column.project_id, - base_id: column.base_id, - }; + } + ); if (!(column.project_id && column.base_id)) { const viewRef = await View.get(column.fk_view_id, ncMeta); diff --git a/packages/nocodb/src/lib/models/LinkToAnotherRecordColumn.ts b/packages/nocodb/src/lib/models/LinkToAnotherRecordColumn.ts index 1234ed1e86..bbed654ea2 100644 --- a/packages/nocodb/src/lib/models/LinkToAnotherRecordColumn.ts +++ b/packages/nocodb/src/lib/models/LinkToAnotherRecordColumn.ts @@ -1,9 +1,9 @@ import Noco from '../Noco'; import Column from './Column'; import Model from './Model'; -// import NocoCache from '../cache/NocoCache'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class LinkToAnotherRecordColumn { fk_column_id?: string; @@ -89,27 +89,21 @@ export default class LinkToAnotherRecordColumn { data: Partial, ncMeta = Noco.ncMeta ) { - await ncMeta.metaInsert2(null, null, MetaTable.COL_RELATIONS, { - fk_column_id: data.fk_column_id, - - // ref_db_alias - type: data.type, - // db_type: - - fk_child_column_id: data.fk_child_column_id, - fk_parent_column_id: data.fk_parent_column_id, - - fk_mm_model_id: data.fk_mm_model_id, - fk_mm_child_column_id: data.fk_mm_child_column_id, - fk_mm_parent_column_id: data.fk_mm_parent_column_id, - - ur: data.ur, - dr: data.dr, - - fk_index_name: data.fk_index_name, - fk_related_model_id: data.fk_related_model_id, - virtual: data.virtual, - }); + const insertObj = extractProps(data, [ + 'fk_column_id', + 'type', + 'fk_child_column_id', + 'fk_parent_column_id', + 'fk_mm_model_id', + 'fk_mm_child_column_id', + 'fk_mm_parent_column_id', + 'ur', + 'dr', + 'fk_index_name', + 'fk_related_model_id', + 'virtual', + ]); + await ncMeta.metaInsert2(null, null, MetaTable.COL_RELATIONS, insertObj); return this.read(data.fk_column_id, ncMeta); } diff --git a/packages/nocodb/src/lib/models/LookupColumn.ts b/packages/nocodb/src/lib/models/LookupColumn.ts index 3737afc5bd..91c51e9a67 100644 --- a/packages/nocodb/src/lib/models/LookupColumn.ts +++ b/packages/nocodb/src/lib/models/LookupColumn.ts @@ -1,8 +1,8 @@ import Noco from '../Noco'; -// import NocoCache from '../cache/NocoCache'; import Column from './Column'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class LookupColumn { fk_relation_column_id: string; @@ -29,11 +29,13 @@ export default class LookupColumn { data: Partial, ncMeta = Noco.ncMeta ) { - await ncMeta.metaInsert2(null, null, MetaTable.COL_LOOKUP, { - fk_column_id: data.fk_column_id, - fk_relation_column_id: data.fk_relation_column_id, - fk_lookup_column_id: data.fk_lookup_column_id, - }); + const insertObj = extractProps(data, [ + 'fk_column_id', + 'fk_relation_column_id', + 'fk_lookup_column_id', + ]); + + await ncMeta.metaInsert2(null, null, MetaTable.COL_LOOKUP, insertObj); await NocoCache.appendToList( CacheScope.COL_LOOKUP, diff --git a/packages/nocodb/src/lib/models/Model.ts b/packages/nocodb/src/lib/models/Model.ts index c22c115d02..5c214c7d1e 100644 --- a/packages/nocodb/src/lib/models/Model.ts +++ b/packages/nocodb/src/lib/models/Model.ts @@ -22,6 +22,7 @@ import View from './View'; import { NcError } from '../meta/helpers/catchError'; import Audit from './Audit'; import { sanitize } from '../db/sql-data-mapper/lib/sql/helpers/sanitize'; +import { extractProps } from '../meta/helpers/extractProps'; export default class Model implements TableType { copy_enabled: boolean; @@ -103,25 +104,38 @@ export default class Model implements TableType { }, ncMeta = Noco.ncMeta ) { + const insertObj = extractProps(model, [ + 'table_name', + 'title', + 'mm', + 'order', + 'type', + 'created_at', + 'updated_at', + 'id', + ]); + + insertObj.mm = !!insertObj.mm; + + if (!insertObj.order) { + insertObj.order = await ncMeta.metaGetNextOrder( + MetaTable.FORM_VIEW_COLUMNS, + { + project_id: projectId, + base_id: baseId, + } + ); + } + + if (!insertObj.type) { + insertObj.type = ModelTypes.TABLE; + } + const { id } = await ncMeta.metaInsert2( projectId, baseId, MetaTable.MODELS, - { - table_name: model.table_name, - title: model.title, - mm: !!model.mm, - order: - model.order || - (await ncMeta.metaGetNextOrder(MetaTable.FORM_VIEW_COLUMNS, { - project_id: projectId, - base_id: baseId, - })), - type: model.type || ModelTypes.TABLE, - created_at: model.created_at, - updated_at: model.updated_at, - id: model.id, - } + insertObj ); await NocoCache.appendToList( @@ -561,14 +575,14 @@ export default class Model implements TableType { ncMeta = Noco.ncMeta ) { const model = await this.getWithInfo({ id: tableId }); - const currentPvCol = model.displayValue; const newPvCol = model.columns.find((c) => c.id === columnId); if (!newPvCol) NcError.badRequest('Column not found'); - if (currentPvCol) { + // drop existing primary column/s + for (const col of model.columns?.filter((c) => c.pv) || []) { // get existing cache - const key = `${CacheScope.COLUMN}:${currentPvCol.id}`; + const key = `${CacheScope.COLUMN}:${col.id}`; const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); if (o) { o.pv = false; @@ -583,7 +597,7 @@ export default class Model implements TableType { { pv: false, }, - currentPvCol.id + col.id ); } diff --git a/packages/nocodb/src/lib/models/ModelRoleVisibility.ts b/packages/nocodb/src/lib/models/ModelRoleVisibility.ts index f6a6a1df2f..74f6515315 100644 --- a/packages/nocodb/src/lib/models/ModelRoleVisibility.ts +++ b/packages/nocodb/src/lib/models/ModelRoleVisibility.ts @@ -8,6 +8,7 @@ import { } from '../utils/globals'; import NocoCache from '../cache/NocoCache'; import View from './View'; +import { extractProps } from '../meta/helpers/extractProps'; export default class ModelRoleVisibility implements ModelRoleVisibilityType { id?: string; @@ -134,17 +135,17 @@ export default class ModelRoleVisibility implements ModelRoleVisibilityType { >, ncMeta = Noco.ncMeta ) { - const insertObj = { - role: body.role, - disabled: body.disabled, - fk_view_id: body.fk_view_id, - project_id: body.project_id, - base_id: body.base_id, - created_at: body.created_at, - updated_at: body.updated_at, - }; + const insertObj = extractProps(body, [ + 'role', + 'disabled', + 'fk_view_id', + 'project_id', + 'base_id', + 'created_at', + 'updated_at', + ]); - if (!(body.project_id && body.base_id)) { + if (!(insertObj.project_id && insertObj.base_id)) { const view = await View.get(body.fk_view_id, ncMeta); insertObj.project_id = view.project_id; insertObj.base_id = view.base_id; diff --git a/packages/nocodb/src/lib/models/Plugin.ts b/packages/nocodb/src/lib/models/Plugin.ts index b5f2097568..711feb700e 100644 --- a/packages/nocodb/src/lib/models/Plugin.ts +++ b/packages/nocodb/src/lib/models/Plugin.ts @@ -2,6 +2,7 @@ import { PluginType } from 'nocodb-sdk'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import Noco from '../Noco'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class Plugin implements PluginType { id?: string; @@ -56,13 +57,12 @@ export default class Plugin implements PluginType { } public static async update(pluginId: string, plugin: Partial) { - const updateObj = { - input: - plugin.input && typeof plugin.input === 'object' - ? JSON.stringify(plugin.input) - : plugin.input, - active: plugin.active, - }; + const updateObj = extractProps(plugin, ['input', 'active']); + + if (updateObj.input && typeof updateObj.input === 'object') { + updateObj.input = JSON.stringify(updateObj.input); + } + // get existing cache const key = `${CacheScope.PLUGIN}:${pluginId}`; let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); diff --git a/packages/nocodb/src/lib/models/Project.ts b/packages/nocodb/src/lib/models/Project.ts index cf1cdf5a4d..ec69d51b88 100644 --- a/packages/nocodb/src/lib/models/Project.ts +++ b/packages/nocodb/src/lib/models/Project.ts @@ -36,25 +36,27 @@ export default class Project implements ProjectType { } public static async createProject( - projectBody: ProjectType & { + project: ProjectType & { created_at?; updated_at?; }, ncMeta = Noco.ncMeta ): Promise { + const insertObj = extractProps(project, [ + 'id', + 'title', + 'prefix', + 'description', + 'is_meta', + 'created_at', + 'updated_at', + ]); + const { id: projectId } = await ncMeta.metaInsert2( null, null, MetaTable.PROJECT, - { - id: projectBody?.id, - title: projectBody.title, - prefix: projectBody.prefix, - description: projectBody.description, - is_meta: projectBody.is_meta, - created_at: projectBody.created_at, - updated_at: projectBody.updated_at, - } + insertObj ); await NocoCache.appendToList( @@ -63,7 +65,7 @@ export default class Project implements ProjectType { `${CacheScope.PROJECT}:${projectId}` ); - for (const base of projectBody.bases) { + for (const base of project.bases) { await Base.createBase( { type: base.config?.client, diff --git a/packages/nocodb/src/lib/models/ProjectUser.ts b/packages/nocodb/src/lib/models/ProjectUser.ts index c4c7454a31..d62f5490e8 100644 --- a/packages/nocodb/src/lib/models/ProjectUser.ts +++ b/packages/nocodb/src/lib/models/ProjectUser.ts @@ -8,6 +8,7 @@ import { import Noco from '../Noco'; import NocoCache from '../cache/NocoCache'; import User from './User'; +import { extractProps } from '../meta/helpers/extractProps'; export default class ProjectUser { project_id: string; @@ -22,17 +23,19 @@ export default class ProjectUser { projectUser: Partial, ncMeta = Noco.ncMeta ) { + const insertObj = extractProps(projectUser, [ + 'fk_user_id', + 'project_id', + 'roles', + 'created_at', + 'updated_at', + ]); + const { project_id, fk_user_id } = await ncMeta.metaInsert2( null, null, MetaTable.PROJECT_USERS, - { - fk_user_id: projectUser.fk_user_id, - project_id: projectUser.project_id, - roles: projectUser.roles, - created_at: projectUser.created_at, - updated_at: projectUser.updated_at, - }, + insertObj, true ); diff --git a/packages/nocodb/src/lib/models/QrCodeColumn.ts b/packages/nocodb/src/lib/models/QrCodeColumn.ts index 0dc39f8d2d..9610b69f06 100644 --- a/packages/nocodb/src/lib/models/QrCodeColumn.ts +++ b/packages/nocodb/src/lib/models/QrCodeColumn.ts @@ -12,15 +12,17 @@ export default class QrCodeColumn { } public static async insert( - data: Partial, + qrCode: Partial, ncMeta = Noco.ncMeta ) { - await ncMeta.metaInsert2(null, null, MetaTable.COL_QRCODE, { - fk_column_id: data.fk_column_id, - fk_qr_value_column_id: data.fk_qr_value_column_id, - }); + const insertObj = extractProps(qrCode, [ + 'fk_column_id', + 'fk_qr_value_column_id', + ]); + + await ncMeta.metaInsert2(null, null, MetaTable.COL_QRCODE, insertObj); - return this.read(data.fk_column_id, ncMeta); + return this.read(qrCode.fk_column_id, ncMeta); } public static async read(columnId: string, ncMeta = Noco.ncMeta) { let column = diff --git a/packages/nocodb/src/lib/models/RollupColumn.ts b/packages/nocodb/src/lib/models/RollupColumn.ts index a66512300a..14fc0d3366 100644 --- a/packages/nocodb/src/lib/models/RollupColumn.ts +++ b/packages/nocodb/src/lib/models/RollupColumn.ts @@ -2,6 +2,7 @@ import Noco from '../Noco'; import Column from './Column'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import NocoCache from '../cache/NocoCache'; +import { extractProps } from '../meta/helpers/extractProps'; export default class RollupColumn { fk_column_id; @@ -20,12 +21,13 @@ export default class RollupColumn { data: Partial, ncMeta = Noco.ncMeta ) { - await ncMeta.metaInsert2(null, null, MetaTable.COL_ROLLUP, { - fk_column_id: data.fk_column_id, - fk_relation_column_id: data.fk_relation_column_id, - fk_rollup_column_id: data.fk_rollup_column_id, - rollup_function: data.rollup_function, - }); + const insertObj = extractProps(data, [ + 'fk_column_id', + 'fk_relation_column_id', + 'fk_rollup_column_id', + 'rollup_function', + ]); + await ncMeta.metaInsert2(null, null, MetaTable.COL_ROLLUP, insertObj); await NocoCache.appendToList( CacheScope.COL_ROLLUP, diff --git a/packages/nocodb/src/lib/models/SelectOption.ts b/packages/nocodb/src/lib/models/SelectOption.ts index ac2af034c9..fa24d06e50 100644 --- a/packages/nocodb/src/lib/models/SelectOption.ts +++ b/packages/nocodb/src/lib/models/SelectOption.ts @@ -1,6 +1,7 @@ import Noco from '../Noco'; import NocoCache from '../cache/NocoCache'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; +import { extractProps } from '../meta/helpers/extractProps'; export default class SelectOption { title: string; @@ -16,11 +17,19 @@ export default class SelectOption { data: Partial, ncMeta = Noco.ncMeta ) { + const insertObj = extractProps(data, [ + 'id', + 'title', + 'fk_column_id', + 'color', + 'order', + ]); + const { id } = await ncMeta.metaInsert2( null, null, MetaTable.COL_SELECT_OPTIONS, - data + insertObj ); await NocoCache.appendToList( diff --git a/packages/nocodb/src/lib/models/Sort.ts b/packages/nocodb/src/lib/models/Sort.ts index 355ca6a725..1d90324f52 100644 --- a/packages/nocodb/src/lib/models/Sort.ts +++ b/packages/nocodb/src/lib/models/Sort.ts @@ -9,6 +9,7 @@ import { } from '../utils/globals'; import NocoCache from '../cache/NocoCache'; import { SortType } from 'nocodb-sdk'; +import { extractProps } from '../meta/helpers/extractProps'; export default class Sort { id: string; @@ -35,11 +36,20 @@ export default class Sort { } public static async insert( - sortObj: Partial & { push_to_top?: boolean }, + sortObj: Partial & { push_to_top?: boolean; order?: number }, ncMeta = Noco.ncMeta ) { + const insertObj = extractProps(sortObj, [ + 'id', + 'fk_view_id', + 'fk_column_id', + 'direction', + 'project_id', + 'base_id', + ]); + // todo: implement a generic function - const order = sortObj.push_to_top + insertObj.order = sortObj.push_to_top ? 1 : (+( await ncMeta @@ -50,16 +60,6 @@ export default class Sort { }) .first() )?.order || 0) + 1; - - const insertObj = { - id: sortObj.id, - fk_view_id: sortObj.fk_view_id, - fk_column_id: sortObj.fk_column_id, - direction: sortObj.direction, - project_id: sortObj.project_id, - base_id: sortObj.base_id, - order, - }; if (!(sortObj.project_id && sortObj.base_id)) { const model = await Column.get({ colId: sortObj.fk_column_id }, ncMeta); insertObj.project_id = model.project_id; diff --git a/packages/nocodb/src/lib/models/SyncLogs.ts b/packages/nocodb/src/lib/models/SyncLogs.ts index 035debc75e..d10e814c56 100644 --- a/packages/nocodb/src/lib/models/SyncLogs.ts +++ b/packages/nocodb/src/lib/models/SyncLogs.ts @@ -1,5 +1,6 @@ import Noco from '../Noco'; import { MetaTable } from '../utils/globals'; +import { extractProps } from '../meta/helpers/extractProps'; export default class SyncLogs { id?: string; @@ -34,13 +35,13 @@ export default class SyncLogs { >, ncMeta = Noco.ncMeta ) { - const insertObj = { - project_id: syncLog?.project_id, - fk_sync_source_id: syncLog?.fk_sync_source_id, - time_taken: syncLog?.time_taken, - status: syncLog?.status, - status_details: syncLog?.status_details, - }; + const insertObj = extractProps(syncLog, [ + 'project_id', + 'fk_sync_source_id', + 'time_taken', + 'status', + 'status_details', + ]); const { id } = await ncMeta.metaInsert2( null, diff --git a/packages/nocodb/src/lib/models/SyncSource.ts b/packages/nocodb/src/lib/models/SyncSource.ts index 4f169fae12..25292a3576 100644 --- a/packages/nocodb/src/lib/models/SyncSource.ts +++ b/packages/nocodb/src/lib/models/SyncSource.ts @@ -73,15 +73,15 @@ export default class SyncSource { >, ncMeta = Noco.ncMeta ) { - const insertObj = { - id: syncSource?.id, - title: syncSource?.title, - type: syncSource?.type, - details: syncSource?.details, - project_id: syncSource?.project_id, - base_id: syncSource?.base_id, - fk_user_id: syncSource?.fk_user_id, - }; + const insertObj = extractProps(syncSource, [ + 'id', + 'title', + 'type', + 'details', + 'project_id', + 'base_id', + 'fk_user_id', + ]); if (insertObj.details && typeof insertObj.details === 'object') { insertObj.details = JSON.stringify(insertObj.details); diff --git a/packages/nocodb/src/lib/models/View.ts b/packages/nocodb/src/lib/models/View.ts index 64a2df528c..b58fe429ac 100644 --- a/packages/nocodb/src/lib/models/View.ts +++ b/packages/nocodb/src/lib/models/View.ts @@ -244,25 +244,29 @@ export default class View implements ViewType { }, ncMeta = Noco.ncMeta ) { + const insertObj = extractProps(view, [ + 'id', + 'title', + 'is_default', + 'type', + 'fk_model_id', + 'project_id', + 'base_id', + 'created_at', + 'updated_at', + 'meta', + ]); + // get order value - const order = await ncMeta.metaGetNextOrder(MetaTable.VIEWS, { + insertObj.order = await ncMeta.metaGetNextOrder(MetaTable.VIEWS, { fk_model_id: view.fk_model_id, }); - const insertObj = { - id: view.id, - title: view.title, - show: true, - is_default: view.is_default, - order, - type: view.type, - fk_model_id: view.fk_model_id, - project_id: view.project_id, - base_id: view.base_id, - created_at: view.created_at, - updated_at: view.updated_at, - meta: view.meta ?? {}, - }; + insertObj.show = true; + + if (!insertObj.meta) { + insertObj.meta = {}; + } insertObj.meta = stringifyMetaProp(insertObj); diff --git a/packages/nocodb/src/lib/version-upgrader/NcUpgrader.ts b/packages/nocodb/src/lib/version-upgrader/NcUpgrader.ts index cd84032692..c125701a4c 100644 --- a/packages/nocodb/src/lib/version-upgrader/NcUpgrader.ts +++ b/packages/nocodb/src/lib/version-upgrader/NcUpgrader.ts @@ -43,8 +43,8 @@ export default class NcUpgrader { { name: '0100002', handler: ncFilterUpgrader }, { name: '0101002', handler: ncAttachmentUpgrader }, { name: '0104002', handler: ncAttachmentUpgrader_0104002 }, - { name: '0104003', handler: ncStickyColumnUpgrader }, { name: '0104004', handler: ncFilterUpgrader_0104004 }, + { name: '0105002', handler: ncStickyColumnUpgrader }, ]; if (!(await ctx.ncMeta.knexConnection?.schema?.hasTable?.('nc_store'))) { return; diff --git a/packages/nocodb/src/lib/version-upgrader/ncProjectUpgraderV2_0090000.ts b/packages/nocodb/src/lib/version-upgrader/ncProjectUpgraderV2_0090000.ts index 2f604b18df..4bd94c8574 100644 --- a/packages/nocodb/src/lib/version-upgrader/ncProjectUpgraderV2_0090000.ts +++ b/packages/nocodb/src/lib/version-upgrader/ncProjectUpgraderV2_0090000.ts @@ -1231,7 +1231,7 @@ async function migrateWebhooks(ctx: MigrateCtxV1, ncMeta: any) { env: string; tn: string; type: string; - event: 'After' | 'Before'; + event: 'after' | 'before'; operation: 'delete' | 'update' | 'insert'; async: boolean; payload: string; diff --git a/packages/nocodb/src/lib/version-upgrader/ncStickyColumnUpgrader.ts b/packages/nocodb/src/lib/version-upgrader/ncStickyColumnUpgrader.ts index 67b02ce842..1fa222cd17 100644 --- a/packages/nocodb/src/lib/version-upgrader/ncStickyColumnUpgrader.ts +++ b/packages/nocodb/src/lib/version-upgrader/ncStickyColumnUpgrader.ts @@ -38,6 +38,50 @@ export default async function ({ ncMeta }: NcUpgraderCtx) { view_columns_meta.push(col_meta); } + // if no display value column is set + if (!view_columns_meta.some((column) => column.pv)) { + const pkIndex = view_columns_meta.findIndex((column) => column.pk); + + // if PK is at the end of table + if (pkIndex === view_columns_meta.length - 1) { + if (pkIndex > 0) { + await ncMeta.metaUpdate( + null, + null, + MetaTable.COLUMNS, + { pv: true }, + view_columns_meta[pkIndex - 1].id + ); + } else if (view_columns_meta.length > 0) { + await ncMeta.metaUpdate( + null, + null, + MetaTable.COLUMNS, + { pv: true }, + view_columns_meta[0].id + ); + } + // pk is not at the end of table + } else if (pkIndex > -1) { + await ncMeta.metaUpdate( + null, + null, + MetaTable.COLUMNS, + { pv: true }, + view_columns_meta[pkIndex + 1].id + ); + // no pk at all + } else if (view_columns_meta.length > 0) { + await ncMeta.metaUpdate( + null, + null, + MetaTable.COLUMNS, + { pv: true }, + view_columns_meta[0].id + ); + } + } + const primary_value_column_meta = view_columns_meta.find((col) => col.pv); if (primary_value_column_meta) { diff --git a/scripts/sdk/swagger.json b/scripts/sdk/swagger.json index a2690a160c..796123f9ff 100644 --- a/scripts/sdk/swagger.json +++ b/scripts/sdk/swagger.json @@ -9175,8 +9175,8 @@ "event": { "type": "string", "enum": [ - "After", - "Before" + "after", + "before" ] }, "operation": {