Browse Source

Merge branch 'develop' into pr/5165

pull/5165/head
Wing-Kam Wong 2 years ago
parent
commit
92190b8ca1
  1. 33
      packages/nc-gui/components/virtual-cell/components/ListItems.vue
  2. 1
      packages/nc-gui/lib/constants.ts
  3. 2
      packages/nc-gui/package-lock.json
  4. 2
      packages/nc-lib-gui/package.json
  5. 4
      packages/nocodb-sdk/package-lock.json
  6. 2
      packages/nocodb-sdk/package.json
  7. 2
      packages/nocodb-sdk/src/lib/Api.ts
  8. 20
      packages/nocodb/package-lock.json
  9. 4
      packages/nocodb/package.json
  10. 2
      packages/nocodb/src/lib/Noco.ts
  11. 2
      packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts
  12. 19
      packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts
  13. 2
      packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2.ts
  14. 2
      packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2Trans.ts
  15. 7
      packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts
  16. 18
      packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2Tans.ts
  17. 2
      packages/nocodb/src/lib/meta/NcMetaMgr.ts
  18. 2
      packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts
  19. 24
      packages/nocodb/src/lib/meta/helpers/mapDefaultDisplayValue.ts
  20. 38
      packages/nocodb/src/lib/models/Audit.ts
  21. 15
      packages/nocodb/src/lib/models/BarcodeColumn.ts
  22. 139
      packages/nocodb/src/lib/models/Column.ts
  23. 37
      packages/nocodb/src/lib/models/Filter.ts
  24. 91
      packages/nocodb/src/lib/models/FormView.ts
  25. 53
      packages/nocodb/src/lib/models/FormViewColumn.ts
  26. 17
      packages/nocodb/src/lib/models/FormulaColumn.ts
  27. 63
      packages/nocodb/src/lib/models/GalleryView.ts
  28. 23
      packages/nocodb/src/lib/models/GalleryViewColumn.ts
  29. 35
      packages/nocodb/src/lib/models/GridView.ts
  30. 19
      packages/nocodb/src/lib/models/GridViewColumn.ts
  31. 120
      packages/nocodb/src/lib/models/Hook.ts
  32. 43
      packages/nocodb/src/lib/models/HookFilter.ts
  33. 38
      packages/nocodb/src/lib/models/KanbanView.ts
  34. 23
      packages/nocodb/src/lib/models/KanbanViewColumn.ts
  35. 38
      packages/nocodb/src/lib/models/LinkToAnotherRecordColumn.ts
  36. 14
      packages/nocodb/src/lib/models/LookupColumn.ts
  37. 52
      packages/nocodb/src/lib/models/Model.ts
  38. 21
      packages/nocodb/src/lib/models/ModelRoleVisibility.ts
  39. 14
      packages/nocodb/src/lib/models/Plugin.ts
  40. 24
      packages/nocodb/src/lib/models/Project.ts
  41. 17
      packages/nocodb/src/lib/models/ProjectUser.ts
  42. 14
      packages/nocodb/src/lib/models/QrCodeColumn.ts
  43. 14
      packages/nocodb/src/lib/models/RollupColumn.ts
  44. 11
      packages/nocodb/src/lib/models/SelectOption.ts
  45. 24
      packages/nocodb/src/lib/models/Sort.ts
  46. 15
      packages/nocodb/src/lib/models/SyncLogs.ts
  47. 18
      packages/nocodb/src/lib/models/SyncSource.ts
  48. 34
      packages/nocodb/src/lib/models/View.ts
  49. 2
      packages/nocodb/src/lib/utils/common/BaseApiBuilder.ts
  50. 2
      packages/nocodb/src/lib/utils/common/NcConnectionMgr.ts
  51. 2
      packages/nocodb/src/lib/utils/common/NcConnectionMgrv2.ts
  52. 2
      packages/nocodb/src/lib/version-upgrader/NcUpgrader.ts
  53. 2
      packages/nocodb/src/lib/version-upgrader/ncProjectUpgraderV2_0090000.ts
  54. 44
      packages/nocodb/src/lib/version-upgrader/ncStickyColumnUpgrader.ts
  55. 4
      scripts/sdk/swagger.json

33
packages/nc-gui/components/virtual-cell/components/ListItems.vue

