From 148d4027c8611a6b329acc2361ca4adf3bb38747 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Fri, 27 Jan 2023 23:32:31 +0530 Subject: [PATCH 01/85] chore: update sdk path Signed-off-by: Pranav C --- packages/nc-gui/package-lock.json | 52 +++++++++++---------------- packages/nc-gui/package.json | 2 +- packages/nocodb-sdk/package-lock.json | 4 +-- packages/nocodb/package-lock.json | 30 +++++++++------- packages/nocodb/package.json | 4 +-- 5 files changed, 42 insertions(+), 50 deletions(-) diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json index a5ce071681..09a4b55412 100644 --- a/packages/nc-gui/package-lock.json +++ b/packages/nc-gui/package-lock.json @@ -29,7 +29,7 @@ "jwt-decode": "^3.1.2", "locale-codes": "^1.3.1", "monaco-editor": "^0.33.0", - "nocodb-sdk": "0.104.2", + "nocodb-sdk": "file:../nocodb-sdk", "papaparse": "^5.3.2", "qrcode": "^1.5.1", "socket.io-client": "^4.5.1", @@ -97,7 +97,6 @@ }, "../nocodb-sdk": { "version": "0.104.2", - "extraneous": true, "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", @@ -8545,6 +8544,7 @@ "version": "1.15.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "devOptional": true, "funding": [ { "type": "individual", @@ -11960,21 +11960,8 @@ } }, "node_modules/nocodb-sdk": { - "version": "0.104.2", - "resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.104.2.tgz", - "integrity": "sha512-D5uONEIcx4gFGLBo42AOr4u0ejEG4BvDvRY0pY6EaoEMSbpvWQIia2XTgiAg9JPYuz2AKxSwWYR2AP6H52Nzjg==", - "dependencies": { - "axios": "^0.21.1", - "jsep": "^1.3.6" - } - }, - "node_modules/nocodb-sdk/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dependencies": { - "follow-redirects": "^1.14.0" - } + "resolved": "../nocodb-sdk", + "link": true }, "node_modules/node-abi": { "version": "3.23.0", @@ -23956,7 +23943,8 @@ "follow-redirects": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", - "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "devOptional": true }, "form-data": { "version": "4.0.0", @@ -26429,22 +26417,22 @@ } }, "nocodb-sdk": { - "version": "0.104.2", - "resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.104.2.tgz", - "integrity": "sha512-D5uONEIcx4gFGLBo42AOr4u0ejEG4BvDvRY0pY6EaoEMSbpvWQIia2XTgiAg9JPYuz2AKxSwWYR2AP6H52Nzjg==", + "version": "file:../nocodb-sdk", "requires": { + "@typescript-eslint/eslint-plugin": "^4.0.1", + "@typescript-eslint/parser": "^4.0.1", "axios": "^0.21.1", - "jsep": "^1.3.6" - }, - "dependencies": { - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "requires": { - "follow-redirects": "^1.14.0" - } - } + "cspell": "^4.1.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", + "jsep": "^1.3.6", + "npm-run-all": "^4.1.5", + "prettier": "^2.1.1", + "typescript": "^4.0.2" } }, "node-abi": { diff --git a/packages/nc-gui/package.json b/packages/nc-gui/package.json index 74d0d13928..b7a3e9e7db 100644 --- a/packages/nc-gui/package.json +++ b/packages/nc-gui/package.json @@ -52,7 +52,7 @@ "jwt-decode": "^3.1.2", "locale-codes": "^1.3.1", "monaco-editor": "^0.33.0", - "nocodb-sdk": "0.104.2", + "nocodb-sdk": "file:../nocodb-sdk", "papaparse": "^5.3.2", "qrcode": "^1.5.1", "socket.io-client": "^4.5.1", diff --git a/packages/nocodb-sdk/package-lock.json b/packages/nocodb-sdk/package-lock.json index e3c72f0716..9995b55586 100644 --- a/packages/nocodb-sdk/package-lock.json +++ b/packages/nocodb-sdk/package-lock.json @@ -1,12 +1,12 @@ { "name": "nocodb-sdk", - "version": "0.104.1", + "version": "0.104.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nocodb-sdk", - "version": "0.104.1", + "version": "0.104.2", "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", diff --git a/packages/nocodb/package-lock.json b/packages/nocodb/package-lock.json index 92ab65c890..cddcdc0e98 100644 --- a/packages/nocodb/package-lock.json +++ b/packages/nocodb/package-lock.json @@ -68,7 +68,7 @@ "nc-lib-gui": "0.104.2", "nc-plugin": "0.1.2", "ncp": "^2.0.0", - "nocodb-sdk": "0.104.2", + "nocodb-sdk": "file:../nocodb-sdk", "nodemailer": "^6.4.10", "object-hash": "^3.0.0", "os-locale": "^5.0.0", @@ -154,7 +154,6 @@ }, "../nocodb-sdk": { "version": "0.104.2", - "extraneous": true, "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^0.21.1", @@ -11223,13 +11222,8 @@ "dev": true }, "node_modules/nocodb-sdk": { - "version": "0.104.2", - "resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.104.2.tgz", - "integrity": "sha512-D5uONEIcx4gFGLBo42AOr4u0ejEG4BvDvRY0pY6EaoEMSbpvWQIia2XTgiAg9JPYuz2AKxSwWYR2AP6H52Nzjg==", - "dependencies": { - "axios": "^0.21.1", - "jsep": "^1.3.6" - } + "resolved": "../nocodb-sdk", + "link": true }, "node_modules/node-abort-controller": { "version": "3.0.1", @@ -27742,12 +27736,22 @@ "dev": true }, "nocodb-sdk": { - "version": "0.104.2", - "resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.104.2.tgz", - "integrity": "sha512-D5uONEIcx4gFGLBo42AOr4u0ejEG4BvDvRY0pY6EaoEMSbpvWQIia2XTgiAg9JPYuz2AKxSwWYR2AP6H52Nzjg==", + "version": "file:../nocodb-sdk", "requires": { + "@typescript-eslint/eslint-plugin": "^4.0.1", + "@typescript-eslint/parser": "^4.0.1", "axios": "^0.21.1", - "jsep": "^1.3.6" + "cspell": "^4.1.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", + "jsep": "^1.3.6", + "npm-run-all": "^4.1.5", + "prettier": "^2.1.1", + "typescript": "^4.0.2" } }, "node-abort-controller": { diff --git a/packages/nocodb/package.json b/packages/nocodb/package.json index 0eb35f3f8d..60a7d5bfbe 100644 --- a/packages/nocodb/package.json +++ b/packages/nocodb/package.json @@ -108,7 +108,7 @@ "nc-lib-gui": "0.104.2", "nc-plugin": "0.1.2", "ncp": "^2.0.0", - "nocodb-sdk": "0.104.2", + "nocodb-sdk": "file:../nocodb-sdk", "nodemailer": "^6.4.10", "object-hash": "^3.0.0", "os-locale": "^5.0.0", @@ -183,4 +183,4 @@ "prettier": { "singleQuote": true } -} \ No newline at end of file +} From 769083e3af267b6f67e62f4042279b454bf3806b Mon Sep 17 00:00:00 2001 From: Ekaterina Balakina Date: Fri, 27 Jan 2023 20:36:44 +0100 Subject: [PATCH 02/85] fix condition for row-column adding --- packages/nc-gui/components/smartsheet/Grid.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/Grid.vue b/packages/nc-gui/components/smartsheet/Grid.vue index e3849ad5cb..bccad6a64d 100644 --- a/packages/nc-gui/components/smartsheet/Grid.vue +++ b/packages/nc-gui/components/smartsheet/Grid.vue @@ -101,9 +101,9 @@ const tbodyEl = ref() const gridWrapper = ref() const tableHead = ref() -const isAddingColumnAllowed = !readOnly.value && !isLocked.value && isUIAllowed('add-column') && !isSqlView.value +const isAddingColumnAllowed = $computed(() => !readOnly.value && !isLocked.value && isUIAllowed('add-column') && !isSqlView.value) -const isAddingEmptyRowAllowed = !isView && !isLocked.value && hasEditPermission && !isSqlView.value +const isAddingEmptyRowAllowed = $computed(() => !isView && !isLocked.value && hasEditPermission && !isSqlView.value) const { isLoading, From 67c019714fca1856ef94338fd001786a8534d713 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 28 Jan 2023 10:55:24 +0800 Subject: [PATCH 03/85] chore(nocodb): lint --- .../nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts b/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts index f280ca72d5..be0b2d0799 100644 --- a/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts +++ b/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts @@ -4,7 +4,7 @@ import Base from '../models/Base'; import Model from '../models/Model'; import { XKnex } from '../db/sql-data-mapper/index'; import NcConnectionMgrv2 from '../utils/common/NcConnectionMgrv2'; -import { BaseType, UITypes } from 'nocodb-sdk' +import { BaseType, UITypes } from 'nocodb-sdk'; // before 0.103.0, an attachment object was like // [{ From 404df667a57c50c85be9d94f5eb2ffa2a3029847 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 28 Jan 2023 12:42:39 +0800 Subject: [PATCH 04/85] fix(nc-gui): field query in kanban view --- .../nc-gui/composables/useKanbanViewStore.ts | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/composables/useKanbanViewStore.ts b/packages/nc-gui/composables/useKanbanViewStore.ts index e3c9f130aa..634d72923a 100644 --- a/packages/nc-gui/composables/useKanbanViewStore.ts +++ b/packages/nc-gui/composables/useKanbanViewStore.ts @@ -24,6 +24,7 @@ import { provide, ref, useApi, + useFieldQuery, useGlobal, useI18n, useInjectionState, @@ -66,6 +67,28 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState( const password = ref(null) + const { search } = useFieldQuery() + + const { sqlUis } = useProject() + + const sqlUi = ref(meta.value?.base_id ? sqlUis.value[meta.value?.base_id] : Object.values(sqlUis.value)[0]) + + const xWhere = computed(() => { + let where + const col = + (meta.value as TableType)?.columns?.find(({ id }) => id === search.value.field) || + (meta.value as TableType)?.columns?.find((v) => v.pv) + if (!col) return + + if (!search.value.query.trim()) return + if (['text', 'string'].includes(sqlUi.value.getAbstractType(col)) && col.dt !== 'bigint') { + where = `(${col.title},like,%${search.value.query.trim()}%)` + } else { + where = `(${col.title},eq,${search.value.query.trim()})` + } + return where + }) + const attachmentColumns = computed(() => (meta.value?.columns as ColumnType[])?.filter((c) => c.uidt === UITypes.Attachment).map((c) => c.title), ) @@ -141,7 +164,8 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState( } async function loadKanbanData() { - if ((!project?.value?.id || !meta.value?.id || !viewMeta?.value?.id) && !isPublic.value) return + if ((!project?.value?.id || !meta.value?.id || !viewMeta?.value?.id || !groupingFieldColumn?.value?.id) && !isPublic.value) + return // reset formattedData & countByStack to avoid storing previous data after changing grouping field formattedData.value = new Map() @@ -161,7 +185,7 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState( meta.value!.id!, viewMeta.value!.id!, groupingFieldColumn!.value!.id!, - {}, + { where: xWhere.value }, {}, ) } @@ -200,6 +224,7 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState( const response = !isPublic.value ? await api.dbViewRow.list('noco', project.value.id!, meta.value!.id!, viewMeta.value!.id!, { + ...{ where: xWhere.value }, ...params, ...(isUIAllowed('sortSync') ? {} : { sortArrJson: JSON.stringify(sorts.value) }), ...(isUIAllowed('filterSync') ? {} : { filterArrJson: JSON.stringify(nestedFilters.value) }), From e45c7d86f4fa8bbe43837dcb0e287cb410160206 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 28 Jan 2023 17:00:02 +0800 Subject: [PATCH 05/85] chore(workflows): disable close-issues action --- .github/workflows/release-nocodb.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release-nocodb.yml b/.github/workflows/release-nocodb.yml index 3a4322d9d6..dceb2732dd 100644 --- a/.github/workflows/release-nocodb.yml +++ b/.github/workflows/release-nocodb.yml @@ -103,12 +103,12 @@ jobs: NC_GITHUB_TOKEN: "${{ secrets.NC_GITHUB_TOKEN }}" # Close all issues with target tags 'Status: Ready for Next Release' - close-issues: - needs: [release-docker, process-input] - uses: ./.github/workflows/release-close-issue.yml - with: - issue_label: '🚀 Status: Ready for Next Release' - version: ${{ needs.process-input.outputs.target_tag }} + # close-issues: + # needs: [release-docker, process-input] + # uses: ./.github/workflows/release-close-issue.yml + # with: + # issue_label: '🚀 Status: Ready for Next Release' + # version: ${{ needs.process-input.outputs.target_tag }} # Publish Docs publish-docs: From 33bf9d5fed07331538c029ac03ab42154c28c66a Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 28 Jan 2023 19:27:02 +0800 Subject: [PATCH 06/85] fix(nc-gui): cater new attachments in gallery view --- packages/nc-gui/composables/useViewData.ts | 58 +++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/composables/useViewData.ts b/packages/nc-gui/composables/useViewData.ts index 591170bd3a..9dc5dc336f 100644 --- a/packages/nc-gui/composables/useViewData.ts +++ b/packages/nc-gui/composables/useViewData.ts @@ -1,5 +1,15 @@ import { UITypes, ViewTypes } from 'nocodb-sdk' -import type { Api, ColumnType, FormColumnType, FormType, GalleryType, PaginatedType, TableType, ViewType } from 'nocodb-sdk' +import type { + Api, + AttachmentType, + ColumnType, + FormColumnType, + FormType, + GalleryType, + PaginatedType, + TableType, + ViewType, +} from 'nocodb-sdk' import type { ComputedRef, Ref } from 'vue' import { IsPublicInj, @@ -81,6 +91,10 @@ export function useViewData( const { isUIAllowed } = useUIPermission() + const attachmentColumns = computed(() => + (meta.value?.columns as ColumnType[])?.filter((c) => c.uidt === UITypes.Attachment).map((c) => c.title), + ) + const routeQuery = $computed(() => route.query as Record) const paginationData = computed({ @@ -187,6 +201,28 @@ export function useViewData( } } + // TODO: refactor + async function getAttachmentUrl(item: AttachmentType) { + const path = item?.path + // if path doesn't exist, use `item.url` + if (path) { + // try ${appInfo.value.ncSiteUrl}/${item.path} first + const url = `${appInfo.ncSiteUrl}/${item.path}` + try { + const res = await fetch(url) + if (res.ok) { + // use `url` if it is accessible + return Promise.resolve(url) + } + } catch { + // for some cases, `url` is not accessible as expected + // do nothing here + } + } + // if it fails, use the original url + return Promise.resolve(item.url) + } + async function loadData(params: Parameters['dbViewRow']['list']>[4] = {}) { if ((!project?.value?.id || !meta.value?.id || !viewMeta.value?.id) && !isPublic.value) return const response = !isPublic.value @@ -198,7 +234,25 @@ export function useViewData( where: where?.value, }) : await fetchSharedViewData({ sortsArr: sorts.value, filtersArr: nestedFilters.value }) - formattedData.value = formatData(response.list) + // reconstruct the url + // See /packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts for the details + const records = [] + for (const record of response.list) { + for (const attachmentColumn of attachmentColumns.value) { + const oldAttachment = + typeof record[attachmentColumn!] === 'string' ? JSON.parse(record[attachmentColumn!]) : record[attachmentColumn!] + const newAttachment = [] + for (const attachmentObj of oldAttachment) { + newAttachment.push({ + ...attachmentObj, + url: await getAttachmentUrl(attachmentObj), + }) + } + record[attachmentColumn!] = newAttachment + } + records.push(record) + } + formattedData.value = formatData(records) paginationData.value = response.pageInfo // to cater the case like when querying with a non-zero offset From 7e50c72fbbf466d1b050d5f28a210758a167d2b9 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Sat, 28 Jan 2023 17:12:07 +0530 Subject: [PATCH 07/85] test: cell selection retry logic to avoid flakyness Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .../playwright/pages/Dashboard/Grid/index.ts | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/tests/playwright/pages/Dashboard/Grid/index.ts b/tests/playwright/pages/Dashboard/Grid/index.ts index 745d5ba1a9..9e3f3b507b 100644 --- a/tests/playwright/pages/Dashboard/Grid/index.ts +++ b/tests/playwright/pages/Dashboard/Grid/index.ts @@ -308,18 +308,41 @@ export class GridPage extends BasePage { } async copyWithKeyboard() { - await this.get().press((await this.isMacOs()) ? 'Meta+C' : 'Control+C'); - await this.verifyToast({ message: 'Copied to clipboard' }); - - return this.getClipboardText(); + // retry to avoid flakiness, until text is copied to clipboard + // + let text = ''; + let retryCount = 5; + while (text === '') { + await this.get().press((await this.isMacOs()) ? 'Meta+C' : 'Control+C'); + await this.verifyToast({ message: 'Copied to clipboard' }); + text = await this.getClipboardText(); + + // retry if text is empty till count is reached + retryCount--; + if (0 === retryCount) { + break; + } + } + return text; } async copyWithMouse({ index, columnHeader }: CellProps) { - await this.cell.get({ index, columnHeader }).click({ button: 'right' }); - await this.get().page().getByTestId('context-menu-item-copy').click(); - - await this.verifyToast({ message: 'Copied to clipboard' }); - - return this.getClipboardText(); + // retry to avoid flakiness, until text is copied to clipboard + // + let text = ''; + let retryCount = 5; + while (text === '') { + await this.cell.get({ index, columnHeader }).click({ button: 'right' }); + await this.get().page().getByTestId('context-menu-item-copy').click(); + await this.verifyToast({ message: 'Copied to clipboard' }); + text = await this.getClipboardText(); + + // retry if text is empty till count is reached + retryCount--; + if (0 === retryCount) { + break; + } + } + return text; } } From 9cb79117bc6b3c180a9f8ed85f1dfc2617c98d98 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Sat, 28 Jan 2023 19:30:10 +0530 Subject: [PATCH 08/85] fix: upgrader errors - skip missing column and tables - ignore errors thrown by deleted projects Signed-off-by: Pranav C --- .../version-upgrader/ncAttachmentUpgrader.ts | 170 +++++++++++------- 1 file changed, 104 insertions(+), 66 deletions(-) diff --git a/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts b/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts index be0b2d0799..84508def4e 100644 --- a/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts +++ b/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts @@ -1,3 +1,4 @@ +import { Knex } from 'knex'; import { NcUpgraderCtx } from './NcUpgrader'; import { MetaTable } from '../utils/globals'; import Base from '../models/Base'; @@ -29,7 +30,7 @@ function getTnPath(knex: XKnex, tb: Model) { const schema = (knex as any).searchPath?.(); const clientType = knex.clientType(); if (clientType === 'mssql' && schema) { - return knex.raw('??.??', [schema, tb.table_name]); + return knex.raw('??.??', [schema, tb.table_name]).toQuery(); } else if (clientType === 'snowflake') { return [ knex.client.config.connection.database, @@ -45,82 +46,119 @@ export default async function ({ ncMeta }: NcUpgraderCtx) { const bases: BaseType[] = await ncMeta.metaList2(null, null, MetaTable.BASES); for (const _base of bases) { const base = new Base(_base); - const knex: XKnex = base.is_meta + + const isProjectDeleted = (await base.getProject(ncMeta)).deleted; + + const knex: Knex = base.is_meta ? ncMeta.knexConnection : NcConnectionMgrv2.get(base); const models = await base.getModels(ncMeta); + for (const model of models) { - const updateRecords = []; - const columns = await ( - await Model.get(model.id, ncMeta) - ).getColumns(ncMeta); - const attachmentColumns = columns - .filter((c) => c.uidt === UITypes.Attachment) - .map((c) => c.column_name); - if (attachmentColumns.length === 0) { - continue; - } - const primaryKeys = columns.filter((c) => c.pk).map((c) => c.column_name); - const records = await knex(getTnPath(knex, model)).select([ - ...primaryKeys, - ...attachmentColumns, - ]); - for (const record of records) { - for (const attachmentColumn of attachmentColumns) { - let attachmentMeta: Array<{ - url: string; - }>; - - // if parsing failed ignore the cell - try { - attachmentMeta = - typeof record[attachmentColumn] === 'string' - ? JSON.parse(record[attachmentColumn]) - : record[attachmentColumn]; - } catch {} - - // if cell data is not an array, ignore it - if (!Array.isArray(attachmentMeta)) { - continue; - } + try { + // if the table is missing in database, skip + if (!(await knex.schema.hasTable(getTnPath(knex, model)))) { + continue; + } + + const updateRecords = []; + + // get all attachment & primary key columns + // and filter out the columns that are missing in database + const columns = await (await Model.get(model.id, ncMeta)) + .getColumns(ncMeta) + .then(async (columns) => { + const filteredColumns = []; + + for (const column of columns) { + if (column.uidt !== UITypes.Attachment && !column.pk) continue; + if ( + !(await knex.schema.hasColumn( + getTnPath(knex, model), + column.column_name + )) + ) + continue; + filteredColumns.push(column); + } + + return filteredColumns; + }); - if (attachmentMeta) { - const newAttachmentMeta = []; - for (const attachment of attachmentMeta) { - if ('url' in attachment && typeof attachment.url === 'string') { - const match = attachment.url.match(/^(.*)\/download\/(.*)$/); - if (match) { - // e.g. http://localhost:8080/download/noco/xcdb/Sheet-1/title5/ee2G8p_nute_gunray.png - // match[1] = http://localhost:8080 - // match[2] = download/noco/xcdb/Sheet-1/title5/ee2G8p_nute_gunray.png - const path = `download/${match[2]}`; - - newAttachmentMeta.push({ - ...attachment, - path, - }); - } else { - // keep it as it is - newAttachmentMeta.push(attachment); + const attachmentColumns = columns + .filter((c) => c.uidt === UITypes.Attachment) + .map((c) => c.column_name); + if (attachmentColumns.length === 0) { + continue; + } + const primaryKeys = columns + .filter((c) => c.pk) + .map((c) => c.column_name); + + const records = await knex(getTnPath(knex, model)).select(); + + for (const record of records) { + for (const attachmentColumn of attachmentColumns) { + let attachmentMeta: Array<{ + url: string; + }>; + + // if parsing failed ignore the cell + try { + attachmentMeta = + typeof record[attachmentColumn] === 'string' + ? JSON.parse(record[attachmentColumn]) + : record[attachmentColumn]; + } catch {} + + // if cell data is not an array, ignore it + if (!Array.isArray(attachmentMeta)) { + continue; + } + + if (attachmentMeta) { + const newAttachmentMeta = []; + for (const attachment of attachmentMeta) { + if ('url' in attachment && typeof attachment.url === 'string') { + const match = attachment.url.match(/^(.*)\/download\/(.*)$/); + if (match) { + // e.g. http://localhost:8080/download/noco/xcdb/Sheet-1/title5/ee2G8p_nute_gunray.png + // match[1] = http://localhost:8080 + // match[2] = download/noco/xcdb/Sheet-1/title5/ee2G8p_nute_gunray.png + const path = `download/${match[2]}`; + + newAttachmentMeta.push({ + ...attachment, + path, + }); + } else { + // keep it as it is + newAttachmentMeta.push(attachment); + } } } - } - const where = primaryKeys - .map((key) => { - return { [key]: record[key] }; - }) - .reduce((acc, val) => Object.assign(acc, val), {}); - updateRecords.push( - await knex(getTnPath(knex, model)) - .update({ - [attachmentColumn]: JSON.stringify(newAttachmentMeta), + const where = primaryKeys + .map((key) => { + return { [key]: record[key] }; }) - .where(where) - ); + .reduce((acc, val) => Object.assign(acc, val), {}); + updateRecords.push( + await knex(getTnPath(knex, model)) + .update({ + [attachmentColumn]: JSON.stringify(newAttachmentMeta), + }) + .where(where) + ); + } } } + await Promise.all(updateRecords); + } catch (e) { + // ignore the error related to deleted project + if (!isProjectDeleted) { + throw e; + } } - await Promise.all(updateRecords); } } } From 33304e63c3f7c702801231d742c414378484b17d Mon Sep 17 00:00:00 2001 From: navi Date: Sat, 28 Jan 2023 15:13:17 +0000 Subject: [PATCH 09/85] New translations en.json (Russian) --- packages/nc-gui/lang/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui/lang/ru.json b/packages/nc-gui/lang/ru.json index 45c44d0722..84202bac2c 100644 --- a/packages/nc-gui/lang/ru.json +++ b/packages/nc-gui/lang/ru.json @@ -206,7 +206,7 @@ "advancedSettings": "Расширенные настройки", "codeSnippet": "Сниппет кода", "keyboardShortcut": "Горячие клавиши", - "generateRandomName": "Generate Random Name" + "generateRandomName": "Сгенерировать случайное имя" }, "labels": { "createdBy": "Автор", From 9b8c11c66dc1c29c6b497e9d118c5240ff055c8a Mon Sep 17 00:00:00 2001 From: Pranav C Date: Sat, 28 Jan 2023 20:50:37 +0530 Subject: [PATCH 10/85] fix: get project using `ncMeta.metaGet2` method Signed-off-by: Pranav C --- .../nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts b/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts index 84508def4e..6e467ffda0 100644 --- a/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts +++ b/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts @@ -47,7 +47,11 @@ export default async function ({ ncMeta }: NcUpgraderCtx) { for (const _base of bases) { const base = new Base(_base); - const isProjectDeleted = (await base.getProject(ncMeta)).deleted; + const isProjectDeleted = ( + await ncMeta.metaGet2(null, null, MetaTable.PROJECT, { + id: base.project_id, + }) + ).deleted; const knex: Knex = base.is_meta ? ncMeta.knexConnection From c9c45f1cf5162045864317b7ff73d79223dae05e Mon Sep 17 00:00:00 2001 From: Pranav C Date: Sun, 29 Jan 2023 15:30:46 +0530 Subject: [PATCH 11/85] fix: handle null project id and missing project Signed-off-by: Pranav C --- .../version-upgrader/ncAttachmentUpgrader.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts b/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts index 6e467ffda0..7d68a7ddea 100644 --- a/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts +++ b/packages/nocodb/src/lib/version-upgrader/ncAttachmentUpgrader.ts @@ -47,11 +47,21 @@ export default async function ({ ncMeta }: NcUpgraderCtx) { for (const _base of bases) { const base = new Base(_base); - const isProjectDeleted = ( - await ncMeta.metaGet2(null, null, MetaTable.PROJECT, { - id: base.project_id, - }) - ).deleted; + // skip if the prodect_id is missing + if (!base.project_id) { + continue; + } + + const project = await ncMeta.metaGet2(null, null, MetaTable.PROJECT, { + id: base.project_id, + }); + + // skip if the project is missing + if (!project) { + continue; + } + + const isProjectDeleted = project.deleted; const knex: Knex = base.is_meta ? ncMeta.knexConnection From fbbe85c4558b6be4d9ef7ef3dcd7466b95559311 Mon Sep 17 00:00:00 2001 From: mertmit Date: Sun, 29 Jan 2023 17:12:11 +0300 Subject: [PATCH 12/85] fix: css for fixed row height Signed-off-by: mertmit --- .../nc-gui/components/smartsheet/Cell.vue | 24 +------------------ .../nc-gui/components/smartsheet/Grid.vue | 4 +++- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/Cell.vue b/packages/nc-gui/components/smartsheet/Cell.vue index b9ff55cfaa..9061933bb0 100644 --- a/packages/nc-gui/components/smartsheet/Cell.vue +++ b/packages/nc-gui/components/smartsheet/Cell.vue @@ -1,9 +1,8 @@ -