From 6be9663a6ca6861421971cb78dfc5cae65ee8b6e Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 28 Apr 2022 19:35:49 +0800 Subject: [PATCH 01/48] fix: key naming for column name --- .../components/import/templateParsers/ExcelTemplateAdapter.js | 4 ++-- .../components/templates/createProjectFromTemplateBtn.vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js b/packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js index 37dfd37bae..469bca5ca9 100644 --- a/packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js +++ b/packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js @@ -79,8 +79,8 @@ export default class ExcelTemplateAdapter extends TemplateGenerator { columnNamePrefixRef[cn] = 0 const column = { - cn, - refCn: cn + column_name: cn, + ref_column_name: cn } table.columns.push(column) diff --git a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue index 9d3c0542c0..709c844936 100644 --- a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue +++ b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue @@ -198,7 +198,7 @@ export default { remapColNames(batchData, columns) { return batchData.map(data => (columns || []).reduce((aggObj, col) => ({ ...aggObj, - [col.column_name]: data[col.refCn] + [col.column_name]: data[col.ref_column_name] }), {}) ) } From f91f46b0c99dc3832af655e2c75b792de90bc03f Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 28 Apr 2022 19:36:03 +0800 Subject: [PATCH 02/48] chore: enable back excel import option --- packages/nc-gui/pages/projects/index.vue | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/nc-gui/pages/projects/index.vue b/packages/nc-gui/pages/projects/index.vue index 86e52191e6..9a6553a5ca 100644 --- a/packages/nc-gui/pages/projects/index.vue +++ b/packages/nc-gui/pages/projects/index.vue @@ -135,6 +135,26 @@ {{ $t("tooltip.extDB") }} + + + + + mdi-file-excel-outline + + + + + + From 6873bcb0e6b2dce65a2e62a2e0b0e5c6976da402 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Thu, 28 Apr 2022 20:03:31 +0800 Subject: [PATCH 03/48] fix: key naming for table name --- .../components/import/templateParsers/ExcelTemplateAdapter.js | 2 +- .../components/templates/createProjectFromTemplateBtn.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js b/packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js index 469bca5ca9..b1964ae5a6 100644 --- a/packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js +++ b/packages/nc-gui/components/import/templateParsers/ExcelTemplateAdapter.js @@ -42,7 +42,7 @@ export default class ExcelTemplateAdapter extends TemplateGenerator { } tableNamePrefixRef[tn] = 0 - const table = { tn, refTn: tn, columns: [] } + const table = { table_name: tn, ref_table_name: tn, columns: [] } this.data[tn] = [] const ws = this.wb.Sheets[sheet] const range = XLSX.utils.decode_range(ws['!ref']) diff --git a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue index 709c844936..0b53645aa4 100644 --- a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue +++ b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue @@ -173,7 +173,7 @@ export default { await Promise.all(this.templateData.tables.map(v => (async(tableMeta) => { const table = tableMeta.table_name - const data = this.importData[tableMeta.refTn] + const data = this.importData[tableMeta.ref_table_name] await this.$store.dispatch('meta/ActLoadMeta', { tn: `${prefix}${table}`, project_id: projectId From 21cd83be9628b62d63a9c728aa6ae6b6d3a09dbc Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 29 Apr 2022 12:45:26 +0800 Subject: [PATCH 04/48] chore: point to file:../nocodb-sdk --- packages/nc-gui/package.json | 2 +- packages/nocodb/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/package.json b/packages/nc-gui/package.json index ab53a44056..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.90.8", + "nocodb-sdk": "file:../nocodb-sdk", "nuxt": "^2.14.0", "odometer": "^0.4.8", "papaparse": "^5.3.1", diff --git a/packages/nocodb/package.json b/packages/nocodb/package.json index faee031447..bdd0f5efd4 100644 --- a/packages/nocodb/package.json +++ b/packages/nocodb/package.json @@ -154,7 +154,7 @@ "nc-lib-gui": "0.90.8", "nc-plugin": "^0.1.1", "ncp": "^2.0.0", - "nocodb-sdk": "0.90.8", + "nocodb-sdk": "file:../nocodb-sdk", "nodemailer": "^6.4.10", "ora": "^4.0.4", "os-locale": "^5.0.0", From 183a4fb659b35f96a249ef954913fea8ea7ff026 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 29 Apr 2022 12:59:12 +0800 Subject: [PATCH 05/48] feat: add createByExcel API --- packages/nocodb-sdk/src/lib/Api.ts | 33 +++++++++++++++ scripts/sdk/swagger.json | 68 ++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index ee6bb65487..3ca7adba17 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -1204,6 +1204,39 @@ export class Api< ...params, }), + /** + * @description Create Project by Importing Excel File + * + * @tags Project + * @name CreateByExcel + * @summary Project create + * @request POST:/api/v1/db/meta/projects/import/excel + * @response `200` `ProjectType` OK + */ + createByExcel: ( + data: { + title?: string; + projectType?: string; + template?: { + title?: string; + tables?: { + table_name?: string; + ref_table_name?: string; + columns?: object[]; + }[]; + }; + }, + params: RequestParams = {} + ) => + this.request({ + path: `/api/v1/db/meta/projects/import/excel`, + method: 'POST', + body: data, + type: ContentType.Json, + format: 'json', + ...params, + }), + /** * @description Read project details * diff --git a/scripts/sdk/swagger.json b/scripts/sdk/swagger.json index 091505e9a9..8ce379b025 100644 --- a/scripts/sdk/swagger.json +++ b/scripts/sdk/swagger.json @@ -801,6 +801,74 @@ ] } }, + "/api/v1/db/meta/projects/import/excel": { + "parameters": [], + "post": { + "summary": "Project create", + "operationId": "project-create-by-excel", + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Project" + } + } + } + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "projectType": { + "type": "string" + }, + "template": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "tables": { + "type": "array", + "items": { + "type": "object", + "properties": { + "table_name": { + "type": "string" + }, + "ref_table_name": { + "type": "string" + }, + "columns": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + } + } + } + } + } + }, + "tags": [ + "Project" + ], + "description": "Create Project by Importing Excel File" + } + }, "/api/v1/db/meta/projects/{projectId}": { "parameters": [ { From 53c6aade153934daba4137aed557f4cffd21f542 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 29 Apr 2022 19:53:32 +0800 Subject: [PATCH 06/48] chore: mark it optional --- packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts index 5ec1d5afa8..1b5b04dff0 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/BaseModelSqlv2.ts @@ -1476,7 +1476,7 @@ class BaseModelSqlv2 { const response = await this.dbDriver .batchInsert(this.model.table_name, insertDatas, 50) - .returning(this.model.primaryKey.column_name); + .returning(this.model.primaryKey?.column_name); // await this.afterInsertb(insertDatas, null); From f34c7aae161e03e509f7dfefe35b2eccd07669c0 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 29 Apr 2022 19:54:20 +0800 Subject: [PATCH 07/48] fix: integrate export import with new api design --- .../createProjectFromTemplateBtn.vue | 110 +++++++++--------- 1 file changed, 52 insertions(+), 58 deletions(-) diff --git a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue index 0b53645aa4..23aa25515b 100644 --- a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue +++ b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue @@ -107,33 +107,57 @@ export default { projectId = this.$route.params.project_id prefix = this.$store.getters['project/GtrProjectPrefix'] } else { - const result = await this.$store.dispatch('sqlMgr/ActSqlOp', [null, 'projectCreateByWebWithXCDB', { - title: this.templateData.title, - projectType, - template: this.templateData, - excelImport: this.excelImport - }]) - projectId = result.id - prefix = result.prefix - await this.$store.dispatch('project/ActLoadProjectInfo') + try { + // Create an empty project + const result = await this.$api.project.create({ + title: this.templateData.title, + external: false + }) + + prefix = result.prefix + + clearInterval(interv) + + await this.$store.dispatch('project/ActLoadProjectInfo') + + this.projectReloading = false + + if (!this.edit && !this.allSchemas) { + this.$router.push({ + path: `/nc/${result.id}`, + query: { + new: 1 + } + }) + } + + this.projectCreated = true + + // Create tables + for (var t of this.templateData.tables) { + const table = await this.$api.dbTable.create(result.id, { + table_name: t.ref_table_name, + title: '', + columns: t.columns, + }); + console.log(table) + t.table_title = table.title + } + } catch (e) { + this.$toast + .error(await this._extractSdkResponseErrorMsg(e)) + .goAway(3000) + } } clearInterval(interv) + + // Bulk import data if (this.importData) { this.$store.commit('loader/MutMessage', 'Importing excel data to project') - await this.importDataToProject({ projectId, projectType, prefix }) + await this.importDataToProject(this.templateData.title, prefix) } this.$store.commit('loader/MutMessage', null) - this.projectReloading = false - if (!this.importToProject) { - await this.$router.push({ - path: `/nc/${projectId}`, - query: { - new: 1 - } - }) - } - this.$emit('success') } catch (e) { console.log(e) @@ -143,53 +167,23 @@ export default { } this.projectCreation = false }, - async importDataToProject({ projectId, projectType, prefix = '' }) { - // this.$store.commit('project/MutProjectId', projectId) - this.$ncApis.setProjectId(projectId) - + async importDataToProject(projectName, prefix) { let total = 0 let progress = 0 - - /* await Promise.all(Object.entries(this.importData).map(v => (async([table, data]) => { - await this.$store.dispatch('meta/ActLoadMeta', { - tn: `${prefix}${table}`, project_id: projectId - }) - - // todo: get table name properly - const api = this.$ncApis.get({ - table: `${prefix}${table}`, - type: projectType - }) - total += data.length - for (let i = 0; i < data.length; i += 500) { - this.$store.commit('loader/MutMessage', `Importing data : ${progress}/${total}`) - this.$store.commit('loader/MutProgress', Math.round(progress && 100 * progress / total)) - const batchData = data.slice(i, i + 500) - await api.insertBulk(batchData) - progress += batchData.length - } - this.$store.commit('loader/MutClear') - })(v))) */ - await Promise.all(this.templateData.tables.map(v => (async(tableMeta) => { - const table = tableMeta.table_name + const table = tableMeta.table_title const data = this.importData[tableMeta.ref_table_name] - - await this.$store.dispatch('meta/ActLoadMeta', { - tn: `${prefix}${table}`, project_id: projectId - }) - - // todo: get table name properly - const api = this.$ncApis.get({ - table: `${prefix}${table}`, - type: projectType - }) total += data.length for (let i = 0; i < data.length; i += 500) { this.$store.commit('loader/MutMessage', `Importing data : ${progress}/${total}`) this.$store.commit('loader/MutProgress', Math.round(progress && 100 * progress / total)) const batchData = this.remapColNames(data.slice(i, i + 500), tableMeta.columns) - await api.insertBulk(batchData) + await this.$api.dbTableRow.bulkCreate( + 'noco', + projectName, + table, + batchData + ) progress += batchData.length } this.$store.commit('loader/MutClear') From 253a3b1fecab3108d4b8c8cc3c3b571b93b48c9b Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Fri, 29 Apr 2022 19:57:05 +0800 Subject: [PATCH 08/48] chore: rm CreateByExcel API --- packages/nocodb-sdk/src/lib/Api.ts | 33 --------------- scripts/sdk/swagger.json | 68 ------------------------------ 2 files changed, 101 deletions(-) diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index 3ca7adba17..ee6bb65487 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -1204,39 +1204,6 @@ export class Api< ...params, }), - /** - * @description Create Project by Importing Excel File - * - * @tags Project - * @name CreateByExcel - * @summary Project create - * @request POST:/api/v1/db/meta/projects/import/excel - * @response `200` `ProjectType` OK - */ - createByExcel: ( - data: { - title?: string; - projectType?: string; - template?: { - title?: string; - tables?: { - table_name?: string; - ref_table_name?: string; - columns?: object[]; - }[]; - }; - }, - params: RequestParams = {} - ) => - this.request({ - path: `/api/v1/db/meta/projects/import/excel`, - method: 'POST', - body: data, - type: ContentType.Json, - format: 'json', - ...params, - }), - /** * @description Read project details * diff --git a/scripts/sdk/swagger.json b/scripts/sdk/swagger.json index 8ce379b025..091505e9a9 100644 --- a/scripts/sdk/swagger.json +++ b/scripts/sdk/swagger.json @@ -801,74 +801,6 @@ ] } }, - "/api/v1/db/meta/projects/import/excel": { - "parameters": [], - "post": { - "summary": "Project create", - "operationId": "project-create-by-excel", - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Project" - } - } - } - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "projectType": { - "type": "string" - }, - "template": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "tables": { - "type": "array", - "items": { - "type": "object", - "properties": { - "table_name": { - "type": "string" - }, - "ref_table_name": { - "type": "string" - }, - "columns": { - "type": "array", - "items": { - "type": "object" - } - } - } - } - } - } - } - } - } - } - } - }, - "tags": [ - "Project" - ], - "description": "Create Project by Importing Excel File" - } - }, "/api/v1/db/meta/projects/{projectId}": { "parameters": [ { From 26205c1d9a6706fd1212e3b24aec0561a7caba0b Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 30 Apr 2022 13:19:53 +0800 Subject: [PATCH 09/48] enhancement: add tooltip --- .../nc-gui/components/templates/editor.vue | 59 +++++++++++-------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/packages/nc-gui/components/templates/editor.vue b/packages/nc-gui/components/templates/editor.vue index 30f4840b45..b9e353c93d 100644 --- a/packages/nc-gui/components/templates/editor.vue +++ b/packages/nc-gui/components/templates/editor.vue @@ -118,15 +118,24 @@ - - mdi-delete-outline - + + + Delete Table + + Delete Column + - - - - - From 387fa87a3ca442cd2f649a1de1f1b7261cc39f06 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 30 Apr 2022 13:28:34 +0800 Subject: [PATCH 10/48] enhancement: add tooltips to bottom options --- .../nc-gui/components/templates/editor.vue | 195 +++++++++++------- 1 file changed, 122 insertions(+), 73 deletions(-) diff --git a/packages/nc-gui/components/templates/editor.vue b/packages/nc-gui/components/templates/editor.vue index b9e353c93d..0022d00f6f 100644 --- a/packages/nc-gui/components/templates/editor.vue +++ b/packages/nc-gui/components/templates/editor.vue @@ -118,10 +118,8 @@ - - + Delete Table @@ -495,24 +493,22 @@ " /> - - + Delete Column @@ -522,57 +518,110 @@
- - {{ getIcon("Number") }} - - - {{ getIcon("SingleLineText") }} - - - {{ getIcon("LongText") }} - - - {{ getIcon("LinkToAnotherRecord") }} - - - {{ getIcon("Lookup") }} - - - {{ getIcon("Rollup") }} - - - + column - + + + + Add Number Column + + + + + + Add SingleLineText Column + + + + + + Add LongText Column + + + + + + Add LinkToAnotherRecord Column + + + + + + Add Lookup Column + + + + + + Add Rollup Column + + + + + + Add Other Column +
From ab15302850a3e842b74b5b341169e5a87671d10e Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 30 Apr 2022 13:31:33 +0800 Subject: [PATCH 11/48] chore: lint fix --- .../nc-gui/components/templates/editor.vue | 774 +++++++++--------- 1 file changed, 387 insertions(+), 387 deletions(-) diff --git a/packages/nc-gui/components/templates/editor.vue b/packages/nc-gui/components/templates/editor.vue index 0022d00f6f..787809a2d2 100644 --- a/packages/nc-gui/components/templates/editor.vue +++ b/packages/nc-gui/components/templates/editor.vue @@ -761,75 +761,75 @@ import { uiTypes, getUIDTIcon, - UITypes, -} from "~/components/project/spreadsheet/helpers/uiTypes"; -import GradientGenerator from "~/components/templates/gradientGenerator"; -import Help from "~/components/templates/help"; + UITypes +} from '~/components/project/spreadsheet/helpers/uiTypes' +import GradientGenerator from '~/components/templates/gradientGenerator' +import Help from '~/components/templates/help' -const LinkToAnotherRecord = "LinkToAnotherRecord"; -const Lookup = "Lookup"; -const Rollup = "Rollup"; -const defaultColProp = {}; +const LinkToAnotherRecord = 'LinkToAnotherRecord' +const Lookup = 'Lookup' +const Rollup = 'Rollup' +const defaultColProp = {} export default { - name: "TemplateEditor", + name: 'TemplateEditor', components: { Help, GradientGenerator }, props: { id: [Number, String], viewMode: Boolean, projectTemplate: Object, - excelImport: Boolean, + excelImport: Boolean }, data: () => ({ loading: false, localId: null, valid: false, - url: "", + url: '', githubConfigForm: false, helpModal: false, editableTn: {}, expansionPanel: 0, project: { - name: "Project name", - tables: [], + name: 'Project name', + tables: [] }, - tableNamesInput: "", - columnNamesInput: "", + tableNamesInput: '', + columnNamesInput: '', createTablesDialog: false, createTableColumnsDialog: false, selectedTable: null, uiTypes: uiTypes.filter( - (t) => ![UITypes.Formula, UITypes.SpecificDBType].includes(t.name) + t => ![UITypes.Formula, UITypes.SpecificDBType].includes(t.name) ), rollupFnList: [ - { text: "count", value: "count" }, - { text: "min", value: "min" }, - { text: "max", value: "max" }, - { text: "avg", value: "avg" }, - { text: "min", value: "min" }, - { text: "sum", value: "sum" }, - { text: "countDistinct", value: "countDistinct" }, - { text: "sumDistinct", value: "sumDistinct" }, - { text: "avgDistinct", value: "avgDistinct" }, + { text: 'count', value: 'count' }, + { text: 'min', value: 'min' }, + { text: 'max', value: 'max' }, + { text: 'avg', value: 'avg' }, + { text: 'min', value: 'min' }, + { text: 'sum', value: 'sum' }, + { text: 'countDistinct', value: 'countDistinct' }, + { text: 'sumDistinct', value: 'sumDistinct' }, + { text: 'avgDistinct', value: 'avgDistinct' } ], colors: { - LinkToAnotherRecord: "blue lighten-5", - Rollup: "pink lighten-5", - Lookup: "green lighten-5", - }, + LinkToAnotherRecord: 'blue lighten-5', + Rollup: 'pink lighten-5', + Lookup: 'green lighten-5' + } }), computed: { counter: { get() { - return this.$store.state.templateC; + return this.$store.state.templateC }, set(c) { - this.$store.commit("mutTemplateC", c); - }, + this.$store.commit('mutTemplateC', c) + } }, updateFilename() { - return this.url && this.url.split("/").pop(); - }, + return this.url && this.url.split('/').pop() + } }, watch: { project: { @@ -844,26 +844,26 @@ export default { hasMany: [], manyToMany: [], belongsTo: [], - v: [], - }; + v: [] + } for (const column of t.columns || []) { if (this.isRelation(column)) { - if (column.type === "hm") { + if (column.type === 'hm') { table.hasMany.push({ tn: column.rtn, - _cn: column.column_name, - }); - } else if (column.type === "mm") { + _cn: column.column_name + }) + } else if (column.type === 'mm') { table.manyToMany.push({ rtn: column.rtn, - _cn: column.column_name, - }); + _cn: column.column_name + }) } else if (column.uidt === UITypes.ForeignKey) { table.belongsTo.push({ tn: column.rtn, - _cn: column.column_name, - }); + _cn: column.column_name + }) } } else if (this.isLookup(column)) { if (column.rtn) { @@ -872,9 +872,9 @@ export default { lk: { ltn: column.rtn.table_name, type: column.rtn.type, - lcn: column.rcn, - }, - }); + lcn: column.rcn + } + }) } } else if (this.isRollup(column)) { if (column.rtn) { @@ -884,267 +884,267 @@ export default { rltn: column.rtn.table_name, rlcn: column.rcn, type: column.rtn.type, - fn: column.fn, - }, - }); + fn: column.fn + } + }) } } else { - table.columns.push(column); + table.columns.push(column) } } - return table; - }), - }; - this.$emit("update:projectTemplate", template); - }, - }, + return table + }) + } + this.$emit('update:projectTemplate', template) + } + } }, created() { - document.addEventListener("keydown", this.handleKeyDown); + document.addEventListener('keydown', this.handleKeyDown) }, destroyed() { - document.removeEventListener("keydown", this.handleKeyDown); + document.removeEventListener('keydown', this.handleKeyDown) }, mounted() { - this.parseAndLoadTemplate(); + this.parseAndLoadTemplate() const input = - this.$refs.projec && this.$refs.project.$el.querySelector("input"); + this.$refs.projec && this.$refs.project.$el.querySelector('input') if (input) { - input.focus(); - input.select(); + input.focus() + input.select() } }, methods: { createTableClick() { - this.createTablesDialog = true; - this.$e("c:table:create:navdraw"); + this.createTablesDialog = true + this.$e('c:table:create:navdraw') }, parseAndLoadTemplate() { if (this.projectTemplate) { - this.parseTemplate(this.projectTemplate); + this.parseTemplate(this.projectTemplate) this.expansionPanel = Array.from( { length: this.project.tables.length }, (_, i) => i - ); + ) } }, getIcon(type) { - return getUIDTIcon(type); + return getUIDTIcon(type) }, getRelatedTables(tableName, rollup = false) { - const tables = []; + const tables = [] for (const t of this.projectTemplate.tables) { if (tableName === t.table_name) { for (const hm of t.hasMany) { const rTable = this.project.tables.find( - (t1) => t1.table_name === hm.table_name - ); + t1 => t1.table_name === hm.table_name + ) tables.push({ ...rTable, - type: "hm", - }); + type: 'hm' + }) } for (const mm of t.manyToMany) { const rTable = this.project.tables.find( - (t1) => t1.table_name === mm.rtn - ); + t1 => t1.table_name === mm.rtn + ) tables.push({ ...rTable, - type: "mm", - }); + type: 'mm' + }) } } else { for (const hm of t.hasMany) { if (hm.table_name === tableName && !rollup) { tables.push({ ...t, - type: "bt", - }); + type: 'bt' + }) } } for (const mm of t.manyToMany) { if (mm.rtn === tableName) { tables.push({ ...t, - type: "mm", - }); + type: 'mm' + }) } } } } - return tables; + return tables }, validateAndFocus() { if (!this.$refs.form.validate()) { - const input = this.$el.querySelector(".v-input.error--text"); + const input = this.$el.querySelector('.v-input.error--text') this.expansionPanel = input && input.parentElement && input.parentElement.parentElement && - +input.parentElement.parentElement.dataset.exp; + +input.parentElement.parentElement.dataset.exp setTimeout(() => { - input.querySelector("input,select").focus(); - }, 500); - return false; + input.querySelector('input,select').focus() + }, 500) + return false } - return true; + return true }, deleteTable(i) { - const deleteTable = this.project.tables[i]; + const deleteTable = this.project.tables[i] for (const table of this.project.tables) { if (table === deleteTable) { - continue; + continue } table.columns = table.columns.filter( - (c) => c.rtn !== deleteTable.table_name - ); + c => c.rtn !== deleteTable.table_name + ) } - this.project.tables.splice(i, 1); + this.project.tables.splice(i, 1) }, deleteTableColumn(i, j, col, table) { - const deleteTable = this.project.tables[i]; - const deleteColumn = deleteTable.columns[j]; + const deleteTable = this.project.tables[i] + const deleteColumn = deleteTable.columns[j] - let rTable, index; + let rTable, index // if relation column, delete the corresponding relation from other table if (col.uidt === UITypes.LinkToAnotherRecord) { - if (col.type === "hm") { - rTable = this.project.tables.find((t) => t.table_name === col.rtn); + if (col.type === 'hm') { + rTable = this.project.tables.find(t => t.table_name === col.rtn) index = rTable && rTable.columns.findIndex( - (c) => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name - ); - } else if (col.type === "mm") { - rTable = this.project.tables.find((t) => t.table_name === col.rtn); + c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + ) + } else if (col.type === 'mm') { + rTable = this.project.tables.find(t => t.table_name === col.rtn) index = rTable && rTable.columns.findIndex( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "mm" - ); + c.type === 'mm' + ) } } else if (col.uidt === UITypes.ForeignKey) { - rTable = this.project.tables.find((t) => t.table_name === col.rtn); + rTable = this.project.tables.find(t => t.table_name === col.rtn) index = rTable && rTable.columns.findIndex( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "hm" - ); + c.type === 'hm' + ) } if (rTable && index > -1) { - rTable.columns.splice(index, 1); + rTable.columns.splice(index, 1) } for (const table of this.project.tables) { if (table === deleteTable) { - continue; + continue } table.columns = table.columns.filter( - (c) => + c => c.rtn !== deleteTable.table_name || c.rcn !== deleteColumn.column_name - ); + ) } - deleteTable.columns.splice(j, 1); + deleteTable.columns.splice(j, 1) }, addTables() { if (!this.tableNamesInput) { - return; + return } // todo: fix const re = - /(?:^|,\s*)(\w+)(?:\(((\w+)(?:\s*,\s*\w+)?)?\)){0,1}(?=\s*,|\s*$)/g; - let m; + /(?:^|,\s*)(\w+)(?:\(((\w+)(?:\s*,\s*\w+)?)?\)){0,1}(?=\s*,|\s*$)/g + let m // eslint-disable-next-line no-cond-assign while ((m = re.exec(this.tableNamesInput))) { - if (this.project.tables.some((t) => t.table_name === m[1])) { - this.$toast.info(`Table '${m[1]}' is already exist`).goAway(1000); - continue; + if (this.project.tables.some(t => t.table_name === m[1])) { + this.$toast.info(`Table '${m[1]}' is already exist`).goAway(1000) + continue } this.project.tables.push({ tn: m[1], columns: (m[2] ? m[2].split(/\s*,\s*/) : []) - .map((col) => ({ + .map(col => ({ cn: col, - ...defaultColProp, + ...defaultColProp })) .filter( (v, i, arr) => - i === arr.findIndex((c) => c.column_name === v.column_name) - ), - }); + i === arr.findIndex(c => c.column_name === v.column_name) + ) + }) } - this.createTablesDialog = false; - this.tableNamesInput = ""; + this.createTablesDialog = false + this.tableNamesInput = '' }, compareRel(a, b) { return ( ((a && a.table_name) || a) === ((b && b.table_name) || b) && (a && a.type) === (b && b.type) - ); + ) }, addColumns() { if (!this.columnNamesInput) { - return; + return } - const table = this.project.tables[this.expansionPanel]; + const table = this.project.tables[this.expansionPanel] for (const col of this.columnNamesInput.split(/\s*,\s*/)) { - if (table.columns.some((c) => c.column_name === col)) { - this.$toast.info(`Column '${col}' is already exist`).goAway(1000); - continue; + if (table.columns.some(c => c.column_name === col)) { + this.$toast.info(`Column '${col}' is already exist`).goAway(1000) + continue } table.columns.push({ cn: col, - ...defaultColProp, - }); + ...defaultColProp + }) } - this.columnNamesInput = ""; - this.createTableColumnsDialog = false; + this.columnNamesInput = '' + this.createTableColumnsDialog = false this.$nextTick(() => { const input = this.$refs[ `uidt_${table.table_name}_${table.columns.length - 1}` - ][0].$el.querySelector("input"); - input.focus(); + ][0].$el.querySelector('input') + input.focus() this.$nextTick(() => { - input.select(); - }); - }); + input.select() + }) + }) }, showColCreateDialog(table) { - this.createTableColumnsDialog = true; - this.selectedTable = table; + this.createTableColumnsDialog = true + this.selectedTable = table }, isRelation(col) { - return col.uidt === "LinkToAnotherRecord" || col.uidt === "ForeignKey"; + return col.uidt === 'LinkToAnotherRecord' || col.uidt === 'ForeignKey' }, isLookup(col) { - return col.uidt === "Lookup"; + return col.uidt === 'Lookup' }, isRollup(col) { - return col.uidt === "Rollup"; + return col.uidt === 'Rollup' }, isVirtual(col) { - return col && uiTypes.some((ut) => ut.name === col.uidt && ut.virtual); + return col && uiTypes.some(ut => ut.name === col.uidt && ut.virtual) }, isLookupOrRollup(col) { - return this.isLookup(col) || this.isRollup(col); + return this.isLookup(col) || this.isRollup(col) }, isSelect(col) { - return col.uidt === "MultiSelect" || col.uidt === "SingleSelect"; + return col.uidt === 'MultiSelect' || col.uidt === 'SingleSelect' }, addNewColumnRow(table, uidt) { table.columns.push({ @@ -1153,120 +1153,120 @@ export default { uidt, ...(uidt === LinkToAnotherRecord ? { - type: "mm", + type: 'mm' } - : {}), - }); + : {}) + }) this.$nextTick(() => { const input = this.$refs[ `cn_${table.table_name}_${table.columns.length - 1}` - ][0].$el.querySelector("input"); - input.focus(); - input.select(); - }); + ][0].$el.querySelector('input') + input.focus() + input.select() + }) }, async handleKeyDown({ metaKey, key, altKey, shiftKey, ctrlKey }) { if (!(metaKey && ctrlKey) && !(altKey && shiftKey)) { - return; + return } switch (key && key.toLowerCase()) { - case "t": - this.createTablesDialog = true; - break; - case "c": - this.createTableColumnsDialog = true; - break; - case "a": - this.addNewColumnRow(this.project.tables[this.expansionPanel]); - break; - case "j": - this.copyJSON(); - break; - case "s": - await this.saveTemplate(); - break; - case "arrowup": + case 't': + this.createTablesDialog = true + break + case 'c': + this.createTableColumnsDialog = true + break + case 'a': + this.addNewColumnRow(this.project.tables[this.expansionPanel]) + break + case 'j': + this.copyJSON() + break + case 's': + await this.saveTemplate() + break + case 'arrowup': this.expansionPanel = this.expansionPanel ? --this.expansionPanel - : this.project.tables.length - 1; - break; - case "arrowdown": + : this.project.tables.length - 1 + break + case 'arrowdown': this.expansionPanel = - ++this.expansionPanel % this.project.tables.length; - break; + ++this.expansionPanel % this.project.tables.length + break - case "1": + case '1': this.addNewColumnRow( this.project.tables[this.expansionPanel], - "Number" - ); - break; - case "2": + 'Number' + ) + break + case '2': this.addNewColumnRow( this.project.tables[this.expansionPanel], - "SingleLineText" - ); - break; - case "3": + 'SingleLineText' + ) + break + case '3': this.addNewColumnRow( this.project.tables[this.expansionPanel], - "LongText" - ); - break; - case "4": + 'LongText' + ) + break + case '4': this.addNewColumnRow( this.project.tables[this.expansionPanel], - "LinkToAnotherRecord" - ); - break; - case "5": + 'LinkToAnotherRecord' + ) + break + case '5': this.addNewColumnRow( this.project.tables[this.expansionPanel], - "Lookup" - ); - break; - case "6": + 'Lookup' + ) + break + case '6': this.addNewColumnRow( this.project.tables[this.expansionPanel], - "Rollup" - ); - break; + 'Rollup' + ) + break } }, copyJSON() { if (!this.validateAndFocus()) { - this.$toast.info("Please fill all the required column!").goAway(5000); - return; + this.$toast.info('Please fill all the required column!').goAway(5000) + return } - const el = document.createElement("textarea"); - el.addEventListener("focusin", (e) => e.stopPropagation()); - el.value = JSON.stringify(this.projectTemplate, null, 2); - el.style = { position: "absolute", left: "-9999px" }; - document.body.appendChild(el); - el.select(); - document.execCommand("copy"); - document.body.removeChild(el); + const el = document.createElement('textarea') + el.addEventListener('focusin', e => e.stopPropagation()) + el.value = JSON.stringify(this.projectTemplate, null, 2) + el.style = { position: 'absolute', left: '-9999px' } + document.body.appendChild(el) + el.select() + document.execCommand('copy') + document.body.removeChild(el) this.$toast - .success("Successfully copied JSON data to clipboard!") - .goAway(3000); - return true; + .success('Successfully copied JSON data to clipboard!') + .goAway(3000) + return true }, openUrl() { - window.open(this.url, "_blank"); + window.open(this.url, '_blank') }, async loadUrl() { try { - let template = (await this.$axios.get(this.url)).data; + let template = (await this.$axios.get(this.url)).data - if (typeof template === "string") { - template = JSON.parse(template); + if (typeof template === 'string') { + template = JSON.parse(template) } - this.parseTemplate(template); + this.parseTemplate(template) } catch (e) { - this.$toast.error(e.message).goAway(5000); + this.$toast.error(e.message).goAway(5000) } }, @@ -1285,62 +1285,62 @@ export default { ...rest, columns: [ ...columns, - ...manyToMany.map((mm) => ({ + ...manyToMany.map(mm => ({ cn: mm.title || `${rest.table_name} <=> ${mm.rtn}`, uidt: LinkToAnotherRecord, - type: "mm", - ...mm, + type: 'mm', + ...mm })), - ...hasMany.map((hm) => ({ + ...hasMany.map(hm => ({ cn: hm.title || `${rest.table_name} => ${hm.table_name}`, uidt: LinkToAnotherRecord, - type: "hm", + type: 'hm', rtn: hm.table_name, - ...hm, + ...hm })), - ...belongsTo.map((bt) => ({ + ...belongsTo.map(bt => ({ cn: bt.title || `${rest.table_name} => ${bt.rtn}`, uidt: UITypes.ForeignKey, rtn: bt.table_name, - ...bt, + ...bt })), ...v.map((v) => { const res = { cn: v.title, rtn: { - ...v, - }, - }; + ...v + } + } if (v.lk) { - res.uidt = Lookup; - res.rtn.table_name = v.lk.ltn; - res.rcn = v.lk.lcn; - res.rtn.type = v.lk.type; + res.uidt = Lookup + res.rtn.table_name = v.lk.ltn + res.rcn = v.lk.lcn + res.rtn.type = v.lk.type } else if (v.rl) { - res.uidt = Rollup; - res.rtn.table_name = v.rl.rltn; - res.rcn = v.rl.rlcn; - res.rtn.type = v.rl.type; - res.fn = v.rl.fn; + res.uidt = Rollup + res.rtn.table_name = v.rl.rltn + res.rcn = v.rl.rlcn + res.rtn.type = v.rl.type + res.fn = v.rl.fn } - return res; - }), - ], + return res + }) + ] }) - ), - }; + ) + } - this.project = parsedTemplate; + this.project = parsedTemplate }, async projectTemplateCreate() { if (!this.validateAndFocus()) { - this.$toast.info("Please fill all the required column!").goAway(5000); - return; + this.$toast.info('Please fill all the required column!').goAway(5000) + return } try { - const githubConfig = this.$store.state.github; + const githubConfig = this.$store.state.github // const token = await models.store.where({ key: 'GITHUB_TOKEN' }).first() // const branch = await models.store.where({ key: 'GITHUB_BRANCH' }).first() @@ -1348,75 +1348,75 @@ export default { // const templateRepo = await models.store.where({ key: 'PROJECT_TEMPLATES_REPO' }).first() if (!githubConfig.token || !githubConfig.repo) { - throw new Error("Missing token or template path"); + throw new Error('Missing token or template path') } - const data = JSON.stringify(this.projectTemplate, 0, 2); + const data = JSON.stringify(this.projectTemplate, 0, 2) const filename = this.updateFilename || - `${this.projectTemplate.name}_${Date.now()}.json`; + `${this.projectTemplate.name}_${Date.now()}.json` const filePath = `${ - githubConfig.filePath ? githubConfig.filePath + "/" : "" - }${filename}`; - const apiPath = `https://api.github.com/repos/${githubConfig.repo}/contents/${filePath}`; + githubConfig.filePath ? githubConfig.filePath + '/' : '' + }${filename}` + const apiPath = `https://api.github.com/repos/${githubConfig.repo}/contents/${filePath}` - let sha; + let sha if (this.updateFilename) { const { - data: { sha: _sha }, + data: { sha: _sha } } = await this.$axios({ url: `https://api.github.com/repos/${githubConfig.repo}/contents/${filePath}`, - method: "get", + method: 'get', headers: { - Authorization: "token " + githubConfig.token, - }, - }); - sha = _sha; + Authorization: 'token ' + githubConfig.token + } + }) + sha = _sha } await this.$axios({ url: apiPath, - method: "put", + method: 'put', headers: { - "Content-Type": "application/json", - Authorization: "token " + githubConfig.token, + 'Content-Type': 'application/json', + Authorization: 'token ' + githubConfig.token }, data: { message: `templates : init template ${filename}`, content: Base64.encode(data), sha, - branch: githubConfig.branch, - }, - }); + branch: githubConfig.branch + } + }) - this.url = `https://raw.githubusercontent.com/${githubConfig.repo}/${githubConfig.branch}/${filePath}`; + this.url = `https://raw.githubusercontent.com/${githubConfig.repo}/${githubConfig.branch}/${filePath}` this.$toast - .success("Template generated and saved successfully!") - .goAway(4000); + .success('Template generated and saved successfully!') + .goAway(4000) } catch (e) { - this.$toast.error(e.message).goAway(5000); + this.$toast.error(e.message).goAway(5000) } }, navigateToTable(tn) { const index = this.projectTemplate.tables.findIndex( - (t) => t.table_name === tn - ); + t => t.table_name === tn + ) if (Array.isArray(this.expansionPanel)) { - this.expansionPanel.push(index); + this.expansionPanel.push(index) } else { - this.expansionPanel = index; + this.expansionPanel = index } this.$nextTick(() => { - const accord = this.$el.querySelector(`#tn_${tn}`); - accord.focus(); - accord.scrollIntoView(); - }); + const accord = this.$el.querySelector(`#tn_${tn}`) + accord.focus() + accord.scrollIntoView() + }) }, async saveTemplate() { - this.loading = true; + this.loading = true try { if (this.id || this.localId) { await this.$axios.put( @@ -1426,281 +1426,281 @@ export default { this.projectTemplate, { params: { - token: this.$store.state.template, - }, + token: this.$store.state.template + } } - ); - this.$toast.success("Template updated successfully").goAway(3000); + ) + this.$toast.success('Template updated successfully').goAway(3000) } else if (!this.$store.state.template) { if (!this.copyJSON()) { - return; + return } - this.$toast.info("Initiating Github for template").goAway(3000); + this.$toast.info('Initiating Github for template').goAway(3000) const res = await this.$axios.post( `${process.env.NC_API_URL}/api/v1/projectTemplateCreate`, this.projectTemplate - ); - this.$toast.success("Initiated Github successfully").goAway(3000); - window.open(res.data.path, "_blank"); + ) + this.$toast.success('Initiated Github successfully').goAway(3000) + window.open(res.data.path, '_blank') } else { const res = await this.$axios.post( `${process.env.NC_API_URL}/api/v1/nc/templates`, this.projectTemplate, { params: { - token: this.$store.state.template, - }, + token: this.$store.state.template + } } - ); - this.localId = res.data.id; - this.$toast.success("Template updated successfully").goAway(3000); + ) + this.localId = res.data.id + this.$toast.success('Template updated successfully').goAway(3000) } - this.$emit("saved"); + this.$emit('saved') } catch (e) { - this.$toast.error(e.message).goAway(3000); + this.$toast.error(e.message).goAway(3000) } finally { - this.loading = false; + this.loading = false } }, getRules(col, table) { - return (v) => + return v => col.uidt !== UITypes.LinkToAnotherRecord || !table.columns.some( - (c) => + c => c !== col && c.uidt === UITypes.LinkToAnotherRecord && c.type === col.type && c.rtn === col.rtn ) || - "Duplicate relation is not allowed"; + 'Duplicate relation is not allowed' }, onTableNameUpdate(oldTable, newVal) { - const oldVal = oldTable.table_name; - this.$set(oldTable, "tn", newVal); + const oldVal = oldTable.table_name + this.$set(oldTable, 'tn', newVal) for (const table of this.project.tables) { for (const col of table.columns) { if (col.uidt === UITypes.LinkToAnotherRecord) { if (col.rtn === oldVal) { - this.$set(col, "rtn", newVal); + this.$set(col, 'rtn', newVal) } } else if ( col.uidt === UITypes.Rollup || col.uidt === UITypes.Lookup ) { if (col.rtn && col.rtn.table_name === oldVal) { - this.$set(col.rtn, "tn", newVal); + this.$set(col.rtn, 'tn', newVal) } } } } }, onColumnNameUpdate(oldCol, newVal, tn) { - const oldVal = oldCol.column_name; - this.$set(oldCol, "cn", newVal); + const oldVal = oldCol.column_name + this.$set(oldCol, 'cn', newVal) for (const table of this.project.tables) { for (const col of table.columns) { if (col.uidt === UITypes.Rollup || col.uidt === UITypes.Lookup) { if (col.rtn && col.rcn === oldVal && col.rtn.table_name === tn) { - this.$set(col, "rcn", newVal); + this.$set(col, 'rcn', newVal) } } } } }, async onRtnChange(oldVal, newVal, col, table) { - this.$set(col, "rtn", newVal); + this.$set(col, 'rtn', newVal) - await this.$nextTick(); + await this.$nextTick() if ( col.uidt !== UITypes.LinkToAnotherRecord && col.uidt !== UITypes.ForeignKey ) { - return; + return } if (oldVal) { - const rTable = this.project.tables.find((t) => t.table_name === oldVal); + const rTable = this.project.tables.find(t => t.table_name === oldVal) // delete relation from other table if exist - let index = -1; - if (col.uidt === UITypes.LinkToAnotherRecord && col.type === "mm") { + let index = -1 + if (col.uidt === UITypes.LinkToAnotherRecord && col.type === 'mm') { index = rTable.columns.findIndex( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "mm" - ); + c.type === 'mm' + ) } else if ( col.uidt === UITypes.LinkToAnotherRecord && - col.type === "hm" + col.type === 'hm' ) { index = rTable.columns.findIndex( - (c) => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name - ); + c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + ) } else if (col.uidt === UITypes.ForeignKey) { index = rTable.columns.findIndex( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "hm" - ); + c.type === 'hm' + ) } if (index > -1) { - rTable.columns.splice(index, 1); + rTable.columns.splice(index, 1) } } if (newVal) { - const rTable = this.project.tables.find((t) => t.table_name === newVal); + const rTable = this.project.tables.find(t => t.table_name === newVal) // check relation relation exist in other table // if not create a relation - if (col.uidt === UITypes.LinkToAnotherRecord && col.type === "mm") { + if (col.uidt === UITypes.LinkToAnotherRecord && col.type === 'mm') { if ( !rTable.columns.find( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "mm" + c.type === 'mm' ) ) { rTable.columns.push({ cn: `title${rTable.columns.length + 1}`, uidt: UITypes.LinkToAnotherRecord, - type: "mm", - rtn: table.table_name, - }); + type: 'mm', + rtn: table.table_name + }) } } else if ( col.uidt === UITypes.LinkToAnotherRecord && - col.type === "hm" + col.type === 'hm' ) { if ( !rTable.columns.find( - (c) => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name ) ) { rTable.columns.push({ cn: `title${rTable.columns.length + 1}`, uidt: UITypes.ForeignKey, - rtn: table.table_name, - }); + rtn: table.table_name + }) } } else if (col.uidt === UITypes.ForeignKey) { if ( !rTable.columns.find( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "hm" + c.type === 'hm' ) ) { rTable.columns.push({ cn: `title${rTable.columns.length + 1}`, uidt: UITypes.LinkToAnotherRecord, - type: "hm", - rtn: table.table_name, - }); + type: 'hm', + rtn: table.table_name + }) } } } }, onRTypeChange(oldType, newType, col, table) { - this.$set(col, "type", newType); + this.$set(col, 'type', newType) - const rTable = this.project.tables.find((t) => t.table_name === col.rtn); + const rTable = this.project.tables.find(t => t.table_name === col.rtn) - let index = -1; + let index = -1 // find column and update relation // or create a new column - if (oldType === "hm") { + if (oldType === 'hm') { index = rTable.columns.findIndex( - (c) => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name - ); - } else if (oldType === "mm") { + c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + ) + } else if (oldType === 'mm') { index = rTable.columns.findIndex( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "mm" - ); + c.type === 'mm' + ) } const rCol = index === -1 ? { cn: `title${rTable.columns.length + 1}` } - : { ...rTable.columns[index] }; - index = index === -1 ? rTable.columns.length : index; - - if (newType === "mm") { - rCol.type = "mm"; - rCol.uidt = UITypes.LinkToAnotherRecord; - } else if (newType === "hm") { - rCol.type = "bt"; - rCol.uidt = UITypes.ForeignKey; + : { ...rTable.columns[index] } + index = index === -1 ? rTable.columns.length : index + + if (newType === 'mm') { + rCol.type = 'mm' + rCol.uidt = UITypes.LinkToAnotherRecord + } else if (newType === 'hm') { + rCol.type = 'bt' + rCol.uidt = UITypes.ForeignKey } - rCol.rtn = table.table_name; + rCol.rtn = table.table_name - this.$set(rTable.columns, index, rCol); + this.$set(rTable.columns, index, rCol) }, onUidtChange(oldVal, newVal, col, table) { - this.$set(col, "uidt", newVal); - this.$set(col, "dtxp", undefined); + this.$set(col, 'uidt', newVal) + this.$set(col, 'dtxp', undefined) // delete relation column from other table // if previous type is relation - let index = -1; - let rTable; + let index = -1 + let rTable if (oldVal === UITypes.LinkToAnotherRecord) { - rTable = this.project.tables.find((t) => t.table_name === col.rtn); + rTable = this.project.tables.find(t => t.table_name === col.rtn) if (rTable) { - if (col.type === "hm") { + if (col.type === 'hm') { index = rTable.columns.findIndex( - (c) => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name - ); - } else if (col.type === "mm") { + c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + ) + } else if (col.type === 'mm') { index = rTable.columns.findIndex( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "mm" - ); + c.type === 'mm' + ) } } } else if (oldVal === UITypes.ForeignKey) { - rTable = this.project.tables.find((t) => t.table_name === col.rtn); + rTable = this.project.tables.find(t => t.table_name === col.rtn) if (rTable) { index = rTable.columns.findIndex( - (c) => + c => c.uidt === UITypes.LinkToAnotherRecord && c.rtn === table.table_name && - c.type === "hm" - ); + c.type === 'hm' + ) } } if (rTable && index > -1) { - rTable.columns.splice(index, 1); + rTable.columns.splice(index, 1) } - col.rtn = undefined; - col.type = undefined; - col.rcn = undefined; + col.rtn = undefined + col.type = undefined + col.rcn = undefined if (col.uidt === LinkToAnotherRecord) { - col.type = col.type || "mm"; + col.type = col.type || 'mm' } - }, - }, -}; + } + } +} + \ No newline at end of file From ffa0ee23b09653cd3312e1b93949aad05e4d4a47 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 30 Apr 2022 18:40:46 +0800 Subject: [PATCH 15/48] fix: empty data after editing column name --- .../components/templates/createProjectFromTemplateBtn.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue index 489575b7e1..7f796a0c2d 100644 --- a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue +++ b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue @@ -162,8 +162,9 @@ export default { // mark updated column_name t.columns.map((c) => { if (c.cn) { + // update column_name if users change it + // the original one will be kept in ref_column_name c.column_name = c.cn - c.ref_column_name = c.column_name } return c }) From 2666d3cd891f98320f17bb733e954d0a0a8b2b52 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 30 Apr 2022 19:42:11 +0800 Subject: [PATCH 16/48] refactor: createProjectFromTemplateBtn.vue --- .../createProjectFromTemplateBtn.vue | 79 +++++++++---------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue index 7f796a0c2d..4cab3288d6 100644 --- a/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue +++ b/packages/nc-gui/components/templates/createProjectFromTemplateBtn.vue @@ -101,25 +101,26 @@ export default { let project + // Not available now if (this.importToProject) { - this.$store.commit('loader/MutMessage', 'Importing excel template') - - const res = await this.$store.dispatch('sqlMgr/ActSqlOp', [{ - // todo: extract based on active - dbAlias: 'db', // this.nodes.dbAlias, - env: '_noco' - }, 'xcModelsCreateFromTemplate', { - template: this.templateData - }]) - - if (res && res.tables && res.tables.length) { - this.$toast.success(`Imported ${res.tables.length} tables successfully`).goAway(3000) - } else { - this.$toast.success('Template imported successfully').goAway(3000) - } + // this.$store.commit('loader/MutMessage', 'Importing excel template') + + // const res = await this.$store.dispatch('sqlMgr/ActSqlOp', [{ + // // todo: extract based on active + // dbAlias: 'db', // this.nodes.dbAlias, + // env: '_noco' + // }, 'xcModelsCreateFromTemplate', { + // template: this.templateData + // }]) + + // if (res && res.tables && res.tables.length) { + // this.$toast.success(`Imported ${res.tables.length} tables successfully`).goAway(3000) + // } else { + // this.$toast.success('Template imported successfully').goAway(3000) + // } - projectId = this.$route.params.project_id - prefix = this.$store.getters['project/GtrProjectPrefix'] + // projectId = this.$route.params.project_id + // prefix = this.$store.getters['project/GtrProjectPrefix'] } else { // Create an empty project try { @@ -159,17 +160,9 @@ export default { .create({ client: 'sqlite3' }) .getNewTableColumns() .filter(c => c.column_name != 'title') - // mark updated column_name - t.columns.map((c) => { - if (c.cn) { - // update column_name if users change it - // the original one will be kept in ref_column_name - c.column_name = c.cn - } - return c - }) + const table = await this.$api.dbTable.create(project.id, { - table_name: t.ref_table_name, + table_name: t.table_name, title: '', columns: [...t.columns, ...systemColumns] }) @@ -186,26 +179,30 @@ export default { } } - if (this.tableCreation) { - // Bulk import data - if (this.importData) { - this.$store.commit('loader/MutMessage', 'Importing excel data to project') - await this.importDataToProject(this.templateData.title, project.prefix) - } - this.$store.commit('loader/MutMessage', null) - this.projectReloading = false - this.$emit('success') + if (!this.tableCreation) { + // failed to create table + return + } + + // Bulk import data + if (this.importData) { + this.$store.commit('loader/MutMessage', 'Importing excel data to project') + await this.importDataToProject(this.templateData.title) } + this.projectReloading = false + this.$emit('success') } catch (e) { console.log(e) this.$toast.error(e.message).goAway(3000) - this.$store.commit('loader/MutMessage', null) + } finally { clearInterval(interv) + this.$store.commit('loader/MutMessage', null) + this.projectCreation = false + this.tableCreation = false + this.projectReloading = false } - this.projectCreation = false - this.tableCreation = false }, - async importDataToProject(projectName, prefix) { + async importDataToProject(projectName) { let total = 0 let progress = 0 await Promise.all(this.localTemplateData.tables.map(v => (async(tableMeta) => { @@ -241,4 +238,4 @@ export default { \ No newline at end of file + From b57d5d9c33d317879b5c14fb1005ab3e0f07a4f1 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sat, 30 Apr 2022 19:42:32 +0800 Subject: [PATCH 17/48] fix: using new naming convention --- .../nc-gui/components/templates/editor.vue | 225 +++++++++--------- 1 file changed, 116 insertions(+), 109 deletions(-) diff --git a/packages/nc-gui/components/templates/editor.vue b/packages/nc-gui/components/templates/editor.vue index 787809a2d2..06504392b3 100644 --- a/packages/nc-gui/components/templates/editor.vue +++ b/packages/nc-gui/components/templates/editor.vue @@ -10,7 +10,9 @@ v-on="on" @click="$toast.info('Happy hacking!').goAway(3000)" > - mdi-file-excel-outline + + mdi-file-excel-outline + Import @@ -24,11 +26,15 @@ - mdi-close + + mdi-close + Reset - mdi-plus + + mdi-plus + New table - {{ col.rtn }} + {{ col.ref_table_name }} @@ -288,13 +294,13 @@ :items=" col.uidt === 'ForeignKey' ? [ - ...uiTypes, - { - name: 'ForeignKey', - icon: 'mdi-link-variant', - virtual: 1, - }, - ] + ...uiTypes, + { + name: 'ForeignKey', + icon: 'mdi-link-variant', + virtual: 1, + }, + ] : uiTypes " item-text="name" @@ -339,7 +345,7 @@ > @@ -413,12 +419,12 @@ - {{ col.rcn }} + {{ col.ref_column_name }} t.table_name === - ((col.rtn && - col.rtn.table_name) || - col.rtn) + ((col.ref_table_name && + col.ref_table_name.table_name) || + col.ref_table_name) ) || { columns: [] } ).columns.filter((v) => !isVirtual(v)) " @@ -484,8 +490,8 @@ v-if="!isRollup(col)" :colspan=" isLookupOrRollup(col) || - isRelation(col) || - isSelect(col) + isRelation(col) || + isSelect(col) ? isRollup(col) ? 0 : 1 @@ -501,8 +507,8 @@ small color="grey" @click.stop=" - deleteTableColumn(i, j, col, table) - " + deleteTableColumn(i, j, col, table) + " v-on="on" > mdi-delete-outline @@ -848,42 +854,43 @@ export default { } for (const column of t.columns || []) { + console.log(column) if (this.isRelation(column)) { if (column.type === 'hm') { table.hasMany.push({ - tn: column.rtn, - _cn: column.column_name + table_name: column.ref_table_name, + title: column.column_name }) } else if (column.type === 'mm') { table.manyToMany.push({ - rtn: column.rtn, - _cn: column.column_name + ref_table_name: column.ref_table_name, + title: column.column_name }) } else if (column.uidt === UITypes.ForeignKey) { table.belongsTo.push({ - tn: column.rtn, - _cn: column.column_name + table_name: column.ref_table_name, + title: column.column_name }) } } else if (this.isLookup(column)) { - if (column.rtn) { + if (column.ref_table_name) { table.v.push({ - _cn: column.column_name, + title: column.column_name, lk: { - ltn: column.rtn.table_name, - type: column.rtn.type, - lcn: column.rcn + ltn: column.ref_table_name.table_name, + type: column.ref_table_name.type, + lcn: column.ref_column_name } }) } } else if (this.isRollup(column)) { - if (column.rtn) { + if (column.ref_table_name) { table.v.push({ - _cn: column.column_name, + title: column.column_name, rl: { - rltn: column.rtn.table_name, - rlcn: column.rcn, - type: column.rtn.type, + rltn: column.ref_table_name.table_name, + rlcn: column.ref_column_name, + type: column.ref_table_name.type, fn: column.fn } }) @@ -947,7 +954,7 @@ export default { } for (const mm of t.manyToMany) { const rTable = this.project.tables.find( - t1 => t1.table_name === mm.rtn + t1 => t1.table_name === mm.ref_table_name ) tables.push({ ...rTable, @@ -964,7 +971,7 @@ export default { } } for (const mm of t.manyToMany) { - if (mm.rtn === tableName) { + if (mm.ref_table_name === tableName) { tables.push({ ...t, type: 'mm' @@ -998,7 +1005,7 @@ export default { continue } table.columns = table.columns.filter( - c => c.rtn !== deleteTable.table_name + c => c.ref_table_name !== deleteTable.table_name ) } this.project.tables.splice(i, 1) @@ -1011,31 +1018,31 @@ export default { // if relation column, delete the corresponding relation from other table if (col.uidt === UITypes.LinkToAnotherRecord) { if (col.type === 'hm') { - rTable = this.project.tables.find(t => t.table_name === col.rtn) + rTable = this.project.tables.find(t => t.table_name === col.ref_table_name) index = rTable && rTable.columns.findIndex( - c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + c => c.uidt === UITypes.ForeignKey && c.ref_table_name === table.table_name ) } else if (col.type === 'mm') { - rTable = this.project.tables.find(t => t.table_name === col.rtn) + rTable = this.project.tables.find(t => t.table_name === col.ref_table_name) index = rTable && rTable.columns.findIndex( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'mm' ) } } else if (col.uidt === UITypes.ForeignKey) { - rTable = this.project.tables.find(t => t.table_name === col.rtn) + rTable = this.project.tables.find(t => t.table_name === col.ref_table_name) index = rTable && rTable.columns.findIndex( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'hm' ) } @@ -1050,8 +1057,8 @@ export default { } table.columns = table.columns.filter( c => - c.rtn !== deleteTable.table_name || - c.rcn !== deleteColumn.column_name + c.ref_table_name !== deleteTable.table_name || + c.ref_column_name !== deleteColumn.column_name ) } deleteTable.columns.splice(j, 1) @@ -1072,10 +1079,10 @@ export default { } this.project.tables.push({ - tn: m[1], + table_name: m[1], columns: (m[2] ? m[2].split(/\s*,\s*/) : []) .map(col => ({ - cn: col, + column_name: col, ...defaultColProp })) .filter( @@ -1105,7 +1112,7 @@ export default { } table.columns.push({ - cn: col, + column_name: col, ...defaultColProp }) } @@ -1148,7 +1155,7 @@ export default { }, addNewColumnRow(table, uidt) { table.columns.push({ - cn: `title${table.columns.length + 1}`, + column_name: `title${table.columns.length + 1}`, ...defaultColProp, uidt, ...(uidt === LinkToAnotherRecord @@ -1286,41 +1293,41 @@ export default { columns: [ ...columns, ...manyToMany.map(mm => ({ - cn: mm.title || `${rest.table_name} <=> ${mm.rtn}`, + column_name: mm.title || `${rest.table_name} <=> ${mm.ref_table_name}`, uidt: LinkToAnotherRecord, type: 'mm', ...mm })), ...hasMany.map(hm => ({ - cn: hm.title || `${rest.table_name} => ${hm.table_name}`, + column_name: hm.title || `${rest.table_name} => ${hm.table_name}`, uidt: LinkToAnotherRecord, type: 'hm', - rtn: hm.table_name, + ref_table_name: hm.table_name, ...hm })), ...belongsTo.map(bt => ({ - cn: bt.title || `${rest.table_name} => ${bt.rtn}`, + column_name: bt.title || `${rest.table_name} => ${bt.ref_table_name}`, uidt: UITypes.ForeignKey, - rtn: bt.table_name, + ref_table_name: bt.table_name, ...bt })), ...v.map((v) => { const res = { - cn: v.title, - rtn: { + column_name: v.title, + ref_table_name: { ...v } } if (v.lk) { res.uidt = Lookup - res.rtn.table_name = v.lk.ltn - res.rcn = v.lk.lcn - res.rtn.type = v.lk.type + res.ref_table_name.table_name = v.lk.ltn + res.ref_column_name = v.lk.lcn + res.ref_table_name.type = v.lk.type } else if (v.rl) { res.uidt = Rollup - res.rtn.table_name = v.rl.rltn - res.rcn = v.rl.rlcn - res.rtn.type = v.rl.type + res.ref_table_name.table_name = v.rl.rltn + res.ref_column_name = v.rl.rlcn + res.ref_table_name.type = v.rl.type res.fn = v.rl.fn } return res @@ -1472,26 +1479,26 @@ export default { c !== col && c.uidt === UITypes.LinkToAnotherRecord && c.type === col.type && - c.rtn === col.rtn + c.ref_table_name === col.ref_table_name ) || 'Duplicate relation is not allowed' }, onTableNameUpdate(oldTable, newVal) { const oldVal = oldTable.table_name - this.$set(oldTable, 'tn', newVal) + this.$set(oldTable, 'table_name', newVal) for (const table of this.project.tables) { for (const col of table.columns) { if (col.uidt === UITypes.LinkToAnotherRecord) { - if (col.rtn === oldVal) { - this.$set(col, 'rtn', newVal) + if (col.ref_table_name === oldVal) { + this.$set(col, 'ref_table_name', newVal) } } else if ( col.uidt === UITypes.Rollup || col.uidt === UITypes.Lookup ) { - if (col.rtn && col.rtn.table_name === oldVal) { - this.$set(col.rtn, 'tn', newVal) + if (col.ref_table_name && col.ref_table_name.table_name === oldVal) { + this.$set(col.ref_table_name, 'table_name', newVal) } } } @@ -1499,20 +1506,20 @@ export default { }, onColumnNameUpdate(oldCol, newVal, tn) { const oldVal = oldCol.column_name - this.$set(oldCol, 'cn', newVal) + this.$set(oldCol, 'column_name', newVal) for (const table of this.project.tables) { for (const col of table.columns) { if (col.uidt === UITypes.Rollup || col.uidt === UITypes.Lookup) { - if (col.rtn && col.rcn === oldVal && col.rtn.table_name === tn) { - this.$set(col, 'rcn', newVal) + if (col.ref_table_name && col.ref_column_name === oldVal && col.ref_table_name.table_name === tn) { + this.$set(col, 'ref_column_name', newVal) } } } } }, async onRtnChange(oldVal, newVal, col, table) { - this.$set(col, 'rtn', newVal) + this.$set(col, 'ref_table_name', newVal) await this.$nextTick() @@ -1532,7 +1539,7 @@ export default { index = rTable.columns.findIndex( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'mm' ) } else if ( @@ -1540,13 +1547,13 @@ export default { col.type === 'hm' ) { index = rTable.columns.findIndex( - c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + c => c.uidt === UITypes.ForeignKey && c.ref_table_name === table.table_name ) } else if (col.uidt === UITypes.ForeignKey) { index = rTable.columns.findIndex( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'hm' ) } @@ -1565,15 +1572,15 @@ export default { !rTable.columns.find( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'mm' ) ) { rTable.columns.push({ - cn: `title${rTable.columns.length + 1}`, + column_name: `title${rTable.columns.length + 1}`, uidt: UITypes.LinkToAnotherRecord, type: 'mm', - rtn: table.table_name + ref_table_name: table.table_name }) } } else if ( @@ -1582,13 +1589,13 @@ export default { ) { if ( !rTable.columns.find( - c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + c => c.uidt === UITypes.ForeignKey && c.ref_table_name === table.table_name ) ) { rTable.columns.push({ - cn: `title${rTable.columns.length + 1}`, + column_name: `title${rTable.columns.length + 1}`, uidt: UITypes.ForeignKey, - rtn: table.table_name + ref_table_name: table.table_name }) } } else if (col.uidt === UITypes.ForeignKey) { @@ -1596,15 +1603,15 @@ export default { !rTable.columns.find( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'hm' ) ) { rTable.columns.push({ - cn: `title${rTable.columns.length + 1}`, + column_name: `title${rTable.columns.length + 1}`, uidt: UITypes.LinkToAnotherRecord, type: 'hm', - rtn: table.table_name + ref_table_name: table.table_name }) } } @@ -1613,7 +1620,7 @@ export default { onRTypeChange(oldType, newType, col, table) { this.$set(col, 'type', newType) - const rTable = this.project.tables.find(t => t.table_name === col.rtn) + const rTable = this.project.tables.find(t => t.table_name === col.ref_table_name) let index = -1 @@ -1622,20 +1629,20 @@ export default { if (oldType === 'hm') { index = rTable.columns.findIndex( - c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + c => c.uidt === UITypes.ForeignKey && c.ref_table_name === table.table_name ) } else if (oldType === 'mm') { index = rTable.columns.findIndex( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'mm' ) } const rCol = index === -1 - ? { cn: `title${rTable.columns.length + 1}` } + ? { column_name: `title${rTable.columns.length + 1}` } : { ...rTable.columns[index] } index = index === -1 ? rTable.columns.length : index @@ -1646,7 +1653,7 @@ export default { rCol.type = 'bt' rCol.uidt = UITypes.ForeignKey } - rCol.rtn = table.table_name + rCol.ref_table_name = table.table_name this.$set(rTable.columns, index, rCol) }, @@ -1661,28 +1668,28 @@ export default { let rTable if (oldVal === UITypes.LinkToAnotherRecord) { - rTable = this.project.tables.find(t => t.table_name === col.rtn) + rTable = this.project.tables.find(t => t.table_name === col.ref_table_name) if (rTable) { if (col.type === 'hm') { index = rTable.columns.findIndex( - c => c.uidt === UITypes.ForeignKey && c.rtn === table.table_name + c => c.uidt === UITypes.ForeignKey && c.ref_table_name === table.table_name ) } else if (col.type === 'mm') { index = rTable.columns.findIndex( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'mm' ) } } } else if (oldVal === UITypes.ForeignKey) { - rTable = this.project.tables.find(t => t.table_name === col.rtn) + rTable = this.project.tables.find(t => t.table_name === col.ref_table_name) if (rTable) { index = rTable.columns.findIndex( c => c.uidt === UITypes.LinkToAnotherRecord && - c.rtn === table.table_name && + c.ref_table_name === table.table_name && c.type === 'hm' ) } @@ -1691,9 +1698,9 @@ export default { rTable.columns.splice(index, 1) } - col.rtn = undefined + col.ref_table_name = undefined col.type = undefined - col.rcn = undefined + col.ref_column_name = undefined if (col.uidt === LinkToAnotherRecord) { col.type = col.type || 'mm' From c4a9f11fb1b254795137b559d5d67d2344993cac Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 4 May 2022 12:48:49 +0800 Subject: [PATCH 18/48] chore: hide virtual columns for time being --- packages/nc-gui/components/templates/editor.vue | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/nc-gui/components/templates/editor.vue b/packages/nc-gui/components/templates/editor.vue index 06504392b3..d229c185b3 100644 --- a/packages/nc-gui/components/templates/editor.vue +++ b/packages/nc-gui/components/templates/editor.vue @@ -569,7 +569,7 @@ Add LongText Column - + Add LinkToAnotherRecord Column @@ -595,7 +594,6 @@ {{ getIcon("Lookup") }} - Add Lookup Column @@ -610,9 +608,8 @@ {{ getIcon("Rollup") }} - Add Rollup Column - + --> From 19bbce998ef06cab767736ee50807a87580a3995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D5=A1=C9=A8=D5=BC=C9=A2=D3=84=D5=A1=D6=85=D5=BC=C9=A2?= Date: Sat, 14 May 2022 21:39:43 +0800 Subject: [PATCH 38/48] feat: quick import (#2042) * wip: basic add / import layout * chore: move excel from create project options to project tabs * chore: move drag attributes & rm unused methods * chore: remove create project logic * chore: rm project title text field * fix: import excel into an existing project logic * refactor: add / import menu ui * feat: integrate with import-csv logic * wip: new csv import logic * feat: import csv basic ui * refactor: use excel adapter for csv import * chore: merge excel & csv together * fix: accept csv for import * i18n: add csv to excelSupport * fix: empty map & extract error msg * fix: duplicate columns with system fields during import * chore: rename excel import -> quick import * chore: separate csv & excel for better tele * chore: pass quickImportType * i18n: remove .csv from the message * fix: wrong import type * chore: hide gradient generator * fix: file type validation * i18n: add importCSV * fix: import button text * fix: set modal to false after importing * fix: header text in quick import * chore: show error message in parseAndExtractData * i18n: add csvURL * fix: import url label * fix: wrong import type * fix: failed to execute 'insertBefore' on 'Node' * fix: delete logic & add pv to first column * feat: set default primary value * chore: disable virtual columns in dropdown * fix: set pk & rqd to ID by default * docs: remove creating project from excel * docs: add quick import * feat: add loadFirstCreatedTableTab * feat: open the tab automatically after import * test/cypress: UI corrections for quick-import Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> * fix: add UI permission to Add / Import * fix: remove unnecessary drop handler * fix: wrong class name in cypress test * fix: use v-if instead of v-show * fix: move _isUIAllowed to parent v-menu Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .../nc-gui/components/ProjectTreeView.vue | 18 +- .../{excelImport.vue => quickImport.vue} | 60 +++- .../importExport/columnMappingModal.vue | 17 +- packages/nc-gui/components/projectTabs.vue | 311 +++++++++++------- .../createProjectFromTemplateBtn.vue | 139 +++++--- .../nc-gui/components/templates/editor.vue | 60 ++-- packages/nc-gui/lang/da.json | 2 + packages/nc-gui/lang/de.json | 2 + packages/nc-gui/lang/en.json | 2 + packages/nc-gui/lang/es.json | 2 + packages/nc-gui/lang/fa.json | 2 + packages/nc-gui/lang/fi.json | 2 + packages/nc-gui/lang/fr.json | 4 +- packages/nc-gui/lang/hr.json | 2 + packages/nc-gui/lang/id.json | 2 + packages/nc-gui/lang/it_IT.json | 2 + packages/nc-gui/lang/iw.json | 2 + packages/nc-gui/lang/ja.json | 2 + packages/nc-gui/lang/ko.json | 2 + packages/nc-gui/lang/lv.json | 2 + packages/nc-gui/lang/nl.json | 2 + packages/nc-gui/lang/no.json | 2 + packages/nc-gui/lang/pl.json | 2 + packages/nc-gui/lang/pt.json | 2 + packages/nc-gui/lang/pt_BR.json | 2 + packages/nc-gui/lang/ru.json | 2 + packages/nc-gui/lang/sl.json | 2 + packages/nc-gui/lang/sv.json | 2 + packages/nc-gui/lang/th.json | 2 + packages/nc-gui/lang/tr.json | 2 + packages/nc-gui/lang/uk.json | 2 + packages/nc-gui/lang/vi.json | 2 + packages/nc-gui/lang/zh_CN.json | 2 + packages/nc-gui/lang/zh_HK.json | 2 + packages/nc-gui/lang/zh_TW.json | 2 + packages/nc-gui/pages/projects/index.vue | 46 +-- packages/nc-gui/store/tabs.js | 17 + .../content/en/setup-and-usages/dashboard.md | 29 +- .../en/setup-and-usages/table-operations.md | 46 ++- .../nocodb/src/lib/noco/meta/NcMetaMgr.ts | 2 +- .../integration/spec/roleValidation.spec.js | 2 +- scripts/cypress/support/commands.js | 1 + 42 files changed, 513 insertions(+), 295 deletions(-) rename packages/nc-gui/components/import/{excelImport.vue => quickImport.vue} (83%) diff --git a/packages/nc-gui/components/ProjectTreeView.vue b/packages/nc-gui/components/ProjectTreeView.vue index 7da30e6573..f074bd2c27 100644 --- a/packages/nc-gui/components/ProjectTreeView.vue +++ b/packages/nc-gui/components/ProjectTreeView.vue @@ -769,12 +769,12 @@ :heading="selectedNodeForDelete.heading" type="error" /> - @@ -795,7 +795,7 @@ import DlgTableCreate from "@/components/utils/dlgTableCreate"; import DlgViewCreate from "@/components/utils/dlgViewCreate"; import SponsorMini from "@/components/sponsorMini"; import {validateTableName} from "~/helpers"; -import ExcelImport from "~/components/import/excelImport"; +import QuickImport from "~/components/import/quickImport"; import draggable from "vuedraggable"; import GithubStarBtn from "~/components/githubStarBtn"; @@ -810,7 +810,7 @@ export default { SettingsModal, GithubStarBtn, draggable, - ExcelImport, + QuickImport, SponsorMini, DlgViewCreate, DlgTableCreate, @@ -864,7 +864,7 @@ export default { open: [], search: null, menuVisible: false, - excelImportDialog: false, + quickImportDialog: false, x: 0, y: 0, menuItem: null, @@ -1162,7 +1162,7 @@ export default { this.miniExpanded = false; } }, - onExcelImport() { + onQuickImport() { if (!this.menuItem || this.menuItem.type !== "tableDir") { this.menuItem = this.listViewArr.find((n) => n.type === "tableDir"); } @@ -1437,7 +1437,7 @@ export default { await this.loadViews(this.menuItem); this.$toast.success("Views refreshed").goAway(1000); } else if (action === "IMPORT_EXCEL") { - this.excelImportDialog = true; + this.quickImportDialog = true; } else if (action === "ENV_DB_FUNCTIONS_REFRESH") { await this.loadFunctions(this.menuItem); this.$toast.success("Functions refreshed").goAway(1000); diff --git a/packages/nc-gui/components/import/excelImport.vue b/packages/nc-gui/components/import/quickImport.vue similarity index 83% rename from packages/nc-gui/components/import/excelImport.vue rename to packages/nc-gui/components/import/quickImport.vue index c9f172bb26..e1c9ae8ecf 100644 --- a/packages/nc-gui/components/import/excelImport.vue +++ b/packages/nc-gui/components/import/quickImport.vue @@ -43,8 +43,8 @@ {{ $t('msg.info.upload_sub') }}

-

- +

+ {{ $t('msg.info.excelSupport') }}

@@ -60,7 +60,7 @@ v-model="url" hide-details="auto" type="url" - :label="$t('msg.info.excelURL')" + :label="quickImportType == 'excel' ? $t('msg.info.excelURL') : $t('msg.info.csvURL') " class="caption" outlined dense @@ -106,6 +106,7 @@ diff --git a/packages/nc-gui/components/projectLogs.vue b/packages/nc-gui/components/ProjectLogs.vue similarity index 100% rename from packages/nc-gui/components/projectLogs.vue rename to packages/nc-gui/components/ProjectLogs.vue diff --git a/packages/nc-gui/components/projectOutput.vue b/packages/nc-gui/components/ProjectOutput.vue similarity index 100% rename from packages/nc-gui/components/projectOutput.vue rename to packages/nc-gui/components/ProjectOutput.vue diff --git a/packages/nc-gui/components/projectTabs.vue b/packages/nc-gui/components/ProjectTabs.vue similarity index 92% rename from packages/nc-gui/components/projectTabs.vue rename to packages/nc-gui/components/ProjectTabs.vue index d272c266b2..59b2cc302d 100644 --- a/packages/nc-gui/components/projectTabs.vue +++ b/packages/nc-gui/components/ProjectTabs.vue @@ -15,7 +15,7 @@ next-icon="mdi-arrow-right-bold-box-outline" prev-icon="mdi-arrow-left-bold-box-outline" show-arrows - :class="{ 'dark-them': $store.state.windows.darkTheme }" + :class="{ 'dark-them': $store.state.settings.darkTheme }" > @@ -357,33 +357,33 @@ diff --git a/packages/nc-gui/components/auth/userManagement.vue b/packages/nc-gui/components/auth/UserManagement.vue similarity index 78% rename from packages/nc-gui/components/auth/userManagement.vue rename to packages/nc-gui/components/auth/UserManagement.vue index 4a7b861ad3..86bbbcc5aa 100644 --- a/packages/nc-gui/components/auth/userManagement.vue +++ b/packages/nc-gui/components/auth/UserManagement.vue @@ -13,7 +13,9 @@ @keypress.enter="loadUsers" > @@ -29,7 +31,9 @@ @click="clickReload" @click.prevent > - refresh + + refresh + {{ $t("general.reload") }} @@ -45,7 +49,9 @@ :disabled="loading" @click="addUser" > - mdi-plus + + mdi-plus + {{ $t("activity.newUser") }} @@ -79,12 +85,16 @@ - mdi-email-outline + + mdi-email-outline + {{ $t("labels.email") }} - mdi-drama-masks + + mdi-drama-masks + {{ $t("objects.roles") }} @@ -223,7 +233,9 @@ - mdi-account-outline + + mdi-account-outline + - mdi-close - mdi-save + + mdi-close + + + mdi-save + - mdi-account-outline + + mdi-account-outline + @@ -254,7 +272,9 @@ - mdi-account-plus + + mdi-account-plus + @@ -285,9 +305,15 @@
- mdi-account-outline - - + + mdi-account-outline + + + - diff --git a/packages/nc-gui/components/project/auditTab/audit.vue b/packages/nc-gui/components/project/auditTab/Audit.vue similarity index 98% rename from packages/nc-gui/components/project/auditTab/audit.vue rename to packages/nc-gui/components/project/auditTab/Audit.vue index f7bc5736a0..0ddfb15f48 100644 --- a/packages/nc-gui/components/project/auditTab/audit.vue +++ b/packages/nc-gui/components/project/auditTab/Audit.vue @@ -54,7 +54,7 @@ {{ audit.description }} - {{ audit.user == null?'Shared base':audit.user }} + {{ audit.user == null ? 'Shared base' : audit.user }} diff --git a/packages/nc-gui/components/project/auditTab/auditCE.vue b/packages/nc-gui/components/project/auditTab/AuditCE.vue similarity index 100% rename from packages/nc-gui/components/project/auditTab/auditCE.vue rename to packages/nc-gui/components/project/auditTab/AuditCE.vue diff --git a/packages/nc-gui/components/project/auditTab/db.vue b/packages/nc-gui/components/project/auditTab/Db.vue similarity index 100% rename from packages/nc-gui/components/project/auditTab/db.vue rename to packages/nc-gui/components/project/auditTab/Db.vue diff --git a/packages/nc-gui/components/project/dlgs/dlgAddRelation.vue b/packages/nc-gui/components/project/dlgs/DlgAddRelation.vue similarity index 100% rename from packages/nc-gui/components/project/dlgs/dlgAddRelation.vue rename to packages/nc-gui/components/project/dlgs/DlgAddRelation.vue diff --git a/packages/nc-gui/components/project/dlgs/dlgTriggerAddEdit.vue b/packages/nc-gui/components/project/dlgs/DlgTriggerAddEdit.vue similarity index 100% rename from packages/nc-gui/components/project/dlgs/dlgTriggerAddEdit.vue rename to packages/nc-gui/components/project/dlgs/DlgTriggerAddEdit.vue diff --git a/packages/nc-gui/components/project/functionTab/functionAcl.vue b/packages/nc-gui/components/project/functionTab/FunctionAcl.vue similarity index 100% rename from packages/nc-gui/components/project/functionTab/functionAcl.vue rename to packages/nc-gui/components/project/functionTab/FunctionAcl.vue diff --git a/packages/nc-gui/components/project/functionTab/functionQuery.vue b/packages/nc-gui/components/project/functionTab/FunctionQuery.vue similarity index 99% rename from packages/nc-gui/components/project/functionTab/functionQuery.vue rename to packages/nc-gui/components/project/functionTab/FunctionQuery.vue index 3a43b6e286..84538e528b 100644 --- a/packages/nc-gui/components/project/functionTab/functionQuery.vue +++ b/packages/nc-gui/components/project/functionTab/FunctionQuery.vue @@ -75,7 +75,7 @@ import { mapGetters, mapActions } from 'vuex' import { SqlUiFactory } from 'nocodb-sdk' import MonacoEditor from '../../monaco/Monaco' -import dlgLabelSubmitCancel from '../../utils/dlgLabelSubmitCancel' +import dlgLabelSubmitCancel from '../../utils/DlgLabelSubmitCancel' export default { components: { MonacoEditor, dlgLabelSubmitCancel }, diff --git a/packages/nc-gui/components/project/procedureTab/procedureAcl.vue b/packages/nc-gui/components/project/procedureTab/ProcedureAcl.vue similarity index 100% rename from packages/nc-gui/components/project/procedureTab/procedureAcl.vue rename to packages/nc-gui/components/project/procedureTab/ProcedureAcl.vue diff --git a/packages/nc-gui/components/project/procedureTab/procedureQuery.vue b/packages/nc-gui/components/project/procedureTab/ProcedureQuery.vue similarity index 99% rename from packages/nc-gui/components/project/procedureTab/procedureQuery.vue rename to packages/nc-gui/components/project/procedureTab/ProcedureQuery.vue index f8b3a819ab..967d12550c 100644 --- a/packages/nc-gui/components/project/procedureTab/procedureQuery.vue +++ b/packages/nc-gui/components/project/procedureTab/ProcedureQuery.vue @@ -71,7 +71,7 @@ import { mapGetters, mapActions } from 'vuex' import MonacoEditor from '../../monaco/Monaco' -import dlgLabelSubmitCancel from '../../utils/dlgLabelSubmitCancel' +import dlgLabelSubmitCancel from '../../utils/DlgLabelSubmitCancel' export default { components: { MonacoEditor, dlgLabelSubmitCancel }, diff --git a/packages/nc-gui/components/project/projectMetadata/disableOrEnableModels.vue b/packages/nc-gui/components/project/projectMetadata/DisableOrEnableModels.vue similarity index 88% rename from packages/nc-gui/components/project/projectMetadata/disableOrEnableModels.vue rename to packages/nc-gui/components/project/projectMetadata/DisableOrEnableModels.vue index 400e6e3159..1ffa987346 100644 --- a/packages/nc-gui/components/project/projectMetadata/disableOrEnableModels.vue +++ b/packages/nc-gui/components/project/projectMetadata/DisableOrEnableModels.vue @@ -1,15 +1,15 @@ - - - diff --git a/packages/nc-gui/components/utils/betterUX.vue b/packages/nc-gui/components/utils/BetterUX.vue similarity index 100% rename from packages/nc-gui/components/utils/betterUX.vue rename to packages/nc-gui/components/utils/BetterUX.vue diff --git a/packages/nc-gui/components/utils/dlgLabelSubmitCancel.vue b/packages/nc-gui/components/utils/DlgLabelSubmitCancel.vue similarity index 100% rename from packages/nc-gui/components/utils/dlgLabelSubmitCancel.vue rename to packages/nc-gui/components/utils/DlgLabelSubmitCancel.vue diff --git a/packages/nc-gui/components/utils/dlgOk.vue b/packages/nc-gui/components/utils/DlgOk.vue similarity index 100% rename from packages/nc-gui/components/utils/dlgOk.vue rename to packages/nc-gui/components/utils/DlgOk.vue diff --git a/packages/nc-gui/components/utils/dlgOkNew.vue b/packages/nc-gui/components/utils/DlgOkNew.vue similarity index 100% rename from packages/nc-gui/components/utils/dlgOkNew.vue rename to packages/nc-gui/components/utils/DlgOkNew.vue diff --git a/packages/nc-gui/components/utils/dlgProjectCreate.vue b/packages/nc-gui/components/utils/DlgProjectCreate.vue similarity index 96% rename from packages/nc-gui/components/utils/dlgProjectCreate.vue rename to packages/nc-gui/components/utils/DlgProjectCreate.vue index 7580003840..04a76a824f 100644 --- a/packages/nc-gui/components/utils/dlgProjectCreate.vue +++ b/packages/nc-gui/components/utils/DlgProjectCreate.vue @@ -97,7 +97,7 @@ export default { this.projectReloading = false - if (this.$store.state.project.projectInfo.firstUser || this.$store.state.project.projectInfo.authType === 'masterKey') { + if (this.$store.state.project.appInfo.firstUser || this.$store.state.project.appInfo.authType === 'masterKey') { return this.$router.push({ path: '/user/authentication/signup' }) diff --git a/packages/nc-gui/components/utils/dlgTableCreate.vue b/packages/nc-gui/components/utils/DlgTableCreate.vue similarity index 100% rename from packages/nc-gui/components/utils/dlgTableCreate.vue rename to packages/nc-gui/components/utils/DlgTableCreate.vue diff --git a/packages/nc-gui/components/utils/dlgTextSubmitCancel.vue b/packages/nc-gui/components/utils/DlgTextSubmitCancel.vue similarity index 100% rename from packages/nc-gui/components/utils/dlgTextSubmitCancel.vue rename to packages/nc-gui/components/utils/DlgTextSubmitCancel.vue diff --git a/packages/nc-gui/components/utils/dlgUnexpectedError.vue b/packages/nc-gui/components/utils/DlgUnexpectedError.vue similarity index 100% rename from packages/nc-gui/components/utils/dlgUnexpectedError.vue rename to packages/nc-gui/components/utils/DlgUnexpectedError.vue diff --git a/packages/nc-gui/components/utils/dlgViewCreate.vue b/packages/nc-gui/components/utils/DlgViewCreate.vue similarity index 100% rename from packages/nc-gui/components/utils/dlgViewCreate.vue rename to packages/nc-gui/components/utils/DlgViewCreate.vue diff --git a/packages/nc-gui/components/utils/language.vue b/packages/nc-gui/components/utils/Language.vue similarity index 57% rename from packages/nc-gui/components/utils/language.vue rename to packages/nc-gui/components/utils/Language.vue index b921431e75..5f4581e30e 100644 --- a/packages/nc-gui/components/utils/language.vue +++ b/packages/nc-gui/components/utils/Language.vue @@ -39,103 +39,103 @@ diff --git a/packages/nc-gui/components/project/auditTab/Audit.vue b/packages/nc-gui/components/project/auditTab/Audit.vue index 0ddfb15f48..339e099dc3 100644 --- a/packages/nc-gui/components/project/auditTab/Audit.vue +++ b/packages/nc-gui/components/project/auditTab/Audit.vue @@ -81,12 +81,7 @@ diff --git a/packages/nc-gui/components/project/spreadsheet/components/MoreActions.vue b/packages/nc-gui/components/project/spreadsheet/components/MoreActions.vue index 4841aa71fa..4a087c0bc5 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/MoreActions.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/MoreActions.vue @@ -104,7 +104,8 @@ :parsed-csv="parsedCsv" @import="importData" /> - + +
@@ -117,10 +118,12 @@ import ColumnMappingModal from '~/components/project/spreadsheet/components/impo import CSVTemplateAdapter from '~/components/import/templateParsers/CSVTemplateAdapter' import { UITypes } from '~/components/project/spreadsheet/helpers/uiTypes' import WebhookModal from '~/components/project/tableTabs/webhook/WebhookModal' +import WebhookSlider from '~/components/project/tableTabs/webhook/WebhookSlider' export default { name: 'ExportImport', components: { + WebhookSlider, WebhookModal, ColumnMappingModal, DropOrSelectFileModal diff --git a/packages/nc-gui/components/project/spreadsheet/components/SpreadsheetNavDrawer.vue b/packages/nc-gui/components/project/spreadsheet/components/SpreadsheetNavDrawer.vue index 69e4d8cb1d..ece4f7f95c 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/SpreadsheetNavDrawer.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/SpreadsheetNavDrawer.vue @@ -286,6 +286,20 @@
+
+ + + mdi-hook + Webhooks + + +
({ + webhookSliderModal: false, codeSnippetModal: false, drag: false, dragOptions: { diff --git a/packages/nc-gui/components/project/tableTabs/webhook/WebhookEditor.vue b/packages/nc-gui/components/project/tableTabs/webhook/WebhookEditor.vue index 0e419aaf12..e850c7de67 100644 --- a/packages/nc-gui/components/project/tableTabs/webhook/WebhookEditor.vue +++ b/packages/nc-gui/components/project/tableTabs/webhook/WebhookEditor.vue @@ -1,42 +1,41 @@ + + + + + + + + + Available context variables are diff --git a/packages/nc-gui/components/project/tableTabs/webhook/WebhookList.vue b/packages/nc-gui/components/project/tableTabs/webhook/WebhookList.vue index afb6abd09a..14223cbd10 100644 --- a/packages/nc-gui/components/project/tableTabs/webhook/WebhookList.vue +++ b/packages/nc-gui/components/project/tableTabs/webhook/WebhookList.vue @@ -1,7 +1,7 @@ + + diff --git a/packages/nc-gui/helpers/index.js b/packages/nc-gui/helpers/index.js index a711136d50..9907847208 100644 --- a/packages/nc-gui/helpers/index.js +++ b/packages/nc-gui/helpers/index.js @@ -1,3 +1,14 @@ +import dayjs from 'dayjs' + +const relativeTime = require('dayjs/plugin/relativeTime') +const utc = require('dayjs/plugin/utc') +dayjs.extend(utc) +dayjs.extend(relativeTime) + +export function calculateDiff(date) { + return dayjs.utc(date).fromNow() +} + export const isEmail = v => /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@(([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{2,})$/i.test(v) // ref : https://stackoverflow.com/a/5717133 From 3fe6c8cd8319d62a1f563e1fbda165508ec6c919 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Sun, 15 May 2022 20:27:22 +0530 Subject: [PATCH 45/48] refactoring Signed-off-by: Pranav C --- packages/nc-gui/components/import/ImportFromAirtable.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/components/import/ImportFromAirtable.vue b/packages/nc-gui/components/import/ImportFromAirtable.vue index 858960aa9c..e8f80c4a4c 100644 --- a/packages/nc-gui/components/import/ImportFromAirtable.vue +++ b/packages/nc-gui/components/import/ImportFromAirtable.vue @@ -5,7 +5,7 @@

{{ $t('title.importFromAirtable') }}

-
+
🚀
@@ -242,7 +242,7 @@ export default { }, enableTurbo() { this.$set(this.syncSource.details, 'syncViews', true) - this.$toast.success('Turbo mode activated! 🚀🚀🚀🚀').goAway(3000) + this.$toast.success('🚀🚀 Ludicrous mode activated! Let\'s go! 🚀🚀').goAway(3000) } } } From 22171bd875c5be9c8024d4950d2991181f016f65 Mon Sep 17 00:00:00 2001 From: Naveen MR Date: Sun, 15 May 2022 23:27:38 +0100 Subject: [PATCH 46/48] docs: import --- .../content/en/setup-and-usages/app-store.md | 2 +- ...le-to-sql-database-within-a-minute-for-free.md | 15 +++++++++++++++ .../content/en/setup-and-usages/languages.md | 2 +- .../en/setup-and-usages/usage-information.md | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 packages/noco-docs/content/en/setup-and-usages/import-airtable-to-sql-database-within-a-minute-for-free.md diff --git a/packages/noco-docs/content/en/setup-and-usages/app-store.md b/packages/noco-docs/content/en/setup-and-usages/app-store.md index 1ee015ad8d..b0fba0d8a6 100644 --- a/packages/noco-docs/content/en/setup-and-usages/app-store.md +++ b/packages/noco-docs/content/en/setup-and-usages/app-store.md @@ -1,7 +1,7 @@ --- title: 'App Store' description: 'App Store' -position: 1200 +position: 1100 category: 'Product' menuTitle: 'App Store' --- diff --git a/packages/noco-docs/content/en/setup-and-usages/import-airtable-to-sql-database-within-a-minute-for-free.md b/packages/noco-docs/content/en/setup-and-usages/import-airtable-to-sql-database-within-a-minute-for-free.md new file mode 100644 index 0000000000..977a6e746d --- /dev/null +++ b/packages/noco-docs/content/en/setup-and-usages/import-airtable-to-sql-database-within-a-minute-for-free.md @@ -0,0 +1,15 @@ +--- +title: 'Import: Airtable to NocoDB' +description: 'Import: Airtable to NocoDB' +position: 1150 +category: 'Product' +menuTitle: 'Import: Airtable to NocoDB' +--- + +## Import Airtable to NocoDB + +### Find & enter your Airtable API Key +- TODO + +### Share you Airtable base +- TODO \ No newline at end of file diff --git a/packages/noco-docs/content/en/setup-and-usages/languages.md b/packages/noco-docs/content/en/setup-and-usages/languages.md index 37621be85b..3c2ff98223 100644 --- a/packages/noco-docs/content/en/setup-and-usages/languages.md +++ b/packages/noco-docs/content/en/setup-and-usages/languages.md @@ -1,7 +1,7 @@ --- title: 'Languages' description: 'Languages' -position: 1200 +position: 900 category: 'Product' menuTitle: 'Languages' --- diff --git a/packages/noco-docs/content/en/setup-and-usages/usage-information.md b/packages/noco-docs/content/en/setup-and-usages/usage-information.md index fc1fd51a09..9d4e9bb97f 100644 --- a/packages/noco-docs/content/en/setup-and-usages/usage-information.md +++ b/packages/noco-docs/content/en/setup-and-usages/usage-information.md @@ -1,7 +1,7 @@ --- title: 'Usage Information' description: 'Non-sensitive and anonymous usage information' -position: 900 +position: 1200 category: 'Product' menuTitle: 'Usage Information' --- From 93099c12f5fb9586d044ee34ea0fd67af864faca Mon Sep 17 00:00:00 2001 From: SiderealArt Date: Mon, 16 May 2022 11:13:43 +0800 Subject: [PATCH 47/48] Update zh_TW.json --- packages/nc-gui/lang/zh_TW.json | 212 ++++++++++++++++---------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/packages/nc-gui/lang/zh_TW.json b/packages/nc-gui/lang/zh_TW.json index 161d84c2a6..0952e8894f 100644 --- a/packages/nc-gui/lang/zh_TW.json +++ b/packages/nc-gui/lang/zh_TW.json @@ -1,57 +1,57 @@ { "general": { "home": "首頁", - "load": "加載", - "open": "打開", + "load": "載入", + "open": "開啟", "close": "關閉", - "yes": "是的", + "yes": "是", "no": "否", - "ok": "行", + "ok": "OK", "and": "和", - "or": "或者", - "add": "添加", + "or": "或", + "add": "新增", "edit": "編輯", - "remove": "消除", - "save": "保存", + "remove": "移除", + "save": "儲存", "cancel": "取消", "submit": "提交", "create": "建立", "insert": "插入", "delete": "刪除", "update": "更新", - "rename": "改名", - "reload": "重新加載", + "rename": "重新命名", + "reload": "重新載入", "reset": "重設", "install": "安裝", - "show": "展示", + "show": "顯示", "hide": "隱藏", "showAll": "顯示所有", - "hideAll": "全部藏起來", + "hideAll": "全部隱藏", "showMore": "顯示更多", "showOptions": "顯示選項", "hideOptions": "隱藏選項", - "showMenu": "顯示菜單", - "hideMenu": "隱藏菜單", - "addAll": "全部添加", - "removeAll": "移除所有", + "showMenu": "顯示選單", + "hideMenu": "隱藏選單", + "addAll": "全部新增", + "removeAll": "全部移除", "signUp": "註冊", "signIn": "登入", "signOut": "登出", "required": "必填", "preferred": "首選", "mandatory": "強制的", - "loading": "loading ...", + "loading": "載入中...", "title": "標題", "upload": "上傳", "download": "下載", - "default": "默認", - "more": "更多的", - "less": "較少的", + "default": "預設", + "more": "更多", + "less": "較少", "event": "事件", - "condition": "健康)狀況", + "condition": "條件", "after": "後", "before": "前", - "search": "搜索", + "search": "搜尋", "notification": "通知", "reference": "參考", "function": "功能" @@ -66,12 +66,12 @@ "column": "列", "columns": "列", "page": "頁", - "pages": "頁面", + "pages": "頁", "record": "記錄", "records": "記錄", - "webhook": "Webhook.", - "webhooks": "Webhooks.", - "view": "看法", + "webhook": "Webhook", + "webhooks": "Webhook", + "view": "檢視表", "views": "檢視表", "viewType": { "grid": "網格", @@ -80,8 +80,8 @@ "kanban": "看板", "calendar": "日曆" }, - "user": "用戶", - "users": "用戶", + "user": "使用者", + "users": "使用者", "role": "角色", "roles": "角色", "roleType": { @@ -89,7 +89,7 @@ "creator": "創造者", "editor": "編輯", "commenter": "評論者", - "viewer": "觀眾" + "viewer": "檢視者" } }, "datatype": { @@ -98,16 +98,16 @@ "SingleLineText": "單行文本", "LongText": "長篇文章", "Attachment": "附件", - "Checkbox": "複選框", + "Checkbox": "核取方塊", "MultiSelect": "多選", - "SingleSelect": "單個選擇", + "SingleSelect": "單選", "Collaborator": "合作者", "Date": "日期", "Year": "年", "Time": "時間", "PhoneNumber": "電話號碼", "Email": "電子郵件", - "URL": "URL.", + "URL": "網址", "Number": "數字", "Decimal": "十進制", "Currency": "貨幣", @@ -129,7 +129,7 @@ "noAction": "沒有任何行動", "cascade": "級聯", "restrict": "嚴格", - "setNull": "設置null.", + "setNull": "設置 null", "setDefault": "默認設置" } }, @@ -158,23 +158,23 @@ "rolesMgmt": "角色管理", "projMeta": "專案中繼資料", "metaMgmt": "中繼資料管理", - "metadata": "元數據", - "exportImportMeta": "導出/導入元數據", - "uiACL": "UI訪問控制", + "metadata": "中繼資料", + "exportImportMeta": "匯出/匯入中繼資料", + "uiACL": "UI 存取控制", "metaOperations": "中繼資料操作", "audit": "稽核", "auditLogs": "稽核記錄", - "sqlMigrations": "SQL遷移", + "sqlMigrations": "SQL 遷移", "dbCredentials": "資料庫憑證", "advancedParameters": "SSL 及進階參數", "headCreateProject": "建立新專案|NocoDB", "headLogin": "登入|NocoDB", "resetPassword": "重設密碼", - "teamAndSettings": "Team & Settings", - "apiDocs": "API Docs" + "teamAndSettings": "團隊 & 設定", + "apiDocs": "API 說明文件" }, "labels": { - "notifyVia": "通知Via", + "notifyVia": "透過...通知", "projName": "項目名", "tableName": "表名稱", "viewName": "查看名稱", @@ -199,7 +199,7 @@ "operationSubType": "操作子類型", "description": "描述", "authentication": "驗證", - "token": "令牌", + "token": "權杖", "where": "在哪裡", "cache": "緩存", "chat": "聊天", @@ -208,9 +208,9 @@ "uiAcl": "UI-ACL", "models": "楷模", "syncState": "同步狀態", - "created": "創造了", - "sqlOutput": "SQL輸出", - "addOption": "添加選項", + "created": "已建立", + "sqlOutput": "SQL 輸出", + "addOption": "新增選項", "aggregateFunction": "匯總功能", "dbCreateIfNotExists": "資料庫:不存在則建立", "clientKey": "用戶端金鑰", @@ -220,7 +220,7 @@ "requriedIdentity": "必填 - IDENTITY", "inflection": { "tableName": "屈折 - 表格名稱", - "columnName": "屈折 - 直行名稱" + "columnName": "屈折 - 欄位名稱" }, "community": { "starUs1": "在 Github 上", @@ -228,20 +228,20 @@ "bookDemo": "預訂免費 Demo", "getAnswered": "解惑您的問題", "joinDiscord": "加入 Discord", - "joinCommunity": "Join NocoDB Community", + "joinCommunity": "加入 NocoDB 社群", "joinReddit": "加入 /r/NocoDB", "followNocodb": "追蹤 NocoDB" }, "docReference": "文件參考文獻", - "selectUserRole": "選擇用戶角色", - "childTable": "兒童表", - "childColumn": "兒童專欄", + "selectUserRole": "選擇使用者角色", + "childTable": "子表格", + "childColumn": "子欄", "onUpdate": "更新", "onDelete": "在刪除" }, "activity": { "createProject": "建立專案", - "importProject": "進口項目", + "importProject": "匯入專案", "searchProject": "搜尋專案", "editProject": "編輯專案", "stopProject": "停止專案", @@ -255,7 +255,7 @@ "excel": "從 Excel 建立專案", "template": "從模板建立專案" }, - "OkSaveProject": "好的和保存項目", + "OkSaveProject": "確認並儲存專案", "upgrade": { "available": "升級可用", "releaseNote": "發行說明", @@ -263,9 +263,9 @@ }, "translate": "幫助翻譯", "account": { - "authToken": "複製auth令牌", - "swagger": "Swagger Apis Doc.", - "projInfo": "複製項目信息", + "authToken": "複製驗證權杖", + "swagger": "Swagger Api 說明文件", + "projInfo": "複製專案資訊", "themes": "主題" }, "sort": "種類", @@ -275,20 +275,20 @@ "share": "分享", "shareBase": { "disable": "禁用共享基礎", - "enable": "任何有鏈接的人", + "enable": "任何有連結的人", "link": "共享基本鏈接" }, "invite": "邀請", "inviteMore": "邀請更多", "inviteTeam": "邀請團隊", - "inviteToken": "邀請令牌", - "newUser": "新用戶", - "editUser": "編輯用戶", - "deleteUser": "從項目中刪除用戶", + "inviteToken": "邀請權杖", + "newUser": "新使用者", + "editUser": "編輯使用者", + "deleteUser": "從專案中刪除使用者", "resendInvite": "重新發送邀請電子郵件", - "copyInviteURL": "複製邀請URL.", + "copyInviteURL": "複製邀請連結", "newRole": "新角色", - "reloadRoles": "重新加載角色", + "reloadRoles": "重新載入角色", "nextPage": "下一頁", "prevPage": "上一頁", "nextRecord": "下一步記錄", @@ -300,14 +300,14 @@ "deleteTable": "表刪除", "addField": "將新字段添加到此表", "setPrimary": "設置為主要值", - "addRow": "添加新行", - "saveRow": "保存行", + "addRow": "新增行", + "saveRow": "儲存行", "insertRow": "插入新行", "deleteRow": "刪除行", "deleteSelectedRow": "刪除所選行", - "importExcel": "導入Excel.", - "downloadCSV": "下載為CSV.", - "uploadCSV": "上傳CSV.", + "importExcel": "匯入 Excel", + "downloadCSV": "下載為 CSV", + "uploadCSV": "上傳 CSV", "import": "匯入", "importMetadata": "匯入中繼資料", "exportMetadata": "匯出中繼資料", @@ -327,12 +327,12 @@ "createKanban": "創建尋呼視圖", "createForm": "創建表單視圖", "showSystemFields": "顯示系統字段", - "copyUrl": "複製URL.", - "openTab": "打開新標籤", - "iFrame": "複製嵌入式HTML代碼", - "addWebhook": "添加新的webhook.", - "newToken": "添加新令牌", - "exportZip": "輸出 ZIP", + "copyUrl": "複製網址", + "openTab": "開啟新分頁", + "iFrame": "複製嵌入式 HTML 程式碼", + "addWebhook": "新增 webhook", + "newToken": "新增權杖", + "exportZip": "匯出 ZIP", "importZip": "匯入 ZIP", "metaSync": "立即同步", "settings": "設定", @@ -345,23 +345,23 @@ "sendEmail": "傳送電子郵件" }, "tooltip": { - "saveChanges": "保存更改", + "saveChanges": "儲存更動", "xcDB": "建立新專案", "extDB": "支援 MySQL、PostgreSQL、SQL Server 和 SQLite", "apiRest": "可透過 REST API 存取", "apiGQL": "可透過 GraphQL API 存取", "theme": { "dark": "它確實有黑色(^⇧b)", - "light": "它是黑色嗎? (^⇧b)" + "light": "它是黑色嗎?(^⇧b)" }, "addTable": "添加新表", "inviteMore": "邀請更多用戶", "toggleNavDraw": "切換導航抽屜", - "reloadApiToken": "重新加載API令牌", - "generateNewApiToken": "生成新的API令牌", + "reloadApiToken": "重新載入 API 權杖", + "generateNewApiToken": "產生新 API 權杖", "addRole": "添加新角色", "reloadList": "重新加載列表", - "metaSync": "同步元數據", + "metaSync": "同步中繼資料", "sqlMigration": "重新加載遷移", "updateRestart": "更新並重新啟動", "cancelReturn": "取消並返回", @@ -387,28 +387,28 @@ "searchApps": "搜索應用程序", "searchModels": "搜索模型", "noItemsFound": "未找到任何項目", - "defaultValue": "默認值", + "defaultValue": "預設值", "filterByEmail": "通過電子郵件過濾" }, "msg": { "info": { "footerInfo": "每頁行駛", - "upload": "選擇文件以上傳", - "upload_sub": "或拖放文件", + "upload": "選擇檔案以上傳", + "upload_sub": "或拖放檔案", "excelSupport": "支持:.xls,.xlsx,.xlsm,.ods,.ots", - "excelURL": "輸入Excel文件URL", + "excelURL": "輸入 Excel 檔案 URL", "footMsg": "要解析為推斷數據類型的行數", "excelImport": "板材可用於進口", - "exportMetadata": "您想從元表導出元數據嗎?", - "importMetadata": "您想從元表導入元數據嗎?", - "clearMetadata": "你想清除元表中的元數據嗎?", + "exportMetadata": "您想從中繼表格中匯出中繼資料嗎?", + "importMetadata": "您想從中繼表格中匯入中繼資料嗎?", + "clearMetadata": "你想清除中繼表格中的中繼資料嗎?", "projectEmptyMessage": "從建立新專案開始", - "stopProject": "你想停止這個項目嗎?", - "startProject": "你想啟動這個項目嗎?", - "restartProject": "你想重新啟動項目嗎?", - "deleteProject": "你想刪除這個項目嗎?", - "shareBasePrivate": "產生公開可享的Readonly Base", - "shareBasePublic": "互聯網上的任何人都可以查看", + "stopProject": "你想停止這個專案嗎?", + "startProject": "你想啟動這個專案嗎?", + "restartProject": "你想重新啟動專案嗎?", + "deleteProject": "你想刪除這個專案嗎?", + "shareBasePrivate": "產生公開可享的 Readonly Base", + "shareBasePublic": "網路上的任何人都可以查看", "userInviteNoSMTP": "看起來你還沒有配置郵件!請複制上面的邀請鏈接並將其發送給", "dragDropHide": "在此處拖放字段以隱藏", "formInput": "輸入表單輸入標籤", @@ -422,7 +422,7 @@ "afterFormSubmitted": "表格提交後", "apiOptions": "存取專案方式", "submitAnotherForm": "顯示“提交另一個表格”按鈕", - "showBlankForm": "5秒後顯示空白表格", + "showBlankForm": "5 秒後顯示空白表格", "emailForm": "發電子郵件給我", "showSysFields": "顯示系統字段", "filterAutoApply": "自動申請", @@ -437,7 +437,7 @@ "editorDesc": "可以編輯記錄但無法更改數據庫/字段的結構。", "commenterDesc": "可以查看和評論記錄,但無法編輯任何內容", "viewerDesc": "可以查看記錄但無法編輯任何內容", - "addUser": "添加新用戶", + "addUser": "新增使用者", "staticRoleInfo": "無法編輯系統定義的角色", "exportZip": "將專案中繼資料匯出為 ZIP 檔案並下載。", "importZip": "匯入專案中繼資料 ZIP 檔案並重新啟動。", @@ -456,7 +456,7 @@ }, "loginMsg": "登入 NocoDB", "passwordRecovery": { - "message_1": "請填入您註冊時使用的電子信箱位址。", + "message_1": "請填入您註冊時使用的電子信箱地址。", "message_2": "我們將傳給您一封電子郵件,其中包含重設密碼的連結。", "success": "請確認您的電子郵件以重設密碼" }, @@ -487,7 +487,7 @@ "invalidDbCredentials": "資料庫憑證無效。", "unableToConnectToDb": "無法連線至資料庫。請檢查您的資料庫是否已經上線。", "userDoesntHaveSufficientPermission": "使用者不存在,或者是無權建立結構。", - "dbConnectionStatus": "數據庫參數無效", + "dbConnectionStatus": "資料庫參數無效", "dbConnectionFailed": "連線失敗:", "signUpRules": { "emailReqd": "電子信箱地址為必填", @@ -497,18 +497,18 @@ } }, "toast": { - "exportMetadata": "項目元數據成功導出", - "importMetadata": "項目元數據成功導入", - "clearMetadata": "項目元數據已成功清除", - "stopProject": "項目成功停止了", - "startProject": "項目成功開始", - "restartProject": "項目成功重新啟動", - "deleteProject": "項目已成功刪除", - "authToken": "驗證令牌複製到剪貼板", - "projInfo": "將項目信息複製到剪貼板", - "inviteUrlCopy": "複製邀請URL到剪貼板", - "createView": "查看成功創建", - "formEmailSMTP": "請激活App Store中的SMTP插件以啟用電子郵件通知", + "exportMetadata": "專案中繼資料已成功匯出", + "importMetadata": "專案中繼資料已成功匯入", + "clearMetadata": "專案中繼資料已成功清除", + "stopProject": "專案成功停止", + "startProject": "專案成功啟動", + "restartProject": "專案成功重新啟動", + "deleteProject": "專案已成功刪除", + "authToken": "驗證權杖已複製到剪貼簿", + "projInfo": "已將專案資訊複製到剪貼簿", + "inviteUrlCopy": "已將邀請連結複製到剪貼簿", + "createView": "成功建立檢視表", + "formEmailSMTP": "請啟用 App Store 中的 SMTP 外掛程式以啟用電子郵件通知", "collabView": "成功轉換為協作視圖", "lockedView": "成功轉換為鎖定視圖", "futureRelease": "即將推出!" From ca4ca96bc99e25d529254c6b34b1fa49ad9067d2 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Mon, 16 May 2022 12:28:53 +0800 Subject: [PATCH 48/48] fix: typo table_nameme -> table_name --- packages/nocodb-sdk/src/lib/Api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb-sdk/src/lib/Api.ts b/packages/nocodb-sdk/src/lib/Api.ts index 4361875a00..dcb115ca87 100644 --- a/packages/nocodb-sdk/src/lib/Api.ts +++ b/packages/nocodb-sdk/src/lib/Api.ts @@ -134,7 +134,7 @@ export interface TableInfoType { fk_project_id?: string; fk_base_id?: string; title: string; - table_nameme: string; + table_name: string; type?: string; enabled?: string; parent_id?: string;