From 70933122f22c75915be96a64a5e331d8e9b51946 Mon Sep 17 00:00:00 2001 From: Naveen MR Date: Sat, 23 Apr 2022 08:55:11 +0100 Subject: [PATCH 01/39] fix: Title of API docs Signed-off-by: Naveen MR --- packages/nocodb/src/lib/noco/rest/ui/auth/swagger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/noco/rest/ui/auth/swagger.ts b/packages/nocodb/src/lib/noco/rest/ui/auth/swagger.ts index aa3aeccbd4..ddfefd6893 100644 --- a/packages/nocodb/src/lib/noco/rest/ui/auth/swagger.ts +++ b/packages/nocodb/src/lib/noco/rest/ui/auth/swagger.ts @@ -1,7 +1,7 @@ export default ` - XC Swagger UI + API Docs From a3022795cbc1a09fc862de63b9dc0b34ef470062 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sun, 24 Apr 2022 17:07:16 +0800 Subject: [PATCH 02/39] chore: revise bug report template Signed-off-by: Wing-Kam Wong --- .github/ISSUE_TEMPLATE/bug_report.md | 36 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3a82761892..32c339ce66 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,11 +9,22 @@ assignees: '' **Please enter the following details** -Copy and paste project info : [Youtube Video](https://www.youtube.com/watch?v=AUSNN-RCwhE) - -or - -please provide the following details : +Copy and Paste Project Info - Tutorials: How to check my Project info? ([YouTube Tutorial](https://www.youtube.com/watch?v=AUSNN-RCwhE) or [Documentation](https://docs.nocodb.com/FAQs#how-to-check-my-project-info-)) + +``` +Node: **v16.14.0** +Arch: **arm64** +Platform: **darwin** +Docker: **false** +Database: **mysql2** +ProjectOnRootDB: **false** +RootDB: **mysql2** +PackageVersion: **0.90.5** +``` + +or provide the following info + +``` NocoDB used as docker : true / false NocoDB version : Database used in NC_DB URL : mysql | pg | mssql | sqlite3 / (defaults to sqlite3 if empty) @@ -22,23 +33,20 @@ Database on which spreadsheet is created : mysql | pg | mssql | sqlite3 / (defau OS on which NocoDB is running : Node.js version if running as node : Database version : +``` **Steps To Reproduce** + 1. Go to '...' 2. Click on '....' 3. See error -**Expected behavior** +**Expected Behavior** + A clear and concise description of what you expected to happen. **Screenshots** -If applicable, add screenshots to help explain your problem. -Join our discord : https://discord.gg/5RgZmkW for realtime help. +If applicable, add screenshots to help explain your problem. -Node version : **v12.22.1** -Arch type: **x64** -Platform: **linux** -Docker: **true** -Database: **sqlite3** -packageVersion: **0.9.27** +Join our discord : https://discord.gg/5RgZmkW for realtime help. \ No newline at end of file From c6d48a9077cf7f6a7e11030e0c20981823b34b89 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Sun, 24 Apr 2022 17:07:32 +0800 Subject: [PATCH 03/39] docs: update screenshots in FAQs Signed-off-by: Wing-Kam Wong --- packages/noco-docs/content/en/FAQs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/noco-docs/content/en/FAQs.md b/packages/noco-docs/content/en/FAQs.md index d92215dab4..88480d20a8 100644 --- a/packages/noco-docs/content/en/FAQs.md +++ b/packages/noco-docs/content/en/FAQs.md @@ -23,13 +23,13 @@ menuTitle: 'FAQs' - You can hover the NocoDB icon on the top left corner or check ``PackageVersion`` in Project info. -![image](https://user-images.githubusercontent.com/35857179/161957765-922058dc-dba1-44c5-95f4-2924c875e1c6.png) +![image](https://user-images.githubusercontent.com/35857179/164968969-da53adda-97fc-4a79-9331-039ddef75a13.png) ## How to check my Project info ? - You can click on top right icon and click ``Copy Project Info``. -![image](https://user-images.githubusercontent.com/35857179/161957820-e0ac8b04-aafd-40c3-8fa8-2fdaa7dc157f.png) +![image](https://user-images.githubusercontent.com/35857179/164968940-6c987863-e7d8-4b44-a46d-2f755825af0a.png) You should see the similar result as below. From c59da67f6719d7b07fd5db3e28d104c5595a2ff1 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Mon, 25 Apr 2022 11:17:15 +0530 Subject: [PATCH 04/39] feat: accept both project id or title in data apis Signed-off-by: Pranav C --- .../nocodb/src/lib/noco-models/Project.ts | 49 +++++++++++++++++++ .../src/lib/noco/meta/api/dataApis/helpers.ts | 6 +-- .../extractProjectIdAndAuthenticate.ts | 2 +- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/packages/nocodb/src/lib/noco-models/Project.ts b/packages/nocodb/src/lib/noco-models/Project.ts index 59599f3d9b..33fa34ede0 100644 --- a/packages/nocodb/src/lib/noco-models/Project.ts +++ b/packages/nocodb/src/lib/noco-models/Project.ts @@ -323,4 +323,53 @@ export default class Project implements ProjectType { } return projectData?.id && this.get(projectData?.id, ncMeta); } + + static async getByTitleOrId(titleOrId: string, ncMeta = Noco.ncMeta) { + const projectId = + titleOrId && + (await NocoCache.get( + `${CacheScope.PROJECT}:${titleOrId}`, + CacheGetType.TYPE_OBJECT + )); + let projectData = null; + if (!projectId) { + projectData = await Noco.ncMeta.metaGet2( + null, + null, + MetaTable.PROJECT, + { + deleted: false + }, + null, + { + _or: [ + { + id: { + eq: titleOrId + } + }, + { + title: { + eq: titleOrId + } + } + ] + } + ); + await NocoCache.set( + `${CacheScope.PROJECT}:${titleOrId}`, + projectData?.id + ); + } else { + return this.get(projectId); + } + return projectData?.id && this.get(projectData?.id, ncMeta); + } + + static async getWithInfoByTitleOrId(titleOrId: string, ncMeta = Noco.ncMeta) { + const project = await this.getByTitleOrId(titleOrId, ncMeta); + if (project) await project.getBases(ncMeta); + + return project; + } } diff --git a/packages/nocodb/src/lib/noco/meta/api/dataApis/helpers.ts b/packages/nocodb/src/lib/noco/meta/api/dataApis/helpers.ts index 75f689952e..56c7224a40 100644 --- a/packages/nocodb/src/lib/noco/meta/api/dataApis/helpers.ts +++ b/packages/nocodb/src/lib/noco/meta/api/dataApis/helpers.ts @@ -18,11 +18,7 @@ export async function getViewAndModelFromRequestByAliasOrId( | Request<{ projectName: string; tableName: string; viewName?: string }> | Request ) { - let project = await Project.getWithInfoByTitle(req.params.projectName); - - if (!project) { - project = await Project.getWithInfo(req.params.projectName); - } + const project = await Project.getWithInfoByTitleOrId(req.params.projectName); const model = await Model.getByAliasOrId({ project_id: project.id, diff --git a/packages/nocodb/src/lib/noco/meta/helpers/extractProjectIdAndAuthenticate.ts b/packages/nocodb/src/lib/noco/meta/helpers/extractProjectIdAndAuthenticate.ts index b30e33bb83..9fcad108da 100644 --- a/packages/nocodb/src/lib/noco/meta/helpers/extractProjectIdAndAuthenticate.ts +++ b/packages/nocodb/src/lib/noco/meta/helpers/extractProjectIdAndAuthenticate.ts @@ -18,7 +18,7 @@ export default async (req, res, next) => { // extract project id based on request path params if (params.projectName) { - const project = await Project.getByTitle(params.projectName); + const project = await Project.getByTitleOrId(params.projectName); req.ncProjectId = project.id; res.locals.project = project; } From 0a7e2e9608030c12edc500b4784dbc0d8204c219 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Mon, 25 Apr 2022 15:35:48 +0800 Subject: [PATCH 05/39] fix: use :ref: instead Signed-off-by: Wing-Kam Wong --- .../nocodb/src/lib/noco-models/Project.ts | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/nocodb/src/lib/noco-models/Project.ts b/packages/nocodb/src/lib/noco-models/Project.ts index 33fa34ede0..25d8485e43 100644 --- a/packages/nocodb/src/lib/noco-models/Project.ts +++ b/packages/nocodb/src/lib/noco-models/Project.ts @@ -179,13 +179,16 @@ export default class Project implements ProjectType { // get existing cache const key = `${CacheScope.PROJECT}:${projectId}`; const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); - if (o?.uuid) { - await NocoCache.del(`${CacheScope.PROJECT}:${o.uuid}`); - } - if (o) await NocoCache.del(`${CacheScope.PROJECT}:${projectId}`); - - if (o?.title) { + if (o) { + // delete : + await NocoCache.del(`${CacheScope.PROJECT}:${projectId}`); + // delete : await NocoCache.del(`${CacheScope.PROJECT}:${o.title}`); + // delete <scope>:<uuid> + await NocoCache.del(`${CacheScope.PROJECT}:${o.uuid}`); + // delete <scope>:ref:<titleOfId> + await NocoCache.del(`${CacheScope.PROJECT}:ref:${o.title}`); + await NocoCache.del(`${CacheScope.PROJECT}:ref:${o.id}`); } // remove item in cache list @@ -264,12 +267,17 @@ export default class Project implements ProjectType { await base.delete(ncMeta); } const project = await this.get(projectId); - if (project.uuid) { + + if (project) { + // delete <scope>:<uuid> await NocoCache.del(`${CacheScope.PROJECT}:${project.uuid}`); - } - if (project.title) { + // delete <scope>:<title> await NocoCache.del(`${CacheScope.PROJECT}:${project.title}`); + // delete <scope>:ref:<titleOfId> + await NocoCache.del(`${CacheScope.PROJECT}:ref:${project.title}`); + await NocoCache.del(`${CacheScope.PROJECT}:ref:${project.id}`); } + await NocoCache.deepDel( CacheScope.PROJECT, `${CacheScope.PROJECT}:${projectId}`, @@ -328,7 +336,7 @@ export default class Project implements ProjectType { const projectId = titleOrId && (await NocoCache.get( - `${CacheScope.PROJECT}:${titleOrId}`, + `${CacheScope.PROJECT}:ref:${titleOrId}`, CacheGetType.TYPE_OBJECT )); let projectData = null; @@ -357,7 +365,7 @@ export default class Project implements ProjectType { } ); await NocoCache.set( - `${CacheScope.PROJECT}:${titleOrId}`, + `${CacheScope.PROJECT}:ref:${titleOrId}`, projectData?.id ); } else { From e5e952aec60abc70342e0fb1bce7b563b4d18e20 Mon Sep 17 00:00:00 2001 From: Pranav C <pranavxc@gmail.com> Date: Mon, 25 Apr 2022 14:50:09 +0530 Subject: [PATCH 06/39] fix: verify model, view and project exist while migrating ui acl re #1847 Signed-off-by: Pranav C <pranavxc@gmail.com> --- .../jobs/ncProjectUpgraderV2_0090000.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts b/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts index 11b87feb59..21df164474 100644 --- a/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts +++ b/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts @@ -1070,17 +1070,26 @@ async function migrateUIAcl(ctx: MigrateCtxV1, ncMeta: any) { }> = await ncMeta.metaList(null, null, 'nc_disabled_models_for_role'); for (const acl of uiAclList) { + // if missing model name skip the view acl migration + if (!acl.title) continue; + let fk_view_id; if (acl.type === 'vtable') { + // if missing parent model name skip the view acl migration + if (!acl.parent_model_title) continue; fk_view_id = - ctx.objViewRef[acl.project_id][acl.parent_model_title][acl.title].id; + ctx.objViewRef[acl.project_id]?.[acl.parent_model_title]?.[acl.title] + ?.id; } else { fk_view_id = - ctx.objViewRef[acl.project_id][acl.title][ - ctx.objModelRef[acl.project_id][acl.title].title - ].id || ctx.objViewRef[acl.project_id][acl.title][acl.title].id; + ctx.objViewRef?.[acl.project_id]?.[acl.title]?.[ + ctx.objModelRef?.[acl.project_id]?.[acl.title]?.title + ].id || ctx.objViewRef[acl.project_id]?.[acl.title]?.[acl.title]?.id; } + // if view id missing skip ui acl view migration + if (!fk_view_id) continue; + await ModelRoleVisibility.insert( { role: acl.role, From 8358666c9eaa2b10eaa12cb8184835fb9bc7b850 Mon Sep 17 00:00:00 2001 From: Pranav C <pranavxc@gmail.com> Date: Mon, 25 Apr 2022 15:56:09 +0530 Subject: [PATCH 07/39] fix: extract using alias reference if table_name reference is not found Signed-off-by: Pranav C <pranavxc@gmail.com> --- .../jobs/ncProjectUpgraderV2_0090000.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts b/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts index 21df164474..c0ef59e8ed 100644 --- a/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts +++ b/packages/nocodb/src/lib/noco/upgrader/jobs/ncProjectUpgraderV2_0090000.ts @@ -1078,8 +1078,12 @@ async function migrateUIAcl(ctx: MigrateCtxV1, ncMeta: any) { // if missing parent model name skip the view acl migration if (!acl.parent_model_title) continue; fk_view_id = - ctx.objViewRef[acl.project_id]?.[acl.parent_model_title]?.[acl.title] - ?.id; + ctx.objViewRef[acl.project_id]?.[ + ( + ctx.objModelRef?.[acl.project_id]?.[acl.parent_model_title] || + ctx.objModelAliasRef?.[acl.project_id]?.[acl.parent_model_title] + )?.table_name + ]?.[acl.title]?.id; } else { fk_view_id = ctx.objViewRef?.[acl.project_id]?.[acl.title]?.[ @@ -1121,9 +1125,14 @@ async function migrateSharedViews(ctx: MigrateCtxV1, ncMeta: any) { if (sharedView.view_type !== 'table' && sharedView.view_type !== 'view') { fk_view_id = - ctx.objViewRef[sharedView.project_id]?.[sharedView.model_name]?.[ - sharedView.view_name - ]?.id; + ctx.objViewRef[sharedView.project_id]?.[ + ( + ctx.objModelRef?.[sharedView.project_id]?.[sharedView.model_name] || + ctx.objModelAliasRef?.[sharedView.project_id]?.[ + sharedView.model_name + ] + )?.title + ]?.[sharedView.view_name]?.id; } else { fk_view_id = ctx.objViewRef[sharedView.project_id]?.[sharedView.model_name]?.[ From 0d194ca76ec43f675972b263b3efd7ff9cc26006 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong <wingkwong.code@gmail.com> Date: Mon, 25 Apr 2022 19:18:01 +0800 Subject: [PATCH 08/39] refactor: automate PR from develop to master Signed-off-by: Wing-Kam Wong <wingkwong.code@gmail.com> --- .github/workflows/pr-to-master.yml | 62 +++++++++++++++++++++++ .github/workflows/release-nocodb.yml | 75 +++++++++++++++++++++++----- .github/workflows/sync-to-master.yml | 23 +++++++++ 3 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/pr-to-master.yml create mode 100644 .github/workflows/sync-to-master.yml diff --git a/.github/workflows/pr-to-master.yml b/.github/workflows/pr-to-master.yml new file mode 100644 index 0000000000..5519b34951 --- /dev/null +++ b/.github/workflows/pr-to-master.yml @@ -0,0 +1,62 @@ +name: 'PR to master branch from develop' + +on: + # Triggered manually + workflow_dispatch: + inputs: + tag: + description: "Tag" + required: true + targetEnv: + description: "Target Environment" + required: true + type: choice + options: + - DEV + - PROD + # Triggered by release-nocodb.yml + workflow_call: + inputs: + tag: + description: "Tag" + required: true + type: string + targetEnv: + description: "Target Environment" + required: true + type: string + +jobs: + pr-to-master: + runs-on: ubuntu-latest + steps: + - run: | + echo 'triggering pr-to-master' + - name: Checkout + uses: actions/checkout@v2 + with: + ref: develop + + - name: Create Pull Request + if: ${{ github.event.inputs.targetEnv == 'PROD' || inputs.targetEnv == 'PROD' }} + id: cpr + uses: repo-sync/pull-request@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + source_branch: "develop" + destination_branch: "master" + pr_title: '${{ github.event.inputs.tag || inputs.tag }} Pre-release' + pr_label: 'Bot: Automated PR,Bot: Automerge' + - name: Check outputs + if: ${{ github.event.inputs.targetEnv == 'PROD' || inputs.targetEnv == 'PROD' }} + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pr_number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pr_url }}" + - name: automerge + if: ${{ github.event.inputs.targetEnv == 'PROD' || inputs.targetEnv == 'PROD' }} + uses: "pascalgn/automerge-action@v0.14.3" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + PULL_REQUEST: "${{ steps.cpr.outputs.pr_number }}" + MERGE_LABELS: "Bot: Automerge" \ No newline at end of file diff --git a/.github/workflows/release-nocodb.yml b/.github/workflows/release-nocodb.yml index fa25dc65bb..927caaf8d9 100644 --- a/.github/workflows/release-nocodb.yml +++ b/.github/workflows/release-nocodb.yml @@ -6,48 +6,99 @@ on: inputs: tag: description: "Target Tag" - required: true + required: false prev_tag: description: "Previous Tag" - required: true + required: false jobs: + # Validate Branch + validate-branch: + runs-on: ubuntu-latest + steps: + - run: | + if [[ ${{ github.ref }} != 'refs/heads/master' ]]; then + echo "NocoDB Release is only allowed to run on master branch" + exit 1 + fi + + # Process Input + process-input: + runs-on: ubuntu-latest + needs: validate-branch + outputs: + target_tag: ${{ steps.process-input.outputs.target_tag }} + prev_tag: ${{ steps.process-input.outputs.prev_tag }} + steps: + - id: process-input + name: process-input + run: | + TARGET_TAG=${{github.event.inputs.tag}} + PREV_TAG=${{github.event.inputs.prev_tag}} + + if [[ ${PREV_TAG} == '' ]]; then + # fetch the latest version + PREV_TAG=$(basename $(curl -fs -o/dev/null -w %{redirect_url} https://github.com/nocodb/nocodb/releases/latest)) + fi + + if [[ ${TARGET_TAG} == '' ]]; then + # bump the version from PREV_TAG + TARGET_TAG=$(echo ${PREV_TAG} | awk -F. -v OFS=. '{$NF += 1 ; print}') + fi + + echo target version: ${TARGET_TAG} + echo previous version: ${PREV_TAG} + echo "::set-output name=target_tag::${TARGET_TAG}" + echo "::set-output name=prev_tag::${PREV_TAG}" + - name: Verify + run : | + echo ${{ steps.process-input.outputs.target_tag }} + + # Merge develop to master + pr-to-master: + needs: process-input + uses: ./.github/workflows/pr-to-master.yml + with: + tag: ${{ needs.process-input.outputs.target_tag }} + targetEnv: ${{ github.event.inputs.targetEnv || 'PROD' }} + # Close all issues with target tags 'Fixed' & 'Resolved' close-fixed-issues: + needs: [pr-to-master, process-input] uses: ./.github/workflows/release-close-issue.yml with: issue_label: 'Status: Fixed' - version: ${{ github.event.inputs.tag }} + version: ${{ needs.process-input.outputs.target_tag }} close-resolved-issues: - needs: close-fixed-issues + needs: [close-fixed-issues, process-input] uses: ./.github/workflows/release-close-issue.yml with: issue_label: 'Status: Resolved' - version: ${{ github.event.inputs.tag }} + version: ${{ needs.process-input.outputs.target_tag }} # Build, install, publish frontend and backend to npm release-npm: - needs: close-resolved-issues + needs: [close-resolved-issues, process-input] uses: ./.github/workflows/release-npm.yml with: - tag: ${{ github.event.inputs.tag }} + tag: ${{ needs.process-input.outputs.target_tag }} targetEnv: ${{ github.event.inputs.targetEnv || 'PROD' }} secrets: NPM_TOKEN: "${{ secrets.NPM_TOKEN }}" # Draft Release Note release-draft-note: - needs: release-npm + needs: [release-npm, process-input] uses: ./.github/workflows/release-draft.yml with: - tag: ${{ github.event.inputs.tag }} - prev_tag: ${{ github.event.inputs.prev_tag }} + tag: ${{ needs.process-input.outputs.target_tag }} + prev_tag: ${{ needs.process-input.outputs.prev_tag }} # Build docker image and push to docker hub release-docker: - needs: release-draft-note + needs: [release-draft-note, process-input] uses: ./.github/workflows/release-docker.yml with: - tag: ${{ github.event.inputs.tag }} + tag: ${{ needs.process-input.outputs.target_tag }} targetEnv: ${{ github.event.inputs.targetEnv || 'PROD' }} secrets: DOCKERHUB_USERNAME: "${{ secrets.DOCKERHUB_USERNAME }}" diff --git a/.github/workflows/sync-to-master.yml b/.github/workflows/sync-to-master.yml new file mode 100644 index 0000000000..f6b730eac1 --- /dev/null +++ b/.github/workflows/sync-to-master.yml @@ -0,0 +1,23 @@ +name: 'Sync changes to master branch from develop' + +on: + # Triggered manually + workflow_dispatch: + # Triggered by release-nocodb.yml + workflow_call: +jobs: + sync-to-master: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Merge from develop to master + uses: wingkwong/gh-action-nightly-merge@master + with: + stable_branch: 'develop' + development_branch: 'master' + allow_ff: true + allow_forks: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 5c104cdb2d19cf376c2f4bfebf722b0d6c6110ce Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong <wingkwong.code@gmail.com> Date: Mon, 25 Apr 2022 19:18:30 +0800 Subject: [PATCH 09/39] chore: rm sync-to-master.yml Signed-off-by: Wing-Kam Wong <wingkwong.code@gmail.com> --- .github/workflows/sync-to-master.yml | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 .github/workflows/sync-to-master.yml diff --git a/.github/workflows/sync-to-master.yml b/.github/workflows/sync-to-master.yml deleted file mode 100644 index f6b730eac1..0000000000 --- a/.github/workflows/sync-to-master.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: 'Sync changes to master branch from develop' - -on: - # Triggered manually - workflow_dispatch: - # Triggered by release-nocodb.yml - workflow_call: -jobs: - sync-to-master: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v1 - - - name: Merge from develop to master - uses: wingkwong/gh-action-nightly-merge@master - with: - stable_branch: 'develop' - development_branch: 'master' - allow_ff: true - allow_forks: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 08acd2ff78fe867d9e582c285dc94248dbc66c3c Mon Sep 17 00:00:00 2001 From: Pranav C <pranavxc@gmail.com> Date: Mon, 25 Apr 2022 17:22:34 +0530 Subject: [PATCH 10/39] fix: execute queries sequentially in case mssql to avoid transaction/timeout issue (#1860) re #1790 Signed-off-by: Pranav C <pranavxc@gmail.com> --- packages/nocodb/src/lib/utils/NcHelp.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/utils/NcHelp.ts b/packages/nocodb/src/lib/utils/NcHelp.ts index cfe5d5848a..7fbfe392ff 100644 --- a/packages/nocodb/src/lib/utils/NcHelp.ts +++ b/packages/nocodb/src/lib/utils/NcHelp.ts @@ -5,7 +5,7 @@ export default class NcHelp { fns: Array<() => Promise<any>>, dbType: string ): Promise<any> { - if (dbType === 'oracledb') { + if (dbType === 'oracledb' || dbType === 'mssql') { for (const fn of fns) { await fn(); } From 6f11dafbea6244387541a3f689bd794ffca12eb6 Mon Sep 17 00:00:00 2001 From: Pranav C <pranavxc@gmail.com> Date: Mon, 25 Apr 2022 20:34:56 +0530 Subject: [PATCH 11/39] feat: show schema name option for mssql and pg Signed-off-by: Pranav C <pranavxc@gmail.com> --- .../nc-gui/components/createOrEditProject.vue | 1256 +++++++++-------- packages/nc-gui/lang/en.json | 1 + 2 files changed, 647 insertions(+), 610 deletions(-) diff --git a/packages/nc-gui/components/createOrEditProject.vue b/packages/nc-gui/components/createOrEditProject.vue index fd597d48b0..545f12c37f 100644 --- a/packages/nc-gui/components/createOrEditProject.vue +++ b/packages/nc-gui/components/createOrEditProject.vue @@ -207,7 +207,9 @@ v-for="(db, dbIndex) in project.envs[envKey].db" :key="dbIndex" > - <v-icon small> mdi-database </v-icon>   + <v-icon small> + mdi-database + </v-icon>   <span class="text-capitalize caption">{{ db.connection.database }}</span> @@ -248,15 +250,13 @@ <span class="ml-2 caption grey--text" - >Refer knex documentation + >Refer knex documentation <a href="https://knexjs.org/#Installation-client" target="_blank" class="grey--text" - >here</a - > - .</span - > + >here</a> + .</span> <monaco-json-object-editor v-model=" @@ -298,7 +298,7 @@ Object.keys( databaseNames ).indexOf(item) % - colors.length + colors.length ] " class="" @@ -317,7 +317,7 @@ Object.keys( databaseNames ).indexOf(data.item) % - colors.length + colors.length ] " class="caption" @@ -453,9 +453,26 @@ " /> </v-col> + <!-- todo : Schema name --> + <v-col + v-if="db.client === 'mssql' || db.client === 'pg'" + cols="4" + class="py-0" + > + <v-text-field + v-model="schema" + :disabled="edit && enableDbEdit < 2" + class="body-2 database-field" + :rules="form.requiredRule" + :label=" + $t('labels.schemaName') + " + /> + </v-col> <!-- todo : ssl & inflection --> <v-col v-if="db.client !== 'sqlite3'" + cols="12" class="" > <v-expansion-panels> @@ -466,12 +483,11 @@ <!-- SSL & Advanced parameters --> <span class="grey--text caption" - >{{ - $t( - "title.advancedParameters" - ) - }}</span - > + >{{ + $t( + "title.advancedParameters" + ) + }}</span> </v-expansion-panel-header> <v-expansion-panel-content> <v-card class="elevation-0"> @@ -505,7 +521,7 @@ dbIndex ) " - /> + > <!-- Select .cert file --> <x-btn v-ge="[ @@ -545,7 +561,7 @@ dbIndex ) " - /> + > <x-btn v-ge="[ 'project', @@ -584,7 +600,7 @@ dbIndex ) " - /> + > <x-btn v-ge="[ 'project', @@ -626,11 +642,11 @@ " :items=" project.projectType === - 'rest' + 'rest' ? [ - 'camelize', - 'none', - ] + 'camelize', + 'none', + ] : ['camelize'] " > @@ -639,8 +655,7 @@ > <span class="caption" - >{{ item }}</span - > + >{{ item }}</span> </template> </v-select> </v-col> @@ -660,11 +675,11 @@ " :items=" project.projectType === - 'rest' + 'rest' ? [ - 'camelize', - 'none', - ] + 'camelize', + 'none', + ] : ['camelize'] " > @@ -673,8 +688,7 @@ > <span class="caption" - >{{ item }}</span - > + >{{ item }}</span> </template> </v-select> </v-col> @@ -839,30 +853,30 @@ </v-container> </template> <script> -import JSON5 from "json5"; +import JSON5 from 'json5' -import { mapGetters, mapActions } from "vuex"; -import Vue from "vue"; +import { mapGetters, mapActions } from 'vuex' +import Vue from 'vue' -import { v4 as uuidv4 } from "uuid"; +import { v4 as uuidv4 } from 'uuid' -import XBtn from "./global/xBtn"; -import dlgOk from "./utils/dlgOk.vue"; -import textDlgSubmitCancel from "./utils/dlgTextSubmitCancel"; -import MonacoJsonObjectEditor from "@/components/monaco/MonacoJsonObjectEditor"; -import ApiOverlay from "@/components/apiOverlay"; -import colors from "@/mixins/colors"; -import DlgOkNew from "@/components/utils/dlgOkNew"; -import readFile from "@/helpers/fileReader"; +import XBtn from './global/xBtn' +import dlgOk from './utils/dlgOk.vue' +import textDlgSubmitCancel from './utils/dlgTextSubmitCancel' +import MonacoJsonObjectEditor from '@/components/monaco/MonacoJsonObjectEditor' +import ApiOverlay from '@/components/apiOverlay' +import colors from '@/mixins/colors' +import DlgOkNew from '@/components/utils/dlgOkNew' +import readFile from '@/helpers/fileReader' const { uniqueNamesGenerator, starWars, adjectives, - animals, -} = require("unique-names-generator"); + animals +} = require('unique-names-generator') -const homeDir = ""; +const homeDir = '' export default { components: { @@ -871,90 +885,91 @@ export default { MonacoJsonObjectEditor, XBtn, dlgOk, - textDlgSubmitCancel, + textDlgSubmitCancel }, mixins: [colors], - layout: "empty", + layout: 'empty', data() { return { + schema: 'public', testSuccess: false, projectCreated: false, allSchemas: false, showMonaco: [], smtpConfiguration: { - from: "", - options: "", + from: '', + options: '' }, showSecret: false, loaderMessages: [ - "Setting up new database configs", - "Inferring database schema", - "Generating APIs.", - "Generating APIs..", - "Generating APIs...", - "Generating APIs....", - "Please wait", - "Please wait.", - "Please wait..", - "Please wait...", - "Please wait..", - "Please wait.", - "Please wait", - "Please wait.", - "Please wait..", - "Please wait...", - "Please wait..", - "Please wait.", - "Please wait..", - "Please wait...", + 'Setting up new database configs', + 'Inferring database schema', + 'Generating APIs.', + 'Generating APIs..', + 'Generating APIs...', + 'Generating APIs....', + 'Please wait', + 'Please wait.', + 'Please wait..', + 'Please wait...', + 'Please wait..', + 'Please wait.', + 'Please wait', + 'Please wait.', + 'Please wait..', + 'Please wait...', + 'Please wait..', + 'Please wait.', + 'Please wait..', + 'Please wait...' ], - loaderMessage: "", + loaderMessage: '', projectReloading: false, enableDbEdit: 0, authTypes: [ { - text: "JWT", - value: "jwt", + text: 'JWT', + value: 'jwt' }, { - text: "Master Key", - value: "masterKey", + text: 'Master Key', + value: 'masterKey' }, { - text: "Middleware", - value: "middleware", + text: 'Middleware', + value: 'middleware' }, { - text: "Disabled", - value: "none", - }, + text: 'Disabled', + value: 'none' + } ], projectTypes: [ { - text: "REST APIs", - value: "rest", - icon: "mdi-code-json", - iconColor: "green", + text: 'REST APIs', + value: 'rest', + icon: 'mdi-code-json', + iconColor: 'green' }, { - text: "GRAPHQL APIs", - value: "graphql", - icon: "mdi-graphql", - iconColor: "pink", - }, + text: 'GRAPHQL APIs', + value: 'graphql', + icon: 'mdi-graphql', + iconColor: 'pink' + } ], showPass: {}, /** ************** START : form related ****************/ form: { - portValidationRule: [(v) => /^\d+$/.test(v) || "Not a valid port"], - titleRequiredRule: [(v) => !!v || "Title is required"], - requiredRule: [(v) => !!v || "Field is required"], - folderRequiredRule: [(v) => !!v || "Folder path is required"], + portValidationRule: [v => /^\d+$/.test(v) || 'Not a valid port'], + titleRequiredRule: [v => !!v || 'Title is required'], + requiredRule: [v => !!v || 'Field is required'], + folderRequiredRule: [v => !!v || 'Folder path is required'] }, valid: null, panel: 0, - client: ["Sqlite"], + client: ['Sqlite'], baseFolder: homeDir, tab: null, @@ -963,244 +978,245 @@ export default { /** ************** END : form related ****************/ auth: { authSecret: uuidv4(), - authType: "jwt", - webhook: null, + authType: 'jwt', + webhook: null }, project: {}, defaultProject: { - title: "", - version: "0.6", + title: '', + version: '0.6', folder: homeDir, envs: { _noco: { db: [ { - client: "pg", + client: 'pg', connection: { - host: "localhost", - port: "5432", - user: "postgres", - password: "password", - database: "_dev", + host: 'localhost', + port: '5432', + user: 'postgres', + password: 'password', + database: '_dev', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, + searchPath: ['public'], meta: { - tn: "nc_evolutions", - dbAlias: "db", + tn: 'nc_evolutions', + dbAlias: 'db', api: { - type: "rest", - prefix: "", - graphqlDepthLimit: 10, + type: 'rest', + prefix: '', + graphqlDepthLimit: 10 }, inflection: { - table_name: "camelize", - column_name: "camelize", - }, + table_name: 'camelize', + column_name: 'camelize' + } }, ui: { setup: -1, ssl: { - key: this.$t("labels.clientKey"), // Client Key - cert: this.$t("labels.clientCert"), // Client Cert - ca: this.$t("labels.serverCA"), // Server CA + key: this.$t('labels.clientKey'), // Client Key + cert: this.$t('labels.clientCert'), // Client Cert + ca: this.$t('labels.serverCA') // Server CA }, - sslUse: "Preferred", - }, - }, + sslUse: 'Preferred' + } + } ], apiClient: { - data: [], - }, - }, + data: [] + } + } }, - workingEnv: "_noco", + workingEnv: '_noco', ui: { envs: { - _noco: {}, - }, + _noco: {} + } }, meta: { - version: "0.6", - seedsFolder: "seeds", - queriesFolder: "queries", - apisFolder: "apis", - projectType: "rest", - type: "mvc", - language: "ts", + version: '0.6', + seedsFolder: 'seeds', + queriesFolder: 'queries', + apisFolder: 'apis', + projectType: 'rest', + type: 'mvc', + language: 'ts' }, - seedsFolder: "seeds", - queriesFolder: "queries", - apisFolder: "apis", - projectType: "rest", - type: "mvc", - language: "ts", + seedsFolder: 'seeds', + queriesFolder: 'queries', + apisFolder: 'apis', + projectType: 'rest', + type: 'mvc', + language: 'ts', apiClient: { - data: [], - }, + data: [] + } }, sampleConnectionData: { Postgres: { - host: "localhost", - port: "5432", - user: "postgres", - password: "password", - database: "_test", + host: 'localhost', + port: '5432', + user: 'postgres', + password: 'password', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, MySQL: { - host: "localhost", - port: "3306", - user: "root", - password: "password", - database: "_test", + host: 'localhost', + port: '3306', + user: 'root', + password: 'password', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, Vitess: { - host: "localhost", - port: "15306", - user: "root", - password: "password", - database: "_test", + host: 'localhost', + port: '15306', + user: 'root', + password: 'password', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, TiDB: { - host: "localhost", - port: "4000", - user: "root", - password: "", - database: "_test", + host: 'localhost', + port: '4000', + user: 'root', + password: '', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, Yugabyte: { - host: "localhost", - port: "5432", - user: "postgres", - password: "", - database: "_test", + host: 'localhost', + port: '5432', + user: 'postgres', + password: '', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, CitusDB: { - host: "localhost", - port: "5432", - user: "postgres", - password: "", - database: "_test", + host: 'localhost', + port: '5432', + user: 'postgres', + password: '', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, CockroachDB: { - host: "localhost", - port: "5432", - user: "postgres", - password: "", - database: "_test", + host: 'localhost', + port: '5432', + user: 'postgres', + password: '', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, Greenplum: { - host: "localhost", - port: "5432", - user: "postgres", - password: "", - database: "_test", + host: 'localhost', + port: '5432', + user: 'postgres', + password: '', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, MsSQL: { - host: "localhost", + host: 'localhost', port: 1433, - user: "sa", - password: "Password123.", - database: "_test", + user: 'sa', + password: 'Password123.', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, Oracle: { - host: "localhost", - port: "1521", - user: "system", - password: "Oracle18", - database: "_test", + host: 'localhost', + port: '1521', + user: 'system', + password: 'Oracle18', + database: '_test', ssl: { - ca: "", - key: "", - cert: "", - }, + ca: '', + key: '', + cert: '' + } }, Sqlite: { - client: "sqlite3", + client: 'sqlite3', database: homeDir, connection: { - filename: homeDir, + filename: homeDir }, - useNullAsDefault: true, - }, + useNullAsDefault: true + } }, dialog: { show: false, - title: "", - heading: "", + title: '', + heading: '', mtdOk: this.testConnectionMethodSubmit, - type: "primary", + type: 'primary' }, // TODO: apply i18n for sslUsage // See general.no - 5 in en.json sslUsage: { - No: "No", - Preferred: "Preferred", - Required: "pg", - "Required-CA": "Required-CA", - "Required-IDENTITY": "Required-IDENTITY", + No: 'No', + Preferred: 'Preferred', + Required: 'pg', + 'Required-CA': 'Required-CA', + 'Required-IDENTITY': 'Required-IDENTITY' }, - sslUse: this.$t("general.preferred"), // Preferred + sslUse: this.$t('general.preferred'), // Preferred ssl: { - key: this.$t("labels.clientKey"), // Client Key - cert: this.$t("labels.clientCert"), // Client Cert - ca: this.$t("labels.serverCA"), // Server CA + key: this.$t('labels.clientKey'), // Client Key + cert: this.$t('labels.clientCert'), // Client Cert + ca: this.$t('labels.serverCA') // Server CA }, databaseNames: { - MySQL: "mysql2", - Postgres: "pg", + MySQL: 'mysql2', + Postgres: 'pg', // Oracle: "oracledb", - MsSQL: "mssql", - Sqlite: "sqlite3", + MsSQL: 'mssql', + Sqlite: 'sqlite3' // Vitess: "mysql2", // TiDB: "mysql2", // Yugabyte: "pg", @@ -1211,40 +1227,40 @@ export default { testDatabaseNames: { mysql2: null, mysql: null, - pg: "postgres", - oracledb: "xe", + pg: 'postgres', + oracledb: 'xe', mssql: undefined, - sqlite3: "a.sqlite", + sqlite3: 'a.sqlite' }, dbIcons: { - Oracle: "temp/db/oracle.png", - Postgres: "temp/db/postgre.png", - MySQL: "temp/db/mysql.png", - MsSQL: "temp/db/mssql.png", - Sqlite: "temp/db/sqlite.svg", - Salesforce: "temp/salesforce-3-569548.webp", - SAP: "temp/sap.png", - Stripe: "temp/stripe.svg", + Oracle: 'temp/db/oracle.png', + Postgres: 'temp/db/postgre.png', + MySQL: 'temp/db/mysql.png', + MsSQL: 'temp/db/mssql.png', + Sqlite: 'temp/db/sqlite.svg', + Salesforce: 'temp/salesforce-3-569548.webp', + SAP: 'temp/sap.png', + Stripe: 'temp/stripe.svg' }, dialogGetEnvName: { dialogShow: false, - heading: "Enter New Environment Name", - field: "Environment Name", + heading: 'Enter New Environment Name', + field: 'Environment Name' }, compErrorMessages: [ - this.$t("msg.error.invalidChar"), // Invalid character in folder path - this.$t("msg.error.invalidDbCredentials"), // Invalid database credentials - this.$t("msg.error.unableToConnectToDb"), // Unable to connect to database, please check your database is up - this.$t("msg.error.userDoesntHaveSufficientPermission"), // User does not exist or have sufficient permission to create schema + this.$t('msg.error.invalidChar'), // Invalid character in folder path + this.$t('msg.error.invalidDbCredentials'), // Invalid database credentials + this.$t('msg.error.unableToConnectToDb'), // Unable to connect to database, please check your database is up + this.$t('msg.error.userDoesntHaveSufficientPermission') // User does not exist or have sufficient permission to create schema ], - compErrorMessage: "", - }; + compErrorMessage: '' + } }, computed: { - ...mapGetters({ sqlMgr: "sqlMgr/sqlMgr" }), + ...mapGetters({ sqlMgr: 'sqlMgr/sqlMgr' }), isTitle() { - return this.project.title && this.project.title.trim().length; + return this.project.title && this.project.title.trim().length }, envStatusValid() { return ( @@ -1252,46 +1268,46 @@ export default { Object.values(this.project.envs).every( this.getEnvironmentStatusAggregatedNew ) - ); + ) }, typeIcon() { if (this.project.projectType) { return this.projectTypes.find( ({ value }) => value === this.project.projectType - ); + ) } else { return { - icon: "mdi-server", - iconColor: "primary", - }; + icon: 'mdi-server', + iconColor: 'primary' + } } }, databaseNamesReverse() { return Object.entries(this.databaseNames).reduce( (newObj, [value, key]) => { - newObj[key] = value; - return newObj; + newObj[key] = value + return newObj }, {} - ); - }, + ) + } }, methods: { async enableAllSchemas() { - this.$toast.info("Enabled all schemas").goAway(3000); - this.allSchemas = true; + this.$toast.info('Enabled all schemas').goAway(3000) + this.allSchemas = true await this.$axios({ - url: "demo", - baseURL: `${this.$axios.defaults.baseURL}/dashboard`, - }); + url: 'demo', + baseURL: `${this.$axios.defaults.baseURL}/dashboard` + }) }, ...mapActions({ - loadProjects: "project/loadProjects", + loadProjects: 'project/loadProjects' }), onAdvancePanelToggle() { if (this.$refs.monacoEditor) { - setTimeout(() => this.$refs.monacoEditor.resizeLayout(), 400); + setTimeout(() => this.$refs.monacoEditor.resizeLayout(), 400) } }, getProjectEditTooltip() { @@ -1302,17 +1318,17 @@ export default { }, readFileContent(db, obj, key, index) { readFile(this.$refs[`${key}FilePath`][index], (data) => { - Vue.set(db.connection[obj], key, data); - }); + Vue.set(db.connection[obj], key, data) + }) }, selectFile(db, obj, key, index) { - this.$refs[key][index].click(); + this.$refs[key][index].click() }, onPanelToggle(panelIndex, envKey) { this.$nextTick(() => { if (this.panel !== undefined) { - const panelContainer = this.$refs.panelContainer; - const panel = this.$refs[`panel${envKey}`][0].$el; + const panelContainer = this.$refs.panelContainer + const panel = this.$refs[`panel${envKey}`][0].$el setTimeout( () => (panelContainer.scrollTop = @@ -1321,100 +1337,100 @@ export default { panelContainer.getBoundingClientRect().top - 50), 500 - ); - setTimeout(() => this.$refs[`password${envKey}`][0].focus()); + ) + setTimeout(() => this.$refs[`password${envKey}`][0].focus()) } - }); + }) }, scrollToTop() { - document.querySelector("html").scrollTop = 0; + document.querySelector('html').scrollTop = 0 }, showDBTabInEnvPanel(panelIndex, tabIndex) { - this.panel = panelIndex; - Vue.set(this.databases, panelIndex, tabIndex); + this.panel = panelIndex + Vue.set(this.databases, panelIndex, tabIndex) }, getProjectJson() { /** * remove UI keys within project */ - const xcConfig = JSON.parse(JSON.stringify(this.project)); - delete xcConfig.ui; + const xcConfig = JSON.parse(JSON.stringify(this.project)) + delete xcConfig.ui for (const env in xcConfig.envs) { for (let i = 0; i < xcConfig.envs[env].db.length; ++i) { - xcConfig.envs[env].db[i].meta.api.type = this.project.projectType; + xcConfig.envs[env].db[i].meta.api.type = this.project.projectType if ( - xcConfig.envs[env].db[i].client === "mysql" || - xcConfig.envs[env].db[i].client === "mysql2" + xcConfig.envs[env].db[i].client === 'mysql' || + xcConfig.envs[env].db[i].client === 'mysql2' ) { - xcConfig.envs[env].db[i].connection.multipleStatements = true; + xcConfig.envs[env].db[i].connection.multipleStatements = true } - this.handleSSL(xcConfig.envs[env].db[i], false); - delete xcConfig.envs[env].db[i].ui; - if (this.client[i] === "Vitess") { - xcConfig.envs[env].db[i].meta.dbtype = "vitess"; + this.handleSSL(xcConfig.envs[env].db[i], false) + delete xcConfig.envs[env].db[i].ui + if (this.client[i] === 'Vitess') { + xcConfig.envs[env].db[i].meta.dbtype = 'vitess' } - if (this.client[i] === "TiDB") { - xcConfig.envs[env].db[i].meta.dbtype = "tidb"; + if (this.client[i] === 'TiDB') { + xcConfig.envs[env].db[i].meta.dbtype = 'tidb' } - if (xcConfig.envs[env].db[i].client === "oracledb") { + if (xcConfig.envs[env].db[i].client === 'oracledb') { xcConfig.envs[env].db[i].pool = { min: 0, - max: 50, - }; + max: 50 + } - xcConfig.envs[env].db[i].acquireConnectionTimeout = 60000; + xcConfig.envs[env].db[i].acquireConnectionTimeout = 60000 } - const inflectionObj = xcConfig.envs[env].db[i].meta.inflection; + const inflectionObj = xcConfig.envs[env].db[i].meta.inflection if (inflectionObj) { if (Array.isArray(inflectionObj.table_name)) { - inflectionObj.table_name = inflectionObj.table_name.join(","); + inflectionObj.table_name = inflectionObj.table_name.join(',') } if (Array.isArray(inflectionObj.column_name)) { - inflectionObj.column_name = inflectionObj.column_name.join(","); + inflectionObj.column_name = inflectionObj.column_name.join(',') } - inflectionObj.table_name = inflectionObj.table_name || "none"; - inflectionObj.column_name = inflectionObj.column_name || "none"; + inflectionObj.table_name = inflectionObj.table_name || 'none' + inflectionObj.column_name = inflectionObj.column_name || 'none' } if (this.allSchemas) { - delete xcConfig.envs[env].db[i].connection.database; - xcConfig.envs[env].db[i].meta.allSchemas = true; + delete xcConfig.envs[env].db[i].connection.database + xcConfig.envs[env].db[i].meta.allSchemas = true } } } - xcConfig.auth = {}; + xcConfig.auth = {} switch (this.auth.authType) { - case "jwt": + case 'jwt': xcConfig.auth.jwt = { secret: this.auth.authSecret, dbAlias: - xcConfig.envs[Object.keys(xcConfig.envs)[0]].db[0].meta.dbAlias, - }; - break; - case "masterKey": + xcConfig.envs[Object.keys(xcConfig.envs)[0]].db[0].meta.dbAlias + } + break + case 'masterKey': xcConfig.auth.masterKey = { - secret: this.auth.authSecret, - }; - sessionStorage.setItem("masterKey", this.auth.authSecret); - break; - case "middleware": + secret: this.auth.authSecret + } + sessionStorage.setItem('masterKey', this.auth.authSecret) + break + case 'middleware': xcConfig.auth.masterKey = { - url: this.auth.webhook, - }; - break; + url: this.auth.webhook + } + break default: - this.auth.disabled = true; - break; + this.auth.disabled = true + break } xcConfig.type = this.$store.state.project.projectInfo ? this.$store.state.project.projectInfo.type - : "docker"; + : 'docker' if ( this.smtpConfiguration && @@ -1424,105 +1440,110 @@ export default { try { xcConfig.mailer = { options: JSON5.parse(this.smtpConfiguration.options), - from: this.smtpConfiguration.from, - }; - } catch (e) {} + from: this.smtpConfiguration.from + } + } catch (e) { + } } - xcConfig.meta = xcConfig.meta || {}; + xcConfig.meta = xcConfig.meta || {} xcConfig.meta.db = { - client: "sqlite3", + client: 'sqlite3', connection: { - filename: "xc.db", - }, - }; + filename: 'xc.db' + } + } - return xcConfig; + return xcConfig }, constructProjectJsonFromProject(project) { - const p = project; // JSON.parse(JSON.stringify(project.projectJson)); + const p = project // JSON.parse(JSON.stringify(project.projectJson)); p.ui = { envs: { - _noco: {}, - }, - }; + _noco: {} + } + } for (const env in p.envs) { - let i = 0; + let i = 0 for (const db of p.envs[env].db) { - Vue.set(this.client, i++, this.databaseNamesReverse[db.client]); + Vue.set(this.client, i++, this.databaseNamesReverse[db.client]) - Vue.set(db, "ui", { + Vue.set(db, 'ui', { setup: 0, ssl: { - key: this.$t("labels.clientKey"), // Client Key - cert: this.$t("labels.clientCert"), // Client Cert - ca: this.$t("labels.serverCA"), // Server CA + key: this.$t('labels.clientKey'), // Client Key + cert: this.$t('labels.clientCert'), // Client Cert + ca: this.$t('labels.serverCA') // Server CA }, - sslUse: this.$t("general.preferred"), // Preferred - }); + sslUse: this.$t('general.preferred') // Preferred + }) } } // delete p.projectJson; if (p.auth) { if (p.auth.jwt) { - this.auth.authType = "jwt"; - this.auth.authSecret = p.auth.jwt.secret; + this.auth.authType = 'jwt' + this.auth.authSecret = p.auth.jwt.secret } else if (p.auth.masterKey) { if (p.auth.masterKey.secret) { - this.auth.authSecret = p.auth.masterKey.secret; - this.auth.authType = "masterKey"; + this.auth.authSecret = p.auth.masterKey.secret + this.auth.authType = 'masterKey' } else if (p.auth.masterKey.url) { - this.auth.webhook = p.auth.masterKey.url; - this.auth.authType = "middleware"; + this.auth.webhook = p.auth.masterKey.url + this.auth.authType = 'middleware' } else { - this.auth.authType = "none"; + this.auth.authType = 'none' } } else { - this.auth.authType = "none"; + this.auth.authType = 'none' } } else { - this.auth.authType = "none"; + this.auth.authType = 'none' } - this.project = p; + this.project = p if (p.mailer) { this.smtpConfiguration = { from: p.mailer.from, - options: JSON.stringify(p.mailer.options, 0, 2), - }; + options: JSON.stringify(p.mailer.options, 0, 2) + } } - delete p.mailer; + delete p.mailer }, async createOrUpdateProject() { - const projectJson = this.getProjectJson(); - delete projectJson.folder; + const projectJson = this.getProjectJson() + delete projectJson.folder - let i = 0; - const toast = this.$toast.info(this.loaderMessages[0]); + let i = 0 + const toast = this.$toast.info(this.loaderMessages[0]) const interv = setInterval(() => { if (this.edit) { - return; + return } if (i < this.loaderMessages.length - 1) { - i++; + i++ } if (toast) { if (!this.allSchemas) { - toast.text(this.loaderMessages[i]); + toast.text(this.loaderMessages[i]) } else { - toast.goAway(100); + toast.goAway(100) } } - }, 1000); + }, 1000) - this.projectReloading = true; + this.projectReloading = true - const con = projectJson.envs._noco.db[0]; - const inflection = (con.meta && con.meta.inflection) || {}; + const con = projectJson.envs._noco.db[0] + if (con.client === 'pg' || con.client === 'mssql') { + con.searchPath = [this.schema] + } + + const inflection = (con.meta && con.meta.inflection) || {} try { const result = await this.$api.project.create({ title: projectJson.title, @@ -1531,204 +1552,206 @@ export default { type: con.client, config: con, inflection_column: inflection.column_name, - inflection_table: inflection.table_name, - }, + inflection_table: inflection.table_name + } ], - external: true, - }); + external: true + }) - clearInterval(interv); - toast.goAway(100); + clearInterval(interv) + toast.goAway(100) - await this.$store.dispatch("project/ActLoadProjectInfo"); + await this.$store.dispatch('project/ActLoadProjectInfo') - this.projectReloading = false; + this.projectReloading = false if (!this.edit && !this.allSchemas) { this.$router.push({ path: `/nc/${result.id}`, query: { - new: 1, - }, - }); + new: 1 + } + }) } - this.projectCreated = true; + this.projectCreated = true } catch (e) { this.$toast .error(await this._extractSdkResponseErrorMsg(e)) - .goAway(3000); - toast.goAway(0); + .goAway(3000) + toast.goAway(0) } - this.projectReloading = false; - this.$e("a:project:create:extdb"); + this.projectReloading = false + this.$e('a:project:create:extdb') }, mtdDialogGetEnvNameSubmit(envName, cookie) { - this.dialogGetEnvName.dialogShow = false; + this.dialogGetEnvName.dialogShow = false if (envName in this.project.envs) { } else { Vue.set(this.project.envs, envName, { db: [ { - client: "pg", + client: 'pg', connection: { - host: "localhost", - port: "5432", - user: "postgres", - password: "password", - database: "new_database", + host: 'localhost', + port: '5432', + user: 'postgres', + password: 'password', + database: 'new_database' }, meta: { - tn: "nc_evolutions", - dbAlias: "db", + tn: 'nc_evolutions', + dbAlias: 'db', inflection: { - table_name: "camelize", - column_name: "camelize", + table_name: 'camelize', + column_name: 'camelize' }, api: { - type: "", - }, + type: '' + } }, ui: { setup: 0, ssl: { - key: this.$t("labels.clientKey"), // Client Key - cert: this.$t("labels.clientCert"), // Client Cert - ca: this.$t("labels.serverCA"), // Server CA + key: this.$t('labels.clientKey'), // Client Key + cert: this.$t('labels.clientCert'), // Client Cert + ca: this.$t('labels.serverCA') // Server CA }, - sslUse: this.$t("general.preferred"), // Preferred - }, - }, + sslUse: this.$t('general.preferred') // Preferred + } + } ], - apiClient: { data: [] }, - }); + apiClient: { data: [] } + }) } }, mtdDialogGetEnvNameCancel() { - this.dialogGetEnvName.dialogShow = false; + this.dialogGetEnvName.dialogShow = false }, addNewEnvironment() { - this.dialogGetEnvName.dialogShow = true; + this.dialogGetEnvName.dialogShow = true }, addNewDB(envKey, panelIndex) { - const len = this.project.envs[envKey].db.length; + const len = this.project.envs[envKey].db.length // eslint-disable-next-line no-unused-vars - const lastDbName = `${this.project.title}_${envKey}_${len}`; + const lastDbName = `${this.project.title}_${envKey}_${len}` const dbType = (this.client[len] = - this.client[len] || this.client[len - 1]); - const newlyCreatedIndex = this.project.envs[envKey].db.length; + this.client[len] || this.client[len - 1]) + const newlyCreatedIndex = this.project.envs[envKey].db.length const dbAlias = this.project.envs[envKey].db.length <= 0 - ? "db" - : `db${this.project.envs[envKey].db.length + 1}`; + ? 'db' + : `db${this.project.envs[envKey].db.length + 1}` this.project.envs[envKey].db.push({ client: this.databaseNames[dbType], connection: { ...this.sampleConnectionData[dbType], - database: `${this.project.title}_${envKey}_${newlyCreatedIndex + 1}`, + database: `${this.project.title}_${envKey}_${newlyCreatedIndex + 1}` }, meta: { - tn: "nc_evolutions", + tn: 'nc_evolutions', dbAlias, inflection: { - table_name: "camelize", - column_name: "camelize", + table_name: 'camelize', + column_name: 'camelize' }, api: { - type: "", - }, + type: '' + } }, ui: { setup: 0, - sslUse: this.$t("general.preferred"), // Preferred + sslUse: this.$t('general.preferred'), // Preferred ssl: { - key: this.$t("labels.clientKey"), // Client Key - cert: this.$t("labels.clientCert"), // Client Cert - ca: this.$t("labels.serverCA"), // Server CA - }, - }, - }); + key: this.$t('labels.clientKey'), // Client Key + cert: this.$t('labels.clientCert'), // Client Cert + ca: this.$t('labels.serverCA') // Server CA + } + } + }) // set active tab as newly created - this.databases[panelIndex] = newlyCreatedIndex; + this.databases[panelIndex] = newlyCreatedIndex }, testConnectionMethodSubmit() { - this.dialog.show = false; + this.dialog.show = false + }, + selectDir(ev) { + }, + selectSqliteFile(db) { }, - selectDir(ev) {}, - selectSqliteFile(db) {}, getDbStatusColor(db) { switch (db.ui.setup) { case -1: - return "red"; + return 'red' case 0: - return "orange"; + return 'orange' case 1: - return "green"; + return 'green' default: - break; + break } }, getDbStatusTooltip(db) { switch (db.ui.setup) { case -1: - return "DB Connection NOT successful"; + return 'DB Connection NOT successful' case 0: - return "MySql Database Detected - Test your connection"; + return 'MySql Database Detected - Test your connection' case 1: - return "DB Connection successful"; + return 'DB Connection successful' default: - break; + break } }, async newTestConnection(db, env, panelIndex) { if ( - db.connection.host === "localhost" && + db.connection.host === 'localhost' && !this.edit && - env === "_noco" && + env === '_noco' && this.project.envs[env].db.length === 1 && - this.project.envs[env].db[0].connection.user === "postgres" && + this.project.envs[env].db[0].connection.user === 'postgres' && this.project.envs[env].db[0].connection.database === - `${this.project.title}_${env}_${this.project.envs[env].length}` + `${this.project.title}_${env}_${this.project.envs[env].length}` ) { - this.handleSSL(db); - if (db.client === "sqlite3") { - db.ui.setup = 1; + this.handleSSL(db) + if (db.client === 'sqlite3') { + db.ui.setup = 1 } else { const c1 = { connection: { ...db.connection, - ...(db.client !== "pg" + ...(db.client !== 'pg' ? { database: this.testDatabaseNames[db.client] } - : {}), + : {}) }, - client: db.client, - }; + client: db.client + } - const result = await this.$store.dispatch("sqlMgr/ActSqlOp", [ + const result = await this.$store.dispatch('sqlMgr/ActSqlOp', [ { query: { - skipProjectHasDb: 1, - }, + skipProjectHasDb: 1 + } }, - "testConnection", - c1, - ]); + 'testConnection', + c1 + ]) if (result.code === 0) { - db.ui.setup = 1; - let passed = true; + db.ui.setup = 1 + let passed = true /** * get other environments * and if host is localhost - test and update connection status @@ -1742,276 +1765,286 @@ export default { const c2 = { connection: { ...this.project.envs[e].db[0].connection, - database: undefined, + database: undefined }, - client: this.project.envs[e].db[0].client, - }; + client: this.project.envs[e].db[0].client + } - this.handleSSL(c2); + this.handleSSL(c2) - const result = await this.sqlMgr.testConnection(c2); + const result = await this.sqlMgr.testConnection(c2) if (result.code === 0) { - this.project.envs[e][0].ui.setup = 1; + this.project.envs[e][0].ui.setup = 1 } else { - this.project.envs[e][0].ui.setup = -1; - passed = false; - break; + this.project.envs[e][0].ui.setup = -1 + passed = false + break } } } if (passed) { - this.panel = null; + this.panel = null } else { // Connection was successful - this.dialog.heading = this.$t("msg.info.dbConnected"); - this.dialog.type = "success"; - this.dialog.show = true; + this.dialog.heading = this.$t('msg.info.dbConnected') + this.dialog.type = 'success' + this.dialog.show = true } } else { - db.ui.setup = -1; + db.ui.setup = -1 // Connection Failure: this.dialog.heading = - this.$t("msg.error.dbConnectionFailed") + result.message; - this.dialog.type = "error"; - this.dialog.show = true; + this.$t('msg.error.dbConnectionFailed') + result.message + this.dialog.type = 'error' + this.dialog.show = true } } - return true; + return true } else { - return false; + return false } }, sendAdvancedConfig(connection) { if (!connection.ssl) { - return false; + return false } - let sendAdvancedConfig = false; - const sslOptions = Object.values(connection.ssl).filter((el) => !!el); + let sendAdvancedConfig = false + const sslOptions = Object.values(connection.ssl).filter(el => !!el) if (sslOptions[0]) { - sendAdvancedConfig = true; + sendAdvancedConfig = true } else { } - return sendAdvancedConfig; + return sendAdvancedConfig }, handleSSL(db, creating = true) { - const sendAdvancedConfig = this.sendAdvancedConfig(db.connection); + const sendAdvancedConfig = this.sendAdvancedConfig(db.connection) if (!sendAdvancedConfig) { - db.connection.ssl = undefined; + db.connection.ssl = undefined } if (db.connection.ssl) { } }, - getDatabaseForTestConnection(dbType) {}, + getDatabaseForTestConnection(dbType) { + }, async testConnection(db, env, panelIndex) { - this.$e("a:project:create:extdb:test-connection"); - this.$store.commit("notification/MutToggleProgressBar", true); + this.$e('a:project:create:extdb:test-connection') + this.$store.commit('notification/MutToggleProgressBar', true) try { if (!(await this.newTestConnection(db, env, panelIndex))) { - this.handleSSL(db); + this.handleSSL(db) - if (db.client === "sqlite3") { - db.ui.setup = 1; + if (db.client === 'sqlite3') { + db.ui.setup = 1 } else { const c1 = { connection: { ...db.connection, - ...(db.client !== "pg" + ...(db.client !== 'pg' ? { database: this.testDatabaseNames[db.client] } - : {}), + : {}) }, - client: db.client, - }; + client: db.client + } - const result = await this.$api.utils.testConnection(c1); + const result = await this.$api.utils.testConnection(c1) if (result.code === 0) { - db.ui.setup = 1; + db.ui.setup = 1 // this.dialog.heading = "Connection was successful" // this.dialog.type = 'success'; // this.dialog.show = true; - this.testSuccess = true; + this.testSuccess = true } else { - db.ui.setup = -1; + db.ui.setup = -1 // this.activeDbNode.testConnectionStatus = false; this.dialog.heading = - this.$t("msg.error.dbConnectionFailed") + result.message; - this.dialog.type = "error"; - this.dialog.show = true; + this.$t('msg.error.dbConnectionFailed') + result.message + this.dialog.type = 'error' + this.dialog.show = true } } } } catch (e) { - console.log(e); + console.log(e) } finally { - this.$store.commit("notification/MutToggleProgressBar", false); + this.$store.commit('notification/MutToggleProgressBar', false) } }, getEnvironmentStatusAggregated(dbs) { - return dbs.every((db) => db.ui.setup === 1); + return dbs.every(db => db.ui.setup === 1) }, getEnvironmentStatusAggregatedNew(dbs) { - return dbs.db.every((db) => db.ui.setup === 1); + return dbs.db.every(db => db.ui.setup === 1) }, openFirstPanel() { if (!this.edit) { - this.panel = 0; + this.panel = 0 } }, onDatabaseTypeChanged(client, db1, index, env) { + if (this.databaseNames[client] === 'mssql') { + this.schema = 'dbo' + } else if (this.databaseNames[client] === 'pg') { + this.schema = 'public' + } + for (const env in this.project.envs) { if (this.project.envs[env].db.length > index) { - const db = this.project.envs[env].db[index]; - Vue.set(db, "client", this.databaseNames[client]); - if (client !== "Sqlite") { - const { ssl, ...connectionDet } = this.sampleConnectionData[client]; + const db = this.project.envs[env].db[index] + Vue.set(db, 'client', this.databaseNames[client]) - Vue.set(db, "connection", { + if (client !== 'Sqlite') { + const { ssl, ...connectionDet } = this.sampleConnectionData[client] + + Vue.set(db, 'connection', { ...connectionDet, database: `${this.project.title}_${env}_${index + 1}`, - ssl: { ...ssl }, - }); + ssl: { ...ssl } + }) for (const env in this.project.envs) { if (this.project.envs[env].length > index) { - this.setDBStatus(this.project.envs[env][index], 0); + this.setDBStatus(this.project.envs[env][index], 0) } } } else { - db.connection = {}; - Vue.set(db, "connection", { - client: "sqlite3", + db.connection = {} + Vue.set(db, 'connection', { + client: 'sqlite3', // connection: {filename: path.join(this.project.folder, `${this.project.title}_${env}_${index + 1}`)}, connection: { filename: [ this.project.folder, - `${this.project.title}_${env}_${index + 1}`, - ].join("/"), + `${this.project.title}_${env}_${index + 1}` + ].join('/') }, database: [ this.project.folder, - `${this.project.title}_${env}_${index + 1}`, - ].join("/"), - useNullAsDefault: true, - }); + `${this.project.title}_${env}_${index + 1}` + ].join('/'), + useNullAsDefault: true + }) } } } }, selectDatabaseClient(database, index = 0) { if (this.client) { - this.client[index] = database; + this.client[index] = database } }, setDBStatus(db, status) { - db.ui.setup = status; + db.ui.setup = status }, removeDBFromEnv(db, env, panelIndex, dbIndex) { for (const env in this.project.envs) { if (this.project.envs[env].db.length > dbIndex) { - this.project.envs[env].db.splice(dbIndex, 1); + this.project.envs[env].db.splice(dbIndex, 1) } } }, removeEnv(envKey) { - delete this.project.envs[envKey]; - Vue.set(this.project, "envs", { ...this.project.envs }); - }, + delete this.project.envs[envKey] + Vue.set(this.project, 'envs', { ...this.project.envs }) + } + }, + fetch({ store, params }) { + }, + beforeCreated() { }, - fetch({ store, params }) {}, - beforeCreated() {}, watch: { - "project.title"(newValue, oldValue) { + 'project.title'(newValue, oldValue) { if (!newValue) { - return; + return } if (!this.edit) { // Vue.set(this.project, 'folder', slash(path.join(this.baseFolder, newValue))) - Vue.set(this.project, "folder", [this.baseFolder, newValue].join("/")); + Vue.set(this.project, 'folder', [this.baseFolder, newValue].join('/')) // }//this.project.folder = `${this.baseFolder}/${newValue}`; for (const env in this.project.envs) { for (const [index, db] of this.project.envs[env].db.entries()) { // db.connection.database = `${this.project.title}_${env}_${index}` - if (db.client !== "sqlite3") { + if (db.client !== 'sqlite3') { Vue.set( db.connection, - "database", + 'database', `${this.project.title}_${env}_${index + 1}` - ); + ) } else { Vue.set( db.connection, - "database", + 'database', `${this.project.title}_${env}_${index + 1}` - ); + ) } } } } }, - "project.envs": { + 'project.envs': { deep: true, handler(envs) { - if (typeof envs === "object" && envs) { + if (typeof envs === 'object' && envs) { Object.entries(envs).forEach(([key, env]) => { - let res = 1; - const msg = {}; + let res = 1 + const msg = {} for (const db of env.db) { - res = db.ui.setup < res ? db.ui.setup : res; + res = db.ui.setup < res ? db.ui.setup : res } if (this.edit) { - Vue.set(this.project.ui, key, ""); + Vue.set(this.project.ui, key, '') } else { switch (res) { case -1: - msg.color = "red"; + msg.color = 'red' // msg.msg = ' ( Invalid database parameters )' - msg.msg = `( ${this.$t("msg.error.dbConnectionStatus")} )`; - break; + msg.msg = `( ${this.$t('msg.error.dbConnectionStatus')} )` + break case 0: - msg.color = "warning"; - msg.msg = " ( Click to validate database credentials )"; - break; + msg.color = 'warning' + msg.msg = ' ( Click to validate database credentials )' + break case 1: - msg.color = "green"; + msg.color = 'green' // msg.msg = ' ( Environment Validated )' - msg.msg = `( ${this.$t("msg.info.dbConnectionStatus")} )`; - break; + msg.msg = `( ${this.$t('msg.info.dbConnectionStatus')} )` + break } - Vue.set(this.project.ui, key, msg); + Vue.set(this.project.ui, key, msg) } - }); + }) } - }, - }, + } + } }, async created() { this.compErrorMessage = this.compErrorMessages[ Math.floor(Math.random() * this.compErrorMessages.length) - ]; + ] if (this.edit) { try { - let data = await this.$store.dispatch("sqlMgr/ActSqlOp", [ + let data = await this.$store.dispatch('sqlMgr/ActSqlOp', [ null, - "xcProjectGetConfig", - ]); - data = JSON.parse(data.config); - this.constructProjectJsonFromProject(data); - this.$set(this.project, "folder", data.folder); + 'xcProjectGetConfig' + ]) + data = JSON.parse(data.config) + this.constructProjectJsonFromProject(data) + this.$set(this.project, 'folder', data.folder) } catch (e) { - this.$toast.error(e.message).goAway(3000); + this.$toast.error(e.message).goAway(3000) } } else { - this.project = JSON.parse(JSON.stringify(this.defaultProject)); + this.project = JSON.parse(JSON.stringify(this.defaultProject)) // this.edit = false; /** @@ -2021,74 +2054,77 @@ export default { * * */ - let dbsAvailable = []; // await PortScanner.getOpenDbPortsAsList(); + let dbsAvailable = [] // await PortScanner.getOpenDbPortsAsList(); // // setting MySQL as default value if no databases are available // if (!dbsAvailable || !dbsAvailable.length) { - dbsAvailable = ["MySQL"]; + dbsAvailable = ['MySQL'] // } - this.selectDatabaseClient(dbsAvailable[0], 0); + this.selectDatabaseClient(dbsAvailable[0], 0) // iterating over environment and setting default connection details based // on first available database for (const env in this.project.envs) { for (const db of this.project.envs[env].db) { - db.client = this.databaseNames[dbsAvailable[0]]; + db.client = this.databaseNames[dbsAvailable[0]] - if (db.client === "sqlite3") { + if (db.client === 'sqlite3') { db.connection = { - ...this.sampleConnectionData[dbsAvailable[0]], - }; + ...this.sampleConnectionData[dbsAvailable[0]] + } - db.ui.setup = 0; + db.ui.setup = 0 } else { db.connection = { ...this.sampleConnectionData[dbsAvailable[0]], - ssl: { ...this.sampleConnectionData[dbsAvailable[0]].ssl }, - }; + ssl: { ...this.sampleConnectionData[dbsAvailable[0]].ssl } + } } } } } }, - beforeMount() {}, + beforeMount() { + }, mounted() { this.$set( this.project, - "title", + 'title', uniqueNamesGenerator({ dictionaries: [[starWars], [adjectives, animals]][ Math.floor(Math.random() * 2) - ], + ] }) .toLowerCase() - .replace(/[ -]/g, "_") - ); + .replace(/[ -]/g, '_') + ) this.$nextTick(() => { - const input = this.$refs.name.$el.querySelector("input"); - input.setSelectionRange(0, this.project.title.length); - input.focus(); - }); + const input = this.$refs.name.$el.querySelector('input') + input.setSelectionRange(0, this.project.title.length) + input.focus() + }) + }, + beforeDestroy() { + }, + destroy() { }, - beforeDestroy() {}, - destroy() {}, validate({ params }) { - return true; + return true }, head() { return { - title: this.$t("title.headCreateProject"), - }; + title: this.$t('title.headCreateProject') + } }, props: { edit: { type: Boolean, - default: false, - }, + default: false + } }, - directives: {}, -}; + directives: {} +} </script> <style scoped> diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json index 5ea5565085..a8f3073817 100644 --- a/packages/nc-gui/lang/en.json +++ b/packages/nc-gui/lang/en.json @@ -191,6 +191,7 @@ "port": "Port Number", "username": "Username", "password": "Password", + "schemaName": "Schema name", "action": "Action", "actions": "Actions", "operation": "Operation", From 76a5bf26cf3df75ed67f9c7128254e13a0de878f Mon Sep 17 00:00:00 2001 From: Pranav C <pranavxc@gmail.com> Date: Tue, 26 Apr 2022 01:04:18 +0530 Subject: [PATCH 12/39] fix: correction in belongs to lookup filter query generation re #1866 Signed-off-by: Pranav C <pranavxc@gmail.com> --- packages/nocodb/src/lib/dataMapper/lib/sql/conditionV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/conditionV2.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/conditionV2.ts index 3f2152c0c3..eca1058825 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/conditionV2.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/conditionV2.ts @@ -349,7 +349,7 @@ async function generateLookupCondition( }; } else if (relationColumnOptions.type === RelationTypes.BELONGS_TO) { qb = knex(`${parentModel.table_name} as ${alias}`); - qb.select(`${alias}.${childColumn.column_name}`); + qb.select(`${alias}.${parentColumn.column_name}`); await nestedConditionJoin( { From cdef167078cfcb57e1595fedb6f6616850720a07 Mon Sep 17 00:00:00 2001 From: Pranav C <pranavxc@gmail.com> Date: Tue, 26 Apr 2022 01:20:33 +0530 Subject: [PATCH 13/39] fix: ignore date formatting if type is not string re #1864 Signed-off-by: Pranav C <pranavxc@gmail.com> --- .../project/spreadsheet/components/virtualCell/formulaCell.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nc-gui/components/project/spreadsheet/components/virtualCell/formulaCell.vue b/packages/nc-gui/components/project/spreadsheet/components/virtualCell/formulaCell.vue index 5f7ff04b7e..25f9db470d 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/virtualCell/formulaCell.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/virtualCell/formulaCell.vue @@ -49,6 +49,7 @@ export default { // handle date returned from PostgreSQL handleTZ(val) { if (!val) { return } + if (typeof val !== 'string') { return val } return val.replace(/((?:-?(?:[1-9][0-9]*)?[0-9]{4})-(?:1[0-2]|0[1-9])-(?:3[01]|0[1-9]|[12][0-9])T(?:2[0-3]|[01][0-9]):(?:[0-5][0-9]):(?:[0-5][0-9])(?:\.[0-9]+)?(?:Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9]))/g, (i, v) => { return dayjs(v).format('YYYY-MM-DD HH:mm') }) From 7e4291f74a109ae5d2b3a42166b92ef0e23ae5f5 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong <wingkwong.code@gmail.com> Date: Tue, 26 Apr 2022 11:48:40 +0800 Subject: [PATCH 14/39] i18n: add schemaName Signed-off-by: Wing-Kam Wong <wingkwong.code@gmail.com> --- packages/nc-gui/lang/da.json | 1 + packages/nc-gui/lang/de.json | 1 + packages/nc-gui/lang/es.json | 1 + packages/nc-gui/lang/fa.json | 1 + packages/nc-gui/lang/fi.json | 1 + packages/nc-gui/lang/fr.json | 1 + packages/nc-gui/lang/hr.json | 1 + packages/nc-gui/lang/id.json | 1 + packages/nc-gui/lang/it_IT.json | 1 + packages/nc-gui/lang/iw.json | 1 + packages/nc-gui/lang/ja.json | 1 + packages/nc-gui/lang/ko.json | 1 + packages/nc-gui/lang/lv.json | 1 + packages/nc-gui/lang/nl.json | 1 + packages/nc-gui/lang/no.json | 1 + packages/nc-gui/lang/pl.json | 1 + packages/nc-gui/lang/pt.json | 1 + packages/nc-gui/lang/pt_BR.json | 1 + packages/nc-gui/lang/ru.json | 1 + packages/nc-gui/lang/sl.json | 1 + packages/nc-gui/lang/sv.json | 1 + packages/nc-gui/lang/th.json | 1 + packages/nc-gui/lang/tr.json | 1 + packages/nc-gui/lang/uk.json | 1 + packages/nc-gui/lang/vi.json | 1 + packages/nc-gui/lang/zh_CN.json | 1 + packages/nc-gui/lang/zh_HK.json | 1 + packages/nc-gui/lang/zh_TW.json | 1 + 28 files changed, 28 insertions(+) diff --git a/packages/nc-gui/lang/da.json b/packages/nc-gui/lang/da.json index 4cd162d3df..ba6ec53aaf 100644 --- a/packages/nc-gui/lang/da.json +++ b/packages/nc-gui/lang/da.json @@ -191,6 +191,7 @@ "port": "Port nummer.", "username": "Brugernavn.", "password": "Adgangskode", + "schemaName": "Schema name", "action": "Handling", "actions": "Handlinger", "operation": "Operation", diff --git a/packages/nc-gui/lang/de.json b/packages/nc-gui/lang/de.json index d47a103f21..e18084beac 100644 --- a/packages/nc-gui/lang/de.json +++ b/packages/nc-gui/lang/de.json @@ -191,6 +191,7 @@ "port": "Port-Nummer", "username": "Benutzername", "password": "Passwort", + "schemaName": "Schema name", "action": "Aktion", "actions": "Aktionen", "operation": "Vorgang", diff --git a/packages/nc-gui/lang/es.json b/packages/nc-gui/lang/es.json index 43a6681a63..88faae315a 100644 --- a/packages/nc-gui/lang/es.json +++ b/packages/nc-gui/lang/es.json @@ -191,6 +191,7 @@ "port": "Puerto", "username": "Usuario", "password": "Contraseña", + "schemaName": "Schema name", "action": "Acción", "actions": "Acciones", "operation": "Operación", diff --git a/packages/nc-gui/lang/fa.json b/packages/nc-gui/lang/fa.json index a8a7a08cab..5d1a197e75 100644 --- a/packages/nc-gui/lang/fa.json +++ b/packages/nc-gui/lang/fa.json @@ -191,6 +191,7 @@ "port": "شماره Port", "username": "نام کاربری", "password": "کلمه عبور", + "schemaName": "Schema name", "action": "اقدام", "actions": "اقدامات", "operation": "عملیات", diff --git a/packages/nc-gui/lang/fi.json b/packages/nc-gui/lang/fi.json index 882d477a03..b12b7e6731 100644 --- a/packages/nc-gui/lang/fi.json +++ b/packages/nc-gui/lang/fi.json @@ -191,6 +191,7 @@ "port": "Porttinumero", "username": "Käyttäjätunnus", "password": "Salasana", + "schemaName": "Schema name", "action": "Toiminta", "actions": "Toiminnot", "operation": "Operaatio", diff --git a/packages/nc-gui/lang/fr.json b/packages/nc-gui/lang/fr.json index 9e4e89adb2..e2063cb51d 100644 --- a/packages/nc-gui/lang/fr.json +++ b/packages/nc-gui/lang/fr.json @@ -191,6 +191,7 @@ "port": "Numéro de port", "username": "Utilisateur", "password": "Mot de passe", + "schemaName": "Schema name", "action": "Action", "actions": "Actions", "operation": "Opération", diff --git a/packages/nc-gui/lang/hr.json b/packages/nc-gui/lang/hr.json index 9b3627b207..94473a66f9 100644 --- a/packages/nc-gui/lang/hr.json +++ b/packages/nc-gui/lang/hr.json @@ -191,6 +191,7 @@ "port": "Broj porta", "username": "Korisničko ime", "password": "Lozinka", + "schemaName": "Schema name", "action": "Akcijski", "actions": "Akcije", "operation": "Operacija", diff --git a/packages/nc-gui/lang/id.json b/packages/nc-gui/lang/id.json index 72db61b4f3..d6c04ec950 100644 --- a/packages/nc-gui/lang/id.json +++ b/packages/nc-gui/lang/id.json @@ -191,6 +191,7 @@ "port": "Nomor port.", "username": "Nama pengguna", "password": "Kata sandi", + "schemaName": "Schema name", "action": "Tindakan", "actions": "Tindakan", "operation": "Operasi", diff --git a/packages/nc-gui/lang/it_IT.json b/packages/nc-gui/lang/it_IT.json index 7b53fc90ee..583240168f 100644 --- a/packages/nc-gui/lang/it_IT.json +++ b/packages/nc-gui/lang/it_IT.json @@ -191,6 +191,7 @@ "port": "Numero di porta", "username": "Nome utente", "password": "Password", + "schemaName": "Schema name", "action": "Azione", "actions": "Azioni", "operation": "Operazione", diff --git a/packages/nc-gui/lang/iw.json b/packages/nc-gui/lang/iw.json index 7bb056a5b7..1d9fcb3576 100644 --- a/packages/nc-gui/lang/iw.json +++ b/packages/nc-gui/lang/iw.json @@ -191,6 +191,7 @@ "port": "פורט", "username": "שם משתמש", "password": "סיסמה", + "schemaName": "Schema name", "action": "פעולה", "actions": "פעולות", "operation": "מבצע", diff --git a/packages/nc-gui/lang/ja.json b/packages/nc-gui/lang/ja.json index af61a190a9..a1ec199abe 100644 --- a/packages/nc-gui/lang/ja.json +++ b/packages/nc-gui/lang/ja.json @@ -191,6 +191,7 @@ "port": "ポート番号", "username": "ユーザー名", "password": "パスワード", + "schemaName": "Schema name", "action": "アクション", "actions": "アクション", "operation": "操作", diff --git a/packages/nc-gui/lang/ko.json b/packages/nc-gui/lang/ko.json index c2b06efebd..b6c05ea421 100644 --- a/packages/nc-gui/lang/ko.json +++ b/packages/nc-gui/lang/ko.json @@ -191,6 +191,7 @@ "port": "포트 번호", "username": "사용자 이름", "password": "비밀번호", + "schemaName": "Schema name", "action": "동작", "actions": "행위", "operation": "작업", diff --git a/packages/nc-gui/lang/lv.json b/packages/nc-gui/lang/lv.json index cce8c9ba2e..9207d3b073 100644 --- a/packages/nc-gui/lang/lv.json +++ b/packages/nc-gui/lang/lv.json @@ -191,6 +191,7 @@ "port": "Porta numurs", "username": "Lietotājvārds", "password": "Parole", + "schemaName": "Schema name", "action": "Darbība", "actions": "Darbības", "operation": "Operācija", diff --git a/packages/nc-gui/lang/nl.json b/packages/nc-gui/lang/nl.json index 32f6a33523..60b16c0a2a 100644 --- a/packages/nc-gui/lang/nl.json +++ b/packages/nc-gui/lang/nl.json @@ -191,6 +191,7 @@ "port": "Poortnummer", "username": "Gebruikersnaam", "password": "Wachtwoord", + "schemaName": "Schema name", "action": "Actie", "actions": "Acties", "operation": "Operatie", diff --git a/packages/nc-gui/lang/no.json b/packages/nc-gui/lang/no.json index 25c438faf2..fff84f5f1e 100644 --- a/packages/nc-gui/lang/no.json +++ b/packages/nc-gui/lang/no.json @@ -191,6 +191,7 @@ "port": "Portnummer", "username": "Brukernavn", "password": "Passord", + "schemaName": "Schema name", "action": "Handling", "actions": "Handlinger", "operation": "Operasjon", diff --git a/packages/nc-gui/lang/pl.json b/packages/nc-gui/lang/pl.json index 2c80c6143b..f7ea3da89a 100644 --- a/packages/nc-gui/lang/pl.json +++ b/packages/nc-gui/lang/pl.json @@ -191,6 +191,7 @@ "port": "Numer portu", "username": "Nazwa użytkownika", "password": "Hasło", + "schemaName": "Schema name", "action": "Akcja", "actions": "działania", "operation": "Operacja", diff --git a/packages/nc-gui/lang/pt.json b/packages/nc-gui/lang/pt.json index b4f2df6a81..59ff4edd80 100644 --- a/packages/nc-gui/lang/pt.json +++ b/packages/nc-gui/lang/pt.json @@ -191,6 +191,7 @@ "port": "Número da Porta", "username": "Utilizador", "password": "Palavra-passe", + "schemaName": "Schema name", "action": "Açao", "actions": "Ações", "operation": "Operação", diff --git a/packages/nc-gui/lang/pt_BR.json b/packages/nc-gui/lang/pt_BR.json index a6fdf678d4..13ec927952 100644 --- a/packages/nc-gui/lang/pt_BR.json +++ b/packages/nc-gui/lang/pt_BR.json @@ -191,6 +191,7 @@ "port": "Número da Porta", "username": "Usuário", "password": "Senha", + "schemaName": "Schema name", "action": "Açao", "actions": "Ações", "operation": "Operação", diff --git a/packages/nc-gui/lang/ru.json b/packages/nc-gui/lang/ru.json index 69cee9d30f..f507f3eafd 100644 --- a/packages/nc-gui/lang/ru.json +++ b/packages/nc-gui/lang/ru.json @@ -191,6 +191,7 @@ "port": "Номер порта", "username": "Имя пользователя", "password": "Пароль", + "schemaName": "Schema name", "action": "Действие", "actions": "Действия", "operation": "Операция", diff --git a/packages/nc-gui/lang/sl.json b/packages/nc-gui/lang/sl.json index 2601a21724..95c0dcb682 100644 --- a/packages/nc-gui/lang/sl.json +++ b/packages/nc-gui/lang/sl.json @@ -191,6 +191,7 @@ "port": "Številka vrat", "username": "Uporabniško ime", "password": "Geslo", + "schemaName": "Schema name", "action": "Akcija", "actions": "Akcijah", "operation": "Operacija", diff --git a/packages/nc-gui/lang/sv.json b/packages/nc-gui/lang/sv.json index c60d7dc738..39c3290005 100644 --- a/packages/nc-gui/lang/sv.json +++ b/packages/nc-gui/lang/sv.json @@ -191,6 +191,7 @@ "port": "Portnummer", "username": "Användarnamn", "password": "Lösenord", + "schemaName": "Schema name", "action": "Handling", "actions": "Handlingar", "operation": "Drift", diff --git a/packages/nc-gui/lang/th.json b/packages/nc-gui/lang/th.json index ea950b6e0b..bebd061fdf 100644 --- a/packages/nc-gui/lang/th.json +++ b/packages/nc-gui/lang/th.json @@ -191,6 +191,7 @@ "port": "หมายเลขพอร์ต", "username": "ชื่อผู้ใช้", "password": "รหัสผ่าน", + "schemaName": "Schema name", "action": "หนังบู๊", "actions": "การกระทำ", "operation": "การดำเนินการ", diff --git a/packages/nc-gui/lang/tr.json b/packages/nc-gui/lang/tr.json index 30746113e7..675cb1f3a8 100644 --- a/packages/nc-gui/lang/tr.json +++ b/packages/nc-gui/lang/tr.json @@ -191,6 +191,7 @@ "port": "Port Numarası", "username": "Kullanıcı Adı", "password": "Şifre", + "schemaName": "Schema name", "action": "Aksiyon", "actions": "Aksiyonlar", "operation": "Operasyon", diff --git a/packages/nc-gui/lang/uk.json b/packages/nc-gui/lang/uk.json index 674a5b86fb..7d6819ff38 100644 --- a/packages/nc-gui/lang/uk.json +++ b/packages/nc-gui/lang/uk.json @@ -191,6 +191,7 @@ "port": "Номер порту", "username": "Ім'я користувача", "password": "Пароль", + "schemaName": "Schema name", "action": "Дія", "actions": "Акції", "operation": "Операція", diff --git a/packages/nc-gui/lang/vi.json b/packages/nc-gui/lang/vi.json index 4e339a4197..567a78412f 100644 --- a/packages/nc-gui/lang/vi.json +++ b/packages/nc-gui/lang/vi.json @@ -191,6 +191,7 @@ "port": "Cổng số", "username": "tên tài khoản", "password": "Mật khẩu", + "schemaName": "Schema name", "action": "Hoạt động", "actions": "Hành động", "operation": "Hoạt động", diff --git a/packages/nc-gui/lang/zh_CN.json b/packages/nc-gui/lang/zh_CN.json index c179cba894..9cba8448dc 100644 --- a/packages/nc-gui/lang/zh_CN.json +++ b/packages/nc-gui/lang/zh_CN.json @@ -191,6 +191,7 @@ "port": "端口号", "username": "用户名", "password": "密码", + "schemaName": "Schema name", "action": "行动", "actions": "行动", "operation": "操作", diff --git a/packages/nc-gui/lang/zh_HK.json b/packages/nc-gui/lang/zh_HK.json index 8159453dda..baa846cfce 100644 --- a/packages/nc-gui/lang/zh_HK.json +++ b/packages/nc-gui/lang/zh_HK.json @@ -191,6 +191,7 @@ "port": "端口號碼", "username": "用戶名稱", "password": "密碼", + "schemaName": "Schema name", "action": "行動", "actions": "行動", "operation": "操作", diff --git a/packages/nc-gui/lang/zh_TW.json b/packages/nc-gui/lang/zh_TW.json index 21c452555e..161d84c2a6 100644 --- a/packages/nc-gui/lang/zh_TW.json +++ b/packages/nc-gui/lang/zh_TW.json @@ -191,6 +191,7 @@ "port": "連線埠號碼", "username": "使用者名稱", "password": "密碼", + "schemaName": "Schema name", "action": "行動", "actions": "行動", "operation": "操作", From 726064ded55b9d150813829077ed4e47f18f1083 Mon Sep 17 00:00:00 2001 From: Pranav C <pranavxc@gmail.com> Date: Tue, 26 Apr 2022 12:13:44 +0530 Subject: [PATCH 15/39] refactor: show LTAR column name instead of table name in Lookup/Rollup re #1811 #1768 Signed-off-by: Pranav C <pranavxc@gmail.com> --- .../spreadsheet/components/editColumn/lookupOptions.vue | 5 +++-- .../spreadsheet/components/editColumn/rollupOptions.vue | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/nc-gui/components/project/spreadsheet/components/editColumn/lookupOptions.vue b/packages/nc-gui/components/project/spreadsheet/components/editColumn/lookupOptions.vue index 0606047029..2484e2a6bc 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/editColumn/lookupOptions.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/editColumn/lookupOptions.vue @@ -18,9 +18,9 @@ dense > <template #item="{item}"> - <span class="caption"><span class="font-weight-bold"> {{ + <span class="caption"><span class="font-weight-bold">{{ item.column.title }}</span> <small>({{ relationNames[item.col.type] }} {{ item.title || item.table_name - }}</span> <small>({{ relationNames[item.col.type] }}) + }}) </small></span> </template> </v-autocomplete> @@ -74,6 +74,7 @@ export default { c.uidt === UITypes.LinkToAnotherRecord && !c.system ).map(c => ({ col: c.colOptions, + column: c, ...this.tables.find(t => t.id === c.colOptions.fk_related_model_id) })) diff --git a/packages/nc-gui/components/project/spreadsheet/components/editColumn/rollupOptions.vue b/packages/nc-gui/components/project/spreadsheet/components/editColumn/rollupOptions.vue index bae2ede28d..73b9f445c9 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/editColumn/rollupOptions.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/editColumn/rollupOptions.vue @@ -18,9 +18,9 @@ dense > <template #item="{item}"> - <span class="caption"><span class="font-weight-bold"> {{ + <span class="caption"><span class="font-weight-bold">{{ item.column.title }}</span> <small>({{ relationNames[item.col.type] }} {{ item.title || item.table_name - }}</span> <small>({{ relationNames[item.col.type] }}) + }}) </small></span> </template> </v-autocomplete> @@ -98,6 +98,7 @@ export default { c.uidt === UITypes.LinkToAnotherRecord && c.colOptions.type !== 'bt' && !c.system ).map(c => ({ col: c.colOptions, + column: c, ...this.tables.find(t => t.id === c.colOptions.fk_related_model_id) })) From 9dfa2845bb0b51ad9c8edd06cfbfea0ad5d2725d Mon Sep 17 00:00:00 2001 From: mertmit <mertmit99@gmail.com> Date: Tue, 26 Apr 2022 10:40:07 +0300 Subject: [PATCH 16/39] fix: using functions for DATEADD interval Signed-off-by: mertmit <mertmit99@gmail.com> --- .../lib/dataMapper/lib/sql/functionMappings/pg.ts | 13 ++----------- .../dataMapper/lib/sql/functionMappings/sqlite.ts | 4 ++-- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts index ffc5d03d0e..7a72c16e14 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/pg.ts @@ -35,17 +35,8 @@ const pg = { }, DATEADD: ({ fn, knex, pt, colAlias }: MapFnArgs) => { return knex.raw( - `CASE - WHEN CAST(${fn(pt.arguments[0])} AS text) LIKE '%:%' THEN - ${fn(pt.arguments[0])} + INTERVAL '${fn(pt.arguments[1])} - ${String(fn(pt.arguments[2])).replace( - /["']/g, - '' - )}' - ELSE - ${fn(pt.arguments[0])} + INTERVAL '${fn(pt.arguments[1])} - ${String(fn(pt.arguments[2])).replace(/["']/g, '')}' - END${colAlias}` + `${fn(pt.arguments[0])} + (${fn(pt.arguments[1])} || + '${String(fn(pt.arguments[2])).replace(/["']/g, '')}')::interval${colAlias}` ); } }; diff --git a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts index 67bfe7e88b..241924640a 100644 --- a/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts +++ b/packages/nocodb/src/lib/dataMapper/lib/sql/functionMappings/sqlite.ts @@ -64,13 +64,13 @@ const sqlite3 = { STRFTIME('%Y-%m-%d %H:%M', DATETIME(DATETIME(${fn( pt.arguments[0] )}, 'localtime'), - '${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( + ${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} || ' ${String(fn(pt.arguments[2])).replace( /["']/g, '' )}')) ELSE DATE(DATETIME(${fn(pt.arguments[0])}, 'localtime'), - '${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} ${String(fn(pt.arguments[2])).replace( + ${dateIN > 0 ? '+' : ''}${fn(pt.arguments[1])} || ' ${String(fn(pt.arguments[2])).replace( /["']/g, '' )}') From 000952939181bfd870268e99cf36263454a6c4b6 Mon Sep 17 00:00:00 2001 From: mertmit <mertmit99@gmail.com> Date: Tue, 26 Apr 2022 11:05:17 +0300 Subject: [PATCH 17/39] fix: belongs to header tooltip Signed-off-by: mertmit <mertmit99@gmail.com> --- .../project/spreadsheet/components/virtualHeaderCell.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue b/packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue index 63c550fecf..b33dec8fe8 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue @@ -228,7 +228,7 @@ export default { } else if (this.type === 'mm') { return `'${this.childTable}' & '${this.parentTable}' have <br>many to many relation` } else if (this.type === 'bt') { - return `'${this.childColumn.column_name}' belongs to '${this.childTable}'` + return `'${this.column.title}' belongs to '${this.childTable}'` } else if (this.type === 'lk') { return `'${this.childColumn.column_name}' from '${this.childTable}' (${this.childColumn.uidt})` } else if (this.type === 'formula') { From 385d47498ef155f28d50b400283d78fcd7a2c5cb Mon Sep 17 00:00:00 2001 From: mertmit <mertmit99@gmail.com> Date: Tue, 26 Apr 2022 12:56:33 +0300 Subject: [PATCH 18/39] fix: use aliases instead of table/column names on tooltips Signed-off-by: mertmit <mertmit99@gmail.com> --- .../spreadsheet/components/virtualHeaderCell.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue b/packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue index b33dec8fe8..ba4bc46d68 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue @@ -202,20 +202,20 @@ export default { return '' }, childTable() { - if (this.relationMeta?.table_name) { - return this.relationMeta.table_name + if (this.relationMeta?.title) { + return this.relationMeta.title } return '' }, parentTable() { if (this.rels.includes(this.type)) { - return this.meta.table_name + return this.meta.title } return '' }, parentColumn() { if (this.rels.includes(this.type)) { - return this.column.column_name + return this.column.title } return '' }, @@ -230,11 +230,11 @@ export default { } else if (this.type === 'bt') { return `'${this.column.title}' belongs to '${this.childTable}'` } else if (this.type === 'lk') { - return `'${this.childColumn.column_name}' from '${this.childTable}' (${this.childColumn.uidt})` + return `'${this.childColumn.title}' from '${this.childTable}' (${this.childColumn.uidt})` } else if (this.type === 'formula') { return `Formula - ${this.column.colOptions.formula}` } else if (this.type === 'rl') { - return `'${this.childColumn.column_name}' of '${this.childTable}' (${this.childColumn.uidt})` + return `'${this.childColumn.title}' of '${this.childTable}' (${this.childColumn.uidt})` } return '' } From 435d52a45688b0fb137eb4ef294e864272ab6643 Mon Sep 17 00:00:00 2001 From: Naveen MR <oof1lab@gmail.com> Date: Tue, 26 Apr 2022 11:16:31 +0100 Subject: [PATCH 19/39] fix: ID is not required in column types. Signed-off-by: Naveen MR <oof1lab@gmail.com> --- .../components/project/spreadsheet/helpers/uiTypes.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nc-gui/components/project/spreadsheet/helpers/uiTypes.js b/packages/nc-gui/components/project/spreadsheet/helpers/uiTypes.js index e95c4dec3e..693b147017 100644 --- a/packages/nc-gui/components/project/spreadsheet/helpers/uiTypes.js +++ b/packages/nc-gui/components/project/spreadsheet/helpers/uiTypes.js @@ -1,8 +1,8 @@ const uiTypes = [ - { - name: 'ID', - icon: 'mdi-identifier' - }, + // { + // name: 'ID', + // icon: 'mdi-identifier' + // }, { name: 'LinkToAnotherRecord', icon: 'mdi-link-variant', From 5703be36661f6062686bc2b0ff9e5dd9d886de2c Mon Sep 17 00:00:00 2001 From: Naveen MR <oof1lab@gmail.com> Date: Tue, 26 Apr 2022 11:24:11 +0100 Subject: [PATCH 20/39] fix: setting new column to singleline text Signed-off-by: Naveen MR <oof1lab@gmail.com> --- packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts | 13 ++++--- packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts | 35 +++++++++---------- packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts | 33 +++++++++-------- packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts | 13 ++++--- packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts | 11 +++--- 5 files changed, 50 insertions(+), 55 deletions(-) diff --git a/packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts index 617a71e36d..527225cdf0 100644 --- a/packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts +++ b/packages/nocodb-sdk/src/lib/sqlUi/MssqlUi.ts @@ -138,10 +138,10 @@ export class MssqlUi { static getNewColumn(suffix) { return { - column_name: 'title' + suffix, - dt: 'int', + column_name: 'title' + suffix, + dt: 'varchar', dtx: 'specificType', - ct: 'integer(11)', + ct: 'varchar(45)', nrqd: true, rqd: false, ck: false, @@ -152,11 +152,10 @@ export class MssqlUi { clen: 45, np: null, ns: null, - // data_type_x_specific: ' ', - dtxp: '', - dtxs: ' ', + dtxp: '45', + dtxs: '', altered: 1, - uidt: 'Number', + uidt: 'SingleLineText', uip: '', uicn: '' }; diff --git a/packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts index cbc9022936..f639e8a2a4 100644 --- a/packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts +++ b/packages/nocodb-sdk/src/lib/sqlUi/MysqlUi.ts @@ -46,8 +46,8 @@ export class MysqlUi { static getNewTableColumns(): readonly any[] { return [ { - column_name: 'id', - title: 'Id', + column_name: 'id', + title: 'Id', dt: 'int', dtx: 'integer', ct: 'int(11)', @@ -69,8 +69,8 @@ export class MysqlUi { uicn: '' }, { - column_name: 'title', - title: 'Title', + column_name: 'title', + title: 'Title', dt: 'varchar', dtx: 'specificType', ct: 'varchar(45)', @@ -92,8 +92,8 @@ export class MysqlUi { uicn: '' }, { - column_name: 'created_at', - title: 'CreatedAt', + column_name: 'created_at', + title: 'CreatedAt', dt: 'timestamp', dtx: 'specificType', ct: 'varchar(45)', @@ -115,8 +115,8 @@ export class MysqlUi { uicn: '' }, { - column_name: 'updated_at', - title: 'UpdatedAt', + column_name: 'updated_at', + title: 'UpdatedAt', dt: 'timestamp', dtx: 'specificType', ct: 'varchar(45)', @@ -142,10 +142,10 @@ export class MysqlUi { static getNewColumn(suffix) { return { - column_name: 'title' + suffix, - dt: 'int', + column_name: 'title' + suffix, + dt: 'varchar', dtx: 'specificType', - ct: 'integer(11)', + ct: 'varchar(45)', nrqd: true, rqd: false, ck: false, @@ -156,11 +156,10 @@ export class MysqlUi { clen: 45, np: null, ns: null, - // data_type_x_specific: ' ', - dtxp: '11', - dtxs: ' ', + dtxp: '45', + dtxs: '', altered: 1, - uidt: 'Number', + uidt: 'SingleLineText', uip: '', uicn: '' }; @@ -678,14 +677,14 @@ export class MysqlUi { // set headers before settings result for (let i = 0; i < keys.length; i++) { const text = keys[i]; - headers.push({ text, value: text, sortable: false }); + headers.push({text, value: text, sortable: false}); } } else { const keys = Object.keys(result); for (let i = 0; i < keys.length; i++) { const text = keys[i]; if (typeof text !== 'function') { - headers.push({ text, value: text, sortable: false }); + headers.push({text, value: text, sortable: false}); } } result = [result]; @@ -732,7 +731,7 @@ export class MysqlUi { const column = { dp: null, tn, - column_name: keys[i], + column_name: keys[i], cno: keys[i], np: 10, ns: 0, diff --git a/packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts index 93cf063cd0..3f1b14ac2a 100644 --- a/packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts +++ b/packages/nocodb-sdk/src/lib/sqlUi/OracleUi.ts @@ -2,8 +2,8 @@ export class OracleUi { static getNewTableColumns(): any[] { return [ { - column_name: 'id', - title: 'Id', + column_name: 'id', + title: 'Id', dt: 'integer', dtx: 'integer', ct: 'int(11)', @@ -25,8 +25,8 @@ export class OracleUi { uicn: '' }, { - column_name: 'title', - title: 'Title', + column_name: 'title', + title: 'Title', dt: 'varchar', dtx: 'specificType', ct: 'varchar(45)', @@ -88,10 +88,10 @@ export class OracleUi { static getNewColumn(suffix) { return { - column_name: 'title' + suffix, - dt: 'integer', + column_name: 'title' + suffix, + dt: 'varchar', dtx: 'specificType', - ct: 'integer(11)', + ct: 'varchar(45)', nrqd: true, rqd: false, ck: false, @@ -102,11 +102,10 @@ export class OracleUi { clen: 45, np: null, ns: null, - // data_type_x_specific: ' ', - dtxp: '11', - dtxs: ' ', + dtxp: '45', + dtxs: '', altered: 1, - uidt: 'Number', + uidt: 'SingleLineText', uip: '', uicn: '' }; @@ -503,7 +502,7 @@ export class OracleUi { columns.push({ dp: null, tn, - column_name: keys[i], + column_name: keys[i], cno: keys[i], dt: 'int', np: 10, @@ -529,7 +528,7 @@ export class OracleUi { columns.push({ dp: null, tn, - column_name: keys[i], + column_name: keys[i], cno: keys[i], dt: 'float', np: 10, @@ -560,7 +559,7 @@ export class OracleUi { columns.push({ dp: null, tn, - column_name: keys[i], + column_name: keys[i], cno: keys[i], dt: 'varchar', np: 45, @@ -586,7 +585,7 @@ export class OracleUi { columns.push({ dp: null, tn, - column_name: keys[i], + column_name: keys[i], cno: keys[i], dt: 'text', np: null, @@ -616,7 +615,7 @@ export class OracleUi { columns.push({ dp: null, tn, - column_name: keys[i], + column_name: keys[i], cno: keys[i], dt: 'boolean', np: 3, @@ -644,7 +643,7 @@ export class OracleUi { columns.push({ dp: null, tn, - column_name: keys[i], + column_name: keys[i], cno: keys[i], dt: 'json', np: 3, diff --git a/packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts index b847250538..8eab633e57 100644 --- a/packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts +++ b/packages/nocodb-sdk/src/lib/sqlUi/PgUi.ts @@ -202,10 +202,10 @@ export class PgUi { static getNewColumn(suffix) { return { - column_name: 'title' + suffix, - dt: 'int4', + column_name: 'title' + suffix, + dt: 'character varying', dtx: 'specificType', - ct: 'integer(11)', + ct: 'varchar(45)', nrqd: true, rqd: false, ck: false, @@ -216,11 +216,10 @@ export class PgUi { clen: 45, np: null, ns: null, - // data_type_x_specific: ' ', - dtxp: '11', - dtxs: ' ', + dtxp: '45', + dtxs: '', altered: 1, - uidt: 'Number', + uidt: 'SingleLineText', uip: '', uicn: '' }; diff --git a/packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts b/packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts index e612ad88ab..f2dfb426ec 100644 --- a/packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts +++ b/packages/nocodb-sdk/src/lib/sqlUi/SqliteUi.ts @@ -125,10 +125,10 @@ export class SqliteUi { static getNewColumn(suffix) { return { - column_name: 'title' + suffix, - dt: 'integer', + column_name: 'title' + suffix, + dt: 'varchar', dtx: 'specificType', - ct: 'integer(11)', + ct: 'varchar', nrqd: true, rqd: false, ck: false, @@ -139,11 +139,10 @@ export class SqliteUi { clen: 45, np: null, ns: null, - // data_type_x_specific: ' ', dtxp: '', - dtxs: ' ', + dtxs: '', altered: 1, - uidt: 'Number', + uidt: 'SingleLineText', uip: '', uicn: '' }; From 1327db90c3c49e70190135db502ad4e5363320ee Mon Sep 17 00:00:00 2001 From: Pranav C <pranavxc@gmail.com> Date: Tue, 26 Apr 2022 16:16:48 +0530 Subject: [PATCH 21/39] chore: install nocodb-sdk locally in CI/CD Signed-off-by: Pranav C <pranavxc@gmail.com> --- .github/workflows/ci-cd.yml | 12 ++++++++++++ package.json | 1 + 2 files changed, 13 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 88af4f801d..2bfa13470d 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -50,6 +50,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -95,6 +96,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -140,6 +142,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -185,6 +188,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -230,6 +234,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -275,6 +280,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -320,6 +326,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -365,6 +372,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -410,6 +418,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -455,6 +464,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -500,6 +510,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -545,6 +556,7 @@ jobs: with: start: | npm run build:common + npm run install:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d diff --git a/package.json b/package.json index 7783eef1cf..b22e825a96 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ }, "scripts": { "build:common": "cd ./packages/nocodb-sdk; npm install; npm run build", + "install:common": "cd ./packages/nocodb; npm install ../nocodb-sdk; cd ../nc-gui; npm install ../nocodb-sdk", "start:api": "cd ./packages/nocodb; npm install; NC_DISABLE_CACHE=true NC_DISABLE_TELE=true npm run watch:run:cypress", "start:xcdb-api": "cd ./packages/nocodb; npm install; NC_DISABLE_CACHE=true NC_DISABLE_TELE=true NC_INFLECTION=camelize DATABASE_URL=sqlite:../../../scripts/cypress/fixtures/sqlite-sakila/sakila.db npm run watch:run:cypress", "start:api:cache": "cd ./packages/nocodb; npm install; NC_DISABLE_TELE=true npm run watch:run:cypress", From 0a76da2c4cf731475832d77de978d705878ff5c9 Mon Sep 17 00:00:00 2001 From: Naveen MR <oof1lab@gmail.com> Date: Tue, 26 Apr 2022 12:00:45 +0100 Subject: [PATCH 22/39] fix: move the community icons to spreadsheetNavDrawer.vue Signed-off-by: Naveen MR <oof1lab@gmail.com> --- .../nc-gui/components/ProjectTreeView.vue | 209 +++++++++--------- .../project/spreadsheet/components/extras.vue | 12 +- .../components/spreadsheetNavDrawer.vue | 5 +- 3 files changed, 118 insertions(+), 108 deletions(-) diff --git a/packages/nc-gui/components/ProjectTreeView.vue b/packages/nc-gui/components/ProjectTreeView.vue index f77494d607..e88298e989 100644 --- a/packages/nc-gui/components/ProjectTreeView.vue +++ b/packages/nc-gui/components/ProjectTreeView.vue @@ -17,7 +17,7 @@ > {{ $store.getters["project/GtrProjectName"] }} </h3> - <github-star-btn v-else /> + <github-star-btn v-else/> </div> <v-navigation-drawer ref="drawer" @@ -183,19 +183,20 @@ class="body-2 font-weight-medium" v-on="on" > - {{ $t("objects.tables") + {{ + $t("objects.tables") }}<template - v-if="item.children && item.children.length" - > + v-if="item.children && item.children.length" + > ({{ - item.children.filter( - (child) => - !search || - child.name - .toLowerCase() - .includes(search.toLowerCase()) - ).length - }})</template></span> + item.children.filter( + (child) => + !search || + child.name + .toLowerCase() + .includes(search.toLowerCase()) + ).length + }})</template></span> <span v-else class="body-2 font-weight-medium" @@ -210,25 +211,26 @@ v-if="item.type === 'tableDir'" class="body-2 font-weight-medium" > - {{ $t("objects.tables") + {{ + $t("objects.tables") }}<template - v-if="item.children && item.children.length" - > + v-if="item.children && item.children.length" + > ({{ - item.children.filter( - (child) => - !search || - child.name - .toLowerCase() - .includes(search.toLowerCase()) - ).length - }})</template></span> + item.children.filter( + (child) => + !search || + child.name + .toLowerCase() + .includes(search.toLowerCase()) + ).length + }})</template></span> <span v-else class="caption font-weight-regular"> {{ item.name }}</span> </template> </v-list-item-title> - <v-spacer /> + <v-spacer/> <v-tooltip bottom> <template #activator="{ on }"> @@ -251,8 +253,8 @@ class="caption" >Add new <span class="text-capitalize">{{ - item.type.slice(0, -3) - }}</span></span> + item.type.slice(0, -3) + }}</span></span> </v-tooltip> </template> @@ -340,13 +342,13 @@ </span> </template> <span class="caption">{{ - child.creator_tooltip - }}</span> + child.creator_tooltip + }}</span> </v-tooltip> <span v-else class="caption">{{ child.name }}</span> </v-list-item-title> <template v-if="child.type === 'table'"> - <v-spacer /> + <v-spacer/> <div class="action d-flex" @click.stop> <v-menu> <template #activator="{ on }"> @@ -481,7 +483,7 @@ /> </div> <div class="pr-3 advance-menu d-none" :class="{ 'pl-3': !mini }"> - <v-divider v-if="_isUIAllowed('treeViewProjectSettings')" /> + <v-divider v-if="_isUIAllowed('treeViewProjectSettings')"/> <v-list v-if="_isUIAllowed('treeViewProjectSettings')" @@ -492,8 +494,8 @@ <v-list-item-title> <!-- Settings --> <span class="body-2 font-weight-medium">{{ - $t("activity.settings") - }}</span> + $t("activity.settings") + }}</span> <v-tooltip top> <template #activator="{ on }"> <x-icon @@ -532,8 +534,8 @@ <!-- App Store --> <v-list-item-title> <span class="font-weight-regular caption">{{ - $t("title.appStore") - }}</span> + $t("title.appStore") + }}</span> </v-list-item-title> </v-list-item> </template> @@ -558,8 +560,8 @@ <!-- Team & Auth --> <v-list-item-title> <span class="font-weight-regular caption">{{ - $t("title.teamAndAuth") - }}</span> + $t("title.teamAndAuth") + }}</span> </v-list-item-title> </v-list-item> </template> @@ -583,8 +585,8 @@ <!-- Project Metadata --> <v-list-item-title> <span class="font-weight-regular caption">{{ - $t("title.projMeta") - }}</span> + $t("title.projMeta") + }}</span> </v-list-item-title> </v-list-item> </template> @@ -609,8 +611,8 @@ <!-- Project Metadata --> <v-list-item-title> <span class="font-weight-regular caption">{{ - $t("title.audit") - }}</span> + $t("title.audit") + }}</span> </v-list-item-title> </v-list-item> </template> @@ -619,14 +621,14 @@ </v-tooltip> </template> </v-list> - <v-divider /> + <v-divider/> <v-list v-if="_isUIAllowed('previewAs') || previewAs" dense> <v-list-item> <!-- Preview as --> <span class="body-2 font-weight-medium">{{ - $t("activity.previewAs") - }}</span> + $t("activity.previewAs") + }}</span> <v-icon small class="ml-1"> mdi-drama-masks </v-icon> @@ -668,18 +670,31 @@ </v-icon> <!-- Reset Preview --> <span class="caption nc-preview-reset">{{ - $t("activity.resetReview") - }}</span> + $t("activity.resetReview") + }}</span> </v-list-item> </template> </v-list> </v-list> </div> - <template v-if="_isUIAllowed('settings')"> - <v-divider /> - <div class="pt-3 pl-5 pr-3 d-flex align-center pb-2"> + + <v-divider/> + <div + v-t="['e:api-docs']" + class="caption pointer nc-docs pb-2 pl-5 pr-3 pt-2 d-flex align-center" + @click="openLink(apiLink)" + > + <v-icon small class="mr-2"> + mdi-api + </v-icon> + {{ $t('title.apiDocs') }} + </div> + + + <template v-if="_isUIAllowed('settings')"> + <div class="pl-5 pr-3 d-flex align-center pb-2"> <settings-modal> <template #default="{ click }"> <div @@ -697,18 +712,9 @@ </div> </template> - <div - v-t="['e:api-docs']" - class="caption pointer nc-docs pb-3 pl-5 pr-3 pt-2 d-flex align-center" - @click="openLink(apiLink)" - > - <v-icon small class="mr-2"> - mdi-api - </v-icon> - {{ $t('title.apiDocs') }} - </div> - <v-divider /> - <extras class="pl-1" /> + + <!-- <v-divider/>--> +<!-- <extras class="pl-1"/>--> </div> </v-navigation-drawer> @@ -776,7 +782,7 @@ <script> /* eslint-disable */ -import { mapMutations, mapGetters, mapActions } from "vuex"; +import {mapMutations, mapGetters, mapActions} from "vuex"; import rightClickOptions from "../helpers/rightClickOptions"; import rightClickOptionsSub from "../helpers/rightClickOptionsSub"; @@ -784,11 +790,11 @@ import icons from "../helpers/treeViewIcons"; import textDlgSubmitCancel from "./utils/dlgTextSubmitCancel"; import dlgLabelSubmitCancel from "./utils/dlgLabelSubmitCancel"; -import { copyTextToClipboard } from "../helpers/xutils"; +import {copyTextToClipboard} from "../helpers/xutils"; import DlgTableCreate from "@/components/utils/dlgTableCreate"; import DlgViewCreate from "@/components/utils/dlgViewCreate"; import SponsorMini from "@/components/sponsorMini"; -import { validateTableName } from "~/helpers"; +import {validateTableName} from "~/helpers"; import ExcelImport from "~/components/import/excelImport"; import draggable from "vuedraggable"; @@ -831,9 +837,9 @@ export default { commenter: "mdi-comment-account-outline", }, rolesList: [ - { title: "editor" }, - { title: "commenter" }, - { title: "viewer" }, + {title: "editor"}, + {title: "commenter"}, + {title: "viewer"}, ], showSqlClient: false, nestedMenu: {}, @@ -862,7 +868,7 @@ export default { x: 0, y: 0, menuItem: null, - menu: [{ title: "Execute" }], + menu: [{title: "Execute"}], icons, tree: [], active: [], @@ -906,8 +912,8 @@ export default { }, }), computed: { - apiLink(){ - return new URL(`/api/v1/db/meta/projects/${this.projectId}/swagger`, this.$store.state.project.projectInfo && this.$store.state.project.projectInfo.ncSiteUrl) + apiLink() { + return new URL(`/api/v1/db/meta/projects/${this.projectId}/swagger`, this.$store.state.project.projectInfo && this.$store.state.project.projectInfo.ncSiteUrl) }, previewAs: { get() { @@ -989,7 +995,7 @@ export default { "order", (children[event.moved.newIndex - 1].order + children[event.moved.newIndex + 1].order) / - 2 + 2 ); } @@ -1051,7 +1057,7 @@ export default { name: "App Store", key: `appStore`, }; - item._nodes = { env: "_noco" }; + item._nodes = {env: "_noco"}; item._nodes.type = "appStore"; this.$store.dispatch("tabs/ActAddTab", item); } @@ -1092,7 +1098,7 @@ export default { name: `${this.$t("title.teamAndAuth")} `, key: `roles`, }; - item._nodes = { env: "_noco" }; + item._nodes = {env: "_noco"}; item._nodes.type = "roles"; this.$store.dispatch("tabs/ActAddTab", item); } @@ -1108,7 +1114,7 @@ export default { name: `${this.$t("title.metaMgmt")}`, key: `disableOrEnableModel`, }; - item._nodes = { env: "_noco" }; + item._nodes = {env: "_noco"}; item._nodes.type = "disableOrEnableModel"; this.$store.dispatch("tabs/ActAddTab", item); } @@ -1151,8 +1157,8 @@ export default { const el = this.$refs.drawer.$el; this.navigation.width = this.$refs.drawer.width = - el.style.width = - "50px"; + el.style.width = + "50px"; this.miniExpanded = false; } }, @@ -1305,15 +1311,15 @@ export default { if ("toast" in this.$route.query) { this.$toast - .success( - `Successfully generated ${( - this.$store.getters["project/GtrProjectType"] || "" - ).toUpperCase()} APIs`, - { - position: "top-center", - } - ) - .goAway(5000); + .success( + `Successfully generated ${( + this.$store.getters["project/GtrProjectType"] || "" + ).toUpperCase()} APIs`, + { + position: "top-center", + } + ) + .goAway(5000); } try { @@ -1332,12 +1338,12 @@ export default { (n) => n.type === `${this.$route.query.type}Dir` ); await this.addTab( - { ...(node || this.listViewArr[0]) }, + {...(node || this.listViewArr[0])}, false, true ); } else { - await this.addTab({ ...this.listViewArr[0] }, false, true); + await this.addTab({...this.listViewArr[0]}, false, true); } } } catch (error) { @@ -1515,7 +1521,7 @@ export default { dbAlias: item._nodes.dbAlias, }, func, - { tn: item.name }, + {tn: item.name}, ]); if (result && result.data) { copyTextToClipboard(result.data, "selection"); @@ -1523,7 +1529,7 @@ export default { copyTextToClipboard("Example String", "selection"); } - let sqlClientNode = { ...item._nodes }; + let sqlClientNode = {...item._nodes}; let newItem = { _nodes: sqlClientNode, }; @@ -1559,8 +1565,8 @@ export default { }); } catch (e) { this.$toast - .error(await this._extractSdkResponseErrorMsg(e)) - .goAway(3000); + .error(await this._extractSdkResponseErrorMsg(e)) + .goAway(3000); return; } await this.removeTabsByName(item); @@ -1833,7 +1839,7 @@ export default { dbAlias: item._nodes.dbAlias, }, "viewRead", - { view_name: item._nodes.view_name }, + {view_name: item._nodes.view_name}, ]); await this.$store.dispatch("sqlMgr/ActSqlOpPlus", [ @@ -1942,7 +1948,8 @@ export default { this.loadDefaultTabs(true); // this.loadRoles(); }, - beforeCreate() {}, + beforeCreate() { + }, mounted() { // this.setBorderWidth(); // this.setEvents(); @@ -2021,9 +2028,9 @@ export default { } /deep/ - .v-list-group - .v-list-group__header - .v-list-item__icon.v-list-group__header__append-icon { +.v-list-group +.v-list-group__header +.v-list-item__icon.v-list-group__header__append-icon { min-width: auto; } @@ -2045,16 +2052,16 @@ export default { } /deep/ - .nc-table-list-filter.theme--light.v-text-field - > .v-input__control - > .v-input__slot:before { +.nc-table-list-filter.theme--light.v-text-field +> .v-input__control +> .v-input__slot:before { border-top-color: rgba(0, 0, 0, 0.12) !important; } /deep/ - .nc-table-list-filter.theme--dark.v-text-field - > .v-input__control - > .v-input__slot:before { +.nc-table-list-filter.theme--dark.v-text-field +> .v-input__control +> .v-input__slot:before { border-top-color: rgba(255, 255, 255, 0.12) !important; } diff --git a/packages/nc-gui/components/project/spreadsheet/components/extras.vue b/packages/nc-gui/components/project/spreadsheet/components/extras.vue index b4a8b69b7d..3b2a187f03 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/extras.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/extras.vue @@ -31,20 +31,20 @@ dense > <v-list-item> - <div class="d-flex justify-space-between d-100 pr-2"> - <v-icon v-t="['e:community:discord']" class="mr-1" size="22" :color="textColors[0]" @click="open('https://discord.gg/5RgZmkW')"> + <div class="justify-space-between d-100 pr-2"> + <v-icon v-t="['e:community:discord']" size="22" :color="textColors[0]" @click="open('https://discord.gg/5RgZmkW')"> mdi-discord </v-icon> - <v-icon v-t="['e:community:discourse']" class="mr-1 discourse" size="22" :color="textColors[0]" @click="open('https://community.nocodb.com/')"> + <v-icon v-t="['e:community:discourse']" class=" discourse" size="22" :color="textColors[0]" @click="open('https://community.nocodb.com/')"> mdi-discourse </v-icon> - <v-icon v-t="['e:community:reddit']" class="mr-1" size="22" color="#ff4600" @click="open('https://www.reddit.com/r/NocoDB/')"> + <v-icon v-t="['e:community:reddit']" size="22" color="#ff4600" @click="open('https://www.reddit.com/r/NocoDB/')"> mdi-reddit </v-icon> - <v-icon v-t="['e:community:twitter']" class="mr-1" size="22" :color="textColors[1]" @click="open('https://twitter.com/NocoDB')"> + <v-icon v-t="['e:community:twitter']" size="22" :color="textColors[1]" @click="open('https://twitter.com/NocoDB')"> mdi-twitter </v-icon> - <v-icon v-t="['e:community:book-demo']" class="mr-1" size="22" :color="textColors[3]" @click="open('https://calendly.com/nocodb-meeting')"> + <v-icon v-t="['e:community:book-demo']" size="22" :color="textColors[3]" @click="open('https://calendly.com/nocodb-meeting')"> mdi-calendar-month </v-icon> </div> diff --git a/packages/nc-gui/components/project/spreadsheet/components/spreadsheetNavDrawer.vue b/packages/nc-gui/components/project/spreadsheet/components/spreadsheetNavDrawer.vue index 6b4b97ada8..f8552449dd 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/spreadsheetNavDrawer.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/spreadsheetNavDrawer.vue @@ -270,7 +270,10 @@ </v-icon> <!-- <extras />--> - <sponsor-mini nav /> + <v-divider/> + <extras class="pl-1"/> + +<!-- <sponsor-mini nav />--> </div> <!--<div class="text-center"> <v-hover > From 6a58e77292d58b853d8462ae3ca730a17a1dcaaa Mon Sep 17 00:00:00 2001 From: Naveen MR <oof1lab@gmail.com> Date: Tue, 26 Apr 2022 12:09:35 +0100 Subject: [PATCH 23/39] fix: removing language from themes Signed-off-by: Naveen MR <oof1lab@gmail.com> --- .../project/settings/appearance.vue | 54 ++++++++----------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/packages/nc-gui/components/project/settings/appearance.vue b/packages/nc-gui/components/project/settings/appearance.vue index f4aa319712..7608f319ad 100644 --- a/packages/nc-gui/components/project/settings/appearance.vue +++ b/packages/nc-gui/components/project/settings/appearance.vue @@ -60,38 +60,6 @@ </v-tooltip> </td> </tr>--> - <tr> - <td>Show M2M Tables</td> - <td> - <v-tooltip bottom> - <template #activator="{ on }"> - <v-checkbox - v-model="includeM2M" - v-t="[`c:themes:show-m2m-tables`]" - x-large - color="primary" - v-on="on" - > - mdi-table-network - </v-checkbox> - </template> - Include/Exclude M2M tables - </v-tooltip> - </td> - </tr> - <tr> - <td>Language</td> - <td> - <v-radio-group v-model="language" row> - <v-radio - v-for="{label,value} in languages" - :key="value" - :label="label" - :value="value" - /> - </v-radio-group> - </td> - </tr> <tr> <td>Themes</td> <td class="pa-1"> @@ -158,6 +126,28 @@ </v-list> </td> </tr> + + <tr> + <td>Show M2M Tables</td> + <td> + <v-tooltip bottom> + <template #activator="{ on }"> + <v-checkbox + v-model="includeM2M" + v-t="[`c:themes:show-m2m-tables`]" + x-large + color="primary" + v-on="on" + > + mdi-table-network + </v-checkbox> + </template> + Include/Exclude M2M tables + </v-tooltip> + </td> + </tr> + + </tbody> </template> </v-simple-table> From 039b728d049c486701a25bff7386f9d0c23d5641 Mon Sep 17 00:00:00 2001 From: Naveen MR <oof1lab@gmail.com> Date: Tue, 26 Apr 2022 12:15:27 +0100 Subject: [PATCH 24/39] fix: title of API docs Signed-off-by: Naveen MR <oof1lab@gmail.com> --- packages/nocodb/src/lib/noco/meta/api/swagger/swaggerHtml.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/noco/meta/api/swagger/swaggerHtml.ts b/packages/nocodb/src/lib/noco/meta/api/swagger/swaggerHtml.ts index af2d3f5e93..9d50dc0258 100644 --- a/packages/nocodb/src/lib/noco/meta/api/swagger/swaggerHtml.ts +++ b/packages/nocodb/src/lib/noco/meta/api/swagger/swaggerHtml.ts @@ -1,7 +1,7 @@ export default `<!DOCTYPE html> <html> <head> - <title>XC Swagger UI + NocoDB : API Docs From d9b543e77f6721c8b502c7e333de32273ec32a25 Mon Sep 17 00:00:00 2001 From: Naveen MR Date: Tue, 26 Apr 2022 12:27:54 +0100 Subject: [PATCH 25/39] fix: at home - swagger api docs not required. Signed-off-by: Naveen MR --- packages/nc-gui/layouts/default.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nc-gui/layouts/default.vue b/packages/nc-gui/layouts/default.vue index e473ca124f..f2222e2f5b 100644 --- a/packages/nc-gui/layouts/default.vue +++ b/packages/nc-gui/layouts/default.vue @@ -160,6 +160,7 @@ Date: Tue, 26 Apr 2022 12:38:27 +0100 Subject: [PATCH 27/39] fix: let how to translate be pointed to i18n docs Signed-off-by: Naveen MR --- packages/nc-gui/components/utils/language.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui/components/utils/language.vue b/packages/nc-gui/components/utils/language.vue index 490f759b4d..b921431e75 100644 --- a/packages/nc-gui/components/utils/language.vue +++ b/packages/nc-gui/components/utils/language.vue @@ -24,7 +24,7 @@ From 16c8ed49e664e5f460ece896a9e51cbcdd0450d8 Mon Sep 17 00:00:00 2001 From: Naveen MR Date: Tue, 26 Apr 2022 12:44:59 +0100 Subject: [PATCH 28/39] fix: icon for api docs Signed-off-by: Naveen MR --- packages/nc-gui/components/ProjectTreeView.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui/components/ProjectTreeView.vue b/packages/nc-gui/components/ProjectTreeView.vue index e88298e989..7da30e6573 100644 --- a/packages/nc-gui/components/ProjectTreeView.vue +++ b/packages/nc-gui/components/ProjectTreeView.vue @@ -686,8 +686,8 @@ class="caption pointer nc-docs pb-2 pl-5 pr-3 pt-2 d-flex align-center" @click="openLink(apiLink)" > - - mdi-api + + mdi-open-in-new {{ $t('title.apiDocs') }} From de8fd072aef8d30b1aefbf7bb7ddb811404b9f07 Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Tue, 26 Apr 2022 19:00:15 +0530 Subject: [PATCH 29/39] chore: disable nocodb-sdk local installation in ci-cd Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .github/workflows/ci-cd.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 2bfa13470d..88af4f801d 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -50,7 +50,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -96,7 +95,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -142,7 +140,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -188,7 +185,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/cypress/docker-compose-pg.yml up -d @@ -234,7 +230,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -280,7 +275,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -326,7 +320,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -372,7 +365,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -418,7 +410,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -464,7 +455,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -510,7 +500,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d @@ -556,7 +545,6 @@ jobs: with: start: | npm run build:common - npm run install:common npm run start:xcdb-api:cache npm run start:web docker-compose -f ./scripts/docker-compose-cypress.yml up -d From e8ca19a1c6749a3947b6690ec7d13cb0ba604ea2 Mon Sep 17 00:00:00 2001 From: Wing-Kam Wong Date: Wed, 27 Apr 2022 14:21:28 +0800 Subject: [PATCH 30/39] fix: storage adapter issue Signed-off-by: Wing-Kam Wong --- packages/nocodb/src/lib/noco/meta/helpers/NcPluginMgrv2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nocodb/src/lib/noco/meta/helpers/NcPluginMgrv2.ts b/packages/nocodb/src/lib/noco/meta/helpers/NcPluginMgrv2.ts index e6b3ac0a1d..0d8ec41526 100644 --- a/packages/nocodb/src/lib/noco/meta/helpers/NcPluginMgrv2.ts +++ b/packages/nocodb/src/lib/noco/meta/helpers/NcPluginMgrv2.ts @@ -123,7 +123,7 @@ class NcPluginMgrv2 { } await plugin.init(pluginData?.input); - return plugin.adapter as IStorageAdapter; + return plugin.getAdapter(); } public static async emailAdapter( From f220fb65bb929ea764ad5da89763328a2e5c9a0e Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Wed, 27 Apr 2022 14:06:40 +0530 Subject: [PATCH 31/39] test/cypress: UI corrections Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- scripts/cypress/integration/spec/roleValidation.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cypress/integration/spec/roleValidation.spec.js b/scripts/cypress/integration/spec/roleValidation.spec.js index e4412d015e..de509a4b07 100644 --- a/scripts/cypress/integration/spec/roleValidation.spec.js +++ b/scripts/cypress/integration/spec/roleValidation.spec.js @@ -214,7 +214,7 @@ export function _editComment(roleType, previewMode) { // Rest: can create/edit export function _viewMenu(roleType, previewMode) { let columnName = "City"; - let navDrawListCnt = 1; + let navDrawListCnt = 2; // Download CSV let actionsMenuItemsCnt = 1; @@ -231,7 +231,7 @@ export function _viewMenu(roleType, previewMode) { // Owner, Creator will have two navigation drawer (on each side of center panel) if (roleType == "owner" || roleType == "creator") { - navDrawListCnt = 2; + navDrawListCnt = 3; // Download CSV / Upload CSV / Shared View List / Webhook actionsMenuItemsCnt = 4; } else if (roleType == "editor") { From 0611c26e0e78710d8a14f7984a61ea21d3c3cf3c Mon Sep 17 00:00:00 2001 From: Pranav C Date: Tue, 26 Apr 2022 17:35:49 +0530 Subject: [PATCH 32/39] fix(gui): block table deletion if there is a relation exist Signed-off-by: Pranav C --- packages/nc-gui/components/project/table.vue | 108 +++++++++++-------- 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/packages/nc-gui/components/project/table.vue b/packages/nc-gui/components/project/table.vue index e5399cb3ba..828964e6d1 100644 --- a/packages/nc-gui/components/project/table.vue +++ b/packages/nc-gui/components/project/table.vue @@ -14,11 +14,12 @@ >