@ -48,15 +48,21 @@ const saveRow = inject(SaveRowInj, () => {})
const selectedRowIndex = ref(0) const selectedRowIndex = ref(0)
const isAltKeyDown = ref(false)
const linkRow = async (row: Record<string, any>) => { const linkRow = async (row: Record<string, any>) => {
if (isNew.value) { if (isNew.value) {
addLTARRef(row, column?.value as ColumnType) addLTARRef(row, column?.value as ColumnType)
saveRow() saveRow!()
} else { } else {
await link(row) await link(row)
} }
if (isAltKeyDown.value) {
loadChildrenExcludedList()
} else {
vModel.value = false vModel.value = false
} }
}
/** reload list on modal open */ /** reload list on modal open */
watch(vModel, (nextVal, prevVal) => { watch(vModel, (nextVal, prevVal) => {
@ -159,6 +165,27 @@ useSelectedCellKeyupListener(vModel, (e: KeyboardEvent) => {
const activeRow = (vNode?: InstanceType<typeof Card>) => { const activeRow = (vNode?: InstanceType<typeof Card>) => {
vNode?.$el?.scrollIntoView({ block: 'nearest', inline: 'nearest' }) 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)
}
})
</script> </script>
<template> <template>
@ -219,6 +246,10 @@ const activeRow = (vNode?: InstanceType<typeof Card>) => {
show-less-items show-less-items
/> />
</div> </div>
<div class="text-xs text-gray-400 text-center px-2 mt-4 pb-0">
* Use <kbd>ALT</kbd> / <kbd>OPT</kbd> + <kbd>Click</kbd> to select multiple records
</div>
</template> </template>
<a-empty v-else class="my-10" :image="Empty.PRESENTED_IMAGE_SIMPLE" /> <a-empty v-else class="my-10" :image="Empty.PRESENTED_IMAGE_SIMPLE" />

1
packages/nc-gui/lib/constants.ts

@ -57,6 +57,7 @@ export const rolePermissions = {
fieldsSync: true, fieldsSync: true,
gridColUpdate: true, gridColUpdate: true,
filterSync: true, filterSync: true,
filterChildrenRead: true,
csvImport: true, csvImport: true,
apiDocs: true, apiDocs: true,
projectSettings: true, projectSettings: true,

2
packages/nc-gui/package-lock.json generated

@ -97,7 +97,7 @@
} }
}, },
"../nocodb-sdk": { "../nocodb-sdk": {
"version": "0.105.2", "version": "0.105.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",

2
packages/nc-lib-gui/package.json

@ -1,6 +1,6 @@
{ {
"name": "nc-lib-gui", "name": "nc-lib-gui",
"version": "0.105.2", "version": "0.105.3",
"description": "NocoDB GUI", "description": "NocoDB GUI",
"author": { "author": {
"name": "NocoDB", "name": "NocoDB",

4
packages/nocodb-sdk/package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "nocodb-sdk", "name": "nocodb-sdk",
"version": "0.105.2", "version": "0.105.3",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "nocodb-sdk", "name": "nocodb-sdk",
"version": "0.105.2", "version": "0.105.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",

2
packages/nocodb-sdk/package.json

@ -1,6 +1,6 @@
{ {
"name": "nocodb-sdk", "name": "nocodb-sdk",
"version": "0.105.2", "version": "0.105.3",
"description": "NocoDB SDK", "description": "NocoDB SDK",
"main": "build/main/index.js", "main": "build/main/index.js",
"typings": "build/main/index.d.ts", "typings": "build/main/index.d.ts",

2
packages/nocodb-sdk/src/lib/Api.ts

@ -502,7 +502,7 @@ export interface HookType {
description?: string; description?: string;
env?: string; env?: string;
type?: string; type?: string;
event?: 'After' | 'Before'; event?: 'after' | 'before';
operation?: 'insert' | 'delete' | 'update'; operation?: 'insert' | 'delete' | 'update';
async?: boolean; async?: boolean;
payload?: string; payload?: string;

20
packages/nocodb/package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "nocodb", "name": "nocodb",
"version": "0.105.2", "version": "0.105.3",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "nocodb", "name": "nocodb",
"version": "0.105.2", "version": "0.105.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@google-cloud/storage": "^5.7.2", "@google-cloud/storage": "^5.7.2",
@ -65,7 +65,7 @@
"mysql2": "^2.2.5", "mysql2": "^2.2.5",
"nanoid": "^3.1.20", "nanoid": "^3.1.20",
"nc-help": "0.2.85", "nc-help": "0.2.85",
"nc-lib-gui": "0.105.2", "nc-lib-gui": "0.105.3",
"nc-plugin": "0.1.2", "nc-plugin": "0.1.2",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"nocodb-sdk": "file:../nocodb-sdk", "nocodb-sdk": "file:../nocodb-sdk",
@ -154,7 +154,7 @@
} }
}, },
"../nocodb-sdk": { "../nocodb-sdk": {
"version": "0.105.2", "version": "0.105.3",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
@ -11257,9 +11257,9 @@
} }
}, },
"node_modules/nc-lib-gui": { "node_modules/nc-lib-gui": {
"version": "0.105.2", "version": "0.105.3",
"resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.105.2.tgz", "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.105.3.tgz",
"integrity": "sha512-uycep2vme3XP6PwvFjJ6wE2fpCNiaJ/ptWR7ZHwRCu500eJGdtonWc00BQf01FitQ1vKq9Cpqqi2b0hoFBLFvQ==", "integrity": "sha512-w07Y2+nBiUQYiUyURwH9nqvzzxXsz8MALU/MhmWyNe3Z0YhBvPPLLUxtG1WR3USLI925YT0BsAZTn+iSP3ooPw==",
"dependencies": { "dependencies": {
"express": "^4.17.1" "express": "^4.17.1"
} }
@ -27875,9 +27875,9 @@
} }
}, },
"nc-lib-gui": { "nc-lib-gui": {
"version": "0.105.2", "version": "0.105.3",
"resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.105.2.tgz", "resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.105.3.tgz",
"integrity": "sha512-uycep2vme3XP6PwvFjJ6wE2fpCNiaJ/ptWR7ZHwRCu500eJGdtonWc00BQf01FitQ1vKq9Cpqqi2b0hoFBLFvQ==", "integrity": "sha512-w07Y2+nBiUQYiUyURwH9nqvzzxXsz8MALU/MhmWyNe3Z0YhBvPPLLUxtG1WR3USLI925YT0BsAZTn+iSP3ooPw==",
"requires": { "requires": {
"express": "^4.17.1" "express": "^4.17.1"
} }

4
packages/nocodb/package.json

@ -1,6 +1,6 @@
{ {
"name": "nocodb", "name": "nocodb",
"version": "0.105.2", "version": "0.105.3",
"description": "NocoDB Backend", "description": "NocoDB Backend",
"main": "dist/bundle.js", "main": "dist/bundle.js",
"author": { "author": {
@ -105,7 +105,7 @@
"mysql2": "^2.2.5", "mysql2": "^2.2.5",
"nanoid": "^3.1.20", "nanoid": "^3.1.20",
"nc-help": "0.2.85", "nc-help": "0.2.85",
"nc-lib-gui": "0.105.2", "nc-lib-gui": "0.105.3",
"nc-plugin": "0.1.2", "nc-plugin": "0.1.2",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"nocodb-sdk": "file:../nocodb-sdk", "nocodb-sdk": "file:../nocodb-sdk",

2
packages/nocodb/src/lib/Noco.ts

@ -105,7 +105,7 @@ export default class Noco {
constructor() { constructor() {
process.env.PORT = process.env.PORT || '8080'; process.env.PORT = process.env.PORT || '8080';
// todo: move // 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 env variable NC_MINIMAL_DBS is set, then disable project creation with external sources
if (process.env.NC_MINIMAL_DBS) { if (process.env.NC_MINIMAL_DBS) {

2
packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts

@ -1913,7 +1913,7 @@ class OracleClient extends KnexClient {
* @returns {Number} code * @returns {Number} code
* @returns {String} message * @returns {String} message
*/ */
async totalRecords(_args: any = {}) { async totalRecords(_args: any = {}): Promise<Result> {
// @ts-ignore // @ts-ignore
const func = this.totalRecords.name; const func = this.totalRecords.name;
throw new Error('Function not supported for oracle yet'); throw new Error('Function not supported for oracle yet');

19
packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts

@ -17,6 +17,14 @@ import NcConnectionMgr from '../../utils/common/NcConnectionMgr';
import { customAlphabet } from 'nanoid'; import { customAlphabet } from 'nanoid';
import Debug from '../util/Debug'; import Debug from '../util/Debug';
import Result from '../util/Result'; import Result from '../util/Result';
import type MssqlClient from '../sql-client/lib/mssql/MssqlClient';
import type MysqlClient from '../sql-client/lib/mysql/MysqlClient';
import type OracleClient from '../sql-client/lib/oracle/OracleClient';
import type PGClient from '../sql-client/lib/pg/PgClient';
import type SnowflakeClient from '../sql-client/lib/snowflake/SnowflakeClient';
import type SqliteClient from '../sql-client/lib/sqlite/SqliteClient';
const randomID = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 20); const randomID = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 20);
const log = new Debug('SqlMgr'); const log = new Debug('SqlMgr');
@ -337,7 +345,16 @@ export default class SqlMgr {
* @returns * @returns
* @memberof SqlMgr * @memberof SqlMgr
*/ */
public async projectGetSqlClient(args) { public async projectGetSqlClient(
args
): Promise<
| SnowflakeClient
| MysqlClient
| SqliteClient
| MssqlClient
| OracleClient
| PGClient
> {
const func = this.projectGetSqlClient.name; const func = this.projectGetSqlClient.name;
log.api(`${func}:args:`, args); log.api(`${func}:args:`, args);

2
packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2.ts

@ -118,7 +118,7 @@ export default class SqlMgrv2 {
return sqlMigrationStatements; return sqlMigrationStatements;
} }
protected async getSqlClient(base: Base): Promise<any> { protected async getSqlClient(base: Base) {
return NcConnectionMgrv2.getSqlClient(base); return NcConnectionMgrv2.getSqlClient(base);
} }
} }

2
packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2Trans.ts

@ -52,7 +52,7 @@ export default class SqlMgrv2Trans extends SqlMgrv2 {
} }
} }
protected async getSqlClient(base: Base): Promise<any> { protected async getSqlClient(base: Base) {
return NcConnectionMgrv2.getSqlClient(base, this.trx); return NcConnectionMgrv2.getSqlClient(base, this.trx);
} }

7
packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts

@ -1,6 +1,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { promisify } from 'util'; import { promisify } from 'util';
import { Knex } from 'knex';
import glob from 'glob'; import glob from 'glob';
import SqlClientFactory from '../../sql-client/lib/SqlClientFactory'; import SqlClientFactory from '../../sql-client/lib/SqlClientFactory';
@ -428,7 +429,7 @@ export default class KnexMigratorv2 {
// } // }
} }
protected async getSqlClient(base: Base): Promise<any> { protected async getSqlClient(base: Base) {
return NcConnectionMgrv2.getSqlClient(base); return NcConnectionMgrv2.getSqlClient(base);
} }
@ -753,7 +754,7 @@ export default class KnexMigratorv2 {
const vm = this; const vm = this;
const trx = sqlClient.knex.isTransaction const trx = sqlClient.knex.isTransaction
? sqlClient.knex ? (sqlClient.knex as Knex.Transaction)
: await sqlClient.knex.transaction(); : await sqlClient.knex.transaction();
try { try {
for (const query of upStatements) { for (const query of upStatements) {
@ -920,7 +921,7 @@ export default class KnexMigratorv2 {
const vm = this; const vm = this;
const trx = sqlClient.knex.isTransaction const trx = sqlClient.knex.isTransaction
? sqlClient.knex ? (sqlClient.knex as Knex.Transaction)
: await sqlClient.knex.transaction(); : await sqlClient.knex.transaction();
try { try {
for (const query of downStatements) { for (const query of downStatements) {

18
packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2Tans.ts

@ -11,6 +11,13 @@ import Noco from '../../../Noco';
import { XKnex } from '../../sql-data-mapper'; import { XKnex } from '../../sql-data-mapper';
import NcMetaIO from '../../../meta/NcMetaIO'; import NcMetaIO from '../../../meta/NcMetaIO';
import type MssqlClient from '../../sql-client/lib/mssql/MssqlClient';
import type MysqlClient from '../../sql-client/lib/mysql/MysqlClient';
import type OracleClient from '../../sql-client/lib/oracle/OracleClient';
import type PGClient from '../../sql-client/lib/pg/PgClient';
import type SnowflakeClient from '../../sql-client/lib/snowflake/SnowflakeClient';
import type SqliteClient from '../../sql-client/lib/sqlite/SqliteClient';
export default class KnexMigratorv2Tans extends KnexMigratorv2 { export default class KnexMigratorv2Tans extends KnexMigratorv2 {
protected sqlClient: any; protected sqlClient: any;
protected ncMeta: NcMetaIO; protected ncMeta: NcMetaIO;
@ -24,7 +31,16 @@ export default class KnexMigratorv2Tans extends KnexMigratorv2 {
protected get metaDb(): XKnex { protected get metaDb(): XKnex {
return this.ncMeta.knex || Noco.ncMeta.knex; return this.ncMeta.knex || Noco.ncMeta.knex;
} }
protected async getSqlClient(base: Base): Promise<any> { protected async getSqlClient(
base: Base
): Promise<
| SnowflakeClient
| MysqlClient
| SqliteClient
| MssqlClient
| OracleClient
| PGClient
> {
return this.sqlClient || NcConnectionMgrv2.getSqlClient(base); return this.sqlClient || NcConnectionMgrv2.getSqlClient(base);
} }
} }

2
packages/nocodb/src/lib/meta/NcMetaMgr.ts

@ -2909,7 +2909,7 @@ export default class NcMetaMgr {
} }
} }
protected async projectGetSqlClient(args): Promise<any> { protected async projectGetSqlClient(args) {
const builder = this.getBuilder(args); const builder = this.getBuilder(args);
return builder?.getSqlClient(); return builder?.getSqlClient();
} }

2
packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts

@ -229,6 +229,8 @@ export async function populateMeta(base: Base, project: Project): Promise<any> {
const columns = (await sqlClient.columnList({ tn: table.table_name })) const columns = (await sqlClient.columnList({ tn: table.table_name }))
?.data?.list; ?.data?.list;
mapDefaultDisplayValue(columns);
/* create nc_models and its rows if it doesn't exists */ /* create nc_models and its rows if it doesn't exists */
models2[table.table_name] = await Model.insert(project.id, base.id, { models2[table.table_name] = await Model.insert(project.id, base.id, {
table_name: table.table_name, table_name: table.table_name,

24
packages/nocodb/src/lib/meta/helpers/mapDefaultDisplayValue.ts

@ -4,31 +4,27 @@ export default function mapDefaultDisplayValue<T extends ColumnType>(
columnsArr: Array<T> columnsArr: Array<T>
): void | T { ): void | T {
if (!columnsArr.some((column) => column.pv)) { if (!columnsArr.some((column) => column.pv)) {
let len = columnsArr.length; const pkIndex = columnsArr.findIndex((column) => column.pk);
let pkIndex = -1;
while (len--) {
if (columnsArr[len].pk) {
pkIndex = len;
break;
}
}
// if PK is at the end of table // if PK is at the end of table
if (pkIndex === columnsArr.length - 1) { if (pkIndex === columnsArr.length - 1) {
if (pkIndex > 0) { if (pkIndex > 0) {
columnsArr[pkIndex - 1].pv = true; columnsArr[pkIndex - 1].pv = true;
return columnsArr[pkIndex - 1]; return columnsArr[pkIndex - 1];
} } else if (columnsArr.length > 0) {
columnsArr[0].pv = true;
return columnsArr[0];
} }
// pk is not at the end of table // pk is not at the end of table
else if (pkIndex > -1) { } else if (pkIndex > -1) {
columnsArr[pkIndex + 1].pv = true; columnsArr[pkIndex + 1].pv = true;
return columnsArr[pkIndex + 1]; return columnsArr[pkIndex + 1];
}
// no pk at all // no pk at all
else { } else {
// todo: if (columnsArr.length > 0) {
columnsArr[0].pv = true;
return columnsArr[0];
}
} }
} }
} }

38
packages/nocodb/src/lib/models/Audit.ts

@ -2,6 +2,7 @@ import { AuditOperationTypes, AuditType } from 'nocodb-sdk';
import { MetaTable } from '../utils/globals'; import { MetaTable } from '../utils/globals';
import Noco from '../Noco'; import Noco from '../Noco';
import Model from './Model'; import Model from './Model';
import { extractProps } from '../meta/helpers/extractProps';
export default class Audit implements AuditType { export default class Audit implements AuditType {
id?: string; id?: string;
@ -48,27 +49,28 @@ export default class Audit implements AuditType {
return; return;
} }
const insertAudit = async () => { const insertAudit = async () => {
if (!audit.project_id && audit.fk_model_id) { const insertObj = extractProps(audit, [
audit.project_id = ( 'user',
await Model.getByIdOrName({ id: audit.fk_model_id }, ncMeta) '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; ).project_id;
} }
return await ncMeta.metaInsert2(null, null, MetaTable.AUDIT, { return await ncMeta.metaInsert2(null, null, MetaTable.AUDIT, insertObj);
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,
});
}; };
if (forceAwait) { if (forceAwait) {

15
packages/nocodb/src/lib/models/BarcodeColumn.ts

@ -14,16 +14,17 @@ export default class BarcodeColumn {
} }
public static async insert( public static async insert(
data: Partial<BarcodeColumn>, barcodeColumn: Partial<BarcodeColumn>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_BARCODE, { const insertObj = extractProps(barcodeColumn, [
fk_column_id: data.fk_column_id, 'fk_column_id',
fk_barcode_value_column_id: data.fk_barcode_value_column_id, 'fk_barcode_value_column_id',
barcode_format: data.barcode_format, '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) { public static async read(columnId: string, ncMeta = Noco.ncMeta) {
let column = let column =

139
packages/nocodb/src/lib/models/Column.ts

@ -25,6 +25,7 @@ import addFormulaErrorIfMissingColumn from '../meta/helpers/addFormulaErrorIfMis
import { NcError } from '../meta/helpers/catchError'; import { NcError } from '../meta/helpers/catchError';
import QrCodeColumn from './QrCodeColumn'; import QrCodeColumn from './QrCodeColumn';
import BarcodeColumn from './BarcodeColumn'; import BarcodeColumn from './BarcodeColumn';
import { extractProps } from '../meta/helpers/extractProps';
export default class Column<T = any> implements ColumnType { export default class Column<T = any> implements ColumnType {
public fk_model_id: string; public fk_model_id: string;
@ -85,41 +86,50 @@ export default class Column<T = any> implements ColumnType {
) { ) {
if (!column.fk_model_id) NcError.badRequest('Missing model id'); if (!column.fk_model_id) NcError.badRequest('Missing model id');
const insertObj: any = { // TODO: fix type
id: column?.id, const insertObj = extractProps(column as any, [
fk_model_id: column.fk_model_id, 'id',
column_name: column.column_name || column.cn, 'fk_model_id',
title: column.title || column._cn, 'column_name',
uidt: column.uidt, 'title',
dt: column.dt, 'uidt',
np: column.np, 'dt',
ns: column.ns, 'np',
clen: column.clen, 'ns',
cop: column.cop, 'clen',
pk: column.pk, 'cop',
rqd: column.rqd, 'pk',
un: column.un, 'rqd',
ct: column.ct, 'un',
ai: column.ai, 'ct',
unique: column.unique, 'ai',
cdf: column.cdf, 'unique',
cc: column.cc, 'cdf',
csn: column.csn, 'cc',
dtx: column.dtx, 'csn',
dtxp: column.dtxp, 'dtx',
dtxs: column.dtxs, 'dtxp',
au: column.au, 'dtxs',
pv: column.pv, 'au',
order: column.order, 'pv',
project_id: column.project_id, 'order',
base_id: column.base_id, 'project_id',
system: column.system, 'base_id',
meta: 'system',
column.meta && typeof column.meta === 'object' 'meta',
? JSON.stringify(column.meta) ]);
: column.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 (column.validate) {
if (typeof column.validate === 'string') if (typeof column.validate === 'string')
insertObj.validate = column.validate; insertObj.validate = column.validate;
@ -873,7 +883,11 @@ export default class Column<T = any> implements ColumnType {
); );
} }
static async update(colId: string, column: any, ncMeta = Noco.ncMeta) { static async update(
colId: string,
column: Partial<Column>,
ncMeta = Noco.ncMeta
) {
const oldCol = await Column.get({ colId }, ncMeta); const oldCol = await Column.get({ colId }, ncMeta);
switch (oldCol.uidt) { switch (oldCol.uidt) {
@ -965,33 +979,34 @@ export default class Column<T = any> implements ColumnType {
break; break;
} }
} }
const updateObj = {
column_name: column.column_name, const updateObj = extractProps(column, [
title: column.title, 'column_name',
uidt: column.uidt, 'title',
dt: column.dt, 'uidt',
np: column.np, 'dt',
ns: column.ns, 'np',
clen: column.clen, 'ns',
cop: column.cop, 'clen',
pk: column.pk, 'cop',
rqd: column.rqd, 'pk',
un: column.un, 'rqd',
ct: column.ct, 'un',
ai: column.ai, 'ct',
unique: column.unique, 'ai',
cdf: column.cdf, 'unique',
cc: column.cc, 'cdf',
csn: column.csn, 'cc',
dtx: column.dtx, 'csn',
dtxp: column.dtxp, 'dtx',
dtxs: column.dtxs, 'dtxp',
au: column.au, 'dtxs',
pv: column.pv, 'au',
system: column.system, 'pv',
validate: null, 'system',
meta: column.meta, 'validate',
}; 'meta',
]);
if (column.validate) { if (column.validate) {
if (typeof column.validate === 'string') if (typeof column.validate === 'string')

37
packages/nocodb/src/lib/models/Filter.ts

@ -77,29 +77,30 @@ export default class Filter {
} }
public static async insert( public static async insert(
filter: Partial<FilterType>, filter: Partial<FilterType> & { order?: number },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = { const insertObj = extractProps(filter, [
id: filter.id, 'id',
fk_view_id: filter.fk_view_id, 'fk_view_id',
fk_hook_id: filter.fk_hook_id, 'fk_hook_id',
fk_column_id: filter.fk_column_id, 'fk_column_id',
comparison_op: filter.comparison_op, 'comparison_op',
value: filter.value, 'value',
fk_parent_id: filter.fk_parent_id, 'fk_parent_id',
'is_group',
is_group: filter.is_group, 'logical_op',
logical_op: filter.logical_op, 'project_id',
'base_id',
project_id: filter.project_id, 'order',
base_id: filter.base_id, ]);
order: await ncMeta.metaGetNextOrder(MetaTable.FILTER_EXP, {
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 ? 'fk_hook_id' : 'fk_view_id']: filter.fk_hook_id
? filter.fk_hook_id ? filter.fk_hook_id
: filter.fk_view_id, : filter.fk_view_id,
}), });
};
if (!(filter.project_id && filter.base_id)) { if (!(filter.project_id && filter.base_id)) {
let model: { project_id?: string; base_id?: string }; let model: { project_id?: string; base_id?: string };
if (filter.fk_view_id) { if (filter.fk_view_id) {

91
packages/nocodb/src/lib/models/FormView.ts

@ -5,6 +5,7 @@ import { deserializeJSON, serializeJSON } from '../utils/serialize';
import FormViewColumn from './FormViewColumn'; import FormViewColumn from './FormViewColumn';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class FormView implements FormType { export default class FormView implements FormType {
show: boolean; show: boolean;
@ -53,22 +54,25 @@ export default class FormView implements FormType {
} }
static async insert(view: Partial<FormView>, ncMeta = Noco.ncMeta) { static async insert(view: Partial<FormView>, ncMeta = Noco.ncMeta) {
const insertObj = { const insertObj = extractProps(view, [
fk_view_id: view.fk_view_id, 'fk_view_id',
project_id: view.project_id, 'project_id',
base_id: view.base_id, 'base_id',
heading: view.heading, 'heading',
subheading: view.subheading, 'subheading',
success_msg: view.success_msg, 'success_msg',
redirect_url: view.redirect_url, 'redirect_url',
redirect_after_secs: view.redirect_after_secs, 'redirect_after_secs',
email: view.email, 'email',
banner_image_url: view.banner_image_url, 'banner_image_url',
logo_url: view.logo_url, 'logo_url',
submit_another_form: view.submit_another_form, 'submit_another_form',
show_blank_form: view.show_blank_form, 'show_blank_form',
meta: serializeJSON(view.meta), 'meta',
}; ]);
if (insertObj.meta) {
insertObj.meta = serializeJSON(insertObj.meta);
}
if (!(view.project_id && view.base_id)) { if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.fk_view_id); const viewRef = await View.get(view.fk_view_id);
insertObj.project_id = viewRef.project_id; insertObj.project_id = viewRef.project_id;
@ -86,44 +90,35 @@ export default class FormView implements FormType {
) { ) {
// get existing cache // get existing cache
const key = `${CacheScope.FORM_VIEW}:${formId}`; 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) { if (o) {
o.heading = body.heading; o = { ...o, ...updateObj };
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;
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o);
o.meta = serializeJSON(body.meta);
} }
if (updateObj.meta) {
updateObj.meta = serializeJSON(updateObj.meta);
}
// update meta // update meta
return await ncMeta.metaUpdate( return await ncMeta.metaUpdate(null, null, MetaTable.FORM_VIEW, updateObj, {
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, fk_view_id: formId,
} });
);
} }
async getColumns(ncMeta = Noco.ncMeta) { async getColumns(ncMeta = Noco.ncMeta) {

53
packages/nocodb/src/lib/models/FormViewColumn.ts

@ -55,27 +55,32 @@ export default class FormViewColumn implements FormColumnType {
} }
static async insert(column: Partial<FormViewColumn>, ncMeta = Noco.ncMeta) { static async insert(column: Partial<FormViewColumn>, ncMeta = Noco.ncMeta) {
const insertObj: Partial<FormViewColumn> = { const insertObj = extractProps(column, [
fk_view_id: column.fk_view_id, 'fk_view_id',
fk_column_id: column.fk_column_id, 'fk_column_id',
order: await ncMeta.metaGetNextOrder(MetaTable.FORM_VIEW_COLUMNS, { 'show',
fk_view_id: column.fk_view_id, 'project_id',
}), 'base_id',
show: column.show, 'label',
project_id: column.project_id, 'help',
base_id: column.base_id, 'description',
label: column.label, 'required',
help: column.help, 'meta',
description: column.description, ]);
required: column.required,
}; insertObj.order = await ncMeta.metaGetNextOrder(
MetaTable.FORM_VIEW_COLUMNS,
if (column.meta) { {
insertObj.meta = serializeJSON(column.meta); fk_view_id: insertObj.fk_view_id,
}
);
if (insertObj.meta) {
insertObj.meta = serializeJSON(insertObj.meta);
} }
if (!(column.project_id && column.base_id)) { if (!(insertObj.project_id && insertObj.base_id)) {
const viewRef = await View.get(column.fk_view_id, ncMeta); const viewRef = await View.get(insertObj.fk_view_id, ncMeta);
insertObj.project_id = viewRef.project_id; insertObj.project_id = viewRef.project_id;
insertObj.base_id = viewRef.base_id; insertObj.base_id = viewRef.base_id;
} }
@ -150,7 +155,7 @@ export default class FormViewColumn implements FormColumnType {
body: Partial<FormViewColumn>, body: Partial<FormViewColumn>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = extractProps(body, [ const updateObj = extractProps(body, [
'label', 'label',
'help', 'help',
'description', 'description',
@ -164,13 +169,13 @@ export default class FormViewColumn implements FormColumnType {
const key = `${CacheScope.FORM_VIEW_COLUMN}:${columnId}`; const key = `${CacheScope.FORM_VIEW_COLUMN}:${columnId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) { if (o) {
Object.assign(o, insertObj); Object.assign(o, updateObj);
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o);
} }
if (insertObj.meta) { if (updateObj.meta) {
insertObj.meta = serializeJSON(insertObj.meta); updateObj.meta = serializeJSON(updateObj.meta);
} }
// update meta // update meta
@ -178,7 +183,7 @@ export default class FormViewColumn implements FormColumnType {
null, null,
null, null,
MetaTable.FORM_VIEW_COLUMNS, MetaTable.FORM_VIEW_COLUMNS,
insertObj, updateObj,
columnId columnId
); );
} }

17
packages/nocodb/src/lib/models/FormulaColumn.ts

@ -14,17 +14,18 @@ export default class FormulaColumn {
} }
public static async insert( public static async insert(
data: Partial<FormulaColumn>, formulaColumn: Partial<FormulaColumn>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_FORMULA, { const insertObj = extractProps(formulaColumn, [
fk_column_id: data.fk_column_id, 'fk_column_id',
formula_raw: data.formula_raw, 'formula_raw',
formula: data.formula, 'formula',
error: data.error, '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) { public static async read(columnId: string, ncMeta = Noco.ncMeta) {
let column = let column =

63
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 { GalleryColumnType, GalleryType, UITypes } from 'nocodb-sdk';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class GalleryView implements GalleryType { export default class GalleryView implements GalleryType {
fk_view_id?: string; fk_view_id?: string;
@ -51,21 +52,23 @@ export default class GalleryView implements GalleryType {
.then((v) => v?.getModel(ncMeta)) .then((v) => v?.getModel(ncMeta))
.then((m) => m.getColumns(ncMeta)); .then((m) => m.getColumns(ncMeta));
const insertObj = { const insertObj = extractProps(view, [
project_id: view.project_id, 'project_id',
base_id: view.base_id, 'base_id',
fk_view_id: view.fk_view_id, 'fk_view_id',
fk_cover_image_col_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 || view?.fk_cover_image_col_id ||
columns?.find((c) => c.uidt === UITypes.Attachment)?.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,
};
if (!(view.project_id && view.base_id)) { if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.fk_view_id); const viewRef = await View.get(view.fk_view_id);
insertObj.project_id = viewRef.project_id; insertObj.project_id = viewRef.project_id;
@ -90,16 +93,19 @@ export default class GalleryView implements GalleryType {
) { ) {
// get existing cache // get existing cache
const key = `${CacheScope.GALLERY_VIEW}:${galleryId}`; 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) { if (o) {
o.next_enabled = body.next_enabled; o = { ...o, ...updateObj };
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;
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o);
} }
@ -108,16 +114,7 @@ export default class GalleryView implements GalleryType {
null, null,
null, null,
MetaTable.GALLERY_VIEW, MetaTable.GALLERY_VIEW,
{ updateObj,
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,
},
{ {
fk_view_id: galleryId, fk_view_id: galleryId,
} }

23
packages/nocodb/src/lib/models/GalleryViewColumn.ts

@ -2,6 +2,7 @@ import Noco from '../Noco';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class GalleryViewColumn { export default class GalleryViewColumn {
id: string; id: string;
@ -43,16 +44,20 @@ export default class GalleryViewColumn {
column: Partial<GalleryViewColumn>, column: Partial<GalleryViewColumn>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = { const insertObj = extractProps(column, [
fk_view_id: column.fk_view_id, 'fk_view_id',
fk_column_id: column.fk_column_id, 'fk_column_id',
order: await ncMeta.metaGetNextOrder(MetaTable.GALLERY_VIEW_COLUMNS, { 'show',
'project_id',
'base_id',
]);
insertObj.order = await ncMeta.metaGetNextOrder(
MetaTable.GALLERY_VIEW_COLUMNS,
{
fk_view_id: column.fk_view_id, 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)) { if (!(column.project_id && column.base_id)) {
const viewRef = await View.get(column.fk_view_id, ncMeta); const viewRef = await View.get(column.fk_view_id, ncMeta);

35
packages/nocodb/src/lib/models/GridView.ts

@ -3,6 +3,7 @@ import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import GridViewColumn from './GridViewColumn'; import GridViewColumn from './GridViewColumn';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class GridView { export default class GridView {
fk_view_id: string; fk_view_id: string;
@ -40,14 +41,15 @@ export default class GridView {
} }
static async insert(view: Partial<GridView>, ncMeta = Noco.ncMeta) { static async insert(view: Partial<GridView>, ncMeta = Noco.ncMeta) {
const insertObj = { const insertObj = extractProps(view, [
fk_view_id: view.fk_view_id, 'fk_view_id',
project_id: view.project_id, 'project_id',
base_id: view.base_id, 'base_id',
row_height: view.row_height, 'row_height',
}; ]);
if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.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.project_id = viewRef.project_id;
insertObj.base_id = viewRef.base_id; insertObj.base_id = viewRef.base_id;
} }
@ -69,23 +71,16 @@ export default class GridView {
) { ) {
// get existing cache // get existing cache
const key = `${CacheScope.GRID_VIEW}:${viewId}`; 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) { if (o) {
o.row_height = body.row_height; o = { ...o, ...updateObj };
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o);
} }
// update meta // update meta
return await ncMeta.metaUpdate( return await ncMeta.metaUpdate(null, null, MetaTable.GRID_VIEW, updateObj, {
null,
null,
MetaTable.GRID_VIEW,
{
row_height: body.row_height,
},
{
fk_view_id: viewId, fk_view_id: viewId,
} });
);
} }
} }

19
packages/nocodb/src/lib/models/GridViewColumn.ts

@ -67,18 +67,19 @@ export default class GridViewColumn implements GridColumnType {
} }
static async insert(column: Partial<GridViewColumn>, ncMeta = Noco.ncMeta) { static async insert(column: Partial<GridViewColumn>, ncMeta = Noco.ncMeta) {
const insertObj = { const insertObj = extractProps(column, [
fk_view_id: column.fk_view_id, 'fk_view_id',
fk_column_id: column.fk_column_id, 'fk_column_id',
order: 'show',
'project_id',
'base_id',
]);
insertObj.order =
column?.order ?? column?.order ??
(await ncMeta.metaGetNextOrder(MetaTable.GRID_VIEW_COLUMNS, { (await ncMeta.metaGetNextOrder(MetaTable.GRID_VIEW_COLUMNS, {
fk_view_id: column.fk_view_id, 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)) { if (!(column.project_id && column.base_id)) {
const viewRef = await View.get(column.fk_view_id, ncMeta); const viewRef = await View.get(column.fk_view_id, ncMeta);

120
packages/nocodb/src/lib/models/Hook.ts

@ -10,6 +10,7 @@ import Model from './Model';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import Filter from './Filter'; import Filter from './Filter';
import HookFilter from './HookFilter'; import HookFilter from './HookFilter';
import { extractProps } from '../meta/helpers/extractProps';
export default class Hook implements HookType { export default class Hook implements HookType {
id?: string; id?: string;
@ -18,7 +19,7 @@ export default class Hook implements HookType {
description?: string; description?: string;
env?: string; env?: string;
type?: string; type?: string;
event?: 'After' | 'Before'; event?: 'after' | 'before';
operation?: 'insert' | 'delete' | 'update'; operation?: 'insert' | 'delete' | 'update';
async?: boolean; async?: boolean;
payload?: string; payload?: string;
@ -121,32 +122,42 @@ export default class Hook implements HookType {
>, >,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = { const insertObj = extractProps(hook, [
fk_model_id: hook.fk_model_id, 'fk_model_id',
title: hook.title, 'title',
description: hook.description, 'description',
env: hook.env, 'env',
type: hook.type, 'type',
event: hook.event?.toLowerCase?.(), 'event',
operation: hook.operation?.toLowerCase?.(), 'operation',
async: hook.async, 'async',
payload: !!hook.payload, 'url',
url: hook.url, 'headers',
headers: hook.headers, 'notification',
condition: hook.condition, 'retries',
notification: 'retry_interval',
hook.notification && typeof hook.notification === 'object' 'timeout',
? JSON.stringify(hook.notification) 'active',
: hook.notification, 'project_id',
retries: hook.retries, 'base_id',
retry_interval: hook.retry_interval, 'created_at',
timeout: hook.timeout, 'updated_at',
active: hook.active, ]);
project_id: hook.project_id,
base_id: hook.base_id, if (insertObj.event) {
created_at: hook.created_at, insertObj.event = insertObj.event.toLowerCase() as 'after' | 'before';
updated_at: hook.updated_at, }
};
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)) { if (!(hook.project_id && hook.base_id)) {
const model = await Model.getByIdOrName({ id: hook.fk_model_id }, ncMeta); const model = await Model.getByIdOrName({ id: hook.fk_model_id }, ncMeta);
@ -175,27 +186,39 @@ export default class Hook implements HookType {
hook: Partial<Hook>, hook: Partial<Hook>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const updateObj = { const updateObj = extractProps(hook, [
title: hook.title, 'title',
description: hook.description, 'description',
env: hook.env, 'env',
type: hook.type, 'type',
event: hook.event?.toLowerCase?.(), 'event',
operation: hook.operation?.toLowerCase?.(), 'operation',
async: hook.async, 'async',
payload: !!hook.payload, 'payload',
url: hook.url, 'url',
headers: hook.headers, 'headers',
condition: !!hook.condition, 'condition',
notification: 'notification',
hook.notification && typeof hook.notification === 'object' 'retries',
? JSON.stringify(hook.notification) 'retry_interval',
: hook.notification, 'timeout',
retries: hook.retries, 'active',
retry_interval: hook.retry_interval, ]);
timeout: hook.timeout,
active: hook.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 // get existing cache
const key = `${CacheScope.HOOK}:${hookId}`; const key = `${CacheScope.HOOK}:${hookId}`;
@ -203,6 +226,7 @@ export default class Hook implements HookType {
if (o) { if (o) {
// update data // update data
o = { ...o, ...updateObj }; o = { ...o, ...updateObj };
// replace notification
o.notification = updateObj.notification; o.notification = updateObj.notification;
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o);

43
packages/nocodb/src/lib/models/HookFilter.ts

@ -10,6 +10,7 @@ import {
import View from './View'; import View from './View';
import { FilterType, UITypes } from 'nocodb-sdk'; import { FilterType, UITypes } from 'nocodb-sdk';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class Filter { export default class Filter {
id: string; id: string;
@ -48,20 +49,19 @@ export default class Filter {
filter: Partial<FilterType>, filter: Partial<FilterType>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = { const insertObj = extractProps(filter, [
id: filter.id, 'id',
fk_view_id: filter.fk_view_id, 'fk_view_id',
fk_column_id: filter.fk_column_id, 'fk_column_id',
comparison_op: filter.comparison_op, 'comparison_op',
value: filter.value, 'value',
fk_parent_id: filter.fk_parent_id, 'fk_parent_id',
'is_group',
is_group: filter.is_group, 'logical_op',
logical_op: filter.logical_op, 'project_id',
'base_id',
]);
project_id: filter.project_id,
base_id: filter.base_id,
};
if (!(filter.project_id && filter.base_id)) { if (!(filter.project_id && filter.base_id)) {
const model = await Column.get({ colId: filter.fk_column_id }, ncMeta); const model = await Column.get({ colId: filter.fk_column_id }, ncMeta);
insertObj.project_id = model.project_id; insertObj.project_id = model.project_id;
@ -138,15 +138,14 @@ export default class Filter {
} }
static async update(id, filter: Partial<Filter>, ncMeta = Noco.ncMeta) { static async update(id, filter: Partial<Filter>, ncMeta = Noco.ncMeta) {
const updateObj = { const updateObj = extractProps(filter, [
fk_column_id: filter.fk_column_id, 'fk_column_id',
comparison_op: filter.comparison_op, 'comparison_op',
value: filter.value, 'value',
fk_parent_id: filter.fk_parent_id, 'fk_parent_id',
'is_group',
is_group: filter.is_group, 'logical_op',
logical_op: filter.logical_op, ]);
};
// get existing cache // get existing cache
const key = `${CacheScope.FILTER_EXP}:${id}`; const key = `${CacheScope.FILTER_EXP}:${id}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);

38
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 { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class KanbanView implements KanbanType { export default class KanbanView implements KanbanType {
fk_view_id: string; fk_view_id: string;
@ -63,16 +64,17 @@ export default class KanbanView implements KanbanType {
.then((v) => v?.getModel(ncMeta)) .then((v) => v?.getModel(ncMeta))
.then((m) => m.getColumns(ncMeta)); .then((m) => m.getColumns(ncMeta));
const insertObj = { const insertObj = extractProps(view, [
project_id: view.project_id, 'project_id',
base_id: view.base_id, 'base_id',
fk_view_id: view.fk_view_id, 'fk_view_id',
fk_grp_col_id: view.fk_grp_col_id, 'fk_grp_col_id',
fk_cover_image_col_id: 'meta',
]);
insertObj.fk_cover_image_col_id =
view?.fk_cover_image_col_id || view?.fk_cover_image_col_id ||
columns?.find((c) => c.uidt === UITypes.Attachment)?.id, columns?.find((c) => c.uidt === UITypes.Attachment)?.id;
meta: view.meta,
};
if (!(view.project_id && view.base_id)) { if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.fk_view_id); const viewRef = await View.get(view.fk_view_id);
@ -99,13 +101,17 @@ export default class KanbanView implements KanbanType {
// get existing cache // get existing cache
const key = `${CacheScope.KANBAN_VIEW}:${kanbanId}`; const key = `${CacheScope.KANBAN_VIEW}:${kanbanId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = {
...body, const updateObj = extractProps(body, [
meta: 'title',
typeof body.meta === 'string' 'fk_cover_image_col_id',
? body.meta 'meta',
: JSON.stringify(body.meta ?? {}), ]);
};
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) { if (o) {
o = { ...o, ...updateObj }; o = { ...o, ...updateObj };
// set cache // set cache

23
packages/nocodb/src/lib/models/KanbanViewColumn.ts

@ -2,6 +2,7 @@ import Noco from '../Noco';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View'; import View from './View';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class KanbanViewColumn { export default class KanbanViewColumn {
id: string; id: string;
@ -40,16 +41,20 @@ export default class KanbanViewColumn {
return view && new KanbanViewColumn(view); return view && new KanbanViewColumn(view);
} }
static async insert(column: Partial<KanbanViewColumn>, ncMeta = Noco.ncMeta) { static async insert(column: Partial<KanbanViewColumn>, ncMeta = Noco.ncMeta) {
const insertObj = { const insertObj = extractProps(column, [
fk_view_id: column.fk_view_id, 'fk_view_id',
fk_column_id: column.fk_column_id, 'fk_column_id',
order: await ncMeta.metaGetNextOrder(MetaTable.KANBAN_VIEW_COLUMNS, { 'show',
'project_id',
'base_id',
]);
insertObj.order = await ncMeta.metaGetNextOrder(
MetaTable.KANBAN_VIEW_COLUMNS,
{
fk_view_id: column.fk_view_id, 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)) { if (!(column.project_id && column.base_id)) {
const viewRef = await View.get(column.fk_view_id, ncMeta); const viewRef = await View.get(column.fk_view_id, ncMeta);

38
packages/nocodb/src/lib/models/LinkToAnotherRecordColumn.ts

@ -1,9 +1,9 @@
import Noco from '../Noco'; import Noco from '../Noco';
import Column from './Column'; import Column from './Column';
import Model from './Model'; import Model from './Model';
// import NocoCache from '../cache/NocoCache';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class LinkToAnotherRecordColumn { export default class LinkToAnotherRecordColumn {
fk_column_id?: string; fk_column_id?: string;
@ -89,27 +89,21 @@ export default class LinkToAnotherRecordColumn {
data: Partial<LinkToAnotherRecordColumn>, data: Partial<LinkToAnotherRecordColumn>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_RELATIONS, { const insertObj = extractProps(data, [
fk_column_id: data.fk_column_id, 'fk_column_id',
'type',
// ref_db_alias 'fk_child_column_id',
type: data.type, 'fk_parent_column_id',
// db_type: 'fk_mm_model_id',
'fk_mm_child_column_id',
fk_child_column_id: data.fk_child_column_id, 'fk_mm_parent_column_id',
fk_parent_column_id: data.fk_parent_column_id, 'ur',
'dr',
fk_mm_model_id: data.fk_mm_model_id, 'fk_index_name',
fk_mm_child_column_id: data.fk_mm_child_column_id, 'fk_related_model_id',
fk_mm_parent_column_id: data.fk_mm_parent_column_id, 'virtual',
]);
ur: data.ur, await ncMeta.metaInsert2(null, null, MetaTable.COL_RELATIONS, insertObj);
dr: data.dr,
fk_index_name: data.fk_index_name,
fk_related_model_id: data.fk_related_model_id,
virtual: data.virtual,
});
return this.read(data.fk_column_id, ncMeta); return this.read(data.fk_column_id, ncMeta);
} }

14
packages/nocodb/src/lib/models/LookupColumn.ts

@ -1,8 +1,8 @@
import Noco from '../Noco'; import Noco from '../Noco';
// import NocoCache from '../cache/NocoCache';
import Column from './Column'; import Column from './Column';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class LookupColumn { export default class LookupColumn {
fk_relation_column_id: string; fk_relation_column_id: string;
@ -29,11 +29,13 @@ export default class LookupColumn {
data: Partial<LookupColumn>, data: Partial<LookupColumn>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_LOOKUP, { const insertObj = extractProps(data, [
fk_column_id: data.fk_column_id, 'fk_column_id',
fk_relation_column_id: data.fk_relation_column_id, 'fk_relation_column_id',
fk_lookup_column_id: data.fk_lookup_column_id, 'fk_lookup_column_id',
}); ]);
await ncMeta.metaInsert2(null, null, MetaTable.COL_LOOKUP, insertObj);
await NocoCache.appendToList( await NocoCache.appendToList(
CacheScope.COL_LOOKUP, CacheScope.COL_LOOKUP,

52
packages/nocodb/src/lib/models/Model.ts

@ -22,6 +22,7 @@ import View from './View';
import { NcError } from '../meta/helpers/catchError'; import { NcError } from '../meta/helpers/catchError';
import Audit from './Audit'; import Audit from './Audit';
import { sanitize } from '../db/sql-data-mapper/lib/sql/helpers/sanitize'; import { sanitize } from '../db/sql-data-mapper/lib/sql/helpers/sanitize';
import { extractProps } from '../meta/helpers/extractProps';
export default class Model implements TableType { export default class Model implements TableType {
copy_enabled: boolean; copy_enabled: boolean;
@ -103,26 +104,39 @@ export default class Model implements TableType {
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const { id } = await ncMeta.metaInsert2( const insertObj = extractProps(model, [
projectId, 'table_name',
baseId, 'title',
MetaTable.MODELS, 'mm',
'order',
'type',
'created_at',
'updated_at',
'id',
]);
insertObj.mm = !!insertObj.mm;
if (!insertObj.order) {
insertObj.order = await ncMeta.metaGetNextOrder(
MetaTable.FORM_VIEW_COLUMNS,
{ {
table_name: model.table_name,
title: model.title,
mm: !!model.mm,
order:
model.order ||
(await ncMeta.metaGetNextOrder(MetaTable.FORM_VIEW_COLUMNS, {
project_id: projectId, project_id: projectId,
base_id: baseId, base_id: baseId,
})),
type: model.type || ModelTypes.TABLE,
created_at: model.created_at,
updated_at: model.updated_at,
id: model.id,
} }
); );
}
if (!insertObj.type) {
insertObj.type = ModelTypes.TABLE;
}
const { id } = await ncMeta.metaInsert2(
projectId,
baseId,
MetaTable.MODELS,
insertObj
);
await NocoCache.appendToList( await NocoCache.appendToList(
CacheScope.MODEL, CacheScope.MODEL,
@ -561,14 +575,14 @@ export default class Model implements TableType {
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const model = await this.getWithInfo({ id: tableId }); const model = await this.getWithInfo({ id: tableId });
const currentPvCol = model.displayValue;
const newPvCol = model.columns.find((c) => c.id === columnId); const newPvCol = model.columns.find((c) => c.id === columnId);
if (!newPvCol) NcError.badRequest('Column not found'); 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 // get existing cache
const key = `${CacheScope.COLUMN}:${currentPvCol.id}`; const key = `${CacheScope.COLUMN}:${col.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) { if (o) {
o.pv = false; o.pv = false;
@ -583,7 +597,7 @@ export default class Model implements TableType {
{ {
pv: false, pv: false,
}, },
currentPvCol.id col.id
); );
} }

21
packages/nocodb/src/lib/models/ModelRoleVisibility.ts

@ -8,6 +8,7 @@ import {
} from '../utils/globals'; } from '../utils/globals';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import View from './View'; import View from './View';
import { extractProps } from '../meta/helpers/extractProps';
export default class ModelRoleVisibility implements ModelRoleVisibilityType { export default class ModelRoleVisibility implements ModelRoleVisibilityType {
id?: string; id?: string;
@ -134,17 +135,17 @@ export default class ModelRoleVisibility implements ModelRoleVisibilityType {
>, >,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = { const insertObj = extractProps(body, [
role: body.role, 'role',
disabled: body.disabled, 'disabled',
fk_view_id: body.fk_view_id, 'fk_view_id',
project_id: body.project_id, 'project_id',
base_id: body.base_id, 'base_id',
created_at: body.created_at, 'created_at',
updated_at: body.updated_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); const view = await View.get(body.fk_view_id, ncMeta);
insertObj.project_id = view.project_id; insertObj.project_id = view.project_id;
insertObj.base_id = view.base_id; insertObj.base_id = view.base_id;

14
packages/nocodb/src/lib/models/Plugin.ts

@ -2,6 +2,7 @@ import { PluginType } from 'nocodb-sdk';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import Noco from '../Noco'; import Noco from '../Noco';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class Plugin implements PluginType { export default class Plugin implements PluginType {
id?: string; id?: string;
@ -56,13 +57,12 @@ export default class Plugin implements PluginType {
} }
public static async update(pluginId: string, plugin: Partial<PluginType>) { public static async update(pluginId: string, plugin: Partial<PluginType>) {
const updateObj = { const updateObj = extractProps(plugin, ['input', 'active']);
input:
plugin.input && typeof plugin.input === 'object' if (updateObj.input && typeof updateObj.input === 'object') {
? JSON.stringify(plugin.input) updateObj.input = JSON.stringify(updateObj.input);
: plugin.input, }
active: plugin.active,
};
// get existing cache // get existing cache
const key = `${CacheScope.PLUGIN}:${pluginId}`; const key = `${CacheScope.PLUGIN}:${pluginId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);

24
packages/nocodb/src/lib/models/Project.ts

@ -36,25 +36,27 @@ export default class Project implements ProjectType {
} }
public static async createProject( public static async createProject(
projectBody: ProjectType & { project: ProjectType & {
created_at?; created_at?;
updated_at?; updated_at?;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
): Promise<Project> { ): Promise<Project> {
const insertObj = extractProps(project, [
'id',
'title',
'prefix',
'description',
'is_meta',
'created_at',
'updated_at',
]);
const { id: projectId } = await ncMeta.metaInsert2( const { id: projectId } = await ncMeta.metaInsert2(
null, null,
null, null,
MetaTable.PROJECT, MetaTable.PROJECT,
{ insertObj
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,
}
); );
await NocoCache.appendToList( await NocoCache.appendToList(
@ -63,7 +65,7 @@ export default class Project implements ProjectType {
`${CacheScope.PROJECT}:${projectId}` `${CacheScope.PROJECT}:${projectId}`
); );
for (const base of projectBody.bases) { for (const base of project.bases) {
await Base.createBase( await Base.createBase(
{ {
type: base.config?.client, type: base.config?.client,

17
packages/nocodb/src/lib/models/ProjectUser.ts

@ -8,6 +8,7 @@ import {
import Noco from '../Noco'; import Noco from '../Noco';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import User from './User'; import User from './User';
import { extractProps } from '../meta/helpers/extractProps';
export default class ProjectUser { export default class ProjectUser {
project_id: string; project_id: string;
@ -22,17 +23,19 @@ export default class ProjectUser {
projectUser: Partial<ProjectUser & { created_at?: any; updated_at?: any }>, projectUser: Partial<ProjectUser & { created_at?: any; updated_at?: any }>,
ncMeta = Noco.ncMeta 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( const { project_id, fk_user_id } = await ncMeta.metaInsert2(
null, null,
null, null,
MetaTable.PROJECT_USERS, MetaTable.PROJECT_USERS,
{ insertObj,
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,
},
true true
); );

14
packages/nocodb/src/lib/models/QrCodeColumn.ts

@ -12,15 +12,17 @@ export default class QrCodeColumn {
} }
public static async insert( public static async insert(
data: Partial<QrCodeColumn>, qrCode: Partial<QrCodeColumn>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_QRCODE, { const insertObj = extractProps(qrCode, [
fk_column_id: data.fk_column_id, 'fk_column_id',
fk_qr_value_column_id: data.fk_qr_value_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) { public static async read(columnId: string, ncMeta = Noco.ncMeta) {
let column = let column =

14
packages/nocodb/src/lib/models/RollupColumn.ts

@ -2,6 +2,7 @@ import Noco from '../Noco';
import Column from './Column'; import Column from './Column';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class RollupColumn { export default class RollupColumn {
fk_column_id; fk_column_id;
@ -20,12 +21,13 @@ export default class RollupColumn {
data: Partial<RollupColumn>, data: Partial<RollupColumn>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_ROLLUP, { const insertObj = extractProps(data, [
fk_column_id: data.fk_column_id, 'fk_column_id',
fk_relation_column_id: data.fk_relation_column_id, 'fk_relation_column_id',
fk_rollup_column_id: data.fk_rollup_column_id, 'fk_rollup_column_id',
rollup_function: data.rollup_function, 'rollup_function',
}); ]);
await ncMeta.metaInsert2(null, null, MetaTable.COL_ROLLUP, insertObj);
await NocoCache.appendToList( await NocoCache.appendToList(
CacheScope.COL_ROLLUP, CacheScope.COL_ROLLUP,

11
packages/nocodb/src/lib/models/SelectOption.ts

@ -1,6 +1,7 @@
import Noco from '../Noco'; import Noco from '../Noco';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import { extractProps } from '../meta/helpers/extractProps';
export default class SelectOption { export default class SelectOption {
title: string; title: string;
@ -16,11 +17,19 @@ export default class SelectOption {
data: Partial<SelectOption>, data: Partial<SelectOption>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = extractProps(data, [
'id',
'title',
'fk_column_id',
'color',
'order',
]);
const { id } = await ncMeta.metaInsert2( const { id } = await ncMeta.metaInsert2(
null, null,
null, null,
MetaTable.COL_SELECT_OPTIONS, MetaTable.COL_SELECT_OPTIONS,
data insertObj
); );
await NocoCache.appendToList( await NocoCache.appendToList(

24
packages/nocodb/src/lib/models/Sort.ts

@ -9,6 +9,7 @@ import {
} from '../utils/globals'; } from '../utils/globals';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { SortType } from 'nocodb-sdk'; import { SortType } from 'nocodb-sdk';
import { extractProps } from '../meta/helpers/extractProps';
export default class Sort { export default class Sort {
id: string; id: string;
@ -35,11 +36,20 @@ export default class Sort {
} }
public static async insert( public static async insert(
sortObj: Partial<Sort> & { push_to_top?: boolean }, sortObj: Partial<Sort> & { push_to_top?: boolean; order?: number },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = extractProps(sortObj, [
'id',
'fk_view_id',
'fk_column_id',
'direction',
'project_id',
'base_id',
]);
// todo: implement a generic function // todo: implement a generic function
const order = sortObj.push_to_top insertObj.order = sortObj.push_to_top
? 1 ? 1
: (+( : (+(
await ncMeta await ncMeta
@ -50,16 +60,6 @@ export default class Sort {
}) })
.first() .first()
)?.order || 0) + 1; )?.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)) { if (!(sortObj.project_id && sortObj.base_id)) {
const model = await Column.get({ colId: sortObj.fk_column_id }, ncMeta); const model = await Column.get({ colId: sortObj.fk_column_id }, ncMeta);
insertObj.project_id = model.project_id; insertObj.project_id = model.project_id;

15
packages/nocodb/src/lib/models/SyncLogs.ts

@ -1,5 +1,6 @@
import Noco from '../Noco'; import Noco from '../Noco';
import { MetaTable } from '../utils/globals'; import { MetaTable } from '../utils/globals';
import { extractProps } from '../meta/helpers/extractProps';
export default class SyncLogs { export default class SyncLogs {
id?: string; id?: string;
@ -34,13 +35,13 @@ export default class SyncLogs {
>, >,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = { const insertObj = extractProps(syncLog, [
project_id: syncLog?.project_id, 'project_id',
fk_sync_source_id: syncLog?.fk_sync_source_id, 'fk_sync_source_id',
time_taken: syncLog?.time_taken, 'time_taken',
status: syncLog?.status, 'status',
status_details: syncLog?.status_details, 'status_details',
}; ]);
const { id } = await ncMeta.metaInsert2( const { id } = await ncMeta.metaInsert2(
null, null,

18
packages/nocodb/src/lib/models/SyncSource.ts

@ -73,15 +73,15 @@ export default class SyncSource {
>, >,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = { const insertObj = extractProps(syncSource, [
id: syncSource?.id, 'id',
title: syncSource?.title, 'title',
type: syncSource?.type, 'type',
details: syncSource?.details, 'details',
project_id: syncSource?.project_id, 'project_id',
base_id: syncSource?.base_id, 'base_id',
fk_user_id: syncSource?.fk_user_id, 'fk_user_id',
}; ]);
if (insertObj.details && typeof insertObj.details === 'object') { if (insertObj.details && typeof insertObj.details === 'object') {
insertObj.details = JSON.stringify(insertObj.details); insertObj.details = JSON.stringify(insertObj.details);

34
packages/nocodb/src/lib/models/View.ts

@ -244,25 +244,29 @@ export default class View implements ViewType {
}, },
ncMeta = Noco.ncMeta 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 // get order value
const order = await ncMeta.metaGetNextOrder(MetaTable.VIEWS, { insertObj.order = await ncMeta.metaGetNextOrder(MetaTable.VIEWS, {
fk_model_id: view.fk_model_id, fk_model_id: view.fk_model_id,
}); });
const insertObj = { insertObj.show = true;
id: view.id,
title: view.title, if (!insertObj.meta) {
show: true, insertObj.meta = {};
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.meta = stringifyMetaProp(insertObj); insertObj.meta = stringifyMetaProp(insertObj);

2
packages/nocodb/src/lib/utils/common/BaseApiBuilder.ts

@ -187,7 +187,7 @@ export default abstract class BaseApiBuilder<T extends Noco>
return this.connectionConfig?.meta?.dbAlias; return this.connectionConfig?.meta?.dbAlias;
} }
public async getSqlClient(): Promise<any> { public async getSqlClient() {
return NcConnectionMgr.getSqlClient({ return NcConnectionMgr.getSqlClient({
dbAlias: this.dbAlias, dbAlias: this.dbAlias,
env: this.config.env, env: this.config.env,

2
packages/nocodb/src/lib/utils/common/NcConnectionMgr.ts

@ -149,7 +149,7 @@ export default class NcConnectionMgr {
env: string; env: string;
config: NcConfig; config: NcConfig;
projectId: string; projectId: string;
}): Promise<any> { }) {
const knex = this.get({ const knex = this.get({
dbAlias, dbAlias,
env, env,

2
packages/nocodb/src/lib/utils/common/NcConnectionMgrv2.ts

@ -149,7 +149,7 @@ export default class NcConnectionMgrv2 {
// return config?.envs?.[env]?.db?.find(db => db?.meta?.dbAlias === dbAlias); // return config?.envs?.[env]?.db?.find(db => db?.meta?.dbAlias === dbAlias);
// } // }
public static async getSqlClient(base: Base, _knex = null): Promise<any> { public static async getSqlClient(base: Base, _knex = null) {
const knex = _knex || this.get(base); const knex = _knex || this.get(base);
return SqlClientFactory.create({ return SqlClientFactory.create({
knex, knex,

2
packages/nocodb/src/lib/version-upgrader/NcUpgrader.ts

@ -43,8 +43,8 @@ export default class NcUpgrader {
{ name: '0100002', handler: ncFilterUpgrader }, { name: '0100002', handler: ncFilterUpgrader },
{ name: '0101002', handler: ncAttachmentUpgrader }, { name: '0101002', handler: ncAttachmentUpgrader },
{ name: '0104002', handler: ncAttachmentUpgrader_0104002 }, { name: '0104002', handler: ncAttachmentUpgrader_0104002 },
{ name: '0104003', handler: ncStickyColumnUpgrader },
{ name: '0104004', handler: ncFilterUpgrader_0104004 }, { name: '0104004', handler: ncFilterUpgrader_0104004 },
{ name: '0105002', handler: ncStickyColumnUpgrader },
]; ];
if (!(await ctx.ncMeta.knexConnection?.schema?.hasTable?.('nc_store'))) { if (!(await ctx.ncMeta.knexConnection?.schema?.hasTable?.('nc_store'))) {
return; return;

2
packages/nocodb/src/lib/version-upgrader/ncProjectUpgraderV2_0090000.ts

@ -1231,7 +1231,7 @@ async function migrateWebhooks(ctx: MigrateCtxV1, ncMeta: any) {
env: string; env: string;
tn: string; tn: string;
type: string; type: string;
event: 'After' | 'Before'; event: 'after' | 'before';
operation: 'delete' | 'update' | 'insert'; operation: 'delete' | 'update' | 'insert';
async: boolean; async: boolean;
payload: string; payload: string;

44
packages/nocodb/src/lib/version-upgrader/ncStickyColumnUpgrader.ts

@ -38,6 +38,50 @@ export default async function ({ ncMeta }: NcUpgraderCtx) {
view_columns_meta.push(col_meta); 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); const primary_value_column_meta = view_columns_meta.find((col) => col.pv);
if (primary_value_column_meta) { if (primary_value_column_meta) {

4
scripts/sdk/swagger.json

@ -9175,8 +9175,8 @@
"event": { "event": {
"type": "string", "type": "string",
"enum": [ "enum": [
"After", "after",
"Before" "before"
] ]
}, },
"operation": { "operation": {

Loading…
Cancel
Save