From 4f76ebffcd6f6428e5f11b620480c59f5c9c00bc Mon Sep 17 00:00:00 2001 From: Pranav C Date: Mon, 11 Apr 2022 17:21:26 +0530 Subject: [PATCH] wip Signed-off-by: Pranav C --- packages/nc-gui/package-lock.json | 79 ++- packages/nc-gui/package.json | 2 +- packages/nocodb/package-lock.json | 79 ++- .../noco/meta/api/dataApis/dataAliasApis.ts | 44 +- .../meta/api/dataApis/dataAliasExportApis.ts | 44 ++ .../src/lib/noco/meta/api/dataApis/helpers.ts | 155 +++++ .../src/lib/noco/meta/api/exportApis.ts | 136 +---- scripts/sdk/swagger.json | 569 +++++++++++------- 8 files changed, 707 insertions(+), 401 deletions(-) create mode 100644 packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasExportApis.ts create mode 100644 packages/nocodb/src/lib/noco/meta/api/dataApis/helpers.ts diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json index 64c5383bdd..b81a35b561 100644 --- a/packages/nc-gui/package-lock.json +++ b/packages/nc-gui/package-lock.json @@ -26,7 +26,7 @@ "monaco-editor": "^0.19.3", "monaco-themes": "^0.2.5", "nano-assign": "^1.0.1", - "nocodb-sdk": "0.0.9", + "nocodb-sdk": "file:../nocodb-sdk", "nuxt": "^2.14.0", "odometer": "^0.4.8", "papaparse": "^5.3.1", @@ -69,6 +69,42 @@ "vue-eslint-parser": "^7.9.0" } }, + "../nocodb-sdk": { + "version": "0.0.9", + "license": "MIT", + "dependencies": { + "axios": "^0.21.1", + "jsep": "^0.4.0" + }, + "devDependencies": { + "@ava/typescript": "^1.1.1", + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@typescript-eslint/eslint-plugin": "^4.0.1", + "@typescript-eslint/parser": "^4.0.1", + "ava": "^3.12.1", + "codecov": "^3.5.0", + "cspell": "^4.1.0", + "cz-conventional-changelog": "^3.3.0", + "eslint": "^7.8.0", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-functional": "^3.0.2", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-prettier": "^4.0.0", + "gh-pages": "^3.1.0", + "npm-run-all": "^4.1.5", + "nyc": "^15.1.0", + "open-cli": "^6.0.1", + "prettier": "^2.1.1", + "standard-version": "^9.0.0", + "ts-node": "^9.0.0", + "typedoc": "^0.19.0", + "typescript": "^4.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@ampproject/remapping": { "version": "2.1.2", "license": "Apache-2.0", @@ -9541,16 +9577,8 @@ } }, "node_modules/nocodb-sdk": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.0.9.tgz", - "integrity": "sha512-MwvHh9WtplJtB2z41DbDUF09bYRLX4WBA+IytgPRWr5e3s8UEBzKZiKN7sLcVnmiY6a9ctT4Ad0CS4viwExoQw==", - "dependencies": { - "axios": "^0.21.1", - "jsep": "^0.4.0" - }, - "engines": { - "node": ">=10" - } + "resolved": "../nocodb-sdk", + "link": true }, "node_modules/node-fetch": { "version": "2.6.7", @@ -21397,12 +21425,33 @@ } }, "nocodb-sdk": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.0.9.tgz", - "integrity": "sha512-MwvHh9WtplJtB2z41DbDUF09bYRLX4WBA+IytgPRWr5e3s8UEBzKZiKN7sLcVnmiY6a9ctT4Ad0CS4viwExoQw==", + "version": "file:../nocodb-sdk", "requires": { + "@ava/typescript": "^1.1.1", + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@typescript-eslint/eslint-plugin": "^4.0.1", + "@typescript-eslint/parser": "^4.0.1", + "ava": "^3.12.1", "axios": "^0.21.1", - "jsep": "^0.4.0" + "codecov": "^3.5.0", + "cspell": "^4.1.0", + "cz-conventional-changelog": "^3.3.0", + "eslint": "^7.8.0", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-functional": "^3.0.2", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-prettier": "^4.0.0", + "gh-pages": "^3.1.0", + "jsep": "^0.4.0", + "npm-run-all": "^4.1.5", + "nyc": "^15.1.0", + "open-cli": "^6.0.1", + "prettier": "^2.1.1", + "standard-version": "^9.0.0", + "ts-node": "^9.0.0", + "typedoc": "^0.19.0", + "typescript": "^4.0.2" } }, "node-fetch": { diff --git a/packages/nc-gui/package.json b/packages/nc-gui/package.json index 0d4d1143c0..67e5eb682c 100644 --- a/packages/nc-gui/package.json +++ b/packages/nc-gui/package.json @@ -29,7 +29,7 @@ "monaco-editor": "^0.19.3", "monaco-themes": "^0.2.5", "nano-assign": "^1.0.1", - "nocodb-sdk": "0.0.9", + "nocodb-sdk": "file:../nocodb-sdk", "nuxt": "^2.14.0", "odometer": "^0.4.8", "papaparse": "^5.3.1", diff --git a/packages/nocodb/package-lock.json b/packages/nocodb/package-lock.json index c236fa1309..5b18455bdd 100644 --- a/packages/nocodb/package-lock.json +++ b/packages/nocodb/package-lock.json @@ -72,7 +72,7 @@ "nc-lib-gui": "0.84.15", "nc-plugin": "^0.1.1", "ncp": "^2.0.0", - "nocodb-sdk": "0.0.9", + "nocodb-sdk": "file:../nocodb-sdk", "nodemailer": "^6.4.10", "ora": "^4.0.4", "os-locale": "^5.0.0", @@ -227,6 +227,42 @@ "node": ">=8.9" } }, + "../nocodb-sdk": { + "version": "0.0.9", + "license": "MIT", + "dependencies": { + "axios": "^0.21.1", + "jsep": "^0.4.0" + }, + "devDependencies": { + "@ava/typescript": "^1.1.1", + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@typescript-eslint/eslint-plugin": "^4.0.1", + "@typescript-eslint/parser": "^4.0.1", + "ava": "^3.12.1", + "codecov": "^3.5.0", + "cspell": "^4.1.0", + "cz-conventional-changelog": "^3.3.0", + "eslint": "^7.8.0", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-functional": "^3.0.2", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-prettier": "^4.0.0", + "gh-pages": "^3.1.0", + "npm-run-all": "^4.1.5", + "nyc": "^15.1.0", + "open-cli": "^6.0.1", + "prettier": "^2.1.1", + "standard-version": "^9.0.0", + "ts-node": "^9.0.0", + "typedoc": "^0.19.0", + "typescript": "^4.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@assemblyscript/loader": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", @@ -16216,16 +16252,8 @@ "dev": true }, "node_modules/nocodb-sdk": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.0.9.tgz", - "integrity": "sha512-MwvHh9WtplJtB2z41DbDUF09bYRLX4WBA+IytgPRWr5e3s8UEBzKZiKN7sLcVnmiY6a9ctT4Ad0CS4viwExoQw==", - "dependencies": { - "axios": "^0.21.1", - "jsep": "^0.4.0" - }, - "engines": { - "node": ">=10" - } + "resolved": "../nocodb-sdk", + "link": true }, "node_modules/node-addon-api": { "version": "2.0.0", @@ -37627,12 +37655,33 @@ "dev": true }, "nocodb-sdk": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.0.9.tgz", - "integrity": "sha512-MwvHh9WtplJtB2z41DbDUF09bYRLX4WBA+IytgPRWr5e3s8UEBzKZiKN7sLcVnmiY6a9ctT4Ad0CS4viwExoQw==", + "version": "file:../nocodb-sdk", "requires": { + "@ava/typescript": "^1.1.1", + "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@typescript-eslint/eslint-plugin": "^4.0.1", + "@typescript-eslint/parser": "^4.0.1", + "ava": "^3.12.1", "axios": "^0.21.1", - "jsep": "^0.4.0" + "codecov": "^3.5.0", + "cspell": "^4.1.0", + "cz-conventional-changelog": "^3.3.0", + "eslint": "^7.8.0", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-functional": "^3.0.2", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-prettier": "^4.0.0", + "gh-pages": "^3.1.0", + "jsep": "^0.4.0", + "npm-run-all": "^4.1.5", + "nyc": "^15.1.0", + "open-cli": "^6.0.1", + "prettier": "^2.1.1", + "standard-version": "^9.0.0", + "ts-node": "^9.0.0", + "typedoc": "^0.19.0", + "typescript": "^4.0.2" } }, "node-addon-api": { diff --git a/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasApis.ts b/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasApis.ts index 92b16f9341..0167b8692f 100644 --- a/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasApis.ts +++ b/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasApis.ts @@ -6,16 +6,15 @@ import NcConnectionMgrv2 from '../../../common/NcConnectionMgrv2'; import { PagedResponseImpl } from '../../helpers/PagedResponse'; import View from '../../../../noco-models/View'; import ncMetaAclMw from '../../helpers/ncMetaAclMw'; -import Project from '../../../../noco-models/Project'; -import { NcError } from '../../helpers/catchError'; +import { getViewAndModelFromRequestByAliasOrId } from './helpers'; export async function dataList(req: Request, res: Response) { - const { model, view } = await getViewAndModelFromRequest(req); + const { model, view } = await getViewAndModelFromRequestByAliasOrId(req); res.json(await getDataList(model, view, req)); } async function dataInsert(req: Request, res: Response) { - const { model, view } = await getViewAndModelFromRequest(req); + const { model, view } = await getViewAndModelFromRequestByAliasOrId(req); const base = await Base.get(model.base_id); @@ -29,7 +28,7 @@ async function dataInsert(req: Request, res: Response) { } async function dataUpdate(req: Request, res: Response) { - const { model, view } = await getViewAndModelFromRequest(req); + const { model, view } = await getViewAndModelFromRequestByAliasOrId(req); const base = await Base.get(model.base_id); const baseModel = await Model.getBaseModelSQL({ @@ -42,7 +41,7 @@ async function dataUpdate(req: Request, res: Response) { } async function dataDelete(req: Request, res: Response) { - const { model, view } = await getViewAndModelFromRequest(req); + const { model, view } = await getViewAndModelFromRequestByAliasOrId(req); const base = await Base.get(model.base_id); const baseModel = await Model.getBaseModelSQL({ id: model.id, @@ -85,25 +84,9 @@ async function getDataList(model, view: View, req) { count }); } -async function getViewAndModelFromRequest(req) { - const project = await Project.getWithInfoByTitle(req.params.projectName); - const model = await Model.getByAliasOrId({ - project_id: project.id, - base_id: project.bases?.[0]?.id, - aliasOrId: req.params.tableName - }); - const view = - req.params.viewName && - (await View.getByTitleOrId({ - titleOrId: req.params.viewName, - fk_model_id: model.id - })); - if (!model) NcError.notFound('Table not found'); - return { model, view }; -} async function dataRead(req: Request, res: Response) { - const { model, view } = await getViewAndModelFromRequest(req); + const { model, view } = await getViewAndModelFromRequestByAliasOrId(req); const base = await Base.get(model.base_id); @@ -125,26 +108,29 @@ async function dataRead(req: Request, res: Response) { const router = Router({ mergeParams: true }); -router.get('/data/:orgs/:projectName/:tableName', ncMetaAclMw(dataList, 'dataList')); router.get( - '/data/:orgs/:projectName/:tableName/views/:viewName', + '/api/v1/db/data/:orgs/:projectName/:tableName', + ncMetaAclMw(dataList, 'dataList') +); +router.get( + '/api/v1/db/data/:orgs/:projectName/:tableName/views/:viewName', ncMetaAclMw(dataList, 'dataList') ); router.post( - '/data/:orgs/:projectName/:tableName/views/:viewName', + '/api/v1/db/data/:orgs/:projectName/:tableName/views/:viewName', ncMetaAclMw(dataInsert, 'dataInsert') ); router.put( - '/data/:orgs/:projectName/:tableName/views/:viewName/:rowId', + '/api/v1/db/data/:orgs/:projectName/:tableName/views/:viewName/:rowId', ncMetaAclMw(dataUpdate, 'dataUpdate') ); router.get( - '/data/:orgs/:projectName/:tableName/views/:viewName/:rowId', + '/api/v1/db/data/:orgs/:projectName/:tableName/views/:viewName/:rowId', ncMetaAclMw(dataRead, 'dataRead') ); router.delete( - '/data/:orgs/:projectName/:tableName/views/:viewName/:rowId', + '/api/v1/db/data/:orgs/:projectName/:tableName/views/:viewName/:rowId', ncMetaAclMw(dataDelete, 'dataDelete') ); diff --git a/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasExportApis.ts b/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasExportApis.ts new file mode 100644 index 0000000000..7f0ab6e9f7 --- /dev/null +++ b/packages/nocodb/src/lib/noco/meta/api/dataApis/dataAliasExportApis.ts @@ -0,0 +1,44 @@ +import { Request, Response, Router } from 'express'; +import ncMetaAclMw from '../../helpers/ncMetaAclMw'; +import { + extractCsvData, + getViewAndModelFromRequestByAliasOrId +} from './helpers'; +import papaparse from 'papaparse'; + +async function csvDataExport(req: Request, res: Response) { + const { model, view } = await getViewAndModelFromRequestByAliasOrId(req); + + const { offset, csvRows, elapsed } = await extractCsvData(model, view, req); + + const data = papaparse.unparse( + { + fields: model.columns.map(c => c.title), + data: csvRows + }, + { + escapeFormulae: true + } + ); + + res.set({ + 'Access-Control-Expose-Headers': 'nc-export-offset', + 'nc-export-offset': offset, + 'nc-export-elapsed-time': elapsed, + 'Content-Disposition': `attachment; filename="${view.title}-export.csv"` + }); + res.send(data); +} + +const router = Router({ mergeParams: true }); + +router.get( + '/api/v1/db/data/:orgs/:projectName/:tableName/export/csv', + ncMetaAclMw(csvDataExport, 'csvDataExport') +); +router.get( + '/api/v1/db/data/:orgs/:projectName/:tableName/views/:viewName/export/csv', + ncMetaAclMw(csvDataExport, 'csvDataExport') +); + +export default router; diff --git a/packages/nocodb/src/lib/noco/meta/api/dataApis/helpers.ts b/packages/nocodb/src/lib/noco/meta/api/dataApis/helpers.ts new file mode 100644 index 0000000000..1ec91fe880 --- /dev/null +++ b/packages/nocodb/src/lib/noco/meta/api/dataApis/helpers.ts @@ -0,0 +1,155 @@ +import Project from '../../../../noco-models/Project'; +import Model from '../../../../noco-models/Model'; +import View from '../../../../noco-models/View'; +import { NcError } from '../../helpers/catchError'; +import { Request } from 'express'; +import Base from '../../../../noco-models/Base'; +import NcConnectionMgrv2 from '../../../common/NcConnectionMgrv2'; +import { isSystemColumn, UITypes } from 'nocodb-sdk'; + +import { nocoExecute } from 'nc-help'; +import Column from '../../../../noco-models/Column'; +import LookupColumn from '../../../../noco-models/LookupColumn'; +import LinkToAnotherRecordColumn from '../../../../noco-models/LinkToAnotherRecordColumn'; + +export async function getViewAndModelFromRequestByAliasOrId( + req: + | Request<{ projectName: string; tableName: string; viewName?: string }> + | Request +) { + let project = await Project.getWithInfoByTitle(req.params.projectName); + + if (!project) { + project = await Project.getWithInfo(req.params.projectName); + } + + const model = await Model.getByAliasOrId({ + project_id: project.id, + base_id: project.bases?.[0]?.id, + aliasOrId: req.params.tableName + }); + const view = + req.params.viewName && + (await View.getByTitleOrId({ + titleOrId: req.params.viewName, + fk_model_id: model.id + })); + if (!model) NcError.notFound('Table not found'); + return { model, view }; +} + +export async function extractCsvData(model: Model, view: View, req: Request) { + const base = await Base.get(model.base_id); + const baseModel = await Model.getBaseModelSQL({ + id: model.id, + viewId: view?.id, + dbDriver: NcConnectionMgrv2.get(base) + }); + + let offset = +req.query.offset || 0; + const limit = 100; + // const size = +process.env.NC_EXPORT_MAX_SIZE || 1024; + const timeout = +process.env.NC_EXPORT_MAX_TIMEOUT || 5000; + const csvRows = []; + const startTime = process.hrtime(); + let elapsed, temp; + + for ( + elapsed = 0; + elapsed < timeout; + offset += limit, + temp = process.hrtime(startTime), + elapsed = temp[0] * 1000 + temp[1] / 1000000 + ) { + const rows = await nocoExecute( + await baseModel.defaultResolverReq(req.query, false, false), + await baseModel.list({ ...req.query, offset, limit }), + {}, + req.query + ); + + if (!rows?.length) { + offset = -1; + break; + } + + for (const row of rows) { + const csvRow = { ...row }; + + for (const column of view.model.columns) { + if (isSystemColumn(column) && !view.show_system_fields) continue; + csvRow[column.title] = await serializeCellValue({ + value: row[column.title], + column + }); + } + csvRows.push(csvRow); + } + } + return { offset, csvRows, elapsed }; +} + +export async function serializeCellValue({ + value, + column +}: { + column?: Column; + value: any; +}) { + if (!column) { + return value; + } + + if (!value) return value; + + switch (column?.uidt) { + case UITypes.Attachment: { + let data = value; + try { + if (typeof value === 'string') { + data = JSON.parse(value); + } + } catch {} + + return (data || []).map( + attachment => + `${encodeURI(attachment.title)}(${encodeURI(attachment.url)})` + ); + } + case UITypes.Lookup: + { + const colOptions = await column.getColOptions(); + const lookupColumn = await colOptions.getLookupColumn(); + return ( + await Promise.all( + [...(Array.isArray(value) ? value : [value])].map(async v => + serializeCellValue({ + value: v, + column: lookupColumn + }) + ) + ) + ).join(', '); + } + break; + case UITypes.LinkToAnotherRecord: + { + const colOptions = await column.getColOptions< + LinkToAnotherRecordColumn + >(); + const relatedModel = await colOptions.getRelatedTable(); + await relatedModel.getColumns(); + return [...(Array.isArray(value) ? value : [value])] + .map(v => { + return v[relatedModel.primaryValue?.title]; + }) + .join(', '); + } + break; + default: + if (value && typeof value === 'object') { + return JSON.stringify(value); + } + return value; + } +} diff --git a/packages/nocodb/src/lib/noco/meta/api/exportApis.ts b/packages/nocodb/src/lib/noco/meta/api/exportApis.ts index d995aefa25..0f2c2b14d9 100644 --- a/packages/nocodb/src/lib/noco/meta/api/exportApis.ts +++ b/packages/nocodb/src/lib/noco/meta/api/exportApis.ts @@ -1,15 +1,10 @@ import { Request, Response, Router } from 'express'; import View from '../../../noco-models/View'; -import Model from '../../../noco-models/Model'; -import Base from '../../../noco-models/Base'; -import NcConnectionMgrv2 from '../../common/NcConnectionMgrv2'; -import { nocoExecute } from 'nc-help'; import papaparse from 'papaparse'; -import { isSystemColumn, UITypes } from 'nocodb-sdk'; +import { isSystemColumn } from 'nocodb-sdk'; import Column from '../../../noco-models/Column'; -import LinkToAnotherRecordColumn from '../../../noco-models/LinkToAnotherRecordColumn'; -import LookupColumn from '../../../noco-models/LookupColumn'; import ncMetaAclMw from '../helpers/ncMetaAclMw'; +import { extractCsvData } from './dataApis/helpers'; async function exportCsv(req: Request, res: Response, next) { const view = await View.get(req.params.viewId); @@ -26,67 +21,7 @@ async function exportCsv(req: Request, res: Response, next) { .filter(column => !isSystemColumn(column) || view.show_system_fields); if (!model) return next(new Error('Table not found')); - - const base = await Base.get(model.base_id); - const baseModel = await Model.getBaseModelSQL({ - id: model.id, - viewId: view?.id, - dbDriver: NcConnectionMgrv2.get(base) - }); - - const key = `${model.title}List`; - const requestObj = { - [key]: await baseModel.defaultResolverReq(req.query, false, false) - }; - - let offset = +req.query.offset || 0; - const limit = 100; - // const size = +process.env.NC_EXPORT_MAX_SIZE || 1024; - const timeout = +process.env.NC_EXPORT_MAX_TIMEOUT || 5000; - const csvRows = []; - const startTime = process.hrtime(); - let elapsed, temp; - - for ( - elapsed = 0; - elapsed < timeout; - offset += limit, - temp = process.hrtime(startTime), - elapsed = temp[0] * 1000 + temp[1] / 1000000 - ) { - console.time('nocoExecute'); - const rows = ( - await nocoExecute( - requestObj, - { - [key]: async args => { - return await baseModel.list({ ...args, offset, limit }); - } - }, - {}, - { nested: { [key]: req.query } } - ) - )?.[key]; - - if (!rows?.length) { - offset = -1; - break; - } - - for (const row of rows) { - const csvRow = { ...row }; - - for (const column of view.model.columns) { - if (isSystemColumn(column) && !view.show_system_fields) continue; - csvRow[column.title] = await serializeCellValue({ - value: row[column.title], - column - }); - } - csvRows.push(csvRow); - } - console.timeEnd('nocoExecute'); - } + const { offset, csvRows, elapsed } = await extractCsvData(model, view, req); const data = papaparse.unparse( { @@ -107,71 +42,6 @@ async function exportCsv(req: Request, res: Response, next) { res.send(data); } -async function serializeCellValue({ - value, - column -}: { - column?: Column; - value: any; -}) { - if (!column) { - return value; - } - - if (!value) return value; - - switch (column?.uidt) { - case UITypes.Attachment: { - let data = value; - try { - if (typeof value === 'string') { - data = JSON.parse(value); - } - } catch {} - - return (data || []).map( - attachment => - `${encodeURI(attachment.title)}(${encodeURI(attachment.url)})` - ); - } - case UITypes.Lookup: - { - const colOptions = await column.getColOptions(); - const lookupColumn = await colOptions.getLookupColumn(); - return ( - await Promise.all( - [...(Array.isArray(value) ? value : [value])].map(async v => - serializeCellValue({ - value: v, - column: lookupColumn - }) - ) - ) - ).join(', '); - } - break; - case UITypes.LinkToAnotherRecord: - { - const colOptions = await column.getColOptions< - LinkToAnotherRecordColumn - >(); - const relatedModel = await colOptions.getRelatedTable(); - await relatedModel.getColumns(); - return [...(Array.isArray(value) ? value : [value])] - .map(v => { - return v[relatedModel.primaryValue?.title]; - }) - .join(', '); - } - break; - default: - if (value && typeof value === 'object') { - return JSON.stringify(value); - } - return value; - } -} - const router = Router({ mergeParams: true }); router.get('/data/:viewId/export/csv', ncMetaAclMw(exportCsv, 'exportCsv')); export default router; diff --git a/scripts/sdk/swagger.json b/scripts/sdk/swagger.json index 7df510d1c4..11be38b85d 100644 --- a/scripts/sdk/swagger.json +++ b/scripts/sdk/swagger.json @@ -2817,7 +2817,59 @@ } } }, - "/data/{orgs}/{projectName}/{tableAlias}": { + "/data/{tableId}/export/{type}": { + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "tableId", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string", + "enum": [ + "csv", + "excel" + ] + }, + "name": "type", + "in": "path", + "required": true + } + ], + "get": { + "summary": "", + "operationId": "data-csv-export", + "description": "CSV or Excel export", + "tags": [ + "Data" + ], + "wrapped": true, + "responses": { + "200": { + "description": "OK", + "content": { + "application/octet-stream": { + "schema": {} + } + }, + "headers": { + "nc-export-offset": { + "schema": { + "type": "integer" + } + } + } + } + }, + "parameters": [] + } + }, + + "/api/v1/db/data/{orgs}/{projectName}/{tableAlias}": { "parameters": [ { "schema": { @@ -2910,7 +2962,7 @@ } } }, - "/data/{orgs}/{projectName}/{tableAlias}/views/{viewName}": { + "/api/v1/db/data/{orgs}/{projectName}/{tableAlias}/views/{viewName}": { "parameters": [ { "schema": { @@ -2991,39 +3043,328 @@ } } } - }, - "post": { + }, + "post": { + "summary": "", + "operationId": "db-view-row-create", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "tags": [ + "DB View Row" + ], + "requestBody": { + "content": { + "application/json": { + "schema": {} + } + } + } + } + }, + "/api/v1/db/data/{orgs}/{projectName}/{tableAlias}/views/{viewName}/{rowId}": { + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "orgs", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "projectName", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "tableAlias", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "viewName", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "rowId", + "in": "path", + "required": true + } + ], + "get": { + "summary": "", + "operationId": "db-view-row-read", + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "description": "", + "tags": [ + "DB View Row" + ] + }, + "put": { + "summary": "", + "operationId": "db-view-row-update", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "tags": [ + "DB View Row" + ], + "requestBody": { + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "delete": { + "summary": "", + "operationId": "db-view-row-delete", + "responses": { + "200": { + "description": "OK" + } + }, + "tags": [ + "DB View Row" + ], + "description": "" + } + }, + "/api/v1/db/data/{orgs}/{projectName}/{tableAlias}/{rowId}": { + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "orgs", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "projectName", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "tableAlias", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "rowId", + "in": "path", + "required": true + } + ], + "get": { + "summary": "", + "operationId": "db-table-row-read", + "responses": { + "201": { + "description": "Created", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "description": "", + "tags": [ + "DB Table Row" + ] + }, + "put": { + "summary": "", + "operationId": "db-table-row-update", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "tags": [ + "DB Table Row" + ], + "requestBody": { + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "delete": { + "summary": "", + "operationId": "db-table-row-model-delete", + "responses": { + "200": { + "description": "OK" + } + }, + "tags": [ + "DB Table Row" + ], + "description": "" + } + }, + "/api/v1/db/data/{orgs}/{projectName}/{tableAlias}/views/{viewName}/export/{type}": { + "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "orgs", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "projectName", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "tableAlias", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "viewName", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string", + "enum": [ + "csv", + "excel" + ] + }, + "name": "type", + "in": "path", + "required": true + } + ], + "get": { "summary": "", - "operationId": "db-view-row-create", + "operationId": "data-csv-export", + "description": "CSV or Excel export", + "tags": [ + "Data" + ], + "wrapped": true, "responses": { "200": { "description": "OK", "content": { - "application/json": { + "application/octet-stream": { "schema": {} } + }, + "headers": { + "nc-export-offset": { + "schema": { + "type": "integer" + } + } } } }, - "tags": [ - "DB View Row" - ], - "requestBody": { - "content": { - "application/json": { - "schema": {} - } - } - } + "parameters": [] } }, - "/data/{tableId}/export/{type}": { + "/api/v1/db/data/{orgs}/{projectName}/{tableAlias}/export/{type}": { "parameters": [ { "schema": { "type": "string" }, - "name": "tableId", + "name": "orgs", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "projectName", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "tableAlias", + "in": "path", + "required": true + }, + { + "schema": { + "type": "string" + }, + "name": "viewName", "in": "path", "required": true }, @@ -3068,6 +3409,8 @@ "parameters": [] } }, + + "/public/data/{uuid}/list": { "parameters": [ { @@ -3792,196 +4135,6 @@ "description": "" } }, - "/data/{orgs}/{projectName}/{tableAlias}/views/{viewName}/{rowId}": { - "parameters": [ - { - "schema": { - "type": "string" - }, - "name": "orgs", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "projectName", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "tableAlias", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "viewName", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "rowId", - "in": "path", - "required": true - } - ], - "get": { - "summary": "", - "operationId": "db-view-row-read", - "responses": { - "201": { - "description": "Created", - "content": { - "application/json": { - "schema": {} - } - } - } - }, - "description": "", - "tags": [ - "DB View Row" - ] - }, - "put": { - "summary": "", - "operationId": "db-view-row-update", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": {} - } - } - } - }, - "tags": [ - "DB View Row" - ], - "requestBody": { - "content": { - "application/json": { - "schema": {} - } - } - } - }, - "delete": { - "summary": "", - "operationId": "db-view-row-delete", - "responses": { - "200": { - "description": "OK" - } - }, - "tags": [ - "DB View Row" - ], - "description": "" - } - }, - "/data/{orgs}/{projectName}/{tableAlias}/{rowId}": { - "parameters": [ - { - "schema": { - "type": "string" - }, - "name": "orgs", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "projectName", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "tableAlias", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "rowId", - "in": "path", - "required": true - } - ], - "get": { - "summary": "", - "operationId": "db-table-row-read", - "responses": { - "201": { - "description": "Created", - "content": { - "application/json": { - "schema": {} - } - } - } - }, - "description": "", - "tags": [ - "DB Table Row" - ] - }, - "put": { - "summary": "", - "operationId": "db-table-row-update", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": {} - } - } - } - }, - "tags": [ - "DB Table Row" - ], - "requestBody": { - "content": { - "application/json": { - "schema": {} - } - } - } - }, - "delete": { - "summary": "", - "operationId": "db-table-row-model-delete", - "responses": { - "200": { - "description": "OK" - } - }, - "tags": [ - "DB Table Row" - ], - "description": "" - } - }, "/audits/comments": { "parameters": [], "get": {