diff --git a/packages/nocodb/src/lib/meta/api/columnApis.ts b/packages/nocodb/src/lib/meta/api/columnApis.ts index ea3aa7c17b..cd5c7612a2 100644 --- a/packages/nocodb/src/lib/meta/api/columnApis.ts +++ b/packages/nocodb/src/lib/meta/api/columnApis.ts @@ -10,7 +10,7 @@ import { customAlphabet } from 'nanoid'; import LinkToAnotherRecordColumn from '../../models/LinkToAnotherRecordColumn'; import { getUniqueColumnAliasName, - getUniqueColumnName + getUniqueColumnName, } from '../helpers/getUniqueName'; import { AuditOperationSubTypes, @@ -21,7 +21,7 @@ import { substituteColumnAliasWithIdInFormula, substituteColumnIdWithAliasInFormula, TableType, - UITypes + UITypes, } from 'nocodb-sdk'; import Audit from '../../models/Audit'; import SqlMgrv2 from '../../db/sql-mgr/v2/SqlMgrv2'; @@ -41,7 +41,7 @@ const randomID = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 10); export enum Altered { NEW_COLUMN = 1, DELETE_COLUMN = 4, - UPDATE_COLUMN = 8 + UPDATE_COLUMN = 8, } async function createHmAndBtColumn( @@ -72,7 +72,7 @@ async function createHmAndBtColumn( fk_parent_column_id: parent.primaryKey.id, fk_related_model_id: parent.id, virtual, - system: isSystemCol + system: isSystemCol, }); } // save hm column @@ -90,14 +90,14 @@ async function createHmAndBtColumn( fk_parent_column_id: parent.primaryKey.id, fk_related_model_id: child.id, virtual, - system: isSystemCol + system: isSystemCol, }); } } export async function columnAdd(req: Request, res: Response) { const table = await Model.getWithInfo({ - id: req.params.tableId + id: req.params.tableId, }); const base = await Base.get(table.base_id); const project = await base.getProject(); @@ -106,7 +106,7 @@ export async function columnAdd(req: Request, res: Response) { !isVirtualCol(req.body) && !(await Column.checkTitleAvailable({ column_name: req.body.column_name, - fk_model_id: req.params.tableId + fk_model_id: req.params.tableId, })) ) { NcError.badRequest('Duplicate column name'); @@ -114,7 +114,7 @@ export async function columnAdd(req: Request, res: Response) { if ( !(await Column.checkAliasAvailable({ title: req.body.title || req.body.column_name, - fk_model_id: req.params.tableId + fk_model_id: req.params.tableId, })) ) { NcError.badRequest('Duplicate column alias'); @@ -129,14 +129,14 @@ export async function columnAdd(req: Request, res: Response) { 'title', 'fk_relation_column_id', 'fk_rollup_column_id', - 'rollup_function' + 'rollup_function', ], req.body ); const relation = await ( await Column.get({ - colId: req.body.fk_relation_column_id + colId: req.body.fk_relation_column_id, }) ).getColOptions(); @@ -148,13 +148,13 @@ export async function columnAdd(req: Request, res: Response) { switch (relation.type) { case 'hm': relatedColumn = await Column.get({ - colId: relation.fk_child_column_id + colId: relation.fk_child_column_id, }); break; case 'mm': case 'bt': relatedColumn = await Column.get({ - colId: relation.fk_parent_column_id + colId: relation.fk_parent_column_id, }); break; } @@ -162,14 +162,14 @@ export async function columnAdd(req: Request, res: Response) { const relatedTable = await relatedColumn.getModel(); if ( !(await relatedTable.getColumns()).find( - c => c.id === req.body.fk_rollup_column_id + (c) => c.id === req.body.fk_rollup_column_id ) ) throw new Error('Rollup column not found in related table'); await Column.insert({ ...colBody, - fk_model_id: table.id + fk_model_id: table.id, }); } break; @@ -182,7 +182,7 @@ export async function columnAdd(req: Request, res: Response) { const relation = await ( await Column.get({ - colId: req.body.fk_relation_column_id + colId: req.body.fk_relation_column_id, }) ).getColOptions(); @@ -194,13 +194,13 @@ export async function columnAdd(req: Request, res: Response) { switch (relation.type) { case 'hm': relatedColumn = await Column.get({ - colId: relation.fk_child_column_id + colId: relation.fk_child_column_id, }); break; case 'mm': case 'bt': relatedColumn = await Column.get({ - colId: relation.fk_parent_column_id + colId: relation.fk_parent_column_id, }); break; } @@ -208,14 +208,14 @@ export async function columnAdd(req: Request, res: Response) { const relatedTable = await relatedColumn.getModel(); if ( !(await relatedTable.getColumns()).find( - c => c.id === req.body.fk_lookup_column_id + (c) => c.id === req.body.fk_lookup_column_id ) ) throw new Error('Lookup column not found in related table'); await Column.insert({ ...colBody, - fk_model_id: table.id + fk_model_id: table.id, }); } break; @@ -231,7 +231,7 @@ export async function columnAdd(req: Request, res: Response) { let childColumn: Column; const sqlMgr = await ProjectMgrv2.getSqlMgr({ - id: base.project_id + id: base.project_id, }); if (req.body.type === 'hm' || req.body.type === 'bt') { // populate fk column name @@ -255,22 +255,22 @@ export async function columnAdd(req: Request, res: Response) { dtxp: parent.primaryKey.dtxp, dtxs: parent.primaryKey.dtxs, un: parent.primaryKey.un, - altered: Altered.NEW_COLUMN + altered: Altered.NEW_COLUMN, }; const tableUpdateBody = { ...child, tn: child.table_name, - originalColumns: child.columns.map(c => ({ + originalColumns: child.columns.map((c) => ({ ...c, - cn: c.column_name + cn: c.column_name, })), columns: [ - ...child.columns.map(c => ({ + ...child.columns.map((c) => ({ ...c, - cn: c.column_name + cn: c.column_name, })), - newColumn - ] + newColumn, + ], }; await sqlMgr.sqlOpPlus(base, 'tableUpdate', tableUpdateBody); @@ -278,7 +278,7 @@ export async function columnAdd(req: Request, res: Response) { const { id } = await Column.insert({ ...newColumn, uidt: UITypes.ForeignKey, - fk_model_id: child.id + fk_model_id: child.id, }); childColumn = await Column.get({ colId: id }); @@ -293,7 +293,7 @@ export async function columnAdd(req: Request, res: Response) { onDelete: 'NO ACTION', onUpdate: 'NO ACTION', type: 'real', - parentColumn: parent.primaryKey.column_name + parentColumn: parent.primaryKey.column_name, }); } @@ -303,10 +303,10 @@ export async function columnAdd(req: Request, res: Response) { await createColumnIndex({ column: new Column({ ...newColumn, - fk_model_id: child.id + fk_model_id: child.id, }), base, - sqlMgr + sqlMgr, }); } } @@ -344,7 +344,7 @@ export async function columnAdd(req: Request, res: Response) { dtxs: childPK.dtxs, un: childPK.un, altered: 1, - uidt: UITypes.ForeignKey + uidt: UITypes.ForeignKey, }, { cn: parentCn, @@ -359,14 +359,14 @@ export async function columnAdd(req: Request, res: Response) { dtxs: parentPK.dtxs, un: parentPK.un, altered: 1, - uidt: UITypes.ForeignKey + uidt: UITypes.ForeignKey, } ); await sqlMgr.sqlOpPlus(base, 'tableCreate', { tn: aTn, _tn: aTnAlias, - columns: associateTableCols + columns: associateTableCols, }); const assocModel = await Model.insert(project.id, base.id, { @@ -374,7 +374,7 @@ export async function columnAdd(req: Request, res: Response) { title: aTnAlias, // todo: sanitize mm: true, - columns: associateTableCols + columns: associateTableCols, }); if (!req.body.virtual) { @@ -384,7 +384,7 @@ export async function columnAdd(req: Request, res: Response) { childColumn: parentCn, parentTable: parent.table_name, parentColumn: parentPK.column_name, - type: 'real' + type: 'real', }; const rel2Args = { ...req.body, @@ -392,17 +392,17 @@ export async function columnAdd(req: Request, res: Response) { childColumn: childCn, parentTable: child.table_name, parentColumn: childPK.column_name, - type: 'real' + type: 'real', }; await sqlMgr.sqlOpPlus(base, 'relationCreate', rel1Args); await sqlMgr.sqlOpPlus(base, 'relationCreate', rel2Args); } const parentCol = (await assocModel.getColumns())?.find( - c => c.column_name === parentCn + (c) => c.column_name === parentCn ); const childCol = (await assocModel.getColumns())?.find( - c => c.column_name === childCn + (c) => c.column_name === childCn ); await createHmAndBtColumn( @@ -442,7 +442,7 @@ export async function columnAdd(req: Request, res: Response) { fk_mm_model_id: assocModel.id, fk_mm_child_column_id: childCol.id, fk_mm_parent_column_id: parentCol.id, - fk_related_model_id: parent.id + fk_related_model_id: parent.id, }); await Column.insert({ title: getUniqueColumnAliasName( @@ -461,7 +461,7 @@ export async function columnAdd(req: Request, res: Response) { fk_mm_model_id: assocModel.id, fk_mm_child_column_id: parentCol.id, fk_mm_parent_column_id: childCol.id, - fk_related_model_id: child.id + fk_related_model_id: child.id, }); // todo: create index for virtual relations as well @@ -470,18 +470,18 @@ export async function columnAdd(req: Request, res: Response) { await createColumnIndex({ column: new Column({ ...associateTableCols[0], - fk_model_id: assocModel.id + fk_model_id: assocModel.id, }), base, - sqlMgr + sqlMgr, }); await createColumnIndex({ column: new Column({ ...associateTableCols[1], - fk_model_id: assocModel.id + fk_model_id: assocModel.id, }), base, - sqlMgr + sqlMgr, }); } } @@ -496,7 +496,7 @@ export async function columnAdd(req: Request, res: Response) { ); await Column.insert({ ...colBody, - fk_model_id: table.id + fk_model_id: table.id, }); break; @@ -506,37 +506,42 @@ export async function columnAdd(req: Request, res: Response) { if (colBody.uidt === UITypes.Duration) { colBody.dtxp = '20'; // by default, colBody.dtxs is 2 - // Duration column needs more that that + // Duration column needs more than that colBody.dtxs = '4'; + } else if (colBody.uidt === UITypes.Percent) { + colBody.dtxp = '20'; + colBody.dtxs = '10'; } const tableUpdateBody = { ...table, tn: table.table_name, - originalColumns: table.columns.map(c => ({ + originalColumns: table.columns.map((c) => ({ ...c, - cn: c.column_name + cn: c.column_name, })), columns: [ - ...table.columns.map(c => ({ ...c, cn: c.column_name })), + ...table.columns.map((c) => ({ ...c, cn: c.column_name })), { ...colBody, cn: colBody.column_name, - altered: Altered.NEW_COLUMN - } - ] + altered: Altered.NEW_COLUMN, + }, + ], }; const sqlClient = NcConnectionMgrv2.getSqlClient(base); const sqlMgr = await ProjectMgrv2.getSqlMgr({ id: base.project_id }); await sqlMgr.sqlOpPlus(base, 'tableUpdate', tableUpdateBody); - const columns: Array & { - cn: string; - system?: boolean; - }> = (await sqlClient.columnList({ tn: table.table_name }))?.data?.list; + const columns: Array< + Omit & { + cn: string; + system?: boolean; + } + > = (await sqlClient.columnList({ tn: table.table_name }))?.data?.list; const insertedColumnMeta = - columns.find(c => c.cn === colBody.column_name) || ({} as any); + columns.find((c) => c.cn === colBody.column_name) || ({} as any); if ( colBody.uidt === UITypes.SingleSelect || @@ -553,7 +558,7 @@ export async function columnAdd(req: Request, res: Response) { ) ? colBody.dtxp : insertedColumnMeta.dtxp, - fk_model_id: table.id + fk_model_id: table.id, }); } break; @@ -567,7 +572,7 @@ export async function columnAdd(req: Request, res: Response) { op_sub_type: AuditOperationSubTypes.CREATED, user: (req as any)?.user?.email, description: `created column ${colBody.column_name} with alias ${colBody.title} from table ${table.table_name}`, - ip: (req as any).clientIp + ip: (req as any).clientIp, }).then(() => {}); Tele.emit('evt', { evt_type: 'column:created' }); @@ -584,7 +589,7 @@ export async function columnUpdate(req: Request, res: Response) { const column = await Column.get({ colId: req.params.columnId }); const table = await Model.getWithInfo({ - id: column.fk_model_id + id: column.fk_model_id, }); const base = await Base.get(table.base_id); @@ -593,7 +598,7 @@ export async function columnUpdate(req: Request, res: Response) { !(await Column.checkTitleAvailable({ column_name: req.body.column_name, fk_model_id: column.fk_model_id, - exclude_id: req.params.columnId + exclude_id: req.params.columnId, })) ) { NcError.badRequest('Duplicate column name'); @@ -602,7 +607,7 @@ export async function columnUpdate(req: Request, res: Response) { !(await Column.checkAliasAvailable({ title: req.body.title, fk_model_id: column.fk_model_id, - exclude_id: req.params.columnId + exclude_id: req.params.columnId, })) ) { NcError.badRequest('Duplicate column alias'); @@ -615,7 +620,7 @@ export async function columnUpdate(req: Request, res: Response) { UITypes.Rollup, UITypes.LinkToAnotherRecord, UITypes.Formula, - UITypes.ForeignKey + UITypes.ForeignKey, ].includes(column.uidt) ) { if (column.uidt === colBody.uidt) { @@ -627,11 +632,11 @@ export async function columnUpdate(req: Request, res: Response) { await Column.update(column.id, { // title: colBody.title, ...column, - ...colBody + ...colBody, }); } else if (colBody.title !== column.title) { await Column.updateAlias(req.params.columnId, { - title: colBody.title + title: colBody.title, }); } } else { @@ -645,7 +650,7 @@ export async function columnUpdate(req: Request, res: Response) { UITypes.Rollup, UITypes.LinkToAnotherRecord, UITypes.Formula, - UITypes.ForeignKey + UITypes.ForeignKey, ].includes(colBody.uidt) ) { NcError.notImplemented( @@ -656,20 +661,20 @@ export async function columnUpdate(req: Request, res: Response) { const tableUpdateBody = { ...table, tn: table.table_name, - originalColumns: table.columns.map(c => ({ + originalColumns: table.columns.map((c) => ({ ...c, cn: c.column_name, - cno: c.column_name + cno: c.column_name, })), columns: await Promise.all( - table.columns.map(async c => { + table.columns.map(async (c) => { if (c.id === req.params.columnId) { const res = { ...c, ...colBody, cn: colBody.column_name, cno: c.column_name, - altered: Altered.UPDATE_COLUMN + altered: Altered.UPDATE_COLUMN, }; // update formula with new column name @@ -690,7 +695,7 @@ export async function columnUpdate(req: Request, res: Response) { [new_column] ); await FormulaColumn.update(c.id, { - formula_raw: new_formula_raw + formula_raw: new_formula_raw, }); } } @@ -701,14 +706,14 @@ export async function columnUpdate(req: Request, res: Response) { } return Promise.resolve(c); }) - ) + ), }; const sqlMgr = await ProjectMgrv2.getSqlMgr({ id: base.project_id }); await sqlMgr.sqlOpPlus(base, 'tableUpdate', tableUpdateBody); await Column.update(req.params.columnId, { - ...colBody + ...colBody, }); } Audit.insert({ @@ -717,7 +722,7 @@ export async function columnUpdate(req: Request, res: Response) { op_sub_type: AuditOperationSubTypes.UPDATED, user: (req as any)?.user?.email, description: `updated column ${column.column_name} with alias ${column.title} from table ${table.table_name}`, - ip: (req as any).clientIp + ip: (req as any).clientIp, }).then(() => {}); await table.getColumns(); @@ -729,7 +734,7 @@ export async function columnUpdate(req: Request, res: Response) { export async function columnDelete(req: Request, res: Response) { const column = await Column.get({ colId: req.params.columnId }); const table = await Model.getWithInfo({ - id: column.fk_model_id + id: column.fk_model_id, }); const base = await Base.get(table.base_id); @@ -750,9 +755,8 @@ export async function columnDelete(req: Request, res: Response) { break; case UITypes.LinkToAnotherRecord: { - const relationColOpt = await column.getColOptions< - LinkToAnotherRecordColumn - >(); + const relationColOpt = + await column.getColOptions(); const childColumn = await relationColOpt.getChildColumn(); const childTable = await childColumn.getModel(); @@ -770,7 +774,7 @@ export async function columnDelete(req: Request, res: Response) { childTable, parentColumn, parentTable, - sqlMgr + sqlMgr, // ncMeta }); } @@ -789,7 +793,7 @@ export async function columnDelete(req: Request, res: Response) { sqlMgr, parentTable: parentTable, childColumn: mmParentCol, - base + base, // ncMeta }, true @@ -803,20 +807,19 @@ export async function columnDelete(req: Request, res: Response) { sqlMgr, parentTable: childTable, childColumn: mmChildCol, - base + base, // ncMeta }, true ); const columnsInRelatedTable: Column[] = await relationColOpt .getRelatedTable() - .then(m => m.getColumns()); + .then((m) => m.getColumns()); for (const c of columnsInRelatedTable) { if (c.uidt !== UITypes.LinkToAnotherRecord) continue; - const colOpt = await c.getColOptions< - LinkToAnotherRecordColumn - >(); + const colOpt = + await c.getColOptions(); if ( colOpt.type === 'mm' && colOpt.fk_parent_column_id === childColumn.id && @@ -836,9 +839,8 @@ export async function columnDelete(req: Request, res: Response) { await mmTable.getColumns(); for (const c of mmTable.columns) { if (c.uidt !== UITypes.LinkToAnotherRecord) continue; - const colOpt = await c.getColOptions< - LinkToAnotherRecordColumn - >(); + const colOpt = + await c.getColOptions(); if (colOpt.type === 'bt') { await Column.delete(c.id); } @@ -848,9 +850,8 @@ export async function columnDelete(req: Request, res: Response) { await parentTable.getColumns(); for (const c of parentTable.columns) { if (c.uidt !== UITypes.LinkToAnotherRecord) continue; - const colOpt = await c.getColOptions< - LinkToAnotherRecordColumn - >(); + const colOpt = + await c.getColOptions(); if (colOpt.fk_related_model_id === mmTable.id) { await Column.delete(c.id); } @@ -860,9 +861,8 @@ export async function columnDelete(req: Request, res: Response) { await childTable.getColumns(); for (const c of childTable.columns) { if (c.uidt !== UITypes.LinkToAnotherRecord) continue; - const colOpt = await c.getColOptions< - LinkToAnotherRecordColumn - >(); + const colOpt = + await c.getColOptions(); if (colOpt.fk_related_model_id === mmTable.id) { await Column.delete(c.id); } @@ -889,24 +889,24 @@ export async function columnDelete(req: Request, res: Response) { const tableUpdateBody = { ...table, tn: table.table_name, - originalColumns: table.columns.map(c => ({ + originalColumns: table.columns.map((c) => ({ ...c, cn: c.column_name, - cno: c.column_name + cno: c.column_name, })), - columns: table.columns.map(c => { + columns: table.columns.map((c) => { if (c.id === req.params.columnId) { return { ...c, cn: c.column_name, cno: c.column_name, - altered: Altered.DELETE_COLUMN + altered: Altered.DELETE_COLUMN, }; } else { (c as any).cn = c.column_name; } return c; - }) + }), }; await sqlMgr.sqlOpPlus(base, 'tableUpdate', tableUpdateBody); @@ -921,7 +921,7 @@ export async function columnDelete(req: Request, res: Response) { op_sub_type: AuditOperationSubTypes.DELETED, user: (req as any)?.user?.email, description: `deleted column ${column.column_name} with alias ${column.title} from table ${table.table_name}`, - ip: (req as any).clientIp + ip: (req as any).clientIp, }).then(() => {}); await table.getColumns(); @@ -955,7 +955,7 @@ const deleteHmOrBtRelation = async ( parentColumn, parentTable, sqlMgr, - ncMeta = Noco.ncMeta + ncMeta = Noco.ncMeta, }: { relationColOpt: LinkToAnotherRecordColumn; base: Base; @@ -974,7 +974,7 @@ const deleteHmOrBtRelation = async ( childColumn: childColumn.column_name, childTable: childTable.table_name, parentTable: parentTable.table_name, - parentColumn: parentColumn.column_name + parentColumn: parentColumn.column_name, // foreignKeyName: relation.fkn }); } catch (e) { @@ -984,7 +984,7 @@ const deleteHmOrBtRelation = async ( if (!relationColOpt) return; const columnsInRelatedTable: Column[] = await relationColOpt .getRelatedTable() - .then(m => m.getColumns()); + .then((m) => m.getColumns()); const relType = relationColOpt.type === 'bt' ? 'hm' : 'bt'; for (const c of columnsInRelatedTable) { if (c.uidt !== UITypes.LinkToAnotherRecord) continue; @@ -1004,29 +1004,29 @@ const deleteHmOrBtRelation = async ( if (!ignoreFkDelete) { const cTable = await Model.getWithInfo({ - id: childTable.id + id: childTable.id, }); const tableUpdateBody = { ...cTable, tn: cTable.table_name, - originalColumns: cTable.columns.map(c => ({ + originalColumns: cTable.columns.map((c) => ({ ...c, cn: c.column_name, - cno: c.column_name + cno: c.column_name, })), - columns: cTable.columns.map(c => { + columns: cTable.columns.map((c) => { if (c.id === childColumn.id) { return { ...c, cn: c.column_name, cno: c.column_name, - altered: Altered.DELETE_COLUMN + altered: Altered.DELETE_COLUMN, }; } else { (c as any).cn = c.column_name; } return c; - }) + }), }; await sqlMgr.sqlOpPlus(base, 'tableUpdate', tableUpdateBody); @@ -1040,7 +1040,7 @@ async function createColumnIndex({ sqlMgr, base, indexName = null, - nonUnique = true + nonUnique = true, }: { column: Column; sqlMgr: SqlMgrv2; @@ -1053,7 +1053,7 @@ async function createColumnIndex({ columns: [column.column_name], tn: model.table_name, non_unique: nonUnique, - indexName + indexName, }; sqlMgr.sqlOpPlus(base, 'indexCreate', indexArgs); }