Browse Source

fix conflicts

pull/4140/head
flisowna 2 years ago
parent
commit
867a3a23cc
  1. 2
      .github/workflows/publish-dev-docs.yml
  2. 8
      .github/workflows/release-docker.yml
  3. 4
      .github/workflows/release-draft.yml
  4. 2
      .github/workflows/release-executables.yml
  5. 6
      .github/workflows/release-nightly-dev.yml
  6. 9
      .github/workflows/release-nocodb.yml
  7. 4
      .github/workflows/release-pr.yml
  8. 166
      packages/nc-cli/package-lock.json
  9. 9
      packages/nc-cli/package.json
  10. 23
      packages/nc-cli/src/index.ts
  11. 23
      packages/nc-cli/src/lib/CliMgr.ts
  12. 23
      packages/nc-cli/src/lib/mgr/AppMgr.ts
  13. 23
      packages/nc-cli/src/lib/mgr/Client.ts
  14. 23
      packages/nc-cli/src/lib/mgr/ComponentMgr.ts
  15. 23
      packages/nc-cli/src/lib/mgr/DockerMgr.ts
  16. 23
      packages/nc-cli/src/lib/mgr/InstantMgr.ts
  17. 23
      packages/nc-cli/src/lib/mgr/MigrationMgr.ts
  18. 23
      packages/nc-cli/src/lib/mgr/ModelMgr.ts
  19. 27
      packages/nc-cli/src/lib/mgr/NewMgr.ts
  20. 23
      packages/nc-cli/src/lib/mgr/OldNewMgr.ts
  21. 23
      packages/nc-cli/src/lib/mgr/PermissionsMgr.ts
  22. 23
      packages/nc-cli/src/lib/mgr/PermissionsMgrJs.ts
  23. 23
      packages/nc-cli/src/lib/mgr/SocialMgr.ts
  24. 23
      packages/nc-cli/src/lib/mgr/SocialText.ts
  25. 23
      packages/nc-cli/src/lib/mgr/TryMgr.ts
  26. 23
      packages/nc-cli/src/lib/mgr/XcInstantMgr.ts
  27. 23
      packages/nc-cli/src/lib/prompts/Menu.ts
  28. 23
      packages/nc-cli/src/lib/prompts/RunOrDownload.ts
  29. 23
      packages/nc-cli/src/lib/util/Lang.ts
  30. 23
      packages/nc-cli/src/lib/util/Locales.ts
  31. 23
      packages/nc-cli/src/lib/util/Util.ts
  32. 23
      packages/nc-cli/src/lib/util/config.ts
  33. 1
      packages/nc-gui/.eslintrc.js
  34. 1
      packages/nc-gui/components.d.ts
  35. 102
      packages/nc-gui/components/api-client/Headers.vue
  36. 2
      packages/nc-gui/components/cell/Checkbox.vue
  37. 4
      packages/nc-gui/components/cell/DatePicker.vue
  38. 2
      packages/nc-gui/components/cell/DateTimePicker.vue
  39. 28
      packages/nc-gui/components/cell/Duration.vue
  40. 23
      packages/nc-gui/components/cell/MultiSelect.vue
  41. 23
      packages/nc-gui/components/cell/SingleSelect.vue
  42. 6
      packages/nc-gui/components/cell/Text.vue
  43. 2
      packages/nc-gui/components/cell/TimePicker.vue
  44. 23
      packages/nc-gui/components/cell/Url.vue
  45. 2
      packages/nc-gui/components/cell/YearPicker.vue
  46. 16
      packages/nc-gui/components/cell/attachment/Modal.vue
  47. 2
      packages/nc-gui/components/cell/attachment/utils.ts
  48. 395
      packages/nc-gui/components/dlg/QuickImport.vue
  49. 7
      packages/nc-gui/components/erd/ConfigPanel.vue
  50. 6
      packages/nc-gui/components/erd/Flow.vue
  51. 4
      packages/nc-gui/components/erd/HistogramPanel.vue
  52. 4
      packages/nc-gui/components/erd/RelationEdge.vue
  53. 2
      packages/nc-gui/components/erd/TableNode.vue
  54. 2
      packages/nc-gui/components/general/Overlay.vue
  55. 2
      packages/nc-gui/components/general/language/Menu.vue
  56. 2
      packages/nc-gui/components/shared-view/Gallery.vue
  57. 2
      packages/nc-gui/components/shared-view/Grid.vue
  58. 2
      packages/nc-gui/components/shared-view/Kanban.vue
  59. 4
      packages/nc-gui/components/smartsheet/Cell.vue
  60. 33
      packages/nc-gui/components/smartsheet/Gallery.vue
  61. 27
      packages/nc-gui/components/smartsheet/Grid.vue
  62. 3
      packages/nc-gui/components/smartsheet/Kanban.vue
  63. 4
      packages/nc-gui/components/smartsheet/Row.vue
  64. 24
      packages/nc-gui/components/smartsheet/TableDataCell.vue
  65. 26
      packages/nc-gui/components/smartsheet/expanded-form/Detached.vue
  66. 2
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  67. 6
      packages/nc-gui/components/smartsheet/sidebar/MenuTop.vue
  68. 7
      packages/nc-gui/components/smartsheet/sidebar/RenameableMenuItem.vue
  69. 2
      packages/nc-gui/components/smartsheet/toolbar/MoreActions.vue
  70. 2
      packages/nc-gui/components/smartsheet/toolbar/ShareView.vue
  71. 2
      packages/nc-gui/components/smartsheet/toolbar/ViewActions.vue
  72. 10
      packages/nc-gui/components/tabs/Smartsheet.vue
  73. 403
      packages/nc-gui/components/template/Editor.vue
  74. 2
      packages/nc-gui/components/virtual-cell/BelongsTo.vue
  75. 4
      packages/nc-gui/components/virtual-cell/Formula.vue
  76. 2
      packages/nc-gui/components/virtual-cell/HasMany.vue
  77. 2
      packages/nc-gui/components/virtual-cell/Lookup.vue
  78. 2
      packages/nc-gui/components/virtual-cell/ManyToMany.vue
  79. 41
      packages/nc-gui/components/virtual-cell/components/ItemChip.vue
  80. 4
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  81. 43
      packages/nc-gui/composables/useDialog/index.ts
  82. 44
      packages/nc-gui/composables/useExpandedFormDetached/index.ts
  83. 2
      packages/nc-gui/composables/useMultiSelect/index.ts
  84. 8
      packages/nc-gui/composables/useRoles/index.ts
  85. 2
      packages/nc-gui/composables/useSharedFormViewStore.ts
  86. 14
      packages/nc-gui/composables/useSmartsheetStore.ts
  87. 18
      packages/nc-gui/composables/useViewData.ts
  88. 2
      packages/nc-gui/context/index.ts
  89. 34
      packages/nc-gui/lang/fr.json
  90. 26
      packages/nc-gui/lang/it.json
  91. 372
      packages/nc-gui/lang/pl.json
  92. 58
      packages/nc-gui/lang/zh-Hans.json
  93. 2
      packages/nc-gui/layouts/base.vue
  94. 5
      packages/nc-gui/lib/types.ts
  95. 473
      packages/nc-gui/package-lock.json
  96. 33
      packages/nc-gui/pages/[projectType]/form/[viewId]/index.vue
  97. 24
      packages/nc-gui/pages/[projectType]/form/[viewId]/index/survey.vue
  98. 18
      packages/nc-gui/pages/[projectType]/view/[viewId].vue
  99. 3
      packages/nc-gui/pages/index/index/create-external.vue
  100. 5
      packages/nc-gui/pages/index/index/user.vue
  101. Some files were not shown because too many files have changed in this diff Show More

2
.github/workflows/publish-dev-docs.yml

@ -35,7 +35,7 @@ jobs:
with:
source_file: 'packages/noco-docs/dist/'
clear_folder: 'docs/dist'
destination_repo: 'nocodb/noco-docs'
destination_repo: 'nocodb/noco-docs-dev'
destination_folder: 'docs'
user_email: 'oof1lab@gmail.com'
user_name: 'o1lab'

8
.github/workflows/release-docker.yml

@ -60,10 +60,10 @@ jobs:
DOCKER_REPOSITORY=${DOCKER_REPOSITORY}-timely
fi
fi
echo "::set-output name=DOCKER_REPOSITORY::${DOCKER_REPOSITORY}"
echo "::set-output name=DOCKER_BUILD_TAG::${DOCKER_BUILD_TAG}"
echo ${DOCKER_REPOSITORY}
echo ${DOCKER_BUILD_TAG}
echo "DOCKER_REPOSITORY=${DOCKER_REPOSITORY}" >> $GITHUB_OUTPUT
echo "DOCKER_BUILD_TAG=${DOCKER_BUILD_TAG}" >> $GITHUB_OUTPUT
echo DOCKER_REPOSITORY: ${DOCKER_REPOSITORY}
echo DOCKER_BUILD_TAG: ${DOCKER_BUILD_TAG}
- name: Checkout
uses: actions/checkout@v3

4
.github/workflows/release-draft.yml

@ -53,7 +53,7 @@ jobs:
if [[ ${{ github.event.inputs.tagHeadSHA || inputs.tagHeadSHA }} == "Y" ]]; then
TARGET_SHA=$(git rev-list -n 1 HEAD | tail -1)
fi
echo "::set-output name=TARGET_SHA::${TARGET_SHA}"
echo "TARGET_SHA=${TARGET_SHA}" >> $GITHUB_OUTPUT
echo "Setting TARGET_SHA: ${TARGET_SHA}"
- name: Create tag
uses: actions/github-script@v3
@ -66,7 +66,7 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
ref: "refs/tags/${{ github.event.inputs.tag || inputs.tag }}",
sha: "${{steps.get-sha.outputs.TARGET_SHA}}"
sha: "${{ steps.get-sha.outputs.TARGET_SHA }}"
})
- uses: actions/setup-node@v3
with:

2
.github/workflows/release-executables.yml

@ -194,7 +194,7 @@ jobs:
cp ./mac-dist/Noco-macos-x64 ./mac-dist/nocodb
tar -czf ./mac-dist/nocodb.tar.gz ./mac-dist/nocodb
rm ./mac-dist/nocodb
echo "::set-output name=CHECKSUM::$(shasum -a 256 ./mac-dist/nocodb.tar.gz | awk '{print $1}')"
echo "CHECKSUM=$(shasum -a 256 ./mac-dist/nocodb.tar.gz | awk '{print $1}')" >> $GITHUB_OUTPUT
id: compress

6
.github/workflows/release-nightly-dev.yml

@ -26,9 +26,9 @@ jobs:
if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then
IS_DAILY='N'
fi
echo "::set-output name=NIGHTLY_BUILD_TAG::${TAG_NAME}"
echo "::set-output name=IS_DAILY::${IS_DAILY}"
echo "::set-output name=CURRENT_VERSION::${CURRENT_VERSION}"
echo "NIGHTLY_BUILD_TAG=${TAG_NAME}" >> $GITHUB_OUTPUT
echo "IS_DAILY=${IS_DAILY}" >> $GITHUB_OUTPUT
echo "CURRENT_VERSION=${CURRENT_VERSION}" >> $GITHUB_OUTPUT
- name: verify-tag
run: |
echo ${{ steps.tag-step.outputs.NIGHTLY_BUILD_TAG }}

9
.github/workflows/release-nocodb.yml

@ -45,13 +45,12 @@ jobs:
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}"
echo "TARGET_TAG=${TARGET_TAG}" >> $GITHUB_OUTPUT
echo "PREV_TAG=${PREV_TAG}" >> $GITHUB_OUTPUT
- name: Verify
run : |
echo ${{ steps.process-input.outputs.target_tag }}
echo TARGET_TAG: ${{ steps.process-input.outputs.target_tag }}
echo PREV_TAG: ${{ steps.process-input.outputs.prev_tag }}
# Merge develop to master
pr-to-master:

4
.github/workflows/release-pr.yml

@ -35,8 +35,8 @@ jobs:
CURRENT_VERSION=$(basename $(curl -fs -o/dev/null -w %{redirect_url} https://github.com/nocodb/nocodb/releases/latest))
# Construct tag name
TAG_NAME=pr-${PR_NUMBER}-${CURRENT_DATE}-${CURRENT_TIME}
echo "::set-output name=TARGET_TAG::${TAG_NAME}"
echo "::set-output name=CURRENT_VERSION::${CURRENT_VERSION}"
echo "TARGET_TAG=${TAG_NAME}" >> $GITHUB_OUTPUT
echo "CURRENT_VERSION=${CURRENT_VERSION}" >> $GITHUB_OUTPUT
- name: verify-tag
run: |
echo ${{ steps.tag-step.outputs.TARGET_TAG }}

166
packages/nc-cli/package-lock.json generated

@ -1,12 +1,12 @@
{
"name": "create-nocodb-app",
"version": "0.1.26",
"version": "0.1.28",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "create-nocodb-app",
"version": "0.1.26",
"version": "0.1.28",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
@ -796,6 +796,64 @@
"node": ">=4.0"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
"integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.9"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
"integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.14",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
"integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -1214,9 +1272,9 @@
}
},
"node_modules/@xmldom/xmldom": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz",
"integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==",
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.6.tgz",
"integrity": "sha512-HHXP9hskkFQHy8QxxUXkS7946FFIhYVfGqsk0WLwllmexN9x/+R4UBLvurHEuyXRfVEObVR8APuQehykLviwSQ==",
"engines": {
"node": ">=10.0.0"
}
@ -14042,13 +14100,14 @@
}
},
"node_modules/terser": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz",
"integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==",
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map": "~0.7.2",
"source-map-support": "~0.5.20"
},
"bin": {
@ -14056,14 +14115,6 @@
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"acorn": "^8.5.0"
},
"peerDependenciesMeta": {
"acorn": {
"optional": true
}
}
},
"node_modules/terser-webpack-plugin": {
@ -14118,15 +14169,6 @@
"node": ">=0.10.0"
}
},
"node_modules/terser/node_modules/source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/test-exclude": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
@ -16700,6 +16742,55 @@
"integrity": "sha512-SxIFtV5/wlXYS7G3zLVj7CddLolX8Bm/hr68fiyNL3MyG2k4FwF9B5Z5GTpVLhw2EELYNwyoYBvFlR4gGnQPdw==",
"dev": true
},
"@jridgewell/gen-mapping": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
"integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
"dev": true,
"requires": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"@jridgewell/resolve-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
"dev": true
},
"@jridgewell/set-array": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
"dev": true
},
"@jridgewell/source-map": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
"integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
"dev": true,
"requires": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
"dev": true
},
"@jridgewell/trace-mapping": {
"version": "0.3.14",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
"integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
"dev": true,
"requires": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -17063,9 +17154,9 @@
"requires": {}
},
"@xmldom/xmldom": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz",
"integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A=="
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.6.tgz",
"integrity": "sha512-HHXP9hskkFQHy8QxxUXkS7946FFIhYVfGqsk0WLwllmexN9x/+R4UBLvurHEuyXRfVEObVR8APuQehykLviwSQ=="
},
"@xtuc/ieee754": {
"version": "1.2.0",
@ -26903,22 +26994,15 @@
"integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="
},
"terser": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz",
"integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==",
"version": "5.14.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
"dev": true,
"requires": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
"commander": "^2.20.0",
"source-map": "~0.7.2",
"source-map-support": "~0.5.20"
},
"dependencies": {
"source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"dev": true
}
}
},
"terser-webpack-plugin": {

9
packages/nc-cli/package.json

@ -1,6 +1,6 @@
{
"name": "create-nocodb-app",
"version": "0.1.27",
"version": "0.1.28",
"description": "nc-cli",
"main": "dist/bundle.js",
"module": "dist/bundle.js",
@ -14,11 +14,8 @@
},
"scripts": {
"describe": "npm-scripts-info",
"build": "run-s clean && run-p build:*",
"build:main": "tsc -p tsconfig.json",
"build:module": "tsc -p tsconfig.module.json",
"build:obfuscate": "webpack --config webpack.config.js",
"build:obfuscate:publish": "export NODE_OPTIONS=--openssl-legacy-provider && rm -rf dist && npm run build:obfuscate && npm publish .",
"build": "webpack --config webpack.config.js",
"build:publish": "export NODE_OPTIONS=--openssl-legacy-provider && rm -rf dist && npm run build && npm publish .",
"fix": "run-s fix:*",
"fix:prettier": "prettier \"src/**/*.ts\" --write",
"fix:tslint": "tslint --fix --project .",

23
packages/nc-cli/src/index.ts

@ -50,25 +50,4 @@ args.folder = process.cwd();
console.error('\n\nThere was an error processing command:');
console.error(err);
});
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/CliMgr.ts

@ -427,25 +427,4 @@ class CliMgr {
}
export default CliMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/AppMgr.ts

