Browse Source

Merge pull request #7762 from nocodb/develop

pull/7763/head 0.204.2
github-actions[bot] 7 months ago committed by GitHub
parent
commit
42ae12b823
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      .github/workflows/ci-cd.yml
  2. 2
      .github/workflows/playwright-test-workflow.yml
  3. 2
      .github/workflows/pre-build-for-playwright.yml
  4. 2
      .github/workflows/publish-blog.yml
  5. 2
      .github/workflows/publish-dev-docs.yml
  6. 2
      .github/workflows/publish-docs.yml
  7. 2
      .github/workflows/publish-noco-i18n.yml
  8. 2
      .github/workflows/publish-prev-docs.yml
  9. 2
      .github/workflows/release-docker.yml
  10. 2
      .github/workflows/release-draft.yml
  11. 2
      .github/workflows/release-executables.yml
  12. 4
      .github/workflows/release-npm.yml
  13. 2
      .github/workflows/release-timely-executables.yml
  14. 2
      .github/workflows/update-sdk-path.yml
  15. 2
      .npmrc
  16. 8
      README.md
  17. 6
      markdown/readme/languages/chinese.md
  18. 2
      markdown/readme/languages/dutch.md
  19. 2
      markdown/readme/languages/french.md
  20. 2
      markdown/readme/languages/german.md
  21. 6
      markdown/readme/languages/indonesian.md
  22. 2
      markdown/readme/languages/italian.md
  23. 2
      markdown/readme/languages/japanese.md
  24. 2
      markdown/readme/languages/korean.md
  25. 2
      markdown/readme/languages/portuguese.md
  26. 2
      markdown/readme/languages/russian.md
  27. 2
      markdown/readme/languages/spanish.md
  28. 8
      markdown/readme/languages/ukrainian.md
  29. 4
      package.json
  30. 77
      packages/nc-gui/app.vue
  31. 4
      packages/nc-gui/assets/nc-icons/bold.svg
  32. 15
      packages/nc-gui/assets/nc-icons/crop.svg
  33. 14
      packages/nc-gui/assets/nc-icons/eye-off.svg
  34. 10
      packages/nc-gui/assets/nc-icons/eye.svg
  35. 5
      packages/nc-gui/assets/nc-icons/italic.svg
  36. 6
      packages/nc-gui/assets/nc-icons/underline.svg
  37. 36
      packages/nc-gui/assets/style.scss
  38. 361
      packages/nc-gui/components/cell/MultiSelect.vue
  39. 2
      packages/nc-gui/components/cell/RichText.vue
  40. 221
      packages/nc-gui/components/cell/SingleSelect.vue
  41. 17
      packages/nc-gui/components/cell/TextArea.vue
  42. 2
      packages/nc-gui/components/cell/Url.vue
  43. 373
      packages/nc-gui/components/cell/User.vue
  44. 3
      packages/nc-gui/components/cell/attachment/utils.ts
  45. 18
      packages/nc-gui/components/dlg/TableDuplicate.vue
  46. 2
      packages/nc-gui/components/dlg/ViewCreate.vue
  47. 17
      packages/nc-gui/components/general/FormBanner.vue
  48. 141
      packages/nc-gui/components/general/ImageCropper.vue
  49. 2
      packages/nc-gui/components/nc/DateWeekSelector.vue
  50. 2
      packages/nc-gui/components/nc/Select.vue
  51. 429
      packages/nc-gui/components/smartsheet/Form.vue
  52. 2
      packages/nc-gui/components/smartsheet/Kanban.vue
  53. 370
      packages/nc-gui/components/smartsheet/calendar/Cell.vue
  54. 58
      packages/nc-gui/components/smartsheet/calendar/DayView/DateField.vue
  55. 122
      packages/nc-gui/components/smartsheet/calendar/DayView/DateTimeField.vue
  56. 94
      packages/nc-gui/components/smartsheet/calendar/MonthView.vue
  57. 19
      packages/nc-gui/components/smartsheet/calendar/RecordCard.vue
  58. 27
      packages/nc-gui/components/smartsheet/calendar/VRecordCard.vue
  59. 67
      packages/nc-gui/components/smartsheet/calendar/WeekView/DateField.vue
  60. 205
      packages/nc-gui/components/smartsheet/calendar/WeekView/DateTimeField.vue
  61. 15
      packages/nc-gui/components/smartsheet/calendar/index.vue
  62. 293
      packages/nc-gui/components/smartsheet/form/LimitOptions.vue
  63. 37
      packages/nc-gui/components/smartsheet/toolbar/FieldsMenu.vue
  64. 3
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  65. 3
      packages/nc-gui/components/virtual-cell/components/ListItems.vue
  66. 2
      packages/nc-gui/composables/useKanbanViewStore.ts
  67. 32
      packages/nc-gui/composables/useMultiSelect/convertCellData.ts
  68. 2
      packages/nc-gui/composables/useMultiSelect/index.ts
  69. 1
      packages/nc-gui/composables/useSharedFormViewStore.ts
  70. 12
      packages/nc-gui/composables/useViewColumns.ts
  71. 1
      packages/nc-gui/composables/useViewData.ts
  72. 44
      packages/nc-gui/lang/ar.json
  73. 44
      packages/nc-gui/lang/bn_IN.json
  74. 44
      packages/nc-gui/lang/cs.json
  75. 44
      packages/nc-gui/lang/da.json
  76. 44
      packages/nc-gui/lang/de.json
  77. 32
      packages/nc-gui/lang/en.json
  78. 230
      packages/nc-gui/lang/es.json
  79. 44
      packages/nc-gui/lang/eu.json
  80. 44
      packages/nc-gui/lang/fa.json
  81. 44
      packages/nc-gui/lang/fi.json
  82. 44
      packages/nc-gui/lang/fr.json
  83. 44
      packages/nc-gui/lang/he.json
  84. 44
      packages/nc-gui/lang/hi.json
  85. 44
      packages/nc-gui/lang/hr.json
  86. 44
      packages/nc-gui/lang/id.json
  87. 44
      packages/nc-gui/lang/it.json
  88. 44
      packages/nc-gui/lang/ja.json
  89. 44
      packages/nc-gui/lang/ko.json
  90. 44
      packages/nc-gui/lang/lv.json
  91. 44
      packages/nc-gui/lang/nl.json
  92. 44
      packages/nc-gui/lang/no.json
  93. 44
      packages/nc-gui/lang/pl.json
  94. 210
      packages/nc-gui/lang/pt.json
  95. 136
      packages/nc-gui/lang/pt_BR.json
  96. 44
      packages/nc-gui/lang/ru.json
  97. 44
      packages/nc-gui/lang/sk.json
  98. 44
      packages/nc-gui/lang/sl.json
  99. 44
      packages/nc-gui/lang/sv.json
  100. 44
      packages/nc-gui/lang/th.json
  101. Some files were not shown because too many files have changed in this diff Show More

4
.github/workflows/ci-cd.yml

@ -40,7 +40,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
@ -75,7 +75,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:

2
.github/workflows/playwright-test-workflow.yml

@ -23,7 +23,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v2 uses: pnpm/action-setup@v2
with: with:

2
.github/workflows/pre-build-for-playwright.yml

@ -13,7 +13,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v2 uses: pnpm/action-setup@v2
with: with:

2
.github/workflows/publish-blog.yml

@ -17,7 +17,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Build blogs - name: Build blogs
run: | run: |
cd packages/noco-blog cd packages/noco-blog

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

@ -20,7 +20,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Build docs - name: Build docs
run: | run: |
cd packages/noco-docs cd packages/noco-docs

2
.github/workflows/publish-docs.yml

@ -19,7 +19,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Build docs - name: Build docs
run: | run: |
cd packages/noco-docs cd packages/noco-docs

2
.github/workflows/publish-noco-i18n.yml

@ -19,7 +19,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Build noco-i18n - name: Build noco-i18n
run: | run: |
cd packages/noco-i18n cd packages/noco-i18n

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

@ -19,7 +19,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Build prev docs - name: Build prev docs
run: | run: |
cd packages/noco-docs-prev cd packages/noco-docs-prev

2
.github/workflows/release-docker.yml

@ -84,7 +84,7 @@ jobs:
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: upgrade packages for nightly build or pr build - name: upgrade packages for nightly build or pr build
if: ${{ github.event.inputs.targetEnv == 'DEV' || inputs.targetEnv == 'DEV' }} if: ${{ github.event.inputs.targetEnv == 'DEV' || inputs.targetEnv == 'DEV' }}

2
.github/workflows/release-draft.yml

@ -70,5 +70,5 @@ jobs:
}) })
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- run: "npx github-release-notes@0.17.2 release --token ${{ secrets.GITHUB_TOKEN }} --draft --tags ${{ github.event.inputs.tag || inputs.tag }}..${{ github.event.inputs.prev_tag || inputs.prev_tag }}" - run: "npx github-release-notes@0.17.2 release --token ${{ secrets.GITHUB_TOKEN }} --draft --tags ${{ github.event.inputs.tag || inputs.tag }}..${{ github.event.inputs.prev_tag || inputs.prev_tag }}"

2
.github/workflows/release-executables.yml

@ -63,7 +63,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name : Install nocodb, other dependencies and build executables - name : Install nocodb, other dependencies and build executables
run: | run: |

4
.github/workflows/release-npm.yml

@ -46,11 +46,11 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
ref: ${{ github.ref }} ref: ${{ github.ref }}
- name: pnpm Setup and Publish with 18.19.0 - name: pnpm Setup and Publish with 18.19.1
# Setup .npmrc file to publish to npm # Setup .npmrc file to publish to npm
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- run: | - run: |
export NODE_OPTIONS="--max_old_space_size=16384" export NODE_OPTIONS="--max_old_space_size=16384"

2
.github/workflows/release-timely-executables.yml

@ -64,7 +64,7 @@ jobs:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Update nocodb-timely - name: Update nocodb-timely
env: env:

2
.github/workflows/update-sdk-path.yml

@ -16,7 +16,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18.19.0 node-version: 18.19.1
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:

2
.npmrc

@ -1,3 +1,3 @@
engine-strict=true engine-strict=true
shamefully-hoist=true shamefully-hoist=true
use-node-version=18.19.0 use-node-version=18.19.1

8
README.md

@ -15,7 +15,7 @@ Turns any MySQL, PostgreSQL, SQL Server, SQLite & MariaDB into a smart spreadshe
<div align="center"> <div align="center">
[![Node version](https://img.shields.io/badge/node-%3E%3D%2018.19.0-brightgreen)](http://nodejs.org/download/) [![Node version](https://img.shields.io/badge/node-%3E%3D%2018.19.1-brightgreen)](http://nodejs.org/download/)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-green.svg)](https://conventionalcommits.org) [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-green.svg)](https://conventionalcommits.org)
</div> </div>
@ -265,11 +265,11 @@ We provide the following ways to let users programmatically invoke actions. You
### Sync Schema ### Sync Schema
We allow you to sync schema changes if you have made changes outside NocoDB GUI. However, it has to be noted then you will have to bring your own schema migrations for moving from one environment to another. See <a href="https://docs.nocodb.com/setup-and-usages/sync-schema/" target="_blank">Sync Schema</a> for details. We allow you to sync schema changes if you have made changes outside NocoDB GUI. However, it has to be noted then you will have to bring your own schema migrations for moving from one environment to another. See <a href="https://docs.nocodb.com/data-sources/sync-with-data-source" target="_blank">Sync Schema</a> for details.
### Audit ### Audit
We are keeping all the user operation logs in one place. See <a href="https://docs.nocodb.com/setup-and-usages/audit" target="_blank">Audit</a> for details. We are keeping all the user operation logs in one place. See <a href="https://docs.nocodb.com/data-sources/actions-on-data-sources/#audit-logs" target="_blank">Audit</a> for details.
# Production Setup # Production Setup
@ -277,7 +277,7 @@ By default, SQLite is used for storing metadata. However, you can specify your d
## Environment variables ## Environment variables
Please refer to the [Environment variables](https://docs.nocodb.com/getting-started/environment-variables) Please refer to the [Environment variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Development Setup # Development Setup

6
markdown/readme/languages/chinese.md

@ -189,11 +189,11 @@ docker-compose up -d
### 架构同步 ### 架构同步
如果您在 NocoDB GUI 之外进行了更改,我们允许您同步架构更改。 但是,必须注意的是,您必须附有自己的迁移架构才能从一个环境迁移到其他环境。 有关详细信息,请参阅 <a href="https://docs.nocodb.com/setup-and-usages/sync-schema/" target="_blank">同步架构</a> 如果您在 NocoDB GUI 之外进行了更改,我们允许您同步架构更改。 但是,必须注意的是,您必须附有自己的迁移架构才能从一个环境迁移到其他环境。 有关详细信息,请参阅 <a href="https://docs.nocodb.com/data-sources/sync-with-data-source" target="_blank">同步架构</a>
### 审计 ### 审计
我们将所有用户操作日志保存在一起。 有关详细信息,请参阅 <a href="https://docs.nocodb.com/setup-and-usages/audit" target="_blank">审计</a> 我们将所有用户操作日志保存在一起。 有关详细信息,请参阅 <a href="https://docs.nocodb.com/data-sources/actions-on-data-sources/#audit-logs" target="_blank">审计</a>
# 生产部署 # 生产部署
@ -201,7 +201,7 @@ docker-compose up -d
## 环境变量 ## 环境变量
参见[环境变量](https://docs.nocodb.com/getting-started/environment-variables) 参见[环境变量](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# 开发 # 开发

2
markdown/readme/languages/dutch.md

@ -181,7 +181,7 @@ docker-compose up -d
## Environment variables ## Environment variables
Please refer to [Environment variables](https://docs.nocodb.com/getting-started/environment-variables) Please refer to [Environment variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Development setup # Development setup

2
markdown/readme/languages/french.md

@ -182,7 +182,7 @@ docker-compose up -d
## Variables d'environnement ## Variables d'environnement
Please refer to [Environment variables](https://docs.nocodb.com/getting-started/environment-variables) Please refer to [Environment variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Paramétrage du développement # Paramétrage du développement

2
markdown/readme/languages/german.md

@ -190,7 +190,7 @@ docker-compose up -d
## Umgebungsvariablen ## Umgebungsvariablen
Siehe [Environment variables](https://docs.nocodb.com/getting-started/environment-variables) Siehe [Environment variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Entwicklungsaufbau # Entwicklungsaufbau

6
markdown/readme/languages/indonesian.md

@ -256,11 +256,11 @@ Akses dasbor menggunakan : [http://localhost:8080/dashboard](http://localhost:80
### Sinkronisasi Skema ### Sinkronisasi Skema
Kami memungkinkan Anda untuk menyinkronkan perubahan skema jika Anda telah melakukan perubahan di luar antarmuka NocoDB GUI. Namun, perlu diperhatikan bahwa Anda harus menyediakan migrasi skema sendiri untuk berpindah dari satu lingkungan ke lingkungan lainnya. Lihat [Sinkronisasi Skema](https://docs.nocodb.com/setup-and-usages/sync-schema/) untuk detail lebih lanjut. Kami memungkinkan Anda untuk menyinkronkan perubahan skema jika Anda telah melakukan perubahan di luar antarmuka NocoDB GUI. Namun, perlu diperhatikan bahwa Anda harus menyediakan migrasi skema sendiri untuk berpindah dari satu lingkungan ke lingkungan lainnya. Lihat [Sinkronisasi Skema](https://docs.nocodb.com/data-sources/sync-with-data-source) untuk detail lebih lanjut.
### Audit ### Audit
Kami menyimpan semua log operasi pengguna di satu tempat. Lihat [Audit](https://docs.nocodb.com/setup-and-usages/audit) untuk detail lebih lanjut. Kami menyimpan semua log operasi pengguna di satu tempat. Lihat [Audit](https://docs.nocodb.com/data-sources/actions-on-data-sources/#audit-logs) untuk detail lebih lanjut.
# Pengaturan Produksi # Pengaturan Produksi
@ -268,7 +268,7 @@ Secara default, SQLite digunakan untuk menyimpan metadata. Namun, Anda dapat men
## Environment variables ## Environment variables
Silakan lihat [Environment Variables](https://docs.nocodb.com/getting-started/environment-variables) untuk informasi lebih lanjut. Silakan lihat [Environment Variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables) untuk informasi lebih lanjut.
# Pengaturan Pengembangan # Pengaturan Pengembangan

2
markdown/readme/languages/italian.md

@ -185,7 +185,7 @@ docker-compose up -d
## Variabili d'ambiente ## Variabili d'ambiente
Please refer to [Environment variables](https://docs.nocodb.com/getting-started/environment-variables) Please refer to [Environment variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Setup di sviluppo # Setup di sviluppo

2
markdown/readme/languages/japanese.md

@ -184,7 +184,7 @@ docker-compose up -d
## 環境変数 ## 環境変数
[環境変数](https://docs.nocodb.com/getting-started/environment-variables)をご参照ください [環境変数](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)をご参照ください
# 開発セットアップ # 開発セットアップ

2
markdown/readme/languages/korean.md

@ -185,7 +185,7 @@ docker-compose up -d
## 환경변수 ## 환경변수
여기서 확인해주세요. 여기서 확인해주세요.
[환경변수 ](https://docs.nocodb.com/getting-started/environment-variables) [환경변수 ](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# 개발 환경에 설치 # 개발 환경에 설치

2
markdown/readme/languages/portuguese.md

@ -183,7 +183,7 @@ docker-compose up -d
## Environment variables ## Environment variables
Please refer to [Environment variables](https://docs.nocodb.com/getting-started/environment-variables) Please refer to [Environment variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Development setup # Development setup

2
markdown/readme/languages/russian.md

@ -185,7 +185,7 @@ docker-compose up -d
## Переменные среды ## Переменные среды
Please refer to [Environment variables](https://docs.nocodb.com/getting-started/environment-variables) Please refer to [Environment variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Настройка разработки # Настройка разработки

2
markdown/readme/languages/spanish.md

@ -182,7 +182,7 @@ docker-compose up -d
## Variables de entorno ## Variables de entorno
Por favor diríjase a [Environment variables](https://docs.nocodb.com/getting-started/environment-variables) Por favor diríjase a [Environment variables](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Configuración de desarollo # Configuración de desarollo

8
markdown/readme/languages/ukrainian.md

@ -15,7 +15,7 @@ Nocodb перетворює будь-яку базу даних MySQL, PostgreSQ
<div align="center"> <div align="center">
[![Node version](https://img.shields.io/badge/node-%3E%3D%2018.19.0-brightgreen)](http://nodejs.org/download/) [![Node version](https://img.shields.io/badge/node-%3E%3D%2018.19.1-brightgreen)](http://nodejs.org/download/)
[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-green.svg)](https://conventionalcommits.org) [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-green.svg)](https://conventionalcommits.org)
</div> </div>
@ -238,11 +238,11 @@ npm start
### Синхронізація схеми ### Синхронізація схеми
Ми дозволяємо вам синхронізувати зміни схеми, якщо ви внесли зміни поза NocoDB GUI. Проте слід зауважити, що вам доведеться мати власні міграції схеми для переміщення з одного середовища в інше. Деталі дивіться у <a href="https://docs.nocodb.com/setup-and-usages/sync-schema/" target="_blank">Sync Schema</a>. Ми дозволяємо вам синхронізувати зміни схеми, якщо ви внесли зміни поза NocoDB GUI. Проте слід зауважити, що вам доведеться мати власні міграції схеми для переміщення з одного середовища в інше. Деталі дивіться у <a href="https://docs.nocodb.com/data-sources/sync-with-data-source" target="_blank">Sync Schema</a>.
### Аудит ### Аудит
Ми зберігаємо всі журнали операцій користувача в одному місці. Деталі дивіться у <a href="https://docs.nocodb.com/setup-and-usages/audit" target="_blank">Audit</a>. Ми зберігаємо всі журнали операцій користувача в одному місці. Деталі дивіться у <a href="https://docs.nocodb.com/data-sources/actions-on-data-sources/#audit-logs" target="_blank">Audit</a>.
# Налаштування продукції # Налаштування продукції
@ -250,7 +250,7 @@ npm start
## Змінні середовища ## Змінні середовища
Будь ласка, звертайтеся до [Змінні середовища](https://docs.nocodb.com/getting-started/environment-variables) Будь ласка, звертайтеся до [Змінні середовища](https://docs.nocodb.com/getting-started/self-hosted/environment-variables)
# Налаштування розробки # Налаштування розробки

4
package.json

@ -17,9 +17,9 @@
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"devDependencies": { "devDependencies": {
"fs": "0.0.1-security", "fs": "0.0.1-security",
"lerna": "^7.0.2", "lerna": "^7.4.2",
"husky": "^8.0.3", "husky": "^8.0.3",
"xlsx": "^0.17.4" "xlsx": "^0.17.5"
}, },
"husky": { "husky": {
"hooks": { "hooks": {

77
packages/nc-gui/app.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { message } from 'ant-design-vue'
import { extractSdkResponseErrorMsg } from './utils'
import { applyNonSelectable, computed, isEeUI, isMac, useCommandPalette, useRouter, useTheme } from '#imports' import { applyNonSelectable, computed, isEeUI, isMac, useCommandPalette, useRouter, useTheme } from '#imports'
import type { CommandPaletteType } from '~/lib' import type { CommandPaletteType } from '~/lib'
@ -96,27 +98,70 @@ onMounted(() => {
refreshCommandPalette() refreshCommandPalette()
}) })
}) })
let errorCount = 0
const handleError = async (error, clearError) => {
console.error('UI ERROR', error.value)
// if error is api error, show toast message with error message
if (error.value?.response) {
message.warn(await extractSdkResponseErrorMsg(error.value))
} else {
// else show generic error message
message.warn('Something went wrong. Please reload the page if page is not functioning properly.')
}
clearError()
// if error count is more than 3 within 3 second, navigate to home
// since it's likely endless loop of errors due to some UI issue in certain page
errorCount++
if (errorCount > 3) {
router.push('/')
}
// reset error count after 1 second
setTimeout(() => {
errorCount = 0
}, 3000)
}
</script> </script>
<template> <template>
<a-config-provider> <a-config-provider>
<NuxtLayout :name="disableBaseLayout ? false : 'base'"> <NuxtLayout :name="disableBaseLayout ? false : 'base'">
<NuxtPage :key="key" :transition="false" /> <NuxtErrorBoundary>
<NuxtPage :key="key" :transition="false" />
<!-- on error, clear error and show toast message -->
<template #error="{ error, clearError }">
{{ handleError(error, clearError) }}
</template>
</NuxtErrorBoundary>
</NuxtLayout> </NuxtLayout>
</a-config-provider> </a-config-provider>
<!-- Command Menu -->
<CmdK <NuxtErrorBoundary>
ref="commandPalette" <div>
v-model:open="cmdK" <!-- Command Menu -->
:scope="activeScope.scope" <CmdK
:data="cmdData" ref="commandPalette"
:placeholder="cmdPlaceholder" v-model:open="cmdK"
:load-temporary-scope="loadTemporaryScope" :scope="activeScope.scope"
:set-active-cmd-view="setActiveCmdView" :data="cmdData"
@scope="onScope" :placeholder="cmdPlaceholder"
/> :load-temporary-scope="loadTemporaryScope"
<!-- Recent Views. Cycles through recently visited Views --> :set-active-cmd-view="setActiveCmdView"
<CmdL v-model:open="cmdL" :set-active-cmd-view="setActiveCmdView" /> @scope="onScope"
<!-- Documentation. Integrated NocoDB Docs directlt inside the Product --> />
<CmdJ /> <!-- Recent Views. Cycles through recently visited Views -->
<CmdL v-model:open="cmdL" :set-active-cmd-view="setActiveCmdView" />
<!-- Documentation. Integrated NocoDB Docs directly inside the Product -->
<CmdJ />
</div>
<!-- on error, clear error and show toast message -->
<template #error="{ error, clearError }">
{{ handleError(error, clearError) }}
</template>
</NuxtErrorBoundary>
</template> </template>

4
packages/nc-gui/assets/nc-icons/bold.svg

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 8H10C10.7072 8 11.3855 8.28095 11.8856 8.78105C12.3857 9.28115 12.6667 9.95942 12.6667 10.6667C12.6667 11.3739 12.3857 12.0522 11.8856 12.5523C11.3855 13.0524 10.7072 13.3333 10 13.3333H4V8Z" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4 2.66663H9.33333C10.0406 2.66663 10.7189 2.94758 11.219 3.44767C11.719 3.94777 12 4.62605 12 5.33329C12 6.04054 11.719 6.71881 11.219 7.21891C10.7189 7.71901 10.0406 7.99996 9.33333 7.99996H4V2.66663Z" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 672 B

15
packages/nc-gui/assets/nc-icons/crop.svg

@ -0,0 +1,15 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_184_5665)">
<path
d="M4.08667 0.666626L4 10.6666C4 11.0202 4.14048 11.3594 4.39052 11.6094C4.64057 11.8595 4.97971 12 5.33333 12H15.3333"
stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M0.666672 4.08667L10.6667 4C11.0203 4 11.3594 4.14048 11.6095 4.39052C11.8595 4.64057 12 4.97971 12 5.33333V15.3333"
stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round" />
</g>
<defs>
<clipPath id="clip0_184_5665">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 797 B

14
packages/nc-gui/assets/nc-icons/eye-off.svg

@ -0,0 +1,14 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_453_14719)">
<path
d="M6.59984 2.82676C7.05873 2.71935 7.52855 2.66566 7.99984 2.66676C12.6665 2.66676 15.3332 8.0001 15.3332 8.0001C14.9285 8.75717 14.4459 9.46992 13.8932 10.1268M9.41317 9.41343C9.23007 9.60993 9.00927 9.76754 8.76394 9.87685C8.51861 9.98616 8.25377 10.0449 7.98523 10.0497C7.71669 10.0544 7.44995 10.005 7.20091 9.90443C6.95188 9.80384 6.72565 9.65412 6.53573 9.4642C6.34582 9.27428 6.1961 9.04806 6.09551 8.79902C5.99492 8.54999 5.94552 8.28325 5.95026 8.0147C5.955 7.74616 6.01378 7.48133 6.12309 7.236C6.2324 6.99067 6.39001 6.76986 6.5865 6.58677M11.9598 11.9601C10.8202 12.8288 9.43258 13.31 7.99984 13.3334C3.33317 13.3334 0.666504 8.0001 0.666504 8.0001C1.49576 6.4547 2.64593 5.1045 4.03984 4.0401L11.9598 11.9601Z"
stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round" />
<path d="M0.666504 0.666748L15.3332 15.3334" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round"
stroke-linejoin="round" />
</g>
<defs>
<clipPath id="clip0_453_14719">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

10
packages/nc-gui/assets/nc-icons/eye.svg

@ -1,4 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.666656 7.99996C0.666656 7.99996 3.33332 2.66663 7.99999 2.66663C12.6667 2.66663 15.3333 7.99996 15.3333 7.99996C15.3333 7.99996 12.6667 13.3333 7.99999 13.3333C3.33332 13.3333 0.666656 7.99996 0.666656 7.99996Z" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path
<path d="M8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> d="M0.666504 8.00008C0.666504 8.00008 3.33317 2.66675 7.99984 2.66675C12.6665 2.66675 15.3332 8.00008 15.3332 8.00008C15.3332 8.00008 12.6665 13.3334 7.99984 13.3334C3.33317 13.3334 0.666504 8.00008 0.666504 8.00008Z"
</svg> stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round" />
<path
d="M8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z"
stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round" />
</svg>

Before

Width:  |  Height:  |  Size: 634 B

After

Width:  |  Height:  |  Size: 675 B

5
packages/nc-gui/assets/nc-icons/italic.svg

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.33325 13.3334H3.33325" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.6667 2.66663H6.66675" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 2.66663L6 13.3333" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 433 B

6
packages/nc-gui/assets/nc-icons/underline.svg

@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="underline">
<path id="Vector" d="M2.66675 14H13.3334" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path id="Vector_2" d="M4 2V6.66667C4 7.72753 4.42143 8.74495 5.17157 9.49509C5.92172 10.2452 6.93913 10.6667 8 10.6667C9.06087 10.6667 10.0783 10.2452 10.8284 9.49509C11.5786 8.74495 12 7.72753 12 6.66667V2" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 547 B

36
packages/nc-gui/assets/style.scss

@ -749,3 +749,39 @@ svg.nc-cell-icon, svg.nc-virtual-cell-icon {
@apply w-1em h-1em flex-none; @apply w-1em h-1em flex-none;
font-size: 1rem; font-size: 1rem;
} }
// For select type field list layout
.nc-field-layout-list {
@apply !flex !flex-col !items-start w-full !space-y-0.5 !max-w-full;
.ant-checkbox-wrapper {
@apply !m-0 !h-9 !mr-0 !flex !items-center w-full !max-w-full pl-2 rounded-lg hover:bg-gray-100;
&:hover {
.ant-checkbox-checked:after {
@apply !rounded;
}
}
.ant-checkbox {
@apply !top-0;
& + span {
@apply !flex !pl-4 max-w-[calc(100%_-_16px)];
}
.ant-checkbox-checked:after,
.ant-checkbox-inner {
@apply !rounded;
}
}
}
.ant-radio-wrapper {
@apply !m-0 !h-9 !mr-0 !flex !items-center w-full !max-w-full pl-2 rounded-lg hover:bg-gray-100;
.ant-radio {
@apply !top-0;
}
.ant-radio + span {
@apply !flex !pl-4 max-w-[calc(100%_-_16px)];
}
}
}

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

@ -3,6 +3,7 @@ import { message } from 'ant-design-vue'
import tinycolor from 'tinycolor2' import tinycolor from 'tinycolor2'
import type { Select as AntSelect } from 'ant-design-vue' import type { Select as AntSelect } from 'ant-design-vue'
import type { SelectOptionType, SelectOptionsType } from 'nocodb-sdk' import type { SelectOptionType, SelectOptionsType } from 'nocodb-sdk'
import type { FormFieldsLimitOptionsType } from '~/lib'
import { import {
ActiveCellInj, ActiveCellInj,
ColumnInj, ColumnInj,
@ -95,7 +96,43 @@ const options = computed<(SelectOptionType & { value?: string })[]>(() => {
for (const op of opts.filter((el: SelectOptionType) => el.order === null)) { for (const op of opts.filter((el: SelectOptionType) => el.order === null)) {
op.title = op.title?.replace(/^'/, '').replace(/'$/, '') op.title = op.title?.replace(/^'/, '').replace(/'$/, '')
} }
return opts.map((o: SelectOptionType) => ({ ...o, value: o.title })) let order = 1
const limitOptionsById =
((parseProp(column.value.meta)?.limitOptions || []).reduce(
(o: Record<string, FormFieldsLimitOptionsType>, f: FormFieldsLimitOptionsType) => {
if (order < (f?.order ?? 0)) {
order = f.order
}
return {
...o,
[f.id]: f,
}
},
{},
) as Record<string, FormFieldsLimitOptionsType>) ?? {}
if (
!isEditColumn.value &&
isForm.value &&
parseProp(column.value.meta)?.isLimitOption &&
(parseProp(column.value.meta)?.limitOptions || []).length
) {
return opts
.filter((o: SelectOptionType) => {
if (limitOptionsById[o.id!]?.show !== undefined) {
return limitOptionsById[o.id!]?.show
}
return false
})
.map((o) => ({
...o,
value: o.title,
order: o.id && limitOptionsById[o.id] ? limitOptionsById[o.id]?.order : order++,
}))
.sort((a, b) => a.order - b.order)
} else {
return opts.map((o: SelectOptionType) => ({ ...o, value: o.title }))
}
} }
return [] return []
}) })
@ -353,154 +390,194 @@ const onFocus = () => {
<template> <template>
<div <div
class="nc-cell-field nc-multi-select h-full w-full flex items-center" class="nc-cell-field nc-multi-select h-full w-full flex items-center"
:class="{ 'read-only': readOnly }" :class="{ 'read-only': readOnly, 'max-w-full': isForm }"
@click="toggleMenu" @click="toggleMenu"
> >
<div <div v-if="!isEditColumn && isForm && parseProp(column.meta)?.isList" class="w-full max-w-full">
v-if="!active" <a-checkbox-group v-model:value="vModel" class="nc-field-layout-list">
class="flex flex-wrap" <a-checkbox
:style="{ v-for="op of options"
'display': '-webkit-box', :key="op.title"
'max-width': '100%', :value="op.title"
'-webkit-line-clamp': rowHeight || 1, :data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
'-webkit-box-orient': 'vertical', :class="`nc-select-option-${column.title}-${op.title}`"
'overflow': 'hidden', >
}" <a-tag class="rounded-tag max-w-full" :color="op.color">
> <span
<template v-for="selectedOpt of selectedOpts" :key="selectedOpt.value"> :style="{
<a-tag class="rounded-tag max-w-full" :color="selectedOpt.color"> 'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
<span ? '#fff'
:style="{ : tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'color': tinycolor.isReadable(selectedOpt.color || '#ccc', '#fff', { level: 'AA', size: 'large' }) 'font-size': '13px',
? '#fff' }"
: tinycolor.mostReadable(selectedOpt.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(), >
'font-size': '13px', <NcTooltip class="truncate max-w-full" show-on-truncate-only>
}" <template #title>
:class="{ 'text-sm': isKanban }" {{ op.title }}
> </template>
<NcTooltip class="truncate max-w-full" show-on-truncate-only> <span
<template #title> class="text-ellipsis overflow-hidden"
{{ selectedOpt.title }} :style="{
</template> wordBreak: 'keep-all',
<span whiteSpace: 'nowrap',
class="text-ellipsis overflow-hidden" display: 'inline',
:style="{ }"
wordBreak: 'keep-all', >
whiteSpace: 'nowrap', {{ op.title }}
display: 'inline', </span>
}" </NcTooltip>
> </span>
{{ selectedOpt.title }} </a-tag>
</span> </a-checkbox>
</NcTooltip> </a-checkbox-group>
</span>
</a-tag>
</template>
</div> </div>
<template v-else>
<a-select <div
v-else v-if="!active"
ref="aselect" class="flex flex-wrap"
v-model:value="vModel" :style="{
mode="multiple" 'display': '-webkit-box',
class="w-full overflow-hidden" 'max-width': '100%',
:placeholder="isEditColumn ? $t('labels.optional') : ''" '-webkit-line-clamp': rowHeight || 1,
:bordered="false" '-webkit-box-orient': 'vertical',
clear-icon 'overflow': 'hidden',
:show-search="!isMobileMode" }"
:show-arrow="editAllowed && !readOnly"
:open="isOpen && editAllowed"
:disabled="readOnly || !editAllowed"
:class="{ 'caret-transparent': !hasEditRoles }"
:dropdown-class-name="`nc-dropdown-multi-select-cell !min-w-200px ${isOpen ? 'active' : ''}`"
@search="search"
@keydown="onKeyDown"
@focus="onFocus"
@blur="isOpen = false"
>
<template #suffixIcon>
<GeneralIcon icon="arrowDown" class="text-gray-700 nc-select-expand-btn" />
</template>
<a-select-option
v-for="op of options"
:key="op.id || op.title"
:value="op.title"
:data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
:class="`nc-select-option-${column.title}-${op.title}`"
@click.stop
> >
<a-tag class="rounded-tag max-w-full" :color="op.color"> <template v-for="selectedOpt of selectedOpts" :key="selectedOpt.value">
<span <a-tag class="rounded-tag max-w-full" :color="selectedOpt.color">
:style="{ <span
'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' }) :style="{
? '#fff' 'color': tinycolor.isReadable(selectedOpt.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
: tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(), ? '#fff'
'font-size': '13px', : tinycolor.mostReadable(selectedOpt.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
}" 'font-size': '13px',
:class="{ 'text-sm': isKanban }" }"
> :class="{ 'text-sm': isKanban }"
<NcTooltip class="truncate max-w-full" show-on-truncate-only> >
<template #title> <NcTooltip class="truncate max-w-full" show-on-truncate-only>
{{ op.title }} <template #title>
</template> {{ selectedOpt.title }}
<span </template>
class="text-ellipsis overflow-hidden" <span
:style="{ class="text-ellipsis overflow-hidden"
wordBreak: 'keep-all', :style="{
whiteSpace: 'nowrap', wordBreak: 'keep-all',
display: 'inline', whiteSpace: 'nowrap',
}" display: 'inline',
> }"
{{ op.title }} >
</span> {{ selectedOpt.title }}
</NcTooltip> </span>
</span> </NcTooltip>
</a-tag> </span>
</a-select-option> </a-tag>
</template>
<a-select-option </div>
v-if="searchVal && isOptionMissing && !isPublic && !disableOptionCreation && isUIAllowed('fieldEdit')"
:key="searchVal" <a-select
:value="searchVal" v-else
ref="aselect"
v-model:value="vModel"
mode="multiple"
class="w-full overflow-hidden"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
:bordered="false"
clear-icon
:show-search="!isMobileMode"
:show-arrow="editAllowed && !readOnly"
:open="isOpen && editAllowed"
:disabled="readOnly || !editAllowed"
:class="{ 'caret-transparent': !hasEditRoles }"
:dropdown-class-name="`nc-dropdown-multi-select-cell !min-w-200px ${isOpen ? 'active' : ''}`"
@search="search"
@keydown="onKeyDown"
@focus="onFocus"
@blur="isOpen = false"
> >
<div class="flex gap-2 text-gray-500 items-center h-full"> <template #suffixIcon>
<component :is="iconMap.plusThick" class="min-w-4" /> <GeneralIcon icon="arrowDown" class="text-gray-700 nc-select-expand-btn" />
<div class="text-xs whitespace-normal"> </template>
{{ $t('msg.selectOption.createNewOptionNamed') }} <strong>{{ searchVal }}</strong> <a-select-option
</div> v-for="op of options"
</div> :key="op.id || op.title"
</a-select-option> :value="op.title"
:data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
<template #tagRender="{ value: val, onClose }"> :class="`nc-select-option-${column.title}-${op.title}`"
<a-tag @click.stop
v-if="options.find((el) => el.title === val)"
class="rounded-tag nc-selected-option"
:style="{ display: 'flex', alignItems: 'center' }"
:color="options.find((el) => el.title === val)?.color"
:closable="editAllowed && (vModel.length > 1 || !column?.rqd)"
:close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })"
@click="onTagClick($event, onClose)"
@close="onClose"
> >
<span <a-tag class="rounded-tag max-w-full" :color="op.color">
:style="{ <span
'color': tinycolor.isReadable(options.find((el) => el.title === val)?.color || '#ccc', '#fff', { :style="{
level: 'AA', 'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
size: 'large', ? '#fff'
}) : tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
? '#fff' 'font-size': '13px',
: tinycolor }"
.mostReadable(options.find((el) => el.title === val)?.color || '#ccc', ['#0b1d05', '#fff']) :class="{ 'text-sm': isKanban }"
.toHex8String(), >
'font-size': '13px', <NcTooltip class="truncate max-w-full" show-on-truncate-only>
}" <template #title>
:class="{ 'text-sm': isKanban }" {{ op.title }}
</template>
<span
class="text-ellipsis overflow-hidden"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ op.title }}
</span>
</NcTooltip>
</span>
</a-tag>
</a-select-option>
<a-select-option
v-if="searchVal && isOptionMissing && !isPublic && !disableOptionCreation && isUIAllowed('fieldEdit')"
:key="searchVal"
:value="searchVal"
>
<div class="flex gap-2 text-gray-500 items-center h-full">
<component :is="iconMap.plusThick" class="min-w-4" />
<div class="text-xs whitespace-normal">
{{ $t('msg.selectOption.createNewOptionNamed') }} <strong>{{ searchVal }}</strong>
</div>
</div>
</a-select-option>
<template #tagRender="{ value: val, onClose }">
<a-tag
v-if="options.find((el) => el.title === val)"
class="rounded-tag nc-selected-option"
:style="{ display: 'flex', alignItems: 'center' }"
:color="options.find((el) => el.title === val)?.color"
:closable="editAllowed && (vModel.length > 1 || !column?.rqd)"
:close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })"
@click="onTagClick($event, onClose)"
@close="onClose"
> >
{{ val }} <span
</span> :style="{
</a-tag> 'color': tinycolor.isReadable(options.find((el) => el.title === val)?.color || '#ccc', '#fff', {
</template> level: 'AA',
</a-select> size: 'large',
})
? '#fff'
: tinycolor
.mostReadable(options.find((el) => el.title === val)?.color || '#ccc', ['#0b1d05', '#fff'])
.toHex8String(),
'font-size': '13px',
}"
:class="{ 'text-sm': isKanban }"
>
{{ val }}
</span>
</a-tag>
</template>
</a-select>
</template>
</div> </div>
</template> </template>

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

