From 224a3bbdbf1cca656a9100a65b9f9e230a4ca7a5 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Tue, 11 Apr 2023 16:44:00 +0800 Subject: [PATCH 01/51] feat(nocodb): include vultr hostname --- packages/nocodb/src/lib/plugins/vultr/index.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/nocodb/src/lib/plugins/vultr/index.ts b/packages/nocodb/src/lib/plugins/vultr/index.ts index 659b0263e6..2bf072c226 100644 --- a/packages/nocodb/src/lib/plugins/vultr/index.ts +++ b/packages/nocodb/src/lib/plugins/vultr/index.ts @@ -5,7 +5,7 @@ import type { XcPluginConfig } from 'nc-plugin'; const config: XcPluginConfig = { builder: VultrPlugin, title: 'Vultr Object Storage', - version: '0.0.1', + version: '0.0.2', logo: 'plugins/vultr.png', description: 'Using Vultr Object Storage can give flexibility and cloud storage that allows applications greater flexibility and access worldwide.', @@ -20,13 +20,13 @@ const config: XcPluginConfig = { type: XcType.SingleLineText, required: true, }, - // { - // key: 'region', - // label: 'Region', - // placeholder: 'Region', - // type: XcType.SingleLineText, - // required: true - // }, + { + key: 'hostname', + label: 'Host Name', + placeholder: 'e.g.: ewr1.vultrobjects.com', + type: XcType.SingleLineText, + required: true + }, { key: 'access_key', label: 'Access Key', From 81eec8833b3f299f6fa3ead3e4d497f2570e53eb Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Tue, 11 Apr 2023 16:44:17 +0800 Subject: [PATCH 02/51] fix(nocodb): s3 endpoint for vultr --- packages/nocodb/src/lib/plugins/vultr/Vultr.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/nocodb/src/lib/plugins/vultr/Vultr.ts b/packages/nocodb/src/lib/plugins/vultr/Vultr.ts index 422512a32f..dcc166bf64 100644 --- a/packages/nocodb/src/lib/plugins/vultr/Vultr.ts +++ b/packages/nocodb/src/lib/plugins/vultr/Vultr.ts @@ -105,9 +105,7 @@ export default class Vultr implements IStorageAdapterV2 { s3Options.accessKeyId = this.input.access_key; s3Options.secretAccessKey = this.input.access_secret; - s3Options.endpoint = new AWS.Endpoint( - `s3.${this.input.region}.cloud.ovh.net` - ); + s3Options.endpoint = new AWS.Endpoint(this.input.hostname); this.s3Client = new AWS.S3(s3Options); } From c98e53152b63db6ea381fa5b690901262830349b Mon Sep 17 00:00:00 2001 From: navi Date: Tue, 11 Apr 2023 15:13:19 +0100 Subject: [PATCH 03/51] New translations en.json (Chinese Simplified) --- packages/nc-gui/lang/zh-Hans.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/nc-gui/lang/zh-Hans.json b/packages/nc-gui/lang/zh-Hans.json index c8aec7fc76..1339d9ead6 100644 --- a/packages/nc-gui/lang/zh-Hans.json +++ b/packages/nc-gui/lang/zh-Hans.json @@ -221,7 +221,7 @@ "viewName": "查看名称", "viewLink": "查看链接", "columnName": "列名", - "columnToScanFor": "Column to scan", + "columnToScanFor": "要扫描的列", "columnType": "列类型", "roleName": "权限组", "roleDescription": "权限描述", @@ -412,8 +412,8 @@ "changePwd": "更改密码", "createView": "创建视图", "shareView": "分享视图", - "findRowByCodeScan": "Find row by scan", - "fillByCodeScan": "Fill by scan", + "findRowByCodeScan": "通过扫描查找行", + "fillByCodeScan": "通过扫描填充", "listSharedView": "共享视图列表", "ListView": "视图列表", "copyView": "复制视图", @@ -430,7 +430,7 @@ "iFrame": "复制可嵌入的 HTML 代码", "addWebhook": "添加新的 Webhook", "enableWebhook": "启用 Webhook", - "testWebhook": "Test Webhook", + "testWebhook": "测试Webhook", "copyWebhook": "复制 Webhook", "deleteWebhook": "删除 Webhook", "newToken": "添加新 Token", @@ -542,9 +542,9 @@ "orgViewer": "游客不能创建新项目,仅允许访问受邀项目。" }, "codeScanner": { - "loadingScanner": "Loading the scanner...", + "loadingScanner": "正在加载扫描仪...", "selectColumn": "Select a column (QR code or Barcode) that you want to use for finding a row by scanning.", - "moreThanOneRowFoundForCode": "More than one row found for this code. Currently only unique codes are supported.", + "moreThanOneRowFoundForCode": "找到了多行此代码。目前只支持唯一的代码。", "noRowFoundForCode": "所选列没有找到此代码行" }, "map": { From 84fb1d5de2ec4293c98a43b34f9602f362ce5458 Mon Sep 17 00:00:00 2001 From: navi Date: Wed, 12 Apr 2023 03:39:51 +0100 Subject: [PATCH 04/51] New translations en.json (Chinese Simplified) --- packages/nc-gui/lang/zh-Hans.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/lang/zh-Hans.json b/packages/nc-gui/lang/zh-Hans.json index 1339d9ead6..03738dc710 100644 --- a/packages/nc-gui/lang/zh-Hans.json +++ b/packages/nc-gui/lang/zh-Hans.json @@ -470,7 +470,7 @@ "addOrEditStack": "添加/编辑分类标签" }, "map": { - "mappedBy": "Mapped By", + "mappedBy": "映射字段", "chooseMappingField": "选择映射字段", "openInGoogleMaps": "谷歌地图", "openInOpenStreetMap": "OSM" @@ -543,14 +543,14 @@ }, "codeScanner": { "loadingScanner": "正在加载扫描仪...", - "selectColumn": "Select a column (QR code or Barcode) that you want to use for finding a row by scanning.", + "selectColumn": "选择要用于扫描查找行的列(二维码或条形码)。", "moreThanOneRowFoundForCode": "找到了多行此代码。目前只支持唯一的代码。", "noRowFoundForCode": "所选列没有找到此代码行" }, "map": { "overLimit": "你已经超出了限制。", "closeLimit": "您已接近上限。", - "limitNumber": "The limit of markers shown in a Map View is 1000 records." + "limitNumber": "在地图视图中显示的标记的限制是1000条记录。" }, "footerInfo": "每页行驶", "upload": "选择文件以上传", From 630de0f3394efd1cdd3d5bbe9afbf1ba8148bee9 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 12 Apr 2023 13:23:48 +0800 Subject: [PATCH 05/51] fix(nc-gui): attachment input height --- packages/nc-gui/components/smartsheet/Cell.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui/components/smartsheet/Cell.vue b/packages/nc-gui/components/smartsheet/Cell.vue index 4a61552030..2023ec9604 100644 --- a/packages/nc-gui/components/smartsheet/Cell.vue +++ b/packages/nc-gui/components/smartsheet/Cell.vue @@ -193,7 +193,7 @@ onUnmounted(() => { `nc-cell-${(column?.uidt || 'default').toLowerCase()}`, { 'text-blue-600': isPrimary(column) && !props.virtual && !isForm }, { 'nc-grid-numeric-cell': isGrid && !isForm && isNumericField }, - { 'h-[40px]': !props.editEnabled && isForm && !isSurveyForm }, + { 'h-[40px]': !props.editEnabled && isForm && !isSurveyForm && !isAttachment(column) }, ]" @keydown.enter.exact="navigate(NavigateDir.NEXT, $event)" @keydown.shift.enter.exact="navigate(NavigateDir.PREV, $event)" From dc5ae370f4a957cd33bf439143b5a519e944970f Mon Sep 17 00:00:00 2001 From: Khisby Al Ghofari Date: Wed, 12 Apr 2023 13:10:42 +0700 Subject: [PATCH 06/51] feat: add check all on action column editor import modal --- packages/nc-gui/components/template/Editor.vue | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/nc-gui/components/template/Editor.vue b/packages/nc-gui/components/template/Editor.vue index 214ce1da20..4de89e1090 100644 --- a/packages/nc-gui/components/template/Editor.vue +++ b/packages/nc-gui/components/template/Editor.vue @@ -87,6 +87,8 @@ const isImporting = ref(false) const importingTips = ref>({}) +const checkAllRecord = ref(false) + const uiTypeOptions = ref( (Object.keys(UITypes) as (keyof typeof UITypes)[]) .filter( @@ -615,6 +617,13 @@ function handleEditableTnChange(idx: number) { function isSelectDisabled(uidt: string, disableSelect = false) { return (uidt === UITypes.SingleSelect || uidt === UITypes.MultiSelect) && disableSelect } + +function handleCheckAllRecord(event, table_name){ + const isChecked = event.target.checked; + for (const record of srcDestMapping.value[table_name]) { + record.enabled = isChecked; + } +} From 348e6a696436ebe14090473d53ce698d9dac345b Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 12 Apr 2023 18:34:57 +0800 Subject: [PATCH 09/51] fix(nocodb): add missing parsing logic --- .../db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts index 2890fd3508..453af0f141 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/BaseModelSqlv2.ts @@ -3242,17 +3242,24 @@ function extractCondition(nestedArrayConditions, aliasColObjMap) { // eslint-disable-next-line prefer-const let [logicOp, alias, op, value] = str.match(/(?:~(and|or|not))?\((.*?),(\w+),(.*)\)/)?.slice(1) || []; + + if (!alias && !op && !value) { + // try match with blank filter format + [logicOp, alias, op, value] = + str.match(/(?:~(and|or|not))?\((.*?),(\w+)\)/)?.slice(1) || []; + } let sub_op = null; if (aliasColObjMap[alias]) { if ( [UITypes.Date, UITypes.DateTime].includes(aliasColObjMap[alias].uidt) ) { - value = value.split(','); + value = value?.split(','); // the first element would be sub_op - sub_op = value[0]; + sub_op = value?.[0]; // remove the first element which is sub_op - value.shift(); + value?.shift(); + value = value?.[0]; } else if (op === 'in') { value = value.split(','); } From 1dc832b0bfaf3375660db1af652b8fc55d152362 Mon Sep 17 00:00:00 2001 From: Khisby Al Ghofari Date: Wed, 12 Apr 2023 17:53:01 +0700 Subject: [PATCH 10/51] feat(nc-gui): specific param type --- packages/nc-gui/components/template/Editor.vue | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/components/template/Editor.vue b/packages/nc-gui/components/template/Editor.vue index ca19059af6..6af851e630 100644 --- a/packages/nc-gui/components/template/Editor.vue +++ b/packages/nc-gui/components/template/Editor.vue @@ -32,6 +32,7 @@ import { useTabs, } from '#imports' import { TabType } from '~/lib' +import type { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface' const { quickImportType, projectTemplate, importData, importColumns, importDataOnly, maxRowsToParse, baseId } = defineProps() @@ -173,7 +174,7 @@ const prevEditableTn = ref([]) onMounted(() => { parseAndLoadTemplate() - + // used to record the previous EditableTn values // for checking the table duplication in current import // and updating the key in importData @@ -618,9 +619,9 @@ function isSelectDisabled(uidt: string, disableSelect = false) { return (uidt === UITypes.SingleSelect || uidt === UITypes.MultiSelect) && disableSelect } -function handleCheckAllRecord(event, table_name) { +function handleCheckAllRecord(event: CheckboxChangeEvent, tableName: string) { const isChecked = event.target.checked - for (const record of srcDestMapping.value[table_name]) { + for (const record of srcDestMapping.value[tableName]) { record.enabled = isChecked } } From 7fecf73556188394e001cb10f98582a90855700e Mon Sep 17 00:00:00 2001 From: Khisby Al Ghofari Date: Wed, 12 Apr 2023 17:54:23 +0700 Subject: [PATCH 11/51] feat(nc-gui): lint --- packages/nc-gui/components/template/Editor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui/components/template/Editor.vue b/packages/nc-gui/components/template/Editor.vue index 6af851e630..455611e3a7 100644 --- a/packages/nc-gui/components/template/Editor.vue +++ b/packages/nc-gui/components/template/Editor.vue @@ -3,6 +3,7 @@ import dayjs from 'dayjs' import utc from 'dayjs/plugin/utc' import type { ColumnType, TableType } from 'nocodb-sdk' import { UITypes, isSystemColumn, isVirtualCol } from 'nocodb-sdk' +import type { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface' import { srcDestMappingColumns, tableColumns } from './utils' import { Empty, @@ -32,7 +33,6 @@ import { useTabs, } from '#imports' import { TabType } from '~/lib' -import type { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface' const { quickImportType, projectTemplate, importData, importColumns, importDataOnly, maxRowsToParse, baseId } = defineProps() From 5036a5d27e752ac69f084e9f84fc2b3aca8ee771 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 12 Apr 2023 20:33:56 +0800 Subject: [PATCH 12/51] fix(nc-gui): remove non-existing sign out api --- packages/nc-gui/composables/useGlobal/actions.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/nc-gui/composables/useGlobal/actions.ts b/packages/nc-gui/composables/useGlobal/actions.ts index b08ec5989d..3190f7dbde 100644 --- a/packages/nc-gui/composables/useGlobal/actions.ts +++ b/packages/nc-gui/composables/useGlobal/actions.ts @@ -10,10 +10,6 @@ export function useGlobalActions(state: State): Actions { const signOut: Actions['signOut'] = async () => { state.token.value = null state.user.value = null - try { - const nuxtApp = useNuxtApp() - await nuxtApp.$api.auth.signout() - } catch {} } /** Sign in by setting the token in localStorage */ From 625cb7c6bbc69f65a21e2f8fb00fd205c436213a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 21:21:29 +0000 Subject: [PATCH 13/51] chore(deps): bump vm2 from 3.9.15 to 3.9.16 in /packages/nocodb Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.15 to 3.9.16. - [Release notes](https://github.com/patriksimek/vm2/releases) - [Changelog](https://github.com/patriksimek/vm2/blob/master/CHANGELOG.md) - [Commits](https://github.com/patriksimek/vm2/compare/3.9.15...3.9.16) --- updated-dependencies: - dependency-name: vm2 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- packages/nocodb/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/nocodb/package-lock.json b/packages/nocodb/package-lock.json index 03e968567c..a9243323a7 100644 --- a/packages/nocodb/package-lock.json +++ b/packages/nocodb/package-lock.json @@ -17364,9 +17364,9 @@ "dev": true }, "node_modules/vm2": { - "version": "3.9.15", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.15.tgz", - "integrity": "sha512-XqNqknHGw2avJo13gbIwLNZUumvrSHc9mLqoadFZTpo3KaNEJoe1I0lqTFhRXmXD7WkLyG01aaraXdXT0pa4ag==", + "version": "3.9.16", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.16.tgz", + "integrity": "sha512-3T9LscojNTxdOyG+e8gFeyBXkMlOBYDoF6dqZbj+MPVHi9x10UfiTAJIobuchRCp3QvC+inybTbMJIUrLsig0w==", "dependencies": { "acorn": "^8.7.0", "acorn-walk": "^8.2.0" @@ -32786,9 +32786,9 @@ "dev": true }, "vm2": { - "version": "3.9.15", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.15.tgz", - "integrity": "sha512-XqNqknHGw2avJo13gbIwLNZUumvrSHc9mLqoadFZTpo3KaNEJoe1I0lqTFhRXmXD7WkLyG01aaraXdXT0pa4ag==", + "version": "3.9.16", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.16.tgz", + "integrity": "sha512-3T9LscojNTxdOyG+e8gFeyBXkMlOBYDoF6dqZbj+MPVHi9x10UfiTAJIobuchRCp3QvC+inybTbMJIUrLsig0w==", "requires": { "acorn": "^8.7.0", "acorn-walk": "^8.2.0" From 000a39f19dfe12114e86210f418720c986b1b564 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 13:02:43 +0800 Subject: [PATCH 14/51] fix(nc-gui): add back signout api --- packages/nc-gui/composables/useGlobal/actions.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/nc-gui/composables/useGlobal/actions.ts b/packages/nc-gui/composables/useGlobal/actions.ts index 3190f7dbde..bfb6e3ad65 100644 --- a/packages/nc-gui/composables/useGlobal/actions.ts +++ b/packages/nc-gui/composables/useGlobal/actions.ts @@ -10,6 +10,10 @@ export function useGlobalActions(state: State): Actions { const signOut: Actions['signOut'] = async () => { state.token.value = null state.user.value = null + try { + const nuxtApp = useNuxtApp() + await nuxtApp.$api.auth.signout() + } catch {} } /** Sign in by setting the token in localStorage */ @@ -46,7 +50,7 @@ export function useGlobalActions(state: State): Actions { message.error(err.message || t('msg.error.youHaveBeenSignedOut')) await signOut() }) - .finally(() => resolve()) + .finally(() => resolve(true)) }) } From d60db3d7bbd3f8587aad8c56268256010c75ab07 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 13:03:11 +0800 Subject: [PATCH 15/51] fix(nocodb): add signout function to clear refresh token --- .../nocodb/src/lib/controllers/user/user.ctl.ts | 10 ++++++++++ packages/nocodb/src/lib/services/user/index.ts | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/packages/nocodb/src/lib/controllers/user/user.ctl.ts b/packages/nocodb/src/lib/controllers/user/user.ctl.ts index c68ada72f7..6b4fee6bc9 100644 --- a/packages/nocodb/src/lib/controllers/user/user.ctl.ts +++ b/packages/nocodb/src/lib/controllers/user/user.ctl.ts @@ -98,6 +98,15 @@ async function signin(req, res, next) { )(req, res, next); } +async function signout(req: Request, res): Promise { + res.json( + await userService.signout({ + req, + res, + }) + ); +} + async function googleSignin(req, res, next) { passport.authenticate( 'google', @@ -246,6 +255,7 @@ const mapRoutes = (router) => { // new API router.post('/api/v1/auth/user/signup', catchError(signup)); router.post('/api/v1/auth/user/signin', catchError(signin)); + router.post('/api/v1/auth/user/signout', catchError(signout)); router.get( '/api/v1/auth/user/me', extractProjectIdAndAuthenticate, diff --git a/packages/nocodb/src/lib/services/user/index.ts b/packages/nocodb/src/lib/services/user/index.ts index 1afa86648e..508b35a1cd 100644 --- a/packages/nocodb/src/lib/services/user/index.ts +++ b/packages/nocodb/src/lib/services/user/index.ts @@ -458,5 +458,20 @@ export async function signup(param: { } as any; } +export async function signout(param: { req: any; res: any }): Promise { + try { + param.res.clearCookie('refresh_token'); + const user = (param.req as any).user; + if (user) { + await User.update(user.id, { + refresh_token: null, + }); + } + return { msg: 'Signed out successfully' }; + } catch (e) { + NcError.badRequest(e.message); + } +} + export * from './helpers'; export { default as initAdminFromEnv } from './initAdminFromEnv'; From efb58e8d31f08cd0c7f7e2d2ed724fee51845c56 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 13:57:16 +0800 Subject: [PATCH 16/51] feat(nocodb): add convertDateFormat --- .../lib/sql/helpers/convertDateFormat.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts new file mode 100644 index 0000000000..c9e833e3b3 --- /dev/null +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts @@ -0,0 +1,23 @@ +export function convertDateFormat(date_format: string, type: string) { + if (date_format === 'YYYY-MM-DD') { + if (type === 'mysql2' || type === 'sqlite') return '%Y-%m-%d'; + } else if (date_format === 'YYYY/MM/DD') { + if (type === 'mysql2' || type === 'sqlite') return '%Y/%m/%d'; + } else if (date_format === 'DD-MM-YYYY') { + if (type === 'mysql2' || type === 'sqlite') return '%d/%m/%Y'; + } else if (date_format === 'MM-DD-YYYY') { + if (type === 'mysql2' || type === 'sqlite') return '%d-%m-%Y'; + } else if (date_format === 'DD/MM/YYYY') { + if (type === 'mysql2' || type === 'sqlite') return '%d/%m/%Y'; + } else if (date_format === 'MM/DD/YYYY') { + if (type === 'mysql2' || type === 'sqlite') return '%m-%d-%Y'; + } else if (date_format === 'DD MM YYYY') { + if (type === 'mysql2' || type === 'sqlite') return '%d %m %Y'; + } else if (date_format === 'MM DD YYYY') { + if (type === 'mysql2' || type === 'sqlite') return '%m %d %Y'; + } else if (date_format === 'YYYY MM DD') { + if (type === 'mysql2' || type === 'sqlite') return '%Y %m %d'; + } + // pg / mssql + return date_format; +} From 64e24b12159ed13128b9a057c92f40c612761b3b Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 13:57:48 +0800 Subject: [PATCH 17/51] fix(nocodb): convert date format based on meta in CONCAT --- .../sql/formulav2/formulaQueryBuilderv2.ts | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts index f6a93ea247..7a660bf2b0 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts @@ -6,8 +6,9 @@ import FormulaColumn from '../../../../../models/FormulaColumn'; import { validateDateWithUnknownFormat } from '../helpers/formulaFnHelper'; import { CacheGetType, CacheScope } from '../../../../../utils/globals'; import NocoCache from '../../../../../cache/NocoCache'; +import Column from '../../../../../models/Column'; +import { convertDateFormat } from '../helpers/convertDateFormat'; import type Model from '../../../../../models/Model'; -import type Column from '../../../../../models/Column'; import type RollupColumn from '../../../../../models/RollupColumn'; import type { XKnex } from '../../../index'; import type LinkToAnotherRecordColumn from '../../../../../models/LinkToAnotherRecordColumn'; @@ -633,8 +634,42 @@ async function _formulaQueryBuilder( `${pt.callee.name}(${( await Promise.all( pt.arguments.map(async (arg) => { - const query = (await fn(arg)).builder.toQuery(); + let query = (await fn(arg)).builder.toQuery(); if (pt.callee.name === 'CONCAT') { + if ( + arg.type === 'Identifier' && + arg.name in columnIdToUidt && + columnIdToUidt[arg.name] === UITypes.Date + ) { + const meta = ( + await Column.get({ + colId: arg.name, + }) + ).meta; + + if (knex.clientType() === 'mysql2') { + query = `DATE_FORMAT(${query}, '${convertDateFormat( + meta.date_format, + knex.clientType() + )}')`; + } else if (knex.clientType() === 'pg') { + query = `TO_CHAR(${query}, '${convertDateFormat( + meta.date_format, + knex.clientType() + )}')`; + } else if (knex.clientType() === 'sqlite') { + query = `strftime('${convertDateFormat( + meta.date_format, + knex.clientType() + )}', ${query})`; + } else if (knex.clientType() === 'mssql') { + query = `FORMAT(${query}, '${convertDateFormat( + meta.date_format, + knex.clientType() + )}')`; + } + } + if (knex.clientType() === 'mysql2') { // mysql2: CONCAT() returns NULL if any argument is NULL. // adding IFNULL to convert NULL values to empty strings From 02fd36589d1d446d9ca5c2ed5cb33802a1fa09ae Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 16:30:00 +0800 Subject: [PATCH 18/51] fix(nocodb): sqlite -> sqlite3 --- .../lib/sql/helpers/convertDateFormat.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts index c9e833e3b3..97057840f3 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/convertDateFormat.ts @@ -1,22 +1,22 @@ export function convertDateFormat(date_format: string, type: string) { if (date_format === 'YYYY-MM-DD') { - if (type === 'mysql2' || type === 'sqlite') return '%Y-%m-%d'; + if (type === 'mysql2' || type === 'sqlite3') return '%Y-%m-%d'; } else if (date_format === 'YYYY/MM/DD') { - if (type === 'mysql2' || type === 'sqlite') return '%Y/%m/%d'; + if (type === 'mysql2' || type === 'sqlite3') return '%Y/%m/%d'; } else if (date_format === 'DD-MM-YYYY') { - if (type === 'mysql2' || type === 'sqlite') return '%d/%m/%Y'; + if (type === 'mysql2' || type === 'sqlite3') return '%d/%m/%Y'; } else if (date_format === 'MM-DD-YYYY') { - if (type === 'mysql2' || type === 'sqlite') return '%d-%m-%Y'; + if (type === 'mysql2' || type === 'sqlite3') return '%d-%m-%Y'; } else if (date_format === 'DD/MM/YYYY') { - if (type === 'mysql2' || type === 'sqlite') return '%d/%m/%Y'; + if (type === 'mysql2' || type === 'sqlite3') return '%d/%m/%Y'; } else if (date_format === 'MM/DD/YYYY') { - if (type === 'mysql2' || type === 'sqlite') return '%m-%d-%Y'; + if (type === 'mysql2' || type === 'sqlite3') return '%m-%d-%Y'; } else if (date_format === 'DD MM YYYY') { - if (type === 'mysql2' || type === 'sqlite') return '%d %m %Y'; + if (type === 'mysql2' || type === 'sqlite3') return '%d %m %Y'; } else if (date_format === 'MM DD YYYY') { - if (type === 'mysql2' || type === 'sqlite') return '%m %d %Y'; + if (type === 'mysql2' || type === 'sqlite3') return '%m %d %Y'; } else if (date_format === 'YYYY MM DD') { - if (type === 'mysql2' || type === 'sqlite') return '%Y %m %d'; + if (type === 'mysql2' || type === 'sqlite3') return '%Y %m %d'; } // pg / mssql return date_format; From 841a57cfcf57e882dbdbf31204273895c56e4551 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 16:30:10 +0800 Subject: [PATCH 19/51] feat(nocodb): add convertDateFormatForConcat --- .../lib/sql/helpers/formulaFnHelper.ts | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/formulaFnHelper.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/formulaFnHelper.ts index e3268d7406..5a21ba3261 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/formulaFnHelper.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/helpers/formulaFnHelper.ts @@ -1,5 +1,8 @@ import dayjs, { extend } from 'dayjs'; import customParseFormat from 'dayjs/plugin/customParseFormat.js'; +import { UITypes } from 'nocodb-sdk'; +import Column from '../../../../../models/Column'; +import { convertDateFormat } from './convertDateFormat'; extend(customParseFormat); export function getWeekdayByText(v: string) { @@ -50,3 +53,45 @@ export function validateDateWithUnknownFormat(v: string) { } return false; } + +export async function convertDateFormatForConcat( + o, + columnIdToUidt, + query, + clientType +) { + if ( + o?.type === 'Identifier' && + o?.name in columnIdToUidt && + columnIdToUidt[o.name] === UITypes.Date + ) { + const meta = ( + await Column.get({ + colId: o.name, + }) + ).meta; + + if (clientType === 'mysql2') { + query = `DATE_FORMAT(${query}, '${convertDateFormat( + meta.date_format, + clientType + )}')`; + } else if (clientType === 'pg') { + query = `TO_CHAR(${query}, '${convertDateFormat( + meta.date_format, + clientType + )}')`; + } else if (clientType === 'sqlite3') { + query = `strftime('${convertDateFormat( + meta.date_format, + clientType + )}', ${query})`; + } else if (clientType === 'mssql') { + query = `FORMAT(${query}, '${convertDateFormat( + meta.date_format, + clientType + )}')`; + } + } + return query; +} From 133de6d7925752a6947e310433437410b0e0e824 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 16:30:29 +0800 Subject: [PATCH 20/51] refactor(nocodb): use convertDateFormatForConcat & fix sqlite case --- .../sql/formulav2/formulaQueryBuilderv2.ts | 69 +++++++++---------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts index 7a660bf2b0..1ee8c93268 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/formulav2/formulaQueryBuilderv2.ts @@ -3,11 +3,13 @@ import { jsepCurlyHook, UITypes } from 'nocodb-sdk'; import mapFunctionName from '../mapFunctionName'; import genRollupSelectv2 from '../genRollupSelectv2'; import FormulaColumn from '../../../../../models/FormulaColumn'; -import { validateDateWithUnknownFormat } from '../helpers/formulaFnHelper'; +import { + convertDateFormatForConcat, + validateDateWithUnknownFormat, +} from '../helpers/formulaFnHelper'; import { CacheGetType, CacheScope } from '../../../../../utils/globals'; import NocoCache from '../../../../../cache/NocoCache'; -import Column from '../../../../../models/Column'; -import { convertDateFormat } from '../helpers/convertDateFormat'; +import type Column from '../../../../../models/Column'; import type Model from '../../../../../models/Model'; import type RollupColumn from '../../../../../models/RollupColumn'; import type { XKnex } from '../../../index'; @@ -636,38 +638,15 @@ async function _formulaQueryBuilder( pt.arguments.map(async (arg) => { let query = (await fn(arg)).builder.toQuery(); if (pt.callee.name === 'CONCAT') { - if ( - arg.type === 'Identifier' && - arg.name in columnIdToUidt && - columnIdToUidt[arg.name] === UITypes.Date - ) { - const meta = ( - await Column.get({ - colId: arg.name, - }) - ).meta; - - if (knex.clientType() === 'mysql2') { - query = `DATE_FORMAT(${query}, '${convertDateFormat( - meta.date_format, - knex.clientType() - )}')`; - } else if (knex.clientType() === 'pg') { - query = `TO_CHAR(${query}, '${convertDateFormat( - meta.date_format, - knex.clientType() - )}')`; - } else if (knex.clientType() === 'sqlite') { - query = `strftime('${convertDateFormat( - meta.date_format, - knex.clientType() - )}', ${query})`; - } else if (knex.clientType() === 'mssql') { - query = `FORMAT(${query}, '${convertDateFormat( - meta.date_format, - knex.clientType() - )}')`; - } + if (knex.clientType() !== 'sqlite3') { + query = await convertDateFormatForConcat( + arg, + columnIdToUidt, + query, + knex.clientType() + ); + } else { + // sqlite3: special handling - See BinaryExpression } if (knex.clientType() === 'mysql2') { @@ -714,8 +693,8 @@ async function _formulaQueryBuilder( pt.left.fnName = pt.left.fnName || 'ARITH'; pt.right.fnName = pt.right.fnName || 'ARITH'; - const left = (await fn(pt.left, null, pt.operator)).builder.toQuery(); - const right = (await fn(pt.right, null, pt.operator)).builder.toQuery(); + let left = (await fn(pt.left, null, pt.operator)).builder.toQuery(); + let right = (await fn(pt.right, null, pt.operator)).builder.toQuery(); let sql = `${left} ${pt.operator} ${right}${colAlias}`; // comparing a date with empty string would throw @@ -759,8 +738,22 @@ async function _formulaQueryBuilder( } } - // handle NULL values when calling CONCAT for sqlite3 if (pt.left.fnName === 'CONCAT' && knex.clientType() === 'sqlite3') { + // handle date format + left = await convertDateFormatForConcat( + pt.left?.arguments?.[0], + columnIdToUidt, + left, + knex.clientType() + ); + right = await convertDateFormatForConcat( + pt.right?.arguments?.[0], + columnIdToUidt, + right, + knex.clientType() + ); + + // handle NULL values when calling CONCAT for sqlite3 sql = `COALESCE(${left}, '') ${pt.operator} COALESCE(${right},'')${colAlias}`; } From 5bc2c389a610ab31548bba0cd6d279ee94f3e772 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 17:22:10 +0800 Subject: [PATCH 21/51] fix(nc-gui): revise signout logic in refreshToken --- packages/nc-gui/composables/useGlobal/actions.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/composables/useGlobal/actions.ts b/packages/nc-gui/composables/useGlobal/actions.ts index bfb6e3ad65..8b62ac9ead 100644 --- a/packages/nc-gui/composables/useGlobal/actions.ts +++ b/packages/nc-gui/composables/useGlobal/actions.ts @@ -46,9 +46,11 @@ export function useGlobalActions(state: State): Actions { signIn(response.data.token) } }) - .catch(async (err) => { - message.error(err.message || t('msg.error.youHaveBeenSignedOut')) - await signOut() + .catch(async () => { + if (state.token.value && state.user.value) { + await signOut() + message.error(t('msg.error.youHaveBeenSignedOut')) + } }) .finally(() => resolve(true)) }) From f2002f2310bfeae3f289a42859a69cce6692115c Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 18:55:15 +0800 Subject: [PATCH 22/51] fix(nocodb): search formula in pg.ts --- .../lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts index 222b0751bc..50fd306e94 100644 --- a/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts +++ b/packages/nocodb/src/lib/db/sql-data-mapper/lib/sql/functionMappings/pg.ts @@ -17,9 +17,9 @@ const pg = { builder: args.knex.raw( `POSITION(${args.knex.raw( (await args.fn(args.pt.arguments[1])).builder.toQuery() - )} in ${args.knex - .raw((await args.fn(args.pt.arguments[0])).builder) - .toQuery()})${args.colAlias}` + )} in ${args.knex.raw( + (await args.fn(args.pt.arguments[0])).builder.toQuery() + )})${args.colAlias}` ), }; }, From 694b6126d8a73d1a41b0069fc47c3e2fa627dbf5 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 19:57:15 +0800 Subject: [PATCH 23/51] fix(nocodb): use multipart/form-data to make multer works --- packages/nocodb/src/schema/swagger.json | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json index 1fcfc3e4eb..b4e9f6c9c5 100644 --- a/packages/nocodb/src/schema/swagger.json +++ b/packages/nocodb/src/schema/swagger.json @@ -10886,20 +10886,7 @@ }, "requestBody": { "content": { - "application/json": { - "schema": { - "type": "object", - "description": "Data Object where the key is column and the value is the data value" - }, - "examples": { - "Example 1": { - "value": { - "col1": "foo", - "col2": "bar" - } - } - } - } + "multipart/form-data": {} }, "description": "" }, From 72de7be4a4a7b5eca2b95cd322916d0708b33039 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 19:57:32 +0800 Subject: [PATCH 24/51] chore(sdk): regenerate Api.ts --- packages/nocodb-sdk/src/lib/Api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index 2407419a29..cdcd4d5800 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -7905,7 +7905,7 @@ export class Api< */ dataCreate: ( sharedViewUuid: string, - data: object, + data: any, params: RequestParams = {} ) => this.request< @@ -7918,7 +7918,7 @@ export class Api< path: `/api/v1/db/public/shared-view/${sharedViewUuid}/rows`, method: 'POST', body: data, - type: ContentType.Json, + type: ContentType.FormData, format: 'json', ...params, }), From d171920cb790958404d0aebfe82508dc2d2f252c Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 13 Apr 2023 20:02:09 +0800 Subject: [PATCH 25/51] chore(nocodb): add comment --- .../src/lib/controllers/publicControllers/publicData.ctl.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nocodb/src/lib/controllers/publicControllers/publicData.ctl.ts b/packages/nocodb/src/lib/controllers/publicControllers/publicData.ctl.ts index 76d708e241..311e4ecb58 100644 --- a/packages/nocodb/src/lib/controllers/publicControllers/publicData.ctl.ts +++ b/packages/nocodb/src/lib/controllers/publicControllers/publicData.ctl.ts @@ -31,6 +31,7 @@ async function dataInsert(req: Request & { files: any[] }, res: Response) { password: req.headers?.['xc-password'] as string, body: req.body?.data, siteUrl: (req as any).ncSiteUrl, + // req.files is enriched by multer files: req.files, }); From 0059e8ef2186484b8722e06e89febbb64bad583a Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 14 Apr 2023 13:25:15 +0800 Subject: [PATCH 26/51] docs: adopt NuxtLink for internal routes --- .../noco-docs/content/en/developer-resources/rest-apis.md | 2 +- packages/noco-docs/content/en/developer-resources/sdk.md | 4 ++-- packages/noco-docs/content/en/getting-started/upgrading.md | 2 +- packages/noco-docs/content/en/index.md | 6 +++--- .../content/en/setup-and-usages/meta-management.md | 2 +- .../content/en/setup-and-usages/table-operations.md | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/noco-docs/content/en/developer-resources/rest-apis.md b/packages/noco-docs/content/en/developer-resources/rest-apis.md index 328932159d..b2e8aa693b 100644 --- a/packages/noco-docs/content/en/developer-resources/rest-apis.md +++ b/packages/noco-docs/content/en/developer-resources/rest-apis.md @@ -12,7 +12,7 @@ Once you've created the schemas, you can manipulate the data or invoke actions u Here's the overview of all APIs. For the details, please check out NocoDB API Documentation. -You may also interact with the API's resources via Swagger UI. +You may also interact with the API's resources via Swagger UI. Currently, the default value for {orgs} is noco. Users will be able to change it in the future release. diff --git a/packages/noco-docs/content/en/developer-resources/sdk.md b/packages/noco-docs/content/en/developer-resources/sdk.md index 53a5efee91..fa4a94ab22 100644 --- a/packages/noco-docs/content/en/developer-resources/sdk.md +++ b/packages/noco-docs/content/en/developer-resources/sdk.md @@ -9,7 +9,7 @@ menuTitle: 'NocoDB SDK' We provide SDK for users to integrate with their applications. Currently only SDK for Javascript is supported. -Note: The NocoDB SDK requires authorization token. If you haven't created one, please check out Accessing APIs for details. +Note: The NocoDB SDK requires authorization token. If you haven't created one, please check out Accessing APIs for details. ## SDK For Javascript @@ -57,7 +57,7 @@ const api = new Api({ Once you have configured `api`, you can call different types of APIs by `api..`. -For Tag and FunctionName, please check out the API table here. +For Tag and FunctionName, please check out the API table here. #### Example: Calling API - /api/v1/db/meta/projects/{projectId}/tables diff --git a/packages/noco-docs/content/en/getting-started/upgrading.md b/packages/noco-docs/content/en/getting-started/upgrading.md index 9ed66e642d..1eecf2bfd7 100644 --- a/packages/noco-docs/content/en/getting-started/upgrading.md +++ b/packages/noco-docs/content/en/getting-started/upgrading.md @@ -8,7 +8,7 @@ link: https://codesandbox.io/embed/vigorous-firefly-80kq5?hidenavigation=1&theme --- By default, if `NC_DB` is not specified upon -installation, then SQLite will be used to store metadata. We suggest users to separate the metadata and user data in different databases as pictured in our architecture. +installation, then SQLite will be used to store metadata. We suggest users to separate the metadata and user data in different databases as pictured in our architecture. ## Docker diff --git a/packages/noco-docs/content/en/index.md b/packages/noco-docs/content/en/index.md index d79a6c3020..4e1b575901 100644 --- a/packages/noco-docs/content/en/index.md +++ b/packages/noco-docs/content/en/index.md @@ -31,7 +31,7 @@ Also NocoDB's app store allows you to build business workflows on views with com ### App Store for Workflow Automations -We provide different integrations in three main categories. See App Store for details. +We provide different integrations in three main categories. See App Store for details. - ⚡  Chat : Slack, Discord, Mattermost, and etc - ⚡  Email : AWS SES, SMTP, MailerSend, and etc @@ -46,11 +46,11 @@ We provide the following ways to let users to invoke actions in a programmatic w ### Sync Schema -We allow you to sync schema changes if you have made changes outside NocoDB GUI. However, it has to be noted then you will have to bring your own schema migrations for moving from environment to others. See Sync Schema for details. +We allow you to sync schema changes if you have made changes outside NocoDB GUI. However, it has to be noted then you will have to bring your own schema migrations for moving from environment to others. See Sync Schema for details. ### Audit -We are keeping all the user operation logs under one place. See Audit for details. +We are keeping all the user operation logs under one place. See Audit for details. ## Why are we building this? Most internet businesses equip themselves with either spreadsheet or a database to solve their business needs. Spreadsheets are used by a Billion+ humans collaboratively every single day. However, we are way off working at similar speeds on databases which are way more powerful tools when it comes to computing. Attempts to solve this with SaaS offerings has meant horrible access controls, vendor lockin, data lockin, abrupt price changes & most importantly a glass ceiling on what's possible in future. diff --git a/packages/noco-docs/content/en/setup-and-usages/meta-management.md b/packages/noco-docs/content/en/setup-and-usages/meta-management.md index 3c6825bf80..266e1155e6 100644 --- a/packages/noco-docs/content/en/setup-and-usages/meta-management.md +++ b/packages/noco-docs/content/en/setup-and-usages/meta-management.md @@ -28,7 +28,7 @@ To access it, click the down arrow button next to Project Name on the top left s ## Sync Metadata -Go to `Data Sources`, click ``Sync Metadata``, you can see your metadata sync status. If it is out of sync, you can sync the schema. See Sync Schema for more.0 +Go to `Data Sources`, click ``Sync Metadata``, you can see your metadata sync status. If it is out of sync, you can sync the schema. See Sync Schema for more. ![image](https://user-images.githubusercontent.com/35857179/219833485-3bcaa6ec-88bc-47cc-b938-5abb4835dc31.png) diff --git a/packages/noco-docs/content/en/setup-and-usages/table-operations.md b/packages/noco-docs/content/en/setup-and-usages/table-operations.md index e6245bdea3..a41449729b 100644 --- a/packages/noco-docs/content/en/setup-and-usages/table-operations.md +++ b/packages/noco-docs/content/en/setup-and-usages/table-operations.md @@ -155,7 +155,7 @@ You can use Quick Import when you have data from external sources such as Airtab ### Import Airtable into an Existing Project -- See here +- See here ### Import CSV data into an Existing Project @@ -165,7 +165,7 @@ You can use Quick Import when you have data from external sources such as Airtab - **Use First Row as Headers**: If it is checked, the first row will be treated as header row. - **Import Data**: If it is checked, all data will be imported. Otherwise, only table will be created. ![image](https://user-images.githubusercontent.com/35857179/197454479-1ed18dce-1d0b-4ee3-88b3-9b6a132dea2a.png) -- You can revise the table name by double clicking it, column name and column type. By default, the first column will be chosen as Display Value and cannot be deleted. +- You can revise the table name by double clicking it, column name and column type. By default, the first column will be chosen as Display Value and cannot be deleted. ![image](https://user-images.githubusercontent.com/35857179/197454633-5b30323e-2b13-4c55-843a-948c093d373e.png) - Click `Import` to start importing process. The table will be created and the data will be imported. ![image](https://user-images.githubusercontent.com/35857179/197455547-2d93df5e-a7f0-4c88-af53-990067625967.png) @@ -178,7 +178,7 @@ You can use Quick Import when you have data from external sources such as Airtab - **Use First Row as Headers**: If it is checked, the first row will be treated as header row. - **Import Data**: If it is checked, all data will be imported. Otherwise, only table will be created. ![image](https://user-images.githubusercontent.com/35857179/197455788-8dd8a7d1-38f3-48c3-a05e-6ab0cf25045c.png) -- You can revise the table name, column name and column type. By default, the first column will be chosen as Display Value and cannot be deleted. +- You can revise the table name, column name and column type. By default, the first column will be chosen as Display Value and cannot be deleted. Note: If your Excel file contains multiple sheets, each sheet will be stored in a separate table. From e86aef08cb1add36c84d25bcccf48d20bd7a08f5 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 14 Apr 2023 14:05:44 +0800 Subject: [PATCH 27/51] chore(nc-gui): import iconMap --- packages/nc-gui/components/cell/attachment/Image.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/nc-gui/components/cell/attachment/Image.vue b/packages/nc-gui/components/cell/attachment/Image.vue index 8c3669be0f..625096b106 100644 --- a/packages/nc-gui/components/cell/attachment/Image.vue +++ b/packages/nc-gui/components/cell/attachment/Image.vue @@ -1,4 +1,6 @@ + + From bc9b8af46b34e30a29b8a9212586ddc8e49aa84d Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Mon, 17 Apr 2023 15:46:06 +0800 Subject: [PATCH 46/51] fix(nc-gui): apply LazySmartsheetDivDataCell --- .../nc-gui/components/smartsheet/Form.vue | 26 ++++++++++--------- .../smartsheet/expanded-form/index.vue | 4 +-- .../form/[viewId]/index/index.vue | 4 +-- .../form/[viewId]/index/survey.vue | 4 +-- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/Form.vue b/packages/nc-gui/components/smartsheet/Form.vue index 6adeda9da5..05a26b2304 100644 --- a/packages/nc-gui/components/smartsheet/Form.vue +++ b/packages/nc-gui/components/smartsheet/Form.vue @@ -727,18 +727,20 @@ watch(view, (nextView) => { }, ]" > - + + +
{{ element.description }}
diff --git a/packages/nc-gui/components/smartsheet/expanded-form/index.vue b/packages/nc-gui/components/smartsheet/expanded-form/index.vue index 0c1e5285c7..d1dc2d97f8 100644 --- a/packages/nc-gui/components/smartsheet/expanded-form/index.vue +++ b/packages/nc-gui/components/smartsheet/expanded-form/index.vue @@ -329,7 +329,7 @@ export default { -
@@ -343,7 +343,7 @@ export default { :active="true" @update:model-value="changedColumns.add(col.title)" /> -
+ diff --git a/packages/nc-gui/pages/[projectType]/form/[viewId]/index/index.vue b/packages/nc-gui/pages/[projectType]/form/[viewId]/index/index.vue index b0b09b4a51..e67aeffe4a 100644 --- a/packages/nc-gui/pages/[projectType]/form/[viewId]/index/index.vue +++ b/packages/nc-gui/pages/[projectType]/form/[viewId]/index/index.vue @@ -146,7 +146,7 @@ const onDecode = async (scannedCodeValue: string) => {
-
+ {
-
+
diff --git a/packages/nc-gui/pages/[projectType]/form/[viewId]/index/survey.vue b/packages/nc-gui/pages/[projectType]/form/[viewId]/index/survey.vue index 90d850f719..1a696db7a9 100644 --- a/packages/nc-gui/pages/[projectType]/form/[viewId]/index/survey.vue +++ b/packages/nc-gui/pages/[projectType]/form/[viewId]/index/survey.vue @@ -283,7 +283,7 @@ onMounted(() => { />
-
+ { to make a line break
- +
From 868590a515c95c8ca90802004b876575fed2b556 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Mon, 17 Apr 2023 16:02:50 +0800 Subject: [PATCH 47/51] fix(nocodb): incorrect router parameters for publicMmList & publicHmList --- .../src/lib/controllers/publicControllers/publicData.ctl.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nocodb/src/lib/controllers/publicControllers/publicData.ctl.ts b/packages/nocodb/src/lib/controllers/publicControllers/publicData.ctl.ts index 311e4ecb58..d68089001d 100644 --- a/packages/nocodb/src/lib/controllers/publicControllers/publicData.ctl.ts +++ b/packages/nocodb/src/lib/controllers/publicControllers/publicData.ctl.ts @@ -96,11 +96,11 @@ router.post( ); router.get( - '/api/v1/db/public/shared-view/:sharedViewUuid/rows/:rowId/mm/:colId', + '/api/v1/db/public/shared-view/:sharedViewUuid/rows/:rowId/mm/:columnId', catchError(publicMmList) ); router.get( - '/api/v1/db/public/shared-view/:sharedViewUuid/rows/:rowId/hm/:colId', + '/api/v1/db/public/shared-view/:sharedViewUuid/rows/:rowId/hm/:columnId', catchError(publicHmList) ); From 86c8c35ab31162062c3dda425640d8977c9ced68 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Mon, 17 Apr 2023 15:28:34 +0530 Subject: [PATCH 48/51] test: child list verification corrections Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .../pages/Dashboard/common/Cell/index.ts | 30 +++++++++++-------- tests/playwright/tests/viewGridShare.spec.ts | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/playwright/pages/Dashboard/common/Cell/index.ts b/tests/playwright/pages/Dashboard/common/Cell/index.ts index 2b30b5eb9b..acbd48c2f4 100644 --- a/tests/playwright/pages/Dashboard/common/Cell/index.ts +++ b/tests/playwright/pages/Dashboard/common/Cell/index.ts @@ -264,9 +264,11 @@ export class CellPageObject extends BasePage { columnHeader, count, value, + verifyChildList = false, }: CellProps & { count?: number; value: string[]; + verifyChildList?: boolean; }) { // const count = value.length; const cell = await this.get({ index, columnHeader }); @@ -282,23 +284,25 @@ export class CellPageObject extends BasePage { await expect(await chips.nth(i).locator('.name')).toHaveText(value[i]); } - // open child list - await this.get({ index, columnHeader }).hover(); - const arrow_expand = await this.get({ index, columnHeader }).locator('.nc-arrow-expand'); + if (verifyChildList) { + // open child list + await this.get({ index, columnHeader }).hover(); + const arrow_expand = await this.get({ index, columnHeader }).locator('.nc-arrow-expand'); - // arrow expand doesn't exist for bt columns - if (await arrow_expand.count()) { - await arrow_expand.click(); + // arrow expand doesn't exist for bt columns + if (await arrow_expand.count()) { + await arrow_expand.click(); - // wait for child list to open - await this.rootPage.waitForSelector('.nc-modal-child-list:visible'); + // wait for child list to open + await this.rootPage.waitForSelector('.nc-modal-child-list:visible'); - // verify child list count & contents - const childList = await this.rootPage.locator('.ant-card'); - expect(await childList.count()).toBe(count); + // verify child list count & contents + const childList = await this.rootPage.locator('.ant-card'); + expect(await childList.count()).toBe(count); - // close child list - await this.rootPage.locator('.nc-modal-child-list').locator('button.ant-modal-close:visible').click(); + // close child list + await this.rootPage.locator('.nc-modal-child-list').locator('button.ant-modal-close:visible').click(); + } } } diff --git a/tests/playwright/tests/viewGridShare.spec.ts b/tests/playwright/tests/viewGridShare.spec.ts index b83bdde221..ec932816e1 100644 --- a/tests/playwright/tests/viewGridShare.spec.ts +++ b/tests/playwright/tests/viewGridShare.spec.ts @@ -90,7 +90,7 @@ test.describe('Shared view', () => { // verify virtual records for (const record of expectedVirtualRecordsByDb) { - await sharedPage.grid.cell.verifyVirtualCell(record); + await sharedPage.grid.cell.verifyVirtualCell({ ...record, verifyChildList: true }); } /** From 7b4a01f7be107fb3c68db89ad4cce53e1cf26447 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Mon, 17 Apr 2023 15:54:32 +0530 Subject: [PATCH 49/51] test: child list card visibility Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- tests/playwright/pages/Dashboard/common/Cell/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/playwright/pages/Dashboard/common/Cell/index.ts b/tests/playwright/pages/Dashboard/common/Cell/index.ts index acbd48c2f4..1b287cb595 100644 --- a/tests/playwright/pages/Dashboard/common/Cell/index.ts +++ b/tests/playwright/pages/Dashboard/common/Cell/index.ts @@ -297,7 +297,7 @@ export class CellPageObject extends BasePage { await this.rootPage.waitForSelector('.nc-modal-child-list:visible'); // verify child list count & contents - const childList = await this.rootPage.locator('.ant-card'); + const childList = await this.rootPage.locator('.ant-card:visible'); expect(await childList.count()).toBe(count); // close child list From a6b05fc0e5658575ba779be3dae6d7e85b8227e3 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Mon, 17 Apr 2023 19:50:44 +0800 Subject: [PATCH 50/51] fix(nc-gui): add select-none to data cell --- packages/nc-gui/components/smartsheet/DivDataCell.vue | 2 +- packages/nc-gui/components/smartsheet/TableDataCell.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/DivDataCell.vue b/packages/nc-gui/components/smartsheet/DivDataCell.vue index 652189906e..cc6fd2774c 100644 --- a/packages/nc-gui/components/smartsheet/DivDataCell.vue +++ b/packages/nc-gui/components/smartsheet/DivDataCell.vue @@ -11,7 +11,7 @@ provide(CurrentCellInj, el) diff --git a/packages/nc-gui/components/smartsheet/TableDataCell.vue b/packages/nc-gui/components/smartsheet/TableDataCell.vue index b40604fd6b..a78d4751ff 100644 --- a/packages/nc-gui/components/smartsheet/TableDataCell.vue +++ b/packages/nc-gui/components/smartsheet/TableDataCell.vue @@ -11,7 +11,7 @@ provide(CurrentCellInj, el) From 422940e3d7ef6850acda0be349865d737476dd10 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Mon, 17 Apr 2023 21:20:37 +0530 Subject: [PATCH 51/51] test: revert version change for quick tests Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- tests/playwright/scripts/docker-compose-pg-pw-quick.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/playwright/scripts/docker-compose-pg-pw-quick.yml b/tests/playwright/scripts/docker-compose-pg-pw-quick.yml index 97d346b716..19dfab2887 100644 --- a/tests/playwright/scripts/docker-compose-pg-pw-quick.yml +++ b/tests/playwright/scripts/docker-compose-pg-pw-quick.yml @@ -1,8 +1,8 @@ -version: "2.2" +version: "2.1" services: - pg147: - image: postgres:14.7 + pg96: + image: postgres:9.6 restart: always environment: POSTGRES_PASSWORD: password