@ -146,25 +146,4 @@ class AppMgr {
export default AppMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/Client.ts

@ -162,25 +162,4 @@ class Client {
//
export default Client;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/ComponentMgr.ts

@ -34,25 +34,4 @@ class ComponentMgr {
export default ComponentMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/DockerMgr.ts

@ -41,25 +41,4 @@ ${
}
export default DockerMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/InstantMgr.ts

@ -257,25 +257,4 @@ class InstantMgr {
}
export default InstantMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/MigrationMgr.ts

@ -135,25 +135,4 @@ class MigrationMgr {
// expose class
export default MigrationMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/ModelMgr.ts

@ -39,25 +39,4 @@ class ModelMgr {
export default ModelMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

27
packages/nc-cli/src/lib/mgr/NewMgr.ts

@ -251,7 +251,7 @@ class NewMgr {
} else if (answers.projectType) {
let env = '';
if (answers.type !== 'sqlite3') {
env = `--env NC_DB="${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}&t=${args._[1]}"`
env = `--env NC_DB="${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}"`
}
const linuxHost = os.type() === 'Linux' ? '--net=host' : '';
if (os.type() === 'Windows_NT') {
@ -641,7 +641,7 @@ ${`Note: ${'app'.bold} - refers to your express server instance`}
`)
} else if (answers.projectType === 'docker') {
const dbUrl = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}&t=${args._[1]}`;
const dbUrl = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`;
// console.log(`
// You can create docker container using following command
//
@ -715,25 +715,4 @@ ${`Note: ${'app'.bold} - refers to your express server instance`}
}
export default NewMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/OldNewMgr.ts

@ -297,25 +297,4 @@ class OldNewMgr {
}
export default OldNewMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/PermissionsMgr.ts

@ -673,25 +673,4 @@ export interface GroupedRoutes {
}
}
}
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/PermissionsMgrJs.ts

@ -686,25 +686,4 @@ class PermissionsMgr {
export default PermissionsMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/SocialMgr.ts

@ -195,25 +195,4 @@ class SocialMgr {
export default SocialMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/SocialText.ts

@ -99,25 +99,4 @@ export default {
'www.nocodb.com'
]
}
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/TryMgr.ts

@ -268,25 +268,4 @@ class TryMgr {
}
export default TryMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/mgr/XcInstantMgr.ts

@ -146,25 +146,4 @@ class AppMgr {
export default AppMgr;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/prompts/Menu.ts

@ -112,25 +112,4 @@ class RunOrDownload {
export default RunOrDownload;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/prompts/RunOrDownload.ts

@ -39,25 +39,4 @@ class RunOrDownload {
export default RunOrDownload;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/util/Lang.ts

@ -152,26 +152,3 @@ export default Lang;
export {
STR
};
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
* @author Wing-Kam Wong <wingkwong.code@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/util/Locales.ts

@ -520,25 +520,4 @@ class Locales {
export default Locales;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/util/Util.ts

@ -911,25 +911,4 @@ ${'VARIATIONS :'.bold}
export default Util;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

23
packages/nc-cli/src/lib/util/config.ts

@ -1,25 +1,4 @@
export default {
port: 23917,
}
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

1
packages/nc-gui/.eslintrc.js

@ -3,6 +3,7 @@ const baseRules = {
'no-console': 0,
'antfu/if-newline': 0,
'no-unused-vars': 0,
'@typescript-eslint/no-this-alias': 0,
'@typescript-eslint/no-unused-vars': [
'error',
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' },

1
packages/nc-gui/components.d.ts vendored

@ -8,6 +8,7 @@ export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
AAlert: typeof import('ant-design-vue/es')['Alert']
AAutoComplete: typeof import('ant-design-vue/es')['AutoComplete']
ABadgeRibbon: typeof import('ant-design-vue/es')['BadgeRibbon']
AButton: typeof import('ant-design-vue/es')['Button']
ACard: typeof import('ant-design-vue/es')['Card']

102
packages/nc-gui/components/api-client/Headers.vue

@ -7,53 +7,61 @@ const props = defineProps<{
const emits = defineEmits(['update:modelValue'])
interface Option {
value: string
}
const vModel = useVModel(props, 'modelValue', emits)
const headerList = [
'A-IM',
'Accept',
'Accept-Charset',
'Accept-Encoding',
'Accept-Language',
'Accept-Datetime',
'Access-Control-Request-Method',
'Access-Control-Request-Headers',
'Authorization',
'Cache-Control',
'Connection',
'Content-Length',
'Content-Type',
'Cookie',
'Date',
'Expect',
'Forwarded',
'From',
'Host',
'If-Match',
'If-Modified-Since',
'If-None-Match',
'If-Range',
'If-Unmodified-Since',
'Max-Forwards',
'Origin',
'Pragma',
'Proxy-Authorization',
'Range',
'Referer',
'TE',
'User-Agent',
'Upgrade',
'Via',
'Warning',
'Non-standard headers',
'Dnt',
'X-Requested-With',
'X-CSRF-Token',
]
const headerList = ref<Option[]>([
{ value: 'A-IM' },
{ value: 'Accept' },
{ value: 'Accept-Charset' },
{ value: 'Accept-Encoding' },
{ value: 'Accept-Language' },
{ value: 'Accept-Datetime' },
{ value: 'Access-Control-Request-Method' },
{ value: 'Access-Control-Request-Headers' },
{ value: 'Authorization' },
{ value: 'Cache-Control' },
{ value: 'Connection' },
{ value: 'Content-Length' },
{ value: 'Content-Type' },
{ value: 'Cookie' },
{ value: 'Date' },
{ value: 'Expect' },
{ value: 'Forwarded' },
{ value: 'From' },
{ value: 'Host' },
{ value: 'If-Match' },
{ value: 'If-Modified-Since' },
{ value: 'If-None-Match' },
{ value: 'If-Range' },
{ value: 'If-Unmodified-Since' },
{ value: 'Max-Forwards' },
{ value: 'Origin' },
{ value: 'Pragma' },
{ value: 'Proxy-Authorization' },
{ value: 'Range' },
{ value: 'Referer' },
{ value: 'TE' },
{ value: 'User-Agent' },
{ value: 'Upgrade' },
{ value: 'Via' },
{ value: 'Warning' },
{ value: 'Non-standard headers' },
{ value: 'Dnt' },
{ value: 'X-Requested-With' },
{ value: 'X-CSRF-Token' },
])
const addHeaderRow = () => vModel.value.push({})
const deleteHeaderRow = (i: number) => vModel.value.splice(i, 1)
const filterOption = (input: string, option: Option) => {
return option.value.toUpperCase().includes(input.toUpperCase())
}
</script>
<template>
@ -89,18 +97,14 @@ const deleteHeaderRow = (i: number) => vModel.value.splice(i, 1)
<td class="px-2 w-min-[400px]">
<a-form-item>
<a-select
<a-auto-complete
v-model:value="headerRow.name"
size="large"
placeholder="Key"
class="nc-input-hook-header-key"
dropdown-class-name="nc-dropdown-webhook-header"
show-search
>
<a-select-option v-for="header in headerList" :key="header" :value="header">
{{ header }}
</a-select-option>
</a-select>
:options="headerList"
:filter-option="filterOption"
/>
</a-form-item>
</td>

2
packages/nc-gui/components/cell/Checkbox.vue

@ -38,7 +38,7 @@ const checkboxMeta = $computed(() => {
})
function onClick() {
if (!readOnly) {
if (!readOnly?.value) {
vModel = !vModel
}
}

4
packages/nc-gui/components/cell/DatePicker.vue

@ -12,11 +12,11 @@ const emit = defineEmits(['update:modelValue'])
const columnMeta = inject(ColumnInj, null)!
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
let isDateInvalid = $ref(false)
const dateFormat = columnMeta?.value?.meta?.date_format ?? 'YYYY-MM-DD'
const dateFormat = $computed(() => columnMeta?.value?.meta?.date_format ?? 'YYYY-MM-DD')
const localState = $computed({
get() {

2
packages/nc-gui/components/cell/DateTimePicker.vue

@ -12,7 +12,7 @@ const emit = defineEmits(['update:modelValue'])
const { isMysql } = useProject()
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
let isDateInvalid = $ref(false)

28
packages/nc-gui/components/cell/Duration.vue

@ -1,4 +1,5 @@
<script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core'
import {
ColumnInj,
EditModeInj,
@ -28,7 +29,7 @@ const durationInMS = ref(0)
const isEdited = ref(false)
const durationType = ref(column?.value?.meta?.duration || 0)
const durationType = computed(() => column?.value?.meta?.duration || 0)
const durationPlaceholder = computed(() => durationOptions[durationType.value].title)
@ -67,13 +68,15 @@ const submitDuration = () => {
}
isEdited.value = false
}
const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
</script>
<template>
<div class="duration-cell-wrapper">
<input
v-if="editEnabled"
ref="durationInput"
:ref="focus"
v-model="localState"
class="w-full !border-none p-0"
:class="{ '!px-2': editEnabled }"
@ -99,25 +102,4 @@ const submitDuration = () => {
</style>
<!--
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Wing-Kam Wong <wingkwong.code@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
-->

23
packages/nc-gui/components/cell/MultiSelect.vue

@ -235,26 +235,5 @@ watch(isOpen, (n, _o) => {
}
</style>
<!--
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
-->

23
packages/nc-gui/components/cell/SingleSelect.vue

@ -111,26 +111,5 @@ watch(isOpen, (n, _o) => {
}
</style>
<!--
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
-->

6
packages/nc-gui/components/cell/Text.vue

@ -1,6 +1,6 @@
<script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core'
import { EditModeInj, inject, useVModel } from '#imports'
import { EditModeInj, ReadonlyInj, inject, ref, useVModel } from '#imports'
interface Props {
modelValue?: string | null
@ -12,6 +12,8 @@ const emits = defineEmits(['update:modelValue'])
const editEnabled = inject(EditModeInj)
const readonly = inject(ReadonlyInj, ref(false))
const vModel = useVModel(props, 'modelValue', emits)
const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
@ -19,7 +21,7 @@ const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
<template>
<input
v-if="editEnabled"
v-if="!readonly && editEnabled"
:ref="focus"
v-model="vModel"
class="h-full w-full outline-none bg-transparent"

2
packages/nc-gui/components/cell/TimePicker.vue

@ -12,7 +12,7 @@ const emit = defineEmits(['update:modelValue'])
const { isMysql } = useProject()
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
let isTimeInvalid = $ref(false)

23
packages/nc-gui/components/cell/Url.vue

@ -117,27 +117,4 @@ watch(
</template>
<!--
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*
* @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com>
* @author Wing-Kam Wong <wingkwong.code@gmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
-->

2
packages/nc-gui/components/cell/YearPicker.vue

@ -10,7 +10,7 @@ const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
let isYearInvalid = $ref(false)

16
packages/nc-gui/components/cell/attachment/Modal.vue

@ -10,7 +10,7 @@ const {
open,
isLoading,
isPublic,
isReadonly,
isReadonly: readOnly,
visibleItems,
modalVisible,
column,
@ -29,7 +29,7 @@ const dropZoneRef = ref<HTMLDivElement>()
const sortableRef = ref<HTMLDivElement>()
const { dragging } = useSortable(sortableRef, visibleItems, updateModelValue, isReadonly)
const { dragging } = useSortable(sortableRef, visibleItems, updateModelValue, readOnly)
const { isOverDropZone } = useDropZone(dropZoneRef, onDrop)
@ -68,7 +68,7 @@ function onClick(item: Record<string, any>) {
<template #title>
<div class="flex gap-4">
<div
v-if="isSharedForm || (!isReadonly && isUIAllowed('tableAttachment') && !isPublic && !isLocked)"
v-if="isSharedForm || (!readOnly && isUIAllowed('tableAttachment') && !isPublic && !isLocked)"
class="nc-attach-file group"
@click="open"
>
@ -77,15 +77,15 @@ function onClick(item: Record<string, any>) {
</div>
<div class="flex items-center gap-2">
<div v-if="isReadonly" class="text-gray-400">[Readonly]</div>
<div v-if="readOnly" class="text-gray-400">[Readonly]</div>
Viewing Attachments of
<div class="font-semibold underline">{{ column.title }}</div>
<div class="font-semibold underline">{{ column?.title }}</div>
</div>
</div>
</template>
<div ref="dropZoneRef">
<template v-if="isSharedForm || (!isReadonly && !dragging)">
<template v-if="isSharedForm || (!readOnly && !dragging)">
<general-overlay
v-model="isOverDropZone"
inline
@ -99,10 +99,10 @@ function onClick(item: Record<string, any>) {
<div ref="sortableRef" :class="{ dragging }" class="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-6 relative p-6">
<div v-for="(item, i) of visibleItems" :key="`${item.title}-${i}`" class="flex flex-col gap-1">
<a-card class="nc-attachment-item group">
<a-tooltip v-if="!isReadonly">
<a-tooltip v-if="!readOnly">
<template #title> Remove File </template>
<MdiCloseCircle
v-if="isSharedForm || (isUIAllowed('tableAttachment') && !isPublicGrid && !isLocked)"
v-if="isSharedForm || (isUIAllowed('tableAttachment') && !isPublic && !isLocked)"
class="nc-attachment-remove"
@click.stop="removeFile(i)"
/>

2
packages/nc-gui/components/cell/attachment/utils.ts

@ -33,7 +33,7 @@ interface AttachmentProps extends File {
export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
(updateModelValue: (data: string | Record<string, any>[]) => void) => {
const isReadonly = inject(ReadonlyInj, false)
const isReadonly = inject(ReadonlyInj, ref(false))
const isPublic = inject(IsPublicInj, ref(false))

395
packages/nc-gui/components/dlg/QuickImport.vue

@ -1,7 +1,9 @@
<script setup lang="ts">
import type { TableType } from 'nocodb-sdk'
import type { UploadChangeParam, UploadFile } from 'ant-design-vue'
import { Upload } from 'ant-design-vue'
import {
CSVTemplateAdapter,
ExcelTemplateAdapter,
ExcelUrlTemplateAdapter,
Form,
@ -20,14 +22,15 @@ import {
useProject,
useVModel,
} from '#imports'
import type { importFileList, streamImportFileList } from '~/lib'
interface Props {
modelValue: boolean
importType: 'csv' | 'json' | 'excel'
importOnly?: boolean
importDataOnly?: boolean
}
const { importType, importOnly = false, ...rest } = defineProps<Props>()
const { importType, importDataOnly = false, ...rest } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
@ -41,7 +44,9 @@ const jsonEditorRef = ref()
const templateEditorRef = ref()
const loading = ref(false)
const preImportLoading = ref(false)
const importLoading = ref(false)
const templateData = ref()
@ -51,16 +56,20 @@ const importColumns = ref([])
const templateEditorModal = ref(false)
const isParsingData = ref(false)
const useForm = Form.useForm
const importState = reactive({
fileList: [] as (UploadFile & { data: string | ArrayBuffer })[],
fileList: [] as importFileList | streamImportFileList,
url: '',
jsonEditor: {},
parserConfig: {
maxRowsToParse: 500,
normalizeNested: true,
importData: true,
autoSelectFieldTypes: true,
firstRowAsHeaders: true,
shouldImportData: true,
},
})
@ -130,47 +139,56 @@ const modalWidth = computed(() => {
return 'max(60vw, 600px)'
})
let templateGenerator: CSVTemplateAdapter | JSONTemplateAdapter | ExcelTemplateAdapter | null
async function handlePreImport() {
loading.value = true
preImportLoading.value = true
isParsingData.value = true
if (activeKey.value === 'uploadTab') {
await parseAndExtractData(importState.fileList[0].data, importState.fileList[0].name)
if (isImportTypeCsv.value) {
await parseAndExtractData(importState.fileList as streamImportFileList)
} else {
await parseAndExtractData((importState.fileList as importFileList)[0].data)
}
} else if (activeKey.value === 'urlTab') {
try {
await validate()
await parseAndExtractData(importState.url, '')
await parseAndExtractData(importState.url)
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
}
} else if (activeKey.value === 'jsonEditorTab') {
await parseAndExtractData(JSON.stringify(importState.jsonEditor), '')
await parseAndExtractData(JSON.stringify(importState.jsonEditor))
}
loading.value = false
}
async function handleImport() {
try {
loading.value = true
if (!templateGenerator) {
message.error(t('msg.error.templateGeneratorNotFound'))
return
}
importLoading.value = true
await templateEditorRef.value.importTemplate()
} catch (e: any) {
return message.error(await extractSdkResponseErrorMsg(e))
} finally {
loading.value = false
importLoading.value = false
}
dialogShow.value = false
}
async function parseAndExtractData(val: string | ArrayBuffer, name: string) {
// UploadFile[] for csv import (streaming)
// ArrayBuffer for excel import
// string for json import
async function parseAndExtractData(val: UploadFile[] | ArrayBuffer | string) {
try {
templateData.value = null
importData.value = null
importColumns.value = []
const templateGenerator = getAdapter(name, val)
templateGenerator = getAdapter(val)
if (!templateGenerator) {
message.error(t('msg.error.templateGeneratorNotFound'))
@ -179,16 +197,24 @@ async function parseAndExtractData(val: string | ArrayBuffer, name: string) {
await templateGenerator.init()
templateGenerator.parse()
templateData.value = templateGenerator.getTemplate()
templateData.value.tables[0].table_name = populateUniqueTableName()
importData.value = templateGenerator.getData()
if (importOnly) importColumns.value = templateGenerator.getColumns()
await templateGenerator.parse()
templateData.value = templateGenerator!.getTemplate()
if (importDataOnly) importColumns.value = templateGenerator!.getColumns()
else {
// ensure the target table name not exist in current table list
templateData.value.tables = templateData.value.tables.map((table: Record<string, any>) => ({
...table,
table_name: populateUniqueTableName(table.table_name),
}))
}
importData.value = templateGenerator!.getData()
templateEditorModal.value = true
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
} finally {
isParsingData.value = false
preImportLoading.value = false
}
}
@ -200,29 +226,34 @@ function rejectDrop(fileList: UploadFile[]) {
function handleChange(info: UploadChangeParam) {
const status = info.file.status
if (status !== 'uploading' && status !== 'removed') {
const reader = new FileReader()
reader.onload = (e: ProgressEvent<FileReader>) => {
const target = importState.fileList.find((f) => f.uid === info.file.uid)
if (e.target && e.target.result) {
/** if the file was pushed into the list by `<a-upload-dragger>` we just add the data to the file */
if (target) {
target.data = e.target.result
} else if (!target) {
/** if the file was added programmatically and not with d&d, we create file infos and push it into the list */
importState.fileList.push({
...info.file,
status: 'done',
data: e.target.result,
})
if (status && status !== 'uploading' && status !== 'removed') {
if (isImportTypeCsv.value) {
if (!importState.fileList.find((f) => f.uid === info.file.uid)) {
;(importState.fileList as streamImportFileList).push({
...info.file,
status: 'done',
})
}
} else {
const reader = new FileReader()
reader.onload = (e: ProgressEvent<FileReader>) => {
const target = (importState.fileList as importFileList).find((f) => f.uid === info.file.uid)
if (e.target && e.target.result) {
/** if the file was pushed into the list by `<a-upload-dragger>` we just add the data to the file */
if (target) {
target.data = e.target.result
} else if (!target) {
/** if the file was added programmatically and not with d&d, we create file infos and push it into the list */
importState.fileList.push({
...info.file,
status: 'done',
data: e.target.result,
})
}
}
}
reader.readAsArrayBuffer(info.file.originFileObj!)
}
reader.readAsArrayBuffer(info.file.originFileObj!)
}
if (status === 'done') {
@ -236,32 +267,50 @@ function formatJson() {
jsonEditorRef.value?.format()
}
function populateUniqueTableName() {
function populateUniqueTableName(tn: string) {
let c = 1
while (tables.value.some((t: TableType) => t.title === `Sheet${c}`)) {
c++
while (
tables.value.some((t: TableType) => {
const s = t.table_name.split('___')
let target = t.table_name
if (s.length > 1) target = s[1]
return target === `${tn}`
})
) {
tn = `${tn}_${c++}`
}
return `Sheet${c}`
return tn
}
function getAdapter(name: string, val: any) {
if (IsImportTypeExcel.value || isImportTypeCsv.value) {
function getAdapter(val: any) {
if (isImportTypeCsv.value) {
switch (activeKey.value) {
case 'uploadTab':
return new CSVTemplateAdapter(val, {
...importState.parserConfig,
importFromURL: false,
})
case 'urlTab':
return new CSVTemplateAdapter(val, {
...importState.parserConfig,
importFromURL: true,
})
}
} else if (IsImportTypeExcel.value) {
switch (activeKey.value) {
case 'uploadTab':
return new ExcelTemplateAdapter(name, val, importState.parserConfig)
return new ExcelTemplateAdapter(val, importState.parserConfig)
case 'urlTab':
return new ExcelUrlTemplateAdapter(val, importState.parserConfig)
}
} else if (isImportTypeJson.value) {
switch (activeKey.value) {
case 'uploadTab':
return new JSONTemplateAdapter(name, val, importState.parserConfig)
return new JSONTemplateAdapter(val, importState.parserConfig)
case 'urlTab':
return new JSONUrlTemplateAdapter(val, importState.parserConfig)
case 'jsonEditorTab':
return new JSONTemplateAdapter(name, val, importState.parserConfig)
return new JSONTemplateAdapter(val, importState.parserConfig)
}
}
@ -282,6 +331,15 @@ const customReqCbk = (customReqArgs: { file: any; onSuccess: () => void }) => {
})
customReqArgs.onSuccess()
}
/** check if the file size exceeds the limit */
const beforeUpload = (file: UploadFile) => {
const exceedLimit = file.size! / 1024 / 1024 > 5
if (exceedLimit) {
message.error(`File ${file.name} is too big. The accepted file size is less than 5MB.`)
}
return !exceedLimit || Upload.LIST_IGNORE
}
</script>
<template>
@ -291,115 +349,130 @@ const customReqCbk = (customReqArgs: { file: any; onSuccess: () => void }) => {
wrap-class-name="nc-modal-quick-import"
@keydown.esc="dialogShow = false"
>
<div class="px-5">
<div class="prose-xl font-weight-bold my-5">{{ importMeta.header }}</div>
<div class="mt-5">
<LazyTemplateEditor
v-if="templateEditorModal"
ref="templateEditorRef"
:project-template="templateData"
:import-data="importData"
:import-columns="importColumns"
:import-only="importOnly"
:quick-import-type="importType"
:max-rows-to-parse="importState.parserConfig.maxRowsToParse"
class="nc-quick-import-template-editor"
@import="handleImport"
/>
<a-tabs v-else v-model:activeKey="activeKey" hide-add type="editable-card" tab-position="top">
<a-tab-pane key="uploadTab" :closable="false">
<template #tab>
<!-- Upload -->
<div class="flex items-center gap-2">
<MdiFileUploadOutline />
{{ $t('general.upload') }}
<a-spin :spinning="isParsingData" tip="Parsing Data ..." size="large">
<div class="px-5">
<div class="prose-xl font-weight-bold my-5">{{ importMeta.header }}</div>
<div class="mt-5">
<LazyTemplateEditor
v-if="templateEditorModal"
ref="templateEditorRef"
:project-template="templateData"
:import-data="importData"
:import-columns="importColumns"
:import-data-only="importDataOnly"
:quick-import-type="importType"
:max-rows-to-parse="importState.parserConfig.maxRowsToParse"
class="nc-quick-import-template-editor"
@import="handleImport"
/>
<a-tabs v-else v-model:activeKey="activeKey" hide-add type="editable-card" tab-position="top">
<a-tab-pane key="uploadTab" :closable="false">
<template #tab>
<!-- Upload -->
<div class="flex items-center gap-2">
<MdiFileUploadOutline />
{{ $t('general.upload') }}
</div>
</template>
<div class="py-6">
<a-upload-dragger
v-model:fileList="importState.fileList"
name="file"
class="nc-input-import !scrollbar-thin-dull"
list-type="picture"
:accept="importMeta.acceptTypes"
:max-count="isImportTypeCsv ? 5 : 1"
:multiple="true"
:custom-request="customReqCbk"
:before-upload="beforeUpload"
@change="handleChange"
@reject="rejectDrop"
>
<MdiFilePlusOutline size="large" />
<!-- Click or drag file to this area to upload -->
<p class="ant-upload-text">{{ $t('msg.info.import.clickOrDrag') }}</p>
<p class="ant-upload-hint">
{{ importMeta.uploadHint }}
</p>
</a-upload-dragger>
</div>
</template>
<div class="py-6">
<a-upload-dragger
v-model:fileList="importState.fileList"
name="file"
class="nc-input-import !scrollbar-thin-dull"
:accept="importMeta.acceptTypes"
:max-count="1"
list-type="picture"
:custom-request="customReqCbk"
@change="handleChange"
@reject="rejectDrop"
>
<MdiFilePlusOutline size="large" />
<!-- Click or drag file to this area to upload -->
<p class="ant-upload-text">{{ $t('msg.info.import.clickOrDrag') }}</p>
<p class="ant-upload-hint">
{{ importMeta.uploadHint }}
</p>
</a-upload-dragger>
</div>
</a-tab-pane>
<a-tab-pane v-if="isImportTypeJson" key="jsonEditorTab" :closable="false">
<template #tab>
<span class="flex items-center gap-2">
<MdiCodeJson />
JSON Editor
</span>
</template>
<div class="pb-3 pt-3">
<LazyMonacoEditor ref="jsonEditorRef" v-model="importState.jsonEditor" class="min-h-60 max-h-80" />
</div>
</a-tab-pane>
<a-tab-pane v-else key="urlTab" :closable="false">
<template #tab>
<span class="flex items-center gap-2">
<MdiLinkVariant />
URL
</span>
</template>
<div class="pr-10 pt-5">
<a-form :model="importState" name="quick-import-url-form" layout="horizontal" class="mb-0">
<a-form-item :label="importMeta.urlInputLabel" v-bind="validateInfos.url">
<a-input v-model:value="importState.url" size="large" />
</a-form-item>
</a-form>
</div>
</a-tab-pane>
</a-tabs>
</div>
<div v-if="!templateEditorModal">
<a-divider />
<div class="mb-4">
<!-- Advanced Settings -->
<span class="prose-lg">{{ $t('title.advancedSettings') }}</span>
<a-form-item class="mt-4 mb-2" :label="t('msg.info.footMsg')" v-bind="validateInfos.maxRowsToParse">
<a-input-number v-model:value="importState.parserConfig.maxRowsToParse" :min="1" :max="50000" />
</a-form-item>
<!-- Flatten nested -->
<div v-if="isImportTypeJson" class="mt-3">
<a-checkbox v-model:checked="importState.parserConfig.normalizeNested">
<span class="caption">{{ $t('labels.flattenNested') }}</span>
</a-checkbox>
</div>
</a-tab-pane>
<a-tab-pane v-if="isImportTypeJson" key="jsonEditorTab" :closable="false">
<template #tab>
<span class="flex items-center gap-2">
<MdiCodeJson />
JSON Editor
</span>
</template>
<div class="pb-3 pt-3">
<LazyMonacoEditor ref="jsonEditorRef" v-model="importState.jsonEditor" class="min-h-60 max-h-80" />
</div>
</a-tab-pane>
<a-tab-pane v-else key="urlTab" :closable="false">
<template #tab>
<span class="flex items-center gap-2">
<MdiLinkVariant />
URL
</span>
</template>
<div class="pr-10 pt-5">
<a-form :model="importState" name="quick-import-url-form" layout="horizontal" class="mb-0">
<a-form-item :label="importMeta.urlInputLabel" v-bind="validateInfos.url">
<a-input v-model:value="importState.url" size="large" />
</a-form-item>
</a-form>
</div>
</a-tab-pane>
</a-tabs>
</div>
<!-- Import Data -->
<div v-if="isImportTypeJson" class="mt-4">
<a-checkbox v-model:checked="importState.parserConfig.importData">{{ $t('labels.importData') }}</a-checkbox>
<div v-if="!templateEditorModal">
<a-divider />
<div class="mb-4">
<!-- Advanced Settings -->
<span class="prose-lg">{{ $t('title.advancedSettings') }}</span>
<a-form-item class="!my-2" :label="t('msg.info.footMsg')" v-bind="validateInfos.maxRowsToParse">
<a-input-number v-model:value="importState.parserConfig.maxRowsToParse" :min="1" :max="50000" />
</a-form-item>
<a-form-item v-if="!importDataOnly" class="!my-2">
<a-checkbox v-model:checked="importState.parserConfig.autoSelectFieldTypes">
<span class="caption">Auto-Select Field Types</span>
</a-checkbox>
</a-form-item>
<a-form-item v-if="isImportTypeCsv || IsImportTypeExcel" class="!my-2">
<a-checkbox v-model:checked="importState.parserConfig.firstRowAsHeaders">
<span class="caption">Use First Row as Headers</span>
</a-checkbox>
</a-form-item>
<!-- Flatten nested -->
<a-form-item v-if="isImportTypeJson" class="!my-2">
<a-checkbox v-model:checked="importState.parserConfig.normalizeNested">
<span class="caption">{{ $t('labels.flattenNested') }}</span>
</a-checkbox>
</a-form-item>
<!-- Import Data -->
<a-form-item v-if="!importDataOnly" class="!my-2">
<a-checkbox v-model:checked="importState.parserConfig.shouldImportData">{{ $t('labels.importData') }}</a-checkbox>
</a-form-item>
</div>
</div>
</div>
</div>
</a-spin>
<template #footer>
<a-button v-if="templateEditorModal" key="back" @click="templateEditorModal = false">Back</a-button>
@ -419,14 +492,14 @@ const customReqCbk = (customReqArgs: { file: any; onSuccess: () => void }) => {
key="pre-import"
type="primary"
class="nc-btn-import"
:loading="loading"
:loading="preImportLoading"
:disabled="disablePreImportButton"
@click="handlePreImport"
>
{{ $t('activity.import') }}
</a-button>
<a-button v-else key="import" type="primary" :loading="loading" :disabled="disableImportButton" @click="handleImport">
<a-button v-else key="import" type="primary" :loading="importLoading" :disabled="disableImportButton" @click="handleImport">
{{ $t('activity.import') }}
</a-button>
</template>

7
packages/nc-gui/components/erd/ConfigPanel.vue

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { Panel } from '@vue-flow/additional-components'
import { Panel, PanelPosition } from '@vue-flow/additional-components'
import type { ERDConfig } from './utils'
import { ref, useGlobal, useVModel } from '#imports'
@ -15,7 +15,10 @@ const showAdvancedOptions = ref(false)
</script>
<template>
<Panel class="flex flex-col bg-white border-1 rounded border-gray-200 z-50 px-3 py-1 nc-erd-context-menu" position="top-right">
<Panel
class="flex flex-col bg-white border-1 rounded border-gray-200 z-50 px-3 py-1 nc-erd-context-menu"
:position="PanelPosition.TopRight"
>
<div class="flex items-center gap-2">
<a-checkbox v-model:checked="config.showAllColumns" v-e="['c:erd:showAllColumns']" class="nc-erd-showColumns-checkbox" />
<span class="select-none nc-erd-showColumns-label" style="font-size: 0.65rem" @dblclick="showAdvancedOptions = true">

6
packages/nc-gui/components/erd/Flow.vue

@ -1,5 +1,5 @@
<script setup lang="ts">
import { Background, Controls, Panel } from '@vue-flow/additional-components'
import { Background, Controls, Panel, PanelPosition } from '@vue-flow/additional-components'
import { VueFlow, useVueFlow } from '@vue-flow/core'
import type { TableType } from 'nocodb-sdk'
import type { ERDConfig } from './utils'
@ -65,7 +65,7 @@ onScopeDispose($destroy)
<template>
<VueFlow v-model="elements">
<Controls class="rounded" position="bottom-left" :show-fit-view="false" :show-interactive="false" />
<Controls class="rounded" :position="PanelPosition.BottomLeft" :show-fit-view="false" :show-interactive="false" />
<template #node-custom="{ data, dragging }">
<ErdTableNode :data="data" :dragging="dragging" :show-skeleton="showSkeleton" />
@ -80,7 +80,7 @@ onScopeDispose($destroy)
<Transition name="layout">
<Panel
v-if="showSkeleton && config.showAllColumns"
position="bottom-center"
:position="PanelPosition.BottomCenter"
class="color-transition z-5 cursor-pointer rounded shadow-sm text-slate-400 font-semibold px-4 py-2 bg-slate-100/50 hover:(text-slate-900 ring ring-accent ring-opacity-100 bg-slate-100/90)"
@click="zoomIn"
>

4
packages/nc-gui/components/erd/HistogramPanel.vue

@ -1,9 +1,9 @@
<script lang="ts" setup>
import { Panel } from '@vue-flow/additional-components'
import { Panel, PanelPosition } from '@vue-flow/additional-components'
</script>
<template>
<Panel class="text-xs bg-white border-1 rounded border-gray-200 z-50 nc-erd-histogram" position="bottom-right">
<Panel class="text-xs bg-white border-1 rounded border-gray-200 z-50 nc-erd-histogram" :position="PanelPosition.BottomRight">
<div class="flex flex-col divide-y-1">
<div class="flex items-center gap-1 p-2">
<MdiTableLarge class="text-primary" />

4
packages/nc-gui/components/erd/RelationEdge.vue

@ -36,7 +36,7 @@ const edgePath = computed(() => {
const { sourceX, sourceY, targetX, targetY } = props
const radiusX = (sourceX - targetX) * 0.6
const radiusY = 50
return [`M ${sourceX} ${sourceY} A ${radiusX} ${radiusY} 0 1 0 ${targetX} ${targetY}`]
return [`M ${sourceX} ${sourceY} A ${radiusX} ${radiusY} 0 1 0 ${targetX} ${targetY}`, NaN, NaN] as const
}
return getBezierPath({ ...props })
@ -94,7 +94,7 @@ export default {
<Transition name="layout">
<EdgeText
v-if="data.label?.length > 0"
v-if="data.label?.length && data.label.length > 0"
:key="`edge-text-${id}.${showSkeleton}`"
class="color-transition"
:class="[

2
packages/nc-gui/components/erd/TableNode.vue

@ -6,7 +6,7 @@ import { UITypes, isVirtualCol } from 'nocodb-sdk'
import type { NodeData } from './utils'
import { MetaInj, computed, provide, refAutoReset, toRef, useNuxtApp, watch } from '#imports'
interface Props extends NodeProps<NodeData> {
interface Props extends Pick<NodeProps<NodeData>, 'data' | 'dragging'> {
data: NodeData
showSkeleton: boolean
dragging: boolean

2
packages/nc-gui/components/general/Overlay.vue

@ -11,7 +11,7 @@ interface Props {
target?: TeleportProps['to']
teleportDisabled?: TeleportProps['disabled']
transition?: boolean
zIndex?: string | number
zIndex?: number
}
interface Emits {

2
packages/nc-gui/components/general/language/Menu.vue

@ -9,7 +9,7 @@ const { lang: currentLang } = useGlobal()
const { locale } = useI18n()
const languages = $computed(() => Object.entries(Language).sort())
const languages = $computed(() => Object.entries(Language).sort() as [keyof typeof Language, Language][])
const isRtlLang = $computed(() => ['fa', 'ar'].includes(currentLang.value))

2
packages/nc-gui/components/shared-view/Gallery.vue

@ -7,7 +7,7 @@ const reloadEventHook = createEventHook()
provide(ReloadViewDataHookInj, reloadEventHook)
provide(ReadonlyInj, true)
provide(ReadonlyInj, ref(true))
provide(MetaInj, meta)

2
packages/nc-gui/components/shared-view/Grid.vue

@ -28,7 +28,7 @@ useProvideSmartsheetStore(sharedView, meta, true, sorts, nestedFilters)
const reloadEventHook = createEventHook()
provide(ReloadViewDataHookInj, reloadEventHook)
provide(ReadonlyInj, true)
provide(ReadonlyInj, ref(true))
provide(MetaInj, meta)
provide(ActiveViewInj, sharedView)
provide(FieldsInj, ref(meta.value?.columns || []))

2
packages/nc-gui/components/shared-view/Kanban.vue

@ -15,7 +15,7 @@ const reloadEventHook = createEventHook()
provide(ReloadViewDataHookInj, reloadEventHook)
provide(ReadonlyInj, true)
provide(ReadonlyInj, ref(true))
provide(MetaInj, meta)

4
packages/nc-gui/components/smartsheet/Cell.vue

@ -1,6 +1,5 @@
<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import {
ActiveCellInj,
ColumnInj,
@ -8,6 +7,7 @@ import {
IsFormInj,
IsLockedInj,
IsPublicInj,
ReadonlyInj,
computed,
inject,
provide,
@ -47,7 +47,7 @@ provide(EditModeInj, useVModel(props, 'editEnabled', emit))
provide(ActiveCellInj, active)
if (readOnly?.value) {
provide(ReadonlyInj, readOnly.value)
provide(ReadonlyInj, readOnly)
}
const isForm = inject(IsFormInj, ref(false))

33
packages/nc-gui/components/smartsheet/Gallery.vue

@ -10,7 +10,6 @@ import {
MetaInj,
OpenNewRecordFormHookInj,
PaginationDataInj,
ReadonlyInj,
ReloadRowDataHookInj,
ReloadViewDataHookInj,
ReloadViewMetaHookInj,
@ -22,7 +21,6 @@ import {
onMounted,
provide,
ref,
useUIPermission,
useViewData,
} from '#imports'
import type { Row as RowType } from '~/lib'
@ -51,14 +49,11 @@ const {
addEmptyRow,
} = useViewData(meta, view)
const { isUIAllowed } = useUIPermission()
provide(IsFormInj, ref(false))
provide(IsGalleryInj, ref(true))
provide(IsGridInj, ref(false))
provide(PaginationDataInj, paginationData)
provide(ChangePageInj, changePage)
provide(ReadonlyInj, !isUIAllowed('xcDatatableEditable'))
const fields = inject(FieldsInj, ref([]))
@ -201,7 +196,7 @@ watch(view, async (nextView) => {
:key="`carousel-${record.row.id}-${index}`"
quality="90"
placeholder
class="h-52 object-cover"
class="h-52 object-contain"
:src="attachment.url"
/>
</a-carousel>
@ -209,23 +204,17 @@ watch(view, async (nextView) => {
<MdiFileImageBox v-else class="w-full h-48 my-4 text-cool-gray-200" />
</template>
<div
v-for="col in fieldsWithoutCover"
:key="`record-${record.row.id}-${col.id}`"
class="flex flex-col space-y-1 px-4 mb-6 bg-gray-50 rounded-lg w-full"
>
<div class="flex flex-row w-full justify-start border-b-1 border-gray-100 py-2.5">
<div class="w-full text-gray-600">
<LazySmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" :hide-menu="true" />
<div v-for="col in fieldsWithoutCover" :key="`record-${record.row.id}-${col.id}`">
<div v-if="!isRowEmpty(record, col)" class="flex flex-col space-y-1 px-4 mb-6 bg-gray-50 rounded-lg w-full">
<div class="flex flex-row w-full justify-start border-b-1 border-gray-100 py-2.5">
<div class="w-full text-gray-600">
<LazySmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" :hide-menu="true" />
<LazySmartsheetHeaderCell v-else :column="col" :hide-menu="true" />
<LazySmartsheetHeaderCell v-else :column="col" :hide-menu="true" />
</div>
</div>
</div>
<div class="flex flex-row w-full pb-3 pt-2 pl-2 items-center justify-start">
<div v-if="isRowEmpty(record, col)" class="h-3 bg-gray-200 px-5 rounded-lg"></div>
<template v-else>
<div class="flex flex-row w-full pb-3 pt-2 pl-2 items-center justify-start">
<LazySmartsheetVirtualCell
v-if="isVirtualCol(col)"
v-model="record.row[col.title]"
@ -240,7 +229,7 @@ watch(view, async (nextView) => {
:edit-enabled="false"
:read-only="true"
/>
</template>
</div>
</div>
</div>
</a-card>
@ -290,7 +279,7 @@ watch(view, async (nextView) => {
.ant-carousel.gallery-carousel :deep(.slick-dots) {
position: relative;
height: auto;
bottom: 0px;
bottom: 0;
}
.ant-carousel.gallery-carousel :deep(.slick-dots li div > div) {

27
packages/nc-gui/components/smartsheet/Grid.vue

@ -18,6 +18,7 @@ import {
ReloadViewDataHookInj,
computed,
createEventHook,
enumColor,
extractPkFromRow,
inject,
isColumnRequiredAndNull,
@ -32,6 +33,7 @@ import {
useI18n,
useMetas,
useMultiSelect,
useRoles,
useRoute,
useSmartsheetStoreOrThrow,
useUIPermission,
@ -50,12 +52,13 @@ const view = inject(ActiveViewInj, ref())
// keep a root fields variable and will get modified from
// fields menu and get used in grid and gallery
const fields = inject(FieldsInj, ref([]))
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false))
const reloadViewDataHook = inject(ReloadViewDataHookInj, createEventHook())
const openNewRecordFormHook = inject(OpenNewRecordFormHookInj, createEventHook())
const { hasRole } = useRoles()
const { isUIAllowed } = useUIPermission()
const hasEditPermission = $computed(() => isUIAllowed('xcDatatableEditable'))
@ -67,7 +70,7 @@ const isView = false
let editEnabled = $ref(false)
const { xWhere, isPkAvail, cellRefs, isSqlView } = useSmartsheetStoreOrThrow()
const { xWhere, isPkAvail, isSqlView } = useSmartsheetStoreOrThrow()
const visibleColLength = $computed(() => fields.value?.length)
@ -224,8 +227,6 @@ provide(PaginationDataInj, paginationData)
provide(ChangePageInj, changePage)
provide(ReadonlyInj, !hasEditPermission)
const disableUrlOverlay = ref(false)
provide(CellUrlDisableOverlayInj, disableUrlOverlay)
@ -273,7 +274,9 @@ watch(contextMenu, () => {
const rowRefs = $ref<any[]>()
async function clearCell(ctx: { row: number; col: number }) {
async function clearCell(ctx: { row: number; col: number } | null) {
if (!ctx) return
const rowObj = data.value[ctx.row]
const columnObj = fields.value[ctx.col]
@ -561,7 +564,12 @@ watch(
<a-checkbox v-model:checked="row.rowMeta.selected" />
</div>
<span class="flex-1" />
<div v-if="!readOnly && !isLocked" class="nc-expand" :class="{ 'nc-comment': row.rowMeta?.commentCount }">
<div
v-if="!readOnly || hasRole('commenter', true) || hasRole('viewer', true)"
class="nc-expand"
:class="{ 'nc-comment': row.rowMeta?.commentCount }"
>
<a-spin v-if="row.rowMeta.saving" class="!flex items-center" />
<template v-else>
<span
@ -586,9 +594,8 @@ watch(
</div>
</div>
</td>
<td
<SmartsheetTableDataCell
v-for="(columnObj, colIndex) of fields"
:ref="cellRefs.set"
:key="columnObj.id"
class="cell relative cursor-pointer nc-grid-cell"
:class="{
@ -625,13 +632,13 @@ watch(
"
:row-index="rowIndex"
:active="selected.col === colIndex && selected.row === rowIndex"
@update:edit-enabled="editEnabled = false"
@update:edit-enabled="editEnabled = $event"
@save="updateOrSaveRow(row, columnObj.title, state)"
@navigate="onNavigate"
@cancel="editEnabled = false"
/>
</div>
</td>
</SmartsheetTableDataCell>
</tr>
</template>
</LazySmartsheetRow>

3
packages/nc-gui/components/smartsheet/Kanban.vue

@ -12,7 +12,6 @@ import {
IsPublicInj,
MetaInj,
OpenNewRecordFormHookInj,
ReadonlyInj,
inject,
onBeforeMount,
onBeforeUnmount,
@ -85,8 +84,6 @@ provide(IsGridInj, ref(false))
provide(IsKanbanInj, ref(true))
provide(ReadonlyInj, !isUIAllowed('xcDatatableEditable'))
const hasEditPermission = $computed(() => isUIAllowed('xcDatatableEditable'))
const fields = inject(FieldsInj, ref([]))

4
packages/nc-gui/components/smartsheet/Row.vue

@ -1,4 +1,6 @@
<script lang="ts" setup>
import type { Ref } from 'vue'
import type { TableType } from 'nocodb-sdk'
import type { Row } from '~/lib'
import {
ReloadRowDataHookInj,
@ -20,7 +22,7 @@ const currentRow = toRef(props, 'row')
const { meta } = useSmartsheetStoreOrThrow()
const { isNew, state, syncLTARRefs, clearLTARCell } = useProvideSmartsheetRowStore(meta, currentRow)
const { isNew, state, syncLTARRefs, clearLTARCell } = useProvideSmartsheetRowStore(meta as Ref<TableType>, currentRow)
// on changing isNew(new record insert) status sync LTAR cell values
watch(isNew, async (nextVal, prevVal) => {

24
packages/nc-gui/components/smartsheet/TableDataCell.vue

@ -0,0 +1,24 @@
<script lang="ts" setup>
import { onBeforeUnmount, onMounted, ref, useSmartsheetStoreOrThrow } from '#imports'
const { cellRefs } = useSmartsheetStoreOrThrow()
const el = ref<HTMLTableDataCellElement>()
onMounted(() => {
cellRefs.value.push(el.value!)
})
onBeforeUnmount(() => {
const index = cellRefs.value.indexOf(el.value!)
if (index > -1) {
cellRefs.value.splice(index, 1)
}
})
</script>
<template>
<td ref="el">
<slot />
</td>
</template>

26
packages/nc-gui/components/smartsheet/expanded-form/Detached.vue

@ -0,0 +1,26 @@
<script lang="ts" setup>
import { useExpandedFormDetached } from '#imports'
const { states, close } = useExpandedFormDetached()
const shouldClose = (isVisible: boolean, i: number) => {
if (!isVisible) close(i)
}
</script>
<template>
<template v-for="(state, i) of states" :key="`expanded-form-${i}`">
<LazySmartsheetExpandedForm
v-model="state.isOpen"
:row="state.row"
:load-row="state.loadRow"
:meta="state.meta"
:row-id="state.rowId"
:state="state.state"
:use-meta-fields="state.useMetaFields"
:view="state.view"
@update:model-value="shouldClose($event, i)"
@cancel="close(i)"
/>
</template>
</template>

2
packages/nc-gui/components/smartsheet/expanded-form/index.vue

@ -9,6 +9,8 @@ import {
MetaInj,
ReloadRowDataHookInj,
computedInject,
createEventHook,
inject,
message,
provide,
ref,

6
packages/nc-gui/components/smartsheet/sidebar/MenuTop.vue

@ -224,11 +224,11 @@ function openDeleteDialog(view: ViewType) {
:key="view.id"
:view="view"
:on-validate="validate"
class="transition-all ease-in duration-300"
class="nc-view-item transition-all ease-in duration-300"
:class="{
'bg-gray-100': isMarked === view.id,
'active': activeView.id === view.id,
[`nc-view-item nc-${viewTypeAlias[view.type] || view.type}-view-item`]: true,
'active': activeView?.id === view.id,
[`nc-${view.type ? viewTypeAlias[view.type] : undefined || view.type}-view-item`]: true,
}"
@change-view="changeView"
@open-modal="$emit('openModal', $event)"

7
packages/nc-gui/components/smartsheet/sidebar/RenameableMenuItem.vue

@ -3,6 +3,7 @@ import type { KanbanType, ViewType, ViewTypes } from 'nocodb-sdk'
import type { WritableComputedRef } from '@vue/reactivity'
import {
IsLockedInj,
computed,
inject,
message,
onKeyStroke,
@ -47,6 +48,8 @@ let isStopped = $ref(false)
/** Original view title when editing the view name */
let originalTitle = $ref<string | undefined>()
const viewType = computed(() => vModel.value.type as number)
/** Debounce click handler, so we can potentially enable editing view name {@see onDblClick} */
const onClick = useDebounceFn(() => {
if (isEditing || isStopped) return
@ -175,9 +178,9 @@ function onStopEdit() {
/>
<component
:is="viewIcons[vModel.type].icon"
:is="viewIcons[viewType].icon"
class="nc-view-icon group-hover:hidden"
:style="{ color: viewIcons[vModel.type].color }"
:style="{ color: viewIcons[viewType].color }"
/>
</div>

2
packages/nc-gui/components/smartsheet/toolbar/MoreActions.vue

@ -166,7 +166,7 @@ const exportFile = async (exportType: ExportTypes) => {
</template>
</a-dropdown>
<LazyDlgQuickImport v-if="quickImportDialog" v-model="quickImportDialog" import-type="csv" :import-only="true" />
<LazyDlgQuickImport v-if="quickImportDialog" v-model="quickImportDialog" import-type="csv" :import-data-only="true" />
<LazyWebhookDrawer v-if="showWebhookDrawer" v-model="showWebhookDrawer" />

2
packages/nc-gui/components/smartsheet/toolbar/ShareView.vue

@ -43,7 +43,7 @@ const shared = ref<SharedView>({ id: '', meta: {}, password: undefined })
const transitionDuration = computed({
get: () => shared.value.meta.transitionDuration || 250,
set: (duration) => {
shared.value.meta = { ...shared.value.meta, transitionDuration: duration }
shared.value.meta = { ...shared.value.meta, transitionDuration: duration > 5000 ? 5000 : duration }
},
})

2
packages/nc-gui/components/smartsheet/toolbar/ViewActions.vue

@ -228,7 +228,7 @@ const { isSqlView } = useSmartsheetStoreOrThrow()
</template>
</a-dropdown>
<LazyDlgQuickImport v-if="quickImportDialog" v-model="quickImportDialog" import-type="csv" :import-only="true" />
<LazyDlgQuickImport v-if="quickImportDialog" v-model="quickImportDialog" import-type="csv" :import-data-only="true" />
<LazyWebhookDrawer v-if="showWebhookDrawer" v-model="showWebhookDrawer" />

10
packages/nc-gui/components/tabs/Smartsheet.vue

@ -7,6 +7,7 @@ import {
IsLockedInj,
MetaInj,
OpenNewRecordFormHookInj,
ReadonlyInj,
ReloadViewDataHookInj,
ReloadViewMetaHookInj,
TabMetaInj,
@ -18,6 +19,7 @@ import {
useMetas,
useProvideKanbanViewStore,
useProvideSmartsheetStore,
useUIPermission,
} from '#imports'
import type { TabItem } from '~/lib'
@ -25,6 +27,8 @@ const props = defineProps<{
activeTab: TabItem
}>()
const { isUIAllowed } = useUIPermission()
const { metas } = useMetas()
const activeTab = toRef(props, 'activeTab')
@ -56,6 +60,10 @@ provide(OpenNewRecordFormHookInj, openNewRecordFormHook)
provide(FieldsInj, fields)
provide(IsFormInj, isForm)
provide(TabMetaInj, activeTab)
provide(
ReadonlyInj,
computed(() => !isUIAllowed('xcDatatableEditable')),
)
</script>
<template>
@ -82,6 +90,8 @@ provide(TabMetaInj, activeTab)
</Transition>
</div>
<LazySmartsheetExpandedFormDetached />
<!-- Lazy loading the sidebar causes issues when deleting elements, i.e. it appears as if multiple elements are removed when they are not -->
<SmartsheetSidebar v-if="meta" class="nc-right-sidebar" />
</div>

403
packages/nc-gui/components/template/Editor.vue

@ -14,22 +14,23 @@ import {
extractSdkResponseErrorMsg,
fieldRequiredValidator,
getDateFormat,
getDateTimeFormat,
getUIDTIcon,
inject,
message,
nextTick,
onMounted,
parseStringDate,
reactive,
ref,
useI18n,
useNuxtApp,
useProject,
useTabs,
useTemplateRefsList,
} from '#imports'
import { TabType } from '~/lib'
const { quickImportType, projectTemplate, importData, importColumns, importOnly, maxRowsToParse } = defineProps<Props>()
const { quickImportType, projectTemplate, importData, importColumns, importDataOnly, maxRowsToParse } = defineProps<Props>()
const emit = defineEmits(['import'])
@ -42,7 +43,7 @@ interface Props {
projectTemplate: Record<string, any>
importData: Record<string, any>
importColumns: any[]
importOnly: boolean
importDataOnly: boolean
maxRowsToParse: number
}
@ -71,11 +72,11 @@ const expansionPanel = ref<number[]>([])
const editableTn = ref<boolean[]>([])
const inputRefs = useTemplateRefsList<HTMLInputElement>()
const inputRefs = ref<HTMLInputElement[]>([])
const isImporting = ref(false)
const importingTip = ref('Importing')
const importingTips = ref<Record<string, string>>({})
const uiTypeOptions = ref<Option[]>(
(Object.keys(UITypes) as (keyof typeof UITypes)[])
@ -92,12 +93,12 @@ const uiTypeOptions = ref<Option[]>(
})),
)
const srcDestMapping = ref<Record<string, any>[]>([])
const srcDestMapping = ref<Record<string, Record<string, any>[]>>({})
const data = reactive<{
title: string | null
name: string
tables: (TableType & { ref_table_name: string; columns: (ColumnType & { _disableSelect?: boolean })[] })[]
tables: (TableType & { ref_table_name: string; columns: (ColumnType & { key: number; _disableSelect?: boolean })[] })[]
}>({
title: null,
name: 'Project Name',
@ -106,7 +107,7 @@ const data = reactive<{
const validators = computed(() =>
data.tables.reduce<Record<string, [ReturnType<typeof fieldRequiredValidator>]>>((acc, table, tableIdx) => {
acc[`tables.${tableIdx}.ref_table_name`] = [fieldRequiredValidator()]
acc[`tables.${tableIdx}.table_name`] = [fieldRequiredValidator()]
hasSelectColumn.value[tableIdx] = false
table.columns?.forEach((column, columnIdx) => {
@ -123,24 +124,36 @@ const validators = computed(() =>
const { validate, validateInfos } = useForm(data, validators)
const isValid = computed(() => {
if (importOnly) {
for (const record of srcDestMapping.value) {
if (!fieldsValidation(record)) {
return false
const isValid = ref(!importDataOnly)
watch(
() => srcDestMapping.value,
() => {
let res = true
if (importDataOnly) {
for (const tn of Object.keys(srcDestMapping.value)) {
if (!atLeastOneEnabledValidation(tn)) {
res = false
}
for (const record of srcDestMapping.value[tn]) {
if (!fieldsValidation(record, tn)) {
return false
}
}
}
}
} else {
for (const [_, o] of Object.entries(validateInfos)) {
if (o?.validateStatus) {
if (o.validateStatus === 'error') {
return false
} else {
for (const [_, o] of Object.entries(validateInfos)) {
if (o?.validateStatus) {
if (o.validateStatus === 'error') {
res = false
}
}
}
}
}
return true
})
isValid.value = res
},
{ deep: true },
)
const prevEditableTn = ref<string[]>([])
@ -150,7 +163,11 @@ onMounted(() => {
// used to record the previous EditableTn values
// for checking the table duplication in current import
// and updating the key in importData
prevEditableTn.value = data.tables.map((t) => t.ref_table_name)
prevEditableTn.value = data.tables.map((t) => t.table_name)
if (importDataOnly) {
mapDefaultColumns()
}
nextTick(() => {
inputRefs.value[0]?.focus()
@ -183,7 +200,7 @@ function parseTemplate({ tables = [], ...rest }: Props['projectTemplate']) {
}),
...v.map((v: any) => ({
column_name: v.title,
ref_table_name: {
table_name: {
...v,
},
})),
@ -202,20 +219,20 @@ function deleteTable(tableIdx: number) {
data.tables.splice(tableIdx, 1)
}
function deleteTableColumn(tableIdx: number, columnIdx: number) {
data.tables[tableIdx].columns?.splice(columnIdx, 1)
function deleteTableColumn(tableIdx: number, columnKey: number) {
const columnIdx = data.tables[tableIdx].columns.findIndex((c: ColumnType & { key: number }) => c.key === columnKey)
data.tables[tableIdx].columns.splice(columnIdx, 1)
}
function addNewColumnRow(table: Record<string, any>, uidt?: string) {
table.columns.push({
key: table.columns.length,
column_name: `title${table.columns.length + 1}`,
function addNewColumnRow(tableIdx: number, uidt: string) {
data.tables[tableIdx].columns.push({
key: data.tables[tableIdx].columns.length,
column_name: `title${data.tables[tableIdx].columns.length + 1}`,
uidt,
})
nextTick(() => {
const input = inputRefs.value[table.columns.length - 1]
const input = inputRefs.value[data.tables[tableIdx].columns.length - 1]
input.focus()
input.select()
})
@ -229,7 +246,12 @@ function remapColNames(batchData: any[], columns: ColumnType[]) {
const dateFormatMap: Record<number, string> = {}
return batchData.map((data) =>
(columns || []).reduce((aggObj, col: Record<string, any>) => {
let d = data[col.ref_column_name || col.column_name]
// for excel & json, if the column name is changed in TemplateEditor,
// then only col.column_name exists in data, else col.ref_column_name
// for csv, col.column_name always exists in data
// since it streams the data in getData() with the updated col.column_name
const key = col.column_name in data ? col.column_name : col.ref_column_name
let d = data[key]
if (col.uidt === UITypes.Date && d) {
let dateFormat
if (col?.meta?.date_format) {
@ -241,12 +263,10 @@ function remapColNames(batchData: any[], columns: ColumnType[]) {
dateFormat = getDateFormat(d)
dateFormatMap[col.key] = dateFormat
}
d = dayjs(d).utc().format(dateFormat)
d = parseStringDate(d, dateFormat)
} else if (col.uidt === UITypes.DateTime && d) {
// TODO: handle more formats for DateTime
d = dayjs(data[col.ref_column_name || col.column_name])
.utc()
.format('YYYY-MM-DD HH:mm')
const dateTimeFormat = getDateTimeFormat(data[key])
d = dayjs(data[key], dateTimeFormat).format('YYYY-MM-DD HH:mm')
}
return {
...aggObj,
@ -256,10 +276,11 @@ function remapColNames(batchData: any[], columns: ColumnType[]) {
)
}
function missingRequiredColumnsValidation() {
function missingRequiredColumnsValidation(tn: string) {
const missingRequiredColumns = columns.value.filter(
(c: Record<string, any>) =>
(c.pk ? !c.ai && !c.cdf : !c.cdf && c.rqd) && !srcDestMapping.value.some((r) => r.destCn === c.title),
(c.pk ? !c.ai && !c.cdf : !c.cdf && c.rqd) &&
!srcDestMapping.value[tn].some((r: Record<string, any>) => r.destCn === c.title),
)
if (missingRequiredColumns.length) {
@ -270,153 +291,156 @@ function missingRequiredColumnsValidation() {
return true
}
function atLeastOneEnabledValidation() {
if (srcDestMapping.value.filter((v) => v.enabled === true).length === 0) {
function atLeastOneEnabledValidation(tn: string) {
if (srcDestMapping.value[tn].filter((v: Record<string, any>) => v.enabled === true).length === 0) {
message.error(t('msg.error.selectAtleastOneColumn'))
return false
}
return true
}
function fieldsValidation(record: Record<string, any>) {
function fieldsValidation(record: Record<string, any>, tn: string) {
// if it is not selected, then pass validation
if (!record.enabled) {
return true
}
const tableName = meta.value?.title || ''
if (!record.destCn) {
message.error(`${t('msg.error.columnDescriptionNotFound')} ${record.srcCn}`)
return false
}
if (srcDestMapping.value.filter((v) => v.destCn === record.destCn).length > 1) {
if (srcDestMapping.value[tn].filter((v: Record<string, any>) => v.destCn === record.destCn).length > 1) {
message.error(t('msg.error.duplicateMappingFound'))
return false
}
const v = columns.value.find((c) => c.title === record.destCn) as Record<string, any>
// check if the input contains null value for a required column
if (v.pk ? !v.ai && !v.cdf : !v.cdf && v.rqd) {
if (
importData[tableName]
.slice(0, maxRowsToParse)
.some((r: Record<string, any>) => r[record.srcCn] === null || r[record.srcCn] === undefined || r[record.srcCn] === '')
) {
message.error(t('msg.error.nullValueViolatesNotNull'))
}
}
switch (v.uidt) {
case UITypes.Number:
for (const tableName of Object.keys(importData)) {
// check if the input contains null value for a required column
if (v.pk ? !v.ai && !v.cdf : !v.cdf && v.rqd) {
if (
importData[tableName]
.slice(0, maxRowsToParse)
.some(
(r: Record<string, any>) => r[record.sourceCn] !== null && r[record.srcCn] !== undefined && isNaN(+r[record.srcCn]),
)
.some((r: Record<string, any>) => r[record.srcCn] === null || r[record.srcCn] === undefined || r[record.srcCn] === '')
) {
message.error(t('msg.error.sourceHasInvalidNumbers'))
return false
message.error(t('msg.error.nullValueViolatesNotNull'))
}
}
break
case UITypes.Checkbox:
if (
importData[tableName].slice(0, maxRowsToParse).some((r: Record<string, any>) => {
if (r[record.srcCn] !== null && r[record.srcCn] !== undefined) {
let input = r[record.srcCn]
if (typeof input === 'string') {
input = input.replace(/["']/g, '').toLowerCase().trim()
return !(
input === 'false' ||
input === 'no' ||
input === 'n' ||
input === '0' ||
input === 'true' ||
input === 'yes' ||
input === 'y' ||
input === '1'
)
}
switch (v.uidt) {
case UITypes.Number:
if (
importData[tableName]
.slice(0, maxRowsToParse)
.some(
(r: Record<string, any>) => r[record.sourceCn] !== null && r[record.srcCn] !== undefined && isNaN(+r[record.srcCn]),
)
) {
message.error(t('msg.error.sourceHasInvalidNumbers'))
return false
}
return input !== 1 && input !== 0 && input !== true && input !== false
}
break
case UITypes.Checkbox:
if (
importData[tableName].slice(0, maxRowsToParse).some((r: Record<string, any>) => {
if (r[record.srcCn] !== null && r[record.srcCn] !== undefined) {
let input = r[record.srcCn]
if (typeof input === 'string') {
input = input.replace(/["']/g, '').toLowerCase().trim()
return !(
input === 'false' ||
input === 'no' ||
input === 'n' ||
input === '0' ||
input === 'true' ||
input === 'yes' ||
input === 'y' ||
input === '1'
)
}
return input !== 1 && input !== 0 && input !== true && input !== false
}
return false
})
) {
message.error(t('msg.error.sourceHasInvalidBoolean'))
return false
})
) {
message.error(t('msg.error.sourceHasInvalidBoolean'))
return false
}
break
}
break
}
}
return true
}
function updateImportTips(projectName: string, tableName: string, progress: number, total: number) {
importingTips.value[
`${projectName}-${tableName}`
] = `Importing data to ${projectName} - ${tableName}: ${progress}/${total} records`
}
async function importTemplate() {
if (importOnly) {
// validate required columns
if (!missingRequiredColumnsValidation()) return
if (importDataOnly) {
for (const table of data.tables) {
// validate required columns
if (!missingRequiredColumnsValidation(table.table_name)) return
// validate at least one column needs to be selected
if (!atLeastOneEnabledValidation()) return
// validate at least one column needs to be selected
if (!atLeastOneEnabledValidation(table.table_name)) return
}
try {
isImporting.value = true
const tableName = meta.value?.title
// only one file is allowed currently
const data = importData[Object.keys(importData)[0]]
const projectName = project.value.title!
const total = data.length
for (let i = 0, progress = 0; i < total; i += maxRowsToParse) {
const batchData = data.slice(i, i + maxRowsToParse).map((row: Record<string, any>) =>
srcDestMapping.value.reduce((res: Record<string, any>, col: Record<string, any>) => {
if (col.enabled && col.destCn) {
const v = columns.value.find((c: Record<string, any>) => c.title === col.destCn) as Record<string, any>
let input = row[col.srcCn]
// parse potential boolean values
if (v.uidt === UITypes.Checkbox) {
input = input.replace(/["']/g, '').toLowerCase().trim()
if (input === 'false' || input === 'no' || input === 'n') {
input = '0'
} else if (input === 'true' || input === 'yes' || input === 'y') {
input = '1'
}
} else if (v.uidt === UITypes.Number) {
if (input === '') {
input = null
}
} else if (v.uidt === UITypes.SingleSelect || v.uidt === UITypes.MultiSelect) {
if (input === '') {
input = null
}
}
res[col.destCn] = input
await Promise.all(
Object.keys(importData).map((key: string) =>
(async (k) => {
const data = importData[k]
const total = data.length
for (let i = 0, progress = 0; i < total; i += maxRowsToParse) {
const batchData = data.slice(i, i + maxRowsToParse).map((row: Record<string, any>) =>
srcDestMapping.value[k].reduce((res: Record<string, any>, col: Record<string, any>) => {
if (col.enabled && col.destCn) {
const v = columns.value.find((c: Record<string, any>) => c.title === col.destCn) as Record<string, any>
let input = row[col.srcCn]
// parse potential boolean values
if (v.uidt === UITypes.Checkbox) {
input = input.replace(/["']/g, '').toLowerCase().trim()
if (input === 'false' || input === 'no' || input === 'n') {
input = '0'
} else if (input === 'true' || input === 'yes' || input === 'y') {
input = '1'
}
} else if (v.uidt === UITypes.Number) {
if (input === '') {
input = null
}
} else if (v.uidt === UITypes.SingleSelect || v.uidt === UITypes.MultiSelect) {
if (input === '') {
input = null
}
} else if (v.uidt === UITypes.Date) {
input = parseStringDate(input, v.meta.date_format)
}
res[col.destCn] = input
}
return res
}, {}),
)
await $api.dbTableRow.bulkCreate('noco', projectName, tableName!, batchData)
updateImportTips(projectName, tableName!, progress, total)
progress += batchData.length
}
return res
}, {}),
)
await $api.dbTableRow.bulkCreate('noco', projectName, tableName!, batchData)
importingTip.value = `Importing data to ${projectName}: ${progress}/${total} records`
progress += batchData.length
}
})(key),
),
)
// reload table
reloadHook.trigger()
@ -473,8 +497,8 @@ async function importTemplate() {
}
const tableMeta = await $api.dbTable.create(project?.value?.id as string, {
table_name: table.ref_table_name,
// leave title empty to get a generated one based on ref_table_name
table_name: table.table_name,
// leave title empty to get a generated one based on table_name
title: '',
columns: table.columns || [],
})
@ -493,22 +517,25 @@ async function importTemplate() {
}
// bulk insert data
if (importData) {
let total = 0
let progress = 0
const offset = maxRowsToParse
const projectName = project.value.title as string
await Promise.all(
data.tables.map((table: Record<string, any>) =>
(async (tableMeta) => {
let progress = 0
let total = 0
// use ref_table_name here instead of table_name
// since importData[talbeMeta.table_name] would be empty after renaming
const data = importData[tableMeta.ref_table_name]
if (data) {
total += data.length
for (let i = 0; i < data.length; i += offset) {
importingTip.value = `Importing data to ${projectName}: ${progress}/${total} records`
updateImportTips(projectName, tableMeta.title, progress, total)
const batchData = remapColNames(data.slice(i, i + offset), tableMeta.columns)
await $api.dbTableRow.bulkCreate('noco', projectName, tableMeta.title, batchData)
progress += batchData.length
}
updateImportTips(projectName, tableMeta.title, total, total)
}
})(table),
),
@ -530,18 +557,23 @@ async function importTemplate() {
}
function mapDefaultColumns() {
srcDestMapping.value = []
for (const col of importColumns[0]) {
const o = { srcCn: col.column_name, destCn: '', enabled: true }
if (columns.value) {
const tableColumn = columns.value.find((c: Record<string, any>) => c.title === col.column_name)
if (tableColumn) {
o.destCn = tableColumn.title as string
} else {
o.enabled = false
srcDestMapping.value = {}
for (let i = 0; i < data.tables.length; i++) {
for (const col of importColumns[i]) {
const o = { srcCn: col.column_name, destCn: '', enabled: true }
if (columns.value) {
const tableColumn = columns.value.find((c) => c.column_name === col.column_name)
if (tableColumn) {
o.destCn = tableColumn.title as string
} else {
o.enabled = false
}
}
if (!(data.tables[i].table_name in srcDestMapping.value)) {
srcDestMapping.value[data.tables[i].table_name] = []
}
srcDestMapping.value[data.tables[i].table_name].push(o)
}
srcDestMapping.value.push(o)
}
}
@ -550,24 +582,14 @@ defineExpose({
isValid,
})
onMounted(() => {
if (importOnly) {
mapDefaultColumns()
}
})
function handleEditableTnChange(idx: number) {
const oldValue = prevEditableTn.value[idx]
const newValue = data.tables[idx].ref_table_name
if (data.tables.filter((t) => t.ref_table_name === newValue).length > 1) {
const newValue = data.tables[idx].table_name
if (data.tables.filter((t) => t.table_name === newValue).length > 1) {
message.warn('Duplicate Table Name')
data.tables[idx].ref_table_name = oldValue
data.tables[idx].table_name = oldValue
} else {
prevEditableTn.value[idx] = newValue
if (oldValue !== newValue) {
// update the key name of importData
delete Object.assign(importData, { [newValue]: importData[oldValue] })[oldValue]
}
}
setEditableTn(idx, false)
}
@ -578,8 +600,13 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
</script>
<template>
<a-spin :spinning="isImporting" :tip="importingTip" size="large">
<a-card v-if="importOnly">
<a-spin :spinning="isImporting" size="large">
<template #tip>
<p v-for="(importingTip, idx) of importingTips" :key="idx" class="mt-[10px]">
{{ importingTip }}
</p>
</template>
<a-card v-if="importDataOnly">
<a-form :model="data" name="import-only">
<p v-if="data.tables && quickImportType === 'excel'" class="text-center">
{{ data.tables.length }} sheet{{ data.tables.length > 1 ? 's' : '' }}
@ -592,8 +619,7 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
<template #header>
<span class="font-weight-bold text-lg flex items-center gap-2">
<mdi-table class="text-primary" />
{{ table.ref_table_name }}
{{ table.table_name }}
</span>
</template>
@ -601,7 +627,7 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
v-if="srcDestMapping"
class="template-form"
row-class-name="template-form-row"
:data-source="srcDestMapping"
:data-source="srcDestMapping[table.table_name]"
:columns="srcDestMappingColumns"
:pagination="false"
>
@ -660,21 +686,21 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
>
<a-collapse-panel v-for="(table, tableIdx) of data.tables" :key="tableIdx">
<template #header>
<a-form-item v-if="editableTn[tableIdx]" v-bind="validateInfos[`tables.${tableIdx}.ref_table_name`]" no-style>
<a-form-item v-if="editableTn[tableIdx]" v-bind="validateInfos[`tables.${tableIdx}.table_name`]" no-style>
<a-input
v-model:value="table.ref_table_name"
class="max-w-xs"
v-model:value="table.table_name"
class="max-w-xs font-weight-bold text-lg"
size="large"
hide-details
:bordered="false"
@click="$event.stopPropagation()"
@blur="handleEditableTnChange(tableIdx)"
@keydown.enter="handleEditableTnChange(tableIdx)"
/>
</a-form-item>
<span v-else class="font-weight-bold text-lg flex items-center gap-2" @click="setEditableTn(tableIdx, true)">
<mdi-table class="text-primary" />
{{ table.ref_table_name }}
{{ table.table_name }}
</span>
</template>
@ -723,7 +749,14 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'column_name'">
<a-form-item v-bind="validateInfos[`tables.${tableIdx}.columns.${record.key}.${column.key}`]">
<a-input :ref="inputRefs.set" v-model:value="record.column_name" />
<a-input
:ref="
(el) => {
inputRefs[record.key] = el
}
"
v-model:value="record.column_name"
/>
</a-form-item>
</template>
@ -794,7 +827,7 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
<span>Add Number Column</span>
</template>
<a-button class="group" @click="addNewColumnRow(table, 'Number')">
<a-button class="group" @click="addNewColumnRow(tableIdx, 'Number')">
<div class="flex items-center">
<mdi-numeric class="group-hover:!text-accent flex text-lg" />
</div>
@ -807,7 +840,7 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
<span>Add SingleLineText Column</span>
</template>
<a-button class="group" @click="addNewColumnRow(table, 'SingleLineText')">
<a-button class="group" @click="addNewColumnRow(tableIdx, 'SingleLineText')">
<div class="flex items-center">
<mdi-alpha-a class="group-hover:!text-accent text-lg" />
</div>
@ -820,7 +853,7 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
<span>Add LongText Column</span>
</template>
<a-button class="group" @click="addNewColumnRow(table, 'LongText')">
<a-button class="group" @click="addNewColumnRow(tableIdx, 'LongText')">
<div class="flex items-center">
<mdi-text class="group-hover:!text-accent text-lg" />
</div>
@ -833,7 +866,7 @@ function isSelectDisabled(uidt: string, disableSelect = false) {
<span>Add Other Column</span>
</template>
<a-button class="group" @click="addNewColumnRow(table, 'SingleLineText')">
<a-button class="group" @click="addNewColumnRow(tableIdx, 'SingleLineText')">
<div class="flex items-center gap-1">
<mdi-plus class="group-hover:!text-accent text-lg" />
</div>

2
packages/nc-gui/components/virtual-cell/BelongsTo.vue

@ -31,7 +31,7 @@ const row = inject(RowInj)!
const active = inject(ActiveCellInj)!
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
const isForm = inject(IsFormInj, ref(false))

4
packages/nc-gui/components/virtual-cell/Formula.vue

@ -6,7 +6,7 @@ import { CellValueInj, ColumnInj, computed, handleTZ, inject, ref, replaceUrlsWi
// todo: column type doesn't have required property `error` - throws in typecheck
const column = inject(ColumnInj) as Ref<ColumnType & { colOptions: { error: any } }>
const value = inject(CellValueInj)
const cellValue = inject(CellValueInj)
const { isPg } = useProject()
@ -20,7 +20,7 @@ const showEditFormulaWarningMessage = () => {
}, 3000)
}
const result = computed(() => (isPg.value ? handleTZ(value) : value))
const result = computed(() => (isPg.value ? handleTZ(cellValue?.value) : cellValue?.value))
const urls = computed(() => replaceUrlsWithLink(result.value))
</script>

2
packages/nc-gui/components/virtual-cell/HasMany.vue

@ -27,7 +27,7 @@ const reloadRowTrigger = inject(ReloadRowDataHookInj, createEventHook())
const isForm = inject(IsFormInj)
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj)

2
packages/nc-gui/components/virtual-cell/Lookup.vue

@ -17,7 +17,7 @@ import {
const { metas, getMeta } = useMetas()
provide(ReadonlyInj, true)
provide(ReadonlyInj, ref(true))
const column = inject(ColumnInj)! as Ref<ColumnType & { colOptions: LookupType }>

2
packages/nc-gui/components/virtual-cell/ManyToMany.vue

@ -28,7 +28,7 @@ const reloadRowTrigger = inject(ReloadRowDataHookInj, createEventHook())
const isForm = inject(IsFormInj)
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj)

41
packages/nc-gui/components/virtual-cell/components/ItemChip.vue

@ -1,5 +1,15 @@
<script lang="ts" setup>
import { ActiveCellInj, IsFormInj, IsLockedInj, ReadonlyInj, inject, ref, useLTARStoreOrThrow, useUIPermission } from '#imports'
import {
ActiveCellInj,
IsFormInj,
IsLockedInj,
ReadonlyInj,
inject,
ref,
useExpandedFormDetached,
useLTARStoreOrThrow,
useUIPermission,
} from '#imports'
interface Props {
value?: string | number | boolean
@ -14,7 +24,7 @@ const { relatedTableMeta } = useLTARStoreOrThrow()!
const { isUIAllowed } = useUIPermission()
const readOnly = inject(ReadonlyInj, false)
const readOnly = inject(ReadonlyInj, ref(false))
const active = inject(ActiveCellInj, ref(false))
@ -22,7 +32,19 @@ const isForm = inject(IsFormInj)!
const isLocked = inject(IsLockedInj, ref(false))
const expandedFormDlg = ref(false)
const { open } = useExpandedFormDetached()
function openExpandedForm() {
if (!readOnly && !isLocked.value) {
open({
isOpen: true,
row: { row: item, rowMeta: {}, oldRow: { ...item } },
meta: relatedTableMeta.value,
loadRow: true,
useMetaFields: true,
})
}
}
</script>
<script lang="ts">
@ -35,24 +57,13 @@ export default {
<div
class="chip group py-1 px-2 mr-1 my-1 flex items-center bg-blue-100/60 hover:bg-blue-100/40 rounded-[2px]"
:class="{ active }"
@click="expandedFormDlg = true"
@click="openExpandedForm"
>
<span class="name">{{ value }}</span>
<div v-show="active || isForm" v-if="!readOnly && !isLocked && isUIAllowed('xcDatatableEditable')" class="flex items-center">
<MdiCloseThick class="unlink-icon text-xs text-gray-500/50 group-hover:text-gray-500" @click.stop="emit('unlink')" />
</div>
<Suspense>
<SmartsheetExpandedForm
v-if="!readOnly && !isLocked && expandedFormDlg"
v-model="expandedFormDlg"
:row="{ row: item, rowMeta: {}, oldRow: { ...item } }"
:meta="relatedTableMeta"
load-row
use-meta-fields
/>
</Suspense>
</div>
</template>

4
packages/nc-gui/components/virtual-cell/components/ListChildItems.vue

@ -29,7 +29,7 @@ const isPublic = inject(IsPublicInj, ref(false))
const column = inject(ColumnInj)
const readonly = inject(ReadonlyInj, false)
const readonly = inject(ReadonlyInj, ref(false))
const {
childrenList,
@ -181,7 +181,7 @@ watch(
<LazySmartsheetExpandedForm
v-if="expandedFormRow && expandedFormDlg"
v-model="expandedFormDlg"
:row="{ row: expandedFormRow }"
:row="{ row: expandedFormRow, oldRow: expandedFormRow, rowMeta: {} }"
:meta="relatedTableMeta"
load-row
use-meta-fields

43
packages/nc-gui/composables/useDialog/index.ts

@ -1,17 +1,22 @@
import type { VNode } from '@vue/runtime-dom'
import { isVNode, render } from '@vue/runtime-dom'
import type { AppContext, VNode } from '@vue/runtime-dom'
import { Suspense, isVNode, render } from '@vue/runtime-dom'
import type { ComponentPublicInstance } from '@vue/runtime-core'
import type { MaybeRef } from '@vueuse/core'
import { isClient } from '@vueuse/core'
import { createEventHook, h, ref, toReactive, tryOnScopeDispose, unref, useNuxtApp, watch } from '#imports'
interface UseDialogOptions {
target: MaybeRef<HTMLElement | ComponentPublicInstance>
context: Partial<AppContext>
}
/**
* Programmatically create a component and attach it to the body (or a specific mount target), like a dialog or modal.
* This composable is not SSR friendly - it should be used only on the client.
*
* @param componentOrVNode The component to create and attach. Can be a VNode or a component definition.
* @param props The props to pass to the component.
* @param mountTarget The target to attach the component to. Defaults to the document body
* @param options Additional options to use {@see UseDialogOptions}
*
* @example
* import { useDialog } from '#imports'
@ -39,7 +44,7 @@ import { createEventHook, h, ref, toReactive, tryOnScopeDispose, unref, useNuxtA
export function useDialog(
componentOrVNode: any,
props: NonNullable<Parameters<typeof h>[1]> = {},
mountTarget?: MaybeRef<Element | ComponentPublicInstance>,
{ target, context }: Partial<UseDialogOptions> = {},
) {
if (typeof document === 'undefined' || !isClient) {
console.warn('[useDialog]: Cannot use outside of browser!')
@ -54,24 +59,36 @@ export function useDialog(
const vNodeRef = ref<VNode>()
let _mountTarget = unref(mountTarget)
_mountTarget = _mountTarget ? ('$el' in _mountTarget ? (_mountTarget.$el as HTMLElement) : _mountTarget) : document.body
/** if specified, append vnode to mount target instead of document.body */
_mountTarget.appendChild(domNode)
const mountTarget = ref<HTMLElement>()
/** When props change, we want to re-render the element with the new prop values */
const stop = watch(
toReactive(props),
(reactiveProps) => {
const _mountTarget = unref(target)
/**
* If it's a component instance, use the instance's root element (`$el`), otherwise use the element itself
* If no target is specified, use the document body
*/
mountTarget.value = _mountTarget
? '$el' in _mountTarget
? (_mountTarget.$el as HTMLElement)
: _mountTarget
: document.body
/** if specified, append vnode to mount target instead of document.body */
mountTarget.value.appendChild(domNode)
// if it's a vnode, just render it, otherwise wrap in `h` to create a vnode
const vNode = isVNode(componentOrVNode) ? componentOrVNode : h(componentOrVNode, reactiveProps)
vNode.appContext = useNuxtApp().vueApp._context
vNode.appContext = { ...useNuxtApp().vueApp._context, ...context }
vNodeRef.value = vNode
render(vNode, domNode)
// wrap in suspense to resolve potential promises
render(h(Suspense, vNode), domNode)
if (!isMounted) mountedHook.trigger()
},
@ -90,7 +107,7 @@ export function useDialog(
setTimeout(() => {
try {
;(_mountTarget as HTMLElement)?.removeChild(domNode)
;(mountTarget.value as HTMLElement)?.removeChild(domNode)
} catch (e) {}
}, 100)

44
packages/nc-gui/composables/useExpandedFormDetached/index.ts

@ -0,0 +1,44 @@
import type { TableType, ViewType } from 'nocodb-sdk'
import { createEventHook, ref, useInjectionState } from '#imports'
import type { Row } from '~/lib'
interface UseExpandedFormDetachedProps {
'isOpen'?: boolean
'row': Row | null
'state'?: Record<string, any> | null
'meta': TableType
'loadRow'?: boolean
'useMetaFields'?: boolean
'rowId'?: string
'view'?: ViewType
'onCancel'?: Function
'onUpdate:modelValue'?: Function
}
const [setup, use] = useInjectionState(() => {
return ref<UseExpandedFormDetachedProps[]>([])
})
export function useExpandedFormDetached() {
let states = use()!
if (!states) {
states = setup()
}
const closeHook = createEventHook<void>()
const index = ref(-1)
const open = (props: UseExpandedFormDetachedProps) => {
states.value.push(props)
index.value = states.value.length - 1
}
const close = (i?: number) => {
states.value.splice(i || index.value, 1)
if (index.value === i || !i) closeHook.trigger()
}
return { states, open, close, onClose: closeHook.on }
}

2
packages/nc-gui/composables/useMultiSelect/index.ts

@ -14,7 +14,7 @@ export function useMultiSelect(
fields: MaybeRef<any[]>,
data: MaybeRef<any[]>,
editEnabled: MaybeRef<boolean>,
isPkAvail: MaybeRef<boolean>,
isPkAvail: MaybeRef<boolean | undefined>,
clearCell: Function,
makeEditable: Function,
scrollToActiveCell?: (row?: number | null, col?: number | null) => void,

8
packages/nc-gui/composables/useRoles/index.ts

@ -12,7 +12,7 @@ import type { ProjectRole, Role, Roles } from '~/lib'
* * `loadProjectRoles` - a function to load the project roles for a specific project (by id)
*/
export const useRoles = createSharedComposable(() => {
const { user } = useGlobal()
const { user, previewAs } = useGlobal()
const { api } = useApi()
@ -57,7 +57,11 @@ export const useRoles = createSharedComposable(() => {
}
}
function hasRole(role: Role | ProjectRole | string) {
function hasRole(role: Role | ProjectRole | string, includePreviewRoles = false) {
if (previewAs.value && includePreviewRoles) {
return previewAs.value === role
}
return allRoles.value[role]
}

2
packages/nc-gui/composables/useSharedFormViewStore.ts

@ -45,7 +45,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
const { t } = useI18n()
const formState = ref({})
const formState = ref<Record<string, any>>({})
const { state: additionalState } = useProvideSmartsheetRowStore(
meta as Ref<TableType>,

14
packages/nc-gui/composables/useSmartsheetStore.ts

@ -1,21 +1,21 @@
import { ViewTypes } from 'nocodb-sdk'
import type { FilterType, KanbanType, SortType, TableType, ViewType } from 'nocodb-sdk'
import type { Ref } from 'vue'
import { computed, reactive, ref, unref, useInjectionState, useNuxtApp, useProject, useTemplateRefsList } from '#imports'
import { computed, reactive, ref, unref, useInjectionState, useNuxtApp, useProject } from '#imports'
const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
(
view: Ref<ViewType | undefined>,
meta: Ref<TableType | KanbanType | undefined>,
shared = false,
initalSorts?: Ref<SortType[]>,
initialSorts?: Ref<SortType[]>,
initialFilters?: Ref<FilterType[]>,
) => {
const { $api } = useNuxtApp()
const { sqlUi } = useProject()
const cellRefs = useTemplateRefsList<HTMLTableDataCellElement>()
const cellRefs = ref<HTMLTableDataCellElement[]>([])
// state
// todo: move to grid view store
@ -51,7 +51,7 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
const isSqlView = computed(() => (meta.value as TableType)?.type === 'view')
const sorts = ref<SortType[]>(unref(initalSorts) ?? [])
const sorts = ref<SortType[]>(unref(initialSorts) ?? [])
const nestedFilters = ref<FilterType[]>(unref(initialFilters) ?? [])
return {
@ -80,9 +80,9 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
export { useProvideSmartsheetStore }
export function useSmartsheetStoreOrThrow() {
const smartsheetStore = useSmartsheetStore()
const state = useSmartsheetStore()
if (smartsheetStore == null) throw new Error('Please call `useSmartsheetStore` on the appropriate parent component')
if (!state) throw new Error('Please call `useProvideSmartsheetStore` on the appropriate parent component')
return smartsheetStore
return state
}

18
packages/nc-gui/composables/useViewData.ts

@ -202,7 +202,6 @@ export function useViewData(
async function insertRow(
currentRow: Row,
_rowIndex = formattedData.value?.length,
ltarState: Record<string, any> = {},
{ metaValue = meta.value, viewMetaValue = viewMeta.value }: { metaValue?: TableType; viewMetaValue?: ViewType } = {},
) {
@ -266,15 +265,24 @@ export function useViewData(
)
// audit
$api.utils.auditRowUpdate(id, {
fk_model_id: meta.value?.id as string,
fk_model_id: metaValue?.id as string,
column_name: property,
row_id: id,
value: getHTMLEncodedText(toUpdate.row[property]),
prev_value: getHTMLEncodedText(toUpdate.oldRow[property]),
})
/** update row data(to sync formula and other related columns) */
Object.assign(toUpdate.row, updatedRowData)
/** update row data(to sync formula and other related columns)
* update only formula, rollup and auto updated datetime columns data to avoid overwriting any changes made by user
*/
Object.assign(
toUpdate.row,
metaValue!.columns!.reduce<Record<string, any>>((acc: Record<string, any>, col: ColumnType) => {
if (col.uidt === UITypes.Formula || col.uidt === UITypes.Rollup || col.au || col.cdf?.includes(' on update '))
acc[col.title!] = updatedRowData[col.title!]
return acc
}, {} as Record<string, any>),
)
Object.assign(toUpdate.oldRow, updatedRowData)
} catch (e: any) {
message.error(`${t('msg.error.rowUpdateFailed')} ${await extractSdkResponseErrorMsg(e)}`)
@ -293,7 +301,7 @@ export function useViewData(
await until(() => !(row.rowMeta?.new && row.rowMeta?.saving)).toMatch((v) => v)
if (row.rowMeta.new) {
return await insertRow(row, formattedData.value.indexOf(row), ltarState, args)
return await insertRow(row, ltarState, args)
} else {
await updateRowProperty(row, property!, args)
}

2
packages/nc-gui/context/index.ts

@ -21,7 +21,7 @@ export const IsKanbanInj: InjectionKey<Ref<boolean>> = Symbol('is-kanban-injecti
export const IsLockedInj: InjectionKey<Ref<boolean>> = Symbol('is-locked-injection')
export const CellValueInj: InjectionKey<Ref<any>> = Symbol('cell-value-injection')
export const ActiveViewInj: InjectionKey<Ref<ViewType>> = Symbol('active-view-injection')
export const ReadonlyInj: InjectionKey<boolean> = Symbol('readonly-injection')
export const ReadonlyInj: InjectionKey<Ref<boolean>> = Symbol('readonly-injection')
/** when bool is passed, it indicates if a loading spinner should be visible while reloading */
export const ReloadViewDataHookInj: InjectionKey<EventHook<boolean | void>> = Symbol('reload-view-data-injection')
export const ReloadViewMetaHookInj: InjectionKey<EventHook<boolean | void>> = Symbol('reload-view-meta-injection')

34
packages/nc-gui/lang/fr.json

@ -106,7 +106,7 @@
"commenter": "Commentateur",
"viewer": "Lecture seule"
},
"sqlVIew": "SQL View"
"sqlVIew": "Vue SQL"
},
"datatype": {
"ID": "Identifiant",
@ -160,7 +160,7 @@
"isNotNull": "est non null"
},
"title": {
"erdView": "ERD View",
"erdView": "Vue ERD",
"newProj": "Nouveau projet",
"myProject": "Mes projets",
"formTitle": "Intitulé du formulaire",
@ -188,10 +188,10 @@
"headLogin": "Connexion | Nocodb",
"resetPassword": "Réinitialiser le mot de passe",
"teamAndSettings": "Équipe & paramètres",
"apiDocs": "API Docs",
"apiDocs": "Docs API",
"importFromAirtable": "Importer depuis Airtable",
"generateToken": "Generate Token",
"APIsAndSupport": "APIs & Support",
"APIsAndSupport": "Les API et la prise en charge",
"helpCenter": "Help center",
"swaggerDocumentation": "Swagger Documentation",
"quickImportFrom": "Quick Import From",
@ -271,10 +271,10 @@
"accentColor": "Accent Color",
"customTheme": "Custom Theme",
"requestDataSource": "Request a data source you need?",
"apiKey": "API Key",
"apiKey": "Clé d'API",
"sharedBase": "Shared Base",
"importData": "Import Data",
"importSecondaryViews": "Import Secondary Views",
"importSecondaryViews": "Importer des vues secondaires",
"importRollupColumns": "Import Rollup Columns",
"importLookupColumns": "Import Lookup Columns",
"importAttachmentColumns": "Import Attachment Columns",
@ -324,7 +324,7 @@
"translate": "Aider à la traduction",
"account": {
"authToken": "Copier le jeton d'authentification",
"swagger": "Swagger: REST APIs",
"swagger": "Swagger : les API REST",
"projInfo": "Copier les informations du projet",
"themes": "Thèmes"
},
@ -406,7 +406,7 @@
"sponsorUs": "Nous Parrainer",
"sendEmail": "ENVOYER UN EMAIL",
"addUserToProject": "Add user to project",
"getApiSnippet": "Get API Snippet",
"getApiSnippet": "Récupérer le Snippet API",
"clearCell": "Clear cell",
"addFilterGroup": "Add Filter Group",
"linkRecord": "Link record",
@ -418,7 +418,7 @@
"erd": {
"showColumns": "Show Columns",
"showPkAndFk": "Show Primary and Foreign Keys",
"showSqlViews": "Show SQL Views",
"showSqlViews": "Afficher les vues SQL",
"showMMTables": "Show Many to Many tables",
"showJunctionTableNames": "Show Junction Table Names"
},
@ -434,8 +434,8 @@
"saveChanges": "Sauvegarder les modifications",
"xcDB": "Créer un nouveau projet",
"extDB": "Base de données supportées MySQL, PostgreSQL, SQL Server & SQLite",
"apiRest": "Accessible via l'API REST",
"apiGQL": "Accessible via l'API GraphQL",
"apiRest": "Accessible via les API REST",
"apiGQL": "Accessible via les API GraphQL",
"theme": {
"dark": "Nuit (^⇧B)",
"light": "Jour (^⇧B)"
@ -582,7 +582,7 @@
"requriedFieldsCantBeMoved": "Required field can't be moved",
"updateNotAllowedWithoutPK": "Update not allowed for table which doesn't have primary key",
"autoIncFieldNotEditable": "Auto increment field is not editable",
"editingPKnotSupported": "Editing primary key not supported",
"editingPKnotSupported": "Modification de la clé primaire non prise en charge",
"deletedCache": "Deleted cache successfully",
"cacheEmpty": "Cache is empty",
"exportedCache": "Exported Cache Successfully",
@ -590,7 +590,7 @@
"noColumnsToUpdate": "No columns to update",
"tableDeleted": "Deleted table successfully",
"generatePublicShareableReadonlyBase": "Generate publicly shareable readonly base",
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteViewConfirmation": "Êtes-vous sûr de vouloir effacer cette vue ?",
"deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack."
@ -639,7 +639,7 @@
"rowUpdateFailed": "Row update failed",
"deleteRowFailed": "Failed to delete row",
"setFormDataFailed": "Failed to set form data",
"formViewUpdateFailed": "Failed to update form view",
"formViewUpdateFailed": "Échec de la mise à jour de la vue du formulaire",
"tableNameRequired": "Table name is required",
"nameShouldStartWithAnAlphabetOr_": "Name should start with an alphabet or _",
"followingCharactersAreNotAllowed": "Following characters are not allowed",
@ -678,12 +678,12 @@
"pluginSettingsSaved": "Plugin settings saved successfully",
"pluginTested": "Successfully tested plugin settings",
"tableRenamed": "Table renamed successfully",
"viewDeleted": "View deleted successfully",
"viewDeleted": "Vue effacée avec succès",
"primaryColumnUpdated": "Successfully updated as primary column",
"tableDataExported": "Successfully exported all table data",
"updated": "Successfully updated",
"sharedViewDeleted": "Deleted shared view successfully",
"viewRenamed": "View renamed successfully",
"sharedViewDeleted": "Vue partagée effacée avec succès",
"viewRenamed": "Vue renommée avec succès",
"tokenGenerated": "Token generated successfully",
"tokenDeleted": "Token deleted successfully",
"userAddedToProject": "Successfully added user to project",

26
packages/nc-gui/lang/it.json

@ -1,6 +1,6 @@
{
"general": {
"home": "Home",
"home": "Pagina iniziale",
"load": "Carica",
"open": "Apri",
"close": "Chiudi",
@ -56,15 +56,15 @@
"notification": "Notifica",
"reference": "Riferimento",
"function": "Funzione",
"confirm": "Confirm",
"generate": "Generate",
"copy": "Copy",
"confirm": "Conferma",
"generate": "Genera",
"copy": "Copia",
"misc": "Miscellaneous",
"lock": "Lock",
"unlock": "Unlock",
"credentials": "Credentials",
"help": "Help",
"questions": "Questions",
"lock": "Blocca",
"unlock": "Sblocca",
"credentials": "Credenziali",
"help": "Aiuto",
"questions": "Domande",
"reachOut": "Reach out here",
"betaNote": "This feature is currently in beta.",
"moreInfo": "More information can be found here",
@ -109,7 +109,7 @@
"sqlVIew": "SQL View"
},
"datatype": {
"ID": "ID",
"ID": "Numero",
"ForeignKey": "Chiave straniera",
"SingleLineText": "Testo a riga singola",
"LongText": "Testo lungo",
@ -196,7 +196,7 @@
"swaggerDocumentation": "Swagger Documentation",
"quickImportFrom": "Quick Import From",
"quickImport": "Quick Import",
"advancedSettings": "Advanced Settings",
"advancedSettings": "Impostazioni Avanzate",
"codeSnippet": "Code Snippet"
},
"labels": {
@ -266,10 +266,10 @@
"onUpdate": "All'aggiornamento",
"onDelete": "All'eliminazione",
"account": "Account",
"language": "Language",
"language": "Lingua",
"primaryColor": "Primary Color",
"accentColor": "Accent Color",
"customTheme": "Custom Theme",
"customTheme": "Tema Personalizzato",
"requestDataSource": "Request a data source you need?",
"apiKey": "API Key",
"sharedBase": "Shared Base",

372
packages/nc-gui/lang/pl.json

@ -16,7 +16,7 @@
"cancel": "Anuluj",
"submit": "Składać",
"create": "Utwórz",
"duplicate": "Duplicate",
"duplicate": "Duplikuj",
"insert": "Wstawić",
"delete": "Kasować",
"update": "Aktualizacja",
@ -56,20 +56,20 @@
"notification": "Powiadomienie",
"reference": "Sprawdzenie",
"function": "Funkcjonować",
"confirm": "Confirm",
"generate": "Generate",
"copy": "Copy",
"misc": "Miscellaneous",
"lock": "Lock",
"unlock": "Unlock",
"credentials": "Credentials",
"help": "Help",
"questions": "Questions",
"reachOut": "Reach out here",
"betaNote": "This feature is currently in beta.",
"moreInfo": "More information can be found here",
"logs": "Logs",
"groupingField": "Grouping Field"
"confirm": "Zatwierdź",
"generate": "Wygeneruj",
"copy": "Kopiuj",
"misc": "Pozostałe",
"lock": "Zablokuj",
"unlock": "Odblokuj",
"credentials": "Dane uwierzytelniające",
"help": "Pomoc",
"questions": "Pytania",
"reachOut": "Skontaktuj się tutaj",
"betaNote": "Ta funkcja jest nadal w fazie beta.",
"moreInfo": "Więcej informacji można znaleźć tutaj",
"logs": "Logi",
"groupingField": "Grupowanie pola"
},
"objects": {
"project": "Projekt",
@ -106,10 +106,10 @@
"commenter": "Komentator",
"viewer": "Widz"
},
"sqlVIew": "SQL View"
"sqlVIew": "Widok SQL"
},
"datatype": {
"ID": "ID",
"ID": "Identyfikator",
"ForeignKey": "Klucz obcy",
"SingleLineText": "Tekst pojedynczy linii",
"LongText": "Długi tekst",
@ -160,7 +160,7 @@
"isNotNull": "nie jest null."
},
"title": {
"erdView": "ERD View",
"erdView": "Widok ERD",
"newProj": "Nowy projekt",
"myProject": "Moje projekty",
"formTitle": "Tytuł formy",
@ -187,17 +187,17 @@
"headCreateProject": "Utwórz projekt |. NOCODB.",
"headLogin": "Zaloguj się | NOCODB.",
"resetPassword": "Zresetuj swoje hasło",
"teamAndSettings": "Team & Settings",
"apiDocs": "API Docs",
"importFromAirtable": "Import From Airtable",
"generateToken": "Generate Token",
"APIsAndSupport": "APIs & Support",
"helpCenter": "Help center",
"swaggerDocumentation": "Swagger Documentation",
"quickImportFrom": "Quick Import From",
"quickImport": "Quick Import",
"advancedSettings": "Advanced Settings",
"codeSnippet": "Code Snippet"
"teamAndSettings": "Ustawienia zespołu",
"apiDocs": "Dokumentacja API",
"importFromAirtable": "Importuj z Airtable",
"generateToken": "Wygeneruj token",
"APIsAndSupport": "API i Wsparcie",
"helpCenter": "Centrum pomocy",
"swaggerDocumentation": "Dokumentacja Swagger",
"quickImportFrom": "Szybki import z",
"quickImport": "Szybki import",
"advancedSettings": "Ustawienia zaawansowane",
"codeSnippet": "Snippet"
},
"labels": {
"notifyVia": "Powiadomić VIA.",
@ -217,7 +217,7 @@
"port": "Numer portu",
"username": "Nazwa użytkownika",
"password": "Hasło",
"schemaName": "Schema name",
"schemaName": "Nazwa schematu",
"database": "Baza danych",
"action": "Akcja",
"actions": "działania",
@ -255,7 +255,7 @@
"bookDemo": "Zarezerwuj darmowe demo",
"getAnswered": "Odpowiedzi na pytania",
"joinDiscord": "Dołącz do Discord.",
"joinCommunity": "Join NocoDB Community",
"joinCommunity": "Dołącz do społeczności NocoDB",
"joinReddit": "Dołącz /r/NocoDB",
"followNocodb": "Śledź NocoDB"
},
@ -265,38 +265,38 @@
"childColumn": "Kolumna dla dzieci",
"onUpdate": "Na aktualizacji",
"onDelete": "Na delete.",
"account": "Account",
"language": "Language",
"primaryColor": "Primary Color",
"accentColor": "Accent Color",
"customTheme": "Custom Theme",
"requestDataSource": "Request a data source you need?",
"apiKey": "API Key",
"sharedBase": "Shared Base",
"importData": "Import Data",
"importSecondaryViews": "Import Secondary Views",
"importRollupColumns": "Import Rollup Columns",
"importLookupColumns": "Import Lookup Columns",
"importAttachmentColumns": "Import Attachment Columns",
"importFormulaColumns": "Import Formula Columns",
"noData": "No Data",
"goToDashboard": "Go to Dashboard",
"importing": "Importing",
"flattenNested": "Flatten Nested",
"downloadAllowed": "Download allowed",
"weAreHiring": "We are Hiring!",
"primaryKey": "Primary key",
"hasMany": "has many",
"belongsTo": "belongs to",
"manyToMany": "have many to many relation",
"extraConnectionParameters": "Extra connection parameters",
"commentsOnly": "Comments only",
"documentation": "Documentation",
"subscribeNewsletter": "Subscribe to our weekly newsletter",
"signUpWithGoogle": "Sign up with Google",
"signInWithGoogle": "Sign in with Google",
"agreeToTos": "By signing up, you agree to the Terms of Service",
"welcomeToNc": "Welcome to NocoDB!"
"account": "Konto",
"language": "Język",
"primaryColor": "Kolor podstawowy",
"accentColor": "Kolor akcentu",
"customTheme": "Motyw Niestandardowy",
"requestDataSource": "Poproś o źródło danych, którego potrzebujesz.",
"apiKey": "Klucz API",
"sharedBase": "Udostępniona baza",
"importData": "Import Danych",
"importSecondaryViews": "Importuj Drugorzędne Widoki",
"importRollupColumns": "Importuj kolumny Rollup",
"importLookupColumns": "Importuj kolumny wyszukiwania",
"importAttachmentColumns": "Importuj kolumny załączników",
"importFormulaColumns": "Importuj kolumny formuły",
"noData": "Brak danych",
"goToDashboard": "Przejdź do pulpitu",
"importing": "Importowanie",
"flattenNested": "Spłaszcz zagnieżdżone",
"downloadAllowed": "Pobieranie dozwolone",
"weAreHiring": "Zatrudniamy!",
"primaryKey": "Klucz główny",
"hasMany": "ma wiele",
"belongsTo": "należy do",
"manyToMany": "ma wiele relacji do wielu",
"extraConnectionParameters": "Dodatkowe parametry połączenia",
"commentsOnly": "Tylko komentarze",
"documentation": "Dokumentacja",
"subscribeNewsletter": "Zapisz się do naszego cotygodniowego newslettera",
"signUpWithGoogle": "Zarejestruj się przez Google",
"signInWithGoogle": "Zaloguj się przez Google",
"agreeToTos": "Rejestrując się, akceptujesz warunki korzystania z usługi",
"welcomeToNc": "Witaj w NocoDB!"
},
"activity": {
"createProject": "Utwórz projekt",
@ -309,7 +309,7 @@
"deleteProject": "Usuń Projekt.",
"refreshProject": "Odśwież projekty",
"saveProject": "Zapisz Projekt",
"deleteKanbanStack": "Delete stack?",
"deleteKanbanStack": "Usunąć stos?",
"createProjectExtended": {
"extDB": "Utwórz przez podłączenie <br> do zewnętrznej bazy danych",
"excel": "Utwórz projekt z Excel",
@ -324,7 +324,7 @@
"translate": "Pomóż przetłumaczyć",
"account": {
"authToken": "Skopiuj auth token.",
"swagger": "Swagger: REST APIs",
"swagger": "Swagger: REST API",
"projInfo": "Skopiuj informacje o projekcie.",
"themes": "Tematy"
},
@ -366,11 +366,11 @@
"deleteRow": "Usuń rząd",
"deleteSelectedRow": "Usuń wybrane wiersze",
"importExcel": "Importuj Excel.",
"importCSV": "Import CSV",
"importCSV": "Importuj z CSV",
"downloadCSV": "Pobierz jako CSV.",
"downloadExcel": "Pobierz jako XLSX",
"uploadCSV": "Prześlij CSV.",
"import": "Import",
"import": "Importuj",
"importMetadata": "Importuj metadane",
"exportMetadata": "Eksportuj metadane",
"clearMetadata": "Wyczyść metadane",
@ -405,29 +405,29 @@
"editConnJson": "Edytuj połączenie JSON.",
"sponsorUs": "Sponsor",
"sendEmail": "WYSŁAĆ EMAIL",
"addUserToProject": "Add user to project",
"getApiSnippet": "Get API Snippet",
"clearCell": "Clear cell",
"addFilterGroup": "Add Filter Group",
"linkRecord": "Link record",
"addNewRecord": "Add new record",
"useConnectionUrl": "Use Connection URL",
"toggleCommentsDraw": "Toggle comments draw",
"expandRecord": "Expand Record",
"deleteRecord": "Delete Record",
"addUserToProject": "Dodaj użytkownika do projektu",
"getApiSnippet": "Pobierz Snippet API",
"clearCell": "Wyczyść komórkę",
"addFilterGroup": "Dodaj grupę filtrów",
"linkRecord": "Połącz rekord",
"addNewRecord": "Dodaj nowy rekord",
"useConnectionUrl": "Użyj adresu URL połączenia",
"toggleCommentsDraw": "Przełącz rysowanie komentarzy",
"expandRecord": "Rozwiń Rekord",
"deleteRecord": "Usuń rekord",
"erd": {
"showColumns": "Show Columns",
"showPkAndFk": "Show Primary and Foreign Keys",
"showSqlViews": "Show SQL Views",
"showMMTables": "Show Many to Many tables",
"showJunctionTableNames": "Show Junction Table Names"
"showColumns": "Pokaż kolumny",
"showPkAndFk": "Pokaż klucze podstawowe i obce",
"showSqlViews": "Pokaż widoki SQL",
"showMMTables": "Pokaż wiele do wielu tabele",
"showJunctionTableNames": "Pokaż nazwy tabel połączeń"
},
"kanban": {
"collapseStack": "Collapse Stack",
"deleteStack": "Delete Stack",
"stackedBy": "Stacked By",
"chooseGroupingField": "Choose a Grouping Field",
"addOrEditStack": "Add / Edit Stack"
"collapseStack": "Zwiń stos",
"deleteStack": "Usuń stos",
"stackedBy": "Ułożone według",
"chooseGroupingField": "Wybierz pole grupowania",
"addOrEditStack": "Dodaj / Edytuj stos"
}
},
"tooltip": {
@ -475,8 +475,8 @@
"noItemsFound": "Nie znaleziono przedmiotów",
"defaultValue": "Domyślna wartość",
"filterByEmail": "Filtruj e-mailem",
"filterQuery": "Filter query",
"selectField": "Select field"
"filterQuery": "Filtruj zapytanie",
"selectField": "Wybierz pole"
},
"msg": {
"info": {
@ -570,30 +570,30 @@
"addDefaultColumns": "Dodaj domyślne kolumny",
"tableNameInDb": "Nazwa tabeli została zapisana w bazie danych",
"airtable": {
"credentials": "Where to find this?"
"credentials": "Gdzie to znaleźć?"
},
"import": {
"clickOrDrag": "Click or drag file to this area to upload"
"clickOrDrag": "Kliknij lub przeciągnij plik do tego obszaru, aby przesłać"
},
"metaDataRecreated": "Table metadata recreated successfully",
"invalidCredentials": "Invalid credentials",
"downloadingMoreFiles": "Downloading more files",
"copiedToClipboard": "Copied to clipboard",
"requriedFieldsCantBeMoved": "Required field can't be moved",
"updateNotAllowedWithoutPK": "Update not allowed for table which doesn't have primary key",
"autoIncFieldNotEditable": "Auto increment field is not editable",
"editingPKnotSupported": "Editing primary key not supported",
"deletedCache": "Deleted cache successfully",
"cacheEmpty": "Cache is empty",
"exportedCache": "Exported Cache Successfully",
"valueAlreadyInList": "This value is already in the list",
"noColumnsToUpdate": "No columns to update",
"tableDeleted": "Deleted table successfully",
"generatePublicShareableReadonlyBase": "Generate publicly shareable readonly base",
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack."
"metaDataRecreated": "Pomyślnie przywrócono metadane tabeli",
"invalidCredentials": "Nieprawidłowe dane logowania",
"downloadingMoreFiles": "Pobieranie większej liczby plików",
"copiedToClipboard": "Skopiowano do schowka",
"requriedFieldsCantBeMoved": "Wymagane pole nie może być przeniesione",
"updateNotAllowedWithoutPK": "Aktualizacja niedozwolona dla tabeli, która nie ma klucza podstawowego",
"autoIncFieldNotEditable": "Pole automatycznego przyrostu nie jest edytowalne",
"editingPKnotSupported": "Edycja klucza głównego nie jest obsługiwana",
"deletedCache": "Usunięto pamięć podręczną",
"cacheEmpty": "Pamięć podręczna jest pusta",
"exportedCache": "Wyeksportowano pamięć podręczną",
"valueAlreadyInList": "Ta wartość jest już na liście",
"noColumnsToUpdate": "Brak kolumn do aktualizacji",
"tableDeleted": "Tabela usunięta pomyślnie",
"generatePublicShareableReadonlyBase": "Generuj publicznie udostępnioną bazę tylko do odczytu",
"deleteViewConfirmation": "Czy na pewno chcesz usunąć ten widok?",
"deleteTableConfirmation": "Czy chcesz usunąć tabelę",
"showM2mTables": "Pokaż tabele M2M",
"deleteKanbanStackConfirmation": "Usunięcie tego stosu spowoduje również usunięcie wybranej opcji `{stackToBeDeleted}` z `{groupingField}`. Rekordy przeniosą się do nieskategoryzowanego stosu."
},
"error": {
"searchProject": "Twoje wyszukiwanie dla {search}, nie znaleziono żadnych wyników",
@ -609,51 +609,51 @@
"passwdRequired": "Wymagane jest hasło",
"passwdLength": "Użytkownik musi być co najmniej 8 znaków",
"passwdMismatch": "Hasła nie pasują do siebie",
"completeRuleSet": "At least 8 characters with one Uppercase, one number and one special character",
"atLeast8Char": "At least 8 characters",
"atLeastOneUppercase": "One Uppercase letter",
"atLeastOneNumber": "One Number",
"atLeastOneSpecialChar": "One special character",
"allowedSpecialCharList": "Allowed special character list"
"completeRuleSet": "Co najmniej 8 znaków z jedną wielką literą, jedną cyfrą i jednym znakiem specjalnym",
"atLeast8Char": "Co najmniej 8 znaków",
"atLeastOneUppercase": "Jedna wielka litera",
"atLeastOneNumber": "Jedna cyfra",
"atLeastOneSpecialChar": "Jeden znak specjalny",
"allowedSpecialCharList": "Dozwolona lista znaków specjalnych"
},
"invalidURL": "Invalid URL",
"internalError": "Some internal error occurred",
"templateGeneratorNotFound": "Template Generator cannot be found!",
"fileUploadFailed": "Failed to upload file",
"primaryColumnUpdateFailed": "Failed to update primary column",
"formDescriptionTooLong": "Data too long for Form Description",
"columnsRequired": "Following columns are required",
"selectAtleastOneColumn": "At least one column has to be selected",
"columnDescriptionNotFound": "Cannot find the destination column for",
"duplicateMappingFound": "Duplicate mapping found, please remove one of the mapping",
"nullValueViolatesNotNull": "Null value violates not-null constraint",
"sourceHasInvalidNumbers": "Source data contains some invalid numbers",
"sourceHasInvalidBoolean": "Source data contains some invalid boolean values",
"invalidForm": "Invalid Form",
"formValidationFailed": "Form validation failed",
"youHaveBeenSignedOut": "You have been signed out",
"failedToLoadList": "Failed to load list",
"failedToLoadChildrenList": "Failed to load children list",
"deleteFailed": "Delete failed",
"unlinkFailed": "Unlink failed",
"rowUpdateFailed": "Row update failed",
"deleteRowFailed": "Failed to delete row",
"setFormDataFailed": "Failed to set form data",
"formViewUpdateFailed": "Failed to update form view",
"tableNameRequired": "Table name is required",
"nameShouldStartWithAnAlphabetOr_": "Name should start with an alphabet or _",
"followingCharactersAreNotAllowed": "Following characters are not allowed",
"columnNameRequired": "Column name is required",
"projectNameExceeds50Characters": "Project name exceeds 50 characters",
"projectNameCannotStartWithSpace": "Project name cannot start with space",
"requiredField": "Required field",
"ipNotAllowed": "IP not allowed",
"targetFileIsNotAnAcceptedFileType": "Target file is not an accepted file type",
"theAcceptedFileTypeIsCsv": "The accepted file type is .csv",
"theAcceptedFileTypesAreXlsXlsxXlsmOdsOts": "The accepted file types are .xls, .xlsx, .xlsm, .ods, .ots",
"parameterKeyCannotBeEmpty": "Parameter key cannot be empty",
"duplicateParameterKeysAreNotAllowed": "Duplicate parameter keys are not allowed",
"fieldRequired": "{value} cannot be empty."
"invalidURL": "Nieprawidłowy adres URL",
"internalError": "Wystąpił błąd wewnętrzny",
"templateGeneratorNotFound": "Nie można znaleźć generatora szablonów!",
"fileUploadFailed": "Nie udało się przesłać pliku",
"primaryColumnUpdateFailed": "Nie udało się zaktualizować kolumny głównej",
"formDescriptionTooLong": "Zbyt długi opis formularza",
"columnsRequired": "Następujące kolumny są wymagane",
"selectAtleastOneColumn": "Co najmniej jedna kolumna musi być wybrana",
"columnDescriptionNotFound": "Nie można znaleźć kolumny docelowej dla",
"duplicateMappingFound": "Znaleziono zduplikowane mapowanie, usuń jedno z mapowań",
"nullValueViolatesNotNull": "Wartość pusta narusza ograniczenie nie puste",
"sourceHasInvalidNumbers": "Dane źródłowe zawierają nieprawidłowe numery",
"sourceHasInvalidBoolean": "Dane źródłowe zawierają nieprawidłowe wartości logiczne",
"invalidForm": "Nieprawidłowy formularz",
"formValidationFailed": "Weryfikacja formularza nie powiodła się",
"youHaveBeenSignedOut": "Wylogowano",
"failedToLoadList": "Nie udało się załadować listy",
"failedToLoadChildrenList": "Nie udało się załadować listy podrzędnej",
"deleteFailed": "Usunięcie nie powiodło się",
"unlinkFailed": "Nie udało się odłączyć",
"rowUpdateFailed": "Aktualizacja wiersza nie powiodła się",
"deleteRowFailed": "Nie udało się usunąć wiersza",
"setFormDataFailed": "Nie udało się ustawić danych formularza",
"formViewUpdateFailed": "Nie udało się zaktualizować widoku formularza",
"tableNameRequired": "Nazwa tabeli jest wymagana",
"nameShouldStartWithAnAlphabetOr_": "Nazwa powinna zaczynać się od alfabetu lub od _",
"followingCharactersAreNotAllowed": "Następujące znaki są niedozwolone",
"columnNameRequired": "Nazwa kolumny jest wymagana",
"projectNameExceeds50Characters": "Nazwa projektu przekracza 50 znaków",
"projectNameCannotStartWithSpace": "Nazwa projektu nie może zaczynać się od spacji",
"requiredField": "Pole wymagane",
"ipNotAllowed": "Adres IP niedozwolony",
"targetFileIsNotAnAcceptedFileType": "Plik docelowy nie jest akceptowanym typem pliku",
"theAcceptedFileTypeIsCsv": "Akceptowany typ pliku to .csv",
"theAcceptedFileTypesAreXlsXlsxXlsmOdsOts": "Akceptowane typy plików to: .xls, .xlsx, .xlsm, .ods, .ots",
"parameterKeyCannotBeEmpty": "Klucz parametru nie może być pusty",
"duplicateParameterKeysAreNotAllowed": "Zduplikowane klucze parametrów są niedozwolone",
"fieldRequired": "{value} nie może być puste."
},
"toast": {
"exportMetadata": "Pomyślnie wyeksportowano metadane projektu",
@ -663,43 +663,43 @@
"startProject": "Projekt rozpoczął się pomyślnie",
"restartProject": "Projekt zrestartowany pomyślnie",
"deleteProject": "Projekt usunięto pomyślnie",
"authToken": "Token autoryzny skopiowany do schowka",
"authToken": "Token został skopiowany do schowka",
"projInfo": "Skopiowane informacje do schowka",
"inviteUrlCopy": "Skopiowany Zaproś URL do schowka",
"inviteUrlCopy": "Skopiowano do schowka",
"createView": "Widok utworzony pomyślnie",
"formEmailSMTP": "Aktywuj wtyczkę SMTP w App Store, aby umożliwić powiadomienie e-mail",
"collabView": "Pomyślnie przełączony na widok współpracy",
"lockedView": "Pomyślnie przełączony na zablokowany widok",
"formEmailSMTP": "Aktywuj wtyczkę SMTP w App Store, aby umożliwić powiadomienia e-mail",
"collabView": "Pomyślnie przełączono na widok współpracy",
"lockedView": "Pomyślnie przełączono na zablokowany widok",
"futureRelease": "Wkrótce!"
},
"success": {
"updatedUIACL": "Updated UI ACL for tables successfully",
"pluginUninstalled": "Plugin uninstalled successfully",
"pluginSettingsSaved": "Plugin settings saved successfully",
"pluginTested": "Successfully tested plugin settings",
"tableRenamed": "Table renamed successfully",
"viewDeleted": "View deleted successfully",
"primaryColumnUpdated": "Successfully updated as primary column",
"tableDataExported": "Successfully exported all table data",
"updated": "Successfully updated",
"sharedViewDeleted": "Deleted shared view successfully",
"viewRenamed": "View renamed successfully",
"tokenGenerated": "Token generated successfully",
"tokenDeleted": "Token deleted successfully",
"userAddedToProject": "Successfully added user to project",
"userDeletedFromProject": "Successfully deleted user from project",
"inviteEmailSent": "Invite Email sent successfully",
"inviteURLCopied": "Invite URL copied to clipboard",
"shareableURLCopied": "Copied shareable base URL to clipboard!",
"embeddableHTMLCodeCopied": "Copied embeddable HTML code!",
"userDetailsUpdated": "Successfully updated the user details",
"tableDataImported": "Successfully imported table data",
"webhookUpdated": "Webhook details updated successfully",
"webhookDeleted": "Hook deleted successfully",
"webhookTested": "Webhook tested successfully",
"columnUpdated": "Column updated",
"columnCreated": "Column created",
"passwordChanged": "Password changed successfully. Please login again."
"updatedUIACL": "Pomyślnie zaktualizowano UI ACL dla tabel",
"pluginUninstalled": "Wtyczka odinstalowana pomyślnie",
"pluginSettingsSaved": "Ustawienia wtyczki zapisane pomyślnie",
"pluginTested": "Pomyślnie przetestowano ustawienia wtyczki",
"tableRenamed": "Zmieniono nazwę tabeli",
"viewDeleted": "Widok usunięty pomyślnie",
"primaryColumnUpdated": "Pomyślnie zaktualizowano jako kolumnę główną",
"tableDataExported": "Pomyślnie wyeksportowano wszystkie dane tabeli",
"updated": "Zaktualizowano pomyślnie",
"sharedViewDeleted": "Usunięto udostępniony widok",
"viewRenamed": "Zmieniono nazwę widoku",
"tokenGenerated": "Token został wygenerowany pomyślnie",
"tokenDeleted": "Token usunięty pomyślnie",
"userAddedToProject": "Pomyślnie dodano użytkownika do projektu",
"userDeletedFromProject": "Użytkownik usunięty z projektu",
"inviteEmailSent": "E-mail z zaproszeniem wysłany pomyślnie",
"inviteURLCopied": "Adres URL zaproszenia skopiowany do schowka",
"shareableURLCopied": "Skopiowano adres URL do schowka!",
"embeddableHTMLCodeCopied": "Skopiowany kod HTML do osadzenia!",
"userDetailsUpdated": "Pomyślnie zaktualizowano dane użytkownika",
"tableDataImported": "Pomyślnie zaimportowano dane tabeli",
"webhookUpdated": "Szczegóły webhooka zostały zaktualizowane",
"webhookDeleted": "Webhook usunięty pomyślnie",
"webhookTested": "Webhook przetestowany pomyślnie",
"columnUpdated": "Kolumna zaktualizowana",
"columnCreated": "Kolumna utworzona",
"passwordChanged": "Hasło zostało zmienione. Zaloguj się ponownie."
}
}
}

58
packages/nc-gui/lang/zh-Hans.json

@ -69,7 +69,7 @@
"betaNote": "此功能仍在测试中。",
"moreInfo": "点击此处了解更多信息。",
"logs": "日志",
"groupingField": "Grouping Field"
"groupingField": "分组字段"
},
"objects": {
"project": "项目",
@ -102,14 +102,14 @@
"roleType": {
"owner": "所有者",
"creator": "创造者",
"editor": "编辑",
"editor": "编辑",
"commenter": "评论者",
"viewer": "观众"
"viewer": "浏览者"
},
"sqlVIew": "SQL View"
"sqlVIew": "SQL 视图"
},
"datatype": {
"ID": "ID",
"ID": "编号",
"ForeignKey": "外键",
"SingleLineText": "单行文本",
"LongText": "长文本",
@ -160,13 +160,13 @@
"isNotNull": "不是空虚"
},
"title": {
"erdView": "ERD View",
"erdView": "实体关系图",
"newProj": "创建新项目",
"myProject": "我的项目",
"formTitle": "表格标题",
"collabView": "合作视图",
"lockedView": "锁定视图",
"personalView": "个人",
"personalView": "个人视图",
"appStore": "软件商店",
"teamAndAuth": "团队和认证",
"rolesUserMgmt": "角色和用户管理",
@ -189,7 +189,7 @@
"resetPassword": "重置密码",
"teamAndSettings": "团队和设置",
"apiDocs": "API 文档",
"importFromAirtable": "Import From Airtable",
"importFromAirtable": "从 Airtable 导入",
"generateToken": "Generate Token",
"APIsAndSupport": "APIs & Support",
"helpCenter": "Help center",
@ -220,7 +220,7 @@
"schemaName": "架构名称",
"database": "数据库",
"action": "行动",
"actions": "行动",
"actions": "操作",
"operation": "操作",
"operationType": "操作类型",
"operationSubType": "操作子类型",
@ -265,11 +265,11 @@
"childColumn": "子列",
"onUpdate": "更新",
"onDelete": "删除",
"account": "Account",
"language": "Language",
"primaryColor": "Primary Color",
"accentColor": "Accent Color",
"customTheme": "Custom Theme",
"account": "帐户",
"language": "语言",
"primaryColor": "主色调",
"accentColor": "强调色",
"customTheme": "定制样式",
"requestDataSource": "Request a data source you need?",
"apiKey": "API Key",
"sharedBase": "Shared Base",
@ -406,19 +406,19 @@
"sponsorUs": "赞助我们",
"sendEmail": "发送邮件",
"addUserToProject": "Add user to project",
"getApiSnippet": "Get API Snippet",
"clearCell": "Clear cell",
"getApiSnippet": "生成代码",
"clearCell": "清除单元格内容",
"addFilterGroup": "Add Filter Group",
"linkRecord": "Link record",
"addNewRecord": "Add new record",
"linkRecord": "链接记录",
"addNewRecord": "新增记录",
"useConnectionUrl": "Use Connection URL",
"toggleCommentsDraw": "Toggle comments draw",
"expandRecord": "Expand Record",
"deleteRecord": "Delete Record",
"erd": {
"showColumns": "Show Columns",
"showPkAndFk": "Show Primary and Foreign Keys",
"showSqlViews": "Show SQL Views",
"showColumns": "显示列",
"showPkAndFk": "显示主键和外键",
"showSqlViews": "显示 SQL 视图",
"showMMTables": "Show Many to Many tables",
"showJunctionTableNames": "Show Junction Table Names"
},
@ -426,7 +426,7 @@
"collapseStack": "Collapse Stack",
"deleteStack": "Delete Stack",
"stackedBy": "Stacked By",
"chooseGroupingField": "Choose a Grouping Field",
"chooseGroupingField": "选择分组字段",
"addOrEditStack": "Add / Edit Stack"
}
},
@ -635,7 +635,7 @@
"failedToLoadList": "Failed to load list",
"failedToLoadChildrenList": "Failed to load children list",
"deleteFailed": "Delete failed",
"unlinkFailed": "Unlink failed",
"unlinkFailed": "撤消链接失败",
"rowUpdateFailed": "Row update failed",
"deleteRowFailed": "Failed to delete row",
"setFormDataFailed": "Failed to set form data",
@ -673,15 +673,15 @@
"futureRelease": "即将推出!"
},
"success": {
"updatedUIACL": "Updated UI ACL for tables successfully",
"updatedUIACL": "已成功更新表的 UI ACL",
"pluginUninstalled": "Plugin uninstalled successfully",
"pluginSettingsSaved": "Plugin settings saved successfully",
"pluginTested": "Successfully tested plugin settings",
"tableRenamed": "Table renamed successfully",
"viewDeleted": "View deleted successfully",
"primaryColumnUpdated": "Successfully updated as primary column",
"primaryColumnUpdated": "成功更新为主列",
"tableDataExported": "Successfully exported all table data",
"updated": "Successfully updated",
"updated": "更新成功",
"sharedViewDeleted": "Deleted shared view successfully",
"viewRenamed": "View renamed successfully",
"tokenGenerated": "Token generated successfully",
@ -692,12 +692,12 @@
"inviteURLCopied": "Invite URL copied to clipboard",
"shareableURLCopied": "Copied shareable base URL to clipboard!",
"embeddableHTMLCodeCopied": "Copied embeddable HTML code!",
"userDetailsUpdated": "Successfully updated the user details",
"userDetailsUpdated": "成功更新用户详细信息",
"tableDataImported": "Successfully imported table data",
"webhookUpdated": "Webhook details updated successfully",
"webhookUpdated": "Webhook 详细信息更新成功",
"webhookDeleted": "Hook deleted successfully",
"webhookTested": "Webhook tested successfully",
"columnUpdated": "Column updated",
"columnUpdated": "列已更新",
"columnCreated": "Column created",
"passwordChanged": "Password changed successfully. Please login again."
}

2
packages/nc-gui/layouts/base.vue

@ -127,7 +127,7 @@ hooks.hook('page:finish', () => {
<a-tooltip placement="bottom">
<template #title> Switch language</template>
<LazyGeneralLanguage v-if="!signedIn" class="nc-lang-btn" />
<LazyGeneralLanguage v-if="!signedIn && !route.params.projectId" class="nc-lang-btn" />
</a-tooltip>
<div class="w-full h-full overflow-hidden">

5
packages/nc-gui/lib/types.ts

@ -1,6 +1,7 @@
import type { FilterType, ViewTypes } from 'nocodb-sdk'
import type { I18n } from 'vue-i18n'
import type { Theme as AntTheme } from 'ant-design-vue/es/config-provider'
import type { UploadFile } from 'ant-design-vue'
import type { ProjectRole, Role, TabType } from './enums'
import type { rolePermissions } from './constants'
@ -94,3 +95,7 @@ export interface SharedView {
type?: ViewTypes
meta: SharedViewMeta
}
export type importFileList = (UploadFile & { data: string | ArrayBuffer })[]
export type streamImportFileList = UploadFile[]

473
packages/nc-gui/package-lock.json generated

@ -90,8 +90,7 @@
}
},
"../nocodb-sdk": {
"version": "0.98.1",
"hasInstallScript": true,
"version": "0.98.3",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
@ -115,10 +114,9 @@
"gh-pages": "^3.1.0",
"npm-run-all": "^4.1.5",
"nyc": "^15.1.0",
"open-cli": "^6.0.1",
"open-cli": "^7.1.0",
"prettier": "^2.1.1",
"standard-version": "^9.0.0",
"swagger-typescript-api": "^10.0.1",
"ts-node": "^9.0.0",
"typedoc": "^0.23.16",
"typescript": "^4.0.2"
@ -2010,6 +2008,38 @@
"vue": "^3.2.39"
}
},
"node_modules/@nuxt/vite-builder/node_modules/@esbuild/android-arm": {
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.11.tgz",
"integrity": "sha512-PzMcQLazLBkwDEkrNPi9AbjFt6+3I7HKbiYF2XtWQ7wItrHvEOeO3T8Am434zAozWtVP7lrTue1bEfc2nYWeCA==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@nuxt/vite-builder/node_modules/@esbuild/linux-loong64": {
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.11.tgz",
"integrity": "sha512-geWp637tUhNmhL3Xgy4Bj703yXB9dqiLJe05lCUfjSFDrQf9C/8pArusyPUbUbPwlC/EAUjBw32sxuIl/11dZw==",
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@nuxt/vite-builder/node_modules/@nuxt/kit": {
"version": "3.0.0-rc.11",
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.0.0-rc.11.tgz",
@ -2072,9 +2102,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.8.tgz",
"integrity": "sha512-Remsk2dmr1Ia65sU+QasE6svJbsHe62lzR+CnjpUvbZ+uSYo1SitiOWPRfZQkCu82YWZBBKXiD/j0i//XWMZ+Q==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.11.tgz",
"integrity": "sha512-OgHGuhlfZ//mToxjte1D5iiiQgWfJ2GByVMwEC/IuoXsBGkuyK1+KrjYu0laSpnN/L1UmLUCv0s25vObdc1bVg==",
"dev": true,
"hasInstallScript": true,
"bin": {
@ -2084,34 +2114,34 @@
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/android-arm": "0.15.8",
"@esbuild/linux-loong64": "0.15.8",
"esbuild-android-64": "0.15.8",
"esbuild-android-arm64": "0.15.8",
"esbuild-darwin-64": "0.15.8",
"esbuild-darwin-arm64": "0.15.8",
"esbuild-freebsd-64": "0.15.8",
"esbuild-freebsd-arm64": "0.15.8",
"esbuild-linux-32": "0.15.8",
"esbuild-linux-64": "0.15.8",
"esbuild-linux-arm": "0.15.8",
"esbuild-linux-arm64": "0.15.8",
"esbuild-linux-mips64le": "0.15.8",
"esbuild-linux-ppc64le": "0.15.8",
"esbuild-linux-riscv64": "0.15.8",
"esbuild-linux-s390x": "0.15.8",
"esbuild-netbsd-64": "0.15.8",
"esbuild-openbsd-64": "0.15.8",
"esbuild-sunos-64": "0.15.8",
"esbuild-windows-32": "0.15.8",
"esbuild-windows-64": "0.15.8",
"esbuild-windows-arm64": "0.15.8"
"@esbuild/android-arm": "0.15.11",
"@esbuild/linux-loong64": "0.15.11",
"esbuild-android-64": "0.15.11",
"esbuild-android-arm64": "0.15.11",
"esbuild-darwin-64": "0.15.11",
"esbuild-darwin-arm64": "0.15.11",
"esbuild-freebsd-64": "0.15.11",
"esbuild-freebsd-arm64": "0.15.11",
"esbuild-linux-32": "0.15.11",
"esbuild-linux-64": "0.15.11",
"esbuild-linux-arm": "0.15.11",
"esbuild-linux-arm64": "0.15.11",
"esbuild-linux-mips64le": "0.15.11",
"esbuild-linux-ppc64le": "0.15.11",
"esbuild-linux-riscv64": "0.15.11",
"esbuild-linux-s390x": "0.15.11",
"esbuild-netbsd-64": "0.15.11",
"esbuild-openbsd-64": "0.15.11",
"esbuild-sunos-64": "0.15.11",
"esbuild-windows-32": "0.15.11",
"esbuild-windows-64": "0.15.11",
"esbuild-windows-arm64": "0.15.11"
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-android-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.8.tgz",
"integrity": "sha512-bVh8FIKOolF7/d4AMzt7xHlL0Ljr+mYKSHI39TJWDkybVWHdn6+4ODL3xZGHOxPpdRpitemXA1WwMKYBsw8dGw==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.11.tgz",
"integrity": "sha512-rrwoXEiuI1kaw4k475NJpexs8GfJqQUKcD08VR8sKHmuW9RUuTR2VxcupVvHdiGh9ihxL9m3lpqB1kju92Ialw==",
"cpu": [
"x64"
],
@ -2120,17 +2150,14 @@
"os": [
"android"
],
"dependencies": {
"esbuild-wasm": "0.15.8"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-android-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.8.tgz",
"integrity": "sha512-ReAMDAHuo0H1h9LxRabI6gwYPn8k6WiUeyxuMvx17yTrJO+SCnIfNc/TSPFvDwtK9MiyiKG/2dBYHouT/M0BXQ==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.11.tgz",
"integrity": "sha512-/hDubOg7BHOhUUsT8KUIU7GfZm5bihqssvqK5PfO4apag7YuObZRZSzViyEKcFn2tPeHx7RKbSBXvAopSHDZJQ==",
"cpu": [
"arm64"
],
@ -2144,9 +2171,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-darwin-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.8.tgz",
"integrity": "sha512-KaKcGfJ+yto7Fo5gAj3xwxHMd1fBIKatpCHK8znTJLVv+9+NN2/tIPBqA4w5rBwjX0UqXDeIE2v1xJP+nGEXgA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.11.tgz",
"integrity": "sha512-1DqHD0ms3AhiwkKnjRUzmiW7JnaJJr5FKrPiR7xuyMwnjDqvNWDdMq4rKSD9OC0piFNK6n0LghsglNMe2MwJtA==",
"cpu": [
"x64"
],
@ -2160,9 +2187,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-darwin-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.8.tgz",
"integrity": "sha512-8tjEaBgAKnXCkP7bhEJmEqdG9HEV6oLkF36BrMzpfW2rgaw0c48Zrxe+9RlfeGvs6gDF4w+agXyTjikzsS3izw==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.11.tgz",
"integrity": "sha512-OMzhxSbS0lwwrW40HHjRCeVIJTURdXFA8c3GU30MlHKuPCcvWNUIKVucVBtNpJySXmbkQMDJdJNrXzNDyvoqvQ==",
"cpu": [
"arm64"
],
@ -2176,9 +2203,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-freebsd-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.8.tgz",
"integrity": "sha512-jaxcsGHYzn2L0/lffON2WfH4Nc+d/EwozVTP5K2v016zxMb5UQMhLoJzvLgBqHT1SG0B/mO+a+THnJCMVg15zw==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.11.tgz",
"integrity": "sha512-8dKP26r0/Qyez8nTCwpq60QbuYKOeBygdgOAWGCRalunyeqWRoSZj9TQjPDnTTI9joxd3QYw3UhVZTKxO9QdRg==",
"cpu": [
"x64"
],
@ -2192,9 +2219,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-freebsd-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.8.tgz",
"integrity": "sha512-2xp2UlljMvX8HExtcg7VHaeQk8OBU0CSl1j18B5CcZmSDkLF9p3utuMXIopG3a08fr9Hv+Dz6+seSXUow/G51w==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.11.tgz",
"integrity": "sha512-aSGiODiukLGGnSg/O9+cGO2QxEacrdCtCawehkWYTt5VX1ni2b9KoxpHCT9h9Y6wGqNHmXFnB47RRJ8BIqZgmQ==",
"cpu": [
"arm64"
],
@ -2208,9 +2235,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-linux-32": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.8.tgz",
"integrity": "sha512-9u1E54BRz1FQMl86iaHK146+4ID2KYNxL3trLZT4QLLx3M7Q9n4lGG3lrzqUatGR2cKy8c33b0iaCzsItZWkFg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.11.tgz",
"integrity": "sha512-lsrAfdyJBGx+6aHIQmgqUonEzKYeBnyfJPkT6N2dOf1RoXYYV1BkWB6G02tjsrz1d5wZzaTc3cF+TKmuTo/ZwA==",
"cpu": [
"ia32"
],
@ -2224,9 +2251,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-linux-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.8.tgz",
"integrity": "sha512-4HxrsN9eUzJXdVGMTYA5Xler82FuZUu21bXKN42zcLHHNKCAMPUzD62I+GwDhsdgUBAUj0tRXDdsQHgaP6v0HA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.11.tgz",
"integrity": "sha512-Y2Rh+PcyVhQqXKBTacPCltINN3uIw2xC+dsvLANJ1SpK5NJUtxv8+rqWpjmBgaNWKQT1/uGpMmA9olALy9PLVA==",
"cpu": [
"x64"
],
@ -2240,9 +2267,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-linux-arm": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.8.tgz",
"integrity": "sha512-7DVBU9SFjX4+vBwt8tHsUCbE6Vvl6y6FQWHAgyw1lybC5gULqn/WnjHYHN2/LJaZRsDBvxWT4msEgwLGq1Wd3Q==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.11.tgz",
"integrity": "sha512-TJllTVk5aSyqPFvvcHTvf6Wu1ZKhWpJ/qNmZO8LL/XeB+LXCclm7HQHNEIz6MT7IX8PmlC1BZYrOiw2sXSB95A==",
"cpu": [
"arm"
],
@ -2256,9 +2283,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-linux-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.8.tgz",
"integrity": "sha512-1OCm7Aq0tEJT70PbxmHSGYDLYP8DKH8r4Nk7/XbVzWaduo9beCjGBB+tGZIHK6DdTQ3h00/4Tb/70YMH/bOtKg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.11.tgz",
"integrity": "sha512-uhcXiTwTmD4OpxJu3xC5TzAAw6Wzf9O1XGWL448EE9bqGjgV1j+oK3lIHAfsHnuIn8K4nDW8yjX0Sv5S++oRuw==",
"cpu": [
"arm64"
],
@ -2272,9 +2299,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-linux-mips64le": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.8.tgz",
"integrity": "sha512-yeFoNPVFPEzZvFYBfUQNG2TjGRaCyV1E27OcOg4LOtnGrxb2wA+mkW3luckyv1CEyd00mpAg7UdHx8nlx3ghgA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.11.tgz",
"integrity": "sha512-WD61y/R1M4BLe4gxXRypoQ0Ci+Vjf714QYzcPNkiYv5I8K8WDz2ZR8Bm6cqKxd6rD+e/rZgPDbhQ9PCf7TMHmA==",
"cpu": [
"mips64el"
],
@ -2288,9 +2315,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-linux-ppc64le": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.8.tgz",
"integrity": "sha512-CEyMMUUNabXibw8OSNmBXhOIGhnjNVl5Lpseiuf00iKN0V47oqDrbo4dsHz1wH62m49AR8iG8wpDlTqfYgKbtg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.11.tgz",
"integrity": "sha512-JVleZS9oPVLTlBhPTWgOwxFWU/wMUdlBwTbGA4GF8c38sLbS13cupj+C8bLq929jU7EMWry4SaL+tKGIaTlqKg==",
"cpu": [
"ppc64"
],
@ -2304,9 +2331,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-linux-riscv64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.8.tgz",
"integrity": "sha512-OCGSOaspMUjexSCU8ZiA0UnV/NiRU+s2vIfEcAQWQ6u32R+2luyfh/4ZaY6jFbylJE07Esc/yRvb9Q5fXuClXA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.11.tgz",
"integrity": "sha512-9aLIalZ2HFHIOZpmVU11sEAS9F8TnHw49daEjcgMpBXHFF57VuT9f9/9LKJhw781Gda0P9jDkuCWJ0tFbErvJw==",
"cpu": [
"riscv64"
],
@ -2320,9 +2347,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-linux-s390x": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.8.tgz",
"integrity": "sha512-RHdpdfxRTSrZXZJlFSLazFU4YwXLB5Rgf6Zr5rffqSsO4y9JybgtKO38bFwxZNlDXliYISXN/YROKrG9s7mZQA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.11.tgz",
"integrity": "sha512-sZHtiXXOKsLI3XGBGoYO4qKBzJlb8xNsWmvFiwFMHFzA4AXgDP1KDp7Dawe9C2pavTRBDvl+Ok4n/DHQ59oaTg==",
"cpu": [
"s390x"
],
@ -2336,9 +2363,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-netbsd-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.8.tgz",
"integrity": "sha512-VolFFRatBH09T5QMWhiohAWCOien1R1Uz9K0BRVVTBgBaVBt7eArsXTKxVhUgRf2vwu2c2SXkuP0r7HLG0eozw==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.11.tgz",
"integrity": "sha512-hUC9yN06K9sg7ju4Vgu9ChAPdsEgtcrcLfyNT5IKwKyfpLvKUwCMZSdF+gRD3WpyZelgTQfJ+pDx5XFbXTlB0A==",
"cpu": [
"x64"
],
@ -2352,9 +2379,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-openbsd-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.8.tgz",
"integrity": "sha512-HTAPlg+n4kUeE/isQxlCfsOz0xJGNoT5LJ9oYZWFKABfVf4Ycu7Zlf5ITgOnrdheTkz8JeL/gISIOCFAoOXrSA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.11.tgz",
"integrity": "sha512-0bBo9SQR4t66Wd91LGMAqmWorzO0TTzVjYiifwoFtel8luFeXuPThQnEm5ztN4g0fnvcp7AnUPPzS/Depf17wQ==",
"cpu": [
"x64"
],
@ -2368,9 +2395,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-sunos-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.8.tgz",
"integrity": "sha512-qMP/jR/FzcIOwKj+W+Lb+8Cfr8GZHbHUJxAPi7DUhNZMQ/6y7sOgRzlOSpRrbbUntrRZh0MqOyDhJ3Gpo6L1QA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.11.tgz",
"integrity": "sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==",
"cpu": [
"x64"
],
@ -2384,9 +2411,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-windows-32": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.8.tgz",
"integrity": "sha512-RKR1QHh4iWzjUhkP8Yqi75PPz/KS+b8zw3wUrzw6oAkj+iU5Qtyj61ZDaSG3Qf2vc6hTIUiPqVTqBH0NpXFNwg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.11.tgz",
"integrity": "sha512-O0/Wo1Wk6dc0rZSxkvGpmTNIycEznHmkObTFz2VHBhjPsO4ZpCgfGxNkCpz4AdAIeMczpTXt/8d5vdJNKEGC+Q==",
"cpu": [
"ia32"
],
@ -2400,9 +2427,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-windows-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.8.tgz",
"integrity": "sha512-ag9ptYrsizgsR+PQE8QKeMqnosLvAMonQREpLw4evA4FFgOBMLEat/dY/9txbpozTw9eEOYyD3a4cE9yTu20FA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.11.tgz",
"integrity": "sha512-x977Q4HhNjnHx00b4XLAnTtj5vfbdEvkxaQwC1Zh5AN8g5EX+izgZ6e5QgqJgpzyRNJqh4hkgIJF1pyy1be0mQ==",
"cpu": [
"x64"
],
@ -2416,9 +2443,9 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/esbuild-windows-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.8.tgz",
"integrity": "sha512-dbpAb0VyPaUs9mgw65KRfQ9rqiWCHpNzrJusoPu+LpEoswosjt/tFxN7cd2l68AT4qWdBkzAjDLRon7uqMeWcg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.11.tgz",
"integrity": "sha512-VwUHFACuBahrvntdcMKZteUZ9HaYrBRODoKe4tIWxguQRvvYoYb7iu5LrcRS/FQx8KPZNaa72zuqwVtHeXsITw==",
"cpu": [
"arm64"
],
@ -2480,12 +2507,12 @@
}
},
"node_modules/@nuxt/vite-builder/node_modules/vite": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-3.1.3.tgz",
"integrity": "sha512-/3XWiktaopByM5bd8dqvHxRt5EEgRikevnnrpND0gRfNkrMrPaGGexhtLCzv15RcCMtV2CLw+BPas8YFeSG0KA==",
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/vite/-/vite-3.1.8.tgz",
"integrity": "sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==",
"dev": true,
"dependencies": {
"esbuild": "^0.15.6",
"esbuild": "^0.15.9",
"postcss": "^8.4.16",
"resolve": "^1.22.1",
"rollup": "~2.78.0"
@ -15072,9 +15099,9 @@
"dev": true
},
"node_modules/terser": {
"version": "5.14.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.1.tgz",
"integrity": "sha512-+ahUAE+iheqBTDxXhTisdA8hgvbEG1hHOQ9xmNjeUJSoi6DU/gMrKNcfZjHkyY6Alnuyc+ikYJaxxfHkT3+WuQ==",
"version": "5.15.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
"integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.2",
@ -15879,15 +15906,15 @@
}
},
"node_modules/vite": {
"version": "2.9.12",
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.12.tgz",
"integrity": "sha512-suxC36dQo9Rq1qMB2qiRorNJtJAdxguu5TMvBHOc/F370KvqAe9t48vYp+/TbPKRNrMh/J55tOUmkuIqstZaew==",
"version": "2.9.15",
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.15.tgz",
"integrity": "sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ==",
"dev": true,
"dependencies": {
"esbuild": "^0.14.27",
"postcss": "^8.4.13",
"resolve": "^1.22.0",
"rollup": "^2.59.0"
"rollup": ">=2.59.0 <2.78.0"
},
"bin": {
"vite": "bin/vite.js"
@ -16068,6 +16095,21 @@
"vite": "^2.0.1 || ^3.0.0"
}
},
"node_modules/vite/node_modules/rollup": {
"version": "2.77.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.3.tgz",
"integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=10.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/vitest": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-0.18.0.tgz",
@ -18436,6 +18478,20 @@
"vue-bundle-renderer": "^0.4.3"
},
"dependencies": {
"@esbuild/android-arm": {
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.11.tgz",
"integrity": "sha512-PzMcQLazLBkwDEkrNPi9AbjFt6+3I7HKbiYF2XtWQ7wItrHvEOeO3T8Am434zAozWtVP7lrTue1bEfc2nYWeCA==",
"dev": true,
"optional": true
},
"@esbuild/linux-loong64": {
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.11.tgz",
"integrity": "sha512-geWp637tUhNmhL3Xgy4Bj703yXB9dqiLJe05lCUfjSFDrQf9C/8pArusyPUbUbPwlC/EAUjBw32sxuIl/11dZw==",
"dev": true,
"optional": true
},
"@nuxt/kit": {
"version": "3.0.0-rc.11",
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.0.0-rc.11.tgz",
@ -18482,175 +18538,172 @@
}
},
"esbuild": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.8.tgz",
"integrity": "sha512-Remsk2dmr1Ia65sU+QasE6svJbsHe62lzR+CnjpUvbZ+uSYo1SitiOWPRfZQkCu82YWZBBKXiD/j0i//XWMZ+Q==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.11.tgz",
"integrity": "sha512-OgHGuhlfZ//mToxjte1D5iiiQgWfJ2GByVMwEC/IuoXsBGkuyK1+KrjYu0laSpnN/L1UmLUCv0s25vObdc1bVg==",
"dev": true,
"requires": {
"@esbuild/android-arm": "0.15.8",
"@esbuild/linux-loong64": "0.15.8",
"esbuild-android-64": "0.15.8",
"esbuild-android-arm64": "0.15.8",
"esbuild-darwin-64": "0.15.8",
"esbuild-darwin-arm64": "0.15.8",
"esbuild-freebsd-64": "0.15.8",
"esbuild-freebsd-arm64": "0.15.8",
"esbuild-linux-32": "0.15.8",
"esbuild-linux-64": "0.15.8",
"esbuild-linux-arm": "0.15.8",
"esbuild-linux-arm64": "0.15.8",
"esbuild-linux-mips64le": "0.15.8",
"esbuild-linux-ppc64le": "0.15.8",
"esbuild-linux-riscv64": "0.15.8",
"esbuild-linux-s390x": "0.15.8",
"esbuild-netbsd-64": "0.15.8",
"esbuild-openbsd-64": "0.15.8",
"esbuild-sunos-64": "0.15.8",
"esbuild-windows-32": "0.15.8",
"esbuild-windows-64": "0.15.8",
"esbuild-windows-arm64": "0.15.8"
"@esbuild/android-arm": "0.15.11",
"@esbuild/linux-loong64": "0.15.11",
"esbuild-android-64": "0.15.11",
"esbuild-android-arm64": "0.15.11",
"esbuild-darwin-64": "0.15.11",
"esbuild-darwin-arm64": "0.15.11",
"esbuild-freebsd-64": "0.15.11",
"esbuild-freebsd-arm64": "0.15.11",
"esbuild-linux-32": "0.15.11",
"esbuild-linux-64": "0.15.11",
"esbuild-linux-arm": "0.15.11",
"esbuild-linux-arm64": "0.15.11",
"esbuild-linux-mips64le": "0.15.11",
"esbuild-linux-ppc64le": "0.15.11",
"esbuild-linux-riscv64": "0.15.11",
"esbuild-linux-s390x": "0.15.11",
"esbuild-netbsd-64": "0.15.11",
"esbuild-openbsd-64": "0.15.11",
"esbuild-sunos-64": "0.15.11",
"esbuild-windows-32": "0.15.11",
"esbuild-windows-64": "0.15.11",
"esbuild-windows-arm64": "0.15.11"
}
},
"esbuild-android-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.8.tgz",
"integrity": "sha512-bVh8FIKOolF7/d4AMzt7xHlL0Ljr+mYKSHI39TJWDkybVWHdn6+4ODL3xZGHOxPpdRpitemXA1WwMKYBsw8dGw==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.11.tgz",
"integrity": "sha512-rrwoXEiuI1kaw4k475NJpexs8GfJqQUKcD08VR8sKHmuW9RUuTR2VxcupVvHdiGh9ihxL9m3lpqB1kju92Ialw==",
"dev": true,
"optional": true,
"requires": {
"esbuild-wasm": "0.15.8"
}
"optional": true
},
"esbuild-android-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.8.tgz",
"integrity": "sha512-ReAMDAHuo0H1h9LxRabI6gwYPn8k6WiUeyxuMvx17yTrJO+SCnIfNc/TSPFvDwtK9MiyiKG/2dBYHouT/M0BXQ==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.11.tgz",
"integrity": "sha512-/hDubOg7BHOhUUsT8KUIU7GfZm5bihqssvqK5PfO4apag7YuObZRZSzViyEKcFn2tPeHx7RKbSBXvAopSHDZJQ==",
"dev": true,
"optional": true
},
"esbuild-darwin-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.8.tgz",
"integrity": "sha512-KaKcGfJ+yto7Fo5gAj3xwxHMd1fBIKatpCHK8znTJLVv+9+NN2/tIPBqA4w5rBwjX0UqXDeIE2v1xJP+nGEXgA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.11.tgz",
"integrity": "sha512-1DqHD0ms3AhiwkKnjRUzmiW7JnaJJr5FKrPiR7xuyMwnjDqvNWDdMq4rKSD9OC0piFNK6n0LghsglNMe2MwJtA==",
"dev": true,
"optional": true
},
"esbuild-darwin-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.8.tgz",
"integrity": "sha512-8tjEaBgAKnXCkP7bhEJmEqdG9HEV6oLkF36BrMzpfW2rgaw0c48Zrxe+9RlfeGvs6gDF4w+agXyTjikzsS3izw==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.11.tgz",
"integrity": "sha512-OMzhxSbS0lwwrW40HHjRCeVIJTURdXFA8c3GU30MlHKuPCcvWNUIKVucVBtNpJySXmbkQMDJdJNrXzNDyvoqvQ==",
"dev": true,
"optional": true
},
"esbuild-freebsd-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.8.tgz",
"integrity": "sha512-jaxcsGHYzn2L0/lffON2WfH4Nc+d/EwozVTP5K2v016zxMb5UQMhLoJzvLgBqHT1SG0B/mO+a+THnJCMVg15zw==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.11.tgz",
"integrity": "sha512-8dKP26r0/Qyez8nTCwpq60QbuYKOeBygdgOAWGCRalunyeqWRoSZj9TQjPDnTTI9joxd3QYw3UhVZTKxO9QdRg==",
"dev": true,
"optional": true
},
"esbuild-freebsd-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.8.tgz",
"integrity": "sha512-2xp2UlljMvX8HExtcg7VHaeQk8OBU0CSl1j18B5CcZmSDkLF9p3utuMXIopG3a08fr9Hv+Dz6+seSXUow/G51w==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.11.tgz",
"integrity": "sha512-aSGiODiukLGGnSg/O9+cGO2QxEacrdCtCawehkWYTt5VX1ni2b9KoxpHCT9h9Y6wGqNHmXFnB47RRJ8BIqZgmQ==",
"dev": true,
"optional": true
},
"esbuild-linux-32": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.8.tgz",
"integrity": "sha512-9u1E54BRz1FQMl86iaHK146+4ID2KYNxL3trLZT4QLLx3M7Q9n4lGG3lrzqUatGR2cKy8c33b0iaCzsItZWkFg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.11.tgz",
"integrity": "sha512-lsrAfdyJBGx+6aHIQmgqUonEzKYeBnyfJPkT6N2dOf1RoXYYV1BkWB6G02tjsrz1d5wZzaTc3cF+TKmuTo/ZwA==",
"dev": true,
"optional": true
},
"esbuild-linux-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.8.tgz",
"integrity": "sha512-4HxrsN9eUzJXdVGMTYA5Xler82FuZUu21bXKN42zcLHHNKCAMPUzD62I+GwDhsdgUBAUj0tRXDdsQHgaP6v0HA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.11.tgz",
"integrity": "sha512-Y2Rh+PcyVhQqXKBTacPCltINN3uIw2xC+dsvLANJ1SpK5NJUtxv8+rqWpjmBgaNWKQT1/uGpMmA9olALy9PLVA==",
"dev": true,
"optional": true
},
"esbuild-linux-arm": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.8.tgz",
"integrity": "sha512-7DVBU9SFjX4+vBwt8tHsUCbE6Vvl6y6FQWHAgyw1lybC5gULqn/WnjHYHN2/LJaZRsDBvxWT4msEgwLGq1Wd3Q==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.11.tgz",
"integrity": "sha512-TJllTVk5aSyqPFvvcHTvf6Wu1ZKhWpJ/qNmZO8LL/XeB+LXCclm7HQHNEIz6MT7IX8PmlC1BZYrOiw2sXSB95A==",
"dev": true,
"optional": true
},
"esbuild-linux-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.8.tgz",
"integrity": "sha512-1OCm7Aq0tEJT70PbxmHSGYDLYP8DKH8r4Nk7/XbVzWaduo9beCjGBB+tGZIHK6DdTQ3h00/4Tb/70YMH/bOtKg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.11.tgz",
"integrity": "sha512-uhcXiTwTmD4OpxJu3xC5TzAAw6Wzf9O1XGWL448EE9bqGjgV1j+oK3lIHAfsHnuIn8K4nDW8yjX0Sv5S++oRuw==",
"dev": true,
"optional": true
},
"esbuild-linux-mips64le": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.8.tgz",
"integrity": "sha512-yeFoNPVFPEzZvFYBfUQNG2TjGRaCyV1E27OcOg4LOtnGrxb2wA+mkW3luckyv1CEyd00mpAg7UdHx8nlx3ghgA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.11.tgz",
"integrity": "sha512-WD61y/R1M4BLe4gxXRypoQ0Ci+Vjf714QYzcPNkiYv5I8K8WDz2ZR8Bm6cqKxd6rD+e/rZgPDbhQ9PCf7TMHmA==",
"dev": true,
"optional": true
},
"esbuild-linux-ppc64le": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.8.tgz",
"integrity": "sha512-CEyMMUUNabXibw8OSNmBXhOIGhnjNVl5Lpseiuf00iKN0V47oqDrbo4dsHz1wH62m49AR8iG8wpDlTqfYgKbtg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.11.tgz",
"integrity": "sha512-JVleZS9oPVLTlBhPTWgOwxFWU/wMUdlBwTbGA4GF8c38sLbS13cupj+C8bLq929jU7EMWry4SaL+tKGIaTlqKg==",
"dev": true,
"optional": true
},
"esbuild-linux-riscv64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.8.tgz",
"integrity": "sha512-OCGSOaspMUjexSCU8ZiA0UnV/NiRU+s2vIfEcAQWQ6u32R+2luyfh/4ZaY6jFbylJE07Esc/yRvb9Q5fXuClXA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.11.tgz",
"integrity": "sha512-9aLIalZ2HFHIOZpmVU11sEAS9F8TnHw49daEjcgMpBXHFF57VuT9f9/9LKJhw781Gda0P9jDkuCWJ0tFbErvJw==",
"dev": true,
"optional": true
},
"esbuild-linux-s390x": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.8.tgz",
"integrity": "sha512-RHdpdfxRTSrZXZJlFSLazFU4YwXLB5Rgf6Zr5rffqSsO4y9JybgtKO38bFwxZNlDXliYISXN/YROKrG9s7mZQA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.11.tgz",
"integrity": "sha512-sZHtiXXOKsLI3XGBGoYO4qKBzJlb8xNsWmvFiwFMHFzA4AXgDP1KDp7Dawe9C2pavTRBDvl+Ok4n/DHQ59oaTg==",
"dev": true,
"optional": true
},
"esbuild-netbsd-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.8.tgz",
"integrity": "sha512-VolFFRatBH09T5QMWhiohAWCOien1R1Uz9K0BRVVTBgBaVBt7eArsXTKxVhUgRf2vwu2c2SXkuP0r7HLG0eozw==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.11.tgz",
"integrity": "sha512-hUC9yN06K9sg7ju4Vgu9ChAPdsEgtcrcLfyNT5IKwKyfpLvKUwCMZSdF+gRD3WpyZelgTQfJ+pDx5XFbXTlB0A==",
"dev": true,
"optional": true
},
"esbuild-openbsd-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.8.tgz",
"integrity": "sha512-HTAPlg+n4kUeE/isQxlCfsOz0xJGNoT5LJ9oYZWFKABfVf4Ycu7Zlf5ITgOnrdheTkz8JeL/gISIOCFAoOXrSA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.11.tgz",
"integrity": "sha512-0bBo9SQR4t66Wd91LGMAqmWorzO0TTzVjYiifwoFtel8luFeXuPThQnEm5ztN4g0fnvcp7AnUPPzS/Depf17wQ==",
"dev": true,
"optional": true
},
"esbuild-sunos-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.8.tgz",
"integrity": "sha512-qMP/jR/FzcIOwKj+W+Lb+8Cfr8GZHbHUJxAPi7DUhNZMQ/6y7sOgRzlOSpRrbbUntrRZh0MqOyDhJ3Gpo6L1QA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.11.tgz",
"integrity": "sha512-EuBdTGlsMTjEl1sQnBX2jfygy7iR6CKfvOzi+gEOfhDqbHXsmY1dcpbVtcwHAg9/2yUZSfMJHMAgf1z8M4yyyw==",
"dev": true,
"optional": true
},
"esbuild-windows-32": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.8.tgz",
"integrity": "sha512-RKR1QHh4iWzjUhkP8Yqi75PPz/KS+b8zw3wUrzw6oAkj+iU5Qtyj61ZDaSG3Qf2vc6hTIUiPqVTqBH0NpXFNwg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.11.tgz",
"integrity": "sha512-O0/Wo1Wk6dc0rZSxkvGpmTNIycEznHmkObTFz2VHBhjPsO4ZpCgfGxNkCpz4AdAIeMczpTXt/8d5vdJNKEGC+Q==",
"dev": true,
"optional": true
},
"esbuild-windows-64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.8.tgz",
"integrity": "sha512-ag9ptYrsizgsR+PQE8QKeMqnosLvAMonQREpLw4evA4FFgOBMLEat/dY/9txbpozTw9eEOYyD3a4cE9yTu20FA==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.11.tgz",
"integrity": "sha512-x977Q4HhNjnHx00b4XLAnTtj5vfbdEvkxaQwC1Zh5AN8g5EX+izgZ6e5QgqJgpzyRNJqh4hkgIJF1pyy1be0mQ==",
"dev": true,
"optional": true
},
"esbuild-windows-arm64": {
"version": "0.15.8",
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.8.tgz",
"integrity": "sha512-dbpAb0VyPaUs9mgw65KRfQ9rqiWCHpNzrJusoPu+LpEoswosjt/tFxN7cd2l68AT4qWdBkzAjDLRon7uqMeWcg==",
"version": "0.15.11",
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.11.tgz",
"integrity": "sha512-VwUHFACuBahrvntdcMKZteUZ9HaYrBRODoKe4tIWxguQRvvYoYb7iu5LrcRS/FQx8KPZNaa72zuqwVtHeXsITw==",
"dev": true,
"optional": true
},
@ -18703,12 +18756,12 @@
}
},
"vite": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-3.1.3.tgz",
"integrity": "sha512-/3XWiktaopByM5bd8dqvHxRt5EEgRikevnnrpND0gRfNkrMrPaGGexhtLCzv15RcCMtV2CLw+BPas8YFeSG0KA==",
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/vite/-/vite-3.1.8.tgz",
"integrity": "sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==",
"dev": true,
"requires": {
"esbuild": "^0.15.6",
"esbuild": "^0.15.9",
"fsevents": "~2.3.2",
"postcss": "^8.4.16",
"resolve": "^1.22.1",
@ -25638,10 +25691,9 @@
"jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"nyc": "^15.1.0",
"open-cli": "^6.0.1",
"open-cli": "^7.1.0",
"prettier": "^2.1.1",
"standard-version": "^9.0.0",
"swagger-typescript-api": "^10.0.1",
"ts-node": "^9.0.0",
"typedoc": "^0.23.16",
"typescript": "^4.0.2"
@ -28044,9 +28096,9 @@
}
},
"terser": {
"version": "5.14.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.1.tgz",
"integrity": "sha512-+ahUAE+iheqBTDxXhTisdA8hgvbEG1hHOQ9xmNjeUJSoi6DU/gMrKNcfZjHkyY6Alnuyc+ikYJaxxfHkT3+WuQ==",
"version": "5.15.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
"integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
"dev": true,
"requires": {
"@jridgewell/source-map": "^0.3.2",
@ -28629,16 +28681,27 @@
}
},
"vite": {
"version": "2.9.12",
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.12.tgz",
"integrity": "sha512-suxC36dQo9Rq1qMB2qiRorNJtJAdxguu5TMvBHOc/F370KvqAe9t48vYp+/TbPKRNrMh/J55tOUmkuIqstZaew==",
"version": "2.9.15",
"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.15.tgz",
"integrity": "sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ==",
"dev": true,
"requires": {
"esbuild": "^0.14.27",
"fsevents": "~2.3.2",
"postcss": "^8.4.13",
"resolve": "^1.22.0",
"rollup": "^2.59.0"
"rollup": ">=2.59.0 <2.78.0"
},
"dependencies": {
"rollup": {
"version": "2.77.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.3.tgz",
"integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==",
"dev": true,
"requires": {
"fsevents": "~2.3.2"
}
}
}
},
"vite-node": {

33
packages/nc-gui/pages/[projectType]/form/[viewId]/index.vue

@ -69,6 +69,8 @@ p {
.nc-form-view {
.nc-cell {
@apply bg-white dark:bg-slate-500;
&.nc-cell-checkbox {
@apply color-transition !border-0;
@ -91,7 +93,20 @@ p {
&.nc-input {
@apply w-full rounded p-2 min-h-[40px] flex items-center border-solid border-1 border-gray-300 dark:border-slate-200;
.duration-cell-wrapper {
@apply w-full;
input {
@apply !outline-none;
&::placeholder {
@apply text-gray-400 dark:text-slate-300;
}
}
}
input,
textarea,
&.nc-virtual-cell,
> div {
@apply bg-white dark:(bg-slate-500 text-white);
@ -104,12 +119,24 @@ p {
@apply dark:(bg-slate-700 text-white);
}
}
}
.nc-attachment-cell > div {
@apply dark:(bg-slate-100);
&.nc-cell-longtext {
@apply !p-0 pb-2px pr-2px;
}
textarea {
@apply px-4 py-2 rounded;
&:focus {
box-shadow: none !important;
}
}
}
}
.nc-attachment-cell > div {
@apply dark:(bg-slate-100);
}
}
}

24
packages/nc-gui/pages/[projectType]/form/[viewId]/index/survey.vue

@ -159,6 +159,12 @@ function resetForm() {
goTo(steps.value[0])
}
function submit() {
if (submitted.value) return
submitForm()
}
onReset(resetForm)
onKeyStroke(['ArrowLeft', 'ArrowDown'], () => {
@ -169,7 +175,7 @@ onKeyStroke(['ArrowRight', 'ArrowUp'], () => {
})
onKeyStroke(['Enter', 'Space'], () => {
if (isLast.value) {
submitForm()
submit()
} else {
goNext(AnimationTarget.OkButton)
}
@ -218,7 +224,7 @@ onMounted(() => {
<Transition :name="`slide-${transitionName}`" :duration="transitionDuration" mode="out-in">
<div
ref="el"
:key="field.title"
:key="field?.title"
class="color-transition h-full flex flex-col mt-6 gap-4 w-full max-w-[max(33%,600px)] m-auto"
>
<div v-if="field && !submitted" class="flex flex-col gap-2">
@ -233,16 +239,18 @@ onMounted(() => {
<LazySmartsheetHeaderCell
v-else
:class="field.uidt === UITypes.Checkbox ? 'nc-form-column-label__checkbox' : ''"
:column="{ ...field, title: field.label || field.title }"
:column="{ meta: {}, ...field, title: field.label || field.title }"
:required="isRequired(field, field.required)"
:hide-menu="true"
/>
</div>
<div>
<div v-if="field.title">
<LazySmartsheetVirtualCell
v-if="isVirtualCol(field)"
v-model="formState[field.title]"
class="mt-0 nc-input"
:row="{ row: {}, oldRow: {}, rowMeta: {} }"
:data-cy="`nc-survey-form__input-${field.title.replaceAll(' ', '')}`"
:column="field"
/>
@ -289,7 +297,7 @@ onMounted(() => {
type="submit"
class="uppercase scaling-btn prose-sm"
data-cy="nc-survey-form__btn-submit"
@click="submitForm"
@click="submit"
>
{{ $t('general.submit') }}
</button>
@ -310,7 +318,7 @@ onMounted(() => {
? 'transform translate-y-[2px] translate-x-[2px] after:(!ring !ring-accent !ring-opacity-100)'
: '',
]"
@click="goNext"
@click="goNext()"
>
<Transition name="fade">
<span v-if="!v$.localState[field.title]?.$error" class="uppercase text-white">Ok</span>
@ -390,7 +398,7 @@ onMounted(() => {
"
class="p-0.5 flex items-center group color-transition"
data-cy="nc-survey-form__icon-prev"
@click="goPrevious"
@click="goPrevious()"
>
<MdiChevronLeft :class="isFirst ? 'text-gray-300' : 'group-hover:text-accent'" class="text-2xl md:text-md" />
</button>
@ -409,7 +417,7 @@ onMounted(() => {
"
class="p-0.5 flex items-center group color-transition"
data-cy="nc-survey-form__icon-next"
@click="goNext"
@click="goNext()"
>
<MdiChevronRight
:class="[isLast || v$.localState[field.title]?.$error ? 'text-gray-300' : 'group-hover:text-accent']"

18
packages/nc-gui/pages/[projectType]/view/[viewId].vue

@ -1,16 +1,5 @@
<script setup lang="ts">
import {
ReadonlyInj,
ReloadViewDataHookInj,
createEventHook,
definePageMeta,
extractSdkResponseErrorMsg,
message,
provide,
ref,
useRoute,
useSharedView,
} from '#imports'
import { definePageMeta, extractSdkResponseErrorMsg, message, ref, useRoute, useSharedView } from '#imports'
definePageMeta({
public: true,
@ -20,11 +9,6 @@ definePageMeta({
const route = useRoute()
const reloadEventHook = createEventHook()
provide(ReloadViewDataHookInj, reloadEventHook)
provide(ReadonlyInj, true)
const { loadSharedView } = useSharedView()
const showPassword = ref(false)

3
packages/nc-gui/pages/index/index/create-external.vue

@ -113,6 +113,9 @@ const onSSLModeChange = ((mode: SSLUsage) => {
delete connection.ssl
break
case SSLUsage.Allowed:
connection.ssl = 'no-verify'
break
case SSLUsage.Preferred:
connection.ssl = 'true'
break
default:

5
packages/nc-gui/pages/index/index/user.vue

@ -1,4 +1,5 @@
<script lang="ts" setup>
import type { RuleObject } from 'ant-design-vue/es/form'
import { message, navigateTo, reactive, ref, useApi, useGlobal, useI18n, useRouter } from '#imports'
const router = useRouter()
@ -17,7 +18,7 @@ const form = reactive({
passwordRepeat: '',
})
const formRules = {
const formRules: Record<string, RuleObject[]> = {
currentPassword: [
// Current password is required
{ required: true, message: t('msg.error.signUpRules.passwdRequired') },
@ -34,7 +35,7 @@ const formRules = {
{
validator: (_: unknown, _v: string) => {
return new Promise((resolve, reject) => {
if (form.password === form.passwordRepeat) return resolve(true)
if (form.password === form.passwordRepeat) return resolve()
reject(new Error(t('msg.error.signUpRules.passwdMismatch')))
})
},

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save