@ -187,7 +187,7 @@ watch(editorDom, () => {
'max-w-[calc(100%_-_198px)] flex justify-end rounded-tr-2xl overflow-hidden': fullMode, 'max-w-[calc(100%_-_198px)] flex justify-end rounded-tr-2xl overflow-hidden': fullMode,
}" }"
> >
<div class="nc-scrollbar-x-md"> <div class="nc-longtext-scrollbar">
<CellRichTextSelectedBubbleMenu v-if="editor" :editor="editor" embed-mode /> <CellRichTextSelectedBubbleMenu v-if="editor" :editor="editor" embed-mode />
</div> </div>
</div> </div>

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

@ -3,6 +3,7 @@ import { message } from 'ant-design-vue'
import tinycolor from 'tinycolor2' import tinycolor from 'tinycolor2'
import type { Select as AntSelect } from 'ant-design-vue' import type { Select as AntSelect } from 'ant-design-vue'
import type { SelectOptionType } from 'nocodb-sdk' import type { SelectOptionType } from 'nocodb-sdk'
import type { FormFieldsLimitOptionsType } from '~/lib'
import { import {
ActiveCellInj, ActiveCellInj,
ColumnInj, ColumnInj,
@ -88,7 +89,44 @@ const options = computed<(SelectOptionType & { value: string })[]>(() => {
for (const op of opts.filter((el: any) => el.order === null)) { for (const op of opts.filter((el: any) => el.order === null)) {
op.title = op.title.replace(/^'/, '').replace(/'$/, '') op.title = op.title.replace(/^'/, '').replace(/'$/, '')
} }
return opts.map((o: any) => ({ ...o, value: o.title }))
let order = 1
const limitOptionsById =
((parseProp(column.value.meta)?.limitOptions || []).reduce(
(o: Record<string, FormFieldsLimitOptionsType>, f: FormFieldsLimitOptionsType) => {
if (order < (f?.order ?? 0)) {
order = f.order
}
return {
...o,
[f.id]: f,
}
},
{},
) as Record<string, FormFieldsLimitOptionsType>) ?? {}
if (
!isEditColumn.value &&
isForm.value &&
parseProp(column.value.meta)?.isLimitOption &&
(parseProp(column.value.meta)?.limitOptions || []).length
) {
return opts
.filter((o: SelectOptionType & { value: string }) => {
if (limitOptionsById[o.id]?.show !== undefined) {
return limitOptionsById[o.id]?.show
}
return false
})
.map((o: any) => ({
...o,
value: o.title,
order: o.id && limitOptionsById[o.id] ? limitOptionsById[o.id]?.order : order++,
}))
.sort((a, b) => a.order - b.order)
} else {
return opts.map((o: any) => ({ ...o, value: o.title }))
}
} }
return [] return []
}) })
@ -272,82 +310,70 @@ const onFocus = () => {
<template> <template>
<div <div
class="nc-cell-field h-full w-full flex items-center nc-single-select focus:outline-transparent" class="nc-cell-field h-full w-full flex items-center nc-single-select focus:outline-transparent"
:class="{ 'read-only': readOnly }" :class="{ 'read-only': readOnly, 'max-w-full': isForm }"
@click="toggleMenu" @click="toggleMenu"
@keydown.enter.stop.prevent="toggleMenu" @keydown.enter.stop.prevent="toggleMenu"
> >
<div v-if="!(active || isEditable)" class="w-full"> <div v-if="!isEditColumn && isForm && parseProp(column.meta)?.isList" class="w-full max-w-full">
<a-tag v-if="selectedOpt" class="rounded-tag max-w-full" :color="selectedOpt.color"> <a-radio-group v-model:value="vModel" class="nc-field-layout-list">
<span <a-radio
:style="{ v-for="op of options"
'color': tinycolor.isReadable(selectedOpt.color || '#ccc', '#fff', { level: 'AA', size: 'large' }) :key="op.title"
? '#fff' :value="op.title"
: tinycolor.mostReadable(selectedOpt.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(), :data-testid="`select-option-${column.title}-${rowIndex}`"
'font-size': '13px', :class="`nc-select-option-${column.title}-${op.title}`"
}"
:class="{ 'text-sm': isKanban }"
> >
<NcTooltip class="truncate max-w-full" show-on-truncate-only> <a-tag class="rounded-tag max-w-full" :color="op.color">
<template #title>
{{ selectedOpt.title }}
</template>
<span <span
class="text-ellipsis overflow-hidden"
:style="{ :style="{
wordBreak: 'keep-all', 'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
whiteSpace: 'nowrap', ? '#fff'
display: 'inline', : tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px',
}" }"
> >
{{ selectedOpt.title }} <NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title>
{{ op.title }}
</template>
<span
class="text-ellipsis overflow-hidden"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ op.title }}
</span>
</NcTooltip>
</span> </span>
</NcTooltip> </a-tag></a-radio
</span> >
</a-tag> </a-radio-group>
</div> <div
v-if="vModel"
<NcSelect class="inline-block px-2 pt-2 cursor-pointer text-xs text-gray-500 hover:text-gray-800"
v-else @click="vModel = ''"
ref="aselect"
v-model:value="vModel"
class="w-full overflow-hidden xs:min-h-12"
:class="{ 'caret-transparent': !hasEditRoles }"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
:allow-clear="!column.rqd && editAllowed"
:bordered="false"
:open="isOpen && editAllowed"
:disabled="readOnly || !editAllowed"
:show-search="!isMobileMode && isOpen && active"
:show-arrow="hasEditRoles && !readOnly && active && (vModel === null || vModel === undefined)"
:dropdown-class-name="`nc-dropdown-single-select-cell !min-w-200px ${isOpen && active ? 'active' : ''}`"
:dropdown-match-select-width="true"
@select="onSelect"
@keydown="onKeydown($event)"
@search="search"
@blur="isOpen = false"
@focus="onFocus"
>
<a-select-option
v-for="op of options"
:key="op.title"
:value="op.title"
:data-testid="`select-option-${column.title}-${rowIndex}`"
:class="`nc-select-option-${column.title}-${op.title}`"
@click.stop
> >
<a-tag class="rounded-tag max-w-full" :color="op.color"> {{ $t('labels.clearSelection') }}
</div>
</div>
<template v-else>
<div v-if="!(active || isEditable)" class="w-full">
<a-tag v-if="selectedOpt" class="rounded-tag max-w-full" :color="selectedOpt.color">
<span <span
:style="{ :style="{
'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' }) 'color': tinycolor.isReadable(selectedOpt.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
? '#fff' ? '#fff'
: tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(), : tinycolor.mostReadable(selectedOpt.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px', 'font-size': '13px',
}" }"
:class="{ 'text-sm': isKanban }" :class="{ 'text-sm': isKanban }"
> >
<NcTooltip class="truncate max-w-full" show-on-truncate-only> <NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title> <template #title>
{{ op.title }} {{ selectedOpt.title }}
</template> </template>
<span <span
class="text-ellipsis overflow-hidden" class="text-ellipsis overflow-hidden"
@ -357,21 +383,80 @@ const onFocus = () => {
display: 'inline', display: 'inline',
}" }"
> >
{{ op.title }} {{ selectedOpt.title }}
</span> </span>
</NcTooltip> </NcTooltip>
</span> </span>
</a-tag> </a-tag>
</a-select-option> </div>
<a-select-option v-if="searchVal && isOptionMissing && isNewOptionCreateEnabled" :key="searchVal" :value="searchVal">
<div class="flex gap-2 text-gray-500 items-center h-full"> <NcSelect
<component :is="iconMap.plusThick" class="min-w-4" /> v-else
<div class="text-xs whitespace-normal"> ref="aselect"
{{ $t('msg.selectOption.createNewOptionNamed') }} <strong>{{ searchVal }}</strong> v-model:value="vModel"
class="w-full overflow-hidden xs:min-h-12"
:class="{ 'caret-transparent': !hasEditRoles }"
:placeholder="isEditColumn ? $t('labels.optional') : ''"
:allow-clear="!column.rqd && editAllowed"
:bordered="false"
:open="isOpen && editAllowed"
:disabled="readOnly || !editAllowed"
:show-search="!isMobileMode && isOpen && active"
:show-arrow="hasEditRoles && !readOnly && active && (vModel === null || vModel === undefined)"
:dropdown-class-name="`nc-dropdown-single-select-cell !min-w-200px ${isOpen && active ? 'active' : ''}`"
:dropdown-match-select-width="true"
@select="onSelect"
@keydown="onKeydown($event)"
@search="search"
@blur="isOpen = false"
@focus="onFocus"
>
<a-select-option
v-for="op of options"
:key="op.title"
:value="op.title"
:data-testid="`select-option-${column.title}-${rowIndex}`"
:class="`nc-select-option-${column.title}-${op.title}`"
@click.stop
>
<a-tag class="rounded-tag max-w-full" :color="op.color">
<span
:style="{
'color': tinycolor.isReadable(op.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
? '#fff'
: tinycolor.mostReadable(op.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px',
}"
:class="{ 'text-sm': isKanban }"
>
<NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title>
{{ op.title }}
</template>
<span
class="text-ellipsis overflow-hidden"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ op.title }}
</span>
</NcTooltip>
</span>
</a-tag>
</a-select-option>
<a-select-option v-if="searchVal && isOptionMissing && isNewOptionCreateEnabled" :key="searchVal" :value="searchVal">
<div class="flex gap-2 text-gray-500 items-center h-full">
<component :is="iconMap.plusThick" class="min-w-4" />
<div class="text-xs whitespace-normal">
{{ $t('msg.selectOption.createNewOptionNamed') }} <strong>{{ searchVal }}</strong>
</div>
</div> </div>
</div> </a-select-option>
</a-select-option> </NcSelect>
</NcSelect> </template>
</div> </div>
</template> </template>

17
packages/nc-gui/components/cell/TextArea.vue

@ -173,7 +173,7 @@ const dragStart = (e: MouseEvent) => {
} }
watch(editEnabled, () => { watch(editEnabled, () => {
if (editEnabled.value) { if (editEnabled.value && isRichMode.value) {
isVisible.value = true isVisible.value = true
} }
}) })
@ -227,7 +227,7 @@ watch(inputWrapperRef, () => {
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
:rows="isForm ? 5 : 4" :rows="isForm ? 5 : 4"
class="h-full w-full outline-none border-none nc-scrollbar-lg" class="h-full w-full outline-none border-none nc-longtext-scrollbar"
:class="{ :class="{
'p-2': editEnabled, 'p-2': editEnabled,
'py-1 h-full': isForm, 'py-1 h-full': isForm,
@ -270,8 +270,8 @@ watch(inputWrapperRef, () => {
<NcTooltip <NcTooltip
v-if="!isVisible" v-if="!isVisible"
placement="bottom" placement="bottom"
class="!absolute right-1 hidden nc-text-area-expand-btn group-hover:block z-3" class="!absolute top-1 hidden nc-text-area-expand-btn group-hover:block z-3"
:class="isExpandedFormOpen || isForm ? 'top-1' : 'bottom-1'" :class="isForm ? 'right-1' : 'right-0'"
> >
<template #title>{{ $t('title.expand') }}</template> <template #title>{{ $t('title.expand') }}</template>
<NcButton type="secondary" size="xsmall" data-testid="attachment-cell-file-picker-button" @click.stop="onExpand"> <NcButton type="secondary" size="xsmall" data-testid="attachment-cell-file-picker-button" @click.stop="onExpand">
@ -318,7 +318,7 @@ watch(inputWrapperRef, () => {
<a-textarea <a-textarea
ref="inputRef" ref="inputRef"
v-model:value="vModel" v-model:value="vModel"
class="nc-text-area-expanded !py-1 !px-3 !text-black !cursor-text !min-h-[210px] !rounded-lg focus:border-brand-500 disabled:!bg-gray-50" class="nc-text-area-expanded !py-1 !px-3 !text-black !cursor-text !min-h-[210px] !rounded-lg focus:border-brand-500 disabled:!bg-gray-50 nc-longtext-scrollbar"
:placeholder="$t('activity.enterText')" :placeholder="$t('activity.enterText')"
:style="{ resize: 'both' }" :style="{ resize: 'both' }"
:disabled="readOnly" :disabled="readOnly"
@ -347,6 +347,9 @@ textarea:focus {
@apply rounded-lg; @apply rounded-lg;
} }
} }
.nc-longtext-scrollbar {
@apply scrollbar-thin scrollbar-thumb-gray-200 hover:scrollbar-thumb-gray-300 scrollbar-track-transparent;
}
</style> </style>
<style lang="scss"> <style lang="scss">
@ -367,6 +370,10 @@ textarea:focus {
max-width: min(1280px, 100vw - 100px); max-width: min(1280px, 100vw - 100px);
max-height: min(864px, 100vh - 100px); max-height: min(864px, 100vh - 100px);
.nc-longtext-scrollbar {
@apply scrollbar-thin scrollbar-thumb-gray-200 hover:scrollbar-thumb-gray-300 scrollbar-track-transparent;
}
} }
} }
} }

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

@ -77,7 +77,7 @@ const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))!
const isForm = inject(IsFormInj)! const isForm = inject(IsFormInj)!
const focus: VNodeRef = (el) => const focus: VNodeRef = (el) =>
!isExpandedFormOpen.value && !isEditColumn.value && isForm.value && (el as HTMLInputElement)?.focus() !isExpandedFormOpen.value && !isEditColumn.value && !isForm.value && (el as HTMLInputElement)?.focus()
watch( watch(
() => editEnabled.value, () => editEnabled.value,

373
packages/nc-gui/components/cell/User.vue

@ -1,8 +1,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import { onUnmounted } from '@vue/runtime-core' import { onUnmounted } from '@vue/runtime-core'
import tinycolor from 'tinycolor2' import tinycolor from 'tinycolor2'
import { Checkbox, CheckboxGroup, Radio, RadioGroup } from 'ant-design-vue'
import type { Select as AntSelect } from 'ant-design-vue' import type { Select as AntSelect } from 'ant-design-vue'
import type { UserFieldRecordType } from 'nocodb-sdk' import type { UserFieldRecordType } from 'nocodb-sdk'
import type { FormFieldsLimitOptionsType } from '~/lib'
import { import {
ActiveCellInj, ActiveCellInj,
CellClickHookInj, CellClickHookInj,
@ -77,16 +79,59 @@ const searchVal = ref<string | null>()
const { isUIAllowed } = useRoles() const { isUIAllowed } = useRoles()
const options = computed<UserFieldRecordType[]>(() => { const options = computed<UserFieldRecordType[]>(() => {
let order = 1
const limitOptionsById =
((parseProp(column.value.meta)?.limitOptions || []).reduce(
(o: Record<string, FormFieldsLimitOptionsType>, f: FormFieldsLimitOptionsType) => {
if (order < (f?.order ?? 0)) {
order = f.order
}
return {
...o,
[f.id]: f,
}
},
{},
) as Record<string, FormFieldsLimitOptionsType>) ?? {}
const collaborators: UserFieldRecordType[] = [] const collaborators: UserFieldRecordType[] = []
collaborators.push( if (
...(baseUsers.value?.map((user: any) => ({ !isEditColumn.value &&
id: user.id, isForm.value &&
email: user.email, parseProp(column.value.meta)?.isLimitOption &&
display_name: user.display_name, (parseProp(column.value.meta)?.limitOptions || []).length
deleted: user.deleted, ) {
})) || []), collaborators.push(
) ...(baseUsers.value || [])
.filter((user) => {
if (limitOptionsById[user.id]?.show !== undefined) {
return limitOptionsById[user.id]?.show
}
return false
})
.map((user: any) => ({
id: user.id,
email: user.email,
display_name: user.display_name,
deleted: user.deleted,
order: user.id && limitOptionsById[user.id] ? limitOptionsById[user.id]?.order ?? user.order : order++,
}))
.sort((a, b) => a.order - b.order),
)
} else {
collaborators.push(
...(baseUsers.value || [])
.map((user: any) => ({
id: user.id,
email: user.email,
display_name: user.display_name,
deleted: user.deleted,
order: order++,
}))
.sort((a, b) => a.order - b.order),
)
}
return collaborators return collaborators
}) })
@ -146,6 +191,14 @@ const vModel = computed({
}, },
}) })
const vModelListLayout = computed(() => {
if (isMultiple.value) {
return (vModel.value || []).map((item) => item.value)
} else {
return (vModel.value || [])?.[0]?.value || ''
}
})
watch(isOpen, (n, _o) => { watch(isOpen, (n, _o) => {
if (!n) searchVal.value = '' if (!n) searchVal.value = ''
@ -266,87 +319,85 @@ const filterOption = (input: string, option: any) => {
:class="{ 'read-only': readOnly }" :class="{ 'read-only': readOnly }"
@click="toggleMenu" @click="toggleMenu"
> >
<div <div v-if="!isEditColumn && isForm && parseProp(column.meta)?.isList" class="w-full max-w-full">
v-if="!active" <component
class="flex flex-wrap" :is="isMultiple ? CheckboxGroup : RadioGroup"
:style="{ v-model:value="vModelListLayout"
'display': '-webkit-box', class="nc-field-layout-list"
'max-width': '100%', @update:value="
'-webkit-line-clamp': rowHeight || 1, (value) => {
'-webkit-box-orient': 'vertical', vModel = isMultiple ? value : [value]
'overflow': 'hidden', }
}" "
> >
<template v-for="selectedOpt of vModel" :key="selectedOpt.value"> <template v-for="op of options" :key="op.id || op.email">
<a-tag class="rounded-tag max-w-full !pl-0" color="'#ccc'"> <component
<span :is="isMultiple ? Checkbox : Radio"
:style="{ v-if="!op.deleted"
'color': tinycolor.isReadable('#ccc' || '#ccc', '#fff', { level: 'AA', size: 'large' }) :key="op.id || op.email"
? '#fff' :value="op.id"
: tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(), :data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
'font-size': '13px', :class="`nc-select-option-${column.title}-${op.email}`"
}"
class="flex items-stretch gap-2"
:class="{ 'text-sm': isKanban }"
> >
<div class="flex-none"> <a-tag class="rounded-tag max-w-full !pl-0" color="'#ccc'">
<GeneralUserIcon
size="auto"
:name="!selectedOpt.label?.includes('@') ? selectedOpt.label.trim() : ''"
:email="selectedOpt.label"
class="!text-[0.65rem]"
/>
</div>
<NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title>
{{ selectedOpt.label }}
</template>
<span <span
class="text-ellipsis overflow-hidden"
:style="{ :style="{
wordBreak: 'keep-all', 'color': tinycolor.isReadable('#ccc' || '#ccc', '#fff', { level: 'AA', size: 'large' })
whiteSpace: 'nowrap', ? '#fff'
display: 'inline', : tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px',
}" }"
class="flex items-stretch gap-2"
> >
{{ selectedOpt.label }} <div>
<GeneralUserIcon
size="auto"
:name="op.display_name?.trim() ? op.display_name?.trim() : ''"
:email="op.email"
class="!text-[0.65rem]"
/>
</div>
<NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title>
{{ op.display_name?.trim() || op.email }}
</template>
<span
class="text-ellipsis overflow-hidden"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ op.display_name?.trim() || op.email }}
</span>
</NcTooltip>
</span> </span>
</NcTooltip> </a-tag>
</span> </component>
</a-tag> </template>
</template> </component>
<div
v-if="!isMultiple && vModel.length"
class="inline-block px-2 pt-2 cursor-pointer text-xs text-gray-500 hover:text-gray-800"
@click="vModel = []"
>
{{ $t('labels.clearSelection') }}
</div>
</div> </div>
<template v-else>
<a-select <div
v-else v-if="!active"
ref="aselect" class="flex flex-wrap"
v-model:value="vModel" :style="{
mode="multiple" 'display': '-webkit-box',
class="w-full overflow-hidden" 'max-width': '100%',
:placeholder="isEditColumn ? $t('labels.optional') : ''" '-webkit-line-clamp': rowHeight || 1,
:bordered="false" '-webkit-box-orient': 'vertical',
clear-icon 'overflow': 'hidden',
:show-search="!isMobileMode" }"
:show-arrow="editAllowed && !readOnly" >
:open="isOpen && editAllowed" <template v-for="selectedOpt of vModel" :key="selectedOpt.value">
:disabled="readOnly || !editAllowed"
:class="{ 'caret-transparent': !hasEditRoles }"
:dropdown-class-name="`nc-dropdown-user-select-cell !min-w-200px ${isOpen ? 'active' : ''}`"
:filter-option="filterOption"
@search="search"
@keydown.stop
>
<template #suffixIcon>
<GeneralIcon icon="arrowDown" class="text-gray-700 nc-select-expand-btn" />
</template>
<template v-for="op of options" :key="op.id || op.email">
<a-select-option
v-if="!op.deleted"
:value="op.id"
:data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
:class="`nc-select-option-${column.title}-${op.email}`"
@click.stop
>
<a-tag class="rounded-tag max-w-full !pl-0" color="'#ccc'"> <a-tag class="rounded-tag max-w-full !pl-0" color="'#ccc'">
<span <span
:style="{ :style="{
@ -358,17 +409,17 @@ const filterOption = (input: string, option: any) => {
class="flex items-stretch gap-2" class="flex items-stretch gap-2"
:class="{ 'text-sm': isKanban }" :class="{ 'text-sm': isKanban }"
> >
<div> <div class="flex-none">
<GeneralUserIcon <GeneralUserIcon
size="auto" size="auto"
:name="op.display_name?.trim() ? op.display_name?.trim() : ''" :name="!selectedOpt.label?.includes('@') ? selectedOpt.label.trim() : ''"
:email="op.email" :email="selectedOpt.label"
class="!text-[0.65rem]" class="!text-[0.65rem]"
/> />
</div> </div>
<NcTooltip class="truncate max-w-full" show-on-truncate-only> <NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title> <template #title>
{{ op.display_name?.trim() || op.email }} {{ selectedOpt.label }}
</template> </template>
<span <span
class="text-ellipsis overflow-hidden" class="text-ellipsis overflow-hidden"
@ -378,51 +429,121 @@ const filterOption = (input: string, option: any) => {
display: 'inline', display: 'inline',
}" }"
> >
{{ op.display_name?.trim() || op.email }} {{ selectedOpt.label }}
</span> </span>
</NcTooltip> </NcTooltip>
</span> </span>
</a-tag> </a-tag>
</a-select-option> </template>
</template> </div>
<template #tagRender="{ label, value: val, onClose }"> <a-select
<a-tag v-else
v-if="options.find((el) => el.id === val)" ref="aselect"
class="rounded-tag nc-selected-option !pl-0" v-model:value="vModel"
:style="{ display: 'flex', alignItems: 'center' }" mode="multiple"
color="'#ccc'" class="w-full overflow-hidden"
:closable="editAllowed && ((vModel?.length ?? 0) > 1 || !column?.rqd)" :placeholder="isEditColumn ? $t('labels.optional') : ''"
:close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })" :bordered="false"
@click="onTagClick($event, onClose)" clear-icon
@close="onClose" :show-search="!isMobileMode"
> :show-arrow="editAllowed && !readOnly"
<span :open="isOpen && editAllowed"
:style="{ :disabled="readOnly || !editAllowed"
'color': tinycolor.isReadable('#ccc' || '#ccc', '#fff', { :class="{ 'caret-transparent': !hasEditRoles }"
level: 'AA', :dropdown-class-name="`nc-dropdown-user-select-cell !min-w-200px ${isOpen ? 'active' : ''}`"
size: 'large', :filter-option="filterOption"
}) @search="search"
? '#fff' @keydown.stop
: tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(), >
'font-size': '13px', <template #suffixIcon>
}" <GeneralIcon icon="arrowDown" class="text-gray-700 nc-select-expand-btn" />
class="flex items-stretch gap-2" </template>
:class="{ 'text-sm': isKanban }" <template v-for="op of options" :key="op.id || op.email">
<a-select-option
v-if="!op.deleted"
:value="op.id"
:data-testid="`select-option-${column.title}-${location === 'filter' ? 'filter' : rowIndex}`"
:class="`nc-select-option-${column.title}-${op.email}`"
@click.stop
>
<a-tag class="rounded-tag max-w-full !pl-0" color="'#ccc'">
<span
:style="{
'color': tinycolor.isReadable('#ccc' || '#ccc', '#fff', { level: 'AA', size: 'large' })
? '#fff'
: tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px',
}"
class="flex items-stretch gap-2"
:class="{ 'text-sm': isKanban }"
>
<div>
<GeneralUserIcon
size="auto"
:name="op.display_name?.trim() ? op.display_name?.trim() : ''"
:email="op.email"
class="!text-[0.65rem]"
/>
</div>
<NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title>
{{ op.display_name?.trim() || op.email }}
</template>
<span
class="text-ellipsis overflow-hidden"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ op.display_name?.trim() || op.email }}
</span>
</NcTooltip>
</span>
</a-tag>
</a-select-option>
</template>
<template #tagRender="{ label, value: val, onClose }">
<a-tag
v-if="options.find((el) => el.id === val)"
class="rounded-tag nc-selected-option !pl-0"
:style="{ display: 'flex', alignItems: 'center' }"
color="'#ccc'"
:closable="editAllowed && ((vModel?.length ?? 0) > 1 || !column?.rqd)"
:close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })"
@click="onTagClick($event, onClose)"
@close="onClose"
> >
<div> <span
<GeneralUserIcon :style="{
size="auto" 'color': tinycolor.isReadable('#ccc' || '#ccc', '#fff', {
:name="!label?.includes('@') ? label.trim() : ''" level: 'AA',
:email="label" size: 'large',
class="!text-[0.65rem]" })
/> ? '#fff'
</div> : tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
{{ label }} 'font-size': '13px',
</span> }"
</a-tag> class="flex items-stretch gap-2"
</template> :class="{ 'text-sm': isKanban }"
</a-select> >
<div>
<GeneralUserIcon
size="auto"
:name="!label?.includes('@') ? label.trim() : ''"
:email="label"
class="!text-[0.65rem]"
/>
</div>
{{ label }}
</span>
</a-tag>
</template>
</a-select>
</template>
</div> </div>
</template> </template>

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

