From 87049413f00385373eca49d2d2573d4f79e71e01 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:20 +0000 Subject: [PATCH 01/19] fix(nc-gui): belongsTo cell copy paste issue --- .../nc-gui/composables/useMultiSelect/convertCellData.ts | 1 - packages/nc-gui/composables/useMultiSelect/index.ts | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index 262cac5402..320cb8a6f6 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -246,7 +246,6 @@ export default function convertCellData( return parsedVal || value } - case UITypes.LinkToAnotherRecord: case UITypes.Lookup: case UITypes.Rollup: case UITypes.Formula: diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 62f9f55536..0064a1c2ee 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -852,8 +852,7 @@ export function useMultiSelect( (columnObj.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.BELONGS_TO ) { const clipboardContext = JSON.parse(clipboardData!) - - rowObj.row[columnObj.title!] = convertCellData( + let pasteVal = convertCellData( { value: clipboardContext, to: columnObj.uidt as UITypes, @@ -863,6 +862,10 @@ export function useMultiSelect( isMysql(meta.value?.source_id), ) + if (pasteVal === undefined) return + + rowObj.row[columnObj.title!] = pasteVal + const foreignKeyColumn = meta.value?.columns?.find( (column: ColumnType) => column.id === (columnObj.colOptions as LinkToAnotherRecordType)?.fk_child_column_id, ) From b938c3f64fe6d47e559cfe8ffb408429b6cf536d Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:20 +0000 Subject: [PATCH 02/19] fix(nc-gui): BT cell verify paste value --- .../composables/useMultiSelect/convertCellData.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index 320cb8a6f6..a9893b2054 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -246,6 +246,17 @@ export default function convertCellData( return parsedVal || value } + case UITypes.LinkToAnotherRecord: { + const parsedVal = typeof value === 'string' ? JSON.parse(value) : value + if (!(parsedVal && typeof parsedVal === 'object' && !Array.isArray(parsedVal) && Object.keys(parsedVal))) { + throw new Error('Invalid LTAR data') + } + + if (isMultiple) { + return undefined + } + return parsedVal + } case UITypes.Lookup: case UITypes.Rollup: case UITypes.Formula: From a1e26f88c1287f65359b21d954349d7747822369 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:21 +0000 Subject: [PATCH 03/19] feat(nc-gui): some part of copy paste mm cell --- .../useMultiSelect/convertCellData.ts | 3 +- .../composables/useMultiSelect/index.ts | 107 ++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index a9893b2054..824418bd47 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -246,7 +246,8 @@ export default function convertCellData( return parsedVal || value } - case UITypes.LinkToAnotherRecord: { + case UITypes.LinkToAnotherRecord: + case UITypes.Links: { const parsedVal = typeof value === 'string' ? JSON.parse(value) : value if (!(parsedVal && typeof parsedVal === 'object' && !Array.isArray(parsedVal) && Object.keys(parsedVal))) { throw new Error('Invalid LTAR data') diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 0064a1c2ee..c078938339 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -113,6 +113,8 @@ export function useMultiSelect( const valueToCopy = (rowObj: Row, columnObj: ColumnType) => { let textToCopy = (columnObj.title && rowObj.row[columnObj.title]) || '' + console.log('rowObj, columnObj', rowObj, columnObj) + if (columnObj.uidt === UITypes.Checkbox) { textToCopy = !!textToCopy } @@ -218,6 +220,18 @@ export function useMultiSelect( textToCopy = `"${textToCopy.replace(/"/g, '\\"')}"` } + if ( + columnObj.uidt === UITypes.Links && + (columnObj.colOptions as LinkToAnotherRecordType).type === RelationTypes.MANY_TO_MANY + ) { + return JSON.stringify({ + rowId: extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]), + columnId: columnObj.id, + fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id, + value: !isNaN(+textToCopy) ? +textToCopy : 0, + }) + } + return textToCopy } @@ -879,6 +893,99 @@ export function useMultiSelect( return await syncCellData?.({ ...activeCell, updatedColumnTitle: foreignKeyColumn.title }) } + if ( + columnObj.uidt === UITypes.Links && + (columnObj.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.MANY_TO_MANY + ) { + const clipboardContext = JSON.parse(clipboardData) + if (clipboardContext?.fk_related_model_id !== (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id) { + throw new Error('Invalid paste data for MM LTAR cell') + return + } + + let pasteVal = convertCellData( + { + value: clipboardContext, + to: columnObj.uidt as UITypes, + column: columnObj, + appInfo: unref(appInfo), + }, + isMysql(meta.value?.source_id), + ) + + console.log('paste data', clipboardContext, pasteVal) + const relatedTableMeta = await getMeta((columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id!) + + const extractedPk = extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) + if (!extractedPk) return + + const [copiedCellchildrenList, pasteCellchildrenList] = await Promise.all([ + api.dbDataTableRow.nestedList( + meta.value?.id as string, + columnObj.id as string, + encodeURIComponent((clipboardContext.rowId as string) || ''), + ), + api.dbDataTableRow.nestedList( + meta.value?.id as string, + columnObj.id as string, + encodeURIComponent(extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) || ''), + ), + ]) + + const relatedTablePrimaryKeys = (extractPk(relatedTableMeta?.columns as ColumnType[]) || '').split('__') + + function filterAndMapRows( + sourceList: Record[], + targetList: Record[], + primaryKeys: string[] = relatedTablePrimaryKeys, + ): Record[] { + return sourceList + .filter( + (sourceRow: Record) => + !targetList.some((targetRow: Record) => + primaryKeys.every((key) => sourceRow[key] === targetRow[key]), + ), + ) + .map((item: Record) => + primaryKeys.reduce((acc, key) => { + acc[key] = item[key] + return acc + }, {} as Record), + ) + } + + const filteredRowsToLink = filterAndMapRows(copiedCellchildrenList.list, pasteCellchildrenList.list) + + const filteredRowsToUnlink = filterAndMapRows(pasteCellchildrenList.list, copiedCellchildrenList.list) + + console.log('copied cell child list', copiedCellchildrenList) + console.log('paste cell child list', pasteCellchildrenList) + console.log('filtered', filteredRowsToLink, filteredRowsToUnlink) + + rowObj.row[columnObj.title!] = clipboardContext.value + + const result = await Promise.all([ + filteredRowsToLink.length && + api.dbDataTableRow.nestedLink( + meta.value?.id as string, + columnObj.id as string, + encodeURIComponent(extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) || ''), + filteredRowsToLink, + ), + filteredRowsToUnlink.length && + api.dbDataTableRow.nestedUnlink( + meta.value?.id as string, + columnObj.id as string, + encodeURIComponent(extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) || ''), + filteredRowsToUnlink, + ), + ]) + + console.log('result', result) + await syncCellData?.(activeCell) + return + } + if (!isPasteable(rowObj, columnObj, true)) { return } From 9682781bd2c41eff88002438ba44bd02449619cf Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:21 +0000 Subject: [PATCH 04/19] feat: new nested link api setup --- .../composables/useMultiSelect/index.ts | 3 +- .../src/controllers/data-table.controller.ts | 25 + packages/nocodb/src/schema/swagger.json | 1531 +++++------------ .../nocodb/src/services/data-table.service.ts | 20 + packages/nocodb/src/utils/acl.ts | 2 + 5 files changed, 465 insertions(+), 1116 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index c078938339..81b241ff6c 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -982,8 +982,7 @@ export function useMultiSelect( ]) console.log('result', result) - await syncCellData?.(activeCell) - return + return await syncCellData?.(activeCell) } if (!isPasteable(rowObj, columnObj, true)) { diff --git a/packages/nocodb/src/controllers/data-table.controller.ts b/packages/nocodb/src/controllers/data-table.controller.ts index 35d4c1c6f2..9a3c5052c1 100644 --- a/packages/nocodb/src/controllers/data-table.controller.ts +++ b/packages/nocodb/src/controllers/data-table.controller.ts @@ -193,4 +193,29 @@ export class DataTableController { cookie: req, }); } + + @Post(['/api/v2/tables/:modelId/links/:columnId/records']) + @Acl('nestedDataLinkUnlink') + async nestedLinkUnlink( + @Req() req: Request, + @Param('modelId') modelId: string, + @Query('viewId') viewId: string, + @Param('columnId') columnId: string, + @Body() + data: { + operation: 'copy' | 'paste'; + rowId: string; + }[], + ) { + console.log('data', data); + + return await this.dataTableService.nestedLinkUnlink({ + modelId, + query: req.query, + viewId, + columnId, + data, + cookie: req, + }); + } } diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json index 17d4d60c89..f9ab81d13f 100644 --- a/packages/nocodb/src/schema/swagger.json +++ b/packages/nocodb/src/schema/swagger.json @@ -11,24 +11,15 @@ "x-tagGroups": [ { "name": "Auth APIs", - "tags": [ - "Auth", - "API Token" - ] + "tags": ["Auth", "API Token"] }, { "name": "Public APIs", - "tags": [ - "Public" - ] + "tags": ["Public"] }, { "name": "Data APIs", - "tags": [ - "DB Table Row", - "DB View Row", - "Storage" - ] + "tags": ["DB Table Row", "DB View Row", "Storage"] }, { "name": "Meta APIs", @@ -50,12 +41,7 @@ }, { "name": "Organisation APIs", - "tags": [ - "Org App Settings", - "Org License", - "Org Tokens", - "Org Users" - ] + "tags": ["Org App Settings", "Org License", "Org Tokens", "Org Users"] } ], "servers": [ @@ -73,9 +59,7 @@ "$ref": "#/components/schemas/User" } }, - "tags": [ - "User profile" - ], + "tags": ["User profile"], "description": "Update User Profile", "requestBody": { "content": { @@ -160,9 +144,7 @@ } } }, - "tags": [ - "Auth" - ], + "tags": ["Auth"], "requestBody": { "content": { "application/json": { @@ -220,9 +202,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Auth" - ], + "tags": ["Auth"], "description": "Clear refresh token from the database and cookie." }, "parameters": [ @@ -264,9 +244,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Auth" - ], + "tags": ["Auth"], "requestBody": { "content": { "application/json": { @@ -328,9 +306,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Auth" - ], + "tags": ["Auth"], "description": "Returns authenticated user info", "parameters": [ { @@ -381,9 +357,7 @@ } }, "description": "Emails user with a reset url.", - "tags": [ - "Auth" - ], + "tags": ["Auth"], "requestBody": { "content": { "application/json": { @@ -441,9 +415,7 @@ } }, "description": "Change password of authenticated user with a new one.", - "tags": [ - "Auth" - ], + "tags": ["Auth"], "requestBody": { "content": { "application/json": { @@ -506,9 +478,7 @@ } }, "description": "Validate password reset url token.", - "tags": [ - "Auth" - ], + "tags": ["Auth"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -566,9 +536,7 @@ } }, "description": "Api for verifying email where token need to be passed which is shared to user email.", - "tags": [ - "Auth" - ], + "tags": ["Auth"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -626,9 +594,7 @@ } }, "description": "Update user password to new by using reset token.", - "tags": [ - "Auth" - ], + "tags": ["Auth"], "requestBody": { "content": { "application/json": { @@ -699,9 +665,7 @@ } }, "description": "Creates a new refresh token and JWT auth token for the user. The refresh token is sent as a cookie, while the JWT auth token is included in the response body.", - "tags": [ - "Auth" - ], + "tags": ["Auth"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -755,9 +719,7 @@ } }, "description": "List all organisation API tokens. Access with API tokens will be blocked.", - "tags": [ - "Org Tokens" - ], + "tags": ["Org Tokens"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -813,9 +775,7 @@ } } }, - "tags": [ - "Org Tokens" - ], + "tags": ["Org Tokens"], "description": "Creat an organisation API token. Access with API tokens will be blocked." } }, @@ -855,9 +815,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Org Tokens" - ], + "tags": ["Org Tokens"], "description": "Delete an organisation API token. Access with API tokens will be blocked.", "parameters": [ { @@ -899,9 +857,7 @@ } }, "description": "Get the application license key. Exclusive for super admin.", - "tags": [ - "Org License" - ], + "tags": ["Org License"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -963,9 +919,7 @@ } } }, - "tags": [ - "Org License" - ], + "tags": ["Org License"], "description": "Set the application license key. Exclusive for super admin.", "parameters": [ { @@ -1008,9 +962,7 @@ } }, "description": "Get the application settings. Exclusive for super admin.", - "tags": [ - "Org App Settings" - ], + "tags": ["Org App Settings"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -1079,9 +1031,7 @@ } } }, - "tags": [ - "Org App Settings" - ], + "tags": ["Org App Settings"], "description": "Update the application settings. Exclusive for super admin.", "parameters": [ { @@ -1133,9 +1083,7 @@ } }, "description": "List all organisation users. Exclusive for Super Admin. Access with API Tokens will be blocked.", - "tags": [ - "Org Users" - ], + "tags": ["Org Users"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -1207,9 +1155,7 @@ } } }, - "tags": [ - "Org Users" - ], + "tags": ["Org Users"], "description": "Create an organisation user. Exclusive for Super Admin. Access with API Tokens will be blocked.", "parameters": [ { @@ -1265,9 +1211,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Org Users" - ], + "tags": ["Org Users"], "description": "Update an organisation user by User ID. Exclusive for Super Admin. Access with API Tokens will be blocked.", "requestBody": { "content": { @@ -1323,9 +1267,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Org Users" - ], + "tags": ["Org Users"], "description": "Delete an organisation user by User ID. Exclusive for Super Admin. Access with API Tokens will be blocked." } }, @@ -1355,9 +1297,7 @@ } } }, - "tags": [ - "Org users" - ], + "tags": ["Org users"], "description": "Organisation User GetByUsername" } }, @@ -1409,9 +1349,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Org Users" - ], + "tags": ["Org Users"], "description": "Resend Invitation to a specific user. Exclusive for Super Admin. Access with API Tokens will be blocked.", "parameters": [ { @@ -1439,9 +1377,7 @@ "description": "OK" } }, - "tags": [ - "Org users" - ], + "tags": ["Org users"], "description": "Create Organisation User Profile", "requestBody": { "content": { @@ -1462,9 +1398,7 @@ } }, "description": "Get Organisation User Profile", - "tags": [ - "Org users" - ] + "tags": ["Org users"] }, "patch": { "summary": "", @@ -1475,9 +1409,7 @@ } }, "description": "Update Organisation User Profile\n", - "tags": [ - "Org users" - ], + "tags": ["Org users"], "requestBody": { "content": { "application/json": { @@ -1508,9 +1440,7 @@ "description": "OK" } }, - "tags": [ - "Org users" - ], + "tags": ["Org users"], "description": "Create Organisation User Follower Relationship (Follow)", "requestBody": { "content": { @@ -1531,9 +1461,7 @@ } }, "description": "List Organisation User Followers", - "tags": [ - "Org users" - ], + "tags": ["Org users"], "requestBody": { "content": { "application/json": { @@ -1552,9 +1480,7 @@ "description": "OK" } }, - "tags": [ - "Org users" - ], + "tags": ["Org users"], "description": "Delete Organisation User Follower Relationship (Unfollow)", "requestBody": { "content": { @@ -1588,9 +1514,7 @@ } }, "description": "List Organisation User Following", - "tags": [ - "Org users" - ] + "tags": ["Org users"] } }, "/api/v1/users/{userId}/isFollowing/{followerId}": { @@ -1621,9 +1545,7 @@ } }, "description": "Check if Organisation User is following someone", - "tags": [ - "Org users" - ] + "tags": ["Org users"] } }, "/api/v1/users/{userId}/generate-reset-url": { @@ -1642,9 +1564,7 @@ "post": { "summary": "Generate Organisation User Password Reset Token", "operationId": "org-users-generate-password-reset-token", - "tags": [ - "Org Users" - ], + "tags": ["Org Users"], "responses": { "200": { "description": "OK", @@ -1713,10 +1633,7 @@ "$ref": "#/components/schemas/Paginated" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] } } }, @@ -1753,9 +1670,7 @@ } }, "description": "List all users in the given base.", - "tags": [ - "Auth" - ], + "tags": ["Auth"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -1886,9 +1801,7 @@ } } }, - "tags": [ - "Auth" - ], + "tags": ["Auth"], "description": "Create a user and add it to the given base", "parameters": [ { @@ -1985,9 +1898,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Get info such as node version, arch, platform, is docker, rootdb and package version of a given base", "parameters": [ { @@ -2072,9 +1983,7 @@ } } }, - "tags": [ - "Auth" - ], + "tags": ["Auth"], "description": "Update a given user in a given base. Exclusive for Super Admin. Access with API Tokens will be blocked.", "parameters": [ { @@ -2117,9 +2026,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Auth" - ], + "tags": ["Auth"], "description": "Delete a given user in a given base. Exclusive for Super Admin. Access with API Tokens will be blocked.", "parameters": [ { @@ -2199,9 +2106,7 @@ } }, "description": "Hide / show views based on user role", - "tags": [ - "Base" - ], + "tags": ["Base"], "parameters": [ { "schema": { @@ -2271,9 +2176,7 @@ } } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Hide / show views based on user role", "parameters": [ { @@ -2357,9 +2260,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Base" - ] + "tags": ["Base"] }, "post": { "summary": "Create Base", @@ -2435,9 +2336,7 @@ } } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Create a new base", "parameters": [ { @@ -2517,9 +2416,7 @@ } } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Duplicate a base", "parameters": [ { @@ -2618,9 +2515,7 @@ } } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Duplicate a base", "parameters": [ { @@ -2663,9 +2558,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Base" - ], + "tags": ["Base"], "responses": { "200": { "description": "OK", @@ -2737,9 +2630,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Delete the given base", "parameters": [ { @@ -2771,9 +2662,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "requestBody": { "content": { "application/json": { @@ -2820,9 +2709,7 @@ "description": "OK" } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "requestBody": { "content": { "application/json": { @@ -2867,9 +2754,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Source" - ], + "tags": ["Source"], "responses": { "200": { "description": "OK", @@ -2926,9 +2811,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Source" - ], + "tags": ["Source"], "description": "Delete the source details of a given base", "parameters": [ { @@ -2973,9 +2856,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Source" - ], + "tags": ["Source"], "requestBody": { "content": { "application/json": { @@ -3048,9 +2929,7 @@ } } }, - "tags": [ - "Source" - ], + "tags": ["Source"], "requestBody": { "content": { "application/json": { @@ -3093,9 +2972,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Source" - ], + "tags": ["Source"], "responses": { "200": { "description": "OK", @@ -3198,9 +3075,7 @@ } } }, - "tags": [ - "Source" - ], + "tags": ["Source"], "description": "Create a new source on a given base", "parameters": [ { @@ -3231,9 +3106,7 @@ "post": { "summary": "share ERD view", "operationId": "source-share-erd", - "tags": [ - "Source" - ], + "tags": ["Source"], "responses": { "200": { "description": "OK", @@ -3255,9 +3128,7 @@ "description": "OK" } }, - "tags": [ - "Source" - ] + "tags": ["Source"] } }, "/api/v1/db/meta/projects/{baseId}/shared": { @@ -3283,9 +3154,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Base" - ], + "tags": ["Base"], "responses": { "200": { "description": "OK", @@ -3349,9 +3218,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Delete Base Shared Base", "parameters": [ { @@ -3385,9 +3252,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "requestBody": { "content": { "application/json": { @@ -3462,9 +3327,7 @@ } } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Update Base Shared Base", "parameters": [ { @@ -3496,9 +3359,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Base" - ], + "tags": ["Base"], "responses": { "200": { "description": "OK", @@ -3917,9 +3778,7 @@ } } }, - "tags": [ - "DB Table" - ], + "tags": ["DB Table"], "description": "Create a new table in a given base", "parameters": [ { @@ -3971,9 +3830,7 @@ "name": "includeM2M" } ], - "tags": [ - "DB Table" - ], + "tags": ["DB Table"], "description": "List all tables in a given base" } }, @@ -4367,9 +4224,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table" - ], + "tags": ["DB Table"], "description": "Read the table meta data by the given table ID", "parameters": [ { @@ -4411,9 +4266,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table" - ], + "tags": ["DB Table"], "requestBody": { "content": { "application/json": { @@ -4483,9 +4336,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table" - ], + "tags": ["DB Table"], "description": "Delete the table meta data by the given table ID", "parameters": [ { @@ -4557,9 +4408,7 @@ } } }, - "tags": [ - "DB Table" - ], + "tags": ["DB Table"], "description": "Duplicate a table", "parameters": [ { @@ -4647,9 +4496,7 @@ } } }, - "tags": [ - "DB Table" - ], + "tags": ["DB Table"], "description": "Duplicate a column", "parameters": [ { @@ -4748,9 +4595,7 @@ "name": "includeM2M" } ], - "tags": [ - "Source" - ], + "tags": ["Source"], "description": "List all tables in a given Base and Source" }, "post": { @@ -5240,9 +5085,7 @@ } } }, - "tags": [ - "Source" - ], + "tags": ["Source"], "description": "Create a new table in a given Base and Source", "parameters": [ { @@ -5309,9 +5152,7 @@ } } }, - "tags": [ - "DB Table" - ], + "tags": ["DB Table"], "description": "Update the order of the given Table", "parameters": [ { @@ -5392,9 +5233,7 @@ } } }, - "tags": [ - "DB Table Column" - ], + "tags": ["DB Table Column"], "description": "Create a new column in a given Table", "parameters": [ { @@ -5441,9 +5280,7 @@ } } }, - "tags": [ - "DB Table Column" - ], + "tags": ["DB Table Column"], "description": "Update the existing column by the given column ID", "parameters": [ { @@ -5462,9 +5299,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Column" - ], + "tags": ["DB Table Column"], "description": "Delete the existing column by the given column ID", "parameters": [ { @@ -5483,9 +5318,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Column" - ], + "tags": ["DB Table Column"], "description": "Get the existing column by the given column ID", "parameters": [ { @@ -5528,9 +5361,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Column" - ], + "tags": ["DB Table Column"], "description": "Set a primary value on a given column", "parameters": [ { @@ -5650,9 +5481,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "List all views in a given Table.", "parameters": [ { @@ -5736,9 +5565,7 @@ } } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "Update the view with the given view Id.", "parameters": [ { @@ -5769,9 +5596,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "Delete the view with the given view Id.", "parameters": [ { @@ -5816,9 +5641,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "Show All Columns in a given View", "parameters": [ { @@ -5870,9 +5693,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "parameters": [ { "schema": { @@ -5963,9 +5784,7 @@ } }, "description": "List all shared views in a given Table", - "tags": [ - "DB View Share" - ], + "tags": ["DB View Share"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -6012,9 +5831,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View Share" - ], + "tags": ["DB View Share"], "description": "Create a shared view in a given View..", "parameters": [ { @@ -6050,9 +5867,7 @@ }, "description": "" }, - "tags": [ - "DB View Share" - ], + "tags": ["DB View Share"], "description": "Update a shared view in a given View..", "parameters": [ { @@ -6084,9 +5899,7 @@ } }, "description": "Delete a shared view in a given View.", - "tags": [ - "DB View Share" - ], + "tags": ["DB View Share"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -6176,9 +5989,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View Column" - ], + "tags": ["DB View Column"], "description": "List all columns by ViewID", "parameters": [ { @@ -6244,9 +6055,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View Column" - ], + "tags": ["DB View Column"], "requestBody": { "content": { "application/json": { @@ -6319,9 +6128,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View Column" - ], + "tags": ["DB View Column"], "requestBody": { "content": { "application/json": { @@ -6402,9 +6209,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Sort" - ], + "tags": ["DB Table Sort"], "description": "List all the sort data in a given View", "parameters": [ { @@ -6435,9 +6240,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Sort" - ], + "tags": ["DB Table Sort"], "requestBody": { "content": { "application/json": { @@ -6513,9 +6316,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Sort" - ], + "tags": ["DB Table Sort"], "description": "Get the sort data by Sort ID", "parameters": [ { @@ -6547,9 +6348,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Sort" - ], + "tags": ["DB Table Sort"], "requestBody": { "content": { "application/json": { @@ -6597,9 +6396,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Sort" - ], + "tags": ["DB Table Sort"], "description": "Delete the sort data by Sort ID", "parameters": [ { @@ -6671,9 +6468,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Filter" - ], + "tags": ["DB Table Filter"], "description": "Get the filter data in a given View", "parameters": [ { @@ -6720,9 +6515,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Filter" - ], + "tags": ["DB Table Filter"], "requestBody": { "content": { "application/json": { @@ -6815,9 +6608,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Webhook Filter" - ], + "tags": ["DB Table Webhook Filter"], "description": "Get the filter data in a given Hook", "parameters": [ { @@ -6864,9 +6655,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Webhook Filter" - ], + "tags": ["DB Table Webhook Filter"], "requestBody": { "content": { "application/json": { @@ -6957,9 +6746,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Webhook Logs" - ], + "tags": ["DB Table Webhook Logs"], "description": "List the log data in a given Hook", "parameters": [ { @@ -7036,9 +6823,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Filter" - ], + "tags": ["DB Table Filter"], "description": "Get the filter data with a given Filter ID", "parameters": [ { @@ -7069,9 +6854,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Filter" - ], + "tags": ["DB Table Filter"], "requestBody": { "content": { "application/json": { @@ -7123,9 +6906,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Filter" - ], + "tags": ["DB Table Filter"], "description": "Delete the filter data with a given Filter ID", "parameters": [ { @@ -7197,9 +6978,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Filter" - ], + "tags": ["DB Table Filter"], "description": "Get Filter Group Children of a given group ID", "parameters": [ { @@ -7262,9 +7041,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -7348,9 +7125,7 @@ } }, "description": "Create a new form view in a given Table", - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -7414,9 +7189,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -7510,9 +7283,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "Get the form data by Form ID", "parameters": [ { @@ -7566,9 +7337,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -7622,9 +7391,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -7701,9 +7468,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "List all columns in the given Grid", "parameters": [ { @@ -7749,9 +7514,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -7831,9 +7594,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -7897,9 +7658,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -7942,9 +7701,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "Get the Gallery View data with Gallery ID", "parameters": [ { @@ -8007,9 +7764,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -8074,9 +7829,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -8162,9 +7915,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "Get the Kanban View data by Kanban ID", "parameters": [ { @@ -8227,9 +7978,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -8295,9 +8044,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "requestBody": { "content": { "application/json": { @@ -8340,9 +8087,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View" - ], + "tags": ["DB View"], "description": "Get the Map View data by Map ID", "parameters": [ { @@ -8399,9 +8144,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Base" - ], + "tags": ["Base"], "description": "Synchronise the meta data difference between NC_DB and external data sources ", "parameters": [ { @@ -8420,9 +8163,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Base" - ], + "tags": ["Base"], "responses": { "200": { "description": "OK", @@ -8581,9 +8322,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Source" - ], + "tags": ["Source"], "description": "Synchronise the meta data difference between NC_DB and external data sources in a given Source", "parameters": [ { @@ -8599,9 +8338,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Source" - ], + "tags": ["Source"], "responses": { "200": { "description": "OK", @@ -8724,9 +8461,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Base" - ], + "tags": ["Base"], "responses": { "200": { "description": "OK", @@ -8778,9 +8513,7 @@ "summary": "List Table Rows", "operationId": "db-table-row-list", "description": "List all table rows in a given table and base", - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "schema": { @@ -8883,10 +8616,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "examples": { "Example 1": { @@ -8968,9 +8698,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "requestBody": { "content": { "application/json": { @@ -9032,9 +8760,7 @@ "summary": "Find One Table Row", "operationId": "db-table-row-find-one", "description": "Return the first result of the target Table Row", - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "schema": { @@ -9130,9 +8856,7 @@ "summary": "Group By Table Row", "operationId": "db-table-row-group-by", "description": "Get the result grouped by the given query", - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "schema": { @@ -9237,9 +8961,7 @@ "summary": "Table Group by Column", "operationId": "db-view-row-grouped-data-list", "description": "Get the grouped data By Column ID. Used in Kanban View.", - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "parameters": [ { "schema": { @@ -9405,9 +9127,7 @@ "summary": "Table Group by Column", "operationId": "db-table-row-grouped-data-list", "description": "Get the grouped data By Column ID. Used in Kanban View.", - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "schema": { @@ -9568,9 +9288,7 @@ "summary": "List Table View Rows", "operationId": "db-view-row-list", "description": "List all table view rows", - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "parameters": [ { "schema": { @@ -9639,10 +9357,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "examples": { "Example 1": { @@ -9737,9 +9452,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "requestBody": { "content": { "application/json": { @@ -9802,9 +9515,7 @@ "summary": "Find One Table View Row", "operationId": "db-view-row-find-one", "description": "Return the first result of table view rows with the given query", - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "parameters": [ { "schema": { @@ -9914,9 +9625,7 @@ "summary": "Group By Table View Row", "operationId": "db-view-row-group-by", "description": "Get the table view rows grouped by the given query", - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "parameters": [ { "schema": { @@ -10011,9 +9720,7 @@ "summary": "Count Table View Rows", "operationId": "db-view-row-count", "description": "Count how many rows in the given Table View", - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "parameters": [ { "schema": { @@ -10140,9 +9847,7 @@ } }, "description": "Get the target Table View Row", - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -10177,9 +9882,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "requestBody": { "content": { "application/json": { @@ -10226,9 +9929,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "description": "Delete the target Table View Row", "parameters": [ { @@ -10308,9 +10009,7 @@ } }, "description": "Check row with provided primary key exists or not", - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -10396,9 +10095,7 @@ } }, "description": "Get the Table Row by Row ID", - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -10433,9 +10130,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "requestBody": { "content": { "application/json": { @@ -10482,9 +10177,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "description": "Delete the Table Row", "parameters": [ { @@ -10556,9 +10249,7 @@ } }, "description": "check row with provided primary key exists or not", - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -10641,9 +10332,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "requestBody": { "content": { "application/json": { @@ -10700,10 +10389,7 @@ }, "examples": { "Example 1": { - "value": [ - 1, - 1 - ] + "value": [1, 1] } } } @@ -10713,9 +10399,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "requestBody": { "content": { "application/json": { @@ -10772,10 +10456,7 @@ }, "examples": { "Example 1": { - "value": [ - 1, - 1 - ] + "value": [1, 1] } } } @@ -10785,9 +10466,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "requestBody": { "content": { "application/json": { @@ -10896,9 +10575,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "requestBody": { "content": { "application/json": { @@ -10941,10 +10618,7 @@ }, "examples": { "Example 1": { - "value": [ - 1, - 1 - ] + "value": [1, 1] } } } @@ -10954,9 +10628,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "requestBody": { "content": { "application/json": { @@ -11021,10 +10693,7 @@ { "schema": { "type": "string", - "enum": [ - "csv", - "excel" - ] + "enum": ["csv", "excel"] }, "name": "type", "in": "path", @@ -11035,9 +10704,7 @@ "summary": "Export Table View Rows", "operationId": "db-view-row-export", "description": "Export Table View Rows by CSV or Excel", - "tags": [ - "DB View Row" - ], + "tags": ["DB View Row"], "wrapped": true, "responses": { "200": { @@ -11099,10 +10766,7 @@ { "schema": { "type": "string", - "enum": [ - "csv", - "excel" - ] + "enum": ["csv", "excel"] }, "name": "type", "in": "path", @@ -11113,9 +10777,7 @@ "summary": "Export Table View Rows", "operationId": "db-table-row-csv-export", "description": "Export Table View Rows by CSV or Excel", - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "wrapped": true, "responses": { "200": { @@ -11186,11 +10848,7 @@ { "schema": { "type": "string", - "enum": [ - "mm", - "hm", - "bt" - ] + "enum": ["mm", "hm", "bt"] }, "name": "relationType", "in": "path", @@ -11223,9 +10881,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "schema": { @@ -11298,11 +10954,7 @@ { "schema": { "type": "string", - "enum": [ - "mm", - "hm", - "bt" - ] + "enum": ["mm", "hm", "bt"] }, "name": "relationType", "in": "path", @@ -11359,9 +11011,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "schema": { @@ -11471,9 +11121,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "description": "Delete a new nested relations row", "parameters": [ { @@ -11523,11 +11171,7 @@ { "schema": { "type": "string", - "enum": [ - "mm", - "hm", - "bt" - ] + "enum": ["mm", "hm", "bt"] }, "name": "relationType", "in": "path", @@ -11558,9 +11202,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Row" - ], + "tags": ["DB Table Row"], "parameters": [ { "schema": { @@ -11653,10 +11295,7 @@ "id": "0xsi3jvwn7duo" }, "description": "the paginated result of the given key", - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "properties": { "list": { "type": "array", @@ -11681,10 +11320,7 @@ } } }, - "required": [ - "key", - "value" - ] + "required": ["key", "value"] } }, "examples": { @@ -11757,9 +11393,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Public" - ], + "tags": ["Public"], "parameters": [ { "schema": { @@ -11915,9 +11549,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Public" - ], + "tags": ["Public"], "parameters": [ { "schema": { @@ -12025,9 +11657,7 @@ }, "description": "" }, - "tags": [ - "Public" - ], + "tags": ["Public"], "parameters": [ { "schema": { @@ -12080,9 +11710,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Public" - ], + "tags": ["Public"], "parameters": [ { "schema": { @@ -12188,11 +11816,7 @@ { "schema": { "type": "string", - "enum": [ - "mm", - "hm", - "bt" - ] + "enum": ["mm", "hm", "bt"] }, "name": "relationType", "in": "path", @@ -12241,10 +11865,7 @@ "description": "Paginated info" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "examples": { "Example 1": { @@ -12286,9 +11907,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Public" - ], + "tags": ["Public"], "parameters": [ { "schema": { @@ -12377,10 +11996,7 @@ { "schema": { "type": "string", - "enum": [ - "csv", - "excel" - ], + "enum": ["csv", "excel"], "example": "csv" }, "name": "type", @@ -12415,9 +12031,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Public" - ] + "tags": ["Public"] } }, "/api/v1/db/public/shared-view/{sharedViewUuid}/nested/{columnName}": { @@ -12536,9 +12150,7 @@ "description": "Used for multiple filter queries" } ], - "tags": [ - "Public" - ], + "tags": ["Public"], "description": "List Nested Data Relation" } }, @@ -12592,9 +12204,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Public" - ] + "tags": ["Public"] } }, "/api/v1/db/public/shared-view/{sharedViewUuid}/meta": { @@ -12696,9 +12306,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Public" - ], + "tags": ["Public"], "description": "Get Share View Meta" } }, @@ -12716,9 +12324,7 @@ "get": { "summary": "", "operationId": "public-shared-erd-meta-get", - "tags": [ - "Public" - ], + "tags": ["Public"], "description": "", "parameters": [] } @@ -12753,9 +12359,7 @@ } } }, - "required": [ - "list" - ] + "required": ["list"] }, "examples": { "Example 1": { @@ -12841,9 +12445,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Utils" - ] + "tags": ["Utils"] }, "post": { "summary": "Comment Rows", @@ -12894,9 +12496,7 @@ } } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "description": "Create a new comment in a row. Logged in Audit.", "parameters": [ { @@ -12948,9 +12548,7 @@ } } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "description": "Update comment in Audit", "requestBody": { "content": { @@ -13009,10 +12607,7 @@ "example": "1" } }, - "required": [ - "count", - "row_id" - ] + "required": ["count", "row_id"] } }, "examples": { @@ -13053,9 +12648,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Utils" - ] + "tags": ["Utils"] } }, "/api/v1/db/meta/projects/{baseId}/audits": { @@ -13095,10 +12688,7 @@ "$ref": "#/components/schemas/Paginated" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] } } } @@ -13136,9 +12726,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Base" - ] + "tags": ["Base"] } }, "/api/v1/db/meta/audits/rows/{rowId}/update": { @@ -13184,9 +12772,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "requestBody": { "content": { "application/json": { @@ -13284,9 +12870,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "DB Table Webhook" - ] + "tags": ["DB Table Webhook"] }, "post": { "summary": "Create Table Hook", @@ -13357,9 +12941,7 @@ } } }, - "tags": [ - "DB Table Webhook" - ] + "tags": ["DB Table Webhook"] } }, "/api/v1/db/meta/tables/{tableId}/hooks/test": { @@ -13410,9 +12992,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Webhook" - ], + "tags": ["DB Table Webhook"], "requestBody": { "content": { "application/json": { @@ -13502,10 +13082,7 @@ { "schema": { "type": "string", - "enum": [ - "v1", - "v2" - ] + "enum": ["v1", "v2"] }, "name": "version", "in": "path", @@ -13558,9 +13135,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "DB Table Webhook" - ] + "tags": ["DB Table Webhook"] } }, "/api/v1/db/meta/hooks/{hookId}": { @@ -13614,9 +13189,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Webhook" - ], + "tags": ["DB Table Webhook"], "requestBody": { "content": { "application/json": { @@ -13676,9 +13249,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Table Webhook" - ], + "tags": ["DB Table Webhook"], "description": "Delete the exsiting hook by its ID", "parameters": [ { @@ -13730,9 +13301,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Plugin" - ] + "tags": ["Plugin"] } }, "/api/v1/db/meta/plugins/webhook": { @@ -13778,9 +13347,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Plugin" - ] + "tags": ["Plugin"] } }, "/api/v1/db/meta/plugins/{pluginTitle}/status": { @@ -13819,9 +13386,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Plugin" - ], + "tags": ["Plugin"], "x-internal": false } }, @@ -13853,9 +13418,7 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": [ - "Plugin" - ], + "tags": ["Plugin"], "requestBody": { "content": { "application/json": { @@ -13904,9 +13467,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Plugin" - ], + "tags": ["Plugin"], "requestBody": { "content": { "application/json": { @@ -13942,9 +13503,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Plugin" - ], + "tags": ["Plugin"], "description": "Get the plugin data by ID", "x-internal": false } @@ -13996,9 +13555,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "requestBody": { "content": { "application/json": { @@ -14093,9 +13650,7 @@ } } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "requestBody": { "content": { "application/json": {} @@ -14113,9 +13668,7 @@ "post": { "summary": "Convert JDBC URL to Config", "operationId": "utils-url-to-config", - "tags": [ - "Utils" - ], + "tags": ["Utils"], "requestBody": { "content": { "application/json": { @@ -14333,11 +13886,7 @@ "x-stoplight": { "id": "uc3vaotye2eu8" }, - "enum": [ - "OFF", - "ERROR", - "ALL" - ], + "enum": ["OFF", "ERROR", "ALL"], "example": "OFF" } } @@ -14374,9 +13923,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "description": "Get the application info such as authType, defaultLimit, version and etc.", "parameters": [ { @@ -14420,9 +13967,7 @@ } } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "x-internal": true, "parameters": [ { @@ -14481,9 +14026,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "description": "Get the application version", "parameters": [ { @@ -14546,9 +14089,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "description": "Get Application Health Status", "parameters": [ { @@ -14775,9 +14316,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "description": "Get Aggregated Meta Info such as tableCount, dbViewCount, viewCount and etc.", "parameters": [ { @@ -14789,9 +14328,7 @@ "/api/v1/db/meta/cache": { "get": { "summary": "Get Cache", - "tags": [ - "Utils" - ], + "tags": ["Utils"], "responses": {}, "operationId": "utils-cache-get", "description": "Get All K/V pairs in NocoCache", @@ -14825,9 +14362,7 @@ } }, "description": "Delete All K/V pairs in NocoCache", - "tags": [ - "Utils" - ], + "tags": ["Utils"], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -14843,9 +14378,7 @@ "/api/v1/db/meta/projects/{baseId}/api-tokens": { "get": { "summary": "List API Tokens in Base", - "tags": [ - "API Token" - ], + "tags": ["API Token"], "responses": { "200": { "description": "OK", @@ -14935,9 +14468,7 @@ }, "description": "" }, - "tags": [ - "API Token" - ], + "tags": ["API Token"], "description": "Create API Token in a base", "parameters": [ { @@ -14984,9 +14515,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "API Token" - ], + "tags": ["API Token"], "description": "Delete the given API Token in base", "parameters": [ { @@ -15023,16 +14552,14 @@ "summary": "Attachment Upload", "operationId": "storage-upload", "responses": {}, - "tags": [ - "Storage" - ], + "tags": ["Storage"], "requestBody": { "content": { "multipart/form-data": { "schema": { - "type":"object", - "properties":{ - "files":{ + "type": "object", + "properties": { + "files": { "type": "array", "required": true, "items": { @@ -15047,9 +14574,9 @@ "files": [ { "mimetype": "image/jpeg", - "fieldname":"files", + "fieldname": "files", "originalname": "22bc-kavypmq4869759 (1).jpg", - "encoding":"7bit", + "encoding": "7bit", "size": 13052, "buffer": "" } @@ -15084,9 +14611,7 @@ "summary": "Attachment Upload by URL", "operationId": "storage-upload-by-url", "responses": {}, - "tags": [ - "Storage" - ], + "tags": ["Storage"], "requestBody": { "content": { "application/json": { @@ -15177,9 +14702,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "Auth" - ], + "tags": ["Auth"], "description": "Resend Invitation to a specific user", "parameters": [ { @@ -15204,9 +14727,7 @@ } } }, - "tags": [ - "Notification" - ], + "tags": ["Notification"], "description": "List notifications", "parameters": [ { @@ -15254,9 +14775,7 @@ } } }, - "tags": [ - "Notification" - ], + "tags": ["Notification"], "description": "Notificattion update" }, "delete": { @@ -15267,9 +14786,7 @@ "description": "OK" } }, - "tags": [ - "Notification" - ], + "tags": ["Notification"], "description": "Delete notification" }, "parameters": [ @@ -15292,9 +14809,7 @@ "description": "OK" } }, - "tags": [ - "Notification" - ], + "tags": ["Notification"], "description": "Mark all notifications as read" } }, @@ -15333,9 +14848,7 @@ } } }, - "tags": [ - "DB Table Column" - ], + "tags": ["DB Table Column"], "description": "Get columns hash for table", "parameters": [ { @@ -15377,11 +14890,7 @@ "properties": { "op": { "type": "string", - "enum": [ - "add", - "update", - "delete" - ], + "enum": ["add", "update", "delete"], "required": true }, "column": { @@ -15433,9 +14942,7 @@ } } }, - "tags": [ - "DB Table Column" - ], + "tags": ["DB Table Column"], "description": "Bulk create-update-delete columns", "parameters": [ { @@ -15468,9 +14975,7 @@ "summary": "List Table Rows", "operationId": "db-data-table-row-list", "description": "List all table rows in a given table", - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "parameters": [ { "schema": { @@ -15564,10 +15069,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "examples": { "Example 1": { @@ -15649,9 +15151,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "requestBody": { "content": { "application/json": { @@ -15704,9 +15204,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "requestBody": { "content": { "application/json": { @@ -15759,9 +15257,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "requestBody": { "content": { "application/json": { @@ -15831,9 +15327,7 @@ "summary": "Read Table Row", "operationId": "db-data-table-row-read", "description": "Get table row in a given table", - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "parameters": [ { "schema": { @@ -15918,9 +15412,7 @@ "summary": "Table Rows Count", "operationId": "db-data-table-row-count", "description": "Count of rows in a given table", - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "parameters": [ { "schema": { @@ -15962,10 +15454,7 @@ "type": "number" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "examples": { "Example 1": { @@ -16056,9 +15545,7 @@ "summary": "Get Nested Relations Rows", "operationId": "db-data-table-row-nested-list", "description": "Linked rows in a given Links/LinkToAnotherRecord column", - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "parameters": [ { "schema": { @@ -16152,10 +15639,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "examples": { "Example 1": { @@ -16237,9 +15721,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "requestBody": { "content": { "application/json": { @@ -16291,9 +15773,7 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": [ - "DB Data Table Row" - ], + "tags": ["DB Data Table Row"], "requestBody": { "content": { "application/json": { @@ -16330,6 +15810,75 @@ ] } }, + "/api/v2/tables/{tableId}/links/{columnId}/records": { + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "tableId", + "in": "path", + "required": true, + "description": "Table ID" + }, + { + "schema": { + "type": "string" + }, + "name": "viewId", + "in": "query", + "description": "View ID" + } + ], + "post": { + "summary": "Create Nest and delete nested Relations Rows", + "operationId": "db-data-table-row-nested-link-unlink", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": {} + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + } + }, + "tags": ["DB Data Table Row"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NestedLinkUnlinkReq" + }, + "examples": { + "Example 1": { + "value": [ + { + "rowId": 1, + "operation": "copy" + }, + { + "rowId": 2, + "operation": "paste" + } + ] + } + } + } + } + }, + "description": "Copy links from the row specified by the copy operation ID and paste them into the row identified by the paste operation ID.", + "parameters": [ + { + "$ref": "#/components/parameters/xc-auth" + } + ] + } + }, "/api/v1/command_palette": { "parameters": [], "post": { @@ -16345,9 +15894,7 @@ } } }, - "tags": [ - "Utils" - ], + "tags": ["Utils"], "requestBody": { "content": { "application/json": {} @@ -16361,9 +15908,7 @@ "summary": "Jobs Listen", "operationId": "jobs-listen", "description": "Listen for job events", - "tags": [ - "Jobs" - ], + "tags": ["Jobs"], "requestBody": { "content": { "application/json": { @@ -16385,9 +15930,7 @@ "summary": "Jobs Status", "operationId": "jobs-status", "description": "Get job status", - "tags": [ - "Jobs" - ], + "tags": ["Jobs"], "requestBody": { "content": { "application/json": { @@ -16531,10 +16074,7 @@ "description": "Model for Paginated" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "Attachment": { "description": "Model for Attachment", @@ -16611,7 +16151,7 @@ "type": "string", "description": "Attachment URL to be uploaded via upload-by-url" }, - "fileName":{ + "fileName": { "type": "string", "description": "The name of the attachment file name" } @@ -16626,9 +16166,9 @@ "x-examples": { "Example 1": { "mimetype": "image/jpeg", - "fieldname":"files", + "fieldname": "files", "originalname": "22bc-kavypmq4869759 (1).jpg", - "encoding":"7bit", + "encoding": "7bit", "size": 13052, "buffer": "" } @@ -17010,10 +16550,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "tty21vb01bfr0" } @@ -17080,9 +16617,7 @@ }, "Bool": { "description": "Model for Bool", - "examples": [ - true - ], + "examples": [true], "oneOf": [ { "description": "0 or 1", @@ -17497,10 +17032,7 @@ } } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "rsk9o5cs00wh5" } @@ -17552,9 +17084,7 @@ "type": "string" } }, - "required": [ - "title" - ] + "required": ["title"] } ], "description": "Model for Column Request", @@ -17630,10 +17160,7 @@ "example": "3" } }, - "required": [ - "fk_model_id", - "row_id" - ], + "required": ["fk_model_id", "row_id"], "x-stoplight": { "id": "ohotsd0vq6d8w" } @@ -17805,11 +17332,7 @@ }, "logical_op": { "description": "Logical Operator", - "enum": [ - "and", - "not", - "or" - ], + "enum": ["and", "not", "or"], "type": "string" }, "base_id": { @@ -17912,10 +17435,7 @@ } } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "wbc42cyev1qzt" } @@ -18007,10 +17527,7 @@ } } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "FilterReq": { "description": "Model for Filter Request", @@ -18117,11 +17634,7 @@ }, "logical_op": { "description": "Logical Operator", - "enum": [ - "and", - "not", - "or" - ], + "enum": ["and", "not", "or"], "type": "string" }, "value": { @@ -18226,11 +17739,7 @@ "example": "My Form" }, "lock_type": { - "enum": [ - "collaborative", - "locked", - "personal" - ], + "enum": ["collaborative", "locked", "personal"], "type": "string", "description": "Lock Type of this view", "example": "collaborative" @@ -18581,9 +18090,7 @@ }, "uidt": { "description": "UI Data Type", - "enum": [ - "Formula" - ], + "enum": ["Formula"], "type": "string" } }, @@ -18653,11 +18160,7 @@ "description": "Foreign Key to View" }, "lock_type": { - "enum": [ - "collaborative", - "locked", - "personal" - ], + "enum": ["collaborative", "locked", "personal"], "type": "string" }, "next_enabled": { @@ -19232,10 +18735,7 @@ "description": "Environment for the hook" }, "event": { - "enum": [ - "after", - "before" - ], + "enum": ["after", "before"], "type": "string", "description": "Event Type for the operation", "example": "after" @@ -19251,10 +18751,7 @@ }, "notification": { "description": "Hook Notification including info such as type, payload, method, body, and etc", - "type": [ - "object", - "string" - ] + "type": ["object", "string"] }, "operation": { "enum": [ @@ -19300,10 +18797,7 @@ }, "example": "v2", "description": "Hook Version", - "enum": [ - "v1", - "v2" - ] + "enum": ["v1", "v2"] } } }, @@ -19352,10 +18846,7 @@ "description": "Environment for the hook" }, "event": { - "enum": [ - "after", - "before" - ], + "enum": ["after", "before"], "type": "string", "description": "Event Type for the operation", "example": "after" @@ -19371,10 +18862,7 @@ }, "notification": { "description": "Hook Notification including info such as type, payload, method, body, and etc", - "type": [ - "object", - "string" - ] + "type": ["object", "string"] }, "operation": { "enum": [ @@ -19410,10 +18898,7 @@ "example": "My Webhook" }, "type": { - "type": [ - "string", - "null" - ], + "type": ["string", "null"], "description": "Hook Type" }, "condition": { @@ -19424,12 +18909,7 @@ "description": "Is this hook assoicated with some filters" } }, - "required": [ - "event", - "notification", - "operation", - "title" - ] + "required": ["event", "notification", "operation", "title"] }, "HookList": { "description": "Model for Hook List", @@ -19507,10 +18987,7 @@ "$ref": "#/components/schemas/Paginated" } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "oza9z6dpygn29" } @@ -19565,10 +19042,7 @@ "type": "string", "description": "Hook Event", "example": "after", - "enum": [ - "after", - "before" - ] + "enum": ["after", "before"] }, "execution_time": { "type": "string", @@ -19680,10 +19154,7 @@ "$ref": "#/components/schemas/Paginated" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "HookTestReq": { "description": "Model for Hook Test Request", @@ -19734,19 +19205,14 @@ "description": "Payload to be sent" } }, - "required": [ - "hook", - "payload" - ], + "required": ["hook", "payload"], "x-stoplight": { "id": "fmxwekzyi46za" } }, "Id": { "description": "Model for ID", - "examples": [ - "string" - ], + "examples": ["string"], "maxLength": 20, "minLength": 0, "title": "ID Model", @@ -20021,19 +19487,12 @@ "description": "The title of the virtual column" }, "type": { - "enum": [ - "bt", - "hm", - "mm" - ], + "enum": ["bt", "hm", "mm"], "type": "string", "description": "The type of the relationship" }, "uidt": { - "enum": [ - "LinkToAnotherRecord", - "Links" - ], + "enum": ["LinkToAnotherRecord", "Links"], "type": "string", "description": "Abstract type of the relationship" }, @@ -20042,13 +19501,7 @@ "description": "Is this relationship virtual?" } }, - "required": [ - "childId", - "parentId", - "title", - "type", - "uidt" - ], + "required": ["childId", "parentId", "title", "type", "uidt"], "title": "LinkToAnotherColumn Request Model", "type": "object", "x-stoplight": { @@ -20199,9 +19652,7 @@ "example": "My Lookup" }, "uidt": { - "enum": [ - "Lookup" - ], + "enum": ["Lookup"], "type": "string", "description": "UI DataType" } @@ -20370,9 +19821,7 @@ }, "Meta": { "description": "Model for Meta", - "examples": [ - {} - ], + "examples": [{}], "oneOf": [ { "type": "null" @@ -20613,9 +20062,7 @@ }, "title": "Normal Column Request Model", "type": "object", - "required": [ - "column_name" - ], + "required": ["column_name"], "x-stoplight": { "id": "fn3gqmojvswv2" } @@ -20634,10 +20081,7 @@ "type": "string" }, "roles": { - "enum": [ - "org-level-creator", - "org-level-viewer" - ], + "enum": ["org-level-creator", "org-level-viewer"], "type": "string", "description": "Roles for the base user" } @@ -20698,9 +20142,7 @@ "Password": { "description": "Model for Password", "example": "password123456789", - "examples": [ - "password123456789" - ], + "examples": ["password123456789"], "minLength": 8, "title": "Password Model", "type": "string", @@ -20728,10 +20170,7 @@ "type": "string" } }, - "required": [ - "currentPassword", - "newPassword" - ], + "required": ["currentPassword", "newPassword"], "title": "Password Change Request Model", "type": "object", "x-stoplight": { @@ -20752,9 +20191,7 @@ "type": "string" } }, - "required": [ - "email" - ], + "required": ["email"], "title": "Password Forgot Request Model", "type": "object", "x-stoplight": { @@ -20777,9 +20214,7 @@ "type": "string" } }, - "required": [ - "password" - ], + "required": ["password"], "title": "Password Reset Request Model", "type": "object", "x-stoplight": { @@ -20971,11 +20406,7 @@ "example": "Email" } }, - "required": [ - "title", - "input", - "category" - ], + "required": ["title", "input", "category"], "x-stoplight": { "id": "zrvjtpfx9wc54" } @@ -21059,11 +20490,7 @@ }, "type": { "type": "string", - "enum": [ - "database", - "documentation", - "dashboard" - ] + "enum": ["database", "documentation", "dashboard"] }, "linked_db_projects": { "description": "List of linked Database Projects that this base has access to (only used in Dashboard bases so far)", @@ -21176,10 +20603,7 @@ "description": "Pagination Info" } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "fr75wwwzt951h" } @@ -21236,11 +20660,7 @@ }, "type": { "type": "string", - "enum": [ - "database", - "documentation", - "dashboard" - ] + "enum": ["database", "documentation", "dashboard"] }, "linked_db_project_ids": { "description": "List of Linked Database Base IDs (only used for Dashboard Projects so far)", @@ -21250,9 +20670,7 @@ } } }, - "required": [ - "title" - ], + "required": ["title"], "title": "Base Request Model", "type": "object", "x-stoplight": { @@ -21345,10 +20763,7 @@ "description": "Base User Role" } }, - "required": [ - "email", - "roles" - ], + "required": ["email", "roles"], "x-stoplight": { "id": "3bvgqk9tn16ur" } @@ -21470,9 +20885,7 @@ "description": "Rollup Function" }, "uidt": { - "enum": [ - "Rollup" - ], + "enum": ["Rollup"], "type": "string", "description": "UI DataType" } @@ -21549,9 +20962,7 @@ } } }, - "required": [ - "options" - ], + "required": ["options"], "x-stoplight": { "id": "3rx8jyy2ufbc3" } @@ -21574,11 +20985,7 @@ "example": "password123" }, "roles": { - "enum": [ - "commenter", - "editor", - "viewer" - ], + "enum": ["commenter", "editor", "viewer"], "type": "string", "description": "The role given the target user", "example": "editor" @@ -21715,10 +21122,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "5gnbbmgal3om3" } @@ -21766,10 +21170,7 @@ "type": "string" } }, - "required": [ - "email", - "password" - ], + "required": ["email", "password"], "title": "Signin Request Model", "type": "object", "x-stoplight": { @@ -21831,10 +21232,7 @@ "description": "Ignore Subscription" } }, - "required": [ - "email", - "password" - ], + "required": ["email", "password"], "x-stoplight": { "id": "6ia1chyii9w48" } @@ -21874,10 +21272,7 @@ "direction": { "type": "string", "description": "Sort direction", - "enum": [ - "asc", - "desc" - ], + "enum": ["asc", "desc"], "example": "desc" }, "order": { @@ -21971,10 +21366,7 @@ } } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "us9qfo1go142f" } @@ -21997,10 +21389,7 @@ }, "direction": { "description": "Sort direction", - "enum": [ - "asc", - "desc" - ], + "enum": ["asc", "desc"], "type": "string" } }, @@ -22026,9 +21415,7 @@ }, "StringOrNull": { "description": "Model for StringOrNull", - "examples": [ - "string" - ], + "examples": ["string"], "oneOf": [ { "maxLength": 255, @@ -22045,9 +21432,7 @@ }, "StringOrNullOrBooleanOrNumber": { "description": "Model for StringOrNullOrBooleanOrNumber", - "examples": [ - "string" - ], + "examples": ["string"], "oneOf": [ { "type": "string" @@ -22488,10 +21873,7 @@ "type": "string" } }, - "required": [ - "table_name", - "title" - ], + "required": ["table_name", "title"], "x-stoplight": { "id": "dkfoyjcny5am9" } @@ -22621,10 +22003,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "urwk2euatlkjl" } @@ -22763,10 +22142,7 @@ "type": "string" } }, - "required": [ - "columns", - "table_name" - ], + "required": ["columns", "table_name"], "title": "Table Request Model", "type": "object", "x-stoplight": { @@ -22841,11 +22217,7 @@ "type": "string" } }, - "required": [ - "id", - "email", - "email_verified" - ], + "required": ["id", "email", "email_verified"], "x-stoplight": { "id": "hcruzlenrwb2x" } @@ -22976,10 +22348,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "32mz06s4tgptq" } @@ -23033,11 +22402,7 @@ }, "lock_type": { "description": "Lock Type of the view", - "enum": [ - "collaborative", - "locked", - "personal" - ], + "enum": ["collaborative", "locked", "personal"], "type": "string" }, "meta": { @@ -23101,12 +22466,7 @@ "description": "Associated View Model" } }, - "required": [ - "fk_model_id", - "show", - "title", - "type" - ], + "required": ["fk_model_id", "show", "title", "type"], "x-stoplight": { "id": "nobjewdlhxrkq" } @@ -23234,10 +22594,7 @@ "description": "Paginated Info" } }, - "required": [ - "list", - "pageInfo" - ], + "required": ["list", "pageInfo"], "x-stoplight": { "id": "a1f99jvpiuugl" } @@ -23309,9 +22666,7 @@ "description": "Foreign Key to Geo Data Column. Used in creating Map View." } }, - "required": [ - "title" - ] + "required": ["title"] }, "ViewUpdateReq": { "description": "Model for View Update Request", @@ -23357,11 +22712,7 @@ "example": "password123" }, "lock_type": { - "enum": [ - "collaborative", - "locked", - "personal" - ], + "enum": ["collaborative", "locked", "personal"], "type": "string", "description": "Lock type of View.", "example": "collaborative" @@ -23554,19 +22905,10 @@ "description": "The email address of the user who invited the recipient" } }, - "required": [ - "id", - "title", - "type", - "invited_by" - ] + "required": ["id", "title", "type", "invited_by"] } }, - "required": [ - "fk_user_id", - "type", - "body" - ] + "required": ["fk_user_id", "type", "body"] }, "ProjectEvent": { "type": "object", @@ -23594,18 +22936,10 @@ "description": "The type of the base" } }, - "required": [ - "id", - "title", - "type" - ] + "required": ["id", "title", "type"] } }, - "required": [ - "fk_user_id", - "type", - "body" - ] + "required": ["fk_user_id", "type", "body"] }, "WelcomeEvent": { "type": "object", @@ -23623,11 +22957,7 @@ "description": "An empty object" } }, - "required": [ - "fk_user_id", - "type", - "body" - ] + "required": ["fk_user_id", "type", "body"] }, "SortEvent": { "type": "object", @@ -23643,11 +22973,7 @@ "type": "object" } }, - "required": [ - "fk_user_id", - "type", - "body" - ] + "required": ["fk_user_id", "type", "body"] }, "FilterEvent": { "type": "object", @@ -23663,11 +22989,7 @@ "type": "object" } }, - "required": [ - "fk_user_id", - "type", - "body" - ] + "required": ["fk_user_id", "type", "body"] }, "TableEvent": { "type": "object", @@ -23700,19 +23022,10 @@ "description": "The ID of the table associated with the event" } }, - "required": [ - "title", - "base_id", - "source_id", - "id" - ] + "required": ["title", "base_id", "source_id", "id"] } }, - "required": [ - "fk_user_id", - "type", - "body" - ] + "required": ["fk_user_id", "type", "body"] }, "ViewEvent": { "type": "object", @@ -23749,20 +23062,10 @@ "description": "The ID of the model that the view is based on" } }, - "required": [ - "title", - "base_id", - "source_id", - "id", - "fk_model_id" - ] + "required": ["title", "base_id", "source_id", "id", "fk_model_id"] } }, - "required": [ - "fk_user_id", - "type", - "body" - ] + "required": ["fk_user_id", "type", "body"] }, "ColumnEvent": { "type": "object", @@ -23799,20 +23102,10 @@ "description": "The ID of the model that the column belongs to" } }, - "required": [ - "title", - "base_id", - "source_id", - "id", - "fk_model_id" - ] + "required": ["title", "base_id", "source_id", "id", "fk_model_id"] } }, - "required": [ - "fk_user_id", - "type", - "body" - ] + "required": ["fk_user_id", "type", "body"] }, "Notification": { "allOf": [ @@ -23877,8 +23170,7 @@ { "list": [ { - "body": { - }, + "body": {}, "type": "invite", "is_read": false, "is_deleted": false, @@ -23912,10 +23204,7 @@ "description": "Model for Paginated" } }, - "required": [ - "list", - "pageInfo" - ] + "required": ["list", "pageInfo"] }, "NotificationUpdate": { "type": "object", @@ -23945,6 +23234,22 @@ "required": false } } + }, + "NestedLinkUnlinkReq": { + "type": "array", + "items": { + "type": "object", + "properties": { + "operation": { + "type": "string", + "enum": ["copy", "paste"] + }, + "rowId": { + "type": "string" + } + }, + "required": ["operation", "rowId"] + } } }, "responses": { @@ -24364,9 +23669,7 @@ "example": "BadRequest [Error]: " } }, - "required": [ - "msg" - ] + "required": ["msg"] }, "examples": { "Example 1": { diff --git a/packages/nocodb/src/services/data-table.service.ts b/packages/nocodb/src/services/data-table.service.ts index 485c290731..a97dd00686 100644 --- a/packages/nocodb/src/services/data-table.service.ts +++ b/packages/nocodb/src/services/data-table.service.ts @@ -8,6 +8,7 @@ import getAst from '~/helpers/getAst'; import { PagedResponseImpl } from '~/helpers/PagedResponse'; import { Column, Model, Source, View } from '~/models'; import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2'; +import { validatePayload } from 'src/helpers'; @Injectable() export class DataTableService { @@ -443,6 +444,25 @@ export class DataTableService { return true; } + async nestedLinkUnlink(param: { + cookie: any; + viewId: string; + modelId: string; + columnId: string; + query: any; + data: { + operation: 'copy' | 'paste'; + rowId: string; + }[]; + }) { + validatePayload( + 'swagger.json#/components/schemas/NestedLinkUnlinkReq', + param.data, + ); + + return true; + } + private validateIds(rowIds: any[] | any) { if (Array.isArray(rowIds)) { const map = new Map(); diff --git a/packages/nocodb/src/utils/acl.ts b/packages/nocodb/src/utils/acl.ts index 83ae16bcdb..add5d3ac81 100644 --- a/packages/nocodb/src/utils/acl.ts +++ b/packages/nocodb/src/utils/acl.ts @@ -120,6 +120,7 @@ const permissionScopes = { 'nestedDataList', 'nestedDataLink', 'nestedDataUnlink', + 'nestedDataLinkUnlink', 'baseUserList', // Base API Tokens @@ -227,6 +228,7 @@ const rolePermissions: nestedDataLink: true, nestedDataUnlink: true, + nestedDataLinkUnlink: true, // TODO add ACL with base scope // upload: true, // uploadViaURL: true, From 16da34f7fc326abfb5009d137fe9d606ec93e9c9 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:21 +0000 Subject: [PATCH 05/19] feat(nocodb): copy paste link cell api --- .../src/controllers/data-table.controller.ts | 4 +- packages/nocodb/src/db/BaseModelSqlv2.ts | 5 +- packages/nocodb/src/schema/swagger.json | 7 +- .../nocodb/src/services/data-table.service.ts | 146 +++++++++++++++++- 4 files changed, 157 insertions(+), 5 deletions(-) diff --git a/packages/nocodb/src/controllers/data-table.controller.ts b/packages/nocodb/src/controllers/data-table.controller.ts index 9a3c5052c1..1d3e424fee 100644 --- a/packages/nocodb/src/controllers/data-table.controller.ts +++ b/packages/nocodb/src/controllers/data-table.controller.ts @@ -194,6 +194,7 @@ export class DataTableController { }); } + // todo: naming @Post(['/api/v2/tables/:modelId/links/:columnId/records']) @Acl('nestedDataLinkUnlink') async nestedLinkUnlink( @@ -205,10 +206,9 @@ export class DataTableController { data: { operation: 'copy' | 'paste'; rowId: string; + fk_related_model_id: string; }[], ) { - console.log('data', data); - return await this.dataTableService.nestedLinkUnlink({ modelId, query: req.query, diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index 14d822b269..cc6e0a88dd 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -1330,6 +1330,7 @@ class BaseModelSqlv2 { public async mmList( { colId, parentId }, args: { limit?; offset?; fieldsSet?: Set } = {}, + selectAllRecords = false ) { const { where, sort, ...rest } = this._getListArgs(args as any); const relColumn = (await this.model.getColumns()).find( @@ -1375,7 +1376,9 @@ class BaseModelSqlv2 { await this.applySortAndFilter({ table: childTable, where, qb, sort }); // todo: sanitize - qb.limit(+rest?.limit || 25); + if (!selectAllRecords) { + qb.limit(+rest?.limit || 25); + } qb.offset(+rest?.offset || 0); const children = await this.execAndParse(qb, await childTable.getColumns()); diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json index f9ab81d13f..d71179ea71 100644 --- a/packages/nocodb/src/schema/swagger.json +++ b/packages/nocodb/src/schema/swagger.json @@ -23237,6 +23237,8 @@ }, "NestedLinkUnlinkReq": { "type": "array", + "minItems": 2, + "maxItems": 2, "items": { "type": "object", "properties": { @@ -23246,9 +23248,12 @@ }, "rowId": { "type": "string" + }, + "fk_related_model_id":{ + "type": "string" } }, - "required": ["operation", "rowId"] + "required": ["operation", "rowId", "fk_related_model_id"] } } }, diff --git a/packages/nocodb/src/services/data-table.service.ts b/packages/nocodb/src/services/data-table.service.ts index a97dd00686..71a07bcfec 100644 --- a/packages/nocodb/src/services/data-table.service.ts +++ b/packages/nocodb/src/services/data-table.service.ts @@ -444,6 +444,7 @@ export class DataTableService { return true; } + // todo: naming & optimizing async nestedLinkUnlink(param: { cookie: any; viewId: string; @@ -453,6 +454,7 @@ export class DataTableService { data: { operation: 'copy' | 'paste'; rowId: string; + fk_related_model_id: string; }[]; }) { validatePayload( @@ -460,7 +462,124 @@ export class DataTableService { param.data, ); - return true; + if ( + param.data[0]?.fk_related_model_id !== param.data[1]?.fk_related_model_id + ) { + throw new Error( + 'The operation is not supported on different fk_related_model_id', + ); + } + + const operationMap = param.data.reduce( + (map, p) => { + map[p.operation] = p; + return map; + }, + {} as Record< + 'copy' | 'paste', + { + operation: 'copy' | 'paste'; + rowId: string; + fk_related_model_id: string; + } + >, + ); + + const { model, view } = await this.getModelAndView(param); + + const source = await Source.get(model.source_id); + + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: await NcConnectionMgrv2.get(source), + }); + + const existsCopyRow = await baseModel.exist(operationMap.copy.rowId); + const existsPasteRow = await baseModel.exist(operationMap.paste.rowId); + + if (!existsCopyRow && !existsPasteRow) { + NcError.notFound( + `Record with id '${operationMap.copy.rowId}' and '${operationMap.paste.rowId}' not found`, + ); + } else if (!existsCopyRow) { + NcError.notFound(`Record with id '${operationMap.copy.rowId}' not found`); + } else if (!existsPasteRow) { + NcError.notFound( + `Record with id '${operationMap.paste.rowId}' not found`, + ); + } + + const column = await this.getColumn(param); + const colOptions = await column.getColOptions(); + const relatedModel = await colOptions.getRelatedTable(); + await relatedModel.getColumns(); + + if (colOptions.type !== RelationTypes.MANY_TO_MANY) return; + + const { ast, dependencyFields } = await getAst({ + model: relatedModel, + query: param.query, + extractOnlyPrimaries: !(param.query?.f || param.query?.fields), + }); + + const listArgs: any = dependencyFields; + + try { + listArgs.filterArr = JSON.parse(listArgs.filterArrJson); + } catch (e) {} + + try { + listArgs.sortArr = JSON.parse(listArgs.sortArrJson); + } catch (e) {} + + const [copiedCellNestedList, pasteCellNestedList] = await Promise.all([ + baseModel.mmList( + { + colId: column.id, + parentId: operationMap.copy.rowId, + }, + listArgs as any, + true, + ), + baseModel.mmList( + { + colId: column.id, + parentId: operationMap.paste.rowId, + }, + listArgs as any, + true, + ), + ]); + + const filteredRowsToLink = this.filterAndMapRows( + copiedCellNestedList, + pasteCellNestedList, + relatedModel.primaryKeys, + ); + + const filteredRowsToUnlink = this.filterAndMapRows( + pasteCellNestedList, + copiedCellNestedList, + relatedModel.primaryKeys, + ); + + await Promise.all([ + baseModel.addLinks({ + colId: column.id, + childIds: filteredRowsToLink, + rowId: operationMap.paste.rowId, + cookie: param.cookie, + }), + baseModel.removeLinks({ + colId: column.id, + childIds: filteredRowsToUnlink, + rowId: operationMap.paste.rowId, + cookie: param.cookie, + }), + ]); + + return { link: filteredRowsToLink, unlink: filteredRowsToUnlink }; } private validateIds(rowIds: any[] | any) { @@ -485,4 +604,29 @@ export class DataTableService { NcError.unprocessableEntity('Invalid row id ' + rowIds); } } + + private filterAndMapRows( + sourceList: Record[], + targetList: Record[], + primaryKeys: Column[], + ): Record[] { + return sourceList + .filter( + (sourceRow: Record) => + !targetList.some((targetRow: Record) => + primaryKeys.every( + (key) => + sourceRow[key.title || key.column_name] === + targetRow[key.title || key.column_name], + ), + ), + ) + .map((item: Record) => + primaryKeys.reduce((acc, key) => { + acc[key.title || key.column_name] = + item[key.title || key.column_name]; + return acc; + }, {} as Record), + ); + } } From 3e0a9b9e8f790932c01968df788b94697b551783 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:21 +0000 Subject: [PATCH 06/19] feat: undo redo support for copy paste mm cell --- .../components/smartsheet/grid/Table.vue | 1 + .../useMultiSelect/convertCellData.ts | 37 +++- .../composables/useMultiSelect/index.ts | 173 ++++++++++-------- packages/nocodb/src/db/BaseModelSqlv2.ts | 2 +- .../nocodb/src/services/data-table.service.ts | 10 +- 5 files changed, 135 insertions(+), 88 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/grid/Table.vue b/packages/nc-gui/components/smartsheet/grid/Table.vue index 08d061c85f..9bc3f8896e 100644 --- a/packages/nc-gui/components/smartsheet/grid/Table.vue +++ b/packages/nc-gui/components/smartsheet/grid/Table.vue @@ -733,6 +733,7 @@ const { }, bulkUpdateRows, fillHandle, + view, ) function scrollToRow(row?: number) { diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index 824418bd47..2b3abf2eac 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -1,6 +1,6 @@ import dayjs from 'dayjs' -import type { ColumnType, SelectOptionsType } from 'nocodb-sdk' -import { UITypes } from 'nocodb-sdk' +import type { ColumnType, LinkToAnotherRecordType, SelectOptionsType } from 'nocodb-sdk' +import { RelationTypes, UITypes } from 'nocodb-sdk' import type { AppInfo } from '~/composables/useGlobal' import { parseProp } from '#imports' @@ -246,17 +246,42 @@ export default function convertCellData( return parsedVal || value } - case UITypes.LinkToAnotherRecord: - case UITypes.Links: { + case UITypes.LinkToAnotherRecord: { + if (isMultiple) { + return undefined + } + const parsedVal = typeof value === 'string' ? JSON.parse(value) : value if (!(parsedVal && typeof parsedVal === 'object' && !Array.isArray(parsedVal) && Object.keys(parsedVal))) { - throw new Error('Invalid LTAR data') + throw new Error(`Unsupported conversion for ${to}`) } + return parsedVal + } + case UITypes.Links: { if (isMultiple) { return undefined } - return parsedVal + + if ((column.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.MANY_TO_MANY) { + const parsedVal = typeof value === 'string' ? JSON.parse(value) : value + if ( + !( + parsedVal && + typeof parsedVal === 'object' && + !Array.isArray(parsedVal) && + // eslint-disable-next-line no-prototype-builtins + ['rowId', 'fk_related_model_id', 'value'].every((key) => (parsedVal as Object).hasOwnProperty(key)) + ) || + parsedVal?.fk_related_model_id !== (column.colOptions as LinkToAnotherRecordType).fk_related_model_id + ) { + throw new Error(`Unsupported conversion for ${to}`) + } + + return parsedVal + } else { + throw new Error(`Unsupported conversion for ${to}`) + } } case UITypes.Lookup: case UITypes.Rollup: diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 81b241ff6c..04a367d375 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -2,7 +2,7 @@ import type { Ref } from 'vue' import { computed } from 'vue' import dayjs from 'dayjs' import type { MaybeRef } from '@vueuse/core' -import type { ColumnType, LinkToAnotherRecordType, TableType, UserFieldRecordType } from 'nocodb-sdk' +import type { ColumnType, LinkToAnotherRecordType, TableType, UserFieldRecordType, ViewType } from 'nocodb-sdk' import { RelationTypes, UITypes, dateFormats, isDateMonthFormat, isSystemColumn, isVirtualCol, timeFormats } from 'nocodb-sdk' import { parse } from 'papaparse' import type { Cell } from './cellRange' @@ -27,6 +27,7 @@ import { useGlobal, useI18n, useMetas, + useUndoRedo, } from '#imports' const MAIN_MOUSE_PRESSED = 0 @@ -49,6 +50,7 @@ export function useMultiSelect( syncCellData?: Function, bulkUpdateRows?: Function, fillHandle?: MaybeRef, + view?: MaybeRef, ) { const meta = ref(_meta) @@ -66,12 +68,16 @@ export function useMultiSelect( const { api } = useApi() + const { addUndo, clone, defineViewScope } = useUndoRedo() + const editEnabled = ref(_editEnabled) const isMouseDown = ref(false) const isFillMode = ref(false) + const activeView = ref(view) + const selectedRange = reactive(new CellRange()) const fillRange = reactive(new CellRange()) @@ -226,7 +232,6 @@ export function useMultiSelect( ) { return JSON.stringify({ rowId: extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]), - columnId: columnObj.id, fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id, value: !isNaN(+textToCopy) ? +textToCopy : 0, }) @@ -866,7 +871,7 @@ export function useMultiSelect( (columnObj.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.BELONGS_TO ) { const clipboardContext = JSON.parse(clipboardData!) - let pasteVal = convertCellData( + const pasteVal = convertCellData( { value: clipboardContext, to: columnObj.uidt as UITypes, @@ -897,15 +902,9 @@ export function useMultiSelect( columnObj.uidt === UITypes.Links && (columnObj.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.MANY_TO_MANY ) { - const clipboardContext = JSON.parse(clipboardData) - if (clipboardContext?.fk_related_model_id !== (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id) { - throw new Error('Invalid paste data for MM LTAR cell') - return - } - - let pasteVal = convertCellData( + const pasteVal = convertCellData( { - value: clipboardContext, + value: clipboardData, to: columnObj.uidt as UITypes, column: columnObj, appInfo: unref(appInfo), @@ -913,75 +912,95 @@ export function useMultiSelect( isMysql(meta.value?.source_id), ) - console.log('paste data', clipboardContext, pasteVal) - const relatedTableMeta = await getMeta((columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id!) + if (pasteVal === undefined) return - const extractedPk = extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) - if (!extractedPk) return - - const [copiedCellchildrenList, pasteCellchildrenList] = await Promise.all([ - api.dbDataTableRow.nestedList( - meta.value?.id as string, - columnObj.id as string, - encodeURIComponent((clipboardContext.rowId as string) || ''), - ), - api.dbDataTableRow.nestedList( - meta.value?.id as string, - columnObj.id as string, - encodeURIComponent(extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) || ''), - ), - ]) - - const relatedTablePrimaryKeys = (extractPk(relatedTableMeta?.columns as ColumnType[]) || '').split('__') - - function filterAndMapRows( - sourceList: Record[], - targetList: Record[], - primaryKeys: string[] = relatedTablePrimaryKeys, - ): Record[] { - return sourceList - .filter( - (sourceRow: Record) => - !targetList.some((targetRow: Record) => - primaryKeys.every((key) => sourceRow[key] === targetRow[key]), - ), - ) - .map((item: Record) => - primaryKeys.reduce((acc, key) => { - acc[key] = item[key] - return acc - }, {} as Record), - ) + const pasteRowPk = extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) + if (!pasteRowPk) return + + const oldCellValue = rowObj.row[columnObj.title!] + + rowObj.row[columnObj.title!] = pasteVal.value + + let result + + try { + result = await api.dbDataTableRow.nestedLinkUnlink(meta.value?.id as string, columnObj.id as string, [ + { + operation: 'copy', + rowId: pasteVal.rowId, + fk_related_model_id: pasteVal.fk_related_model_id, + }, + { + operation: 'paste', + rowId: pasteRowPk, + fk_related_model_id: + (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id || pasteVal.fk_related_model_id, + }, + ]) + } catch { + rowObj.row[columnObj.title!] = oldCellValue + } + + if (result && result?.link && result?.unlink && Array.isArray(result.link) && Array.isArray(result.unlink)) { + addUndo({ + redo: { + fn: async ( + tableId: string, + columnId: string, + pasteRowPk: string, + result: { link: any[]; unlink: any[] }, + value: number, + activeCell: Nullable, + ) => { + await Promise.all([ + result.link.length && + api.dbDataTableRow.nestedLink(tableId, columnId, encodeURIComponent(pasteRowPk), result.link), + result.unlink.length && + api.dbDataTableRow.nestedUnlink( + meta.value?.id as string, + columnObj.id as string, + encodeURIComponent(pasteRowPk), + result.unlink, + ), + ]) + + rowObj.row[columnObj.title!] = value + + await syncCellData?.(activeCell) + }, + args: [meta.value?.id as string, columnObj.id as string, pasteRowPk, result, pasteVal.value, clone(activeCell)], + }, + undo: { + fn: async ( + tableId: string, + columnId: string, + pasteRowPk: string, + result: { link: any[]; unlink: any[] }, + value: number, + activeCell: Nullable, + ) => { + await Promise.all([ + result.unlink.length && + api.dbDataTableRow.nestedLink(tableId, columnId, encodeURIComponent(pasteRowPk), result.unlink), + result.link.length && + api.dbDataTableRow.nestedUnlink( + meta.value?.id as string, + columnObj.id as string, + encodeURIComponent(pasteRowPk), + result.link, + ), + ]) + + rowObj.row[columnObj.title!] = value + + await syncCellData?.(activeCell) + }, + args: [meta.value?.id as string, columnObj.id as string, pasteRowPk, result, oldCellValue, clone(activeCell)], + }, + scope: defineViewScope({ view: activeView?.value }), + }) } - const filteredRowsToLink = filterAndMapRows(copiedCellchildrenList.list, pasteCellchildrenList.list) - - const filteredRowsToUnlink = filterAndMapRows(pasteCellchildrenList.list, copiedCellchildrenList.list) - - console.log('copied cell child list', copiedCellchildrenList) - console.log('paste cell child list', pasteCellchildrenList) - console.log('filtered', filteredRowsToLink, filteredRowsToUnlink) - - rowObj.row[columnObj.title!] = clipboardContext.value - - const result = await Promise.all([ - filteredRowsToLink.length && - api.dbDataTableRow.nestedLink( - meta.value?.id as string, - columnObj.id as string, - encodeURIComponent(extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) || ''), - filteredRowsToLink, - ), - filteredRowsToUnlink.length && - api.dbDataTableRow.nestedUnlink( - meta.value?.id as string, - columnObj.id as string, - encodeURIComponent(extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) || ''), - filteredRowsToUnlink, - ), - ]) - - console.log('result', result) return await syncCellData?.(activeCell) } diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index cc6e0a88dd..7ec561ab05 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -1330,7 +1330,7 @@ class BaseModelSqlv2 { public async mmList( { colId, parentId }, args: { limit?; offset?; fieldsSet?: Set } = {}, - selectAllRecords = false + selectAllRecords = false, ) { const { where, sort, ...rest } = this._getListArgs(args as any); const relColumn = (await this.model.getColumns()).find( diff --git a/packages/nocodb/src/services/data-table.service.ts b/packages/nocodb/src/services/data-table.service.ts index 71a07bcfec..26471ae61c 100644 --- a/packages/nocodb/src/services/data-table.service.ts +++ b/packages/nocodb/src/services/data-table.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import { isLinksOrLTAR, RelationTypes } from 'nocodb-sdk'; import { nocoExecute } from 'nc-help'; +import { validatePayload } from 'src/helpers'; import type { LinkToAnotherRecordColumn } from '~/models'; import { DatasService } from '~/services/datas.service'; import { NcError } from '~/helpers/catchError'; @@ -8,7 +9,6 @@ import getAst from '~/helpers/getAst'; import { PagedResponseImpl } from '~/helpers/PagedResponse'; import { Column, Model, Source, View } from '~/models'; import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2'; -import { validatePayload } from 'src/helpers'; @Injectable() export class DataTableService { @@ -495,8 +495,10 @@ export class DataTableService { dbDriver: await NcConnectionMgrv2.get(source), }); - const existsCopyRow = await baseModel.exist(operationMap.copy.rowId); - const existsPasteRow = await baseModel.exist(operationMap.paste.rowId); + const [existsCopyRow, existsPasteRow] = await Promise.all([ + baseModel.exist(operationMap.copy.rowId), + baseModel.exist(operationMap.paste.rowId), + ]); if (!existsCopyRow && !existsPasteRow) { NcError.notFound( @@ -517,7 +519,7 @@ export class DataTableService { if (colOptions.type !== RelationTypes.MANY_TO_MANY) return; - const { ast, dependencyFields } = await getAst({ + const { dependencyFields } = await getAst({ model: relatedModel, query: param.query, extractOnlyPrimaries: !(param.query?.f || param.query?.fields), From b65240b6b25b813b0c3d6bedacf1cc4e703f702f Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:21 +0000 Subject: [PATCH 07/19] fix: copy paste mm cell from different where relatedTableModelId is same --- .../useMultiSelect/convertCellData.ts | 2 +- .../composables/useMultiSelect/index.ts | 9 ++++++ .../src/controllers/data-table.controller.ts | 1 + packages/nocodb/src/schema/swagger.json | 5 +++- .../nocodb/src/services/data-table.service.ts | 30 +++++++++++-------- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index 2b3abf2eac..5a6c01530a 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -271,7 +271,7 @@ export default function convertCellData( typeof parsedVal === 'object' && !Array.isArray(parsedVal) && // eslint-disable-next-line no-prototype-builtins - ['rowId', 'fk_related_model_id', 'value'].every((key) => (parsedVal as Object).hasOwnProperty(key)) + ['rowId', 'columnId', 'fk_related_model_id', 'value'].every((key) => (parsedVal as Object).hasOwnProperty(key)) ) || parsedVal?.fk_related_model_id !== (column.colOptions as LinkToAnotherRecordType).fk_related_model_id ) { diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 04a367d375..d41ac0f826 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -232,6 +232,7 @@ export function useMultiSelect( ) { return JSON.stringify({ rowId: extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]), + columnId: columnObj.id, fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id, value: !isNaN(+textToCopy) ? +textToCopy : 0, }) @@ -923,16 +924,20 @@ export function useMultiSelect( let result + console.log('column', columnObj.id) + try { result = await api.dbDataTableRow.nestedLinkUnlink(meta.value?.id as string, columnObj.id as string, [ { operation: 'copy', rowId: pasteVal.rowId, + columnId: pasteVal.columnId, fk_related_model_id: pasteVal.fk_related_model_id, }, { operation: 'paste', rowId: pasteRowPk, + columnId: pasteVal.columnId, fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id || pasteVal.fk_related_model_id, }, @@ -942,6 +947,10 @@ export function useMultiSelect( } if (result && result?.link && result?.unlink && Array.isArray(result.link) && Array.isArray(result.unlink)) { + if (!result.link.length && !result.unlink.length) { + rowObj.row[columnObj.title!] = oldCellValue + return + } addUndo({ redo: { fn: async ( diff --git a/packages/nocodb/src/controllers/data-table.controller.ts b/packages/nocodb/src/controllers/data-table.controller.ts index 1d3e424fee..acf72af3e5 100644 --- a/packages/nocodb/src/controllers/data-table.controller.ts +++ b/packages/nocodb/src/controllers/data-table.controller.ts @@ -206,6 +206,7 @@ export class DataTableController { data: { operation: 'copy' | 'paste'; rowId: string; + columnId: string; fk_related_model_id: string; }[], ) { diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json index d71179ea71..a5d9db01ed 100644 --- a/packages/nocodb/src/schema/swagger.json +++ b/packages/nocodb/src/schema/swagger.json @@ -23249,11 +23249,14 @@ "rowId": { "type": "string" }, + "columnId":{ + "type": "string" + }, "fk_related_model_id":{ "type": "string" } }, - "required": ["operation", "rowId", "fk_related_model_id"] + "required": ["operation", "rowId", "columnId", "fk_related_model_id"] } } }, diff --git a/packages/nocodb/src/services/data-table.service.ts b/packages/nocodb/src/services/data-table.service.ts index 26471ae61c..f0be837e52 100644 --- a/packages/nocodb/src/services/data-table.service.ts +++ b/packages/nocodb/src/services/data-table.service.ts @@ -454,6 +454,7 @@ export class DataTableService { data: { operation: 'copy' | 'paste'; rowId: string; + columnId: string; fk_related_model_id: string; }[]; }) { @@ -480,6 +481,7 @@ export class DataTableService { { operation: 'copy' | 'paste'; rowId: string; + columnId: string; fk_related_model_id: string; } >, @@ -538,7 +540,7 @@ export class DataTableService { const [copiedCellNestedList, pasteCellNestedList] = await Promise.all([ baseModel.mmList( { - colId: column.id, + colId: operationMap.copy.columnId, parentId: operationMap.copy.rowId, }, listArgs as any, @@ -567,18 +569,20 @@ export class DataTableService { ); await Promise.all([ - baseModel.addLinks({ - colId: column.id, - childIds: filteredRowsToLink, - rowId: operationMap.paste.rowId, - cookie: param.cookie, - }), - baseModel.removeLinks({ - colId: column.id, - childIds: filteredRowsToUnlink, - rowId: operationMap.paste.rowId, - cookie: param.cookie, - }), + filteredRowsToLink.length && + baseModel.addLinks({ + colId: column.id, + childIds: filteredRowsToLink, + rowId: operationMap.paste.rowId, + cookie: param.cookie, + }), + filteredRowsToUnlink.length && + baseModel.removeLinks({ + colId: column.id, + childIds: filteredRowsToUnlink, + rowId: operationMap.paste.rowId, + cookie: param.cookie, + }), ]); return { link: filteredRowsToLink, unlink: filteredRowsToUnlink }; From aed6b95bc1de29d7f4e7d90ba61864436db55a9e Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:21 +0000 Subject: [PATCH 08/19] fix(nc-gui): prevent paste bt cell value to different fk_related_model_id cell --- .../useMultiSelect/convertCellData.ts | 17 +++++++++++++---- .../nc-gui/composables/useMultiSelect/index.ts | 14 +++++++++++--- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index 5a6c01530a..97bad12d8a 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -251,12 +251,20 @@ export default function convertCellData( return undefined } - const parsedVal = typeof value === 'string' ? JSON.parse(value) : value - if (!(parsedVal && typeof parsedVal === 'object' && !Array.isArray(parsedVal) && Object.keys(parsedVal))) { + if ((column.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.MANY_TO_MANY) { + const parsedVal = typeof value === 'string' ? JSON.parse(value) : value + + if ( + !(parsedVal && typeof parsedVal === 'object' && !Array.isArray(parsedVal) && Object.keys(parsedVal)) || + parsedVal?.fk_related_model_id !== (column.colOptions as LinkToAnotherRecordType)?.fk_related_model_id + ) { + throw new Error(`Unsupported conversion for ${to}`) + } + + return parsedVal + } else { throw new Error(`Unsupported conversion for ${to}`) } - - return parsedVal } case UITypes.Links: { if (isMultiple) { @@ -265,6 +273,7 @@ export default function convertCellData( if ((column.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.MANY_TO_MANY) { const parsedVal = typeof value === 'string' ? JSON.parse(value) : value + if ( !( parsedVal && diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index d41ac0f826..398f7f4e8c 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -137,6 +137,15 @@ export function useMultiSelect( } } + if ( + typeof textToCopy === 'object' && + columnObj.uidt === UITypes.LinkToAnotherRecord && + (columnObj.colOptions as LinkToAnotherRecordType).type === RelationTypes.BELONGS_TO + ) { + // fk_related_model_id is used to prevent paste operation in different fk_related_model_id cell + textToCopy = { ...textToCopy, fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id } + } + if (typeof textToCopy === 'object') { textToCopy = JSON.stringify(textToCopy) } else { @@ -871,10 +880,9 @@ export function useMultiSelect( columnObj.uidt === UITypes.LinkToAnotherRecord && (columnObj.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.BELONGS_TO ) { - const clipboardContext = JSON.parse(clipboardData!) const pasteVal = convertCellData( { - value: clipboardContext, + value: clipboardData, to: columnObj.uidt as UITypes, column: columnObj, appInfo: unref(appInfo), @@ -894,7 +902,7 @@ export function useMultiSelect( if (!foreignKeyColumn) return - rowObj.row[foreignKeyColumn.title!] = extractPkFromRow(clipboardContext, (relatedTableMeta as any)!.columns!) + rowObj.row[foreignKeyColumn.title!] = extractPkFromRow(pasteVal, (relatedTableMeta as any)!.columns!) return await syncCellData?.({ ...activeCell, updatedColumnTitle: foreignKeyColumn.title }) } From fb6dacba480c3d1c8871c77c4e71a62fd936ae82 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:21 +0000 Subject: [PATCH 09/19] fix: renamed function name --- .../useMultiSelect/convertCellData.ts | 2 +- .../composables/useMultiSelect/index.ts | 46 +++++++++---------- .../src/controllers/data-table.controller.ts | 6 +-- packages/nocodb/src/schema/swagger.json | 40 ++++++++++++---- .../nocodb/src/services/data-table.service.ts | 4 +- packages/nocodb/src/utils/acl.ts | 4 +- 6 files changed, 60 insertions(+), 42 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index 97bad12d8a..aa51b2c2d1 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -251,7 +251,7 @@ export default function convertCellData( return undefined } - if ((column.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.MANY_TO_MANY) { + if ((column.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.BELONGS_TO) { const parsedVal = typeof value === 'string' ? JSON.parse(value) : value if ( diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 398f7f4e8c..cbd577cc8f 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -119,8 +119,6 @@ export function useMultiSelect( const valueToCopy = (rowObj: Row, columnObj: ColumnType) => { let textToCopy = (columnObj.title && rowObj.row[columnObj.title]) || '' - console.log('rowObj, columnObj', rowObj, columnObj) - if (columnObj.uidt === UITypes.Checkbox) { textToCopy = !!textToCopy } @@ -138,12 +136,27 @@ export function useMultiSelect( } if ( - typeof textToCopy === 'object' && columnObj.uidt === UITypes.LinkToAnotherRecord && (columnObj.colOptions as LinkToAnotherRecordType).type === RelationTypes.BELONGS_TO ) { // fk_related_model_id is used to prevent paste operation in different fk_related_model_id cell - textToCopy = { ...textToCopy, fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id } + textToCopy = { + rowId: extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]), + fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id, + value: textToCopy || null, + } + } + + if ( + columnObj.uidt === UITypes.Links && + (columnObj.colOptions as LinkToAnotherRecordType).type === RelationTypes.MANY_TO_MANY + ) { + textToCopy = { + rowId: extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]), + columnId: columnObj.id, + fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id, + value: !isNaN(+textToCopy) ? +textToCopy : 0, + } } if (typeof textToCopy === 'object') { @@ -235,18 +248,6 @@ export function useMultiSelect( textToCopy = `"${textToCopy.replace(/"/g, '\\"')}"` } - if ( - columnObj.uidt === UITypes.Links && - (columnObj.colOptions as LinkToAnotherRecordType).type === RelationTypes.MANY_TO_MANY - ) { - return JSON.stringify({ - rowId: extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]), - columnId: columnObj.id, - fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id, - value: !isNaN(+textToCopy) ? +textToCopy : 0, - }) - } - return textToCopy } @@ -892,17 +893,15 @@ export function useMultiSelect( if (pasteVal === undefined) return - rowObj.row[columnObj.title!] = pasteVal - const foreignKeyColumn = meta.value?.columns?.find( (column: ColumnType) => column.id === (columnObj.colOptions as LinkToAnotherRecordType)?.fk_child_column_id, ) - const relatedTableMeta = await getMeta((columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id!) - if (!foreignKeyColumn) return - rowObj.row[foreignKeyColumn.title!] = extractPkFromRow(pasteVal, (relatedTableMeta as any)!.columns!) + rowObj.row[columnObj.title!] = pasteVal?.value + + rowObj.row[foreignKeyColumn.title!] = pasteVal?.value ? pasteVal.rowId : null return await syncCellData?.({ ...activeCell, updatedColumnTitle: foreignKeyColumn.title }) } @@ -932,10 +931,8 @@ export function useMultiSelect( let result - console.log('column', columnObj.id) - try { - result = await api.dbDataTableRow.nestedLinkUnlink(meta.value?.id as string, columnObj.id as string, [ + result = await api.dbDataTableRow.nestedListCopyPaste(meta.value?.id as string, columnObj.id as string, [ { operation: 'copy', rowId: pasteVal.rowId, @@ -951,6 +948,7 @@ export function useMultiSelect( }, ]) } catch { + console.log('catch') rowObj.row[columnObj.title!] = oldCellValue } diff --git a/packages/nocodb/src/controllers/data-table.controller.ts b/packages/nocodb/src/controllers/data-table.controller.ts index acf72af3e5..a6c65b471b 100644 --- a/packages/nocodb/src/controllers/data-table.controller.ts +++ b/packages/nocodb/src/controllers/data-table.controller.ts @@ -196,8 +196,8 @@ export class DataTableController { // todo: naming @Post(['/api/v2/tables/:modelId/links/:columnId/records']) - @Acl('nestedDataLinkUnlink') - async nestedLinkUnlink( + @Acl('nestedDataListCopyPaste') + async nestedListCopyPaste( @Req() req: Request, @Param('modelId') modelId: string, @Query('viewId') viewId: string, @@ -210,7 +210,7 @@ export class DataTableController { fk_related_model_id: string; }[], ) { - return await this.dataTableService.nestedLinkUnlink({ + return await this.dataTableService.nestedListCopyPaste({ modelId, query: req.query, viewId, diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json index a5d9db01ed..b055ff7145 100644 --- a/packages/nocodb/src/schema/swagger.json +++ b/packages/nocodb/src/schema/swagger.json @@ -15831,14 +15831,30 @@ } ], "post": { - "summary": "Create Nest and delete nested Relations Rows", - "operationId": "db-data-table-row-nested-link-unlink", + "summary": "Copy paste nested link", + "operationId": "db-data-table-row-nested-list-copy-paste", "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": {} + }, + "examples": { + "Example 1" : { + "value": { + "link": [ + {"Id": 1}, + {"Id": 2}, + {"Id": 3}, + {"Id": 5}, + {"Id": 6}, + ], + "unlink": [ + {"Id": 4} + ] + } + } } } }, @@ -15852,26 +15868,30 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/NestedLinkUnlinkReq" + "$ref": "#/components/schemas/nestedListCopyPasteReq" }, "examples": { "Example 1": { "value": [ { - "rowId": 1, - "operation": "copy" + "operation": "copy", + "rowId": "1", + "columnId": "ca2ppiy8raidc09", + "fk_related_model_id": "m797s6vbrqvo2pv" }, { - "rowId": 2, - "operation": "paste" + "operation": "paste", + "rowId": "2", + "columnId": "ca2ppiy8raidc09", + "fk_related_model_id": "m797s6vbrqvo2pv" } - ] + ] } } } } }, - "description": "Copy links from the row specified by the copy operation ID and paste them into the row identified by the paste operation ID.", + "description": "Copy links from the one cell and paste them into another cell", "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -23235,7 +23255,7 @@ } } }, - "NestedLinkUnlinkReq": { + "nestedListCopyPasteReq": { "type": "array", "minItems": 2, "maxItems": 2, diff --git a/packages/nocodb/src/services/data-table.service.ts b/packages/nocodb/src/services/data-table.service.ts index f0be837e52..8b4d55f35d 100644 --- a/packages/nocodb/src/services/data-table.service.ts +++ b/packages/nocodb/src/services/data-table.service.ts @@ -445,7 +445,7 @@ export class DataTableService { } // todo: naming & optimizing - async nestedLinkUnlink(param: { + async nestedListCopyPaste(param: { cookie: any; viewId: string; modelId: string; @@ -459,7 +459,7 @@ export class DataTableService { }[]; }) { validatePayload( - 'swagger.json#/components/schemas/NestedLinkUnlinkReq', + 'swagger.json#/components/schemas/nestedListCopyPasteReq', param.data, ); diff --git a/packages/nocodb/src/utils/acl.ts b/packages/nocodb/src/utils/acl.ts index add5d3ac81..8173b464bf 100644 --- a/packages/nocodb/src/utils/acl.ts +++ b/packages/nocodb/src/utils/acl.ts @@ -120,7 +120,7 @@ const permissionScopes = { 'nestedDataList', 'nestedDataLink', 'nestedDataUnlink', - 'nestedDataLinkUnlink', + 'nestedListCopyPaste', 'baseUserList', // Base API Tokens @@ -228,7 +228,7 @@ const rolePermissions: nestedDataLink: true, nestedDataUnlink: true, - nestedDataLinkUnlink: true, + nestedListCopyPaste: true, // TODO add ACL with base scope // upload: true, // uploadViaURL: true, From 521272f6b1bbfca26558b2cc279dc7d8ca419ce6 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:22 +0000 Subject: [PATCH 10/19] chore: remove swagger file auto format changes --- packages/nocodb/src/schema/swagger.json | 1450 +++++++++++++++++------ 1 file changed, 1116 insertions(+), 334 deletions(-) diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json index b055ff7145..88180e1b23 100644 --- a/packages/nocodb/src/schema/swagger.json +++ b/packages/nocodb/src/schema/swagger.json @@ -11,15 +11,24 @@ "x-tagGroups": [ { "name": "Auth APIs", - "tags": ["Auth", "API Token"] + "tags": [ + "Auth", + "API Token" + ] }, { "name": "Public APIs", - "tags": ["Public"] + "tags": [ + "Public" + ] }, { "name": "Data APIs", - "tags": ["DB Table Row", "DB View Row", "Storage"] + "tags": [ + "DB Table Row", + "DB View Row", + "Storage" + ] }, { "name": "Meta APIs", @@ -41,7 +50,12 @@ }, { "name": "Organisation APIs", - "tags": ["Org App Settings", "Org License", "Org Tokens", "Org Users"] + "tags": [ + "Org App Settings", + "Org License", + "Org Tokens", + "Org Users" + ] } ], "servers": [ @@ -59,7 +73,9 @@ "$ref": "#/components/schemas/User" } }, - "tags": ["User profile"], + "tags": [ + "User profile" + ], "description": "Update User Profile", "requestBody": { "content": { @@ -144,7 +160,9 @@ } } }, - "tags": ["Auth"], + "tags": [ + "Auth" + ], "requestBody": { "content": { "application/json": { @@ -202,7 +220,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Auth"], + "tags": [ + "Auth" + ], "description": "Clear refresh token from the database and cookie." }, "parameters": [ @@ -244,7 +264,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Auth"], + "tags": [ + "Auth" + ], "requestBody": { "content": { "application/json": { @@ -306,7 +328,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Auth"], + "tags": [ + "Auth" + ], "description": "Returns authenticated user info", "parameters": [ { @@ -357,7 +381,9 @@ } }, "description": "Emails user with a reset url.", - "tags": ["Auth"], + "tags": [ + "Auth" + ], "requestBody": { "content": { "application/json": { @@ -415,7 +441,9 @@ } }, "description": "Change password of authenticated user with a new one.", - "tags": ["Auth"], + "tags": [ + "Auth" + ], "requestBody": { "content": { "application/json": { @@ -478,7 +506,9 @@ } }, "description": "Validate password reset url token.", - "tags": ["Auth"], + "tags": [ + "Auth" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -536,7 +566,9 @@ } }, "description": "Api for verifying email where token need to be passed which is shared to user email.", - "tags": ["Auth"], + "tags": [ + "Auth" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -594,7 +626,9 @@ } }, "description": "Update user password to new by using reset token.", - "tags": ["Auth"], + "tags": [ + "Auth" + ], "requestBody": { "content": { "application/json": { @@ -665,7 +699,9 @@ } }, "description": "Creates a new refresh token and JWT auth token for the user. The refresh token is sent as a cookie, while the JWT auth token is included in the response body.", - "tags": ["Auth"], + "tags": [ + "Auth" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -719,7 +755,9 @@ } }, "description": "List all organisation API tokens. Access with API tokens will be blocked.", - "tags": ["Org Tokens"], + "tags": [ + "Org Tokens" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -775,7 +813,9 @@ } } }, - "tags": ["Org Tokens"], + "tags": [ + "Org Tokens" + ], "description": "Creat an organisation API token. Access with API tokens will be blocked." } }, @@ -815,7 +855,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Org Tokens"], + "tags": [ + "Org Tokens" + ], "description": "Delete an organisation API token. Access with API tokens will be blocked.", "parameters": [ { @@ -857,7 +899,9 @@ } }, "description": "Get the application license key. Exclusive for super admin.", - "tags": ["Org License"], + "tags": [ + "Org License" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -919,7 +963,9 @@ } } }, - "tags": ["Org License"], + "tags": [ + "Org License" + ], "description": "Set the application license key. Exclusive for super admin.", "parameters": [ { @@ -962,7 +1008,9 @@ } }, "description": "Get the application settings. Exclusive for super admin.", - "tags": ["Org App Settings"], + "tags": [ + "Org App Settings" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -1031,7 +1079,9 @@ } } }, - "tags": ["Org App Settings"], + "tags": [ + "Org App Settings" + ], "description": "Update the application settings. Exclusive for super admin.", "parameters": [ { @@ -1083,7 +1133,9 @@ } }, "description": "List all organisation users. Exclusive for Super Admin. Access with API Tokens will be blocked.", - "tags": ["Org Users"], + "tags": [ + "Org Users" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -1155,7 +1207,9 @@ } } }, - "tags": ["Org Users"], + "tags": [ + "Org Users" + ], "description": "Create an organisation user. Exclusive for Super Admin. Access with API Tokens will be blocked.", "parameters": [ { @@ -1211,7 +1265,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Org Users"], + "tags": [ + "Org Users" + ], "description": "Update an organisation user by User ID. Exclusive for Super Admin. Access with API Tokens will be blocked.", "requestBody": { "content": { @@ -1267,7 +1323,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Org Users"], + "tags": [ + "Org Users" + ], "description": "Delete an organisation user by User ID. Exclusive for Super Admin. Access with API Tokens will be blocked." } }, @@ -1297,7 +1355,9 @@ } } }, - "tags": ["Org users"], + "tags": [ + "Org users" + ], "description": "Organisation User GetByUsername" } }, @@ -1349,7 +1409,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Org Users"], + "tags": [ + "Org Users" + ], "description": "Resend Invitation to a specific user. Exclusive for Super Admin. Access with API Tokens will be blocked.", "parameters": [ { @@ -1377,7 +1439,9 @@ "description": "OK" } }, - "tags": ["Org users"], + "tags": [ + "Org users" + ], "description": "Create Organisation User Profile", "requestBody": { "content": { @@ -1398,7 +1462,9 @@ } }, "description": "Get Organisation User Profile", - "tags": ["Org users"] + "tags": [ + "Org users" + ] }, "patch": { "summary": "", @@ -1409,7 +1475,9 @@ } }, "description": "Update Organisation User Profile\n", - "tags": ["Org users"], + "tags": [ + "Org users" + ], "requestBody": { "content": { "application/json": { @@ -1440,7 +1508,9 @@ "description": "OK" } }, - "tags": ["Org users"], + "tags": [ + "Org users" + ], "description": "Create Organisation User Follower Relationship (Follow)", "requestBody": { "content": { @@ -1461,7 +1531,9 @@ } }, "description": "List Organisation User Followers", - "tags": ["Org users"], + "tags": [ + "Org users" + ], "requestBody": { "content": { "application/json": { @@ -1480,7 +1552,9 @@ "description": "OK" } }, - "tags": ["Org users"], + "tags": [ + "Org users" + ], "description": "Delete Organisation User Follower Relationship (Unfollow)", "requestBody": { "content": { @@ -1514,7 +1588,9 @@ } }, "description": "List Organisation User Following", - "tags": ["Org users"] + "tags": [ + "Org users" + ] } }, "/api/v1/users/{userId}/isFollowing/{followerId}": { @@ -1545,7 +1621,9 @@ } }, "description": "Check if Organisation User is following someone", - "tags": ["Org users"] + "tags": [ + "Org users" + ] } }, "/api/v1/users/{userId}/generate-reset-url": { @@ -1564,7 +1642,9 @@ "post": { "summary": "Generate Organisation User Password Reset Token", "operationId": "org-users-generate-password-reset-token", - "tags": ["Org Users"], + "tags": [ + "Org Users" + ], "responses": { "200": { "description": "OK", @@ -1633,7 +1713,10 @@ "$ref": "#/components/schemas/Paginated" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] } } }, @@ -1670,7 +1753,9 @@ } }, "description": "List all users in the given base.", - "tags": ["Auth"], + "tags": [ + "Auth" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -1801,7 +1886,9 @@ } } }, - "tags": ["Auth"], + "tags": [ + "Auth" + ], "description": "Create a user and add it to the given base", "parameters": [ { @@ -1898,7 +1985,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Get info such as node version, arch, platform, is docker, rootdb and package version of a given base", "parameters": [ { @@ -1983,7 +2072,9 @@ } } }, - "tags": ["Auth"], + "tags": [ + "Auth" + ], "description": "Update a given user in a given base. Exclusive for Super Admin. Access with API Tokens will be blocked.", "parameters": [ { @@ -2026,7 +2117,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Auth"], + "tags": [ + "Auth" + ], "description": "Delete a given user in a given base. Exclusive for Super Admin. Access with API Tokens will be blocked.", "parameters": [ { @@ -2106,7 +2199,9 @@ } }, "description": "Hide / show views based on user role", - "tags": ["Base"], + "tags": [ + "Base" + ], "parameters": [ { "schema": { @@ -2176,7 +2271,9 @@ } } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Hide / show views based on user role", "parameters": [ { @@ -2260,7 +2357,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Base"] + "tags": [ + "Base" + ] }, "post": { "summary": "Create Base", @@ -2336,7 +2435,9 @@ } } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Create a new base", "parameters": [ { @@ -2416,7 +2517,9 @@ } } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Duplicate a base", "parameters": [ { @@ -2515,7 +2618,9 @@ } } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Duplicate a base", "parameters": [ { @@ -2558,7 +2663,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Base"], + "tags": [ + "Base" + ], "responses": { "200": { "description": "OK", @@ -2630,7 +2737,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Delete the given base", "parameters": [ { @@ -2662,7 +2771,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "requestBody": { "content": { "application/json": { @@ -2709,7 +2820,9 @@ "description": "OK" } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "requestBody": { "content": { "application/json": { @@ -2754,7 +2867,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Source"], + "tags": [ + "Source" + ], "responses": { "200": { "description": "OK", @@ -2811,7 +2926,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Source"], + "tags": [ + "Source" + ], "description": "Delete the source details of a given base", "parameters": [ { @@ -2856,7 +2973,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Source"], + "tags": [ + "Source" + ], "requestBody": { "content": { "application/json": { @@ -2929,7 +3048,9 @@ } } }, - "tags": ["Source"], + "tags": [ + "Source" + ], "requestBody": { "content": { "application/json": { @@ -2972,7 +3093,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Source"], + "tags": [ + "Source" + ], "responses": { "200": { "description": "OK", @@ -3075,7 +3198,9 @@ } } }, - "tags": ["Source"], + "tags": [ + "Source" + ], "description": "Create a new source on a given base", "parameters": [ { @@ -3106,7 +3231,9 @@ "post": { "summary": "share ERD view", "operationId": "source-share-erd", - "tags": ["Source"], + "tags": [ + "Source" + ], "responses": { "200": { "description": "OK", @@ -3128,7 +3255,9 @@ "description": "OK" } }, - "tags": ["Source"] + "tags": [ + "Source" + ] } }, "/api/v1/db/meta/projects/{baseId}/shared": { @@ -3154,7 +3283,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Base"], + "tags": [ + "Base" + ], "responses": { "200": { "description": "OK", @@ -3218,7 +3349,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Delete Base Shared Base", "parameters": [ { @@ -3252,7 +3385,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "requestBody": { "content": { "application/json": { @@ -3327,7 +3462,9 @@ } } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Update Base Shared Base", "parameters": [ { @@ -3359,7 +3496,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Base"], + "tags": [ + "Base" + ], "responses": { "200": { "description": "OK", @@ -3778,7 +3917,9 @@ } } }, - "tags": ["DB Table"], + "tags": [ + "DB Table" + ], "description": "Create a new table in a given base", "parameters": [ { @@ -3830,7 +3971,9 @@ "name": "includeM2M" } ], - "tags": ["DB Table"], + "tags": [ + "DB Table" + ], "description": "List all tables in a given base" } }, @@ -4224,7 +4367,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table"], + "tags": [ + "DB Table" + ], "description": "Read the table meta data by the given table ID", "parameters": [ { @@ -4266,7 +4411,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table"], + "tags": [ + "DB Table" + ], "requestBody": { "content": { "application/json": { @@ -4336,7 +4483,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table"], + "tags": [ + "DB Table" + ], "description": "Delete the table meta data by the given table ID", "parameters": [ { @@ -4408,7 +4557,9 @@ } } }, - "tags": ["DB Table"], + "tags": [ + "DB Table" + ], "description": "Duplicate a table", "parameters": [ { @@ -4496,7 +4647,9 @@ } } }, - "tags": ["DB Table"], + "tags": [ + "DB Table" + ], "description": "Duplicate a column", "parameters": [ { @@ -4595,7 +4748,9 @@ "name": "includeM2M" } ], - "tags": ["Source"], + "tags": [ + "Source" + ], "description": "List all tables in a given Base and Source" }, "post": { @@ -5085,7 +5240,9 @@ } } }, - "tags": ["Source"], + "tags": [ + "Source" + ], "description": "Create a new table in a given Base and Source", "parameters": [ { @@ -5152,7 +5309,9 @@ } } }, - "tags": ["DB Table"], + "tags": [ + "DB Table" + ], "description": "Update the order of the given Table", "parameters": [ { @@ -5233,7 +5392,9 @@ } } }, - "tags": ["DB Table Column"], + "tags": [ + "DB Table Column" + ], "description": "Create a new column in a given Table", "parameters": [ { @@ -5280,7 +5441,9 @@ } } }, - "tags": ["DB Table Column"], + "tags": [ + "DB Table Column" + ], "description": "Update the existing column by the given column ID", "parameters": [ { @@ -5299,7 +5462,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Column"], + "tags": [ + "DB Table Column" + ], "description": "Delete the existing column by the given column ID", "parameters": [ { @@ -5318,7 +5483,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Column"], + "tags": [ + "DB Table Column" + ], "description": "Get the existing column by the given column ID", "parameters": [ { @@ -5361,7 +5528,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Column"], + "tags": [ + "DB Table Column" + ], "description": "Set a primary value on a given column", "parameters": [ { @@ -5481,7 +5650,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "List all views in a given Table.", "parameters": [ { @@ -5565,7 +5736,9 @@ } } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "Update the view with the given view Id.", "parameters": [ { @@ -5596,7 +5769,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "Delete the view with the given view Id.", "parameters": [ { @@ -5641,7 +5816,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "Show All Columns in a given View", "parameters": [ { @@ -5693,7 +5870,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "parameters": [ { "schema": { @@ -5784,7 +5963,9 @@ } }, "description": "List all shared views in a given Table", - "tags": ["DB View Share"], + "tags": [ + "DB View Share" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -5831,7 +6012,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View Share"], + "tags": [ + "DB View Share" + ], "description": "Create a shared view in a given View..", "parameters": [ { @@ -5867,7 +6050,9 @@ }, "description": "" }, - "tags": ["DB View Share"], + "tags": [ + "DB View Share" + ], "description": "Update a shared view in a given View..", "parameters": [ { @@ -5899,7 +6084,9 @@ } }, "description": "Delete a shared view in a given View.", - "tags": ["DB View Share"], + "tags": [ + "DB View Share" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -5989,7 +6176,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View Column"], + "tags": [ + "DB View Column" + ], "description": "List all columns by ViewID", "parameters": [ { @@ -6055,7 +6244,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View Column"], + "tags": [ + "DB View Column" + ], "requestBody": { "content": { "application/json": { @@ -6128,7 +6319,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View Column"], + "tags": [ + "DB View Column" + ], "requestBody": { "content": { "application/json": { @@ -6209,7 +6402,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Sort"], + "tags": [ + "DB Table Sort" + ], "description": "List all the sort data in a given View", "parameters": [ { @@ -6240,7 +6435,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Sort"], + "tags": [ + "DB Table Sort" + ], "requestBody": { "content": { "application/json": { @@ -6316,7 +6513,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Sort"], + "tags": [ + "DB Table Sort" + ], "description": "Get the sort data by Sort ID", "parameters": [ { @@ -6348,7 +6547,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Sort"], + "tags": [ + "DB Table Sort" + ], "requestBody": { "content": { "application/json": { @@ -6396,7 +6597,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Sort"], + "tags": [ + "DB Table Sort" + ], "description": "Delete the sort data by Sort ID", "parameters": [ { @@ -6468,7 +6671,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Filter"], + "tags": [ + "DB Table Filter" + ], "description": "Get the filter data in a given View", "parameters": [ { @@ -6515,7 +6720,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Filter"], + "tags": [ + "DB Table Filter" + ], "requestBody": { "content": { "application/json": { @@ -6608,7 +6815,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Webhook Filter"], + "tags": [ + "DB Table Webhook Filter" + ], "description": "Get the filter data in a given Hook", "parameters": [ { @@ -6655,7 +6864,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Webhook Filter"], + "tags": [ + "DB Table Webhook Filter" + ], "requestBody": { "content": { "application/json": { @@ -6746,7 +6957,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Webhook Logs"], + "tags": [ + "DB Table Webhook Logs" + ], "description": "List the log data in a given Hook", "parameters": [ { @@ -6823,7 +7036,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Filter"], + "tags": [ + "DB Table Filter" + ], "description": "Get the filter data with a given Filter ID", "parameters": [ { @@ -6854,7 +7069,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Filter"], + "tags": [ + "DB Table Filter" + ], "requestBody": { "content": { "application/json": { @@ -6906,7 +7123,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Filter"], + "tags": [ + "DB Table Filter" + ], "description": "Delete the filter data with a given Filter ID", "parameters": [ { @@ -6978,7 +7197,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Filter"], + "tags": [ + "DB Table Filter" + ], "description": "Get Filter Group Children of a given group ID", "parameters": [ { @@ -7041,7 +7262,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7125,7 +7348,9 @@ } }, "description": "Create a new form view in a given Table", - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7189,7 +7414,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7283,7 +7510,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "Get the form data by Form ID", "parameters": [ { @@ -7337,7 +7566,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7391,7 +7622,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7468,7 +7701,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "List all columns in the given Grid", "parameters": [ { @@ -7514,7 +7749,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7594,7 +7831,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7658,7 +7897,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7701,7 +7942,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "Get the Gallery View data with Gallery ID", "parameters": [ { @@ -7764,7 +8007,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7829,7 +8074,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -7915,7 +8162,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "Get the Kanban View data by Kanban ID", "parameters": [ { @@ -7978,7 +8227,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -8044,7 +8295,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "requestBody": { "content": { "application/json": { @@ -8087,7 +8340,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View"], + "tags": [ + "DB View" + ], "description": "Get the Map View data by Map ID", "parameters": [ { @@ -8144,7 +8399,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Base"], + "tags": [ + "Base" + ], "description": "Synchronise the meta data difference between NC_DB and external data sources ", "parameters": [ { @@ -8163,7 +8420,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Base"], + "tags": [ + "Base" + ], "responses": { "200": { "description": "OK", @@ -8322,7 +8581,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Source"], + "tags": [ + "Source" + ], "description": "Synchronise the meta data difference between NC_DB and external data sources in a given Source", "parameters": [ { @@ -8338,7 +8599,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Source"], + "tags": [ + "Source" + ], "responses": { "200": { "description": "OK", @@ -8461,7 +8724,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Base"], + "tags": [ + "Base" + ], "responses": { "200": { "description": "OK", @@ -8513,7 +8778,9 @@ "summary": "List Table Rows", "operationId": "db-table-row-list", "description": "List all table rows in a given table and base", - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "schema": { @@ -8616,7 +8883,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "examples": { "Example 1": { @@ -8698,7 +8968,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "requestBody": { "content": { "application/json": { @@ -8760,7 +9032,9 @@ "summary": "Find One Table Row", "operationId": "db-table-row-find-one", "description": "Return the first result of the target Table Row", - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "schema": { @@ -8856,7 +9130,9 @@ "summary": "Group By Table Row", "operationId": "db-table-row-group-by", "description": "Get the result grouped by the given query", - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "schema": { @@ -8961,7 +9237,9 @@ "summary": "Table Group by Column", "operationId": "db-view-row-grouped-data-list", "description": "Get the grouped data By Column ID. Used in Kanban View.", - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "parameters": [ { "schema": { @@ -9127,7 +9405,9 @@ "summary": "Table Group by Column", "operationId": "db-table-row-grouped-data-list", "description": "Get the grouped data By Column ID. Used in Kanban View.", - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "schema": { @@ -9288,7 +9568,9 @@ "summary": "List Table View Rows", "operationId": "db-view-row-list", "description": "List all table view rows", - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "parameters": [ { "schema": { @@ -9357,7 +9639,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "examples": { "Example 1": { @@ -9452,7 +9737,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "requestBody": { "content": { "application/json": { @@ -9515,7 +9802,9 @@ "summary": "Find One Table View Row", "operationId": "db-view-row-find-one", "description": "Return the first result of table view rows with the given query", - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "parameters": [ { "schema": { @@ -9625,7 +9914,9 @@ "summary": "Group By Table View Row", "operationId": "db-view-row-group-by", "description": "Get the table view rows grouped by the given query", - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "parameters": [ { "schema": { @@ -9720,7 +10011,9 @@ "summary": "Count Table View Rows", "operationId": "db-view-row-count", "description": "Count how many rows in the given Table View", - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "parameters": [ { "schema": { @@ -9847,7 +10140,9 @@ } }, "description": "Get the target Table View Row", - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -9882,7 +10177,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "requestBody": { "content": { "application/json": { @@ -9929,7 +10226,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "description": "Delete the target Table View Row", "parameters": [ { @@ -10009,7 +10308,9 @@ } }, "description": "Check row with provided primary key exists or not", - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -10095,7 +10396,9 @@ } }, "description": "Get the Table Row by Row ID", - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -10130,7 +10433,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "requestBody": { "content": { "application/json": { @@ -10177,7 +10482,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "description": "Delete the Table Row", "parameters": [ { @@ -10249,7 +10556,9 @@ } }, "description": "check row with provided primary key exists or not", - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -10332,7 +10641,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "requestBody": { "content": { "application/json": { @@ -10389,7 +10700,10 @@ }, "examples": { "Example 1": { - "value": [1, 1] + "value": [ + 1, + 1 + ] } } } @@ -10399,7 +10713,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "requestBody": { "content": { "application/json": { @@ -10456,7 +10772,10 @@ }, "examples": { "Example 1": { - "value": [1, 1] + "value": [ + 1, + 1 + ] } } } @@ -10466,7 +10785,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "requestBody": { "content": { "application/json": { @@ -10575,7 +10896,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "requestBody": { "content": { "application/json": { @@ -10618,7 +10941,10 @@ }, "examples": { "Example 1": { - "value": [1, 1] + "value": [ + 1, + 1 + ] } } } @@ -10628,7 +10954,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "requestBody": { "content": { "application/json": { @@ -10693,7 +11021,10 @@ { "schema": { "type": "string", - "enum": ["csv", "excel"] + "enum": [ + "csv", + "excel" + ] }, "name": "type", "in": "path", @@ -10704,7 +11035,9 @@ "summary": "Export Table View Rows", "operationId": "db-view-row-export", "description": "Export Table View Rows by CSV or Excel", - "tags": ["DB View Row"], + "tags": [ + "DB View Row" + ], "wrapped": true, "responses": { "200": { @@ -10766,7 +11099,10 @@ { "schema": { "type": "string", - "enum": ["csv", "excel"] + "enum": [ + "csv", + "excel" + ] }, "name": "type", "in": "path", @@ -10777,7 +11113,9 @@ "summary": "Export Table View Rows", "operationId": "db-table-row-csv-export", "description": "Export Table View Rows by CSV or Excel", - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "wrapped": true, "responses": { "200": { @@ -10848,7 +11186,11 @@ { "schema": { "type": "string", - "enum": ["mm", "hm", "bt"] + "enum": [ + "mm", + "hm", + "bt" + ] }, "name": "relationType", "in": "path", @@ -10881,7 +11223,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "schema": { @@ -10954,7 +11298,11 @@ { "schema": { "type": "string", - "enum": ["mm", "hm", "bt"] + "enum": [ + "mm", + "hm", + "bt" + ] }, "name": "relationType", "in": "path", @@ -11011,7 +11359,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "schema": { @@ -11121,7 +11471,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "description": "Delete a new nested relations row", "parameters": [ { @@ -11171,7 +11523,11 @@ { "schema": { "type": "string", - "enum": ["mm", "hm", "bt"] + "enum": [ + "mm", + "hm", + "bt" + ] }, "name": "relationType", "in": "path", @@ -11202,7 +11558,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Row"], + "tags": [ + "DB Table Row" + ], "parameters": [ { "schema": { @@ -11295,7 +11653,10 @@ "id": "0xsi3jvwn7duo" }, "description": "the paginated result of the given key", - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "properties": { "list": { "type": "array", @@ -11320,7 +11681,10 @@ } } }, - "required": ["key", "value"] + "required": [ + "key", + "value" + ] } }, "examples": { @@ -11393,7 +11757,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Public"], + "tags": [ + "Public" + ], "parameters": [ { "schema": { @@ -11549,7 +11915,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Public"], + "tags": [ + "Public" + ], "parameters": [ { "schema": { @@ -11657,7 +12025,9 @@ }, "description": "" }, - "tags": ["Public"], + "tags": [ + "Public" + ], "parameters": [ { "schema": { @@ -11710,7 +12080,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Public"], + "tags": [ + "Public" + ], "parameters": [ { "schema": { @@ -11816,7 +12188,11 @@ { "schema": { "type": "string", - "enum": ["mm", "hm", "bt"] + "enum": [ + "mm", + "hm", + "bt" + ] }, "name": "relationType", "in": "path", @@ -11865,7 +12241,10 @@ "description": "Paginated info" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "examples": { "Example 1": { @@ -11907,7 +12286,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Public"], + "tags": [ + "Public" + ], "parameters": [ { "schema": { @@ -11996,7 +12377,10 @@ { "schema": { "type": "string", - "enum": ["csv", "excel"], + "enum": [ + "csv", + "excel" + ], "example": "csv" }, "name": "type", @@ -12031,7 +12415,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Public"] + "tags": [ + "Public" + ] } }, "/api/v1/db/public/shared-view/{sharedViewUuid}/nested/{columnName}": { @@ -12150,7 +12536,9 @@ "description": "Used for multiple filter queries" } ], - "tags": ["Public"], + "tags": [ + "Public" + ], "description": "List Nested Data Relation" } }, @@ -12204,7 +12592,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Public"] + "tags": [ + "Public" + ] } }, "/api/v1/db/public/shared-view/{sharedViewUuid}/meta": { @@ -12306,7 +12696,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Public"], + "tags": [ + "Public" + ], "description": "Get Share View Meta" } }, @@ -12324,7 +12716,9 @@ "get": { "summary": "", "operationId": "public-shared-erd-meta-get", - "tags": ["Public"], + "tags": [ + "Public" + ], "description": "", "parameters": [] } @@ -12359,7 +12753,9 @@ } } }, - "required": ["list"] + "required": [ + "list" + ] }, "examples": { "Example 1": { @@ -12445,7 +12841,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Utils"] + "tags": [ + "Utils" + ] }, "post": { "summary": "Comment Rows", @@ -12496,7 +12894,9 @@ } } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "description": "Create a new comment in a row. Logged in Audit.", "parameters": [ { @@ -12548,7 +12948,9 @@ } } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "description": "Update comment in Audit", "requestBody": { "content": { @@ -12607,7 +13009,10 @@ "example": "1" } }, - "required": ["count", "row_id"] + "required": [ + "count", + "row_id" + ] } }, "examples": { @@ -12648,7 +13053,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Utils"] + "tags": [ + "Utils" + ] } }, "/api/v1/db/meta/projects/{baseId}/audits": { @@ -12688,7 +13095,10 @@ "$ref": "#/components/schemas/Paginated" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] } } } @@ -12726,7 +13136,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Base"] + "tags": [ + "Base" + ] } }, "/api/v1/db/meta/audits/rows/{rowId}/update": { @@ -12772,7 +13184,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "requestBody": { "content": { "application/json": { @@ -12870,7 +13284,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["DB Table Webhook"] + "tags": [ + "DB Table Webhook" + ] }, "post": { "summary": "Create Table Hook", @@ -12941,7 +13357,9 @@ } } }, - "tags": ["DB Table Webhook"] + "tags": [ + "DB Table Webhook" + ] } }, "/api/v1/db/meta/tables/{tableId}/hooks/test": { @@ -12992,7 +13410,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Webhook"], + "tags": [ + "DB Table Webhook" + ], "requestBody": { "content": { "application/json": { @@ -13082,7 +13502,10 @@ { "schema": { "type": "string", - "enum": ["v1", "v2"] + "enum": [ + "v1", + "v2" + ] }, "name": "version", "in": "path", @@ -13135,7 +13558,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["DB Table Webhook"] + "tags": [ + "DB Table Webhook" + ] } }, "/api/v1/db/meta/hooks/{hookId}": { @@ -13189,7 +13614,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Webhook"], + "tags": [ + "DB Table Webhook" + ], "requestBody": { "content": { "application/json": { @@ -13249,7 +13676,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Table Webhook"], + "tags": [ + "DB Table Webhook" + ], "description": "Delete the exsiting hook by its ID", "parameters": [ { @@ -13301,7 +13730,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Plugin"] + "tags": [ + "Plugin" + ] } }, "/api/v1/db/meta/plugins/webhook": { @@ -13347,7 +13778,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Plugin"] + "tags": [ + "Plugin" + ] } }, "/api/v1/db/meta/plugins/{pluginTitle}/status": { @@ -13386,7 +13819,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Plugin"], + "tags": [ + "Plugin" + ], "x-internal": false } }, @@ -13418,7 +13853,9 @@ "$ref": "#/components/parameters/xc-auth" } ], - "tags": ["Plugin"], + "tags": [ + "Plugin" + ], "requestBody": { "content": { "application/json": { @@ -13467,7 +13904,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Plugin"], + "tags": [ + "Plugin" + ], "requestBody": { "content": { "application/json": { @@ -13503,7 +13942,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Plugin"], + "tags": [ + "Plugin" + ], "description": "Get the plugin data by ID", "x-internal": false } @@ -13555,7 +13996,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "requestBody": { "content": { "application/json": { @@ -13650,7 +14093,9 @@ } } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "requestBody": { "content": { "application/json": {} @@ -13668,7 +14113,9 @@ "post": { "summary": "Convert JDBC URL to Config", "operationId": "utils-url-to-config", - "tags": ["Utils"], + "tags": [ + "Utils" + ], "requestBody": { "content": { "application/json": { @@ -13886,7 +14333,11 @@ "x-stoplight": { "id": "uc3vaotye2eu8" }, - "enum": ["OFF", "ERROR", "ALL"], + "enum": [ + "OFF", + "ERROR", + "ALL" + ], "example": "OFF" } } @@ -13923,7 +14374,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "description": "Get the application info such as authType, defaultLimit, version and etc.", "parameters": [ { @@ -13967,7 +14420,9 @@ } } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "x-internal": true, "parameters": [ { @@ -14026,7 +14481,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "description": "Get the application version", "parameters": [ { @@ -14089,7 +14546,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "description": "Get Application Health Status", "parameters": [ { @@ -14316,7 +14775,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "description": "Get Aggregated Meta Info such as tableCount, dbViewCount, viewCount and etc.", "parameters": [ { @@ -14328,7 +14789,9 @@ "/api/v1/db/meta/cache": { "get": { "summary": "Get Cache", - "tags": ["Utils"], + "tags": [ + "Utils" + ], "responses": {}, "operationId": "utils-cache-get", "description": "Get All K/V pairs in NocoCache", @@ -14362,7 +14825,9 @@ } }, "description": "Delete All K/V pairs in NocoCache", - "tags": ["Utils"], + "tags": [ + "Utils" + ], "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -14378,7 +14843,9 @@ "/api/v1/db/meta/projects/{baseId}/api-tokens": { "get": { "summary": "List API Tokens in Base", - "tags": ["API Token"], + "tags": [ + "API Token" + ], "responses": { "200": { "description": "OK", @@ -14468,7 +14935,9 @@ }, "description": "" }, - "tags": ["API Token"], + "tags": [ + "API Token" + ], "description": "Create API Token in a base", "parameters": [ { @@ -14515,7 +14984,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["API Token"], + "tags": [ + "API Token" + ], "description": "Delete the given API Token in base", "parameters": [ { @@ -14552,14 +15023,16 @@ "summary": "Attachment Upload", "operationId": "storage-upload", "responses": {}, - "tags": ["Storage"], + "tags": [ + "Storage" + ], "requestBody": { "content": { "multipart/form-data": { "schema": { - "type": "object", - "properties": { - "files": { + "type":"object", + "properties":{ + "files":{ "type": "array", "required": true, "items": { @@ -14574,9 +15047,9 @@ "files": [ { "mimetype": "image/jpeg", - "fieldname": "files", + "fieldname":"files", "originalname": "22bc-kavypmq4869759 (1).jpg", - "encoding": "7bit", + "encoding":"7bit", "size": 13052, "buffer": "" } @@ -14611,7 +15084,9 @@ "summary": "Attachment Upload by URL", "operationId": "storage-upload-by-url", "responses": {}, - "tags": ["Storage"], + "tags": [ + "Storage" + ], "requestBody": { "content": { "application/json": { @@ -14702,7 +15177,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["Auth"], + "tags": [ + "Auth" + ], "description": "Resend Invitation to a specific user", "parameters": [ { @@ -14727,7 +15204,9 @@ } } }, - "tags": ["Notification"], + "tags": [ + "Notification" + ], "description": "List notifications", "parameters": [ { @@ -14775,7 +15254,9 @@ } } }, - "tags": ["Notification"], + "tags": [ + "Notification" + ], "description": "Notificattion update" }, "delete": { @@ -14786,7 +15267,9 @@ "description": "OK" } }, - "tags": ["Notification"], + "tags": [ + "Notification" + ], "description": "Delete notification" }, "parameters": [ @@ -14809,7 +15292,9 @@ "description": "OK" } }, - "tags": ["Notification"], + "tags": [ + "Notification" + ], "description": "Mark all notifications as read" } }, @@ -14848,7 +15333,9 @@ } } }, - "tags": ["DB Table Column"], + "tags": [ + "DB Table Column" + ], "description": "Get columns hash for table", "parameters": [ { @@ -14890,7 +15377,11 @@ "properties": { "op": { "type": "string", - "enum": ["add", "update", "delete"], + "enum": [ + "add", + "update", + "delete" + ], "required": true }, "column": { @@ -14942,7 +15433,9 @@ } } }, - "tags": ["DB Table Column"], + "tags": [ + "DB Table Column" + ], "description": "Bulk create-update-delete columns", "parameters": [ { @@ -14975,7 +15468,9 @@ "summary": "List Table Rows", "operationId": "db-data-table-row-list", "description": "List all table rows in a given table", - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "parameters": [ { "schema": { @@ -15069,7 +15564,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "examples": { "Example 1": { @@ -15151,7 +15649,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "requestBody": { "content": { "application/json": { @@ -15204,7 +15704,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "requestBody": { "content": { "application/json": { @@ -15257,7 +15759,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "requestBody": { "content": { "application/json": { @@ -15327,7 +15831,9 @@ "summary": "Read Table Row", "operationId": "db-data-table-row-read", "description": "Get table row in a given table", - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "parameters": [ { "schema": { @@ -15412,7 +15918,9 @@ "summary": "Table Rows Count", "operationId": "db-data-table-row-count", "description": "Count of rows in a given table", - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "parameters": [ { "schema": { @@ -15454,7 +15962,10 @@ "type": "number" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "examples": { "Example 1": { @@ -15545,7 +16056,9 @@ "summary": "Get Nested Relations Rows", "operationId": "db-data-table-row-nested-list", "description": "Linked rows in a given Links/LinkToAnotherRecord column", - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "parameters": [ { "schema": { @@ -15639,7 +16152,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "examples": { "Example 1": { @@ -15721,7 +16237,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "requestBody": { "content": { "application/json": { @@ -15773,7 +16291,9 @@ "$ref": "#/components/responses/BadRequest" } }, - "tags": ["DB Data Table Row"], + "tags": [ + "DB Data Table Row" + ], "requestBody": { "content": { "application/json": { @@ -15848,7 +16368,7 @@ {"Id": 2}, {"Id": 3}, {"Id": 5}, - {"Id": 6}, + {"Id": 6} ], "unlink": [ {"Id": 4} @@ -15885,7 +16405,7 @@ "columnId": "ca2ppiy8raidc09", "fk_related_model_id": "m797s6vbrqvo2pv" } - ] + ] } } } @@ -15914,7 +16434,9 @@ } } }, - "tags": ["Utils"], + "tags": [ + "Utils" + ], "requestBody": { "content": { "application/json": {} @@ -15928,7 +16450,9 @@ "summary": "Jobs Listen", "operationId": "jobs-listen", "description": "Listen for job events", - "tags": ["Jobs"], + "tags": [ + "Jobs" + ], "requestBody": { "content": { "application/json": { @@ -15950,7 +16474,9 @@ "summary": "Jobs Status", "operationId": "jobs-status", "description": "Get job status", - "tags": ["Jobs"], + "tags": [ + "Jobs" + ], "requestBody": { "content": { "application/json": { @@ -16094,7 +16620,10 @@ "description": "Model for Paginated" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "Attachment": { "description": "Model for Attachment", @@ -16171,7 +16700,7 @@ "type": "string", "description": "Attachment URL to be uploaded via upload-by-url" }, - "fileName": { + "fileName":{ "type": "string", "description": "The name of the attachment file name" } @@ -16186,9 +16715,9 @@ "x-examples": { "Example 1": { "mimetype": "image/jpeg", - "fieldname": "files", + "fieldname":"files", "originalname": "22bc-kavypmq4869759 (1).jpg", - "encoding": "7bit", + "encoding":"7bit", "size": 13052, "buffer": "" } @@ -16570,7 +17099,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "tty21vb01bfr0" } @@ -16637,7 +17169,9 @@ }, "Bool": { "description": "Model for Bool", - "examples": [true], + "examples": [ + true + ], "oneOf": [ { "description": "0 or 1", @@ -17052,7 +17586,10 @@ } } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "rsk9o5cs00wh5" } @@ -17104,7 +17641,9 @@ "type": "string" } }, - "required": ["title"] + "required": [ + "title" + ] } ], "description": "Model for Column Request", @@ -17180,7 +17719,10 @@ "example": "3" } }, - "required": ["fk_model_id", "row_id"], + "required": [ + "fk_model_id", + "row_id" + ], "x-stoplight": { "id": "ohotsd0vq6d8w" } @@ -17352,7 +17894,11 @@ }, "logical_op": { "description": "Logical Operator", - "enum": ["and", "not", "or"], + "enum": [ + "and", + "not", + "or" + ], "type": "string" }, "base_id": { @@ -17455,7 +18001,10 @@ } } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "wbc42cyev1qzt" } @@ -17547,7 +18096,10 @@ } } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "FilterReq": { "description": "Model for Filter Request", @@ -17654,7 +18206,11 @@ }, "logical_op": { "description": "Logical Operator", - "enum": ["and", "not", "or"], + "enum": [ + "and", + "not", + "or" + ], "type": "string" }, "value": { @@ -17759,7 +18315,11 @@ "example": "My Form" }, "lock_type": { - "enum": ["collaborative", "locked", "personal"], + "enum": [ + "collaborative", + "locked", + "personal" + ], "type": "string", "description": "Lock Type of this view", "example": "collaborative" @@ -18110,7 +18670,9 @@ }, "uidt": { "description": "UI Data Type", - "enum": ["Formula"], + "enum": [ + "Formula" + ], "type": "string" } }, @@ -18180,7 +18742,11 @@ "description": "Foreign Key to View" }, "lock_type": { - "enum": ["collaborative", "locked", "personal"], + "enum": [ + "collaborative", + "locked", + "personal" + ], "type": "string" }, "next_enabled": { @@ -18755,7 +19321,10 @@ "description": "Environment for the hook" }, "event": { - "enum": ["after", "before"], + "enum": [ + "after", + "before" + ], "type": "string", "description": "Event Type for the operation", "example": "after" @@ -18771,7 +19340,10 @@ }, "notification": { "description": "Hook Notification including info such as type, payload, method, body, and etc", - "type": ["object", "string"] + "type": [ + "object", + "string" + ] }, "operation": { "enum": [ @@ -18817,7 +19389,10 @@ }, "example": "v2", "description": "Hook Version", - "enum": ["v1", "v2"] + "enum": [ + "v1", + "v2" + ] } } }, @@ -18866,7 +19441,10 @@ "description": "Environment for the hook" }, "event": { - "enum": ["after", "before"], + "enum": [ + "after", + "before" + ], "type": "string", "description": "Event Type for the operation", "example": "after" @@ -18882,7 +19460,10 @@ }, "notification": { "description": "Hook Notification including info such as type, payload, method, body, and etc", - "type": ["object", "string"] + "type": [ + "object", + "string" + ] }, "operation": { "enum": [ @@ -18918,7 +19499,10 @@ "example": "My Webhook" }, "type": { - "type": ["string", "null"], + "type": [ + "string", + "null" + ], "description": "Hook Type" }, "condition": { @@ -18929,7 +19513,12 @@ "description": "Is this hook assoicated with some filters" } }, - "required": ["event", "notification", "operation", "title"] + "required": [ + "event", + "notification", + "operation", + "title" + ] }, "HookList": { "description": "Model for Hook List", @@ -19007,7 +19596,10 @@ "$ref": "#/components/schemas/Paginated" } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "oza9z6dpygn29" } @@ -19062,7 +19654,10 @@ "type": "string", "description": "Hook Event", "example": "after", - "enum": ["after", "before"] + "enum": [ + "after", + "before" + ] }, "execution_time": { "type": "string", @@ -19174,7 +19769,10 @@ "$ref": "#/components/schemas/Paginated" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "HookTestReq": { "description": "Model for Hook Test Request", @@ -19225,14 +19823,19 @@ "description": "Payload to be sent" } }, - "required": ["hook", "payload"], + "required": [ + "hook", + "payload" + ], "x-stoplight": { "id": "fmxwekzyi46za" } }, "Id": { "description": "Model for ID", - "examples": ["string"], + "examples": [ + "string" + ], "maxLength": 20, "minLength": 0, "title": "ID Model", @@ -19507,12 +20110,19 @@ "description": "The title of the virtual column" }, "type": { - "enum": ["bt", "hm", "mm"], + "enum": [ + "bt", + "hm", + "mm" + ], "type": "string", "description": "The type of the relationship" }, "uidt": { - "enum": ["LinkToAnotherRecord", "Links"], + "enum": [ + "LinkToAnotherRecord", + "Links" + ], "type": "string", "description": "Abstract type of the relationship" }, @@ -19521,7 +20131,13 @@ "description": "Is this relationship virtual?" } }, - "required": ["childId", "parentId", "title", "type", "uidt"], + "required": [ + "childId", + "parentId", + "title", + "type", + "uidt" + ], "title": "LinkToAnotherColumn Request Model", "type": "object", "x-stoplight": { @@ -19672,7 +20288,9 @@ "example": "My Lookup" }, "uidt": { - "enum": ["Lookup"], + "enum": [ + "Lookup" + ], "type": "string", "description": "UI DataType" } @@ -19841,7 +20459,9 @@ }, "Meta": { "description": "Model for Meta", - "examples": [{}], + "examples": [ + {} + ], "oneOf": [ { "type": "null" @@ -20082,7 +20702,9 @@ }, "title": "Normal Column Request Model", "type": "object", - "required": ["column_name"], + "required": [ + "column_name" + ], "x-stoplight": { "id": "fn3gqmojvswv2" } @@ -20101,7 +20723,10 @@ "type": "string" }, "roles": { - "enum": ["org-level-creator", "org-level-viewer"], + "enum": [ + "org-level-creator", + "org-level-viewer" + ], "type": "string", "description": "Roles for the base user" } @@ -20162,7 +20787,9 @@ "Password": { "description": "Model for Password", "example": "password123456789", - "examples": ["password123456789"], + "examples": [ + "password123456789" + ], "minLength": 8, "title": "Password Model", "type": "string", @@ -20190,7 +20817,10 @@ "type": "string" } }, - "required": ["currentPassword", "newPassword"], + "required": [ + "currentPassword", + "newPassword" + ], "title": "Password Change Request Model", "type": "object", "x-stoplight": { @@ -20211,7 +20841,9 @@ "type": "string" } }, - "required": ["email"], + "required": [ + "email" + ], "title": "Password Forgot Request Model", "type": "object", "x-stoplight": { @@ -20234,7 +20866,9 @@ "type": "string" } }, - "required": ["password"], + "required": [ + "password" + ], "title": "Password Reset Request Model", "type": "object", "x-stoplight": { @@ -20426,7 +21060,11 @@ "example": "Email" } }, - "required": ["title", "input", "category"], + "required": [ + "title", + "input", + "category" + ], "x-stoplight": { "id": "zrvjtpfx9wc54" } @@ -20510,7 +21148,11 @@ }, "type": { "type": "string", - "enum": ["database", "documentation", "dashboard"] + "enum": [ + "database", + "documentation", + "dashboard" + ] }, "linked_db_projects": { "description": "List of linked Database Projects that this base has access to (only used in Dashboard bases so far)", @@ -20623,7 +21265,10 @@ "description": "Pagination Info" } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "fr75wwwzt951h" } @@ -20680,7 +21325,11 @@ }, "type": { "type": "string", - "enum": ["database", "documentation", "dashboard"] + "enum": [ + "database", + "documentation", + "dashboard" + ] }, "linked_db_project_ids": { "description": "List of Linked Database Base IDs (only used for Dashboard Projects so far)", @@ -20690,7 +21339,9 @@ } } }, - "required": ["title"], + "required": [ + "title" + ], "title": "Base Request Model", "type": "object", "x-stoplight": { @@ -20783,7 +21434,10 @@ "description": "Base User Role" } }, - "required": ["email", "roles"], + "required": [ + "email", + "roles" + ], "x-stoplight": { "id": "3bvgqk9tn16ur" } @@ -20905,7 +21559,9 @@ "description": "Rollup Function" }, "uidt": { - "enum": ["Rollup"], + "enum": [ + "Rollup" + ], "type": "string", "description": "UI DataType" } @@ -20982,7 +21638,9 @@ } } }, - "required": ["options"], + "required": [ + "options" + ], "x-stoplight": { "id": "3rx8jyy2ufbc3" } @@ -21005,7 +21663,11 @@ "example": "password123" }, "roles": { - "enum": ["commenter", "editor", "viewer"], + "enum": [ + "commenter", + "editor", + "viewer" + ], "type": "string", "description": "The role given the target user", "example": "editor" @@ -21142,7 +21804,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "5gnbbmgal3om3" } @@ -21190,7 +21855,10 @@ "type": "string" } }, - "required": ["email", "password"], + "required": [ + "email", + "password" + ], "title": "Signin Request Model", "type": "object", "x-stoplight": { @@ -21252,7 +21920,10 @@ "description": "Ignore Subscription" } }, - "required": ["email", "password"], + "required": [ + "email", + "password" + ], "x-stoplight": { "id": "6ia1chyii9w48" } @@ -21292,7 +21963,10 @@ "direction": { "type": "string", "description": "Sort direction", - "enum": ["asc", "desc"], + "enum": [ + "asc", + "desc" + ], "example": "desc" }, "order": { @@ -21386,7 +22060,10 @@ } } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "us9qfo1go142f" } @@ -21409,7 +22086,10 @@ }, "direction": { "description": "Sort direction", - "enum": ["asc", "desc"], + "enum": [ + "asc", + "desc" + ], "type": "string" } }, @@ -21435,7 +22115,9 @@ }, "StringOrNull": { "description": "Model for StringOrNull", - "examples": ["string"], + "examples": [ + "string" + ], "oneOf": [ { "maxLength": 255, @@ -21452,7 +22134,9 @@ }, "StringOrNullOrBooleanOrNumber": { "description": "Model for StringOrNullOrBooleanOrNumber", - "examples": ["string"], + "examples": [ + "string" + ], "oneOf": [ { "type": "string" @@ -21893,7 +22577,10 @@ "type": "string" } }, - "required": ["table_name", "title"], + "required": [ + "table_name", + "title" + ], "x-stoplight": { "id": "dkfoyjcny5am9" } @@ -22023,7 +22710,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "urwk2euatlkjl" } @@ -22162,7 +22852,10 @@ "type": "string" } }, - "required": ["columns", "table_name"], + "required": [ + "columns", + "table_name" + ], "title": "Table Request Model", "type": "object", "x-stoplight": { @@ -22237,7 +22930,11 @@ "type": "string" } }, - "required": ["id", "email", "email_verified"], + "required": [ + "id", + "email", + "email_verified" + ], "x-stoplight": { "id": "hcruzlenrwb2x" } @@ -22368,7 +23065,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "32mz06s4tgptq" } @@ -22422,7 +23122,11 @@ }, "lock_type": { "description": "Lock Type of the view", - "enum": ["collaborative", "locked", "personal"], + "enum": [ + "collaborative", + "locked", + "personal" + ], "type": "string" }, "meta": { @@ -22486,7 +23190,12 @@ "description": "Associated View Model" } }, - "required": ["fk_model_id", "show", "title", "type"], + "required": [ + "fk_model_id", + "show", + "title", + "type" + ], "x-stoplight": { "id": "nobjewdlhxrkq" } @@ -22614,7 +23323,10 @@ "description": "Paginated Info" } }, - "required": ["list", "pageInfo"], + "required": [ + "list", + "pageInfo" + ], "x-stoplight": { "id": "a1f99jvpiuugl" } @@ -22686,7 +23398,9 @@ "description": "Foreign Key to Geo Data Column. Used in creating Map View." } }, - "required": ["title"] + "required": [ + "title" + ] }, "ViewUpdateReq": { "description": "Model for View Update Request", @@ -22732,7 +23446,11 @@ "example": "password123" }, "lock_type": { - "enum": ["collaborative", "locked", "personal"], + "enum": [ + "collaborative", + "locked", + "personal" + ], "type": "string", "description": "Lock type of View.", "example": "collaborative" @@ -22925,10 +23643,19 @@ "description": "The email address of the user who invited the recipient" } }, - "required": ["id", "title", "type", "invited_by"] + "required": [ + "id", + "title", + "type", + "invited_by" + ] } }, - "required": ["fk_user_id", "type", "body"] + "required": [ + "fk_user_id", + "type", + "body" + ] }, "ProjectEvent": { "type": "object", @@ -22956,10 +23683,18 @@ "description": "The type of the base" } }, - "required": ["id", "title", "type"] + "required": [ + "id", + "title", + "type" + ] } }, - "required": ["fk_user_id", "type", "body"] + "required": [ + "fk_user_id", + "type", + "body" + ] }, "WelcomeEvent": { "type": "object", @@ -22977,7 +23712,11 @@ "description": "An empty object" } }, - "required": ["fk_user_id", "type", "body"] + "required": [ + "fk_user_id", + "type", + "body" + ] }, "SortEvent": { "type": "object", @@ -22993,7 +23732,11 @@ "type": "object" } }, - "required": ["fk_user_id", "type", "body"] + "required": [ + "fk_user_id", + "type", + "body" + ] }, "FilterEvent": { "type": "object", @@ -23009,7 +23752,11 @@ "type": "object" } }, - "required": ["fk_user_id", "type", "body"] + "required": [ + "fk_user_id", + "type", + "body" + ] }, "TableEvent": { "type": "object", @@ -23042,10 +23789,19 @@ "description": "The ID of the table associated with the event" } }, - "required": ["title", "base_id", "source_id", "id"] + "required": [ + "title", + "base_id", + "source_id", + "id" + ] } }, - "required": ["fk_user_id", "type", "body"] + "required": [ + "fk_user_id", + "type", + "body" + ] }, "ViewEvent": { "type": "object", @@ -23082,10 +23838,20 @@ "description": "The ID of the model that the view is based on" } }, - "required": ["title", "base_id", "source_id", "id", "fk_model_id"] + "required": [ + "title", + "base_id", + "source_id", + "id", + "fk_model_id" + ] } }, - "required": ["fk_user_id", "type", "body"] + "required": [ + "fk_user_id", + "type", + "body" + ] }, "ColumnEvent": { "type": "object", @@ -23122,10 +23888,20 @@ "description": "The ID of the model that the column belongs to" } }, - "required": ["title", "base_id", "source_id", "id", "fk_model_id"] + "required": [ + "title", + "base_id", + "source_id", + "id", + "fk_model_id" + ] } }, - "required": ["fk_user_id", "type", "body"] + "required": [ + "fk_user_id", + "type", + "body" + ] }, "Notification": { "allOf": [ @@ -23190,7 +23966,8 @@ { "list": [ { - "body": {}, + "body": { + }, "type": "invite", "is_read": false, "is_deleted": false, @@ -23224,7 +24001,10 @@ "description": "Model for Paginated" } }, - "required": ["list", "pageInfo"] + "required": [ + "list", + "pageInfo" + ] }, "NotificationUpdate": { "type": "object", @@ -23697,7 +24477,9 @@ "example": "BadRequest [Error]: " } }, - "required": ["msg"] + "required": [ + "msg" + ] }, "examples": { "Example 1": { From 4e84b6e753767bd864a38a34f98d46cc37de19f4 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:22 +0000 Subject: [PATCH 11/19] fix(nc-gui): nocodb/nocodb#7552 and nocodb/nocodb#7557 --- .../nc-gui/composables/useMultiSelect/convertCellData.ts | 7 +++++-- packages/nc-gui/composables/useMultiSelect/index.ts | 8 +++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index aa51b2c2d1..3973c75bf7 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -56,7 +56,7 @@ export default function convertCellData( } return null case UITypes.Date: { - const parsedDate = dayjs(value, column?.meta?.date_format ?? 'YYYY-MM-DD') + const parsedDate = dayjs(value, parseProp(column?.meta)?.date_format ?? 'YYYY-MM-DD') if (!parsedDate.isValid()) { if (isMultiple) { return null @@ -67,7 +67,10 @@ export default function convertCellData( return parsedDate.format('YYYY-MM-DD') } case UITypes.DateTime: { - const parsedDateTime = dayjs(value) + const parsedDateTime = dayjs( + value, + `${parseProp(column?.meta)?.date_format ?? 'YYYY-MM-DD'} ${parseProp(column?.meta)?.time_format ?? 'HH:mm'}`, + ) if (!parsedDateTime.isValid()) { if (isMultiple) { return null diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index cbd577cc8f..d8c43a8ff9 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -28,6 +28,7 @@ import { useI18n, useMetas, useUndoRedo, + parseProp, } from '#imports' const MAIN_MOUSE_PRESSED = 0 @@ -173,7 +174,7 @@ export function useMultiSelect( }) } - if ([UITypes.DateTime, UITypes.CreatedTime, UITypes.LastModifiedTime].includes(columnObj.uidt)) { + if ([UITypes.DateTime, UITypes.CreatedTime, UITypes.LastModifiedTime].includes(columnObj.uidt as UITypes)) { // remove `"` // e.g. "2023-05-12T08:03:53.000Z" -> 2023-05-12T08:03:53.000Z textToCopy = textToCopy.replace(/["']/g, '') @@ -194,14 +195,15 @@ export function useMultiSelect( // therefore, here we reformat to the correct datetime format based on the meta textToCopy = d.format(constructDateTimeFormat(columnObj)) - if (!dayjs(textToCopy).isValid()) { + if (!d.isValid()) { // return empty string for invalid datetime return '' } } if (columnObj.uidt === UITypes.Date) { - const dateFormat = columnObj.meta?.date_format + const dateFormat = parseProp(columnObj.meta)?.date_format + if (dateFormat && isDateMonthFormat(dateFormat)) { // any date month format (e.g. YYYY-MM) couldn't be stored in database // with date type since it is not a valid date From 109b9625862743390b59ac3e2b59b2501373dffc Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:22 +0000 Subject: [PATCH 12/19] fix: small changes --- packages/nc-gui/composables/useMultiSelect/index.ts | 4 ++-- packages/nocodb/src/db/BaseModelSqlv2.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index d8c43a8ff9..a75e62348b 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -17,6 +17,7 @@ import { isMac, isTypableInputColumn, message, + parseProp, reactive, ref, unref, @@ -28,7 +29,6 @@ import { useI18n, useMetas, useUndoRedo, - parseProp, } from '#imports' const MAIN_MOUSE_PRESSED = 0 @@ -950,8 +950,8 @@ export function useMultiSelect( }, ]) } catch { - console.log('catch') rowObj.row[columnObj.title!] = oldCellValue + return } if (result && result?.link && result?.unlink && Array.isArray(result.link) && Array.isArray(result.unlink)) { diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index 7ec561ab05..36c82045e6 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -1379,7 +1379,8 @@ class BaseModelSqlv2 { if (!selectAllRecords) { qb.limit(+rest?.limit || 25); } - qb.offset(+rest?.offset || 0); + qb.offset(selectAllRecords ? 0 : +rest?.offset || 0); + const children = await this.execAndParse(qb, await childTable.getColumns()); const proto = await ( From 6154811253a27998d69167565c150e3a82cdf90d Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:22 +0000 Subject: [PATCH 13/19] chore: lint --- packages/nc-gui/composables/useMultiSelect/index.ts | 3 --- packages/nocodb/src/db/BaseModelSqlv2.ts | 1 - 2 files changed, 4 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index a75e62348b..981bd42e58 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -27,7 +27,6 @@ import { useEventListener, useGlobal, useI18n, - useMetas, useUndoRedo, } from '#imports' @@ -59,8 +58,6 @@ export function useMultiSelect( const { copy } = useCopy() - const { getMeta } = useMetas() - const { appInfo } = useGlobal() const { isMysql, isPg } = useBase() diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index 36c82045e6..e0bfb3f3ee 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -1380,7 +1380,6 @@ class BaseModelSqlv2 { qb.limit(+rest?.limit || 25); } qb.offset(selectAllRecords ? 0 : +rest?.offset || 0); - const children = await this.execAndParse(qb, await childTable.getColumns()); const proto = await ( From 09ac06d073d9a32f4fb700bb24385245ed446aaa Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:22 +0000 Subject: [PATCH 14/19] fix: paste picks up ID from the copy source record ID & not the link --- packages/nc-gui/composables/useMultiSelect/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 981bd42e58..72824d45e7 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -27,6 +27,7 @@ import { useEventListener, useGlobal, useI18n, + useMetas, useUndoRedo, } from '#imports' @@ -58,6 +59,8 @@ export function useMultiSelect( const { copy } = useCopy() + const { getMeta } = useMetas() + const { appInfo } = useGlobal() const { isMysql, isPg } = useBase() @@ -139,7 +142,6 @@ export function useMultiSelect( ) { // fk_related_model_id is used to prevent paste operation in different fk_related_model_id cell textToCopy = { - rowId: extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]), fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id, value: textToCopy || null, } @@ -898,9 +900,13 @@ export function useMultiSelect( if (!foreignKeyColumn) return + const relatedTableMeta = await getMeta((columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id!) + rowObj.row[columnObj.title!] = pasteVal?.value - rowObj.row[foreignKeyColumn.title!] = pasteVal?.value ? pasteVal.rowId : null + rowObj.row[foreignKeyColumn.title!] = pasteVal?.value + ? extractPkFromRow(pasteVal.value, (relatedTableMeta as any)!.columns!) + : null return await syncCellData?.({ ...activeCell, updatedColumnTitle: foreignKeyColumn.title }) } From 6b9ea2aba4529514f92a0355acf42a9aad737381 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:22 +0000 Subject: [PATCH 15/19] fix(nc-gui): incorrect lib path import --- packages/nc-gui/composables/useViewSorts.ts | 2 +- packages/nc-gui/utils/dataUtils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/composables/useViewSorts.ts b/packages/nc-gui/composables/useViewSorts.ts index 79cf08dc90..ab510c2237 100644 --- a/packages/nc-gui/composables/useViewSorts.ts +++ b/packages/nc-gui/composables/useViewSorts.ts @@ -1,6 +1,6 @@ import type { ColumnType, SortType, ViewType } from 'nocodb-sdk' import type { Ref } from 'vue' -import type { UndoRedoAction } from 'lib' +import type { UndoRedoAction } from '~/lib' import type { EventHook } from '@vueuse/core' import { IsPublicInj, diff --git a/packages/nc-gui/utils/dataUtils.ts b/packages/nc-gui/utils/dataUtils.ts index 229123547e..1bea695361 100644 --- a/packages/nc-gui/utils/dataUtils.ts +++ b/packages/nc-gui/utils/dataUtils.ts @@ -1,6 +1,6 @@ import { RelationTypes, UITypes, isLinksOrLTAR, isSystemColumn, isVirtualCol } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk' -import type { Row } from 'lib' +import type { Row } from '~/lib' import { isColumnRequiredAndNull } from './columnUtils' export const extractPkFromRow = (row: Record, columns: ColumnType[]) => { From 4434da23e9ed2bffe82839728f946c8494b81cd3 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:22 +0000 Subject: [PATCH 16/19] fix: undo redo mm cell copy paste --- packages/nc-gui/components/smartsheet/Row.vue | 3 +- .../components/smartsheet/grid/Table.vue | 42 +++-- packages/nc-gui/composables/useData.ts | 2 +- packages/nc-gui/composables/useLTARStore.ts | 11 +- .../useMultiSelect/convertCellData.ts | 8 +- .../composables/useMultiSelect/index.ts | 74 ++++---- .../composables/useSmartsheetRowStore.ts | 40 +++- .../src/controllers/data-table.controller.ts | 6 +- packages/nocodb/src/schema/swagger.json | 24 ++- .../nocodb/src/services/data-table.service.ts | 178 +++++++++++------- packages/nocodb/src/utils/acl.ts | 4 +- 11 files changed, 254 insertions(+), 138 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/Row.vue b/packages/nc-gui/components/smartsheet/Row.vue index 16e6ae4019..80a806bdfb 100644 --- a/packages/nc-gui/components/smartsheet/Row.vue +++ b/packages/nc-gui/components/smartsheet/Row.vue @@ -21,7 +21,7 @@ const currentRow = toRef(props, 'row') const { meta } = useSmartsheetStoreOrThrow() -const { isNew, state, syncLTARRefs, clearLTARCell, addLTARRef } = useProvideSmartsheetRowStore(meta as Ref, currentRow) +const { isNew, state, syncLTARRefs, clearLTARCell, addLTARRef, cleaMMCell } = useProvideSmartsheetRowStore(meta as Ref, currentRow) const reloadViewDataTrigger = inject(ReloadViewDataHookInj)! @@ -41,6 +41,7 @@ defineExpose({ syncLTARRefs, clearLTARCell, addLTARRef, + cleaMMCell }) diff --git a/packages/nc-gui/components/smartsheet/grid/Table.vue b/packages/nc-gui/components/smartsheet/grid/Table.vue index 9bc3f8896e..63378c34d4 100644 --- a/packages/nc-gui/components/smartsheet/grid/Table.vue +++ b/packages/nc-gui/components/smartsheet/grid/Table.vue @@ -50,6 +50,7 @@ import { useViewColumnsOrThrow, useViewsStore, watch, + useApi } from '#imports' import type { CellRange, Row } from '#imports' @@ -98,6 +99,8 @@ const dataRef = toRef(props, 'data') const paginationStyleRef = toRef(props, 'pagination') +const { api } = useApi() + const { loadData, changePage, @@ -263,17 +266,19 @@ provide(JsonExpandInj, isJsonExpand) async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = false) { if (!ctx || !hasEditPermission.value || (!isLinksOrLTAR(fields.value[ctx.col]) && isVirtualCol(fields.value[ctx.col]))) return - if (fields.value[ctx.col]?.uidt === UITypes.Links) { - return message.info(t('msg.linkColumnClearNotSupportedYet')) - } - const rowObj = dataRef.value[ctx.row] const columnObj = fields.value[ctx.col] if (isVirtualCol(columnObj)) { + let mmClearResult + + if (isMm(columnObj) && rowRefs.value) { + mmClearResult = await rowRefs.value[ctx.row]!.cleaMMCell(columnObj) + } + addUndo({ undo: { - fn: async (ctx: { row: number; col: number }, col: ColumnType, row: Row, pg: PaginatedType) => { + fn: async (ctx: { row: number; col: number }, col: ColumnType, row: Row, pg: PaginatedType, mmClearResult: any[]) => { if (paginationDataRef.value?.pageSize === pg.pageSize) { if (paginationDataRef.value?.page !== pg.page) { await changePage?.(pg.page!) @@ -286,11 +291,17 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = rowId === extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) && columnObj.id === col.id ) { - rowObj.row[columnObj.title] = row.row[columnObj.title] if (rowRefs.value) { - await rowRefs.value[ctx.row]!.addLTARRef(rowObj.row[columnObj.title], columnObj) - await rowRefs.value[ctx.row]!.syncLTARRefs(rowObj.row) + if (isBt(columnObj)) { + rowObj.row[columnObj.title] = row.row[columnObj.title] + + await rowRefs.value[ctx.row]!.addLTARRef(rowObj.row[columnObj.title], columnObj) + await rowRefs.value[ctx.row]!.syncLTARRefs(rowObj.row) + } else if (isMm(columnObj)) { + await api.dbDataTableRow.nestedLink(meta.value?.id as string, columnObj.id as string, encodeURIComponent(rowId as string), mmClearResult) + rowObj.row[columnObj.title] = mmClearResult?.length ? mmClearResult?.length : null + } } // eslint-disable-next-line @typescript-eslint/no-use-before-define @@ -305,10 +316,10 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = throw new Error(t('msg.pageSizeChanged')) } }, - args: [clone(ctx), clone(columnObj), clone(rowObj), clone(paginationDataRef.value)], + args: [clone(ctx), clone(columnObj), clone(rowObj), clone(paginationDataRef.value), mmClearResult], }, redo: { - fn: async (ctx: { row: number; col: number }, col: ColumnType, row: Row, pg: PaginatedType) => { + fn: async (ctx: { row: number; col: number }, col: ColumnType, row: Row, pg: PaginatedType, mmClearResult:any[]) => { if (paginationDataRef.value?.pageSize === pg.pageSize) { if (paginationDataRef.value?.page !== pg.page) { await changePage?.(pg.page!) @@ -318,7 +329,11 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = const columnObj = fields.value[ctx.col] if (rowId === extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) && columnObj.id === col.id) { if (rowRefs.value) { - await rowRefs.value[ctx.row]!.clearLTARCell(columnObj) + if (isBt(columnObj)) { + await rowRefs.value[ctx.row]!.clearLTARCell(columnObj) + } else if (isMm(columnObj)){ + await rowRefs.value[ctx.row]!.cleaMMCell(columnObj) + } } // eslint-disable-next-line @typescript-eslint/no-use-before-define activeCell.col = ctx.col @@ -332,11 +347,12 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = throw new Error(t('msg.pageSizeChanged')) } }, - args: [clone(ctx), clone(columnObj), clone(rowObj), clone(paginationDataRef.value)], + args: [clone(ctx), clone(columnObj), clone(rowObj), clone(paginationDataRef.value), mmClearResult], }, scope: defineViewScope({ view: view.value }), }) - if (rowRefs.value) await rowRefs.value[ctx.row]!.clearLTARCell(columnObj) + if (isBt(columnObj) && rowRefs.value) await rowRefs.value[ctx.row]!.clearLTARCell(columnObj) + return } diff --git a/packages/nc-gui/composables/useData.ts b/packages/nc-gui/composables/useData.ts index c588e3fc0f..33f3cfb57b 100644 --- a/packages/nc-gui/composables/useData.ts +++ b/packages/nc-gui/composables/useData.ts @@ -480,7 +480,7 @@ export function useData(args: { base.value.title as string, metaValue?.title as string, encodeURIComponent(rowId), - type as 'mm' | 'hm', + type as RelationTypes, column.title as string, encodeURIComponent(relatedRowId), ) diff --git a/packages/nc-gui/composables/useLTARStore.ts b/packages/nc-gui/composables/useLTARStore.ts index 37e154df0e..51882e0673 100644 --- a/packages/nc-gui/composables/useLTARStore.ts +++ b/packages/nc-gui/composables/useLTARStore.ts @@ -8,6 +8,7 @@ import { dateFormats, parseStringDateTime, timeFormats, + RelationTypes, } from 'nocodb-sdk' import type { ComputedRef, Ref } from 'vue' import { @@ -230,7 +231,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState( baseId, meta.value.id, encodeURIComponent(rowId.value), - colOptions.value.type as 'mm' | 'hm', + colOptions.value.type as RelationTypes, column?.value?.id, { limit: String(childrenExcludedListPagination.size), @@ -284,7 +285,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState( childrenList.value = await $api.public.dataNestedList( sharedView.value?.uuid as string, encodeURIComponent(rowId.value), - colOptions.value.type as 'mm' | 'hm', + colOptions.value.type as RelationTypes, column.value.id, { limit: String(childrenListPagination.size), @@ -304,7 +305,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState( (base?.value?.id || (sharedView.value?.view as any)?.base_id) as string, meta.value.id, encodeURIComponent(rowId.value), - colOptions.value.type as 'mm' | 'hm', + colOptions.value.type as RelationTypes, column?.value?.id, { limit: String(childrenListPagination.size), @@ -395,7 +396,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState( base.value.id as string, metaValue.id!, encodeURIComponent(rowId.value), - colOptions.value.type as 'mm' | 'hm', + colOptions.value.type as RelationTypes, column?.value?.id, encodeURIComponent(getRelatedTableRowId(row) as string), ) @@ -461,7 +462,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState( base.value.id as string, metaValue.id as string, encodeURIComponent(rowId.value), - colOptions.value.type as 'mm' | 'hm', + colOptions.value.type as RelationTypes, column?.value?.id, encodeURIComponent(getRelatedTableRowId(row) as string) as string, ) diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts index 3973c75bf7..0325993020 100644 --- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts +++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts @@ -1,8 +1,8 @@ import dayjs from 'dayjs' import type { ColumnType, LinkToAnotherRecordType, SelectOptionsType } from 'nocodb-sdk' -import { RelationTypes, UITypes } from 'nocodb-sdk' +import { UITypes } from 'nocodb-sdk' import type { AppInfo } from '~/composables/useGlobal' -import { parseProp } from '#imports' +import { isBt, isMm, parseProp } from '#imports' export default function convertCellData( args: { to: UITypes; value: string; column: ColumnType; appInfo: AppInfo; files?: FileList | File[]; oldValue?: unknown }, @@ -254,7 +254,7 @@ export default function convertCellData( return undefined } - if ((column.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.BELONGS_TO) { + if (isBt(column)) { const parsedVal = typeof value === 'string' ? JSON.parse(value) : value if ( @@ -274,7 +274,7 @@ export default function convertCellData( return undefined } - if ((column.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.MANY_TO_MANY) { + if (isMm(column)) { const parsedVal = typeof value === 'string' ? JSON.parse(value) : value if ( diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 72824d45e7..9de520ff92 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -3,7 +3,7 @@ import { computed } from 'vue' import dayjs from 'dayjs' import type { MaybeRef } from '@vueuse/core' import type { ColumnType, LinkToAnotherRecordType, TableType, UserFieldRecordType, ViewType } from 'nocodb-sdk' -import { RelationTypes, UITypes, dateFormats, isDateMonthFormat, isSystemColumn, isVirtualCol, timeFormats } from 'nocodb-sdk' +import { UITypes, dateFormats, isDateMonthFormat, isSystemColumn, isVirtualCol, timeFormats } from 'nocodb-sdk' import { parse } from 'papaparse' import type { Cell } from './cellRange' import { CellRange } from './cellRange' @@ -12,9 +12,11 @@ import type { Nullable, Row } from '#imports' import { extractPkFromRow, extractSdkResponseErrorMsg, + isBt, isDrawerOrModalExist, isExpandedCellInputExist, isMac, + isMm, isTypableInputColumn, message, parseProp, @@ -136,10 +138,7 @@ export function useMultiSelect( } } - if ( - columnObj.uidt === UITypes.LinkToAnotherRecord && - (columnObj.colOptions as LinkToAnotherRecordType).type === RelationTypes.BELONGS_TO - ) { + if (isBt(columnObj)) { // fk_related_model_id is used to prevent paste operation in different fk_related_model_id cell textToCopy = { fk_related_model_id: (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id, @@ -147,10 +146,7 @@ export function useMultiSelect( } } - if ( - columnObj.uidt === UITypes.Links && - (columnObj.colOptions as LinkToAnotherRecordType).type === RelationTypes.MANY_TO_MANY - ) { + if (isMm(columnObj)) { textToCopy = { rowId: extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]), columnId: columnObj.id, @@ -878,10 +874,7 @@ export function useMultiSelect( const columnObj = unref(fields)[activeCell.col] // handle belongs to column - if ( - columnObj.uidt === UITypes.LinkToAnotherRecord && - (columnObj.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.BELONGS_TO - ) { + if (isBt(columnObj)) { const pasteVal = convertCellData( { value: clipboardData, @@ -911,10 +904,7 @@ export function useMultiSelect( return await syncCellData?.({ ...activeCell, updatedColumnTitle: foreignKeyColumn.title }) } - if ( - columnObj.uidt === UITypes.Links && - (columnObj.colOptions as LinkToAnotherRecordType)?.type === RelationTypes.MANY_TO_MANY - ) { + if (isMm(columnObj)) { const pasteVal = convertCellData( { value: clipboardData, @@ -937,21 +927,26 @@ export function useMultiSelect( let result try { - result = await api.dbDataTableRow.nestedListCopyPaste(meta.value?.id as string, columnObj.id as string, [ - { - operation: 'copy', - rowId: pasteVal.rowId, - columnId: pasteVal.columnId, - fk_related_model_id: pasteVal.fk_related_model_id, - }, - { - operation: 'paste', - rowId: pasteRowPk, - columnId: pasteVal.columnId, - fk_related_model_id: - (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id || pasteVal.fk_related_model_id, - }, - ]) + result = await api.dbDataTableRow.nestedListCopyPasteOrDeleteAll( + meta.value?.id as string, + columnObj.id as string, + [ + { + operation: 'copy', + rowId: pasteVal.rowId, + columnId: pasteVal.columnId, + fk_related_model_id: pasteVal.fk_related_model_id, + }, + { + operation: 'paste', + rowId: pasteRowPk, + columnId: columnObj.id as string, + fk_related_model_id: + (columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id || pasteVal.fk_related_model_id, + }, + ], + { viewId: activeView?.value?.id }, + ) } catch { rowObj.row[columnObj.title!] = oldCellValue return @@ -970,17 +965,23 @@ export function useMultiSelect( pasteRowPk: string, result: { link: any[]; unlink: any[] }, value: number, - activeCell: Nullable, + activeCell: Cell, ) => { + const rowObj = unref(data)[activeCell.row] + const columnObj = unref(fields)[activeCell.col] + await Promise.all([ result.link.length && - api.dbDataTableRow.nestedLink(tableId, columnId, encodeURIComponent(pasteRowPk), result.link), + api.dbDataTableRow.nestedLink(tableId, columnId, encodeURIComponent(pasteRowPk), result.link, { + viewId: activeView?.value?.id, + }), result.unlink.length && api.dbDataTableRow.nestedUnlink( meta.value?.id as string, columnObj.id as string, encodeURIComponent(pasteRowPk), result.unlink, + { viewId: activeView?.value?.id }, ), ]) @@ -997,8 +998,11 @@ export function useMultiSelect( pasteRowPk: string, result: { link: any[]; unlink: any[] }, value: number, - activeCell: Nullable, + activeCell: Cell, ) => { + const rowObj = unref(data)[activeCell.row] + const columnObj = unref(fields)[activeCell.col] + await Promise.all([ result.unlink.length && api.dbDataTableRow.nestedLink(tableId, columnId, encodeURIComponent(pasteRowPk), result.unlink), diff --git a/packages/nc-gui/composables/useSmartsheetRowStore.ts b/packages/nc-gui/composables/useSmartsheetRowStore.ts index 74781244b6..0e68daada8 100644 --- a/packages/nc-gui/composables/useSmartsheetRowStore.ts +++ b/packages/nc-gui/composables/useSmartsheetRowStore.ts @@ -83,7 +83,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState( base.value.id as string, metaValue?.id as string, encodeURIComponent(rowId), - type as 'mm' | 'hm', + type, column.id as string, encodeURIComponent(relatedRowId), ) @@ -185,6 +185,43 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState( }) } + // clear MM cell + const cleaMMCell = async (column: ColumnType) => { + try { + if (!column || !isLinksOrLTAR(column)) return + + const relatedTableMeta = metas.value?.[(column?.colOptions)?.fk_related_model_id as string] + + if (isNew.value) { + state.value[column.title!] = null + } else if (currentRow.value) { + if ((column.colOptions)?.type === RelationTypes.MANY_TO_MANY) { + if (!currentRow.value.row[column.title!]) return + + console.log('currentRow.value.row, meta.value?.columns', currentRow.value.row, meta.value?.columns) + const result = await $api.dbDataTableRow.nestedListCopyPasteOrDeleteAll( + meta.value?.id as string, + column.id as string, + [ + { + operation: 'deleteAll', + rowId: extractPkFromRow(currentRow.value.row, meta.value?.columns as ColumnType[]) as string, + columnId: column.id as string, + fk_related_model_id: (column.colOptions as LinkToAnotherRecordType)?.fk_related_model_id as string, + }, + ], + ) + + currentRow.value.row[column.title!] = null + + return Array.isArray(result.unlink) ? result.unlink : [] + } + } + } catch (e: any) { + message.error(await extractSdkResponseErrorMsg(e)) + } + } + return { row, state, @@ -196,6 +233,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState( loadRow, currentRow, clearLTARCell, + cleaMMCell, } }, 'smartsheet-row-store', diff --git a/packages/nocodb/src/controllers/data-table.controller.ts b/packages/nocodb/src/controllers/data-table.controller.ts index a6c65b471b..04a8501661 100644 --- a/packages/nocodb/src/controllers/data-table.controller.ts +++ b/packages/nocodb/src/controllers/data-table.controller.ts @@ -196,8 +196,8 @@ export class DataTableController { // todo: naming @Post(['/api/v2/tables/:modelId/links/:columnId/records']) - @Acl('nestedDataListCopyPaste') - async nestedListCopyPaste( + @Acl('nestedDataListCopyPasteOrDeleteAll') + async nestedListCopyPasteOrDeleteAll( @Req() req: Request, @Param('modelId') modelId: string, @Query('viewId') viewId: string, @@ -210,7 +210,7 @@ export class DataTableController { fk_related_model_id: string; }[], ) { - return await this.dataTableService.nestedListCopyPaste({ + return await this.dataTableService.nestedListCopyPasteOrDeleteAll({ modelId, query: req.query, viewId, diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json index 88180e1b23..ecccd9c63d 100644 --- a/packages/nocodb/src/schema/swagger.json +++ b/packages/nocodb/src/schema/swagger.json @@ -16351,8 +16351,8 @@ } ], "post": { - "summary": "Copy paste nested link", - "operationId": "db-data-table-row-nested-list-copy-paste", + "summary": "Copy paste or deleteAll nested link", + "operationId": "db-data-table-row-nested-list-copy-paste-or-deleteAll", "responses": { "200": { "description": "OK", @@ -16388,7 +16388,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/nestedListCopyPasteReq" + "$ref": "#/components/schemas/nestedListCopyPasteOrDeleteAllReq" }, "examples": { "Example 1": { @@ -16406,12 +16406,22 @@ "fk_related_model_id": "m797s6vbrqvo2pv" } ] + }, + "Example 2": { + "value": [ + { + "operation": "deleteAll", + "rowId": "1", + "columnId": "ca2ppiy8raidc09", + "fk_related_model_id": "m797s6vbrqvo2pv" + } + ] } } } } }, - "description": "Copy links from the one cell and paste them into another cell", + "description": "Copy links from the one cell and paste them into another cell or delete all records from cell", "parameters": [ { "$ref": "#/components/parameters/xc-auth" @@ -24035,16 +24045,16 @@ } } }, - "nestedListCopyPasteReq": { + "nestedListCopyPasteOrDeleteAllReq": { "type": "array", - "minItems": 2, + "minItems": 1, "maxItems": 2, "items": { "type": "object", "properties": { "operation": { "type": "string", - "enum": ["copy", "paste"] + "enum": ["copy", "paste", "deleteAll"] }, "rowId": { "type": "string" diff --git a/packages/nocodb/src/services/data-table.service.ts b/packages/nocodb/src/services/data-table.service.ts index 8b4d55f35d..3725b50b6f 100644 --- a/packages/nocodb/src/services/data-table.service.ts +++ b/packages/nocodb/src/services/data-table.service.ts @@ -445,41 +445,33 @@ export class DataTableService { } // todo: naming & optimizing - async nestedListCopyPaste(param: { + async nestedListCopyPasteOrDeleteAll(param: { cookie: any; viewId: string; modelId: string; columnId: string; query: any; data: { - operation: 'copy' | 'paste'; + operation: 'copy' | 'paste' | 'deleteAll'; rowId: string; columnId: string; fk_related_model_id: string; }[]; }) { validatePayload( - 'swagger.json#/components/schemas/nestedListCopyPasteReq', + 'swagger.json#/components/schemas/nestedListCopyPasteOrDeleteAllReq', param.data, ); - if ( - param.data[0]?.fk_related_model_id !== param.data[1]?.fk_related_model_id - ) { - throw new Error( - 'The operation is not supported on different fk_related_model_id', - ); - } - const operationMap = param.data.reduce( (map, p) => { map[p.operation] = p; return map; }, {} as Record< - 'copy' | 'paste', + 'copy' | 'paste' | 'deleteAll', { - operation: 'copy' | 'paste'; + operation: 'copy' | 'paste' | 'deleteAll'; rowId: string; columnId: string; fk_related_model_id: string; @@ -487,6 +479,16 @@ export class DataTableService { >, ); + if ( + !operationMap.deleteAll && + operationMap.copy.fk_related_model_id !== + operationMap.paste.fk_related_model_id + ) { + throw new Error( + 'The operation is not supported on different fk_related_model_id', + ); + } + const { model, view } = await this.getModelAndView(param); const source = await Source.get(model.source_id); @@ -497,21 +499,32 @@ export class DataTableService { dbDriver: await NcConnectionMgrv2.get(source), }); - const [existsCopyRow, existsPasteRow] = await Promise.all([ - baseModel.exist(operationMap.copy.rowId), - baseModel.exist(operationMap.paste.rowId), - ]); - - if (!existsCopyRow && !existsPasteRow) { - NcError.notFound( - `Record with id '${operationMap.copy.rowId}' and '${operationMap.paste.rowId}' not found`, - ); - } else if (!existsCopyRow) { - NcError.notFound(`Record with id '${operationMap.copy.rowId}' not found`); - } else if (!existsPasteRow) { + if ( + operationMap.deleteAll && + !(await baseModel.exist(operationMap.deleteAll.rowId)) + ) { NcError.notFound( - `Record with id '${operationMap.paste.rowId}' not found`, + `Record with id '${operationMap.deleteAll.rowId}' not found`, ); + } else if (operationMap.copy && operationMap.paste) { + const [existsCopyRow, existsPasteRow] = await Promise.all([ + baseModel.exist(operationMap.copy.rowId), + baseModel.exist(operationMap.paste.rowId), + ]); + + if (!existsCopyRow && !existsPasteRow) { + NcError.notFound( + `Record with id '${operationMap.copy.rowId}' and '${operationMap.paste.rowId}' not found`, + ); + } else if (!existsCopyRow) { + NcError.notFound( + `Record with id '${operationMap.copy.rowId}' not found`, + ); + } else if (!existsPasteRow) { + NcError.notFound( + `Record with id '${operationMap.paste.rowId}' not found`, + ); + } } const column = await this.getColumn(param); @@ -537,55 +550,88 @@ export class DataTableService { listArgs.sortArr = JSON.parse(listArgs.sortArrJson); } catch (e) {} - const [copiedCellNestedList, pasteCellNestedList] = await Promise.all([ - baseModel.mmList( - { - colId: operationMap.copy.columnId, - parentId: operationMap.copy.rowId, - }, - listArgs as any, - true, - ), - baseModel.mmList( + if (operationMap.deleteAll) { + let deleteCellNestedList = await baseModel.mmList( { colId: column.id, - parentId: operationMap.paste.rowId, + parentId: operationMap.deleteAll.rowId, }, listArgs as any, true, - ), - ]); - - const filteredRowsToLink = this.filterAndMapRows( - copiedCellNestedList, - pasteCellNestedList, - relatedModel.primaryKeys, - ); - - const filteredRowsToUnlink = this.filterAndMapRows( - pasteCellNestedList, - copiedCellNestedList, - relatedModel.primaryKeys, - ); + ); - await Promise.all([ - filteredRowsToLink.length && - baseModel.addLinks({ + if (deleteCellNestedList && Array.isArray(deleteCellNestedList)) { + await baseModel.removeLinks({ colId: column.id, - childIds: filteredRowsToLink, - rowId: operationMap.paste.rowId, + childIds: deleteCellNestedList, + rowId: operationMap.deleteAll.rowId, cookie: param.cookie, - }), - filteredRowsToUnlink.length && - baseModel.removeLinks({ - colId: column.id, - childIds: filteredRowsToUnlink, - rowId: operationMap.paste.rowId, - cookie: param.cookie, - }), - ]); + }); + + // extract only pk row data + deleteCellNestedList = deleteCellNestedList.map((nestedList) => { + return relatedModel.primaryKeys.reduce((acc, col) => { + acc[col.title || col.column_name] = + nestedList[col.title || col.column_name]; + return acc; + }, {}); + }); + } else { + deleteCellNestedList = []; + } - return { link: filteredRowsToLink, unlink: filteredRowsToUnlink }; + return { link: [], unlink: deleteCellNestedList }; + } else if (operationMap.copy && operationMap.paste) { + const [copiedCellNestedList, pasteCellNestedList] = await Promise.all([ + baseModel.mmList( + { + colId: operationMap.copy.columnId, + parentId: operationMap.copy.rowId, + }, + listArgs as any, + true, + ), + baseModel.mmList( + { + colId: column.id, + parentId: operationMap.paste.rowId, + }, + listArgs as any, + true, + ), + ]); + + const filteredRowsToLink = this.filterAndMapRows( + copiedCellNestedList, + pasteCellNestedList, + relatedModel.primaryKeys, + ); + + const filteredRowsToUnlink = this.filterAndMapRows( + pasteCellNestedList, + copiedCellNestedList, + relatedModel.primaryKeys, + ); + + await Promise.all([ + filteredRowsToLink.length && + baseModel.addLinks({ + colId: column.id, + childIds: filteredRowsToLink, + rowId: operationMap.paste.rowId, + cookie: param.cookie, + }), + filteredRowsToUnlink.length && + baseModel.removeLinks({ + colId: column.id, + childIds: filteredRowsToUnlink, + rowId: operationMap.paste.rowId, + cookie: param.cookie, + }), + ]); + + return { link: filteredRowsToLink, unlink: filteredRowsToUnlink }; + } } private validateIds(rowIds: any[] | any) { diff --git a/packages/nocodb/src/utils/acl.ts b/packages/nocodb/src/utils/acl.ts index 8173b464bf..b60c414e9b 100644 --- a/packages/nocodb/src/utils/acl.ts +++ b/packages/nocodb/src/utils/acl.ts @@ -120,7 +120,7 @@ const permissionScopes = { 'nestedDataList', 'nestedDataLink', 'nestedDataUnlink', - 'nestedListCopyPaste', + 'nestedListCopyPasteOrDeleteAll', 'baseUserList', // Base API Tokens @@ -228,7 +228,7 @@ const rolePermissions: nestedDataLink: true, nestedDataUnlink: true, - nestedListCopyPaste: true, + nestedListCopyPasteOrDeleteAll: true, // TODO add ACL with base scope // upload: true, // uploadViaURL: true, From 71158bc6d740f3038404e80c06ad38763f8b9bdf Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:23 +0000 Subject: [PATCH 17/19] fix: show warning on paste or clear on not supported col --- packages/nc-gui/components/smartsheet/Row.vue | 7 +++-- .../components/smartsheet/grid/Table.vue | 27 ++++++++++++++----- packages/nc-gui/composables/useLTARStore.ts | 9 +++---- .../composables/useMultiSelect/index.ts | 12 +++++++++ .../composables/useSmartsheetRowStore.ts | 2 -- packages/nc-gui/composables/useViewSorts.ts | 2 +- packages/nc-gui/lang/en.json | 5 +++- packages/nc-gui/utils/dataUtils.ts | 2 +- packages/nocodb/src/db/BaseModelSqlv2.ts | 1 + 9 files changed, 47 insertions(+), 20 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/Row.vue b/packages/nc-gui/components/smartsheet/Row.vue index 80a806bdfb..4b5567e90e 100644 --- a/packages/nc-gui/components/smartsheet/Row.vue +++ b/packages/nc-gui/components/smartsheet/Row.vue @@ -21,7 +21,10 @@ const currentRow = toRef(props, 'row') const { meta } = useSmartsheetStoreOrThrow() -const { isNew, state, syncLTARRefs, clearLTARCell, addLTARRef, cleaMMCell } = useProvideSmartsheetRowStore(meta as Ref, currentRow) +const { isNew, state, syncLTARRefs, clearLTARCell, addLTARRef, cleaMMCell } = useProvideSmartsheetRowStore( + meta as Ref, + currentRow, +) const reloadViewDataTrigger = inject(ReloadViewDataHookInj)! @@ -41,7 +44,7 @@ defineExpose({ syncLTARRefs, clearLTARCell, addLTARRef, - cleaMMCell + cleaMMCell, }) diff --git a/packages/nc-gui/components/smartsheet/grid/Table.vue b/packages/nc-gui/components/smartsheet/grid/Table.vue index 63378c34d4..b3a8bb8301 100644 --- a/packages/nc-gui/components/smartsheet/grid/Table.vue +++ b/packages/nc-gui/components/smartsheet/grid/Table.vue @@ -29,15 +29,18 @@ import { getEnumColorByIndex, iconMap, inject, + isBt, isColumnRequiredAndNull, isDrawerOrModalExist, isEeUI, isMac, + isMm, message, onClickOutside, onMounted, provide, ref, + useApi, useEventListener, useI18n, useMultiSelect, @@ -50,7 +53,6 @@ import { useViewColumnsOrThrow, useViewsStore, watch, - useApi } from '#imports' import type { CellRange, Row } from '#imports' @@ -291,7 +293,6 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = rowId === extractPkFromRow(rowObj.row, meta.value?.columns as ColumnType[]) && columnObj.id === col.id ) { - if (rowRefs.value) { if (isBt(columnObj)) { rowObj.row[columnObj.title] = row.row[columnObj.title] @@ -299,7 +300,12 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = await rowRefs.value[ctx.row]!.addLTARRef(rowObj.row[columnObj.title], columnObj) await rowRefs.value[ctx.row]!.syncLTARRefs(rowObj.row) } else if (isMm(columnObj)) { - await api.dbDataTableRow.nestedLink(meta.value?.id as string, columnObj.id as string, encodeURIComponent(rowId as string), mmClearResult) + await api.dbDataTableRow.nestedLink( + meta.value?.id as string, + columnObj.id as string, + encodeURIComponent(rowId as string), + mmClearResult, + ) rowObj.row[columnObj.title] = mmClearResult?.length ? mmClearResult?.length : null } } @@ -319,7 +325,7 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = args: [clone(ctx), clone(columnObj), clone(rowObj), clone(paginationDataRef.value), mmClearResult], }, redo: { - fn: async (ctx: { row: number; col: number }, col: ColumnType, row: Row, pg: PaginatedType, mmClearResult:any[]) => { + fn: async (ctx: { row: number; col: number }, col: ColumnType, row: Row, pg: PaginatedType) => { if (paginationDataRef.value?.pageSize === pg.pageSize) { if (paginationDataRef.value?.page !== pg.page) { await changePage?.(pg.page!) @@ -331,7 +337,7 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = if (rowRefs.value) { if (isBt(columnObj)) { await rowRefs.value[ctx.row]!.clearLTARCell(columnObj) - } else if (isMm(columnObj)){ + } else if (isMm(columnObj)) { await rowRefs.value[ctx.row]!.cleaMMCell(columnObj) } } @@ -347,7 +353,7 @@ async function clearCell(ctx: { row: number; col: number } | null, skipUpdate = throw new Error(t('msg.pageSizeChanged')) } }, - args: [clone(ctx), clone(columnObj), clone(rowObj), clone(paginationDataRef.value), mmClearResult], + args: [clone(ctx), clone(columnObj), clone(rowObj), clone(paginationDataRef.value)], }, scope: defineViewScope({ view: view.value }), }) @@ -912,13 +918,20 @@ async function clearSelectedRangeOfCells() { const cols = fields.value.slice(startCol, endCol + 1) const rows = dataRef.value.slice(startRow, endRow + 1) const props = [] + let isInfoShown = false for (const row of rows) { for (const col of cols) { if (!row || !col || !col.title) continue // TODO handle LinkToAnotherRecord - if (isVirtualCol(col)) continue + if (isVirtualCol(col)) { + if ((isBt(col) || isMm(col)) && !isInfoShown) { + message.info(t('msg.info.groupClearIsNotSupportedOnLinksColumn')) + isInfoShown = true + } + continue + } row.row[col.title] = null props.push(col.title) diff --git a/packages/nc-gui/composables/useLTARStore.ts b/packages/nc-gui/composables/useLTARStore.ts index 51882e0673..14b43b745c 100644 --- a/packages/nc-gui/composables/useLTARStore.ts +++ b/packages/nc-gui/composables/useLTARStore.ts @@ -1,14 +1,11 @@ -import { +import { UITypes, dateFormats, parseStringDateTime, timeFormats } from 'nocodb-sdk' +import type { type ColumnType, type LinkToAnotherRecordType, type PaginatedType, + RelationTypes, type RequestParams, type TableType, - UITypes, - dateFormats, - parseStringDateTime, - timeFormats, - RelationTypes, } from 'nocodb-sdk' import type { ComputedRef, Ref } from 'vue' import { diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index 9de520ff92..a510c05de0 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -825,6 +825,7 @@ export function useMultiSelect( const propsToPaste: string[] = [] let pastedRows = 0 + let isInfoShown = false for (let i = 0; i < pasteMatrixRows; i++) { const pasteRow = rowsToPaste[i] @@ -838,6 +839,10 @@ export function useMultiSelect( const pasteCol = colsToPaste[j] if (!isPasteable(pasteRow, pasteCol)) { + if ((isBt(pasteCol) || isMm(pasteCol)) && !isInfoShown) { + message.info(t('msg.info.groupPasteIsNotSupportedOnLinksColumn')) + isInfoShown = true + } continue } @@ -1070,13 +1075,20 @@ export function useMultiSelect( const props = [] let pasteValue + let isInfoShown = false + const files = e.clipboardData?.files + for (const row of rows) { // TODO handle insert new row if (!row || row.rowMeta.new) continue for (const col of cols) { if (!col.title || !isPasteable(row, col)) { + if ((isBt(col) || isMm(col)) && !isInfoShown) { + message.info(t('msg.info.groupPasteIsNotSupportedOnLinksColumn')) + isInfoShown = true + } continue } diff --git a/packages/nc-gui/composables/useSmartsheetRowStore.ts b/packages/nc-gui/composables/useSmartsheetRowStore.ts index 0e68daada8..ad86ab3366 100644 --- a/packages/nc-gui/composables/useSmartsheetRowStore.ts +++ b/packages/nc-gui/composables/useSmartsheetRowStore.ts @@ -190,8 +190,6 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState( try { if (!column || !isLinksOrLTAR(column)) return - const relatedTableMeta = metas.value?.[(column?.colOptions)?.fk_related_model_id as string] - if (isNew.value) { state.value[column.title!] = null } else if (currentRow.value) { diff --git a/packages/nc-gui/composables/useViewSorts.ts b/packages/nc-gui/composables/useViewSorts.ts index ab510c2237..75032b0eab 100644 --- a/packages/nc-gui/composables/useViewSorts.ts +++ b/packages/nc-gui/composables/useViewSorts.ts @@ -1,7 +1,7 @@ import type { ColumnType, SortType, ViewType } from 'nocodb-sdk' import type { Ref } from 'vue' -import type { UndoRedoAction } from '~/lib' import type { EventHook } from '@vueuse/core' +import type { UndoRedoAction } from '~/lib' import { IsPublicInj, ReloadViewDataHookInj, diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json index a2786d1463..cf09521c93 100644 --- a/packages/nc-gui/lang/en.json +++ b/packages/nc-gui/lang/en.json @@ -1255,7 +1255,10 @@ "thankYou": "Thank you!", "submittedFormData": "You have successfully submitted the form data.", "editingSystemKeyNotSupported": "Editing system key not supported", - "notAvailableAtTheMoment": "Not available at the moment" + "notAvailableAtTheMoment": "Not available at the moment", + "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", + "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" + }, "error": { "scopesRequired": "Scopes required", diff --git a/packages/nc-gui/utils/dataUtils.ts b/packages/nc-gui/utils/dataUtils.ts index 1bea695361..566d5e5404 100644 --- a/packages/nc-gui/utils/dataUtils.ts +++ b/packages/nc-gui/utils/dataUtils.ts @@ -1,7 +1,7 @@ import { RelationTypes, UITypes, isLinksOrLTAR, isSystemColumn, isVirtualCol } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk' -import type { Row } from '~/lib' import { isColumnRequiredAndNull } from './columnUtils' +import type { Row } from '~/lib' export const extractPkFromRow = (row: Record, columns: ColumnType[]) => { if (!row || !columns) return null diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index e0bfb3f3ee..b6a7c16034 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -5168,6 +5168,7 @@ class BaseModelSqlv2 { ]), ); }); + if (parentTable.primaryKeys.length > 1) { childRowsQb.where((qb) => { for (const childId of childIds) { From 9c05cdaa25a75fa6b2ce807a955839ed9239bca1 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:23 +0000 Subject: [PATCH 18/19] fix(nv-gui): undo redo issue of bt col cell --- packages/nc-gui/composables/useMultiSelect/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts index a510c05de0..ebc3d11e4b 100644 --- a/packages/nc-gui/composables/useMultiSelect/index.ts +++ b/packages/nc-gui/composables/useMultiSelect/index.ts @@ -900,6 +900,12 @@ export function useMultiSelect( const relatedTableMeta = await getMeta((columnObj.colOptions as LinkToAnotherRecordType).fk_related_model_id!) + // update old row to allow undo redo as bt column update only through foreignKeyColumn title + rowObj.oldRow[columnObj.title!] = rowObj.row[columnObj.title!] + rowObj.oldRow[foreignKeyColumn.title!] = rowObj.row[columnObj.title!] + ? extractPkFromRow(rowObj.row[columnObj.title!], (relatedTableMeta as any)!.columns!) + : null + rowObj.row[columnObj.title!] = pasteVal?.value rowObj.row[foreignKeyColumn.title!] = pasteVal?.value From 0483af6b49c49e212f5f9bc2ce37545f09cdd566 Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Mon, 19 Feb 2024 03:41:23 +0000 Subject: [PATCH 19/19] fix(nc-gui): mm cell redo undo issue --- .../components/smartsheet/grid/Table.vue | 4 +- .../composables/useMultiSelect/index.ts | 163 ++++++++++++------ 2 files changed, 114 insertions(+), 53 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/grid/Table.vue b/packages/nc-gui/components/smartsheet/grid/Table.vue index b3a8bb8301..e0f1393520 100644 --- a/packages/nc-gui/components/smartsheet/grid/Table.vue +++ b/packages/nc-gui/components/smartsheet/grid/Table.vue @@ -1,7 +1,7 @@