@ -1,6 +1,7 @@
import type { AttachmentReqType, AttachmentType } from 'nocodb-sdk' import type { AttachmentReqType, AttachmentType } from 'nocodb-sdk'
import { populateUniqueFileName } from 'nocodb-sdk' import { populateUniqueFileName } from 'nocodb-sdk'
import DOMPurify from 'isomorphic-dompurify' import DOMPurify from 'isomorphic-dompurify'
import { saveAs } from 'file-saver'
import RenameFile from './RenameFile.vue' import RenameFile from './RenameFile.vue'
import { import {
ColumnInj, ColumnInj,
@ -317,7 +318,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
async function downloadFile(item: AttachmentType) { async function downloadFile(item: AttachmentType) {
const src = await getAttachmentSrc(item) const src = await getAttachmentSrc(item)
if (src) { if (src) {
;(await import('file-saver')).saveAs(src, item.title) saveAs(src, item.title)
} else { } else {
message.error('Failed to download file') message.error('Failed to download file')
} }

18
packages/nc-gui/components/dlg/TableDuplicate.vue

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import type { TableType } from 'nocodb-sdk' import { type LinkToAnotherRecordType, type TableType, UITypes } from 'nocodb-sdk'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { useVModel } from '#imports' import { useVModel } from '#imports'
import type { TabType } from '#imports' import type { TabType } from '#imports'
@ -31,6 +31,8 @@ const { loadTables } = baseStore
const { tables } = storeToRefs(baseStore) const { tables } = storeToRefs(baseStore)
const { getMeta } = useMetas()
const { t } = useI18n() const { t } = useI18n()
const { activeTable: _activeTable } = storeToRefs(useTablesStore()) const { activeTable: _activeTable } = storeToRefs(useTablesStore())
@ -74,6 +76,20 @@ const _duplicate = async () => {
}) => { }) => {
if (data.status !== 'close') { if (data.status !== 'close') {
if (data.status === JobStatus.COMPLETED) { if (data.status === JobStatus.COMPLETED) {
const sourceTable = await getMeta(props.table.id!)
if (sourceTable) {
for (const col of sourceTable.columns || []) {
if ([UITypes.Links, UITypes.LinkToAnotherRecord].includes(col.uidt as UITypes)) {
if (col && col.colOptions) {
const relatedTableId = (col.colOptions as LinkToAnotherRecordType)?.fk_related_model_id
if (relatedTableId) {
await getMeta(relatedTableId, true)
}
}
}
}
}
await loadTables() await loadTables()
refreshCommandPalette() refreshCommandPalette()
const newTable = tables.value.find((el) => el.id === data?.data?.result?.id) const newTable = tables.value.find((el) => el.id === data?.data?.result?.id)

2
packages/nc-gui/components/dlg/ViewCreate.vue

@ -376,7 +376,7 @@ onMounted(async () => {
<a <a
v-if="!form.copy_from_id" v-if="!form.copy_from_id"
class="text-sm !text-gray-600 !hover:text-gray-600" class="text-sm !text-gray-600 !hover:text-gray-600"
href="https://docs.nocodb.com/views/view-types/calendar/" :href="`https://docs.nocodb.com/views/view-types/${typeAlias}`"
target="_blank" target="_blank"
> >
Go to Docs Go to Docs

17
packages/nc-gui/components/general/FormBanner.vue

@ -3,19 +3,22 @@ interface Props {
bannerImageUrl?: string | null bannerImageUrl?: string | null
} }
const { bannerImageUrl } = defineProps<Props>() const { bannerImageUrl } = defineProps<Props>()
const { getPossibleAttachmentSrc } = useAttachment()
</script> </script>
<template> <template>
<div <div
class="w-full max-w-screen-xl mx-auto bg-white border-1 border-gray-200 rounded-3xl overflow-hidden" class="nc-form-banner-wrapper w-full mx-auto bg-white border-1 border-gray-200 rounded-2xl overflow-hidden"
:style=" :style="{ aspectRatio: 4 / 1 }"
bannerImageUrl
? { 'background-image': `url(${bannerImageUrl})`, 'background-size': 'cover', 'background-position': 'center' }
: {}
"
> >
<LazyCellAttachmentImage
v-if="bannerImageUrl"
:srcs="getPossibleAttachmentSrc(parseProp(bannerImageUrl))"
class="nc-form-banner-image object-cover w-full"
/>
<!-- Todo: aspect ratio and cover image uploader and image cropper to crop image in fixed aspect ratio --> <!-- Todo: aspect ratio and cover image uploader and image cropper to crop image in fixed aspect ratio -->
<div v-if="!bannerImageUrl" class="h-full flex items-stretch justify-between"> <div v-else class="h-full flex items-stretch justify-between">
<div class="flex"> <div class="flex">
<img src="~assets/img/form-banner-left.png" alt="form-banner-left'" /> <img src="~assets/img/form-banner-left.png" alt="form-banner-left'" />
</div> </div>

141
packages/nc-gui/components/general/ImageCropper.vue

@ -0,0 +1,141 @@
<script lang="ts" setup>
import { Cropper } from 'vue-advanced-cropper'
import 'vue-advanced-cropper/dist/style.css'
import 'vue-advanced-cropper/dist/theme.classic.css'
import type { AttachmentReqType } from 'nocodb-sdk'
import { extractSdkResponseErrorMsg, useApi } from '#imports'
interface Props {
imageConfig: {
src: string
type: string
name: string
}
cropperConfig: {
aspectRatio?: number
}
uploadConfig?: {
path?: string
}
showCropper: boolean
}
const { imageConfig, cropperConfig, uploadConfig, ...props } = defineProps<Props>()
const emit = defineEmits(['update:showCropper', 'submit'])
const showCropper = useVModel(props, 'showCropper', emit)
const { api, isLoading } = useApi()
const cropperRef = ref()
const previewImage = ref({
canvas: {},
src: '',
})
const handleCropImage = () => {
const { canvas } = cropperRef.value.getResult()
previewImage.value = {
canvas,
src: canvas.toDataURL(),
}
}
const handleUploadImage = async (fileToUpload: AttachmentReqType[]) => {
if (uploadConfig?.path) {
try {
const uploadResult = await api.storage.uploadByUrl(
{
path: uploadConfig?.path as string,
},
fileToUpload,
)
if (uploadResult?.[0]) {
emit('submit', {
...uploadResult[0],
})
} else {
emit('submit', fileToUpload[0])
}
} catch (error: any) {
console.error(error)
message.error(await extractSdkResponseErrorMsg(error))
}
} else {
emit('submit', fileToUpload[0])
}
showCropper.value = false
}
const handleSaveImage = async () => {
if (previewImage.value.canvas) {
;(previewImage.value.canvas as any).toBlob(async (blob: Blob) => {
await handleUploadImage([
{
title: imageConfig.name,
fileName: imageConfig.name,
mimetype: imageConfig.type,
size: blob.size,
url: previewImage.value.src,
},
])
}, imageConfig.type)
}
}
watch(showCropper, () => {
if (!showCropper.value) {
previewImage.value = {
canvas: {},
src: '',
}
}
})
</script>
<template>
<NcModal v-model:visible="showCropper" :mask-closable="false">
<div class="nc-image-cropper-wrapper relative">
<Cropper
ref="cropperRef"
class="nc-cropper relative"
:src="imageConfig.src"
:auto-zoom="true"
:stencil-props="cropperConfig?.aspectRatio ? { aspectRatio: cropperConfig.aspectRatio } : {}"
/>
<div v-if="previewImage.src" class="result_preview">
<img :src="previewImage.src" alt="Preview Image" />
</div>
</div>
<div class="flex justify-between items-center space-x-4 mt-4">
<div class="flex items-center space-x-4">
<NcButton type="secondary" size="small" :disabled="isLoading" @click="showCropper = false"> Cancel </NcButton>
</div>
<div class="flex items-center space-x-4">
<NcButton type="secondary" size="small" :disabled="isLoading" @click="handleCropImage">
<GeneralIcon icon="crop"></GeneralIcon>
<span class="ml-2">Crop</span>
</NcButton>
<NcButton size="small" :loading="isLoading" :disabled="!previewImage.src" @click="handleSaveImage"> Save </NcButton>
</div>
</div>
</NcModal>
</template>
<style lang="scss" scoped>
.nc-cropper {
min-height: 400px;
max-height: 400px;
}
.nc-image-cropper-wrapper {
.result_preview {
@apply absolute right-4 bottom-4 border-1 border-dashed border-white/50 w-28 h-28 opacity-90 pointer-events-none;
img {
@apply w-full h-full object-contain;
}
}
}
</style>

2
packages/nc-gui/components/nc/DateWeekSelector.vue

@ -180,7 +180,7 @@ const paginate = (action: 'next' | 'prev') => {
'text-gray-400': !isDateInCurrentMonth(date), 'text-gray-400': !isDateInCurrentMonth(date),
'nc-selected-week-start': isSameDate(date, selectedWeek?.start), 'nc-selected-week-start': isSameDate(date, selectedWeek?.start),
'nc-selected-week-end': isSameDate(date, selectedWeek?.end), 'nc-selected-week-end': isSameDate(date, selectedWeek?.end),
'rounded-md bg-brand-50 text-brand-500': isSameDate(date, dayjs()) && isDateInCurrentMonth(date), 'rounded-md bg-brand-50 nc-calendar-today text-brand-500': isSameDate(date, dayjs()) && isDateInCurrentMonth(date),
}" }"
class="h-9 w-9 px-1 py-2 relative font-medium flex items-center cursor-pointer justify-center" class="h-9 w-9 px-1 py-2 relative font-medium flex items-center cursor-pointer justify-center"
data-testid="nc-calendar-date" data-testid="nc-calendar-date"

2
packages/nc-gui/components/nc/Select.vue

@ -82,7 +82,7 @@ const onChange = (value: string) => {
height: fit-content; height: fit-content;
.ant-select-selector { .ant-select-selector {
box-shadow: 0px 5px 3px -2px rgba(0, 0, 0, 0.02), 0px 3px 1px -2px rgba(0, 0, 0, 0.06); box-shadow: 0px 5px 3px -2px rgba(0, 0, 0, 0.02), 0px 3px 1px -2px rgba(0, 0, 0, 0.06);
@apply border-1 border-gray-200 !rounded-lg; @apply border-1 border-gray-200 rounded-lg;
} }
.ant-select-selection-item { .ant-select-selection-item {

429
packages/nc-gui/components/smartsheet/Form.vue

@ -1,10 +1,18 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core'
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
import tinycolor from 'tinycolor2' import tinycolor from 'tinycolor2'
import { Pane, Splitpanes } from 'splitpanes' import { Pane, Splitpanes } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css' import 'splitpanes/dist/splitpanes.css'
import { RelationTypes, UITypes, ViewTypes, getSystemColumns, isLinksOrLTAR, isVirtualCol } from 'nocodb-sdk' import {
ProjectRoles,
RelationTypes,
UITypes,
ViewTypes,
getSystemColumns,
isLinksOrLTAR,
isSelectTypeCol,
isVirtualCol,
} from 'nocodb-sdk'
import type { Permission } from '#imports' import type { Permission } from '#imports'
import { import {
ActiveViewInj, ActiveViewInj,
@ -26,6 +34,7 @@ import {
ref, ref,
useDebounceFn, useDebounceFn,
useEventListener, useEventListener,
useFileDialog,
useGlobal, useGlobal,
useI18n, useI18n,
useNuxtApp, useNuxtApp,
@ -62,6 +71,10 @@ const { $api, $e } = useNuxtApp()
const { isUIAllowed } = useRoles() const { isUIAllowed } = useRoles()
const { base } = storeToRefs(useBase())
const { getPossibleAttachmentSrc } = useAttachment()
let formState = reactive<Record<string, any>>({}) let formState = reactive<Record<string, any>>({})
const secondsRemain = ref(0) const secondsRemain = ref(0)
@ -85,7 +98,7 @@ reloadEventHook.on(async () => {
setFormData() setFormData()
}) })
const { fields, showAll, hideAll, saveOrUpdate } = useViewColumnsOrThrow() const { fields, showAll, hideAll } = useViewColumnsOrThrow()
const { state, row } = useProvideSmartsheetRowStore( const { state, row } = useProvideSmartsheetRowStore(
meta, meta,
@ -118,9 +131,35 @@ const isTabPressed = ref(false)
const isLoadingFormView = ref(false) const isLoadingFormView = ref(false)
const focusLabel: VNodeRef = (el) => { const showCropper = ref(false)
return (el as HTMLInputElement)?.focus()
} const imageCropperData = ref<{
imageConfig: {
src: string
type: string
name: string
}
cropperConfig: {
aspectRatio?: number
}
uploadConfig?: {
path?: string
}
cropFor: 'banner' | 'logo'
}>({
imageConfig: {
src: '',
type: '',
name: '',
},
cropperConfig: {},
uploadConfig: {
path: '',
},
cropFor: 'banner',
})
const focusLabel = ref<HTMLTextAreaElement>()
const searchQuery = ref('') const searchQuery = ref('')
@ -128,6 +167,12 @@ const { t } = useI18n()
const { betaFeatureToggleState } = useBetaFeatureToggle() const { betaFeatureToggleState } = useBetaFeatureToggle()
const { open, onChange: onChangeFile } = useFileDialog({
accept: 'image/*',
multiple: false,
reset: true,
})
const visibleColumns = computed(() => localColumns.value.filter((f) => f.show).sort((a, b) => a.order - b.order)) const visibleColumns = computed(() => localColumns.value.filter((f) => f.show).sort((a, b) => a.order - b.order))
const updateView = useDebounceFn( const updateView = useDebounceFn(
@ -139,6 +184,8 @@ const updateView = useDebounceFn(
) )
async function submitForm() { async function submitForm() {
if (isLocked.value || !isUIAllowed('dataInsert')) return
try { try {
await formRef.value?.validateFields() await formRef.value?.validateFields()
} catch (e: any) { } catch (e: any) {
@ -158,6 +205,8 @@ async function submitForm() {
} }
async function clearForm() { async function clearForm() {
if (isLocked.value || !isUIAllowed('dataInsert')) return
formState = reactive<Record<string, any>>({}) formState = reactive<Record<string, any>>({})
state.value = {} state.value = {}
await formRef.value.clearValidate() await formRef.value.clearValidate()
@ -205,14 +254,15 @@ function onMoveCallback(event: any) {
} }
} }
// Todo: reorder visible form fields async function onMove(event: any, isVisibleFormFields = false) {
function onMove(event: any, isVisibleFormFields = false) { if (isLocked.value || !isEditable) return
const { oldIndex } = event.moved const { oldIndex } = event.moved
let { newIndex, element } = event.moved let { newIndex, element } = event.moved
const fieldIndex = fields.value?.findIndex((f) => f?.fk_column_id === element.fk_column_id) const fieldIndex = fields.value?.findIndex((f) => f?.fk_column_id === element.fk_column_id)
if (fieldIndex === -1 || fieldIndex === undefined) return if (fieldIndex === -1 || fieldIndex === undefined || !fields.value?.[fieldIndex]) return
if (isVisibleFormFields) { if (isVisibleFormFields) {
element = localColumns.value[localColumns.value?.findIndex((c) => c.fk_column_id === element.fk_column_id)] element = localColumns.value[localColumns.value?.findIndex((c) => c.fk_column_id === element.fk_column_id)]
@ -233,28 +283,38 @@ function onMove(event: any, isVisibleFormFields = false) {
element.order = ((localColumns.value[newIndex - 1]?.order || 0) + (localColumns.value[newIndex + 1].order || 0)) / 2 element.order = ((localColumns.value[newIndex - 1]?.order || 0) + (localColumns.value[newIndex + 1].order || 0)) / 2
} }
saveOrUpdate(element, fieldIndex) await $api.dbView.formColumnUpdate(element.id, element)
fields.value[fieldIndex] = element as any
// saveOrUpdate(element, fieldIndex)
$e('a:form-view:reorder') $e('a:form-view:reorder')
} }
async function showOrHideColumn(column: Record<string, any>, show: boolean, isSidePannel = false) { async function showOrHideColumn(column: Record<string, any>, show: boolean, isSidePannel = false) {
if (isLocked.value || !isEditable) return
if (shouldSkipColumn(column)) { if (shouldSkipColumn(column)) {
// Required field can't be moved // Required field can't be moved
!isSidePannel && message.info(t('msg.info.requriedFieldsCantBeMoved')) !isSidePannel && message.info(t('msg.info.requriedFieldsCantBeMoved'))
return return
} }
const fieldIndex = fields.value?.findIndex((f) => f?.fk_column_id === column.fk_column_id) const fieldIndex = fields.value?.findIndex((f) => f?.fk_column_id === column.fk_column_id)
if (fieldIndex !== -1 && fieldIndex !== undefined) { if (fieldIndex !== -1 && fieldIndex !== undefined && fields.value?.[fieldIndex]) {
await saveOrUpdate( console.log('column', column)
{ column.show = show
...column, await $api.dbView.formColumnUpdate(column.id, column)
show,
}, fields.value[fieldIndex] = column as any
fieldIndex, // await saveOrUpdate(
) // {
// ...column,
// show,
// },
// fieldIndex,
// )
reloadEventHook.trigger() reloadEventHook.trigger()
@ -273,6 +333,8 @@ function shouldSkipColumn(col: Record<string, any>) {
} }
async function handleAddOrRemoveAllColumns(value: boolean) { async function handleAddOrRemoveAllColumns(value: boolean) {
if (isLocked.value || !isEditable) return
if (value) { if (value) {
for (const col of (localColumns as Record<string, any>)?.value) { for (const col of (localColumns as Record<string, any>)?.value) {
col.show = true col.show = true
@ -310,6 +372,8 @@ function setFormData() {
systemFieldsIds.value = getSystemColumns(col).map((c) => c.fk_column_id) systemFieldsIds.value = getSystemColumns(col).map((c) => c.fk_column_id)
formViewData.value = { formViewData.value = {
banner_image_url: '',
logo_url: '',
...formViewData.value, ...formViewData.value,
submit_another_form: !!(formViewData.value?.submit_another_form ?? 0), submit_another_form: !!(formViewData.value?.submit_another_form ?? 0),
show_blank_form: !!(formViewData.value?.show_blank_form ?? 0), show_blank_form: !!(formViewData.value?.show_blank_form ?? 0),
@ -383,11 +447,14 @@ const columnSupportsScanning = (elementType: UITypes) =>
const onFormItemClick = (element: any) => { const onFormItemClick = (element: any) => {
if (isLocked.value || !isEditable) return if (isLocked.value || !isEditable) return
activeRow.value = element.title activeRow.value = element.title
isTabPressed.value = false isTabPressed.value = false
} }
const handleChangeBackground = (color: string) => { const handleChangeBackground = (color: string) => {
if (isLocked.value || !isEditable) return
const tcolor = tinycolor(color) const tcolor = tinycolor(color)
if (tcolor.isValid()) { if (tcolor.isValid()) {
;(formViewData.value?.meta as Record<string, any>).background_color = color ;(formViewData.value?.meta as Record<string, any>).background_color = color
@ -395,12 +462,74 @@ const handleChangeBackground = (color: string) => {
} }
} }
onClickOutside(draggableRef, () => { const openUploadImage = (isUploadBanner: boolean) => {
if (!isEditable) return
imageCropperData.value.uploadConfig = {
path: [NOCO, base.value.id, meta.value?.id, formViewData.value?.id].join('/'),
}
if (isUploadBanner) {
imageCropperData.value.cropperConfig = {
aspectRatio: 4 / 1,
}
imageCropperData.value.cropFor = 'banner'
} else {
imageCropperData.value.cropperConfig = {
aspectRatio: undefined,
}
imageCropperData.value.cropFor = 'logo'
}
open()
}
onChangeFile((files) => {
if (files && files[0]) {
// 1. Revoke the object URL, to allow the garbage collector to destroy the uploaded before file
if (imageCropperData.value.imageConfig.src) {
URL.revokeObjectURL(imageCropperData.value.imageConfig.src)
}
// 2. Create the blob link to the file to optimize performance:
const blob = URL.createObjectURL(files[0])
// 3. Update the image. The type will be derived from the extension
imageCropperData.value.imageConfig = {
src: blob,
type: files[0].type,
name: files[0].name,
}
showCropper.value = true
}
})
const handleOnUploadImage = (data: Record<string, any> = {}) => {
if (imageCropperData.value.cropFor === 'banner') {
formViewData.value!.banner_image_url = stringifyProp(data) ?? ''
} else {
formViewData.value!.logo_url = stringifyProp(data) ?? ''
}
updateView()
}
onClickOutside(draggableRef, (e) => {
if (
(e.target as HTMLElement)?.closest(
'.nc-dropdown-single-select-cell, .nc-dropdown-multi-select-cell, .nc-dropdown-user-select-cell',
)
) {
return
}
activeRow.value = '' activeRow.value = ''
isTabPressed.value = false isTabPressed.value = false
}) })
onMounted(async () => { onMounted(async () => {
if (imageCropperData.value.src) {
URL.revokeObjectURL(imageCropperData.value.imageConfig.src)
}
isLoadingFormView.value = true isLoadingFormView.value = true
await loadFormView() await loadFormView()
setFormData() setFormData()
@ -447,6 +576,12 @@ watch(activeRow, (newValue) => {
} }
}) })
watch([focusLabel, activeRow], () => {
if (activeRow && focusLabel.value) {
focusLabel.value?.focus()
}
})
useEventListener( useEventListener(
formRef, formRef,
'focusout', 'focusout',
@ -480,7 +615,7 @@ useEventListener(
</script> </script>
<template> <template>
<div class="h-full"> <div class="h-full relative">
<template v-if="isMobileMode"> <template v-if="isMobileMode">
<div class="pl-6 pr-[120px] py-6 bg-white flex-col justify-start items-start gap-2.5 inline-flex"> <div class="pl-6 pr-[120px] py-6 bg-white flex-col justify-start items-start gap-2.5 inline-flex">
<div class="text-gray-500 text-5xl font-semibold leading-16"> <div class="text-gray-500 text-5xl font-semibold leading-16">
@ -550,18 +685,61 @@ useEventListener(
class="flex-1 h-full overflow-auto nc-form-scrollbar p-6" class="flex-1 h-full overflow-auto nc-form-scrollbar p-6"
:style="{background:(formViewData?.meta as Record<string,any>).background_color || '#F9F9FA'}" :style="{background:(formViewData?.meta as Record<string,any>).background_color || '#F9F9FA'}"
> >
<div :class="isEditable ? 'min-w-[616px] overflow-x-auto nc-form-scrollbar' : ''"> <div class="min-w-[616px] overflow-x-auto nc-form-scrollbar">
<!-- for future implementation of cover image --> <GeneralImageCropper
<!-- Todo: cover image uploader and image cropper to crop image in fixed aspect ratio --> v-if="isEditable"
<GeneralFormBanner v-model:show-cropper="showCropper"
v-if=" :image-config="imageCropperData.imageConfig"
formViewData.banner_image_url || !(parseProp(formViewData?.meta).hide_branding && !formViewData.banner_image_url) :cropper-config="imageCropperData.cropperConfig"
" :upload-config="imageCropperData.uploadConfig"
:banner-image-url="formViewData.banner_image_url" @submit="handleOnUploadImage"
/> ></GeneralImageCropper>
<!-- cover image -->
<div class="group relative max-w-[max(33%,688px)] mx-auto">
<GeneralFormBanner :banner-image-url="formViewData.banner_image_url" />
<div class="absolute bottom-0 right-0 hidden group-hover:block">
<div class="flex items-center space-x-1 m-2">
<NcButton
type="secondary"
size="small"
class="nc-form-upload-banner-btn"
data-testid="nc-form-upload-banner-btn"
@click="openUploadImage(true)"
>
<div class="flex gap-2 items-center">
<component :is="iconMap.upload" class="w-4 h-4" />
<span>
{{ formViewData.banner_image_url ? $t('general.replace') : $t('general.upload') }}
{{ $t('general.banner') }}
</span>
</div>
</NcButton>
<NcTooltip v-if="formViewData.banner_image_url">
<template #title> {{ $t('general.delete') }} {{ $t('general.banner') }} </template>
<NcButton
type="secondary"
size="small"
class="nc-form-delete-banner-btn"
data-testid="nc-form-delete-banner-btn"
@click="
() => {
if (isEditable) {
formViewData!.banner_image_url = ''
updateView()
}
}
"
>
<div class="flex gap-2 items-center">
<component :is="iconMap.delete" class="w-4 h-4" />
</div>
</NcButton>
</NcTooltip>
</div>
</div>
</div>
<a-card <a-card
class="!py-8 !lg:py-12 !border-gray-200 !rounded-3xl !mt-6 max-w-[688px] !mx-auto" class="!py-8 !lg:py-12 !border-gray-200 !rounded-3xl !mt-6 !max-w-[max(33%,688px)] !mx-auto"
:body-style="{ :body-style="{
margin: '0 auto', margin: '0 auto',
padding: '0px !important', padding: '0px !important',
@ -571,16 +749,59 @@ useEventListener(
<!-- form header --> <!-- form header -->
<div class="flex flex-col px-4 lg:px-6"> <div class="flex flex-col px-4 lg:px-6">
<!-- Form logo --> <!-- Form logo -->
<!-- <div v-if="isEditable"> <div class="mb-4">
<div class="inline-block rounded-xl bg-gray-100 p-3"> <div
<NcButton type="secondary" size="small" class="nc-form-upload-logo" data-testid="nc-form-upload-log"> class="nc-form-logo-wrapper mx-6 group relative rounded-xl inline-block h-56px max-w-189px overflow-hidden"
<div class="flex gap-2 items-center"> :class="formViewData.logo_url ? 'hover:(w-full bg-gray-100)' : 'bg-gray-100'"
<component :is="iconMap.upload" class="w-4 h-4" /> style="transition: all 0.3s ease-in"
<span> Upload Logo </span> >
</div> <LazyCellAttachmentImage
</NcButton> v-if="formViewData.logo_url"
:srcs="getPossibleAttachmentSrc(parseProp(formViewData.logo_url))"
class="nc-form-logo !object-contain object-left max-h-full max-w-full !m-0 rounded-xl"
/>
<div
class="items-center space-x-1 flex-nowrap m-3"
:class="formViewData.logo_url ? 'hidden absolute top-0 left-0 group-hover:flex' : 'flex'"
>
<NcButton
v-if="isEditable"
type="secondary"
size="small"
class="nc-form-upload-logo-btn"
data-testid="nc-form-upload-log-btn"
@click="openUploadImage(false)"
>
<div class="flex gap-2 items-center">
<component :is="iconMap.upload" class="w-4 h-4" />
<span> {{ formViewData.logo_url ? $t('general.replace') : $t('general.upload') }} Logo</span>
</div>
</NcButton>
<NcTooltip v-if="formViewData.logo_url">
<template #title> {{ $t('general.delete') }} {{ $t('general.logo') }} </template>
<NcButton
type="secondary"
size="small"
class="nc-form-delete-logo-btn"
data-testid="nc-form-delete-logo-btn"
@click="
() => {
if (isEditable) {
formViewData!.logo_url = ''
updateView()
}
}
"
>
<div class="flex gap-2 items-center">
<component :is="iconMap.delete" class="w-4 h-4" />
</div>
</NcButton>
</NcTooltip>
</div>
</div> </div>
</div> --> </div>
<!-- form title --> <!-- form title -->
<div <div
class="border-transparent px-4 lg:px-6" class="border-transparent px-4 lg:px-6"
@ -594,6 +815,9 @@ useEventListener(
{ {
'hover:bg-gray-50': activeRow !== 'nc-form-heading' && isEditable, 'hover:bg-gray-50': activeRow !== 'nc-form-heading' && isEditable,
}, },
{
'bg-gray-50': activeRow === 'nc-form-heading' && isEditable,
},
{ {
'!hover:bg-white !ring-0 !cursor-auto': isLocked, '!hover:bg-white !ring-0 !cursor-auto': isLocked,
}, },
@ -641,6 +865,9 @@ useEventListener(
{ {
'hover:bg-gray-50': activeRow !== 'nc-form-sub-heading' && isEditable, 'hover:bg-gray-50': activeRow !== 'nc-form-sub-heading' && isEditable,
}, },
{
'bg-gray-50': activeRow === 'nc-form-sub-heading' && isEditable,
},
{ {
'!hover:bg-white !ring-0 !cursor-auto': isLocked, '!hover:bg-white !ring-0 !cursor-auto': isLocked,
}, },
@ -693,13 +920,13 @@ useEventListener(
:class="[ :class="[
`nc-form-drag-${element.title.replaceAll(' ', '')}`, `nc-form-drag-${element.title.replaceAll(' ', '')}`,
{ {
'rounded-2xl overflow-hidden border-2 cursor-pointer my-1': isEditable, 'rounded-2xl overflow-hidden border-2 my-1': isEditable,
}, },
{ {
'p-4 lg:p-6 border-transparent my-0': !isEditable, 'p-4 lg:p-6 border-transparent my-0': !isEditable,
}, },
{ {
'nc-form-field-drag-handler border-transparent hover:(bg-gray-50) p-4 lg:p-6 ': 'nc-form-field-drag-handler border-transparent hover:(bg-gray-50) p-4 lg:p-6 cursor-pointer':
activeRow !== element.title && isEditable, activeRow !== element.title && isEditable,
}, },
@ -782,7 +1009,7 @@ useEventListener(
<template v-if="activeRow === element.title"> <template v-if="activeRow === element.title">
<a-form-item class="my-0 !mb-2"> <a-form-item class="my-0 !mb-2">
<a-textarea <a-textarea
:ref="focusLabel" ref="focusLabel"
v-model:value="element.label" v-model:value="element.label"
:rows="1" :rows="1"
auto-size auto-size
@ -869,7 +1096,10 @@ useEventListener(
v-else v-else
v-model="formState[element.title]" v-model="formState[element.title]"
class="nc-input truncate" class="nc-input truncate"
:class="`nc-form-input-${element.title.replaceAll(' ', '')}`" :class="[
`nc-form-input-${element.title.replaceAll(' ', '')}`,
{ 'layout-list': element.meta.isList },
]"
:data-testid="`nc-form-input-${element.title.replaceAll(' ', '')}`" :data-testid="`nc-form-input-${element.title.replaceAll(' ', '')}`"
:column="element" :column="element"
:edit-enabled="true" :edit-enabled="true"
@ -880,19 +1110,55 @@ useEventListener(
</div> </div>
<!-- Field Settings --> <!-- Field Settings -->
<!-- eslint-disable vue/no-constant-condition -->
<div <div
v-if="activeRow === element.title && false" v-if="activeRow === element.title"
class="nc-form-field-settings border-t border-gray-200 p-4 lg:p-6" class="nc-form-field-settings border-t border-gray-200 p-4 lg:p-6 flex flex-col gap-3"
> >
<!-- Todo: Show on conditions, options limit,... --> <!-- Layout -->
<div class="flex items-start gap-3 px-3 py-2 border-1 border-gray-200 rounded-lg"> <div v-if="isSelectTypeCol(element.uidt)">
<div>Layout</div>
<a-radio-group
v-model:value="element.meta.isList"
class="nc-form-field-layout !mt-2"
@change="updateColMeta(element)"
>
<a-radio :value="false">{{ $t('general.dropdown') }}</a-radio>
<a-radio :value="true">{{ $t('general.list') }}</a-radio>
</a-radio-group>
</div>
<!-- Todo: Show on conditions,... -->
<!-- eslint-disable vue/no-constant-condition -->
<div v-if="false" class="flex items-start gap-3 px-3 py-2 border-1 border-gray-200 rounded-lg">
<a-switch v-e="['a:form-view:field:show-on-condition']" size="small" /> <a-switch v-e="['a:form-view:field:show-on-condition']" size="small" />
<div> <div>
<div class="font-medium text-gray-800">{{ $t('labels.showOnConditions') }}</div> <div class="font-medium text-gray-800">{{ $t('labels.showOnConditions') }}</div>
<div class="text-gray-500">{{ $t('labels.showFieldOnConditionsMet') }}</div> <div class="text-gray-500">{{ $t('labels.showFieldOnConditionsMet') }}</div>
</div> </div>
</div> </div>
<!-- Limit options -->
<div v-if="isSelectTypeCol(element.uidt)" class="px-3 py-2 border-1 border-gray-200 rounded-lg">
<div class="flex items-center gap-3">
<a-switch
v-model:checked="element.meta.isLimitOption"
v-e="['a:form-view:field:limit-options']"
size="small"
@change="updateColMeta(element)"
/>
<div class="font-medium text-gray-800">{{ $t('labels.limitOptions') }}</div>
</div>
<div class="pl-10 mt-2 flex-1 max-w-[calc(100%_-_40px)]">
<div class="text-gray-500">{{ $t('labels.limitOptionsSubtext') }}.</div>
<div v-if="element.meta.isLimitOption" class="mt-5 max-w-[80%]">
<LazySmartsheetFormLimitOptions
v-model:model-value="element.meta.limitOptions"
:column="element"
@update:model-value="updateColMeta(element)"
></LazySmartsheetFormLimitOptions>
</div>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -944,8 +1210,8 @@ useEventListener(
</a-card> </a-card>
</div> </div>
</div> </div>
<div v-if="isEditable" class="h-full flex-1 max-w-[384px] nc-form-left-drawer border-l border-gray-200"> <div class="h-full flex-1 max-w-[384px] nc-form-left-drawer border-l border-gray-200">
<Splitpanes horizontal class="w-full nc-form-right-splitpane"> <Splitpanes v-if="formViewData" horizontal class="w-full nc-form-right-splitpane">
<Pane min-size="30" size="50" class="nc-form-right-splitpane-item p-4 flex flex-col space-y-4 !min-h-200px"> <Pane min-size="30" size="50" class="nc-form-right-splitpane-item p-4 flex flex-col space-y-4 !min-h-200px">
<div class="flex flex-wrap justify-between items-center gap-2"> <div class="flex flex-wrap justify-between items-center gap-2">
<div class="flex gap-3"> <div class="flex gap-3">
@ -958,6 +1224,7 @@ useEventListener(
</div> </div>
<a-dropdown <a-dropdown
v-if="isUIAllowed('fieldAdd')"
v-model:visible="showColumnDropdown" v-model:visible="showColumnDropdown"
:trigger="['click']" :trigger="['click']"
overlay-class-name="nc-dropdown-form-add-column" overlay-class-name="nc-dropdown-form-add-column"
@ -1035,6 +1302,7 @@ useEventListener(
item-key="id" item-key="id"
ghost-class="nc-form-field-ghost" ghost-class="nc-form-field-ghost"
:style="{ height: 'calc(100% - 64px)' }" :style="{ height: 'calc(100% - 64px)' }"
:disabled="isLocked || !isEditable"
@change="onMove($event)" @change="onMove($event)"
@start="drag = true" @start="drag = true"
@end="drag = false" @end="drag = false"
@ -1080,7 +1348,7 @@ useEventListener(
<span v-if="isRequired(field, field.required)" class="text-red-500 text-sm align-top">&nbsp;*</span> <span v-if="isRequired(field, field.required)" class="text-red-500 text-sm align-top">&nbsp;*</span>
</div> </div>
</div> </div>
<NcSwitch :checked="!!field.show" :disabled="field.required" /> <NcSwitch :checked="!!field.show" :disabled="field.required || isLocked || !isEditable" />
</div> </div>
</div> </div>
</template> </template>
@ -1096,17 +1364,12 @@ useEventListener(
</template> </template>
</div> </div>
</Pane> </Pane>
<Pane <Pane min-size="20" size="50" class="nc-form-right-splitpane-item !overflow-y-auto nc-form-scrollbar">
v-if="isEditable && !isLocked && formViewData"
min-size="20"
size="50"
class="nc-form-right-splitpane-item !overflow-y-auto nc-form-scrollbar"
>
<div class="p-4 flex flex-col space-y-4 border-b border-gray-200"> <div class="p-4 flex flex-col space-y-4 border-b border-gray-200">
<!-- Appearance Settings --> <!-- Appearance Settings -->
<div class="text-base font-bold text-gray-900">{{ $t('labels.appearanceSettings') }}</div> <div class="text-base font-bold text-gray-900">{{ $t('labels.appearanceSettings') }}</div>
<div> <div :class="isLocked || !isEditable ? 'pointer-events-none' : ''">
<div class="text-gray-800">{{ $t('labels.backgroundColor') }}</div> <div class="text-gray-800">{{ $t('labels.backgroundColor') }}</div>
<div class="flex justify-start"> <div class="flex justify-start">
<LazyGeneralColorPicker <LazyGeneralColorPicker
@ -1149,8 +1412,11 @@ useEventListener(
size="small" size="small"
class="nc-form-hide-branding" class="nc-form-hide-branding"
data-testid="nc-form-hide-branding" data-testid="nc-form-hide-branding"
:disabled="isLocked || !isEditable"
@change=" @change="
(value) => { (value) => {
if (isLocked || !isEditable) return
(formViewData!.meta as Record<string,any>).hide_branding = value (formViewData!.meta as Record<string,any>).hide_branding = value
updateView() updateView()
} }
@ -1183,6 +1449,7 @@ useEventListener(
hide-details hide-details
class="nc-form-after-submit-msg !rounded-lg !px-3 !py-1" class="nc-form-after-submit-msg !rounded-lg !px-3 !py-1"
data-testid="nc-form-after-submit-msg" data-testid="nc-form-after-submit-msg"
:disabled="isLocked || !isEditable"
@change="updateView" @change="updateView"
/> />
</div> </div>
@ -1197,6 +1464,7 @@ useEventListener(
size="small" size="small"
class="nc-form-checkbox-submit-another-form" class="nc-form-checkbox-submit-another-form"
data-testid="nc-form-checkbox-submit-another-form" data-testid="nc-form-checkbox-submit-another-form"
:disabled="isLocked || !isEditable"
@change="updateView" @change="updateView"
/> />
<span class="ml-4">{{ $t('msg.info.submitAnotherForm') }}</span> <span class="ml-4">{{ $t('msg.info.submitAnotherForm') }}</span>
@ -1210,6 +1478,7 @@ useEventListener(
size="small" size="small"
class="nc-form-checkbox-show-blank-form" class="nc-form-checkbox-show-blank-form"
data-testid="nc-form-checkbox-show-blank-form" data-testid="nc-form-checkbox-show-blank-form"
:disabled="isLocked || !isEditable"
@change="updateView" @change="updateView"
/> />
@ -1223,6 +1492,7 @@ useEventListener(
size="small" size="small"
class="nc-form-checkbox-send-email" class="nc-form-checkbox-send-email"
data-testid="nc-form-checkbox-send-email" data-testid="nc-form-checkbox-send-email"
:disabled="isLocked || !isEditable"
@change="onEmailChange" @change="onEmailChange"
/> />
@ -1239,6 +1509,21 @@ useEventListener(
</div> </div>
</div> </div>
</template> </template>
<div
v-if="user?.base_roles?.viewer || user?.base_roles?.commenter"
class="absolute inset-0 bg-black/40 z-500 grid place-items-center"
>
<div class="text-center bg-white px-6 py-8 rounded-xl max-w-lg">
<div class="text-2xl text-gray-800 font-bold">
{{ $t('msg.info.yourCurrentRoleIs') }}
'<span class="capitalize"> {{ Object.keys(user.base_roles)?.[0] ?? ProjectRoles.NO_ACCESS }}</span
>'.
</div>
<div class="text-sm text-gray-700 pt-6">
{{ $t('msg.info.pleaseRequestAccessForView', { viewName: 'form view' }) }}
</div>
</div>
</div>
</div> </div>
</template> </template>
@ -1250,7 +1535,13 @@ useEventListener(
} }
.nc-input { .nc-input {
@apply appearance-none w-full !bg-white rounded-lg border-solid border-1 border-gray-200 focus-within:border-brand-500; @apply appearance-none w-full;
&:not(.layout-list) {
@apply !bg-white rounded-lg border-solid border-1 border-gray-200 focus-within:border-brand-500;
}
&.layout-list {
@apply h-auto !pl-0 !py-1;
}
&.nc-cell-rating, &.nc-cell-rating,
&.nc-cell-geodata { &.nc-cell-geodata {
@apply !py-1; @apply !py-1;
@ -1300,6 +1591,12 @@ useEventListener(
@apply mt-2; @apply mt-2;
} }
} }
:deep(.ant-form-item-has-error .ant-select:not(.ant-select-disabled) .ant-select-selector) {
border: none !important;
}
:deep(.ant-form-item-has-success .ant-select:not(.ant-select-disabled) .ant-select-selector) {
border: none !important;
}
:deep(.nc-cell-attachment) { :deep(.nc-cell-attachment) {
@apply p-0; @apply p-0;
@ -1357,4 +1654,14 @@ useEventListener(
:deep(.nc-form-input-required + button):focus { :deep(.nc-form-input-required + button):focus {
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #3366ff; box-shadow: 0 0 0 2px #fff, 0 0 0 4px #3366ff;
} }
.nc-form-field-layout {
@apply !flex !items-center w-full space-x-3;
:deep(.ant-radio-wrapper) {
@apply border-1 border-gray-200 rounded-lg !py-2 !px-3 basis-full !mr-0 !items-center;
.ant-radio {
@apply !top-0;
}
}
}
</style> </style>

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

@ -232,7 +232,7 @@ async function onMoveStack(event: any, undo = false) {
const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value
groupingFieldColOptions.value[oldIndex].order = newIndex groupingFieldColOptions.value[oldIndex].order = newIndex
groupingFieldColOptions.value[newIndex].order = oldIndex groupingFieldColOptions.value[newIndex].order = oldIndex
const stackMetaObj = JSON.parse(stack_meta as string) || {} const stackMetaObj = parseProp(stack_meta) || {}
stackMetaObj[fk_grp_col_id as string] = groupingFieldColOptions.value stackMetaObj[fk_grp_col_id as string] = groupingFieldColOptions.value
await updateKanbanMeta({ await updateKanbanMeta({
meta: stackMetaObj, meta: stackMetaObj,

370
packages/nc-gui/components/smartsheet/calendar/Cell.vue

@ -0,0 +1,370 @@
<script lang="ts" setup>
import {
type BoolType,
type ColumnType,
type LookupType,
type RollupType,
dateFormats,
isCreatedOrLastModifiedByCol,
isCreatedOrLastModifiedTimeCol,
timeFormats,
} from 'nocodb-sdk'
import dayjs from 'dayjs'
import {
computed,
isBoolean,
isDate,
isDateTime,
isInt,
parseProp,
ref,
storeToRefs,
useAttachment,
useBase,
useMetas,
} from '#imports'
interface Props {
column: ColumnType
modelValue: any
bold?: BoolType
italic?: BoolType
underline?: BoolType
}
const props = defineProps<Props>()
const meta = inject(MetaInj)
const { t } = useI18n()
const { metas } = useMetas()
const column = toRef(props, 'column')
const { sqlUis } = storeToRefs(useBase())
const basesStore = useBases()
const { basesUser } = storeToRefs(basesStore)
const { isXcdbBase, isMssql, isMysql } = useBase()
const { getPossibleAttachmentSrc } = useAttachment()
const sqlUi = ref(column.value?.source_id ? sqlUis.value[column.value?.source_id] : Object.values(sqlUis.value)[0])
const abstractType = computed(() => column.value && sqlUi.value.getAbstractType(column.value))
const getCheckBoxValue = (modelValue: boolean | string | number | '0' | '1') => {
return !!modelValue && modelValue !== '0' && modelValue !== 0 && modelValue !== 'false'
}
const getMultiSelectValue = (modelValue: any, col: ColumnType): string => {
if (!modelValue) {
return ''
}
return modelValue
? Array.isArray(modelValue)
? modelValue.join(', ')
: modelValue.toString()
: isMysql(col.source_id)
? modelValue.toString().split(',').join(', ')
: modelValue.split(', ')
}
const getDateValue = (modelValue: string | null | number, col: ColumnType, isSystemCol?: boolean) => {
const dateFormat = !isSystemCol ? parseProp(col.meta)?.date_format ?? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss'
if (!modelValue || !dayjs(modelValue).isValid()) {
return ''
} else {
return dayjs(/^\d+$/.test(String(modelValue)) ? +modelValue : modelValue).format(dateFormat)
}
}
const getYearValue = (modelValue: string | null) => {
if (!modelValue) {
return ''
} else if (!dayjs(modelValue).isValid()) {
return ''
} else {
return dayjs(modelValue.toString(), 'YYYY').format('YYYY')
}
}
const getDateTimeValue = (modelValue: string | null, col: ColumnType) => {
if (!modelValue || !dayjs(modelValue).isValid()) {
return ''
}
const dateFormat = parseProp(col?.meta)?.date_format ?? dateFormats[0]
const timeFormat = parseProp(col?.meta)?.time_format ?? timeFormats[0]
const dateTimeFormat = `${dateFormat} ${timeFormat}`
const isXcDB = isXcdbBase(col.source_id)
if (!isXcDB) {
return dayjs(/^\d+$/.test(modelValue) ? +modelValue : modelValue, dateTimeFormat).format(dateTimeFormat)
}
if (isMssql(col.source_id)) {
// e.g. 2023-04-29T11:41:53.000Z
return dayjs(modelValue, dateTimeFormat).format(dateTimeFormat)
} else {
return dayjs(modelValue).utc().local().format(dateTimeFormat)
}
}
const getTimeValue = (modelValue: string | null) => {
if (!modelValue) {
return ''
}
let dateTime = dayjs(modelValue)
if (!dateTime.isValid()) {
dateTime = dayjs(modelValue, 'HH:mm:ss')
}
if (!dateTime.isValid()) {
dateTime = dayjs(`1999-01-01 ${modelValue}`)
}
if (!dateTime.isValid()) {
return ''
}
return dateTime.format('HH:mm')
}
const getDurationValue = (modelValue: string | null, col: ColumnType) => {
const durationType = parseProp(col.meta)?.duration || 0
return convertMS2Duration(modelValue, durationType)
}
const getPercentValue = (modelValue: string | null) => {
return modelValue ? `${modelValue}%` : ''
}
const getCurrencyValue = (modelValue: string | number | null | undefined, col: ColumnType): string => {
const currencyMeta = {
currency_locale: 'en-US',
currency_code: 'USD',
...parseProp(col.meta),
}
try {
if (modelValue === null || modelValue === undefined || isNaN(modelValue)) {
return modelValue === null || modelValue === undefined ? '' : (modelValue as string)
}
return new Intl.NumberFormat(currencyMeta.currency_locale || 'en-US', {
style: 'currency',
currency: currencyMeta.currency_code || 'USD',
}).format(+modelValue)
} catch (e) {
return modelValue as string
}
}
const getUserValue = (modelValue: string | string[] | null | Array<any>) => {
if (!modelValue) {
return ''
}
const baseUsers = meta?.value.base_id ? basesUser.value.get(meta?.value.base_id) || [] : []
if (typeof modelValue === 'string') {
const idsOrMails = modelValue.split(',')
return idsOrMails
.map((idOrMail) => {
const user = baseUsers.find((u) => u.id === idOrMail || u.email === idOrMail)
return user ? user.display_name || user.email : idOrMail.id
})
.join(', ')
} else {
if (Array.isArray(modelValue)) {
return modelValue
.map((idOrMail) => {
const user = baseUsers.find((u) => u.id === idOrMail.id || u.email === idOrMail.email)
return user ? user.display_name || user.email : idOrMail.id
})
.join(', ')
} else {
return modelValue ? modelValue.display_name || modelValue.email : ''
}
}
}
const getDecimalValue = (modelValue: string | null | number, col: ColumnType) => {
if (!modelValue || isNaN(Number(modelValue))) {
return ''
}
const columnMeta = parseProp(col.meta)
return Number(modelValue).toFixed(columnMeta?.precision ?? 1)
}
const getIntValue = (modelValue: string | null | number) => {
if (!modelValue || isNaN(Number(modelValue))) {
return ''
}
return Number(modelValue) as unknown as string
}
const getTextAreaValue = (modelValue: string | null, col: ColumnType) => {
const isRichMode = typeof col.meta === 'string' ? JSON.parse(col.meta).richMode : col.meta?.richMode
if (isRichMode) {
return modelValue?.replace(/[*_~\[\]]|<\/?[^>]+(>|$)/g, '') || ''
}
return modelValue || ''
}
const getRollupValue = (modelValue: string | null | number, col: ColumnType) => {
const colOptions = col.colOptions as RollupType
const fns = ['count', 'avg', 'sum', 'countDistinct', 'sumDistinct', 'avgDistinct']
if (fns.includes(colOptions.rollup_function!)) {
return modelValue as string
} else {
const relationColumnOptions = colOptions.fk_relation_column_id
? meta?.value.columns?.find((c) => c.id === colOptions.fk_relation_column_id)?.colOptions
: null
const relatedTableMeta =
relationColumnOptions?.fk_related_model_id && metas.value?.[relationColumnOptions.fk_related_model_id as string]
const childColumn = relatedTableMeta?.columns.find((c: ColumnType) => c.id === colOptions.fk_rollup_column_id)
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return parseValue(modelValue, childColumn) as string
}
}
const getLookupValue = (modelValue: string | null | number | Array<any>, col: ColumnType) => {
const colOptions = col.colOptions as LookupType
const relationColumnOptions = colOptions.fk_relation_column_id
? meta?.value.columns?.find((c) => c.id === colOptions.fk_relation_column_id)?.colOptions
: null
const relatedTableMeta =
relationColumnOptions?.fk_related_model_id && metas.value?.[relationColumnOptions.fk_related_model_id as string]
const childColumn = relatedTableMeta?.columns.find((c: ColumnType) => c.id === colOptions.fk_lookup_column_id) as
| ColumnType
| undefined
if (Array.isArray(modelValue)) {
return modelValue
.map((v) => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return parseValue(v, childColumn!)
})
.join(', ')
}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return parseValue(modelValue, childColumn!)
}
const getAttachmentValue = (modelValue: string | null | number | Array<any>) => {
if (Array.isArray(modelValue)) {
return modelValue.map((v) => `${v.title} (${getPossibleAttachmentSrc(v).join(', ')})`).join(', ')
}
return modelValue as string
}
const getLinksValue = (modelValue: string, col: ColumnType) => {
if (typeof col.meta === 'string') {
col.meta = JSON.parse(col.meta)
}
const parsedValue = +modelValue || 0
if (!parsedValue) {
return ''
} else if (parsedValue === 1) {
return `1 ${col?.meta?.singular || t('general.link')}`
} else {
return `${parsedValue} ${col?.meta?.plural || t('general.links')}`
}
}
const parseValue = (value: any, col: ColumnType): string => {
if (!col) {
return ''
}
if (isGeoData(col)) {
const [latitude, longitude] = ((value as string) || '').split(';')
return latitude && longitude ? `${latitude}; ${longitude}` : value
}
if (isTextArea(col)) {
return getTextAreaValue(value, col)
}
if (isBoolean(col, abstractType)) {
return getCheckBoxValue(value) ? 'Checked' : 'Unchecked'
}
if (isMultiSelect(col)) {
return getMultiSelectValue(value, col)
}
if (isDate(col, abstractType)) {
return getDateValue(value, col)
}
if (isYear(col, abstractType)) {
return getYearValue(value)
}
if (isDateTime(col, abstractType)) {
return getDateTimeValue(value, col)
}
if (isTime(col, abstractType)) {
return getTimeValue(value)
}
if (isDuration(col)) {
return getDurationValue(value, col)
}
if (isPercent(col)) {
return getPercentValue(value)
}
if (isCurrency(col)) {
return getCurrencyValue(value, col)
}
if (isUser(col)) {
return getUserValue(value)
}
if (isDecimal(col)) {
return getDecimalValue(value, col)
}
if (isInt(col, abstractType)) {
return getIntValue(value)
}
if (isJSON(col)) {
return JSON.stringify(value, null, 2)
}
if (isRollup(col)) {
return getRollupValue(value, col)
}
if (isLookup(col)) {
return getLookupValue(value, col)
}
if (isCreatedOrLastModifiedTimeCol(col)) {
return getDateValue(value, col, true)
}
if (isCreatedOrLastModifiedByCol(col)) {
return getUserValue(value)
}
if (isAttachment(col)) {
return getAttachmentValue(value)
}
if (isLink(col)) {
return getLinksValue(value, col)
}
return value as unknown as string
}
</script>
<template>
<span
:class="{
'font-bold': bold,
'italic': italic,
'underline': underline,
}"
data-testid="nc-calendar-cell"
>
{{ parseValue(modelValue, column) }}
</span>
</template>
<style lang="scss" scoped></style>

58
packages/nc-gui/components/smartsheet/calendar/DayView/DateField.vue

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { type Row, computed, ref } from '#imports' import { type Row, computed, isPrimary, ref, useViewColumnsOrThrow } from '#imports'
import { isRowEmpty } from '~/utils' import { isRowEmpty } from '~/utils'
const emit = defineEmits(['expand-record', 'new-record']) const emit = defineEmits(['expand-record', 'new-record'])
@ -15,6 +15,22 @@ const { isUIAllowed } = useRoles()
const { selectedDate, formattedData, formattedSideBarData, calendarRange, updateRowProperty, displayField } = const { selectedDate, formattedData, formattedSideBarData, calendarRange, updateRowProperty, displayField } =
useCalendarViewStoreOrThrow() useCalendarViewStoreOrThrow()
const fields = inject(FieldsInj, ref())
const { fields: _fields } = useViewColumnsOrThrow()
const getFieldStyle = (field: ColumnType) => {
const fi = _fields.value.find((f) => f.title === field.title)
return {
underline: fi.underline,
bold: fi.bold,
italic: fi.italic,
}
}
const fieldsWithoutDisplay = computed(() => fields.value.filter((f) => !isPrimary(f)))
// We loop through all the records and calculate the position of each record based on the range // We loop through all the records and calculate the position of each record based on the range
// We only need to calculate the top, of the record since there is no overlap in the day view of date Field // We only need to calculate the top, of the record since there is no overlap in the day view of date Field
const recordsAcrossAllRange = computed<Row[]>(() => { const recordsAcrossAllRange = computed<Row[]>(() => {
@ -196,27 +212,23 @@ const dropEvent = (event: DragEvent) => {
@click="emit('expand-record', record)" @click="emit('expand-record', record)"
> >
<template v-if="!isRowEmpty(record, displayField)"> <template v-if="!isRowEmpty(record, displayField)">
<div <LazySmartsheetCalendarCell
:class="{ v-if="!isRowEmpty(record, displayField!)"
'!mt-1.5 ml-1': displayField.uidt === UITypes.SingleLineText, v-model="record.row[displayField!.title!]"
'!mt-1': displayField.uidt === UITypes.MultiSelect || displayField.uidt === UITypes.SingleSelect, :bold="getFieldStyle(displayField!).bold"
}" :column="displayField!"
> :italic="getFieldStyle(displayField!).italic"
<LazySmartsheetVirtualCell :underline="getFieldStyle(displayField!).underline"
v-if="isVirtualCol(displayField!)" />
v-model="record.row[displayField!.title!]" </template>
:column="displayField" <template v-for="(field, id) in fieldsWithoutDisplay" :key="id">
:row="record" <LazySmartsheetCalendarCell
/> v-model="record.row[field!.title!]"
:bold="getFieldStyle(field).bold"
<LazySmartsheetCell :column="field"
v-else :italic="getFieldStyle(field).italic"
v-model="record.row[displayField!.title!]" :underline="getFieldStyle(field).underline"
:column="displayField" />
:edit-enabled="false"
:read-only="true"
/>
</div>
</template> </template>
</LazySmartsheetCalendarRecordCard> </LazySmartsheetCalendarRecordCard>
</LazySmartsheetRow> </LazySmartsheetRow>

122
packages/nc-gui/components/smartsheet/calendar/DayView/DateTimeField.vue

@ -1,12 +1,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { type Row, computed, ref } from '#imports' import { type Row, computed, isPrimary, ref, useViewColumnsOrThrow } from '#imports'
import { generateRandomNumber, isRowEmpty } from '~/utils' import { generateRandomNumber, isRowEmpty } from '~/utils'
const emit = defineEmits(['expandRecord', 'new-record']) const emit = defineEmits(['expandRecord', 'new-record'])
const { const {
// activeCalendarView,
selectedDate, selectedDate,
selectedTime, selectedTime,
formattedData, formattedData,
@ -24,6 +25,23 @@ const { isUIAllowed } = useRoles()
const meta = inject(MetaInj, ref()) const meta = inject(MetaInj, ref())
const fields = inject(FieldsInj, ref())
const { fields: _fields } = useViewColumnsOrThrow()
const getFieldStyle = (field: ColumnType) => {
if (!_fields.value) return { underline: false, bold: false, italic: false }
const fi = _fields.value.find((f) => f.title === field.title)
return {
underline: fi?.underline,
bold: fi?.bold,
italic: fi?.italic,
}
}
const fieldsWithoutDisplay = computed(() => fields.value?.filter((f) => !isPrimary(f)))
const hours = computed(() => { const hours = computed(() => {
const hours: Array<dayjs.Dayjs> = [] const hours: Array<dayjs.Dayjs> = []
const _selectedDate = dayjs(selectedDate.value) const _selectedDate = dayjs(selectedDate.value)
@ -38,7 +56,7 @@ const recordsAcrossAllRange = computed<{
record: Row[] record: Row[]
count: { count: {
[key: string]: { [key: string]: {
id: string id: string[]
overflow: boolean overflow: boolean
overflowCount: number overflowCount: number
} }
@ -149,7 +167,7 @@ const recordsAcrossAllRange = computed<{
style.display = 'none' style.display = 'none'
overlaps[timeKey].overflowCount += 1 overlaps[timeKey].overflowCount += 1
} }
_startDate = _startDate.add(15, 'minutes') _startDate = _startDate.add(1, 'minutes')
} }
// This property is used to determine which side the record should be rounded. It can be top, bottom, both or none // This property is used to determine which side the record should be rounded. It can be top, bottom, both or none
@ -187,16 +205,21 @@ const recordsAcrossAllRange = computed<{
const id = generateRandomNumber() const id = generateRandomNumber()
const startDate = dayjs(record.row[fromCol.title!]) const startDate = dayjs(record.row[fromCol.title!])
const endDate = dayjs(record.row[fromCol.title!]).add(15, 'minutes')
let endDate = dayjs(record.row[fromCol.title!]).add(1, 'hour')
if (endDate.isAfter(scheduleEnd, 'minutes')) {
endDate = scheduleEnd
}
const startHour = startDate.hour() const startHour = startDate.hour()
let style: Partial<CSSStyleDeclaration> = {} let style: Partial<CSSStyleDeclaration> = {}
let _startDate = startDate.clone() let _startDate = startDate.clone()
// We loop through every 15 minutes between the start and end date and keep track of the number of records that overlap at a given time // We loop through every minute between the start and end date and keep track of the number of records that overlap at a given time
while (_startDate.isBefore(endDate)) { while (_startDate.isBefore(endDate)) {
const timeKey = _startDate.startOf('hour').format('HH:mm') const timeKey = _startDate.format('HH:mm')
if (!overlaps[timeKey]) { if (!overlaps[timeKey]) {
overlaps[timeKey] = { overlaps[timeKey] = {
@ -216,15 +239,20 @@ const recordsAcrossAllRange = computed<{
display: 'none', display: 'none',
} }
} }
_startDate = _startDate.add(15, 'minutes') _startDate = _startDate.add(1, 'minute')
} }
const topInPixels = (startDate.hour() + startDate.startOf('hour').minute() / 60) * 80 // The top of the record is calculated based on the start hour
// Update such that it is also based on Minutes
const minutes = startDate.minute() + startDate.hour() * 60
const updatedTopInPixels = (minutes * 80) / 60
// A minimum height of 80px is set for each record // A minimum height of 80px is set for each record
const heightInPixels = Math.max((endDate.diff(startDate, 'minute') / 60) * 80, perRecordHeight) const heightInPixels = Math.max((endDate.diff(startDate, 'minute') / 60) * 80, perRecordHeight)
const finalTopInPixels = topInPixels + startHour * 2 const finalTopInPixels = updatedTopInPixels + startHour * 2
style = { style = {
...style, ...style,
@ -314,8 +342,9 @@ const calculateNewRow = (event: MouseEvent) => {
// It can be between 0 and 23 (inclusive) // It can be between 0 and 23 (inclusive)
const hour = Math.max(Math.floor(percentY * 23), 0) const hour = Math.max(Math.floor(percentY * 23), 0)
const minutes = Math.min(Math.max(Math.round(Math.floor((percentY * 23 - hour) * 60) / 15) * 15, 0), 60)
// We calculate the new startDate by adding the hour to the start of the selected date // We calculate the new startDate by adding the hour to the start of the selected date
const newStartDate = dayjs(selectedDate.value).startOf('day').add(hour, 'hour') const newStartDate = dayjs(selectedDate.value).startOf('day').add(hour, 'hour').add(minutes, 'minute')
if (!newStartDate || !fromCol) return { newRow: null, updateProperty: [] } if (!newStartDate || !fromCol) return { newRow: null, updateProperty: [] }
let endDate let endDate
@ -552,6 +581,35 @@ const dragStart = (event: MouseEvent, record: Row) => {
document.addEventListener('mouseup', onMouseUp) document.addEventListener('mouseup', onMouseUp)
} }
const isOverflowAcrossHourRange = (hour: dayjs.Dayjs) => {
let startOfHour = hour.startOf('hour')
const endOfHour = hour.endOf('hour')
const ids: Array<string> = []
let isOverflow = false
let overflowCount = 0
while (startOfHour.isBefore(endOfHour, 'minute')) {
const hourKey = startOfHour.format('HH:mm')
if (recordsAcrossAllRange.value?.count?.[hourKey]?.overflow) {
isOverflow = true
recordsAcrossAllRange.value?.count?.[hourKey]?.id.forEach((id) => {
if (!ids.includes(id)) {
ids.push(id)
overflowCount += 1
}
})
}
startOfHour = startOfHour.add(1, 'minute')
}
overflowCount = overflowCount > 8 ? overflowCount - 8 : 0
return { isOverflow, overflowCount }
}
const viewMore = (hour: dayjs.Dayjs) => { const viewMore = (hour: dayjs.Dayjs) => {
sideBarFilterOption.value = 'selectedHours' sideBarFilterOption.value = 'selectedHours'
selectedTime.value = hour selectedTime.value = hour
@ -662,7 +720,7 @@ const viewMore = (hour: dayjs.Dayjs) => {
</NcButton> </NcButton>
<NcButton <NcButton
v-if="recordsAcrossAllRange?.count?.[hour.format('HH:mm')]?.overflow" v-if="isOverflowAcrossHourRange(hour).isOverflow"
class="!absolute bottom-2 text-center w-15 mx-auto inset-x-0 z-3 text-gray-500" class="!absolute bottom-2 text-center w-15 mx-auto inset-x-0 z-3 text-gray-500"
size="xxsmall" size="xxsmall"
type="secondary" type="secondary"
@ -670,7 +728,7 @@ const viewMore = (hour: dayjs.Dayjs) => {
> >
<span class="text-xs"> <span class="text-xs">
+ +
{{ recordsAcrossAllRange?.count[hour.format('HH:mm')]?.overflowCount }} {{ isOverflowAcrossHourRange(hour).overflowCount }}
more more
</span> </span>
</NcButton> </NcButton>
@ -699,27 +757,23 @@ const viewMore = (hour: dayjs.Dayjs) => {
@resize-start="onResizeStart" @resize-start="onResizeStart"
> >
<template v-if="!isRowEmpty(record, displayField)"> <template v-if="!isRowEmpty(record, displayField)">
<div <LazySmartsheetCalendarCell
:class="{ v-if="!isRowEmpty(record, displayField!)"
'!mt-2': displayField!.uidt === UITypes.SingleLineText, v-model="record.row[displayField!.title!]"
'!mt-1': displayField!.uidt === UITypes.MultiSelect || displayField!.uidt === UITypes.SingleSelect, :bold="getFieldStyle(displayField!).bold"
}" :column="displayField"
> :italic="getFieldStyle(displayField!).italic"
<LazySmartsheetVirtualCell :underline="getFieldStyle(displayField!).underline"
v-if="isVirtualCol(displayField!)" />
v-model="record.row[displayField!.title!]" </template>
:column="displayField" <template v-for="(field, id) in fieldsWithoutDisplay" :key="id">
:row="record" <LazySmartsheetCalendarCell
/> v-model="record.row[field!.title!]"
:bold="getFieldStyle(field).bold"
<LazySmartsheetCell :column="field"
v-else :italic="getFieldStyle(field).italic"
v-model="record.row[displayField!.title!]" :underline="getFieldStyle(field).underline"
:column="displayField" />
:edit-enabled="false"
:read-only="true"
/>
</div>
</template> </template>
</LazySmartsheetCalendarVRecordCard> </LazySmartsheetCalendarVRecordCard>
</LazySmartsheetRow> </LazySmartsheetRow>

94
packages/nc-gui/components/smartsheet/calendar/MonthView.vue

@ -1,8 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import dayjs from 'dayjs' import dayjs from 'dayjs'
import type { ColumnType } from 'nocodb-sdk'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import { type Row, computed, isPrimary, ref, useViewColumnsOrThrow } from '#imports'
import type { Row } from '#imports'
import { generateRandomNumber, isRowEmpty } from '~/utils' import { generateRandomNumber, isRowEmpty } from '~/utils'
const emit = defineEmits(['new-record', 'expandRecord']) const emit = defineEmits(['new-record', 'expandRecord'])
@ -61,6 +60,23 @@ const resizeDirection = ref<'right' | 'left'>()
const resizeRecord = ref<Row>() const resizeRecord = ref<Row>()
const fields = inject(FieldsInj, ref())
const { fields: _fields } = useViewColumnsOrThrow()
const getFieldStyle = (field: ColumnType | undefined) => {
if (!field) return { underline: false, bold: false, italic: false }
const fi = _fields.value?.find((f) => f.title === field.title)
return {
underline: fi?.underline,
bold: fi?.bold,
italic: fi?.italic,
}
}
const fieldsWithoutDisplay = computed(() => fields.value?.filter((f) => !isPrimary(f)))
const dates = computed(() => { const dates = computed(() => {
const startOfMonth = selectedMonth.value.startOf('month') const startOfMonth = selectedMonth.value.startOf('month')
const endOfMonth = selectedMonth.value.endOf('month') const endOfMonth = selectedMonth.value.endOf('month')
@ -331,8 +347,8 @@ const calculateNewRow = (event: MouseEvent, updateSideBar?: boolean) => {
const percentY = (event.clientY - top - window.scrollY) / height const percentY = (event.clientY - top - window.scrollY) / height
const percentX = (event.clientX - left - window.scrollX) / width const percentX = (event.clientX - left - window.scrollX) / width
const fromCol = dragRecord.value.rowMeta.range?.fk_from_col const fromCol = dragRecord.value?.rowMeta.range?.fk_from_col
const toCol = dragRecord.value.rowMeta.range?.fk_to_col const toCol = dragRecord.value?.rowMeta.range?.fk_to_col
const week = Math.floor(percentY * dates.value.length) const week = Math.floor(percentY * dates.value.length)
const day = Math.floor(percentX * 7) const day = Math.floor(percentX * 7)
@ -345,7 +361,7 @@ const calculateNewRow = (event: MouseEvent, updateSideBar?: boolean) => {
const newRow = { const newRow = {
...dragRecord.value, ...dragRecord.value,
row: { row: {
...dragRecord.value.row, ...dragRecord.value?.row,
[fromCol!.title!]: dayjs(newStartDate).format('YYYY-MM-DD HH:mm:ssZ'), [fromCol!.title!]: dayjs(newStartDate).format('YYYY-MM-DD HH:mm:ssZ'),
}, },
} }
@ -353,8 +369,8 @@ const calculateNewRow = (event: MouseEvent, updateSideBar?: boolean) => {
const updateProperty = [fromCol!.title!] const updateProperty = [fromCol!.title!]
if (toCol) { if (toCol) {
const fromDate = dragRecord.value.row[fromCol!.title!] ? dayjs(dragRecord.value.row[fromCol!.title!]) : null const fromDate = dragRecord.value?.row[fromCol!.title!] ? dayjs(dragRecord.value.row[fromCol!.title!]) : null
const toDate = dragRecord.value.row[toCol!.title!] ? dayjs(dragRecord.value.row[toCol!.title!]) : null const toDate = dragRecord.value?.row[toCol!.title!] ? dayjs(dragRecord.value?.row[toCol!.title!]) : null
if (fromDate && toDate) { if (fromDate && toDate) {
endDate = dayjs(newStartDate).add(toDate.diff(fromDate, 'day'), 'day') endDate = dayjs(newStartDate).add(toDate.diff(fromDate, 'day'), 'day')
@ -366,7 +382,6 @@ const calculateNewRow = (event: MouseEvent, updateSideBar?: boolean) => {
endDate = newStartDate.clone() endDate = newStartDate.clone()
} }
dragRecord.value = undefined
newRow.row[toCol!.title!] = dayjs(endDate).format('YYYY-MM-DD HH:mm:ssZ') newRow.row[toCol!.title!] = dayjs(endDate).format('YYYY-MM-DD HH:mm:ssZ')
updateProperty.push(toCol!.title!) updateProperty.push(toCol!.title!)
} }
@ -440,7 +455,7 @@ const onResize = (event: MouseEvent) => {
[toCol!.title!]: dayjs(newEndDate).format('YYYY-MM-DD HH:mm:ssZ'), [toCol!.title!]: dayjs(newEndDate).format('YYYY-MM-DD HH:mm:ssZ'),
}, },
} }
} else if (resizeDirection.value === 'left') { } else {
let newStartDate = dates.value[week] ? dayjs(dates.value[week][day]) : null let newStartDate = dates.value[week] ? dayjs(dates.value[week][day]) : null
updateProperty = [fromCol!.title!] updateProperty = [fromCol!.title!]
@ -465,7 +480,9 @@ const onResize = (event: MouseEvent) => {
return pk === newPk ? newRow : r return pk === newPk ? newRow : r
}) })
useDebouncedRowUpdate(newRow, updateProperty, false) if (newRow) {
useDebouncedRowUpdate(newRow, updateProperty, false)
}
} }
const onResizeEnd = () => { const onResizeEnd = () => {
@ -480,7 +497,7 @@ const onResizeEnd = () => {
const onResizeStart = (direction: 'right' | 'left', event: MouseEvent, record: Row) => { const onResizeStart = (direction: 'right' | 'left', event: MouseEvent, record: Row) => {
if (!isUIAllowed('dataEdit') || draggingId.value) return if (!isUIAllowed('dataEdit') || draggingId.value) return
selectedDate.value = null // selectedDate.value = null
resizeInProgress.value = true resizeInProgress.value = true
resizeDirection.value = direction resizeDirection.value = direction
resizeRecord.value = record resizeRecord.value = record
@ -490,11 +507,10 @@ const onResizeStart = (direction: 'right' | 'left', event: MouseEvent, record: R
} }
const stopDrag = (event: MouseEvent) => { const stopDrag = (event: MouseEvent) => {
clearTimeout(dragTimeout.value)
if (!isUIAllowed('dataEdit') || !dragRecord.value || !isDragging.value) return if (!isUIAllowed('dataEdit') || !dragRecord.value || !isDragging.value) return
event.preventDefault() event.preventDefault()
clearTimeout(dragTimeout.value)
dragElement.value!.style.boxShadow = 'none' dragElement.value!.style.boxShadow = 'none'
const { newRow, updateProperty } = calculateNewRow(event, false) const { newRow, updateProperty } = calculateNewRow(event, false)
@ -540,7 +556,7 @@ const dragStart = (event: MouseEvent, record: Row) => {
}) })
dragRecord.value = record dragRecord.value = record
selectedDate.value = null // selectedDate.value = null
isDragging.value = true isDragging.value = true
dragElement.value = target dragElement.value = target
@ -613,7 +629,7 @@ const isDateSelected = (date: dayjs.Dayjs) => {
<div <div
v-for="(day, index) in days" v-for="(day, index) in days"
:key="index" :key="index"
class="text-center bg-gray-50 py-1 text-sm border-b-1 border-r-1 last:border-r-0 border-gray-200 font-semibold text-gray-500" class="text-center bg-gray-50 py-1 text-sm border-b-1 border-r-1 last:border-r-0 border-gray-100 font-semibold text-gray-500"
> >
{{ day }} {{ day }}
</div> </div>
@ -637,7 +653,7 @@ const isDateSelected = (date: dayjs.Dayjs) => {
isDateSelected(day) || (focusedDate && dayjs(day).isSame(focusedDate, 'day')), isDateSelected(day) || (focusedDate && dayjs(day).isSame(focusedDate, 'day')),
'!text-gray-400': !isDayInPagedMonth(day), '!text-gray-400': !isDayInPagedMonth(day),
}" }"
class="text-right relative group last:border-r-0 text-sm h-full border-r-1 border-b-1 border-gray-200 font-medium hover:bg-gray-50 text-gray-800 bg-white" class="text-right relative group last:border-r-0 text-sm h-full border-r-1 border-b-1 border-gray-100 font-medium hover:bg-gray-50 text-gray-800 bg-white"
data-testid="nc-calendar-month-day" data-testid="nc-calendar-month-day"
@click="selectDate(day)" @click="selectDate(day)"
> >
@ -769,30 +785,25 @@ const isDateSelected = (date: dayjs.Dayjs) => {
: false : false
" "
@resize-start="onResizeStart" @resize-start="onResizeStart"
@dblclick.stop="emit('expand-record', record)" @dblclick.stop="emit('expandRecord', record)"
> >
<template v-if="!isRowEmpty(record, displayField)"> <template v-if="!isRowEmpty(record, displayField)">
<div <LazySmartsheetCalendarCell
:class="{ v-model="record.row[displayField!.title!]"
'mt-1.4': displayField!.uidt === UITypes.SingleLineText, :bold="getFieldStyle(displayField).bold"
'mt-1': displayField!.uidt === UITypes.MultiSelect || displayField!.uidt === UITypes.SingleSelect, :column="displayField"
}" :italic="getFieldStyle(displayField).italic"
> :underline="getFieldStyle(displayField).underline"
<LazySmartsheetVirtualCell />
v-if="isVirtualCol(displayField!)" </template>
v-model="record.row[displayField!.title!]" <template v-for="(field, id) in fieldsWithoutDisplay" :key="id">
:column="displayField" <LazySmartsheetCalendarCell
:row="record" v-model="record.row[field!.title!]"
/> :bold="getFieldStyle(field).bold"
:column="field"
<LazySmartsheetCell :italic="getFieldStyle(field).italic"
v-else :underline="getFieldStyle(field).underline"
v-model="record.row[displayField!.title!]" />
:column="displayField"
:edit-enabled="false"
:read-only="true"
/>
</div>
</template> </template>
</LazySmartsheetCalendarRecordCard> </LazySmartsheetCalendarRecordCard>
</LazySmartsheetRow> </LazySmartsheetRow>
@ -802,11 +813,6 @@ const isDateSelected = (date: dayjs.Dayjs) => {
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.hide {
transition: 0.01s;
transform: translateX(-9999px);
}
.prevent-select { .prevent-select {
-webkit-user-select: none; /* Safari */ -webkit-user-select: none; /* Safari */
-ms-user-select: none; /* IE 10 and IE 11 */ -ms-user-select: none; /* IE 10 and IE 11 */

19
packages/nc-gui/components/smartsheet/calendar/RecordCard.vue

@ -28,8 +28,8 @@ const emit = defineEmits(['resize-start'])
:class="{ :class="{
'min-h-9': size === 'small', 'min-h-9': size === 'small',
'h-full': size === 'auto', 'h-full': size === 'auto',
'rounded-l-lg ml-1': position === 'leftRounded', 'rounded-l-lg': position === 'leftRounded',
'rounded-r-lg mr-1': position === 'rightRounded', 'rounded-r-lg': position === 'rightRounded',
'rounded-lg mx-1': position === 'rounded', 'rounded-lg mx-1': position === 'rounded',
'rounded-none': position === 'none', 'rounded-none': position === 'none',
'bg-maroon-50': color === 'maroon', 'bg-maroon-50': color === 'maroon',
@ -53,10 +53,10 @@ const emit = defineEmits(['resize-start'])
'bg-pink-500': color === 'pink', 'bg-pink-500': color === 'pink',
'bg-purple-500': color === 'purple', 'bg-purple-500': color === 'purple',
}" }"
class="block h-full min-h-5 w-1 rounded" class="w-1 min-h-5 bg-blue-500 rounded-x rounded-y-sm"
></div> ></div>
<div v-if="(position === 'leftRounded' || position === 'rounded') && resize" class="mt-0.1 h-7.1 absolute -left-4 resize"> <div v-if="(position === 'leftRounded' || position === 'rounded') && resize" class="mt-0.7 h-7.1 absolute -left-4 resize">
<NcButton <NcButton
:class="{ :class="{
'!block z-1 !border-brand-500': selected || hover, '!block z-1 !border-brand-500': selected || hover,
@ -70,15 +70,20 @@ const emit = defineEmits(['resize-start'])
</NcButton> </NcButton>
</div> </div>
<div class="overflow-hidden ml-2 h-8 absolute"> <div class="overflow-hidden items-center flex w-full ml-2 h-8">
<span v-if="position === 'rightRounded' || position === 'none'" class="mr-1"> .... </span> <span v-if="position === 'rightRounded' || position === 'none'" class="mr-1"> .... </span>
<span class="text-sm !w-[80%] text-gray-800"> <span
:class="{
'pr-7': position === 'leftRounded',
}"
class="text-sm pr-3 mr-3 break-word space-x-2 whitespace-nowrap gap-2 overflow-hidden text-ellipsis w-full truncate text-gray-800"
>
<slot /> <slot />
</span> </span>
<span v-if="position === 'leftRounded' || position === 'none'" class="absolute my-0 right-5"> .... </span> <span v-if="position === 'leftRounded' || position === 'none'" class="absolute my-0 right-5"> .... </span>
</div> </div>
<div v-if="(position === 'rightRounded' || position === 'rounded') && resize" class="absolute mt-0.1 z-1 -right-4 resize"> <div v-if="(position === 'rightRounded' || position === 'rounded') && resize" class="absolute mt-0.3 z-1 -right-4 resize">
<NcButton <NcButton
:class="{ :class="{
'!block !border-brand-500': selected || hover, '!block !border-brand-500': selected || hover,

27
packages/nc-gui/components/smartsheet/calendar/VRecordCard.vue

@ -26,14 +26,14 @@ const emit = defineEmits(['resize-start'])
> >
<NcButton <NcButton
:class="{ :class="{
'!flex border-1 rounded-lg border-brand-500': selected || hover, '!flex rounded-lg border-brand-500': selected || hover,
}" }"
class="!group-hover:(border-brand-500) !border-1 cursor-ns-resize" class="!group-hover:(border-brand-500) !border-1 text-gray-400 cursor-ns-resize"
size="xsmall" size="xsmall"
type="secondary" type="secondary"
@mousedown.stop="emit('resize-start', 'left', $event, record)" @mousedown.stop="emit('resize-start', 'left', $event, record)"
> >
<component :is="iconMap.drag" class="text-gray-400"></component> <component :is="iconMap.drag" class="mt-0.5" />
</NcButton> </NcButton>
</div> </div>
<div <div
@ -51,9 +51,9 @@ const emit = defineEmits(['resize-start'])
'group-hover:(border-brand-500)': resize, 'group-hover:(border-brand-500)': resize,
'!border-brand-500 border-1': selected || hover, '!border-brand-500 border-1': selected || hover,
}" }"
class="relative h-full ml-0.25 border-1 border-gray-50" class="relative flex items-center h-full ml-0.25 border-1 border-transparent"
> >
<div class="h-full absolute py-2"> <div class="h-full py-1">
<div <div
:class="{ :class="{
'bg-maroon-500': color === 'maroon', 'bg-maroon-500': color === 'maroon',
@ -63,17 +63,18 @@ const emit = defineEmits(['resize-start'])
'bg-pink-500': color === 'pink', 'bg-pink-500': color === 'pink',
'bg-purple-500': color === 'purple', 'bg-purple-500': color === 'purple',
}" }"
class="block h-full min-h-5 ml-1 w-1 rounded mr-2" class="block h-full min-h-5 ml-1 w-1 rounded"
></div> ></div>
</div> </div>
<div v-if="position === 'bottomRounded' || position === 'none'" class="ml-3">....</div> <div v-if="position === 'bottomRounded' || position === 'none'" class="ml-3">....</div>
<div class="ml-3 pr-3 text-ellipsis overflow-hidden w-full h-8 absolute"> <span
<span class="text-sm text-gray-800"> class="pl-1 pr-1 text-sm h-[80%] text-gray-800 leading-7 space-x-2 break-all whitespace-normal truncate w-full overflow-y-hidden"
<slot /> >
</span> <slot />
</div> </span>
<div v-if="position === 'topRounded' || position === 'none'" class="h-full pb-7 flex items-end ml-3">....</div> <div v-if="position === 'topRounded' || position === 'none'" class="h-full pb-7 flex items-end ml-3">....</div>
</div> </div>
<div <div
@ -84,12 +85,12 @@ const emit = defineEmits(['resize-start'])
:class="{ :class="{
'!flex border-1 rounded-lg z-1 cursor-ns-resize border-brand-500': selected || hover, '!flex border-1 rounded-lg z-1 cursor-ns-resize border-brand-500': selected || hover,
}" }"
class="!group-hover:(border-brand-500) !border-1" class="!group-hover:(border-brand-500) text-gray-400 !border-1"
size="xsmall" size="xsmall"
type="secondary" type="secondary"
@mousedown.stop="emit('resize-start', 'right', $event, record)" @mousedown.stop="emit('resize-start', 'right', $event, record)"
> >
<component :is="iconMap.drag" class="text-gray-400"></component> <component :is="iconMap.drag" class="mt-0.5" />
</NcButton> </NcButton>
</div> </div>
</template> </template>

67
packages/nc-gui/components/smartsheet/calendar/WeekView/DateField.vue

@ -1,8 +1,8 @@
<script lang="ts" setup> <script lang="ts" setup>
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import { type ColumnType } from 'nocodb-sdk'
import type { Row } from '~/lib' import type { Row } from '~/lib'
import { ref } from '#imports' import { computed, isPrimary, ref, useViewColumnsOrThrow } from '#imports'
import { generateRandomNumber, isRowEmpty } from '~/utils' import { generateRandomNumber, isRowEmpty } from '~/utils'
const emits = defineEmits(['expandRecord']) const emits = defineEmits(['expandRecord'])
@ -18,14 +18,30 @@ const { isUIAllowed } = useRoles()
const meta = inject(MetaInj, ref()) const meta = inject(MetaInj, ref())
const fields = inject(FieldsInj, ref())
const { fields: _fields } = useViewColumnsOrThrow()
const getFieldStyle = (field: ColumnType | undefined) => {
const fi = _fields.value?.find((f) => f.title === field.title)
return {
underline: fi?.underline,
bold: fi?.bold,
italic: fi?.italic,
}
}
const fieldsWithoutDisplay = computed(() => fields.value?.filter((f) => !isPrimary(f)))
// Calculate the dates of the week // Calculate the dates of the week
const weekDates = computed(() => { const weekDates = computed(() => {
const startOfWeek = new Date(selectedDateRange.value.start!) let startOfWeek = dayjs(selectedDateRange.value.start)
const endOfWeek = new Date(selectedDateRange.value.end!) const endOfWeek = dayjs(selectedDateRange.value.end)
const datesArray = [] const datesArray = []
while (startOfWeek.getTime() <= endOfWeek.getTime()) { while (startOfWeek.isBefore(endOfWeek) || startOfWeek.isSame(endOfWeek, 'day')) {
datesArray.push(new Date(startOfWeek)) datesArray.push(dayjs(startOfWeek))
startOfWeek.setDate(startOfWeek.getDate() + 1) startOfWeek = startOfWeek.add(1, 'day')
} }
return datesArray return datesArray
}) })
@ -567,27 +583,22 @@ const dropEvent = (event: DragEvent) => {
@resize-start="onResizeStart" @resize-start="onResizeStart"
> >
<template v-if="!isRowEmpty(record, displayField)"> <template v-if="!isRowEmpty(record, displayField)">
<div <LazySmartsheetCalendarCell
:class="{ v-model="record.row[displayField!.title!]"
'mt-2': displayField.uidt === UITypes.SingleLineText, :bold="getFieldStyle(displayField).bold"
'mt-1': displayField.uidt === UITypes.MultiSelect || displayField.uidt === UITypes.SingleSelect, :column="displayField"
}" :italic="getFieldStyle(displayField).italic"
> :underline="getFieldStyle(displayField).underline"
<LazySmartsheetVirtualCell />
v-if="isVirtualCol(displayField)" </template>
v-model="record.row[displayField.title]" <template v-for="(field, index) in fieldsWithoutDisplay" :key="index">
:column="displayField" <LazySmartsheetCalendarCell
:row="record" v-model="record.row[field!.title!]"
/> :bold="getFieldStyle(field).bold"
:column="field"
<LazySmartsheetCell :italic="getFieldStyle(field).italic"
v-else :underline="getFieldStyle(field).underline"
v-model="record.row[displayField.title]" />
:column="displayField"
:edit-enabled="false"
:read-only="true"
/>
</div>
</template> </template>
</LazySmartsheetCalendarRecordCard> </LazySmartsheetCalendarRecordCard>
</LazySmartsheetRow> </LazySmartsheetRow>

205
packages/nc-gui/components/smartsheet/calendar/WeekView/DateTimeField.vue

@ -1,8 +1,8 @@
<script lang="ts" setup> <script lang="ts" setup>
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import { type ColumnType } from 'nocodb-sdk'
import type { Row } from '~/lib' import type { Row } from '~/lib'
import { computed, ref } from '#imports' import { computed, isPrimary, ref, useViewColumnsOrThrow } from '#imports'
import { generateRandomNumber, isRowEmpty } from '~/utils' import { generateRandomNumber, isRowEmpty } from '~/utils'
const emits = defineEmits(['expandRecord']) const emits = defineEmits(['expandRecord'])
@ -30,6 +30,23 @@ const { isUIAllowed } = useRoles()
const meta = inject(MetaInj, ref()) const meta = inject(MetaInj, ref())
const fields = inject(FieldsInj, ref())
const { fields: _fields } = useViewColumnsOrThrow()
const getFieldStyle = (field: ColumnType | undefined) => {
if (!field) return { underline: false, bold: false, italic: false }
const fi = _fields.value?.find((f) => f.title === field.title)
return {
underline: fi?.underline,
bold: fi?.bold,
italic: fi?.italic,
}
}
const fieldsWithoutDisplay = computed(() => fields.value?.filter((f) => !isPrimary(f)))
// Since it is a datetime Week view, we need to create a 2D array of dayjs objects to represent the hours in a day for each day in the week // Since it is a datetime Week view, we need to create a 2D array of dayjs objects to represent the hours in a day for each day in the week
const datesHours = computed(() => { const datesHours = computed(() => {
const datesHours: Array<Array<dayjs.Dayjs>> = [] const datesHours: Array<Array<dayjs.Dayjs>> = []
@ -68,7 +85,11 @@ const recordsAcrossAllRange = computed<{
} }
} }
}>(() => { }>(() => {
if (!formattedData.value || !calendarRange.value || !container.value) return { records: [], count: {} } if (!formattedData.value || !calendarRange.value || !container.value || !scrollContainer.value)
return {
records: [],
count: {},
}
const { scrollHeight } = scrollContainer.value const { scrollHeight } = scrollContainer.value
@ -78,7 +99,7 @@ const recordsAcrossAllRange = computed<{
const scheduleStart = dayjs(selectedDateRange.value.start).startOf('day') const scheduleStart = dayjs(selectedDateRange.value.start).startOf('day')
const scheduleEnd = dayjs(selectedDateRange.value.end).endOf('day') const scheduleEnd = dayjs(selectedDateRange.value.end).endOf('day')
// We need to keep track of the overlaps for each day and hour in the week to calculate the width and left position of each record // We need to keep track of the overlaps for each day and hour, minute in the week to calculate the width and left position of each record
// The first key is the date, the second key is the hour, and the value is an object containing the ids of the records that overlap // The first key is the date, the second key is the hour, and the value is an object containing the ids of the records that overlap
// The key is in the format YYYY-MM-DD and the hour is in the format HH:mm // The key is in the format YYYY-MM-DD and the hour is in the format HH:mm
const overlaps: { const overlaps: {
@ -116,61 +137,83 @@ const recordsAcrossAllRange = computed<{
sortedFormattedData.forEach((record: Row) => { sortedFormattedData.forEach((record: Row) => {
if (!toCol && fromCol) { if (!toCol && fromCol) {
// If there is no toColumn chosen in the range // If there is no toColumn chosen in the range
const startDate = record.row[fromCol.title!] ? dayjs(record.row[fromCol.title!]) : null const ogStartDate = record.row[fromCol.title!] ? dayjs(record.row[fromCol.title!]) : null
if (!startDate) return if (!ogStartDate) return
// Hour Key currently is set as start of the hour let endDate = ogStartDate.clone().add(1, 'hour')
// TODO: Need to work on the granularity of the hour
const dateKey = startDate?.format('YYYY-MM-DD') if (endDate.isAfter(scheduleEnd, 'minutes')) {
const hourKey = startDate?.startOf('hour').format('HH:mm') endDate = scheduleEnd
}
const id = record.rowMeta.id ?? generateRandomNumber() const id = record.rowMeta.id ?? generateRandomNumber()
let startDate = ogStartDate.clone()
let style: Partial<CSSStyleDeclaration> = {} let style: Partial<CSSStyleDeclaration> = {}
// If the dateKey and hourKey are valid, we add the id to the overlaps object while (startDate.isBefore(endDate, 'minutes')) {
if (dateKey && hourKey) { const dateKey = startDate?.format('YYYY-MM-DD')
if (!overlaps[dateKey]) { const hourKey = startDate?.format('HH:mm')
overlaps[dateKey] = {}
} // If the dateKey and hourKey are valid, we add the id to the overlaps object
if (!overlaps[dateKey][hourKey]) { if (dateKey && hourKey) {
overlaps[dateKey][hourKey] = { if (!overlaps[dateKey]) {
id: [], overlaps[dateKey] = {}
overflow: false,
overflowCount: 0,
} }
if (!overlaps[dateKey][hourKey]) {
overlaps[dateKey][hourKey] = {
id: [],
overflow: false,
overflowCount: 0,
}
}
overlaps[dateKey][hourKey].id.push(id)
} }
overlaps[dateKey][hourKey].id.push(id)
}
// If the number of records that overlap in a single hour is more than 4, we hide the record and set the overflow flag to true // If the number of records that overlap in a single hour is more than 4, we hide the record and set the overflow flag to true
// We also keep track of the number of records that overflow // We also keep track of the number of records that overflow
if (overlaps[dateKey][hourKey].id.length > 4) { if (overlaps[dateKey][hourKey].id.length > 4) {
overlaps[dateKey][hourKey].overflow = true overlaps[dateKey][hourKey].overflow = true
style.display = 'none' style.display = 'none'
overlaps[dateKey][hourKey].overflowCount += 1 overlaps[dateKey][hourKey].overflowCount += 1
}
// TODO: dayIndex is not calculated perfectly
// Should revisit this part in next iteration
let dayIndex = dayjs(dateKey).day() - 1
if (dayIndex === -1) {
dayIndex = 6
}
startDate = startDate.add(1, 'minute')
} }
// TODO: dayIndex is not calculated perfectly let dayIndex = ogStartDate.day() - 1
// Should revisit this part in next iteration
let dayIndex = dayjs(dateKey).day() - 1
if (dayIndex === -1) { if (dayIndex === -1) {
dayIndex = 6 dayIndex = 6
} }
const hourKey = ogStartDate.format('HH:mm')
// We calculate the index of the hour in the day and set the top and height of the record // We calculate the index of the hour in the day and set the top and height of the record
const hourIndex = Math.min( const hourIndex = Math.min(
Math.max( Math.max(
datesHours.value[dayIndex].findIndex((h) => h.startOf('hour').format('HH:mm') === hourKey), datesHours.value[dayIndex]?.findIndex((h) => h.startOf('hour').format('HH:mm') === hourKey),
0, 0,
), ),
23, 23,
) )
const minutes = ogStartDate.minute() + ogStartDate.hour() * 60
const topPx = (minutes * perHeight) / 60
style = { style = {
...style, ...style,
top: `${hourIndex * perHeight - hourIndex - hourIndex * 0.15}px`, top: `${topPx - hourIndex - hourIndex * 0.15 + 0.7}px`,
height: `${perHeight - 2}px`, height: `${perHeight - 4}px`,
} }
recordsToDisplay.push({ recordsToDisplay.push({
@ -332,14 +375,14 @@ const recordsAcrossAllRange = computed<{
overlapIndex = Math.max(overlapIndex, overlaps[dateKey][hours].id.indexOf(record.rowMeta.id!)) overlapIndex = Math.max(overlapIndex, overlaps[dateKey][hours].id.indexOf(record.rowMeta.id!))
} }
} }
const spacing = 1 const spacing = 0.1
const widthPerRecord = (100 - spacing * (maxOverlaps - 1)) / maxOverlaps / 7 const widthPerRecord = (100 - spacing * (maxOverlaps - 1)) / maxOverlaps / 7
const leftPerRecord = widthPerRecord * overlapIndex const leftPerRecord = widthPerRecord * overlapIndex
record.rowMeta.style = { record.rowMeta.style = {
...record.rowMeta.style, ...record.rowMeta.style,
left: `calc(${dayIndex * perWidth}px + ${leftPerRecord}%)`, left: `calc(${dayIndex * perWidth}px + ${leftPerRecord}% )`,
width: `calc(${widthPerRecord}%)`, width: `calc(${widthPerRecord - 0.1}%)`,
} }
return record return record
}) })
@ -483,7 +526,7 @@ const calculateNewRow = (
const { scrollHeight } = container.value const { scrollHeight } = container.value
const percentX = (event.clientX - left - window.scrollX) / width const percentX = (event.clientX - left - window.scrollX) / width
const percentY = (event.clientY - top + container.value.scrollTop) / scrollHeight const percentY = (event.clientY - top + container.value.scrollTop - 36.8) / scrollHeight
const fromCol = dragRecord.value.rowMeta.range?.fk_from_col const fromCol = dragRecord.value.rowMeta.range?.fk_from_col
const toCol = dragRecord.value.rowMeta.range?.fk_to_col const toCol = dragRecord.value.rowMeta.range?.fk_to_col
@ -493,7 +536,9 @@ const calculateNewRow = (
const day = Math.max(0, Math.min(6, Math.floor(percentX * 7))) const day = Math.max(0, Math.min(6, Math.floor(percentX * 7)))
const hour = Math.max(0, Math.min(23, Math.floor(percentY * 24))) const hour = Math.max(0, Math.min(23, Math.floor(percentY * 24)))
const newStartDate = dayjs(selectedDateRange.value.start).add(day, 'day').add(hour, 'hour') const minutes = Math.round(((percentY * 24 * 60) % 60) / 15) * 15
const newStartDate = dayjs(selectedDateRange.value.start).add(day, 'day').add(hour, 'hour').add(minutes, 'minute')
if (!newStartDate) return { newRow: null, updatedProperty: [] } if (!newStartDate) return { newRow: null, updatedProperty: [] }
let endDate let endDate
@ -552,9 +597,9 @@ const onDrag = (event: MouseEvent) => {
const scrollBottomThreshold = 20 const scrollBottomThreshold = 20
if (event.clientY > containerRect.bottom - scrollBottomThreshold) { if (event.clientY > containerRect.bottom - scrollBottomThreshold) {
scrollContainer.value.scrollTop += 10 scrollContainer.value.scrollTop += 20
} else if (event.clientY < containerRect.top + scrollBottomThreshold) { } else if (event.clientY < containerRect.top + scrollBottomThreshold) {
scrollContainer.value.scrollTop -= 10 scrollContainer.value.scrollTop -= 20
} }
calculateNewRow(event) calculateNewRow(event)
@ -657,6 +702,36 @@ const viewMore = (hour: dayjs.Dayjs) => {
selectedTime.value = hour selectedTime.value = hour
showSideMenu.value = true showSideMenu.value = true
} }
const isOverflowAcrossHourRange = (hour: dayjs.Dayjs) => {
let startOfHour = hour.startOf('hour')
const endOfHour = hour.endOf('hour')
const ids: Array<string> = []
let isOverflow = false
let overflowCount = 0
while (startOfHour.isBefore(endOfHour, 'minute')) {
const dateKey = startOfHour.format('YYYY-MM-DD')
const hourKey = startOfHour.format('HH:mm')
if (recordsAcrossAllRange.value?.count?.[dateKey]?.[hourKey]?.overflow) {
isOverflow = true
recordsAcrossAllRange.value?.count?.[dateKey]?.[hourKey]?.id.forEach((id) => {
if (!ids.includes(id)) {
ids.push(id)
overflowCount += 1
}
})
}
startOfHour = startOfHour.add(1, 'minute')
}
overflowCount = overflowCount > 4 ? overflowCount - 4 : 0
return { isOverflow, overflowCount }
}
</script> </script>
<template> <template>
@ -673,7 +748,7 @@ const viewMore = (hour: dayjs.Dayjs) => {
:class="{ :class="{
'text-brand-500': date[0].isSame(dayjs(), 'date'), 'text-brand-500': date[0].isSame(dayjs(), 'date'),
}" }"
class="w-1/7 text-center text-sm text-gray-500 w-full py-1 border-gray-200 last:border-r-0 border-b-0 border-l-1 border-r-0 bg-gray-50" class="w-1/7 text-center text-sm text-gray-500 w-full py-1 border-gray-100 last:border-r-0 border-b-0 border-l-1 border-r-0 bg-gray-50"
> >
{{ dayjs(date[0]).format('DD ddd') }} {{ dayjs(date[0]).format('DD ddd') }}
</div> </div>
@ -688,14 +763,14 @@ const viewMore = (hour: dayjs.Dayjs) => {
</div> </div>
</div> </div>
<div ref="container" class="absolute ml-16 flex w-[calc(100%-64px)]"> <div ref="container" class="absolute ml-16 flex w-[calc(100%-64px)]">
<div v-for="(date, index) in datesHours" :key="index" class="h-full w-1/7" data-testid="nc-calendar-week-day"> <div v-for="(date, index) in datesHours" :key="index" class="h-full w-1/7 mt-7.1" data-testid="nc-calendar-week-day">
<div <div
v-for="(hour, hourIndex) in date" v-for="(hour, hourIndex) in date"
:key="hourIndex" :key="hourIndex"
:class="{ :class="{
'border-1 !border-brand-500 bg-gray-50': hour.isSame(selectedTime, 'hour'), 'border-1 !border-brand-500 bg-gray-50': hour.isSame(selectedTime, 'hour'),
}" }"
class="text-center relative first:mt-7.1 h-20 text-sm text-gray-500 w-full hover:bg-gray-50 py-1 border-transparent border-1 border-x-gray-200 border-t-gray-200" class="text-center relative h-20 text-sm text-gray-500 w-full hover:bg-gray-50 py-1 border-transparent border-1 border-x-gray-100 border-t-gray-100"
data-testid="nc-calendar-week-hour" data-testid="nc-calendar-week-hour"
@click=" @click="
() => { () => {
@ -705,7 +780,7 @@ const viewMore = (hour: dayjs.Dayjs) => {
" "
> >
<NcButton <NcButton
v-if="recordsAcrossAllRange?.count?.[hour.format('YYYY-MM-DD')]?.[hour.format('HH:mm')]?.overflow" v-if="isOverflowAcrossHourRange(hour).isOverflow"
class="!absolute bottom-1 text-center w-15 ml-auto inset-x-0 z-3 text-gray-500" class="!absolute bottom-1 text-center w-15 ml-auto inset-x-0 z-3 text-gray-500"
size="xxsmall" size="xxsmall"
type="secondary" type="secondary"
@ -713,7 +788,7 @@ const viewMore = (hour: dayjs.Dayjs) => {
> >
<span class="text-xs"> <span class="text-xs">
+ +
{{ recordsAcrossAllRange?.count[hour.format('YYYY-MM-DD')][hour.format('HH:mm')]?.overflowCount }} {{ isOverflowAcrossHourRange(hour).overflowCount }}
more more
</span> </span>
</NcButton> </NcButton>
@ -746,27 +821,23 @@ const viewMore = (hour: dayjs.Dayjs) => {
@resize-start="onResizeStart" @resize-start="onResizeStart"
> >
<template v-if="!isRowEmpty(record, displayField)"> <template v-if="!isRowEmpty(record, displayField)">
<div <LazySmartsheetCalendarCell
:class="{ v-if="!isRowEmpty(record, displayField!)"
'!mt-2': displayField!.uidt === UITypes.SingleLineText, v-model="record.row[displayField!.title!]"
'!mt-1': displayField!.uidt === UITypes.MultiSelect || displayField!.uidt === UITypes.SingleSelect, :bold="getFieldStyle(displayField).bold"
}" :column="displayField"
> :italic="getFieldStyle(displayField).italic"
<LazySmartsheetVirtualCell :underline="getFieldStyle(displayField).underline"
v-if="isVirtualCol(displayField!)" />
v-model="record.row[displayField!.title!]" </template>
:column="displayField" <template v-for="(field, id) in fieldsWithoutDisplay" :key="id">
:row="record" <LazySmartsheetCalendarCell
/> v-model="record.row[field!.title!]"
:bold="getFieldStyle(field).bold"
<LazySmartsheetCell :column="field"
v-else :italic="getFieldStyle(field).italic"
v-model="record.row[displayField!.title!]" :underline="getFieldStyle(field).underline"
:column="displayField" />
:edit-enabled="false"
:read-only="true"
/>
</div>
</template> </template>
</LazySmartsheetCalendarVRecordCard> </LazySmartsheetCalendarVRecordCard>
</LazySmartsheetRow> </LazySmartsheetRow>

15
packages/nc-gui/components/smartsheet/calendar/index.vue

@ -41,6 +41,7 @@ provide(IsKanbanInj, ref(false))
provide(IsCalendarInj, ref(true)) provide(IsCalendarInj, ref(true))
const { const {
activeCalendarView,
calendarRange, calendarRange,
calDataType, calDataType,
loadCalendarMeta, loadCalendarMeta,
@ -53,7 +54,6 @@ const {
pageDate, pageDate,
showSideMenu, showSideMenu,
selectedDateRange, selectedDateRange,
activeCalendarView,
paginateCalendarView, paginateCalendarView,
} = useCalendarViewStoreOrThrow() } = useCalendarViewStoreOrThrow()
@ -140,6 +140,11 @@ const goToToday = () => {
start: dayjs().startOf('week'), start: dayjs().startOf('week'),
end: dayjs().endOf('week'), end: dayjs().endOf('week'),
} }
document?.querySelector('.nc-calendar-today')?.scrollIntoView({
behavior: 'smooth',
block: 'center',
})
} }
const headerText = computed(() => { const headerText = computed(() => {
@ -181,8 +186,8 @@ const headerText = computed(() => {
</NcTooltip> </NcTooltip>
<NcDropdown v-model:visible="calendarRangeDropdown" :auto-close="false" :trigger="['click']"> <NcDropdown v-model:visible="calendarRangeDropdown" :auto-close="false" :trigger="['click']">
<NcButton :class="{ '!w-24': activeCalendarView === 'year' }" class="w-45" full-width size="small" type="secondary"> <NcButton :class="{ '!w-22': activeCalendarView === 'year' }" class="w-45" full-width size="small" type="secondary">
<div class="flex w-full px-3 py-1 w-full items-center justify-between"> <div class="flex px-2 w-full items-center justify-between">
<span class="font-bold text-center text-brand-500" data-testid="nc-calendar-active-date">{{ headerText }}</span> <span class="font-bold text-center text-brand-500" data-testid="nc-calendar-active-date">{{ headerText }}</span>
<component :is="iconMap.arrowDown" class="h-4 w-4 text-gray-700" /> <component :is="iconMap.arrowDown" class="h-4 w-4 text-gray-700" />
</div> </div>
@ -237,7 +242,9 @@ const headerText = computed(() => {
type="secondary" type="secondary"
@click="goToToday" @click="goToToday"
> >
{{ $t('activity.goToToday') }} <span class="text-gray-700">
{{ $t('activity.goToToday') }}
</span>
</NcButton> </NcButton>
<span class="opacity-0" data-testid="nc-active-calendar-view"> <span class="opacity-0" data-testid="nc-active-calendar-view">
{{ activeCalendarView }} {{ activeCalendarView }}

293
packages/nc-gui/components/smartsheet/form/LimitOptions.vue

@ -0,0 +1,293 @@
<script setup lang="ts">
import Draggable from 'vuedraggable'
import tinycolor from 'tinycolor2'
import type { ColumnType, SelectOptionType, SelectOptionsType, UserFieldRecordType } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import type { FormFieldsLimitOptionsType } from '~/lib'
import { MetaInj, iconMap } from '#imports'
const props = defineProps<{
modelValue: FormFieldsLimitOptionsType[]
column: ColumnType
}>()
const emit = defineEmits(['update:modelValue'])
const meta = inject(MetaInj)!
const column = toRef(props, 'column')
const basesStore = useBases()
const { basesUser } = storeToRefs(basesStore)
const baseUsers = computed(() => (meta.value.base_id ? basesUser.value.get(meta.value.base_id) || [] : []))
const searchQuery = ref('')
const drag = ref(false)
const vModel = computed({
get: () => {
let order = 1
const limitOptionsById =
(props.modelValue || []).reduce((o: Record<string, FormFieldsLimitOptionsType>, f: FormFieldsLimitOptionsType) => {
if (order < (f?.order ?? 0)) {
order = f.order
}
return {
...o,
[f.id]: f,
}
}, {} as Record<string, FormFieldsLimitOptionsType>) ?? {}
if (UITypes.User === column.value.uidt) {
const collaborators = ((baseUsers.value || []) as UserFieldRecordType[])
.filter((user) => !user?.deleted)
.map((user: any) => ({
id: user.id,
email: user.email,
display_name: user.display_name,
order: user.id && limitOptionsById[user.id] ? limitOptionsById[user.id]?.order ?? user.order : order++,
show: user.id && limitOptionsById[user.id] ? limitOptionsById[user.id]?.show : !(props.modelValue || []).length,
}))
.sort((a, b) => a.order - b.order)
if ((props.modelValue || []).length !== collaborators.length) {
emit(
'update:modelValue',
collaborators.map((o) => ({ id: o.id, order: o.order, show: o.show })),
)
}
return collaborators
} else if ([UITypes.SingleSelect, UITypes.MultiSelect].includes(column.value.uidt as UITypes)) {
const updateModelValue = ((column.value.colOptions as SelectOptionsType)?.options || [])
.map((c) => {
return {
...c,
order: c.id && limitOptionsById[c.id] ? limitOptionsById[c.id]?.order ?? c.order : order++,
show: c.id && limitOptionsById[c.id] ? limitOptionsById[c.id]?.show : !(props.modelValue || []).length,
} as SelectOptionType & { show?: boolean }
})
.sort((a, b) => {
if (a.order !== undefined && b.order !== undefined) {
return a.order - b.order
}
return 0
})
if ((props.modelValue || []).length !== ((column.value.colOptions as SelectOptionsType)?.options || []).length) {
emit(
'update:modelValue',
updateModelValue.map((o) => ({ id: o.id, order: o.order, show: o.show })),
)
}
return updateModelValue
}
return []
},
set: (val) => {
emit(
'update:modelValue',
val.map((o) => ({ id: o.id, order: o.order, show: o.show })),
)
},
})
async function onMove(_event: { moved: { newIndex: number; oldIndex: number; element: any } }) {
const {
moved: { newIndex = 0, oldIndex = 0, element },
} = _event
let nextOrder: number
// set new order value based on the new order of the items
if (!vModel.value.length || vModel.value.length === 1) {
nextOrder = 1
} else if (vModel.value.length - 1 === newIndex) {
// If moving to the end, set nextOrder greater than the maximum order in the list
nextOrder = Math.max(...vModel.value.map((item) => item?.order ?? 0)) + 1
} else if (newIndex === 0) {
// If moving to the beginning, set nextOrder smaller than the minimum order in the list
nextOrder = Math.min(...vModel.value.map((item) => item?.order ?? 0)) / 2
} else {
nextOrder =
(parseFloat(String(vModel.value[newIndex - 1]?.order ?? 0)) + parseFloat(String(vModel.value[newIndex + 1]?.order ?? 0))) /
2
}
const _nextOrder = !isNaN(Number(nextOrder)) ? nextOrder : oldIndex
element.order = _nextOrder
vModel.value = [...vModel.value]
}
</script>
<template>
<div class="w-full h-full nc-col-select-option nc-form-scrollbar">
<div v-if="vModel.length > 12">
<a-input
v-model:value="searchQuery"
class="!h-9 !px-3 !py-1 !rounded-lg mb-2"
:placeholder="`${$t('placeholder.searchOptions')}...`"
name="nc-form-field-limit-option-search-input"
data-testid="nc-form-field-limit-option-search-input"
>
<template #prefix>
<GeneralIcon icon="search" class="mr-2 h-4 w-4 text-gray-500 group-hover:text-black" />
</template>
<template #suffix>
<GeneralIcon
v-if="searchQuery.length > 0"
icon="close"
class="ml-2 h-4 w-4 text-gray-500 group-hover:text-black"
data-testid="nc-form-field-clear-search"
@click="searchQuery = ''"
/>
</template>
</a-input>
</div>
<Draggable
v-if="vModel.length"
:model-value="vModel"
item-key="id"
handle=".nc-child-draggable-icon"
ghost-class="nc-form-field-limit-option-ghost"
class="rounded-lg border-1 border-gray-200 !max-h-[224px] overflow-y-auto nc-form-scrollbar"
@change="onMove($event)"
@start="drag = true"
@end="drag = false"
>
<template #item="{ element }">
<div
v-if="
column.uidt === UITypes.User
? (element?.display_name?.trim() || element?.email)?.toLowerCase().includes(searchQuery.toLowerCase())
: element.title?.toLowerCase().includes(searchQuery.toLowerCase())
"
:key="element.id"
class="w-full h-10 px-2 py-1.5 flex flex-row items-center gap-3 border-b-1 last:border-none border-gray-200"
:class="[
`nc-form-field-${column.title?.replaceAll(' ', '')}-limit-option-${element.title?.replaceAll(' ', '')}`,
`${element.show ? 'hover:bg-gray-50' : 'bg-gray-100'}`,
]"
:data-testid="`nc-form-field-${column.title?.replaceAll(' ', '')}-limit-option-${element.title?.replaceAll(' ', '')}`"
>
<component :is="iconMap.drag" class="nc-child-draggable-icon flex-none cursor-move !h-4 !w-4 text-gray-600" />
<div
@click="
() => {
element.show = !element.show
vModel = [...vModel]
}
"
>
<component
:is="element.show ? iconMap.eye : iconMap.eyeSlash"
class="flex-none cursor-pointer !h-4 !w-4 text-gray-600"
/>
</div>
<a-tag v-if="column.uidt === UITypes.User" class="rounded-tag max-w-[calc(100%_-_70px)] !pl-0" color="'#ccc'">
<span
:style="{
'color': tinycolor.isReadable('#ccc' || '#ccc', '#fff', { level: 'AA', size: 'large' })
? '#fff'
: tinycolor.mostReadable('#ccc' || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px',
}"
class="flex items-stretch gap-2"
>
<div>
<GeneralUserIcon
size="auto"
:name="element.display_name?.trim() ? element.display_name?.trim() : ''"
:email="element.email"
class="!text-[0.65rem]"
/>
</div>
<NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title>
{{ element.display_name?.trim() || element?.email }}
</template>
<span
class="text-ellipsis overflow-hidden"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ element.display_name?.trim() || element?.email }}
</span>
</NcTooltip>
</span>
</a-tag>
<a-tag v-else class="rounded-tag max-w-[calc(100%_-_70px)]" :color="element.color">
<span
:style="{
'color': tinycolor.isReadable(element.color || '#ccc', '#fff', { level: 'AA', size: 'large' })
? '#fff'
: tinycolor.mostReadable(element.color || '#ccc', ['#0b1d05', '#fff']).toHex8String(),
'font-size': '13px',
}"
>
<NcTooltip class="truncate max-w-full" show-on-truncate-only>
<template #title>
{{ element.title }}
</template>
<span
class="text-ellipsis overflow-hidden"
:style="{
wordBreak: 'keep-all',
whiteSpace: 'nowrap',
display: 'inline',
}"
>
{{ element.title }}
</span>
</NcTooltip>
</span>
</a-tag>
</div>
</template>
<template v-if="!vModel.length" #footer
><div class="px-0.5 py-2 text-gray-500 text-center">{{ $t('title.noOptionsFound') }}</div></template
>
<template
v-else-if="
vModel.length &&
searchQuery &&
!vModel?.filter((element) => {
return column.uidt === UITypes.User
? (element?.display_name?.trim() || element?.email)?.toLowerCase().includes(searchQuery.toLowerCase())
: element.title?.toLowerCase().includes(searchQuery.toLowerCase())
})?.length
"
#footer
>
<div class="px-0.5 py-2 text-gray-500 text-center">{{ $t('title.noOptionsFound') }} with title `{{ searchQuery }}`</div>
</template>
</Draggable>
</div>
</template>
<style scoped lang="scss">
.nc-form-scrollbar {
@apply scrollbar scrollbar-thin scrollbar-thumb-gray-200 scrollbar-track-transparent;
&::-webkit-scrollbar-thumb:hover {
@apply !scrollbar-thumb-gray-300;
}
}
.rounded-tag {
@apply py-0 px-[12px] rounded-[12px];
}
:deep(.ant-tag) {
@apply rounded-tag my-[2px];
}
.nc-form-field-limit-option-ghost {
@apply bg-gray-50;
}
</style>

37
packages/nc-gui/components/smartsheet/toolbar/FieldsMenu.vue

@ -50,6 +50,7 @@ const {
saveOrUpdate, saveOrUpdate,
metaColumnById, metaColumnById,
loadViewColumns, loadViewColumns,
toggleFieldStyles,
toggleFieldVisibility, toggleFieldVisibility,
} = useViewColumnsOrThrow() } = useViewColumnsOrThrow()
@ -396,7 +397,41 @@ useMenuCloseOnEsc(open)
</template> </template>
<template #default>{{ field.title }}</template> <template #default>{{ field.title }}</template>
</NcTooltip> </NcTooltip>
<div v-if="activeView.type === ViewTypes.CALENDAR" class="flex mr-2">
<NcButton
:class="{
'!bg-gray-800 !text-white': field.bold,
}"
class="!rounded-r-none"
size="xxsmall"
type="secondary"
@click.stop="toggleFieldStyles(field, 'bold', !field.bold)"
>
<component :is="iconMap.bold" />
</NcButton>
<NcButton
:class="{
'!bg-gray-800 !text-white': field.italic,
}"
class="!rounded-x-none !border-x-0"
size="xxsmall"
type="secondary"
@click.stop="toggleFieldStyles(field, 'italic', !field.italic)"
>
<component :is="iconMap.italic" />
</NcButton>
<NcButton
:class="{
'!bg-gray-800 !text-white': field.underline,
}"
class="!rounded-l-none"
size="xxsmall"
type="secondary"
@click.stop="toggleFieldStyles(field, 'underline', !field.underline)"
>
<component :is="iconMap.underline" />
</NcButton>
</div>
<NcSwitch :checked="field.show" :disabled="field.isViewEssentialField" @change="$t('a:fields:show-hide')" /> <NcSwitch :checked="field.show" :disabled="field.isViewEssentialField" @change="$t('a:fields:show-hide')" />
</div> </div>

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

@ -188,7 +188,7 @@ const linkedShortcuts = (e: KeyboardEvent) => {
try { try {
e.target?.previousElementSibling?.focus() e.target?.previousElementSibling?.focus()
} catch (e) {} } catch (e) {}
} else if (e.key !== 'Tab' && e.key !== 'Shift' && e.key !== 'Enter' && e.key !== ' ') { } else if (!expandedFormDlg.value && e.key !== 'Tab' && e.key !== 'Shift' && e.key !== 'Enter' && e.key !== ' ') {
try { try {
filterQueryRef.value?.focus() filterQueryRef.value?.focus()
} catch (e) {} } catch (e) {}
@ -200,6 +200,7 @@ onMounted(() => {
}) })
onUnmounted(() => { onUnmounted(() => {
childrenListPagination.query = ''
window.removeEventListener('keydown', linkedShortcuts) window.removeEventListener('keydown', linkedShortcuts)
}) })
</script> </script>

3
packages/nc-gui/components/virtual-cell/components/ListItems.vue

@ -230,7 +230,7 @@ const linkedShortcuts = (e: KeyboardEvent) => {
try { try {
e.target?.previousElementSibling?.focus() e.target?.previousElementSibling?.focus()
} catch (e) {} } catch (e) {}
} else if (e.key !== 'Tab' && e.key !== 'Shift' && e.key !== 'Enter' && e.key !== ' ') { } else if (!expandedFormDlg.value && e.key !== 'Tab' && e.key !== 'Shift' && e.key !== 'Enter' && e.key !== ' ') {
try { try {
filterQueryRef.value?.focus() filterQueryRef.value?.focus()
} catch (e) {} } catch (e) {}
@ -242,6 +242,7 @@ onMounted(() => {
}) })
onUnmounted(() => { onUnmounted(() => {
childrenExcludedListPagination.query = ''
window.removeEventListener('keydown', linkedShortcuts) window.removeEventListener('keydown', linkedShortcuts)
}) })
</script> </script>

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

@ -211,7 +211,7 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState(
const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value const { fk_grp_col_id, meta: stack_meta } = kanbanMetaData.value
stackMetaObj.value = stack_meta ? JSON.parse(stack_meta as string) : {} stackMetaObj.value = parseProp(stack_meta) || {}
if (stackMetaObj.value && fk_grp_col_id && stackMetaObj.value[fk_grp_col_id]) { if (stackMetaObj.value && fk_grp_col_id && stackMetaObj.value[fk_grp_col_id]) {
// keep the existing order (index of the array) but update the values done outside kanban // keep the existing order (index of the array) but update the values done outside kanban

32
packages/nc-gui/composables/useMultiSelect/convertCellData.ts

@ -1,6 +1,6 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import type { AttachmentType, ColumnType, LinkToAnotherRecordType, SelectOptionsType } from 'nocodb-sdk' import type { AttachmentType, ColumnType, LinkToAnotherRecordType, SelectOptionsType } from 'nocodb-sdk'
import { UITypes, populateUniqueFileName } from 'nocodb-sdk' import { UITypes, getDateFormat, getDateTimeFormat, populateUniqueFileName } from 'nocodb-sdk'
import type { AppInfo } from '~/composables/useGlobal' import type { AppInfo } from '~/composables/useGlobal'
import { isBt, isMm, parseProp } from '#imports' import { isBt, isMm, parseProp } from '#imports'
@ -55,30 +55,24 @@ export default function convertCellData(
if (strval === 'false' || strval === '0' || strval === '') return false if (strval === 'false' || strval === '0' || strval === '') return false
} }
return null return null
case UITypes.Date: { case UITypes.Date:
const parsedDate = dayjs(value, parseProp(column?.meta)?.date_format ?? 'YYYY-MM-DD')
if (!parsedDate.isValid()) {
if (isMultiple) {
return null
} else {
throw new Error('Not a valid date')
}
}
return parsedDate.format('YYYY-MM-DD')
}
case UITypes.DateTime: { case UITypes.DateTime: {
const parsedDateTime = dayjs( let parsedDateOrDateTime = dayjs(value, getDateTimeFormat(value))
value,
`${parseProp(column?.meta)?.date_format ?? 'YYYY-MM-DD'} ${parseProp(column?.meta)?.time_format ?? 'HH:mm'}`, if (!parsedDateOrDateTime.isValid()) {
) parsedDateOrDateTime = dayjs(value, getDateFormat(value))
if (!parsedDateTime.isValid()) { }
if (!parsedDateOrDateTime.isValid()) {
if (isMultiple) { if (isMultiple) {
return null return null
} else { } else {
throw new Error('Not a valid datetime value') throw new Error(`Not a valid '${to}' value`)
} }
} }
return parsedDateTime.utc().format('YYYY-MM-DD HH:mm:ssZ') return to === UITypes.Date
? parsedDateOrDateTime.format('YYYY-MM-DD')
: parsedDateOrDateTime.utc().format('YYYY-MM-DD HH:mm:ssZ')
} }
case UITypes.Time: { case UITypes.Time: {
let parsedTime = dayjs(value) let parsedTime = dayjs(value)

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

@ -785,7 +785,7 @@ export function useMultiSelect(
if (columnObj.uidt === UITypes.LongText) { if (columnObj.uidt === UITypes.LongText) {
if (rowObj.row[columnObj.title] === '<br />') { if (rowObj.row[columnObj.title] === '<br />') {
rowObj.row[columnObj.title] = e.key rowObj.row[columnObj.title] = e.key
} else { } else if (parseProp(columnObj.meta).richMode) {
rowObj.row[columnObj.title] = rowObj.row[columnObj.title] ? rowObj.row[columnObj.title] + e.key : e.key rowObj.row[columnObj.title] = rowObj.row[columnObj.title] ? rowObj.row[columnObj.title] + e.key : e.key
} }
} else { } else {

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

@ -109,6 +109,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
columns.value = viewMeta.model?.columns?.map((c) => ({ columns.value = viewMeta.model?.columns?.map((c) => ({
...c, ...c,
meta: { ...parseProp(fieldById[c.id].meta), ...parseProp(c.meta) },
description: fieldById[c.id].description, description: fieldById[c.id].description,
})) }))

12
packages/nc-gui/composables/useViewColumns.ts

@ -1,8 +1,8 @@
import { ViewTypes, isHiddenCol, isSystemColumn } from 'nocodb-sdk'
import type { ColumnType, GridColumnReqType, GridColumnType, MapType, TableType, ViewType } from 'nocodb-sdk' import type { ColumnType, GridColumnReqType, GridColumnType, MapType, TableType, ViewType } from 'nocodb-sdk'
import { ViewTypes, isHiddenCol, isSystemColumn } from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import { computed, ref, storeToRefs, useBase, useNuxtApp, useRoles, useUndoRedo, watch } from '#imports'
import type { Field } from '#imports' import type { Field } from '#imports'
import { computed, ref, storeToRefs, useBase, useNuxtApp, useRoles, useUndoRedo, watch } from '#imports'
const [useProvideViewColumns, useViewColumns] = useInjectionState( const [useProvideViewColumns, useViewColumns] = useInjectionState(
( (
@ -278,6 +278,13 @@ const [useProvideViewColumns, useViewColumns] = useInjectionState(
saveOrUpdate(field, fieldIndex) saveOrUpdate(field, fieldIndex)
} }
const toggleFieldStyles = (field: any, style: 'underline' | 'bold' | 'italic', status: boolean) => {
const fieldIndex = fields.value?.findIndex((f) => f.fk_column_id === field.fk_column_id)
if (!fieldIndex && fieldIndex !== 0) return
field[style] = status
saveOrUpdate(field, fieldIndex, true)
}
// reload view columns when active view changes // reload view columns when active view changes
// or when columns changes(delete/add) // or when columns changes(delete/add)
watch( watch(
@ -351,6 +358,7 @@ const [useProvideViewColumns, useViewColumns] = useInjectionState(
showSystemFields, showSystemFields,
metaColumnById, metaColumnById,
toggleFieldVisibility, toggleFieldVisibility,
toggleFieldStyles,
isViewColumnsLoading, isViewColumnsLoading,
updateGridViewColumn, updateGridViewColumn,
gridViewCols, gridViewCols,

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

@ -297,6 +297,7 @@ export function useViewData(
fk_column_id: c.id, fk_column_id: c.id,
fk_view_id: viewMeta.value?.id, fk_view_id: viewMeta.value?.id,
...(fieldById[c.id!] ? fieldById[c.id!] : {}), ...(fieldById[c.id!] ? fieldById[c.id!] : {}),
meta: { ...parseProp(fieldById[c.id!]?.meta), ...parseProp(c.meta) }, // TODO: discuss with @pranav
order: (fieldById[c.id!] && fieldById[c.id!].order) || order++, order: (fieldById[c.id!] && fieldById[c.id!].order) || order++,
id: fieldById[c.id!] && fieldById[c.id!].id, id: fieldById[c.id!] && fieldById[c.id!].id,
})) }))

44
packages/nc-gui/lang/ar.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "الوصول مقيد بكلمة مرور", "afterEnablePwd": "الوصول مقيد بكلمة مرور",
"privateLink": "تتم مشاركة هذا العرض عبر رابط خاص", "privateLink": "تتم مشاركة هذا العرض عبر رابط خاص",
"privateLinkAdditionalInfo": "يمكن للأشخاص الذين لديهم رابط خاص رؤية الخلايا المرئية فقط في طريقة العرض هذه", "privateLinkAdditionalInfo": "يمكن للأشخاص الذين لديهم رابط خاص رؤية الخلايا المرئية فقط في طريقة العرض هذه",
"afterFormSubmitted": "بعد تقديم النموذج", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "الوصول للمشروع عبر", "apiOptions": "الوصول للمشروع عبر",
"submitAnotherForm": "إظهار زر 'إرسال نموذج آخر'", "submitAnotherForm": "إظهار زر 'إرسال نموذج آخر'",
"showBlankForm": "إظهار نموذج فارغ بعد 5 ثوان", "showBlankForm": "إظهار نموذج فارغ بعد 5 ثوان",
"emailForm": "راسلني بالبريد عبر", "emailForm": "راسلني بالبريد عبر",
"showSysFields": "إظهار حقول النظام", "showSysFields": "إظهار حقول النظام",
"filterAutoApply": "تطبيق تلقائي", "filterAutoApply": "تطبيق تلقائي",
"showMessage": "اعرض هذه الرسالة", "formDisplayMessage": "Display Message",
"viewNotShared": "لم تتم مشاركة العرض الحالي!", "viewNotShared": "لم تتم مشاركة العرض الحالي!",
"showAllViews": "عرض جميع المشاهدات المشتركة لهذا الجدول", "showAllViews": "عرض جميع المشاهدات المشتركة لهذا الجدول",
"collabView": "يمكن للمتعاونين الذين لديهم أذونات تحرير أو أعلى تغيير تكوين العرض.", "collabView": "يمكن للمتعاونين الذين لديهم أذونات تحرير أو أعلى تغيير تكوين العرض.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "تصدير البيانات الوصفية للمشروع بنجاح", "exportMetadata": "تصدير البيانات الوصفية للمشروع بنجاح",

44
packages/nc-gui/lang/bn_IN.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "অস পসওযড সবদধ", "afterEnablePwd": "অস পসওযড সবদধ",
"privateLink": "এই ভিউটি একটিযকিগত লির মযমগ কর হয", "privateLink": "এই ভিউটি একটিযকিগত লির মযমগ কর হয",
"privateLinkAdditionalInfo": "বযকিগত লিকযত লবল এই দষগিযমন দখত", "privateLinkAdditionalInfo": "বযকিগত লিকযত লবল এই দষগিযমন দখত",
"afterFormSubmitted": "ফরম জমওযর পর", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "মযমস পরকলপ", "apiOptions": "মযমস পরকলপ",
"submitAnotherForm": "অনয ফরম জমিন' বমটিন", "submitAnotherForm": "অনয ফরম জমিন' বমটিন",
"showBlankForm": "5 সড পর একটি ফরম দন", "showBlankForm": "5 সড পর একটি ফরম দন",
"emailForm": "আম ইমল করন", "emailForm": "আম ইমল করন",
"showSysFields": "সিম করগিন", "showSysFields": "সিম করগিন",
"filterAutoApply": "অটরযগ", "filterAutoApply": "অটরযগ",
"showMessage": "এই বি", "formDisplayMessage": "Display Message",
"viewNotShared": "বরতমন ভিউ ভগ কর হয!", "viewNotShared": "বরতমন ভিউ ভগ কর হয!",
"showAllViews": "এই টির সমসত ভগ কর দরশন দন", "showAllViews": "এই টির সমসত ভগ কর দরশন দন",
"collabView": "সমদন অনমতি উচচতর সহ সহযিউ কনফিশন পরিবরতন করত।", "collabView": "সমদন অনমতি উচচতর সহ সহযিউ কনফিশন পরিবরতন করত।",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "পরকলপ ম সফলভ রফতি কর", "exportMetadata": "পরকলপ ম সফলভ রফতি কর",

44
packages/nc-gui/lang/cs.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Přepnout Mobilní režim", "toggleMobileMode": "Přepnout Mobilní režim",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Přístup je omezen heslem", "afterEnablePwd": "Přístup je omezen heslem",
"privateLink": "Tento pohled je sdílen prostřednictvím soukromého odkazu", "privateLink": "Tento pohled je sdílen prostřednictvím soukromého odkazu",
"privateLinkAdditionalInfo": "Lidé se soukromým odkazem mohou vidět pouze buňky viditelné v tomto zobrazení.", "privateLinkAdditionalInfo": "Lidé se soukromým odkazem mohou vidět pouze buňky viditelné v tomto zobrazení.",
"afterFormSubmitted": "Po odeslání formuláře", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Přístup k projektu přes", "apiOptions": "Přístup k projektu přes",
"submitAnotherForm": "Zobrazit tlačítko \"Odeslat další formulář", "submitAnotherForm": "Zobrazit tlačítko \"Odeslat další formulář",
"showBlankForm": "Zobrazení prázdného formuláře po 5 sekundách", "showBlankForm": "Zobrazení prázdného formuláře po 5 sekundách",
"emailForm": "Pošlete mi e-mail na adresu", "emailForm": "Pošlete mi e-mail na adresu",
"showSysFields": "Zobrazit systémová pole", "showSysFields": "Zobrazit systémová pole",
"filterAutoApply": "Automatické použití", "filterAutoApply": "Automatické použití",
"showMessage": "Zobrazit tuto zprávu", "formDisplayMessage": "Display Message",
"viewNotShared": "Současný pohled není sdílený!", "viewNotShared": "Současný pohled není sdílený!",
"showAllViews": "Zobrazit všechna sdílená zobrazení této tabulky", "showAllViews": "Zobrazit všechna sdílená zobrazení této tabulky",
"collabView": "Spolupracovníci s oprávněním k úpravám nebo vyšším mohou měnit konfiguraci zobrazení.", "collabView": "Spolupracovníci s oprávněním k úpravám nebo vyšším mohou měnit konfiguraci zobrazení.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Úspěšný export metadat projektu", "exportMetadata": "Úspěšný export metadat projektu",

44
packages/nc-gui/lang/da.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Skift Mobil Tilstand", "toggleMobileMode": "Skift Mobil Tilstand",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Adgang er adgangskode begrænset", "afterEnablePwd": "Adgang er adgangskode begrænset",
"privateLink": "Denne visning deles via et privat link", "privateLink": "Denne visning deles via et privat link",
"privateLinkAdditionalInfo": "Folk med privat link kan kun se celler synlige i denne opfattelse", "privateLinkAdditionalInfo": "Folk med privat link kan kun se celler synlige i denne opfattelse",
"afterFormSubmitted": "Efter formularen er indsendt", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Access Project Via.", "apiOptions": "Access Project Via.",
"submitAnotherForm": "Vis 'Indsend en anden formular' -knap", "submitAnotherForm": "Vis 'Indsend en anden formular' -knap",
"showBlankForm": "Vis en blank form efter 5 sekunder", "showBlankForm": "Vis en blank form efter 5 sekunder",
"emailForm": "E-mail mig på", "emailForm": "E-mail mig på",
"showSysFields": "Vis systemfelter", "showSysFields": "Vis systemfelter",
"filterAutoApply": "Auto Application", "filterAutoApply": "Auto Application",
"showMessage": "Vis denne besked", "formDisplayMessage": "Display Message",
"viewNotShared": "Nuværende visning er ikke delt!", "viewNotShared": "Nuværende visning er ikke delt!",
"showAllViews": "Vis alle fælles visninger af denne tabel", "showAllViews": "Vis alle fælles visninger af denne tabel",
"collabView": "Samarbejdspartnere med redigeringstilladelser eller højere kan ændre visningskonfigurationen.", "collabView": "Samarbejdspartnere med redigeringstilladelser eller højere kan ændre visningskonfigurationen.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Project Metadata eksporteres med succes", "exportMetadata": "Project Metadata eksporteres med succes",

44
packages/nc-gui/lang/de.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Mobilen Modus umschalten", "toggleMobileMode": "Mobilen Modus umschalten",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Zugriff ist Passwort-geschützt", "afterEnablePwd": "Zugriff ist Passwort-geschützt",
"privateLink": "Diese Ansicht wird durch einen persönlichen Link geteilt", "privateLink": "Diese Ansicht wird durch einen persönlichen Link geteilt",
"privateLinkAdditionalInfo": "Personen mit einem persönlichen Link können nur Zellen sehen, die in dieser Ansicht angezeigt werden", "privateLinkAdditionalInfo": "Personen mit einem persönlichen Link können nur Zellen sehen, die in dieser Ansicht angezeigt werden",
"afterFormSubmitted": "Nachdem das Formular übermittelt wurde", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Zugriff auf das Projekt via", "apiOptions": "Zugriff auf das Projekt via",
"submitAnotherForm": "Weiteres Formular übermitteln'-Button anzeigen", "submitAnotherForm": "Weiteres Formular übermitteln'-Button anzeigen",
"showBlankForm": "Ein leeres Formular nach 5 Sekunden anzeigen", "showBlankForm": "Ein leeres Formular nach 5 Sekunden anzeigen",
"emailForm": "E-Mail an mich unter", "emailForm": "E-Mail an mich unter",
"showSysFields": "Systemfelder anzeigen", "showSysFields": "Systemfelder anzeigen",
"filterAutoApply": "Automatisch anwenden", "filterAutoApply": "Automatisch anwenden",
"showMessage": "Diese Nachricht anzeigen", "formDisplayMessage": "Display Message",
"viewNotShared": "Aktuelle Ansicht wird nicht geteilt!", "viewNotShared": "Aktuelle Ansicht wird nicht geteilt!",
"showAllViews": "Alle geteilten Ansichten dieser Tabelle anzeigen", "showAllViews": "Alle geteilten Ansichten dieser Tabelle anzeigen",
"collabView": "Mitarbeitern mit Bearbeitungsberechtigung oder höher können die Ansichtenkonfiguration ändern", "collabView": "Mitarbeitern mit Bearbeitungsberechtigung oder höher können die Ansichtenkonfiguration ändern",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Projektmetadaten erfolgreich exportiert", "exportMetadata": "Projektmetadaten erfolgreich exportiert",

32
packages/nc-gui/lang/en.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -422,7 +427,8 @@
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
}, },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here" "selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -685,11 +691,14 @@
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Make changes to field properties by selecting a field from the list" "selectFieldLabel": "Make changes to field properties by selecting a field from the list"
}, },
"appearanceSettings":"Appearance Settings", "appearanceSettings": "Appearance Settings",
"backgroundColor":"Background Color", "backgroundColor": "Background Color",
"hideNocodbBranding":"Hide NocoDB Branding", "hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions", "showOnConditions": "Show on condtions",
"showFieldOnConditionsMet":"Shows field only when conditions are met" "showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit ptions",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range", "noRange": "Calendar view requires a date range",
@ -999,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Looks like you haven’t generated any API tokens yet.", "noTokenCreatedLabel": "Looks like you haven’t generated any API tokens yet.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Fast track your projects by collaborating on them with your team!" "inviteYourTeamLabel": "Fast track your projects by collaborating on them with your team!",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1107,7 +1117,7 @@
"tooLargeFieldEntity": "The field is too large to be converted to {entity}", "tooLargeFieldEntity": "The field is too large to be converted to {entity}",
"roleRequired": "Role required", "roleRequired": "Role required",
"warning": { "warning": {
"calendarNoFields": "Calendar view requires a date or date time field to be setup. Try setting up a calendar view after adding a date / date time field!", "calendarNoFields": "Calendar view requires a date or date time field to be setup. Try setting up a calendar view after adding a date/ date time field!",
"kanbanNoFields": "Kanban view requires a single select field to be setup. Try setting up a kanban view after adding a single select field!", "kanbanNoFields": "Kanban view requires a single select field to be setup. Try setting up a kanban view after adding a single select field!",
"mapNoFields": "Map view requires a geo data field to be setup. Try setting up a map view after adding a geo data field!", "mapNoFields": "Map view requires a geo data field to be setup. Try setting up a map view after adding a geo data field!",
"dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!", "dbValid": "Please make sure database you are trying to connect is valid! This operation can cause schema loss!!",
@ -1294,7 +1304,9 @@
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column", "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}" "upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data", "fetchingCalendarData": "Error fetching calendar data",
@ -1382,7 +1394,7 @@
"theAcceptedFileTypesAreXlsXlsxXlsmOdsOts": "The accepted file types are .xls, .xlsx, .xlsm, .ods, .ots", "theAcceptedFileTypesAreXlsXlsxXlsmOdsOts": "The accepted file types are .xls, .xlsx, .xlsm, .ods, .ots",
"parameterKeyCannotBeEmpty": "Parameter key cannot be empty", "parameterKeyCannotBeEmpty": "Parameter key cannot be empty",
"duplicateParameterKeysAreNotAllowed": "Duplicate parameter keys are not allowed", "duplicateParameterKeysAreNotAllowed": "Duplicate parameter keys are not allowed",
"fieldRequired": "{value} cannot be empty", "fieldRequired": "{value} cannot be empty.",
"projectNotAccessible": "Base not accessible", "projectNotAccessible": "Base not accessible",
"copyToClipboardError": "Failed to copy to clipboard", "copyToClipboardError": "Failed to copy to clipboard",
"pasteFromClipboardError": "Failed to paste from clipboard", "pasteFromClipboardError": "Failed to paste from clipboard",

230
packages/nc-gui/lang/es.json

@ -192,13 +192,18 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Segundos", "seconds": "Segundos",
"paste": "Pegar", "paste": "Pegar",
"restore": "Restaurar" "restore": "Restaurar",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Día",
"week": "Week", "week": "Semana",
"month": "Month", "month": "Mes",
"year": "Year", "year": "Año",
"workspace": "Espacio de trabajo", "workspace": "Espacio de trabajo",
"workspaces": "Espacios de trabajo", "workspaces": "Espacios de trabajo",
"project": "Proyecto", "project": "Proyecto",
@ -305,7 +310,7 @@
"isNotNull": "no es nulo" "isNotNull": "no es nulo"
}, },
"title": { "title": {
"sso": "Authentication (SSO)", "sso": "Autenticación (SSO)",
"docs": "Documentos", "docs": "Documentos",
"forum": "Foro", "forum": "Foro",
"parameter": "Parámetro", "parameter": "Parámetro",
@ -336,7 +341,7 @@
"virtualRelation": "Relación virtual", "virtualRelation": "Relación virtual",
"linkMore": "Enlace más", "linkMore": "Enlace más",
"linkMoreRecords": "Vincular más registros", "linkMoreRecords": "Vincular más registros",
"linkRecords": "Link Records", "linkRecords": "Registros de Enlaces",
"downloadFile": "Descargar archivo", "downloadFile": "Descargar archivo",
"renameTable": "Renombrar tabla", "renameTable": "Renombrar tabla",
"renamingTable": "Renombrar tabla", "renamingTable": "Renombrar tabla",
@ -403,7 +408,7 @@
"findRowByScanningCode": "Find row by scanning a QR or Barcode", "findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Gestión de Token", "tokenManagement": "Gestión de Token",
"addNewToken": "Añadir nuevo token", "addNewToken": "Añadir nuevo token",
"createNewToken": "Create new token", "createNewToken": "Crear nuevo token",
"accountSettings": "Configuración de la cuenta", "accountSettings": "Configuración de la cuenta",
"resetPasswordMenu": "Restablecer contraseña", "resetPasswordMenu": "Restablecer contraseña",
"tokens": "Tokens", "tokens": "Tokens",
@ -421,80 +426,82 @@
"restrict": "Restringir", "restrict": "Restringir",
"setNull": "Establecer NULL", "setNull": "Establecer NULL",
"setDefault": "Establecer por defecto" "setDefault": "Establecer por defecto"
} },
"selectFieldsFromRightPannelToAddHere": "Selecciona los campos del panel derecho para añadirlos aquí",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Seleccionar Año",
"save": "Save", "save": "Guardar",
"cancel": "Cancel", "cancel": "Cancelar",
"metadataUrl": "Metadata URL", "metadataUrl": "URL de metadatos",
"audience-entityId": "Audience/ Entity ID", "audience-entityId": "Audiencia/ Entidad ID",
"redirectUrl": "Redirect URL", "redirectUrl": "URL de redirección",
"oidc": "OpenID Connect (OIDC)", "oidc": "OpenID Connect (OIDC)",
"saml": "Security Assertion Markup Language (SAML)", "saml": "Security Assertion Markup Language (SAML)",
"newProvider": "New Provider", "newProvider": "Nuevo proveedor",
"generalSettings": "General Settings", "generalSettings": "Ajustes Generales",
"ssoSettings": "SSO Settings", "ssoSettings": "Ajustes SSO",
"organizeBy": "Organize by", "organizeBy": "Organizar por",
"previous": "Previous", "previous": "Anterior",
"nextMonth": "Next Month", "nextMonth": "Mes siguiente",
"previousMonth": "Previous Month", "previousMonth": "Mes anterior",
"next": "Next", "next": "Siguiente",
"organiseBy": "Organise by", "organiseBy": "Organizar por",
"heading1": "Encabezado 1", "heading1": "Encabezado 1",
"heading2": "Encabezado 2", "heading2": "Encabezado 2",
"heading3": "Heading 3", "heading3": "Encabezado 3",
"bold": "Bold", "bold": "Negrita",
"italic": "Italic", "italic": "Cursiva",
"underline": "Underline", "underline": "Subrayado",
"strike": "Strike", "strike": "Tachado",
"taskList": "Task List", "taskList": "Lista de Tareas",
"bulletList": "Bullet List", "bulletList": "Lista con viñetas",
"numberedList": "Numbered List", "numberedList": "Lista numerada",
"downloadData": "Download Data", "downloadData": "Descargar Datos",
"blockQuote": "Block Quote", "blockQuote": "Bloque de cita",
"noToken": "No Token", "noToken": "Sin Token",
"tokenLimit": "Only one token per user is allowed", "tokenLimit": "Sólo se permite un token por usuario",
"duplicateAttachment": "File with name {filename} already attached", "duplicateAttachment": "Archivo con el nombre {filename} ya adjuntado",
"viewIdColon": "VIEW ID: {viewId}", "viewIdColon": "VIEW ID: {viewId}",
"toAddress": "To Address", "toAddress": "A Dirección",
"subject": "Subject", "subject": "Asunto",
"body": "Body", "body": "Cuerpo",
"commaSeparatedMobileNumber": "Comma separated Mobile #", "commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name", "headerName": "Nombre del encabezado",
"icon": "Icon", "icon": "Icono",
"max": "Max", "max": "Máximo",
"enableRichText": "Enable Rich Text", "enableRichText": "Activar Texto Enriquecido",
"idColon": "Id:", "idColon": "Id:",
"copiedRecordURL": "Copied Record URL", "copiedRecordURL": "URL del registro copiado",
"copyRecordURL": "Copy Record URL", "copyRecordURL": "Copiar URL de registro",
"duplicateRecord": "Duplicate record", "duplicateRecord": "Duplicar registro",
"binaryEncodingFormat": "Binary encoding format", "binaryEncodingFormat": "Formato de codificación binaria",
"syntax": "Syntax", "syntax": "Sintaxis",
"examples": "Examples", "examples": "Ejemplos",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).", "durationInfo": "Una duración de tiempo en minutos o segundos (por ejemplo, 1:23).",
"addHeader": "Add Header", "addHeader": "Añadir Encabezado",
"enterDefaultUrlOptional": "Enter default URL (Optional)", "enterDefaultUrlOptional": "Introdcir URL predeterminada (Opcional)",
"negative": "Negative", "negative": "Negativo",
"discard": "Discard", "discard": "Descartar",
"default": "Default", "default": "Por defecto",
"defaultNumberPercent": "Default Number (%)", "defaultNumberPercent": "Número por defecto (%)",
"durationFormat": "Duration Format", "durationFormat": "Formato de la duración",
"dateFormat": "Date Format", "dateFormat": "Formato de fecha",
"timeFormat": "Time Format", "timeFormat": "Formato de hora",
"singularLabel": "Singular Label", "singularLabel": "Etiqueta Singular",
"pluralLabel": "Plural Label", "pluralLabel": "Etiqueta Plural",
"selectDateField": "Select a date field", "selectDateField": "Seleccionar un campo de fecha",
"endDateField": "End date field", "endDateField": "Campo fecha de fin",
"optional": "(Optional)", "optional": "(Opcional)",
"clickToMake": "Click to make", "clickToMake": "Pulsar para hacer",
"visibleForRole": "visible for role:", "visibleForRole": "visible para el rol:",
"inUI": "in UI Dashboard", "inUI": "in UI Dashboard",
"projectSettings": "Base Settings", "projectSettings": "Ajustes básicos",
"clickToHide": "Click to hide", "clickToHide": "Clic para ocultar",
"clickToDownload": "Click to download", "clickToDownload": "Clic para descargar",
"forRole": "for role", "forRole": "para el rol",
"clickToCopyViewID": "Click to copy View ID", "clickToCopyViewID": "Clic para copiar View ID",
"viewMode": "Modo solo lectura", "viewMode": "Modo solo lectura",
"searchUsers": "Buscar usuarios", "searchUsers": "Buscar usuarios",
"superAdmin": "Super Admin", "superAdmin": "Super Admin",
@ -528,9 +535,9 @@
"duplicateFormView": "Duplicar vista de formulario", "duplicateFormView": "Duplicar vista de formulario",
"createFormView": "Crear vista de formulario", "createFormView": "Crear vista de formulario",
"duplicateKanbanView": "Duplicar vista Kanban", "duplicateKanbanView": "Duplicar vista Kanban",
"duplicateCalendarView": "Duplicate Calendar View", "duplicateCalendarView": "Duplicar vista de calendario",
"createKanbanView": "Crear vista Kanban", "createKanbanView": "Crear vista Kanban",
"createCalendarView": "Create Calendar View", "createCalendarView": "Crear vista de calendario",
"viewName": "Nombre de la vista", "viewName": "Nombre de la vista",
"viewLink": "Ver enlace", "viewLink": "Ver enlace",
"columnName": "Nombre de columna", "columnName": "Nombre de columna",
@ -683,18 +690,27 @@
"incompleteConfiguration": "Configuración incompleta", "incompleteConfiguration": "Configuración incompleta",
"selectField": "Seleccione un campo", "selectField": "Seleccione un campo",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Ajustes de apariencia",
"backgroundColor": "Color de Fondo",
"hideNocodbBranding": "Ocultar marca NocoDB",
"showOnConditions": "Mostrar en condiciones",
"showFieldOnConditionsMet": "Muestra el campo sólo cuando se cumplen las condiciones",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"goToToday": "Go to Today", "noRange": "La vista del calendario requiere un rango de fechas",
"toggleSidebar": "Toggle Sidebar", "goToToday": "Ir a Hoy",
"addEndDate": "Add end date", "toggleSidebar": "Alternar Barra Lateral",
"withEndDate": "with end date", "addEndDate": "Añadir fecha final",
"calendar": "Calendar", "withEndDate": "con fecha de fin",
"viewSettings": "View settings", "calendar": "Calendario",
"viewSettings": "Ver ajustes",
"googleOAuth": "Google OAuth", "googleOAuth": "Google OAuth",
"registerOIDC": "Register OIDC Identity Provider", "registerOIDC": "Registrar proveedor de identidad OIDC",
"registerSAML": "Register SAML Identity Provider", "registerSAML": "Registrar proveedor de identidad SAML",
"openInANewTab": "Abrir en una nueva pestaña", "openInANewTab": "Abrir en una nueva pestaña",
"copyIFrameCode": "Copiar código IFrame", "copyIFrameCode": "Copiar código IFrame",
"onCondition": "En Condición", "onCondition": "En Condición",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Activar el modo móvil", "toggleMobileMode": "Activar el modo móvil",
"startCommenting": "¡Empieza a comentar!" "startCommenting": "¡Empieza a comentar!",
"clearForm": "Limpiar formulario",
"addFieldFromFormView": "Añadir Campo",
"selectAllFields": "Seleccionar todos los campos"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limitado a una única fuente de datos por el momento", "reachedSourceLimit": "Limitado a una única fuente de datos por el momento",
@ -952,7 +971,7 @@
"selectGroupField": "Seleccione un campo de agrupación", "selectGroupField": "Seleccione un campo de agrupación",
"selectGroupFieldNotFound": "No se encuentra ningún campo de selección único. Por favor, cree uno primero.", "selectGroupFieldNotFound": "No se encuentra ningún campo de selección único. Por favor, cree uno primero.",
"selectGeoField": "Seleccione un campo de datos geográficos", "selectGeoField": "Seleccione un campo de datos geográficos",
"notSelected": "-not selected-", "notSelected": "-no seleccionado-",
"selectGeoFieldNotFound": "No se encuentra ningún campo de datos geográficos. Por favor, cree uno primero.", "selectGeoFieldNotFound": "No se encuentra ningún campo de datos geográficos. Por favor, cree uno primero.",
"password": { "password": {
"enter": "Ingresa la contraseña", "enter": "Ingresa la contraseña",
@ -962,7 +981,7 @@
"confirm": "Confirmar nueva contraseña" "confirm": "Confirmar nueva contraseña"
}, },
"selectAColumnForTheQRCodeValue": "Select a field for the QR code value", "selectAColumnForTheQRCodeValue": "Select a field for the QR code value",
"allowNegativeNumbers": "Allow negative numbers", "allowNegativeNumbers": "Permitir números negativos",
"searchProjectTree": "Buscar tablas", "searchProjectTree": "Buscar tablas",
"searchFields": "Buscar campos", "searchFields": "Buscar campos",
"searchColumn": "Buscar columna {search}", "searchColumn": "Buscar columna {search}",
@ -973,7 +992,7 @@
"filterByEmail": "Filtrar por correo electrónico", "filterByEmail": "Filtrar por correo electrónico",
"filterQuery": "Filtrar consulta", "filterQuery": "Filtrar consulta",
"selectField": "Seleccionar campo", "selectField": "Seleccionar campo",
"precision": "Precision", "precision": "Precisión",
"decimal1": "1.0", "decimal1": "1.0",
"decimal2": "1.00", "decimal2": "1.00",
"decimal3": "1.000", "decimal3": "1.000",
@ -982,21 +1001,22 @@
"decimal6": "1.000000", "decimal6": "1.000000",
"decimal7": "1.0000000", "decimal7": "1.0000000",
"decimal8": "1.00000000", "decimal8": "1.00000000",
"value": "Value", "value": "Valor",
"key": "Key", "key": "Clave",
"createTable": "Create your First Table!", "createTable": "Create your First Table!",
"createTableLabel": "Create your first table effortlessly, from scratch, or by importing/connecting to an external database.", "createTableLabel": "Create your first table effortlessly, from scratch, or by importing/connecting to an external database.",
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
"enterPassword": "Enter password", "enterPassword": "Introducir la contraseña",
"bySigningUp": "By signing up, you agree to the", "bySigningUp": "By signing up, you agree to the",
"subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter", "subscribeToOurWeeklyNewsletter": "Subscribe to our weekly newsletter",
"verifyingPassword": "Verifying Password", "verifyingPassword": "Verificando contraseña",
"thisSharedViewIsProtected": "This shared view is protected", "thisSharedViewIsProtected": "This shared view is protected",
"successfullySubmittedFormData": "Successfully submitted form data", "successfullySubmittedFormData": "Successfully submitted form data",
"formViewNotSupportedOnMobile": "Form view is not supported on mobile", "formViewNotSupportedOnMobile": "Form view is not supported on mobile",
@ -1004,19 +1024,19 @@
"optimizedQueryDisabled": "Optimized query is disabled", "optimizedQueryDisabled": "Optimized query is disabled",
"optimizedQueryEnabled": "Optimized query is enabled", "optimizedQueryEnabled": "Optimized query is enabled",
"lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation", "lookupNonBtWarning": "Lookup field is not supported for non-Belongs to relation",
"invalidTime": "Invalid Time", "invalidTime": "Hora no válida",
"linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup", "linkColumnClearNotSupportedYet": "You don't have any supported links for Lookup",
"recordCouldNotBeFound": "Record could not be found", "recordCouldNotBeFound": "Record could not be found",
"invalidPhoneNumber": "Invalid phone number", "invalidPhoneNumber": "Invalid phone number",
"pageSizeChanged": "Page size changed", "pageSizeChanged": "Tamaño de página modificado",
"errorLoadingData": "Error loading data", "errorLoadingData": "Error al cargar datos",
"webhookBodyMsg1": "Use context variable", "webhookBodyMsg1": "Use context variable",
"webhookBodyMsg2": "body", "webhookBodyMsg2": "cuerpo",
"webhookBodyMsg3": "to refer the record under consideration", "webhookBodyMsg3": "to refer the record under consideration",
"formula": { "formula": {
"hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out", "hintStart": "Hint: Use {placeholder1} to reference fields, e.g: {placeholder2}. For more, please check out",
"hintEnd": "Formulas.", "hintEnd": "Fórmulas.",
"noSuggestedFormulaFound": "No suggested formula found", "noSuggestedFormulaFound": "Fórmula sugerida no encontrada",
"typeIsExpected": "{calleeName} requires a {type} at position {position}", "typeIsExpected": "{calleeName} requires a {type} at position {position}",
"numericTypeIsExpected": "Numeric type is expected", "numericTypeIsExpected": "Numeric type is expected",
"stringTypeIsExpected": "String type is expected", "stringTypeIsExpected": "String type is expected",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Restricción mediante contraseña", "afterEnablePwd": "Restricción mediante contraseña",
"privateLink": "Esta vista es compartida por link privado", "privateLink": "Esta vista es compartida por link privado",
"privateLinkAdditionalInfo": "Las personas con el link privado podrán únicamente ver celdas visibles de esta vista", "privateLinkAdditionalInfo": "Las personas con el link privado podrán únicamente ver celdas visibles de esta vista",
"afterFormSubmitted": "Después de enviar el formulario", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Accede al proyecto a través de", "apiOptions": "Accede al proyecto a través de",
"submitAnotherForm": "Mostrar el botón 'Presentar otro formulario'", "submitAnotherForm": "Mostrar el botón 'Presentar otro formulario'",
"showBlankForm": "Muestra un formulario en blanco después de 5 segundos.", "showBlankForm": "Muestra un formulario en blanco después de 5 segundos.",
"emailForm": "Envíame un correo electrónico a", "emailForm": "Envíame un correo electrónico a",
"showSysFields": "Mostrar campos del sistema", "showSysFields": "Mostrar campos del sistema",
"filterAutoApply": "Aplicar automáticamente", "filterAutoApply": "Aplicar automáticamente",
"showMessage": "Mostrar este mensaje", "formDisplayMessage": "Display Message",
"viewNotShared": "La vista actual no está compartida!", "viewNotShared": "La vista actual no está compartida!",
"showAllViews": "Mostrar todas las vistas compartidas de esta tabla", "showAllViews": "Mostrar todas las vistas compartidas de esta tabla",
"collabView": "Los colaboradores con permisos de edición o superior pueden cambiar la configuración de la vista.", "collabView": "Los colaboradores con permisos de edición o superior pueden cambiar la configuración de la vista.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Metadatos del proyecto exportados con éxito.", "exportMetadata": "Metadatos del proyecto exportados con éxito.",

44
packages/nc-gui/lang/eu.json

@ -192,7 +192,12 @@
"enter": "Sartu", "enter": "Sartu",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Itsatsi", "paste": "Itsatsi",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Access is password restricted", "afterEnablePwd": "Access is password restricted",
"privateLink": "This view is shared via a private link", "privateLink": "This view is shared via a private link",
"privateLinkAdditionalInfo": "People with private link can only see cells visible in this view", "privateLinkAdditionalInfo": "People with private link can only see cells visible in this view",
"afterFormSubmitted": "After form is submitted", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Access Project via", "apiOptions": "Access Project via",
"submitAnotherForm": "Show 'Submit Another Form' button", "submitAnotherForm": "Show 'Submit Another Form' button",
"showBlankForm": "Show a blank form after 5 seconds", "showBlankForm": "Show a blank form after 5 seconds",
"emailForm": "E-mail me at", "emailForm": "E-mail me at",
"showSysFields": "Show system fields", "showSysFields": "Show system fields",
"filterAutoApply": "Auto apply", "filterAutoApply": "Auto apply",
"showMessage": "Show this message", "formDisplayMessage": "Display Message",
"viewNotShared": "Current view is not shared!", "viewNotShared": "Current view is not shared!",
"showAllViews": "Show all shared views of this table", "showAllViews": "Show all shared views of this table",
"collabView": "Collaborators with edit permissions or higher can change the view configuration.", "collabView": "Collaborators with edit permissions or higher can change the view configuration.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Project metadata exported successfully", "exportMetadata": "Project metadata exported successfully",

44
packages/nc-gui/lang/fa.json

@ -192,7 +192,12 @@
"enter": "وارد کردن", "enter": "وارد کردن",
"seconds": "ثانیه ها", "seconds": "ثانیه ها",
"paste": "جای گذاری", "paste": "جای گذاری",
"restore": "بازیابی" "restore": "بازیابی",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "تغییر وضعیت حالت موبایل", "toggleMobileMode": "تغییر وضعیت حالت موبایل",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "دسترسی با لزوم ورود کلمه عبور محدود شده", "afterEnablePwd": "دسترسی با لزوم ورود کلمه عبور محدود شده",
"privateLink": "این نمایش از طریق لینک خصوصی به اشتراک گذاشته شده", "privateLink": "این نمایش از طریق لینک خصوصی به اشتراک گذاشته شده",
"privateLinkAdditionalInfo": "افراد با لینک خصوصی تنها میتوانند سلولهایی که در این نمایش قابل مشاهده است را ببینند", "privateLinkAdditionalInfo": "افراد با لینک خصوصی تنها میتوانند سلولهایی که در این نمایش قابل مشاهده است را ببینند",
"afterFormSubmitted": "بعد از ارسال فرم", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "دسترسی به پروژه از طریق", "apiOptions": "دسترسی به پروژه از طریق",
"submitAnotherForm": "نمایش دکمه \"ارسال فرمی دیگر\"", "submitAnotherForm": "نمایش دکمه \"ارسال فرمی دیگر\"",
"showBlankForm": "نمایش فرم خالی پس از 5 ثانیه", "showBlankForm": "نمایش فرم خالی پس از 5 ثانیه",
"emailForm": "به این آدرس پست الکترونیکی من پیام ارسال کنید", "emailForm": "به این آدرس پست الکترونیکی من پیام ارسال کنید",
"showSysFields": "نمایش فیلدهای سیستم", "showSysFields": "نمایش فیلدهای سیستم",
"filterAutoApply": "اعمال خودکار", "filterAutoApply": "اعمال خودکار",
"showMessage": "نمایش این پیام", "formDisplayMessage": "Display Message",
"viewNotShared": "نمایش فعلی به اشتراک گذاشته نشده!", "viewNotShared": "نمایش فعلی به اشتراک گذاشته نشده!",
"showAllViews": "مشاهده تمام نمایش های به اشتراک گذاشته شده از این جدول", "showAllViews": "مشاهده تمام نمایش های به اشتراک گذاشته شده از این جدول",
"collabView": "همکاران با دسترسی ویرایش یا فراتر میتوانند پیکربندی نمایش را تغییر دهند.", "collabView": "همکاران با دسترسی ویرایش یا فراتر میتوانند پیکربندی نمایش را تغییر دهند.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "فراداده پروژه با موفقیت خارج شد", "exportMetadata": "فراداده پروژه با موفقیت خارج شد",

44
packages/nc-gui/lang/fi.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Pääsy on salasana rajoitettu", "afterEnablePwd": "Pääsy on salasana rajoitettu",
"privateLink": "Tämä näkymä on jaettu yksityisen linkin kautta", "privateLink": "Tämä näkymä on jaettu yksityisen linkin kautta",
"privateLinkAdditionalInfo": "Ihmiset, joilla on oma linkki, voivat nähdä vain tässä näkymässä näkyviä soluja", "privateLinkAdditionalInfo": "Ihmiset, joilla on oma linkki, voivat nähdä vain tässä näkymässä näkyviä soluja",
"afterFormSubmitted": "Lomakkeen jälkeen", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Access Project kautta", "apiOptions": "Access Project kautta",
"submitAnotherForm": "Näytä \"Lähetä toinen lomake\" -painike", "submitAnotherForm": "Näytä \"Lähetä toinen lomake\" -painike",
"showBlankForm": "Näytä tyhjä lomake 5 sekunnin kuluttua", "showBlankForm": "Näytä tyhjä lomake 5 sekunnin kuluttua",
"emailForm": "Lähetä minulle sähköpostia", "emailForm": "Lähetä minulle sähköpostia",
"showSysFields": "Näytä järjestelmäkenttiä", "showSysFields": "Näytä järjestelmäkenttiä",
"filterAutoApply": "Auto Apply", "filterAutoApply": "Auto Apply",
"showMessage": "Näytä tämä viesti", "formDisplayMessage": "Display Message",
"viewNotShared": "Nykyistä näkymää ei ole jaettu!", "viewNotShared": "Nykyistä näkymää ei ole jaettu!",
"showAllViews": "Näytä kaikki tämän taulukon yhteiset näkymät", "showAllViews": "Näytä kaikki tämän taulukon yhteiset näkymät",
"collabView": "Yhteistyökumppanit, joissa on muokkausoikeudet tai uudempi, voivat muuttaa näkymäasetusta.", "collabView": "Yhteistyökumppanit, joissa on muokkausoikeudet tai uudempi, voivat muuttaa näkymäasetusta.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Project Metadata viedään onnistuneesti", "exportMetadata": "Project Metadata viedään onnistuneesti",

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

@ -192,7 +192,12 @@
"enter": "Entrée", "enter": "Entrée",
"seconds": "Secondes", "seconds": "Secondes",
"paste": "Coller", "paste": "Coller",
"restore": "Restaurer" "restore": "Restaurer",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "(Dés-)activer le mode Mobile", "toggleMobileMode": "(Dés-)activer le mode Mobile",
"startCommenting": "Commencez à commenter !" "startCommenting": "Commencez à commenter !",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limité à une seule source de données pour le moment", "reachedSourceLimit": "Limité à une seule source de données pour le moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Cliquer pour copier l'ID du champ", "clickToCopyFieldId": "Cliquer pour copier l'ID du champ",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "L’accès est restreint par un mot de passe", "afterEnablePwd": "L’accès est restreint par un mot de passe",
"privateLink": "Cette vue est partagée avec un lien privé", "privateLink": "Cette vue est partagée avec un lien privé",
"privateLinkAdditionalInfo": "Les personnes ayant le lien privé peuvent voir uniquement les cellules visibles de cette vue", "privateLinkAdditionalInfo": "Les personnes ayant le lien privé peuvent voir uniquement les cellules visibles de cette vue",
"afterFormSubmitted": "Après que le formulaire a été soumis", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Accéder au projet via", "apiOptions": "Accéder au projet via",
"submitAnotherForm": "Afficher le bouton \"Soumettre un autre formulaire\"", "submitAnotherForm": "Afficher le bouton \"Soumettre un autre formulaire\"",
"showBlankForm": "Montrer un formulaire vierge après 5 secondes", "showBlankForm": "Montrer un formulaire vierge après 5 secondes",
"emailForm": "Écrivez-moi à", "emailForm": "Écrivez-moi à",
"showSysFields": "Afficher les champs système", "showSysFields": "Afficher les champs système",
"filterAutoApply": "Appliquer automatiquement", "filterAutoApply": "Appliquer automatiquement",
"showMessage": "Montrer ce message ", "formDisplayMessage": "Display Message",
"viewNotShared": "La vue actuelle n'est pas partagée!", "viewNotShared": "La vue actuelle n'est pas partagée!",
"showAllViews": "Montrer toutes les vues partagées sur cette table", "showAllViews": "Montrer toutes les vues partagées sur cette table",
"collabView": "Les collaborateurs avec des autorisations d'édition ou plus peuvent modifier la configuration de la vue.", "collabView": "Les collaborateurs avec des autorisations d'édition ou plus peuvent modifier la configuration de la vue.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Les métadonnées de projet sont exportées avec succès", "exportMetadata": "Les métadonnées de projet sont exportées avec succès",

44
packages/nc-gui/lang/he.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "הגישה היא מוגבלת בסיסמה", "afterEnablePwd": "הגישה היא מוגבלת בסיסמה",
"privateLink": "תצוגה זו משותפת דרך קישור פרטי", "privateLink": "תצוגה זו משותפת דרך קישור פרטי",
"privateLinkAdditionalInfo": "אנשים עם קישור פרטי יכולים לראות רק תאים גלוי בתצוגה זו", "privateLinkAdditionalInfo": "אנשים עם קישור פרטי יכולים לראות רק תאים גלוי בתצוגה זו",
"afterFormSubmitted": "לאחר הטופס מוגשת", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "גישה לפרויקט דרך", "apiOptions": "גישה לפרויקט דרך",
"submitAnotherForm": "הצג 'שלח עוד כפתור' טופס '", "submitAnotherForm": "הצג 'שלח עוד כפתור' טופס '",
"showBlankForm": "הצג טופס ריק לאחר 5 שניות", "showBlankForm": "הצג טופס ריק לאחר 5 שניות",
"emailForm": "דואר אלקטרוני לי ב", "emailForm": "דואר אלקטרוני לי ב",
"showSysFields": "הצג שדות מערכת", "showSysFields": "הצג שדות מערכת",
"filterAutoApply": "החל אוטומטי", "filterAutoApply": "החל אוטומטי",
"showMessage": "הצג הודעה זו", "formDisplayMessage": "Display Message",
"viewNotShared": "התצוגה הנוכחית אינה משותפת!", "viewNotShared": "התצוגה הנוכחית אינה משותפת!",
"showAllViews": "הצג את כל הנופים המשותפים של השולחן הזה", "showAllViews": "הצג את כל הנופים המשותפים של השולחן הזה",
"collabView": "משתפי פעולה עם הרשאות עריכה או גבוה יותר יכולים לשנות את תצורת התצוגה.", "collabView": "משתפי פעולה עם הרשאות עריכה או גבוה יותר יכולים לשנות את תצורת התצוגה.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "פרויקט Metadata מיוצא בהצלחה", "exportMetadata": "פרויקט Metadata מיוצא בהצלחה",

44
packages/nc-gui/lang/hi.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "एकस पसवरड परतिित ह", "afterEnablePwd": "एकस पसवरड परतिित ह",
"privateLink": "यह दय एक नििक कयम सि गय", "privateLink": "यह दय एक नििक कयम सि गय",
"privateLinkAdditionalInfo": "नििक वग कवल इस दय मिई दिख सकत", "privateLinkAdditionalInfo": "नििक वग कवल इस दय मिई दिख सकत",
"afterFormSubmitted": "फम कद परसत कि", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "कयम सट", "apiOptions": "कयम सट",
"submitAnotherForm": "एक और फम सबमिट कर' बटन दि", "submitAnotherForm": "एक और फम सबमिट कर' बटन दि",
"showBlankForm": "5 सड कद एक खम दि", "showBlankForm": "5 सड कद एक खम दि",
"emailForm": "म ई-मल कर", "emailForm": "म ई-मल कर",
"showSysFields": "सिटम फड दि", "showSysFields": "सिटम फड दि",
"filterAutoApply": "ऑट कर", "filterAutoApply": "ऑट कर",
"showMessage": "यह सश दि", "formDisplayMessage": "Display Message",
"viewNotShared": "वरतमन दय स नह!", "viewNotShared": "वरतमन दय स नह!",
"showAllViews": "इस ति सभिर दि", "showAllViews": "इस ति सभिर दि",
"collabView": "सदन अनमति उचचतर कथ सहयय किगरशन क बदल सकत।", "collabView": "सदन अनमति उचचतर कथ सहयय किगरशन क बदल सकत।",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "परिजन सफलतवक नित क गई", "exportMetadata": "परिजन सफलतवक नित क गई",

44
packages/nc-gui/lang/hr.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Preklopi na način za mobilne uređaje", "toggleMobileMode": "Preklopi na način za mobilne uređaje",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Pristup je ograničen lozinkom", "afterEnablePwd": "Pristup je ograničen lozinkom",
"privateLink": "Ovaj prikaz se dijeli putem privatne veze", "privateLink": "Ovaj prikaz se dijeli putem privatne veze",
"privateLinkAdditionalInfo": "Osobe s privatnom vezom mogu vidjeti samo ćelije vidljive u ovom pogledu", "privateLinkAdditionalInfo": "Osobe s privatnom vezom mogu vidjeti samo ćelije vidljive u ovom pogledu",
"afterFormSubmitted": "Nakon podnošenja obrasca", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Projekt pristupa putem", "apiOptions": "Projekt pristupa putem",
"submitAnotherForm": "Prikaži \"Pošalji još jedan obrazac\"", "submitAnotherForm": "Prikaži \"Pošalji još jedan obrazac\"",
"showBlankForm": "Pokažite prazan obrazac nakon 5 sekundi", "showBlankForm": "Pokažite prazan obrazac nakon 5 sekundi",
"emailForm": "E-mail me na", "emailForm": "E-mail me na",
"showSysFields": "Prikaži polja sustava", "showSysFields": "Prikaži polja sustava",
"filterAutoApply": "Automatsko primjenjivanje", "filterAutoApply": "Automatsko primjenjivanje",
"showMessage": "Pokažite ovu poruku", "formDisplayMessage": "Display Message",
"viewNotShared": "Trenutni prikaz se ne dijeli!", "viewNotShared": "Trenutni prikaz se ne dijeli!",
"showAllViews": "Prikaži sve zajedničke poglede na ovu tablicu", "showAllViews": "Prikaži sve zajedničke poglede na ovu tablicu",
"collabView": "Suradnici s uređivanjem dopuštenja ili više mogu promijeniti konfiguraciju prikaza.", "collabView": "Suradnici s uređivanjem dopuštenja ili više mogu promijeniti konfiguraciju prikaza.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Projektni metapodaci su uspješno izvozili", "exportMetadata": "Projektni metapodaci su uspješno izvozili",

44
packages/nc-gui/lang/id.json

@ -192,7 +192,12 @@
"enter": "Masuk", "enter": "Masuk",
"seconds": "Detik", "seconds": "Detik",
"paste": "Tempel", "paste": "Tempel",
"restore": "Pulihkan" "restore": "Pulihkan",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Akses dibatasi kata sandi", "afterEnablePwd": "Akses dibatasi kata sandi",
"privateLink": "Tampilan ini dibagikan melalui tautan pribadi", "privateLink": "Tampilan ini dibagikan melalui tautan pribadi",
"privateLinkAdditionalInfo": "Orang dengan tautan pribadi hanya dapat melihat sel yang terlihat dalam pandangan ini", "privateLinkAdditionalInfo": "Orang dengan tautan pribadi hanya dapat melihat sel yang terlihat dalam pandangan ini",
"afterFormSubmitted": "Setelah formulir dikirimkan", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "PROYEK AKSES VIA.", "apiOptions": "PROYEK AKSES VIA.",
"submitAnotherForm": "Tampilkan tombol 'Kirim formulir lain'", "submitAnotherForm": "Tampilkan tombol 'Kirim formulir lain'",
"showBlankForm": "Tampilkan formulir kosong setelah 5 detik", "showBlankForm": "Tampilkan formulir kosong setelah 5 detik",
"emailForm": "E-mail saya di", "emailForm": "E-mail saya di",
"showSysFields": "Tampilkan bidang sistem", "showSysFields": "Tampilkan bidang sistem",
"filterAutoApply": "Terapkan secara otomatis", "filterAutoApply": "Terapkan secara otomatis",
"showMessage": "Tampilkan pesan ini", "formDisplayMessage": "Display Message",
"viewNotShared": "Tampilan saat ini tidak dibagikan!", "viewNotShared": "Tampilan saat ini tidak dibagikan!",
"showAllViews": "Tampilkan semua tampilan bersama dari tabel ini", "showAllViews": "Tampilkan semua tampilan bersama dari tabel ini",
"collabView": "Kolaborator dengan izin edit atau lebih tinggi dapat mengubah konfigurasi tampilan.", "collabView": "Kolaborator dengan izin edit atau lebih tinggi dapat mengubah konfigurasi tampilan.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Metadata proyek berhasil diekspor", "exportMetadata": "Metadata proyek berhasil diekspor",

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

@ -192,7 +192,12 @@
"enter": "Invio", "enter": "Invio",
"seconds": "Secondi", "seconds": "Secondi",
"paste": "Incolla", "paste": "Incolla",
"restore": "Ripristino" "restore": "Ripristino",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Limita", "restrict": "Limita",
"setNull": "Imposta NULL", "setNull": "Imposta NULL",
"setDefault": "Imposta default" "setDefault": "Imposta default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Configurazione incompleta", "incompleteConfiguration": "Configurazione incompleta",
"selectField": "Seleziona un campo", "selectField": "Seleziona un campo",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Attiva/Disattiva Modalità Mobile", "toggleMobileMode": "Attiva/Disattiva Modalità Mobile",
"startCommenting": "Inizi a commentare!" "startCommenting": "Inizi a commentare!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limitato a una sola sorgente dati per il momento", "reachedSourceLimit": "Limitato a una sola sorgente dati per il momento",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Fare clic per copiare l'Id del campo", "clickToCopyFieldId": "Fare clic per copiare l'Id del campo",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "L'accesso è protetto da una password", "afterEnablePwd": "L'accesso è protetto da una password",
"privateLink": "Questa vista è condivisa tramite un collegamento privato", "privateLink": "Questa vista è condivisa tramite un collegamento privato",
"privateLinkAdditionalInfo": "Le persone con collegamento privato possono vedere solo le celle visibili in questa vista", "privateLinkAdditionalInfo": "Le persone con collegamento privato possono vedere solo le celle visibili in questa vista",
"afterFormSubmitted": "Dopo che il modulo è stato inviato", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Accedi al progetto tramite", "apiOptions": "Accedi al progetto tramite",
"submitAnotherForm": "Mostra \"Invia un altro modulo\"", "submitAnotherForm": "Mostra \"Invia un altro modulo\"",
"showBlankForm": "Mostra un modulo vuoto dopo 5 secondi", "showBlankForm": "Mostra un modulo vuoto dopo 5 secondi",
"emailForm": "Mandami un'e-mail a", "emailForm": "Mandami un'e-mail a",
"showSysFields": "Mostra campi di sistema", "showSysFields": "Mostra campi di sistema",
"filterAutoApply": "Auto Apply.", "filterAutoApply": "Auto Apply.",
"showMessage": "Mostra questo messaggio", "formDisplayMessage": "Display Message",
"viewNotShared": "La vista corrente non è condivisa!", "viewNotShared": "La vista corrente non è condivisa!",
"showAllViews": "Mostra tutte le viste condivise di questa tabella", "showAllViews": "Mostra tutte le viste condivise di questa tabella",
"collabView": "I collaboratori con autorizzazioni di modifica o superiore possono modificare la configurazione della vista", "collabView": "I collaboratori con autorizzazioni di modifica o superiore possono modificare la configurazione della vista",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "La modifica della chiave di sistema non è supportata", "editingSystemKeyNotSupported": "La modifica della chiave di sistema non è supportata",
"notAvailableAtTheMoment": "Non disponibile al momento", "notAvailableAtTheMoment": "Non disponibile al momento",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Si prega di completare la configurazione di tutti i campi prima di salvare", "multiFieldSaveValidation": "Si prega di completare la configurazione di tutti i campi prima di salvare",
"somethingWentWrong": "Qualcosa è andato storto", "somethingWentWrong": "Qualcosa è andato storto",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Metadati del progetto esportati con successo", "exportMetadata": "Metadati del progetto esportati con successo",

44
packages/nc-gui/lang/ja.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "アクセスするにはパスワードが必要です", "afterEnablePwd": "アクセスするにはパスワードが必要です",
"privateLink": "このビューはプライベートリンクを介して共有されています", "privateLink": "このビューはプライベートリンクを介して共有されています",
"privateLinkAdditionalInfo": "プライベートリンクを持つ人々は、このビューで表示されているセルのみを見ることができます", "privateLinkAdditionalInfo": "プライベートリンクを持つ人々は、このビューで表示されているセルのみを見ることができます",
"afterFormSubmitted": "フォーム送信後の操作", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "プロジェクトへのアクセス: ", "apiOptions": "プロジェクトへのアクセス: ",
"submitAnotherForm": "「他の回答を送信」ボタンを表示", "submitAnotherForm": "「他の回答を送信」ボタンを表示",
"showBlankForm": "5秒後に空白のフォームを表示", "showBlankForm": "5秒後に空白のフォームを表示",
"emailForm": "次のアドレスへメールを送る", "emailForm": "次のアドレスへメールを送る",
"showSysFields": "システムフィールドを表示", "showSysFields": "システムフィールドを表示",
"filterAutoApply": "自動適用", "filterAutoApply": "自動適用",
"showMessage": "このメッセージを表示", "formDisplayMessage": "Display Message",
"viewNotShared": "共有されているビューはありません!", "viewNotShared": "共有されているビューはありません!",
"showAllViews": "このテーブルのすべての共有されているビューを表示する", "showAllViews": "このテーブルのすべての共有されているビューを表示する",
"collabView": "編集権限を持つコラボレータは、ビュー構成を変更できます。", "collabView": "編集権限を持つコラボレータは、ビュー構成を変更できます。",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "プロジェクトメタデータは正常にエクスポートされました", "exportMetadata": "プロジェクトメタデータは正常にエクスポートされました",

44
packages/nc-gui/lang/ko.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "초", "seconds": "초",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "제한", "restrict": "제한",
"setNull": "null 설정", "setNull": "null 설정",
"setDefault": "기본값 설정" "setDefault": "기본값 설정"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "모바일 모드 전환", "toggleMobileMode": "모바일 모드 전환",
"startCommenting": "댓글 달기" "startCommenting": "댓글 달기",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "데이터 소스 제한에 도달했습니다.", "reachedSourceLimit": "데이터 소스 제한에 도달했습니다.",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "클릭하여 필드 ID 복사", "clickToCopyFieldId": "클릭하여 필드 ID 복사",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "엑세스 비밀번호 제한", "afterEnablePwd": "엑세스 비밀번호 제한",
"privateLink": "비공개 링크로 현재 뷰 공유", "privateLink": "비공개 링크로 현재 뷰 공유",
"privateLinkAdditionalInfo": "비공개 링크가 있는 사용자는 현재 보기에서 표시되는 셀만 볼 수 있습니다.", "privateLinkAdditionalInfo": "비공개 링크가 있는 사용자는 현재 보기에서 표시되는 셀만 볼 수 있습니다.",
"afterFormSubmitted": "양식이 제출 된 후", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "API 옵션", "apiOptions": "API 옵션",
"submitAnotherForm": "다른 양식 제출", "submitAnotherForm": "다른 양식 제출",
"showBlankForm": "5 초 후에 빈 양식을 보여줍니다", "showBlankForm": "5 초 후에 빈 양식을 보여줍니다",
"emailForm": "이메일로 공유", "emailForm": "이메일로 공유",
"showSysFields": "시스템 필드 표시", "showSysFields": "시스템 필드 표시",
"filterAutoApply": "자동 적용", "filterAutoApply": "자동 적용",
"showMessage": "아래 메시지 표시", "formDisplayMessage": "Display Message",
"viewNotShared": "현재 뷰가 공유되지 않습니다!", "viewNotShared": "현재 뷰가 공유되지 않습니다!",
"showAllViews": "테이블의 공유된 모든 뷰 표시", "showAllViews": "테이블의 공유된 모든 뷰 표시",
"collabView": "편집 권한 이상의 권한을 보유한 공동 작업자는 뷰 구성을 변경할 수 있습니다.", "collabView": "편집 권한 이상의 권한을 보유한 공동 작업자는 뷰 구성을 변경할 수 있습니다.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "프로젝트 메타 데이터를 성공적으로 내보냈습니다.", "exportMetadata": "프로젝트 메타 데이터를 성공적으로 내보냈습니다.",

44
packages/nc-gui/lang/lv.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Piekļuve ir ierobežota ar paroli", "afterEnablePwd": "Piekļuve ir ierobežota ar paroli",
"privateLink": "Šis skats ir koplietots izmantojot privātu saiti", "privateLink": "Šis skats ir koplietots izmantojot privātu saiti",
"privateLinkAdditionalInfo": "Cilvēkiar privātu saiti var redzēt tikai šūnas šajā skatā", "privateLinkAdditionalInfo": "Cilvēkiar privātu saiti var redzēt tikai šūnas šajā skatā",
"afterFormSubmitted": "Pēc formas iesniegšanas", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Piekļūt projektam caur", "apiOptions": "Piekļūt projektam caur",
"submitAnotherForm": "Parādīt 'Iesniegt vēl vienu formu' pogu", "submitAnotherForm": "Parādīt 'Iesniegt vēl vienu formu' pogu",
"showBlankForm": "Parādīt tukšu formu pēc 5 sekundēm", "showBlankForm": "Parādīt tukšu formu pēc 5 sekundēm",
"emailForm": "Nosūtīt epastu man uz", "emailForm": "Nosūtīt epastu man uz",
"showSysFields": "Parādīt sistēmas laukus", "showSysFields": "Parādīt sistēmas laukus",
"filterAutoApply": "Automātiski pielietot", "filterAutoApply": "Automātiski pielietot",
"showMessage": "Parādīt šo ziņojumu", "formDisplayMessage": "Display Message",
"viewNotShared": "Esošais skats nav koplietots!", "viewNotShared": "Esošais skats nav koplietots!",
"showAllViews": "Parādīt visus šīs tabulas koplietotos skatus", "showAllViews": "Parādīt visus šīs tabulas koplietotos skatus",
"collabView": "Līdzautori ar rediģēšanas vai augstākām atļaujām var mainīt šī skata konfigurāciju.", "collabView": "Līdzautori ar rediģēšanas vai augstākām atļaujām var mainīt šī skata konfigurāciju.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Projekta metadati eksportēti veiksmīgi", "exportMetadata": "Projekta metadati eksportēti veiksmīgi",

44
packages/nc-gui/lang/nl.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Toegang is wachtwoord beperkt", "afterEnablePwd": "Toegang is wachtwoord beperkt",
"privateLink": "Deze weergave wordt gedeeld via een privélink", "privateLink": "Deze weergave wordt gedeeld via een privélink",
"privateLinkAdditionalInfo": "Mensen met privélink kunnen alleen cellen zien die zichtbaar zijn in deze weergave", "privateLinkAdditionalInfo": "Mensen met privélink kunnen alleen cellen zien die zichtbaar zijn in deze weergave",
"afterFormSubmitted": "Nadat het formulier ingediend wordt", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Krijg toegang tot het project via", "apiOptions": "Krijg toegang tot het project via",
"submitAnotherForm": "Toon 'Stuur een nieuwe inzending' in", "submitAnotherForm": "Toon 'Stuur een nieuwe inzending' in",
"showBlankForm": "Toon een leeg formulier na 5 seconden", "showBlankForm": "Toon een leeg formulier na 5 seconden",
"emailForm": "E-mail me op", "emailForm": "E-mail me op",
"showSysFields": "Toon systeemvelden", "showSysFields": "Toon systeemvelden",
"filterAutoApply": "Automatisch toepassen", "filterAutoApply": "Automatisch toepassen",
"showMessage": "Toon dit bericht", "formDisplayMessage": "Display Message",
"viewNotShared": "Huidige weergave is niet gedeeld!", "viewNotShared": "Huidige weergave is niet gedeeld!",
"showAllViews": "Toon alle gedeelde weergaven van deze tabel", "showAllViews": "Toon alle gedeelde weergaven van deze tabel",
"collabView": "Collaborators met bewerkingsmachtigingen of hoger kunnen de weergaveconfiguratie wijzigen.", "collabView": "Collaborators met bewerkingsmachtigingen of hoger kunnen de weergaveconfiguratie wijzigen.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Project metadata met succes geëxporteerd", "exportMetadata": "Project metadata met succes geëxporteerd",

44
packages/nc-gui/lang/no.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Tilgang er passordbegrenset", "afterEnablePwd": "Tilgang er passordbegrenset",
"privateLink": "Denne visningen deles via en privat lenke", "privateLink": "Denne visningen deles via en privat lenke",
"privateLinkAdditionalInfo": "Personer med privat kobling kan bare se celler synlige i denne visningen", "privateLinkAdditionalInfo": "Personer med privat kobling kan bare se celler synlige i denne visningen",
"afterFormSubmitted": "Etter skjema er sendt inn", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Tilgang til prosjekt via", "apiOptions": "Tilgang til prosjekt via",
"submitAnotherForm": "Vis 'Send inn en annen form' -knapp", "submitAnotherForm": "Vis 'Send inn en annen form' -knapp",
"showBlankForm": "Vis et tomt skjema etter 5 sekunder", "showBlankForm": "Vis et tomt skjema etter 5 sekunder",
"emailForm": "E-post meg på", "emailForm": "E-post meg på",
"showSysFields": "Vis systemfelt", "showSysFields": "Vis systemfelt",
"filterAutoApply": "Auto gjelder", "filterAutoApply": "Auto gjelder",
"showMessage": "Vis denne meldingen", "formDisplayMessage": "Display Message",
"viewNotShared": "Nåværende visning er ikke delt!", "viewNotShared": "Nåværende visning er ikke delt!",
"showAllViews": "Vis alle felles syn på dette bordet", "showAllViews": "Vis alle felles syn på dette bordet",
"collabView": "Samarbeidspartnere med redigeringsrettigheter eller høyere kan endre visningskonfigurasjonen.", "collabView": "Samarbeidspartnere med redigeringsrettigheter eller høyere kan endre visningskonfigurasjonen.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Prosjektmetadata eksporteres vellykket", "exportMetadata": "Prosjektmetadata eksporteres vellykket",

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

@ -192,7 +192,12 @@
"enter": "Wprowadź", "enter": "Wprowadź",
"seconds": "Sekundy", "seconds": "Sekundy",
"paste": "Wklej", "paste": "Wklej",
"restore": "Przywróć" "restore": "Przywróć",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Ogranicz", "restrict": "Ogranicz",
"setNull": "Ustaw NULL", "setNull": "Ustaw NULL",
"setDefault": "Ustaw domyślne" "setDefault": "Ustaw domyślne"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Niekompletna konfiguracja", "incompleteConfiguration": "Niekompletna konfiguracja",
"selectField": "Wybierz pole", "selectField": "Wybierz pole",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "Otwórz w OpenStreetMap" "openInOpenStreetMap": "Otwórz w OpenStreetMap"
}, },
"toggleMobileMode": "Przełącz tryb mobilny", "toggleMobileMode": "Przełącz tryb mobilny",
"startCommenting": "Rozpocznij komentowanie" "startCommenting": "Rozpocznij komentowanie",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Ograniczenie do jednego źródła danych w tej chwili", "reachedSourceLimit": "Ograniczenie do jednego źródła danych w tej chwili",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Kliknij, aby skopiować Identyfikator Pola", "clickToCopyFieldId": "Kliknij, aby skopiować Identyfikator Pola",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Dostęp jest ograniczony hasłem", "afterEnablePwd": "Dostęp jest ograniczony hasłem",
"privateLink": "Ten widok jest współdzielony przez prywatny link", "privateLink": "Ten widok jest współdzielony przez prywatny link",
"privateLinkAdditionalInfo": "Ludzie z prywatnym ogniwem mogą widzieć tylko komórki widoczne w tym widoku", "privateLinkAdditionalInfo": "Ludzie z prywatnym ogniwem mogą widzieć tylko komórki widoczne w tym widoku",
"afterFormSubmitted": "Po złożeniu formularza", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Dostęp do projektu przez", "apiOptions": "Dostęp do projektu przez",
"submitAnotherForm": "Pokaż przycisk \"Prześlij inny formularz\"", "submitAnotherForm": "Pokaż przycisk \"Prześlij inny formularz\"",
"showBlankForm": "Pokaż pustą formę po 5 sekundach", "showBlankForm": "Pokaż pustą formę po 5 sekundach",
"emailForm": "E-mail mnie", "emailForm": "E-mail mnie",
"showSysFields": "Pokaż pola systemowe.", "showSysFields": "Pokaż pola systemowe.",
"filterAutoApply": "Automatyczne zastosowanie", "filterAutoApply": "Automatyczne zastosowanie",
"showMessage": "Pokaż tę wiadomość", "formDisplayMessage": "Display Message",
"viewNotShared": "Aktualny widok nie jest udostępniany!", "viewNotShared": "Aktualny widok nie jest udostępniany!",
"showAllViews": "Pokaż wszystkie wspólne widoki na tę tabelę", "showAllViews": "Pokaż wszystkie wspólne widoki na tę tabelę",
"collabView": "Współpracownicy z uprawnieniami edycji lub wyższe mogą zmienić konfigurację widoku.", "collabView": "Współpracownicy z uprawnieniami edycji lub wyższe mogą zmienić konfigurację widoku.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Edycja klucza systemowego nie jest obsługiwana", "editingSystemKeyNotSupported": "Edycja klucza systemowego nie jest obsługiwana",
"notAvailableAtTheMoment": "Obecnie niedostępne", "notAvailableAtTheMoment": "Obecnie niedostępne",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Proszę zakończyć konfigurację wszystkich pól przed zapisaniem", "multiFieldSaveValidation": "Proszę zakończyć konfigurację wszystkich pól przed zapisaniem",
"somethingWentWrong": "Coś poszło nie tak", "somethingWentWrong": "Coś poszło nie tak",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Pomyślnie wyeksportowano metadane projektu", "exportMetadata": "Pomyślnie wyeksportowano metadane projektu",

210
packages/nc-gui/lang/pt.json

@ -35,7 +35,7 @@
"heatmap_chart": "Gráfico de mapa de calor", "heatmap_chart": "Gráfico de mapa de calor",
"treemap_chart": "Gráfico em árvore", "treemap_chart": "Gráfico em árvore",
"box_plot_chart": "Gráfico de caixas", "box_plot_chart": "Gráfico de caixas",
"candlestick_chart": "Candlestick Chart" "candlestick_chart": "Gráfico castiçal"
} }
}, },
"general": { "general": {
@ -65,7 +65,7 @@
"saving": "Gravando", "saving": "Gravando",
"cancel": "Cancelar", "cancel": "Cancelar",
"null": "Nulo", "null": "Nulo",
"escape": "Escape", "escape": "Sair",
"hex": "Hex", "hex": "Hex",
"clear": "Limpar", "clear": "Limpar",
"slack": "Slack", "slack": "Slack",
@ -75,39 +75,39 @@
"matterMost": "Mattermost", "matterMost": "Mattermost",
"twilio": "Twilio", "twilio": "Twilio",
"whatsappTwilio": "WhatsApp Twilio", "whatsappTwilio": "WhatsApp Twilio",
"quote": "Quote", "quote": "Citar",
"submit": "Enviar", "submit": "Enviar",
"create": "Criar", "create": "Criar",
"createEntity": "Create {entity}", "createEntity": "Criar {entity}",
"creating": "Creating", "creating": "Criando",
"creatingEntity": "Creating {entity}", "creatingEntity": "Criando {entity}",
"details": "Details", "details": "Detalhes",
"skip": "Skip", "skip": "Saltar",
"code": "Code", "code": "Código",
"duplicate": "Duplicado", "duplicate": "Duplicado",
"duplicating": "Duplicating", "duplicating": "Duplicando",
"activate": "Activate", "activate": "Ativar",
"action": "Action", "action": "Ação",
"insert": "Inserir", "insert": "Inserir",
"delete": "Excluir", "delete": "Excluir",
"deleteEntity": "Delete {entity}", "deleteEntity": "Eliminar {entity}",
"bulkInsert": "Bulk Insert", "bulkInsert": "Inserção em massa",
"bulkDelete": "Bulk Delete", "bulkDelete": "Excluir em massa",
"bulkUpdate": "Bulk Update", "bulkUpdate": "Atualização em massa",
"deleting": "Deleting", "deleting": "Apagando",
"update": "Atualizar", "update": "Atualizar",
"rename": "Renomear", "rename": "Renomear",
"reload": "recarregar", "reload": "recarregar",
"reset": "Redefinir", "reset": "Redefinir",
"install": "Instalar", "install": "Instalar",
"show": "Mostrar", "show": "Mostrar",
"access": "Access", "access": "Acesso",
"visibility": "Visibility", "visibility": "Visibilidade",
"hide": "Esconder", "hide": "Esconder",
"deprecated": "Deprecated", "deprecated": "Descontinuado",
"showAll": "Mostre tudo", "showAll": "Mostre tudo",
"hideAll": "Esconda tudo", "hideAll": "Esconda tudo",
"notFound": "Not found", "notFound": "Não encontrado",
"showMore": "Mostre mais", "showMore": "Mostre mais",
"showOptions": "Mostrar opções", "showOptions": "Mostrar opções",
"hideOptions": "Ocultar opções", "hideOptions": "Ocultar opções",
@ -119,7 +119,7 @@
"signIn": "AUTENTIQUE-SE", "signIn": "AUTENTIQUE-SE",
"signOut": "Sair", "signOut": "Sair",
"required": "Obrigatório", "required": "Obrigatório",
"enableScanner": "Enable Scanner for filling", "enableScanner": "Ativar scanner para preenchimento",
"preferred": "Preferido", "preferred": "Preferido",
"mandatory": "Obrigatoriedade", "mandatory": "Obrigatoriedade",
"loading": "Carregando ...", "loading": "Carregando ...",
@ -127,8 +127,8 @@
"upload": "Carregar", "upload": "Carregar",
"download": "Descarregar", "download": "Descarregar",
"default": "Predefinição", "default": "Predefinição",
"base": "Source", "base": "Origem",
"datasource": "Data Source", "datasource": "Origem dos dados",
"more": "Mais", "more": "Mais",
"less": "Menos", "less": "Menos",
"event": "Evento", "event": "Evento",
@ -136,7 +136,7 @@
"after": "Depois de", "after": "Depois de",
"before": "Antes de", "before": "Antes de",
"search": "Procurar", "search": "Procurar",
"searchIn": "Search In", "searchIn": "Pesquisar em",
"notification": "Notificação", "notification": "Notificação",
"reference": "Referência", "reference": "Referência",
"function": "Função", "function": "Função",
@ -157,25 +157,25 @@
"groupingField": "Campo de Agrupamento", "groupingField": "Campo de Agrupamento",
"insertAfter": "Inserir depois", "insertAfter": "Inserir depois",
"insertBefore": "Inserir Antes", "insertBefore": "Inserir Antes",
"insertAbove": "Insert above", "insertAbove": "Inserir acima",
"insertBelow": "Insert below", "insertBelow": "Inserir abaixo",
"hideField": "Ocultar Campo", "hideField": "Ocultar Campo",
"sortAsc": "Ordenar Ascendente", "sortAsc": "Ordenar Ascendente",
"sortDesc": "Ordenar Descendente", "sortDesc": "Ordenar Descendente",
"move": "Move", "move": "Mover",
"geoDataField": "GeoData Field", "geoDataField": "Campo de dados geográficos",
"type": "Type", "type": "Tipo",
"name": "Name", "name": "Nome",
"changes": "Changes", "changes": "Alterações",
"new": "New", "new": "Novo",
"old": "Old", "old": "Antigo",
"data": "Data", "data": "Dados",
"source": "Source", "source": "Origem",
"destination": "Destination", "destination": "Destino",
"active": "Active", "active": "Ativo",
"inactive": "Inactive", "inactive": "Inativo",
"linked": "linked", "linked": "vinculado",
"finish": "Finish", "finish": "Concluir",
"min": "Min", "min": "Min",
"max": "Máximo", "max": "Máximo",
"avg": "Média", "avg": "Média",
@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Segundos", "seconds": "Segundos",
"paste": "Colar", "paste": "Colar",
"restore": "Restaurar" "restore": "Restaurar",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -395,17 +400,17 @@
"quickImportExcel": "Quick Import - Excel", "quickImportExcel": "Quick Import - Excel",
"quickImportJSON": "Quick Import - JSON", "quickImportJSON": "Quick Import - JSON",
"jsonEditor": "JSON Editor", "jsonEditor": "JSON Editor",
"comingSoon": "Coming Soon", "comingSoon": "Brevemente",
"advancedSettings": "Configurações avançadas", "advancedSettings": "Configurações avançadas",
"codeSnippet": "Código Snippet", "codeSnippet": "Código Snippet",
"keyboardShortcut": "Atalhos de teclado", "keyboardShortcut": "Atalhos de teclado",
"generateRandomName": "Generate Random Name", "generateRandomName": "Gerar nome aleatório",
"findRowByScanningCode": "Find row by scanning a QR or Barcode", "findRowByScanningCode": "Find row by scanning a QR or Barcode",
"tokenManagement": "Token Management", "tokenManagement": "Gestão de tokens",
"addNewToken": "Add new token", "addNewToken": "Adicionar novo token",
"createNewToken": "Create new token", "createNewToken": "Criar novo token",
"accountSettings": "Account Settings", "accountSettings": "Configurações da conta",
"resetPasswordMenu": "Reset Password", "resetPasswordMenu": "Repor a palavra-passe",
"tokens": "Tokens", "tokens": "Tokens",
"userManagement": "Gestão de utilizadores", "userManagement": "Gestão de utilizadores",
"accountManagement": "Gestão de contas", "accountManagement": "Gestão de contas",
@ -418,29 +423,31 @@
"links": { "links": {
"noAction": "Sem ação", "noAction": "Sem ação",
"cascade": "Cascata", "cascade": "Cascata",
"restrict": "Restrict", "restrict": "Restringir",
"setNull": "Set NULL", "setNull": "Definir NULL",
"setDefault": "Set Default" "setDefault": "Definir como padrão"
} },
"selectFieldsFromRightPannelToAddHere": "Seleccione campos do painel direito para adicionar aqui",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Selecionar ano",
"save": "Guardar", "save": "Guardar",
"cancel": "Cancelar", "cancel": "Cancelar",
"metadataUrl": "URL de metadados", "metadataUrl": "URL de metadados",
"audience-entityId": "Audience/ Entity ID", "audience-entityId": "Público-alvo/Entidade ID",
"redirectUrl": "URL de redirecionamento", "redirectUrl": "URL de redirecionamento",
"oidc": "OpenID Connect (OIDC)", "oidc": "Ligação OpenID (OIDC)",
"saml": "Security Assertion Markup Language (SAML)", "saml": "Security Assertion Markup Language (SAML)",
"newProvider": "Novo provedor", "newProvider": "Novo provedor",
"generalSettings": "Configurações gerais", "generalSettings": "Configurações gerais",
"ssoSettings": "Configurações SSO", "ssoSettings": "Configurações SSO",
"organizeBy": "Organize by", "organizeBy": "Organizar por",
"previous": "Previous", "previous": "Anterior",
"nextMonth": "Next Month", "nextMonth": "Próximo mês",
"previousMonth": "Previous Month", "previousMonth": "Mês anterior",
"next": "Next", "next": "Próximo",
"organiseBy": "Organise by", "organiseBy": "Organizar por",
"heading1": "Cabeçalho 1", "heading1": "Cabeçalho 1",
"heading2": "Cabeçalho 2", "heading2": "Cabeçalho 2",
"heading3": "Cabeçalho 3", "heading3": "Cabeçalho 3",
@ -452,36 +459,36 @@
"bulletList": "Lista com marcadores", "bulletList": "Lista com marcadores",
"numberedList": "Lista numerada", "numberedList": "Lista numerada",
"downloadData": "Transferir dados", "downloadData": "Transferir dados",
"blockQuote": "Block Quote", "blockQuote": "Bloco de citação",
"noToken": "No Token", "noToken": "Nenhum Token",
"tokenLimit": "Só é permitido um token por utilizador", "tokenLimit": "Só é permitido um token por utilizador",
"duplicateAttachment": "Arquivo com o nome {filename} já está anexado", "duplicateAttachment": "Arquivo com o nome {filename} já está anexado",
"viewIdColon": "VIEW ID: {viewId}", "viewIdColon": "ID DE VISUALIZAÇÃO: {viewId}",
"toAddress": "To Address", "toAddress": "Para o endereço",
"subject": "Subject", "subject": "Assunto",
"body": "Body", "body": "Body",
"commaSeparatedMobileNumber": "Comma separated Mobile #", "commaSeparatedMobileNumber": "Comma separated Mobile #",
"headerName": "Header Name", "headerName": "Nome do cabeçalho",
"icon": "Icon", "icon": "Ícone",
"max": "Max", "max": "Max",
"enableRichText": "Enable Rich Text", "enableRichText": "Ativar texto rico",
"idColon": "Id:", "idColon": "Id:",
"copiedRecordURL": "Copied Record URL", "copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL", "copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record", "duplicateRecord": "Duplicar registo",
"binaryEncodingFormat": "Binary encoding format", "binaryEncodingFormat": "Formato de codificação binária",
"syntax": "Syntax", "syntax": "Sintaxe",
"examples": "Examples", "examples": "Exemplos",
"durationInfo": "A duration of time in minutes or seconds (e.g. 1:23).", "durationInfo": "Duração de tempo em minutos ou segundos (exp. 1:23).",
"addHeader": "Add Header", "addHeader": "Adicionar cabeçalho",
"enterDefaultUrlOptional": "Enter default URL (Optional)", "enterDefaultUrlOptional": "Introduzir URL predefinido (opcional)",
"negative": "Negative", "negative": "Negativo",
"discard": "Discard", "discard": "Descartar",
"default": "Default", "default": "Padrão",
"defaultNumberPercent": "Default Number (%)", "defaultNumberPercent": "Número padrão (%)",
"durationFormat": "Duration Format", "durationFormat": "Formato de duração",
"dateFormat": "Date Format", "dateFormat": "Formato da data",
"timeFormat": "Time Format", "timeFormat": "Formato da hora",
"singularLabel": "Singular Label", "singularLabel": "Singular Label",
"pluralLabel": "Plural Label", "pluralLabel": "Plural Label",
"selectDateField": "Select a date field", "selectDateField": "Select a date field",
@ -530,7 +537,7 @@
"duplicateKanbanView": "Duplicate Kanban View", "duplicateKanbanView": "Duplicate Kanban View",
"duplicateCalendarView": "Duplicate Calendar View", "duplicateCalendarView": "Duplicate Calendar View",
"createKanbanView": "Create Kanban View", "createKanbanView": "Create Kanban View",
"createCalendarView": "Create Calendar View", "createCalendarView": "Criar visualização de calendário",
"viewName": "Visualizar nome", "viewName": "Visualizar nome",
"viewLink": "View link.", "viewLink": "View link.",
"columnName": "Nome da coluna", "columnName": "Nome da coluna",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "O acesso está protegido por uma palavra-passe", "afterEnablePwd": "O acesso está protegido por uma palavra-passe",
"privateLink": "Esta vista é partilhada através de uma ligação privada", "privateLink": "Esta vista é partilhada através de uma ligação privada",
"privateLinkAdditionalInfo": "As pessoas com acesso à ligação privada só podem ver as células visíveis nesta vista", "privateLinkAdditionalInfo": "As pessoas com acesso à ligação privada só podem ver as células visíveis nesta vista",
"afterFormSubmitted": "Após o formulário é submetido", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Aceder ao Projecto por", "apiOptions": "Aceder ao Projecto por",
"submitAnotherForm": "Mostrar 'enviar outro formulário' botão", "submitAnotherForm": "Mostrar 'enviar outro formulário' botão",
"showBlankForm": "Mostre um formulário em branco após 5 segundos", "showBlankForm": "Mostre um formulário em branco após 5 segundos",
"emailForm": "E-mail para", "emailForm": "E-mail para",
"showSysFields": "Mostrar campos do sistema", "showSysFields": "Mostrar campos do sistema",
"filterAutoApply": "Aplicar automaticamente", "filterAutoApply": "Aplicar automaticamente",
"showMessage": "Mostre esta mensagem", "formDisplayMessage": "Display Message",
"viewNotShared": "A visão atual não é compartilhada!", "viewNotShared": "A visão atual não é compartilhada!",
"showAllViews": "Mostrar todas as vistas compartilhadas desta mesa", "showAllViews": "Mostrar todas as vistas compartilhadas desta mesa",
"collabView": "Colaboradores com permissões de edição ou maiores podem alterar a configuração da visualização.", "collabView": "Colaboradores com permissões de edição ou maiores podem alterar a configuração da visualização.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Metadados do projeto exportado com sucesso", "exportMetadata": "Metadados do projeto exportado com sucesso",

136
packages/nc-gui/lang/pt_BR.json

@ -1,28 +1,28 @@
{ {
"dashboards": { "dashboards": {
"create_new_dashboard_project": "Create New Interface", "create_new_dashboard_project": "Criar nova interface",
"connect_data_sources": "Connect data sources", "connect_data_sources": "Conectar fontes de dados",
"alert": "Alert", "alert": "Alert",
"alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.", "alert-message": "No databases have been connected. Connect database bases to build interfaces. Skip this step and add databases from the base home page later.",
"select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Select Database Bases that you want to link to this Interface.", "select_database_projects_that_you_want_to_link_to_this_dashboard_projects": "Selecione as bases de dados que você deseja vincular a esta interface.",
"create_interface": "Create interface", "create_interface": "Criar interface",
"project_name": "Base Name", "project_name": "Base Name",
"connect": "Connect", "connect": "Conectar",
"buttonActionTypes": { "buttonActionTypes": {
"open_external_url": "Open external link", "open_external_url": "Abrir link externo",
"delete_record": "Delete record", "delete_record": "Excluir registro",
"update_record": "Update record", "update_record": "Atualizar registro",
"open_layout": "Open layout" "open_layout": "Abrir layout"
}, },
"widgets": { "widgets": {
"static_text": "Text", "static_text": "Texto",
"chart": "Chart", "chart": "Gráfico",
"table": "Table", "table": "Tabela",
"image": "Image", "image": "Imagem",
"map": "Map", "map": "Map",
"button": "Button", "button": "Botão",
"number": "Number", "number": "Número",
"bar_chart": "Bar Chart", "bar_chart": "Gráfico de barras",
"line_chart": "Line Chart", "line_chart": "Line Chart",
"area_chart": "Area Chart", "area_chart": "Area Chart",
"pie_chart": "Pie Chart", "pie_chart": "Pie Chart",
@ -39,7 +39,7 @@
} }
}, },
"general": { "general": {
"quit": "Quit", "quit": "Sair",
"home": "Início", "home": "Início",
"load": "Carregar", "load": "Carregar",
"open": "Abrir", "open": "Abrir",
@ -47,7 +47,7 @@
"yes": "Sim", "yes": "Sim",
"no": "Não", "no": "Não",
"ok": "OK", "ok": "OK",
"back": "Back", "back": "Voltar",
"and": "E", "and": "E",
"or": "Ou", "or": "Ou",
"add": "Adicionar", "add": "Adicionar",
@ -55,16 +55,16 @@
"link": "Link", "link": "Link",
"links": "Links", "links": "Links",
"remove": "Remover", "remove": "Remover",
"import": "Import", "import": "Importar",
"logout": "Log Out", "logout": "Encerrar Sessão",
"empty": "Empty", "empty": "Empty",
"changeIcon": "Change Icon", "changeIcon": "Alterar Ícone",
"save": "Salvar", "save": "Salvar",
"available": "Available", "available": "Disponível",
"abort": "Abort", "abort": "Abortar",
"saving": "Saving", "saving": "Saving",
"cancel": "Cancelar", "cancel": "Cancelar",
"null": "Null", "null": "Nulo",
"escape": "Escape", "escape": "Escape",
"hex": "Hex", "hex": "Hex",
"clear": "Clear", "clear": "Clear",
@ -164,17 +164,17 @@
"sortDesc": "Ordenar Descendente", "sortDesc": "Ordenar Descendente",
"move": "Move", "move": "Move",
"geoDataField": "Campo GeoData", "geoDataField": "Campo GeoData",
"type": "Type", "type": "Tipo",
"name": "Name", "name": "Nome",
"changes": "Changes", "changes": "Mudanças",
"new": "New", "new": "Novo",
"old": "Old", "old": "Antigo",
"data": "Data", "data": "Dados",
"source": "Source", "source": "Fonte",
"destination": "Destination", "destination": "Destino",
"active": "Active", "active": "Ativo",
"inactive": "Inactive", "inactive": "Inativo",
"linked": "linked", "linked": "vinculado",
"finish": "Finish", "finish": "Finish",
"min": "Min", "min": "Min",
"max": "Max", "max": "Max",
@ -190,15 +190,20 @@
"useSurveyMode": "Use Survey Mode", "useSurveyMode": "Use Survey Mode",
"shift": "Shift", "shift": "Shift",
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Segundos",
"paste": "Paste", "paste": "Colar",
"restore": "Restore" "restore": "Restaurar",
"replace": "Substituir",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Dia",
"week": "Week", "week": "Semana",
"month": "Month", "month": "Mês",
"year": "Year", "year": "Ano",
"workspace": "Workspace", "workspace": "Workspace",
"workspaces": "Workspaces", "workspaces": "Workspaces",
"project": "Projeto", "project": "Projeto",
@ -217,7 +222,7 @@
"webhooks": "WebHooks.", "webhooks": "WebHooks.",
"view": "Visualizar", "view": "Visualizar",
"views": "Vizualizações", "views": "Vizualizações",
"sidebar": "Sidebar", "sidebar": "Barra lateral",
"viewType": { "viewType": {
"grid": "Grade", "grid": "Grade",
"gallery": "Galeria", "gallery": "Galeria",
@ -230,7 +235,7 @@
"users": "Usuários", "users": "Usuários",
"role": "Função", "role": "Função",
"roles": "Funções", "roles": "Funções",
"developer": "Developer", "developer": "Desenvolvedor",
"roleType": { "roleType": {
"owner": "Proprietário", "owner": "Proprietário",
"creator": "Criador", "creator": "Criador",
@ -238,7 +243,7 @@
"commenter": "Comentarista", "commenter": "Comentarista",
"viewer": "Visualizador", "viewer": "Visualizador",
"noaccess": "No Access", "noaccess": "No Access",
"superAdmin": "Super Admin", "superAdmin": "Super Administrador",
"orgLevelCreator": "Criador de Nível da Organização", "orgLevelCreator": "Criador de Nível da Organização",
"orgLevelViewer": "Visualizador de nível da organização" "orgLevelViewer": "Visualizador de nível da organização"
}, },
@ -250,7 +255,7 @@
"tall": "Tall", "tall": "Tall",
"extra": "Extra" "extra": "Extra"
}, },
"externalDb": "External Database" "externalDb": "Banco de Dados externo"
}, },
"datatype": { "datatype": {
"ID": "ID", "ID": "ID",
@ -305,7 +310,7 @@
"isNotNull": "não é nulo" "isNotNull": "não é nulo"
}, },
"title": { "title": {
"sso": "Authentication (SSO)", "sso": "Autenticação (SSO)",
"docs": "Docs", "docs": "Docs",
"forum": "Forum", "forum": "Forum",
"parameter": "Parameter", "parameter": "Parameter",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Alternar o modo móvel", "toggleMobileMode": "Alternar o modo móvel",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "O acesso está protegido por uma senha", "afterEnablePwd": "O acesso está protegido por uma senha",
"privateLink": "Esta vizualização é compartilhada através de uma conexão privada", "privateLink": "Esta vizualização é compartilhada através de uma conexão privada",
"privateLinkAdditionalInfo": "As pessoas com acesso a conexão privada só podem ver as células visíveis nesta vizualização", "privateLinkAdditionalInfo": "As pessoas com acesso a conexão privada só podem ver as células visíveis nesta vizualização",
"afterFormSubmitted": "Após o formulário é submetido", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Acesse o projeto via", "apiOptions": "Acesse o projeto via",
"submitAnotherForm": "Mostrar 'enviar outro formulário' botão", "submitAnotherForm": "Mostrar 'enviar outro formulário' botão",
"showBlankForm": "Mostre um formulário em branco após 5 segundos", "showBlankForm": "Mostre um formulário em branco após 5 segundos",
"emailForm": "E-mail para", "emailForm": "E-mail para",
"showSysFields": "Mostrar campos do sistema", "showSysFields": "Mostrar campos do sistema",
"filterAutoApply": "Aplicar automaticamente", "filterAutoApply": "Aplicar automaticamente",
"showMessage": "Mostre esta mensagem", "formDisplayMessage": "Display Message",
"viewNotShared": "A visão atual não é compartilhada!", "viewNotShared": "A visão atual não é compartilhada!",
"showAllViews": "Mostrar todas as vistas compartilhadas desta mesa", "showAllViews": "Mostrar todas as vistas compartilhadas desta mesa",
"collabView": "Colaboradores com permissões de edição ou maiores podem alterar a configuração da visualização.", "collabView": "Colaboradores com permissões de edição ou maiores podem alterar a configuração da visualização.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Metadados do projeto exportado com sucesso", "exportMetadata": "Metadados do projeto exportado com sucesso",

44
packages/nc-gui/lang/ru.json

@ -192,7 +192,12 @@
"enter": "Вход", "enter": "Вход",
"seconds": "Секунды", "seconds": "Секунды",
"paste": "Вставить", "paste": "Вставить",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Установить в NULL", "setNull": "Установить в NULL",
"setDefault": "Установить по умолчанию" "setDefault": "Установить по умолчанию"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Выбрать поле", "selectField": "Выбрать поле",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Переключить мобильный режим", "toggleMobileMode": "Переключить мобильный режим",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Доступ защищенный паролем", "afterEnablePwd": "Доступ защищенный паролем",
"privateLink": "Это представление передано личной ссылкой.", "privateLink": "Это представление передано личной ссылкой.",
"privateLinkAdditionalInfo": "Люди с личной ссыкой могу видеть только ячейки видимые в этом представлении", "privateLinkAdditionalInfo": "Люди с личной ссыкой могу видеть только ячейки видимые в этом представлении",
"afterFormSubmitted": "После отправки формы", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Доступ проекта через", "apiOptions": "Доступ проекта через",
"submitAnotherForm": "Показать кнопку «Отправить другую форму»", "submitAnotherForm": "Показать кнопку «Отправить другую форму»",
"showBlankForm": "Показать пустую форму через 5 секунд", "showBlankForm": "Показать пустую форму через 5 секунд",
"emailForm": "Напишите мне на", "emailForm": "Напишите мне на",
"showSysFields": "Показать системные поля", "showSysFields": "Показать системные поля",
"filterAutoApply": "Применять автоматически", "filterAutoApply": "Применять автоматически",
"showMessage": "Покажите это сообщение", "formDisplayMessage": "Display Message",
"viewNotShared": "Текущим представлением не поделились", "viewNotShared": "Текущим представлением не поделились",
"showAllViews": "Показать все общие представление этой таблицы", "showAllViews": "Показать все общие представление этой таблицы",
"collabView": "Сотрудники с разрешениями редактирования или выше могут изменить конфигурацию представления", "collabView": "Сотрудники с разрешениями редактирования или выше могут изменить конфигурацию представления",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Метаданные проекта успешно экспортированы", "exportMetadata": "Метаданные проекта успешно экспортированы",

44
packages/nc-gui/lang/sk.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Prístup je obmedzený heslom", "afterEnablePwd": "Prístup je obmedzený heslom",
"privateLink": "Tento pohľad sa zdieľa prostredníctvom súkromného prepojenia", "privateLink": "Tento pohľad sa zdieľa prostredníctvom súkromného prepojenia",
"privateLinkAdditionalInfo": "Ľudia so súkromným prepojením môžu vidieť iba bunky viditeľné v tomto zobrazení", "privateLinkAdditionalInfo": "Ľudia so súkromným prepojením môžu vidieť iba bunky viditeľné v tomto zobrazení",
"afterFormSubmitted": "Po odoslaní formulára", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Prístup k projektu cez", "apiOptions": "Prístup k projektu cez",
"submitAnotherForm": "Zobrazenie tlačidla Odoslať ďalší formulár", "submitAnotherForm": "Zobrazenie tlačidla Odoslať ďalší formulár",
"showBlankForm": "Zobrazenie prázdneho formulára po 5 sekundách", "showBlankForm": "Zobrazenie prázdneho formulára po 5 sekundách",
"emailForm": "Napíšte mi na e-mailovú adresu", "emailForm": "Napíšte mi na e-mailovú adresu",
"showSysFields": "Zobrazenie systémových polí", "showSysFields": "Zobrazenie systémových polí",
"filterAutoApply": "Automatická aplikácia", "filterAutoApply": "Automatická aplikácia",
"showMessage": "Zobraziť túto správu", "formDisplayMessage": "Display Message",
"viewNotShared": "Súčasný pohľad nie je zdieľaný!", "viewNotShared": "Súčasný pohľad nie je zdieľaný!",
"showAllViews": "Zobrazenie všetkých zdieľaných zobrazení tejto tabuľky", "showAllViews": "Zobrazenie všetkých zdieľaných zobrazení tejto tabuľky",
"collabView": "Spolupracovníci s oprávneniami na úpravu alebo vyššími môžu zmeniť konfiguráciu zobrazenia.", "collabView": "Spolupracovníci s oprávneniami na úpravu alebo vyššími môžu zmeniť konfiguráciu zobrazenia.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Úspešný export metadát projektu", "exportMetadata": "Úspešný export metadát projektu",

44
packages/nc-gui/lang/sl.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Za dostop je potrebno geslo", "afterEnablePwd": "Za dostop je potrebno geslo",
"privateLink": "Ta pogled je v skupni rabi prek zasebne povezave", "privateLink": "Ta pogled je v skupni rabi prek zasebne povezave",
"privateLinkAdditionalInfo": "Ljudje z zasebno povezavo lahko vidijo le celice, ki so vidne v tem pogledu", "privateLinkAdditionalInfo": "Ljudje z zasebno povezavo lahko vidijo le celice, ki so vidne v tem pogledu",
"afterFormSubmitted": "Po obrazec", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Dostopaj projekt prek", "apiOptions": "Dostopaj projekt prek",
"submitAnotherForm": "Pokaži gumb \"Pošljite gumb\"", "submitAnotherForm": "Pokaži gumb \"Pošljite gumb\"",
"showBlankForm": "Po 5 sekundah pokažite prazno obliko", "showBlankForm": "Po 5 sekundah pokažite prazno obliko",
"emailForm": "Pošlji mi e-pošto", "emailForm": "Pošlji mi e-pošto",
"showSysFields": "Pokaži sistemska polja", "showSysFields": "Pokaži sistemska polja",
"filterAutoApply": "Auto Nanesite", "filterAutoApply": "Auto Nanesite",
"showMessage": "Pokaži to sporočilo", "formDisplayMessage": "Display Message",
"viewNotShared": "Trenutni pogled ni v skupni rabi!", "viewNotShared": "Trenutni pogled ni v skupni rabi!",
"showAllViews": "Pokaži vse skupne poglede na to tabelo", "showAllViews": "Pokaži vse skupne poglede na to tabelo",
"collabView": "Sodelavci z dovoljenji za urejanje ali višje lahko spremenijo konfiguracijo pogleda.", "collabView": "Sodelavci z dovoljenji za urejanje ali višje lahko spremenijo konfiguracijo pogleda.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Projekt Metapodatki se je uspešno izvozil", "exportMetadata": "Projekt Metapodatki se je uspešno izvozil",

44
packages/nc-gui/lang/sv.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "Åtkomst är lösenordsbegränsad", "afterEnablePwd": "Åtkomst är lösenordsbegränsad",
"privateLink": "Denna uppfattning delas via en privat länk", "privateLink": "Denna uppfattning delas via en privat länk",
"privateLinkAdditionalInfo": "Människor med privat länk kan bara se celler synliga i den här vyn", "privateLinkAdditionalInfo": "Människor med privat länk kan bara se celler synliga i den här vyn",
"afterFormSubmitted": "Efter formuläret skickas in", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "Åtkomstprojekt via", "apiOptions": "Åtkomstprojekt via",
"submitAnotherForm": "Visa \"Skicka en annan formulär\" -knapp", "submitAnotherForm": "Visa \"Skicka en annan formulär\" -knapp",
"showBlankForm": "Visa en tom form efter 5 sekunder", "showBlankForm": "Visa en tom form efter 5 sekunder",
"emailForm": "E-posta mig på", "emailForm": "E-posta mig på",
"showSysFields": "Visa systemfält", "showSysFields": "Visa systemfält",
"filterAutoApply": "Auto ansöker", "filterAutoApply": "Auto ansöker",
"showMessage": "Visa det här meddelandet", "formDisplayMessage": "Display Message",
"viewNotShared": "Aktuell vy är inte delad!", "viewNotShared": "Aktuell vy är inte delad!",
"showAllViews": "Visa alla delade utsikt över denna tabell", "showAllViews": "Visa alla delade utsikt över denna tabell",
"collabView": "Samarbetare med redigeringsbehörigheter eller högre kan ändra visningskonfigurationen.", "collabView": "Samarbetare med redigeringsbehörigheter eller högre kan ändra visningskonfigurationen.",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "Projektmetadata exporterades framgångsrikt", "exportMetadata": "Projektmetadata exporterades framgångsrikt",

44
packages/nc-gui/lang/th.json

@ -192,7 +192,12 @@
"enter": "Enter", "enter": "Enter",
"seconds": "Seconds", "seconds": "Seconds",
"paste": "Paste", "paste": "Paste",
"restore": "Restore" "restore": "Restore",
"replace": "Replace",
"banner": "Banner",
"logo": "Logo",
"dropdown": "Dropdown",
"list": "List"
}, },
"objects": { "objects": {
"day": "Day", "day": "Day",
@ -421,7 +426,9 @@
"restrict": "Restrict", "restrict": "Restrict",
"setNull": "Set NULL", "setNull": "Set NULL",
"setDefault": "Set Default" "setDefault": "Set Default"
} },
"selectFieldsFromRightPannelToAddHere": "Select fields from right panel to add here",
"noOptionsFound": "No options found"
}, },
"labels": { "labels": {
"selectYear": "Select Year", "selectYear": "Select Year",
@ -683,9 +690,18 @@
"incompleteConfiguration": "Incomplete configuration", "incompleteConfiguration": "Incomplete configuration",
"selectField": "Select a field", "selectField": "Select a field",
"selectFieldLabel": "Begin by selecting a field to customise its properties and structure." "selectFieldLabel": "Begin by selecting a field to customise its properties and structure."
} },
"appearanceSettings": "Appearance Settings",
"backgroundColor": "Background Color",
"hideNocodbBranding": "Hide NocoDB Branding",
"showOnConditions": "Show on condtions",
"showFieldOnConditionsMet": "Shows field only when conditions are met",
"limitOptions": "Limit options",
"limitOptionsSubtext": "Limit options visible to users by selecting available options",
"clearSelection": "Clear selection"
}, },
"activity": { "activity": {
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today", "goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar", "toggleSidebar": "Toggle Sidebar",
"addEndDate": "Add end date", "addEndDate": "Add end date",
@ -907,7 +923,10 @@
"openInOpenStreetMap": "OSM" "openInOpenStreetMap": "OSM"
}, },
"toggleMobileMode": "Toggle Mobile Mode", "toggleMobileMode": "Toggle Mobile Mode",
"startCommenting": "Start commenting!" "startCommenting": "Start commenting!",
"clearForm": "Clear Form",
"addFieldFromFormView": "Add Field",
"selectAllFields": "Select all fields"
}, },
"tooltip": { "tooltip": {
"reachedSourceLimit": "Limited to only one data source for the moment", "reachedSourceLimit": "Limited to only one data source for the moment",
@ -989,7 +1008,8 @@
"noTokenCreated": "No API Tokens created", "noTokenCreated": "No API Tokens created",
"noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.", "noTokenCreatedLabel": "Begin by creating API tokens to unlock advanced functionalities.",
"inviteYourTeam": "Invite your team", "inviteYourTeam": "Invite your team",
"inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace." "inviteYourTeamLabel": "Streamline collaboration and productivity with your team – start by inviting them to join your workspace.",
"searchOptions": "Search options"
}, },
"msg": { "msg": {
"clickToCopyFieldId": "Click to copy Field Id", "clickToCopyFieldId": "Click to copy Field Id",
@ -1166,14 +1186,14 @@
"afterEnablePwd": "การเขาถงคอรหสผานท จำกด", "afterEnablePwd": "การเขาถงคอรหสผานท จำกด",
"privateLink": "มมมองนใชวมกนผานลงควนตว", "privateLink": "มมมองนใชวมกนผานลงควนตว",
"privateLinkAdditionalInfo": "ผงควนตวสามารถเหนเซลลมองเหนไดในมมมองนเทานน", "privateLinkAdditionalInfo": "ผงควนตวสามารถเหนเซลลมองเหนไดในมมมองนเทานน",
"afterFormSubmitted": "หลงจากสงแบบฟอรมแล", "postFormSubmissionSettings": "Post Form Submission Settings",
"apiOptions": "เขาถงโครงการผานทาง", "apiOptions": "เขาถงโครงการผานทาง",
"submitAnotherForm": "แสดงปม 'สงฟอรมอน'", "submitAnotherForm": "แสดงปม 'สงฟอรมอน'",
"showBlankForm": "แสดงแบบฟอรมเปลาหลงจาก 5 วนาท", "showBlankForm": "แสดงแบบฟอรมเปลาหลงจาก 5 วนาท",
"emailForm": "สงอเมลถงฉนท", "emailForm": "สงอเมลถงฉนท",
"showSysFields": "แสดงฟลดระบบ", "showSysFields": "แสดงฟลดระบบ",
"filterAutoApply": "ใชตโนม", "filterAutoApply": "ใชตโนม",
"showMessage": "แสดงขอความน", "formDisplayMessage": "Display Message",
"viewNotShared": "มมมองปจจนไมไดแชร!", "viewNotShared": "มมมองปจจนไมไดแชร!",
"showAllViews": "แสดงมมมองทแชรงหมดของตารางน", "showAllViews": "แสดงมมมองทแชรงหมดของตารางน",
"collabView": "ผทำงานรวมกนททธแกไขหรอสงกวาสามารถเปลยนการกำหนดคามมมอง", "collabView": "ผทำงานรวมกนททธแกไขหรอสงกวาสามารถเปลยนการกำหนดคามมมอง",
@ -1283,9 +1303,14 @@
"editingSystemKeyNotSupported": "Editing system key not supported", "editingSystemKeyNotSupported": "Editing system key not supported",
"notAvailableAtTheMoment": "Not available at the moment", "notAvailableAtTheMoment": "Not available at the moment",
"groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column", "groupPasteIsNotSupportedOnLinksColumn": "Group paste operation is not supported on Links/LinkToAnotherRecord column",
"groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column" "groupClearIsNotSupportedOnLinksColumn": "Group clear operation is not supported on Links/LinkToAnotherRecord column",
"upgradeToEnterpriseEdition": "Upgrade to Enterprise Edition {extraInfo}",
"yourCurrentRoleIs": "Your current role is",
"pleaseRequestAccessForView": "Please request for higher permission from the Admin / Base owner / Workspace owner to get access to this {viewName}"
}, },
"error": { "error": {
"fetchingCalendarData": "Error fetching calendar data",
"fetchingActiveDates": "Error fetching active dates",
"scopesRequired": "Scopes required", "scopesRequired": "Scopes required",
"authUrlRequired": "Auth URL is required", "authUrlRequired": "Auth URL is required",
"userNameAttributeRequired": "Username attribute is required", "userNameAttributeRequired": "Username attribute is required",
@ -1376,7 +1401,8 @@
"multiFieldSaveValidation": "Please complete the configuration of all fields before saving", "multiFieldSaveValidation": "Please complete the configuration of all fields before saving",
"somethingWentWrong": "Something went wrong", "somethingWentWrong": "Something went wrong",
"draggedContentIsNotTypeOfImage": "Dragged content is not type of image", "draggedContentIsNotTypeOfImage": "Dragged content is not type of image",
"fieldToParseImageData": "Field to parse image data" "fieldToParseImageData": "Field to parse image data",
"someOfTheRequiredFieldsAreEmpty": "Some of the required fields are empty"
}, },
"toast": { "toast": {
"exportMetadata": "ขอมลเมตาของโครงการสงออกเรยบรอยแลว", "exportMetadata": "ขอมลเมตาของโครงการสงออกเรยบรอยแลว",

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

Loading…
Cancel
Save