Browse Source

Merge pull request #1138 from nocodb/develop

0.84.10 Pre-Release
pull/1140/head
navi 3 years ago committed by GitHub
parent
commit
8d96a8c977
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 96
      .github/workflows/ci-cd.yml
  2. 2
      README.md
  3. 2
      docker-compose/mssql/docker-compose.yml
  4. 2
      docker-compose/mysql/docker-compose.yml
  5. 2
      docker-compose/nginx-proxy-manager/docker-compose.yml
  6. 2
      docker-compose/pg/docker-compose.yml
  7. 6
      packages/nc-gui/components/ProjectTreeView.vue
  8. 14
      packages/nc-gui/components/project/spreadsheet/components/columnFilter.vue
  9. 8
      packages/nc-gui/components/project/spreadsheet/components/columnFilterMenu.vue
  10. 16
      packages/nc-gui/components/project/spreadsheet/components/fieldsMenu.vue
  11. 23
      packages/nc-gui/components/project/spreadsheet/components/importExport/columnMappingModal.vue
  12. 10
      packages/nc-gui/components/project/spreadsheet/components/moreActions.vue
  13. 3
      packages/nc-gui/components/project/spreadsheet/components/shareViewMenu.vue
  14. 10
      packages/nc-gui/components/project/spreadsheet/components/sortListMenu.vue
  15. 30
      packages/nc-gui/components/project/spreadsheet/public/xcTable.vue
  16. 25
      packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue
  17. 4
      packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue
  18. 2
      packages/nc-gui/components/project/tableTabs/columnsMock.vue
  19. 2
      packages/nc-gui/components/project/tableTabs/constraints.vue
  20. 2
      packages/nc-gui/components/project/tableTabs/indexes.vue
  21. 2
      packages/nc-gui/components/project/tableTabs/relations.vue
  22. 4
      packages/nc-gui/components/project/tableTabs/triggers.vue
  23. 104
      packages/nc-gui/components/project/viewTabs/viewSpreadsheet.vue
  24. 3
      packages/nc-gui/components/projectTabs.vue
  25. 10
      packages/nc-gui/components/sponsorMini.vue
  26. 5
      packages/nc-gui/components/templates/editor.vue
  27. 2
      packages/nc-gui/helpers/sqlUi/PgUi.js
  28. 3
      packages/nc-gui/lang/en.json
  29. 31
      packages/nc-gui/layouts/default.vue
  30. 2
      packages/nc-gui/store/tabs.js
  31. 6
      packages/noco-docs/content/en/getting-started/installation.md
  32. 2
      packages/noco-docs/content/en/setup-and-usages/audit.md
  33. 2
      packages/noco-docs/content/en/setup-and-usages/column-operations.md
  34. 2
      packages/noco-docs/content/en/setup-and-usages/column-types.md
  35. 2
      packages/noco-docs/content/en/setup-and-usages/dashboard.md
  36. 2
      packages/noco-docs/content/en/setup-and-usages/formulas.md
  37. 2
      packages/noco-docs/content/en/setup-and-usages/link-to-another-record.md
  38. 2
      packages/noco-docs/content/en/setup-and-usages/lookup.md
  39. 2
      packages/noco-docs/content/en/setup-and-usages/meta-management.md
  40. 2
      packages/noco-docs/content/en/setup-and-usages/primary-value.md
  41. 2
      packages/noco-docs/content/en/setup-and-usages/rollup.md
  42. 2
      packages/noco-docs/content/en/setup-and-usages/sync-schema.md
  43. 2
      packages/noco-docs/content/en/setup-and-usages/table-operations.md
  44. 2
      packages/noco-docs/content/en/setup-and-usages/team-and-auth.md
  45. 40
      packages/noco-docs/content/en/setup-and-usages/usage-information.md
  46. 28
      packages/nocodb/src/lib/noco/common/BaseApiBuilder.ts
  47. 11
      packages/nocodb/src/lib/noco/gql/GqlApiBuilder.ts
  48. 11
      packages/nocodb/src/lib/noco/rest/RestApiBuilder.ts
  49. 2
      packages/nocodb/src/lib/sqlUi/PgUi.ts
  50. 2
      scripts/cypress/integration/common/6b_downloadCsv.js
  51. 3
      scripts/cypress/integration/common/6d_language_validation.js
  52. 2
      scripts/markdown/readme/languages/chinese.md
  53. 2
      scripts/markdown/readme/languages/dutch.md
  54. 2
      scripts/markdown/readme/languages/french.md
  55. 2
      scripts/markdown/readme/languages/german.md
  56. 2
      scripts/markdown/readme/languages/indonesian.md
  57. 2
      scripts/markdown/readme/languages/italian.md
  58. 2
      scripts/markdown/readme/languages/japanese.md
  59. 2
      scripts/markdown/readme/languages/korean.md
  60. 2
      scripts/markdown/readme/languages/portuguese.md
  61. 2
      scripts/markdown/readme/languages/russian.md
  62. 2
      scripts/markdown/readme/languages/spanish.md

96
.github/workflows/ci-cd.yml

@ -55,6 +55,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: restTableOps-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-restViews-run: cypress-restViews-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -93,6 +99,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: restViews-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-restRoles-run: cypress-restRoles-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -131,6 +143,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: restRoles-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-restMisc-run: cypress-restMisc-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -169,6 +187,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: restMisc-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-xcdb-restTableOps-run: cypress-xcdb-restTableOps-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -206,6 +230,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: xcdb-restTableOps-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-xcdb-restViews-run: cypress-xcdb-restViews-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -244,6 +274,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: xcdb-restViews-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-xcdb-restRoles-run: cypress-xcdb-restRoles-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -282,6 +318,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: xcdb-restRoles-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-xcdb-restMisc-run: cypress-xcdb-restMisc-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -320,6 +362,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: xcdb-restMisc-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-gqlTableOps-run: cypress-gqlTableOps-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -358,6 +406,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: gqlTableOps-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-gqlViews-run: cypress-gqlViews-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -396,6 +450,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: gqlViews-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-gqlRoles-run: cypress-gqlRoles-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -434,6 +494,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: gqlRoles-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-gqlMisc-run: cypress-gqlMisc-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -472,6 +538,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: gqlMisc-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-xcdb-gqlTableOps-run: cypress-xcdb-gqlTableOps-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -510,6 +582,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: xcdb-gqlTableOps-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-xcdb-gqlViews-run: cypress-xcdb-gqlViews-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -548,6 +626,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: xcdb-gqlViews-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-xcdb-gqlRoles-run: cypress-xcdb-gqlRoles-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -586,6 +670,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: xcdb-gqlRoles-snapshots
path: scripts/cypress/screenshots
retention-days: 2
cypress-xcdb-gqlMisc-run: cypress-xcdb-gqlMisc-run:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
@ -624,6 +714,12 @@ jobs:
wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js" wait-on: "http://localhost:8080, http://localhost:3000/_nuxt/runtime.js"
wait-on-timeout: 1200 wait-on-timeout: 1200
config-file: scripts/cypress/cypress.json config-file: scripts/cypress/cypress.json
- name: Upload screenshots
uses: actions/upload-artifact@v2
with:
name: xcdb-gqlMisc-snapshots
path: scripts/cypress/screenshots
retention-days: 2
docker: docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

2
README.md

@ -224,7 +224,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Environment variables ## Environment variables

2
docker-compose/mssql/docker-compose.yml

@ -6,6 +6,7 @@ services:
restart: always restart: always
volumes: volumes:
- db_data:/var/opt/mssql - db_data:/var/opt/mssql
- nc_data:/usr/app/data
environment: environment:
SA_PASSWORD: Password123. SA_PASSWORD: Password123.
ACCEPT_EULA: Y ACCEPT_EULA: Y
@ -28,3 +29,4 @@ services:
NC_DB: "mssql://root_db:1433?u=sa&p=Password123.&d=root_db" NC_DB: "mssql://root_db:1433?u=sa&p=Password123.&d=root_db"
volumes: volumes:
db_data: {} db_data: {}
nc_data: {}

2
docker-compose/mysql/docker-compose.yml

@ -5,6 +5,7 @@ services:
image: mysql:5.7 image: mysql:5.7
volumes: volumes:
- db_data:/var/lib/mysql - db_data:/var/lib/mysql
- nc_data:/usr/app/data
restart: always restart: always
environment: environment:
MYSQL_ROOT_PASSWORD: password MYSQL_ROOT_PASSWORD: password
@ -28,3 +29,4 @@ services:
NC_DB: "mysql2://root_db:3306?u=noco&p=password&d=root_db" NC_DB: "mysql2://root_db:3306?u=noco&p=password&d=root_db"
volumes: volumes:
db_data: {} db_data: {}
nc_data: {}

2
docker-compose/nginx-proxy-manager/docker-compose.yml

@ -5,6 +5,7 @@ services:
image: mysql:5.7 image: mysql:5.7
volumes: volumes:
- db_data:/var/lib/mysql - db_data:/var/lib/mysql
- nc_data:/usr/app/data
restart: always restart: always
environment: environment:
MYSQL_ROOT_PASSWORD: password MYSQL_ROOT_PASSWORD: password
@ -49,6 +50,7 @@ services:
volumes: volumes:
nginx-proxy-manager: {} nginx-proxy-manager: {}
db_data: {} db_data: {}
nc_data: {}
networks: networks:
default: default:

2
docker-compose/pg/docker-compose.yml

@ -6,6 +6,7 @@ services:
restart: always restart: always
volumes: volumes:
- db_data:/var/lib/postgresql/data - db_data:/var/lib/postgresql/data
- nc_data:/usr/app/data
environment: environment:
POSTGRES_PASSWORD: password POSTGRES_PASSWORD: password
POSTGRES_USER: postgres POSTGRES_USER: postgres
@ -27,3 +28,4 @@ services:
NC_DB: "pg://root_db:5432?u=postgres&p=password&d=root_db" NC_DB: "pg://root_db:5432?u=postgres&p=password&d=root_db"
volumes: volumes:
db_data: {} db_data: {}
nc_data: {}

6
packages/nc-gui/components/ProjectTreeView.vue

@ -32,7 +32,7 @@
<v-text-field <v-text-field
v-else v-else
v-model="search" v-model="search"
placeholder="Search tables" :placeholder="$t('placeholder.searchProjectTree')"
dense dense
hide-details hide-details
class="elevation-0 mr-2 pl-3 pr-1 caption nc-table-list-filter" class="elevation-0 mr-2 pl-3 pr-1 caption nc-table-list-filter"
@ -162,7 +162,7 @@
<v-tooltip v-if="!isNonAdminAccessAllowed(item)" top> <v-tooltip v-if="!isNonAdminAccessAllowed(item)" top>
<template #activator="{ on }"> <template #activator="{ on }">
<span v-if="item.type === 'tableDir'" class="body-2 font-weight-medium" v-on="on"> <span v-if="item.type === 'tableDir'" class="body-2 font-weight-medium" v-on="on">
Tables<template v-if="item.children && item.children.length"> ({{ {{ $t('objects.tables') }}<template v-if="item.children && item.children.length"> ({{
item.children.filter(child => !search || child.name.toLowerCase().includes(search.toLowerCase())).length item.children.filter(child => !search || child.name.toLowerCase().includes(search.toLowerCase())).length
}})</template></span> }})</template></span>
<span v-else class="body-2 font-weight-medium" v-on="on"> <span v-else class="body-2 font-weight-medium" v-on="on">
@ -174,7 +174,7 @@
v-else v-else
> >
<span v-if="item.type === 'tableDir'" class="body-2 font-weight-medium"> <span v-if="item.type === 'tableDir'" class="body-2 font-weight-medium">
Tables<template v-if="item.children && item.children.length"> ({{ {{ $t('objects.tables') }}<template v-if="item.children && item.children.length"> ({{
item.children.filter(child => !search || child.name.toLowerCase().includes(search.toLowerCase())).length item.children.filter(child => !search || child.name.toLowerCase().includes(search.toLowerCase())).length
}})</template></span> }})</template></span>
<span v-else class="caption font-weight-regular"> <span v-else class="caption font-weight-regular">

14
packages/nc-gui/components/project/spreadsheet/components/columnFilter.vue

@ -20,7 +20,10 @@
v-if="!i" v-if="!i"
:key="i + '_2'" :key="i + '_2'"
class="caption d-flex align-center" class="caption d-flex align-center"
>where</span> >
<!-- where -->
{{ $t('labels.where') }}
</span>
<v-select <v-select
v-else v-else
@ -44,7 +47,7 @@
:key="i + '_5'" :key="i + '_5'"
v-model="filter.field" v-model="filter.field"
class="caption " class="caption "
placeholder="Field" :placeholder="$t('objects.field')"
solo solo
flat flat
dense dense
@ -62,7 +65,7 @@
v-model="filter.field" v-model="filter.field"
class="caption nc-filter-field-select" class="caption nc-filter-field-select"
:items="fieldList" :items="fieldList"
placeholder="Field" :placeholder="$t('objects.field')"
solo solo
flat flat
dense dense
@ -79,7 +82,7 @@
v-model="filter.op" v-model="filter.op"
class="flex-shrink-1 flex-grow-0 caption nc-filter-operation-select" class="flex-shrink-1 flex-grow-0 caption nc-filter-operation-select"
:items="opList" :items="opList"
placeholder="Operation" :placeholder="$t('labels.operation')"
solo solo
flat flat
style="max-width:120px" style="max-width:120px"
@ -126,7 +129,8 @@
<v-icon small color="grey"> <v-icon small color="grey">
mdi-plus mdi-plus
</v-icon> </v-icon>
Add Filter <!-- Add Filter -->
{{ $t('activity.addFilter') }}
</v-btn> </v-btn>
<slot /> <slot />
</div> </div>

8
packages/nc-gui/components/project/spreadsheet/components/columnFilterMenu.vue

@ -19,7 +19,8 @@
<v-icon small class="mr-1" color="grey darken-3"> <v-icon small class="mr-1" color="grey darken-3">
mdi-filter-outline mdi-filter-outline
</v-icon> </v-icon>
Filter <!-- Filter -->
{{ $t('activity.filter') }}
<v-icon small color="#777"> <v-icon small color="#777">
mdi-menu-down mdi-menu-down
</v-icon> </v-icon>
@ -38,7 +39,10 @@
color="grey" color="grey"
> >
<template #label> <template #label>
<span class="grey--text caption">Auto apply</span> <span class="grey--text caption">
{{ $t('msg.info.filterAutoApply') }}
<!-- Auto apply -->
</span>
</template> </template>
</v-checkbox> </v-checkbox>

16
packages/nc-gui/components/project/spreadsheet/components/fieldsMenu.vue

@ -19,7 +19,8 @@
<v-icon small class="mr-1" color="#777"> <v-icon small class="mr-1" color="#777">
mdi-eye-off-outline mdi-eye-off-outline
</v-icon> </v-icon>
Fields <!-- Fields -->
{{ $t('objects.fields') }}
<v-icon small color="#777"> <v-icon small color="#777">
mdi-menu-down mdi-menu-down
</v-icon> </v-icon>
@ -86,7 +87,7 @@
flat flat
class="caption mt-3 mb-2" class="caption mt-3 mb-2"
color="grey" color="grey"
placeholder="Search fields" :placeholder="$t('placeholder.searchFields')"
hide-details hide-details
@click.stop @click.stop
> >
@ -137,16 +138,21 @@
@click.stop @click.stop
> >
<template #label> <template #label>
<span class="caption">Show System Fields</span> <span class="caption">
<!-- Show System Fields -->
{{ $t('activity.showSystemFields') }}
</span>
</template> </template>
</v-checkbox> </v-checkbox>
</v-list-item> </v-list-item>
<v-list-item dense class="mt-2 list-btn mb-3"> <v-list-item dense class="mt-2 list-btn mb-3">
<v-btn small class="elevation-0 grey--text" @click.stop="showAll"> <v-btn small class="elevation-0 grey--text" @click.stop="showAll">
Show All <!-- Show All -->
{{ $t('general.showAll') }}
</v-btn> </v-btn>
<v-btn small class="elevation-0 grey--text" @click.stop="hideAll"> <v-btn small class="elevation-0 grey--text" @click.stop="hideAll">
Hide All <!-- Hide All -->
{{ $t('general.hideAll') }}
</v-btn> </v-btn>
</v-list-item> </v-list-item>
</v-list> </v-list>

23
packages/nc-gui/components/project/spreadsheet/components/importExport/columnMappingModal.vue

@ -7,7 +7,11 @@
</v-card-title> </v-card-title>
<v-spacer /> <v-spacer />
<v-btn <v-btn
:disabled="!valid || requiredColumnValidationError" :disabled="
!valid ||
(typeof requiredColumnValidationError === 'string' || requiredColumnValidationError) ||
(typeof noSelectedColumnError === 'string' || noSelectedColumnError)
"
color="primary" color="primary"
large large
@click="$emit('import',mappings)" @click="$emit('import',mappings)"
@ -21,6 +25,9 @@
<div v-if="requiredColumnValidationError" class="error--text caption pa-2 text-center"> <div v-if="requiredColumnValidationError" class="error--text caption pa-2 text-center">
{{ requiredColumnValidationError }} {{ requiredColumnValidationError }}
</div> </div>
<div v-if="noSelectedColumnError" class="error--text caption pa-2 text-center">
{{ noSelectedColumnError }}
</div>
<v-divider /> <v-divider />
<v-container fluid> <v-container fluid>
<v-form ref="form" v-model="valid"> <v-form ref="form" v-model="valid">
@ -39,7 +46,7 @@
<tbody> <tbody>
<tr v-for="(r,i) in mappings" :key="i"> <tr v-for="(r,i) in mappings" :key="i">
<td> <td>
<v-checkbox v-model="r.enabled" class="mt-0" dense hide-details /> <v-checkbox v-model="r.enabled" class="mt-0" dense hide-details @change="$refs.form.validate()"/>
</td> </td>
<td class="caption" style="width:45%"> <td class="caption" style="width:45%">
<div :title="r.sourceCn" style=""> <div :title="r.sourceCn" style="">
@ -117,6 +124,12 @@ export default {
return `Following columns are required : ${missingRequiredColumns.map(c => c._cn).join(', ')}` return `Following columns are required : ${missingRequiredColumns.map(c => c._cn).join(', ')}`
} }
return false return false
},
noSelectedColumnError() {
if ((this.mappings || []).filter(v => v.enabled === true).length == 0) {
return 'At least one column has to be selected'
}
return false
} }
}, },
mounted() { mounted() {
@ -129,6 +142,11 @@ export default {
return true return true
} }
// if it is not selected, then pass validation
if (!row.enabled) {
return true
}
const v = this.meta && this.meta.columns.find(c => c._cn === _cn) const v = this.meta && this.meta.columns.find(c => c._cn === _cn)
if ((this.mappings || []).filter(v => v.destCn === _cn).length > 1) { return 'Duplicate mapping found, please remove one of the mapping' } if ((this.mappings || []).filter(v => v.destCn === _cn).length > 1) { return 'Duplicate mapping found, please remove one of the mapping' }
@ -154,6 +172,7 @@ export default {
} }
this.mappings.push(o) this.mappings.push(o)
} }
this.$nextTick(()=> this.$refs.form.validate())
}, },
getIcon(uidt) { getIcon(uidt) {
return getUIDTIcon(uidt) || 'mdi-alpha-v-circle-outline' return getUIDTIcon(uidt) || 'mdi-alpha-v-circle-outline'

10
packages/nc-gui/components/project/spreadsheet/components/moreActions.vue

@ -34,7 +34,8 @@
mdi-download-outline mdi-download-outline
</v-icon> </v-icon>
<span class="caption"> <span class="caption">
Download as CSV <!-- Download as CSV -->
{{ $t('activity.downloadCSV') }}
</span> </span>
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
@ -48,7 +49,8 @@
mdi-upload-outline mdi-upload-outline
</v-icon> </v-icon>
<span class="caption "> <span class="caption ">
Upload CSV <!-- Upload CSV -->
{{ $t('activity.uploadCSV') }}
</span> </span>
<span class="caption grey--text">(<x-icon small color="grey lighten-2"> <span class="caption grey--text">(<x-icon small color="grey lighten-2">
@ -66,7 +68,8 @@
mdi-view-list-outline mdi-view-list-outline
</v-icon> </v-icon>
<span class="caption "> <span class="caption ">
Shared View List <!-- Shared View List -->
{{ $t('activity.listSharedView') }}
</span> </span>
</v-list-item-title> </v-list-item-title>
</v-list-item> <v-list-item </v-list-item> <v-list-item
@ -286,6 +289,7 @@ export default {
} }
this.columnMappingModal = false this.columnMappingModal = false
this.$store.commit('loader/MutClear') this.$store.commit('loader/MutClear')
this.$emit('reload')
this.$toast.success('Successfully imported table data').goAway(3000) this.$toast.success('Successfully imported table data').goAway(3000)
} catch (e) { } catch (e) {
this.$toast.error(e.message).goAway(3000) this.$toast.error(e.message).goAway(3000)

3
packages/nc-gui/components/project/spreadsheet/components/shareViewMenu.vue

@ -17,7 +17,8 @@
<v-icon size="13" class="mr-1" color="#777"> <v-icon size="13" class="mr-1" color="#777">
mdi-open-in-new mdi-open-in-new
</v-icon> </v-icon>
Share View <!-- Share View -->
{{ $t('activity.shareView') }}
</v-btn> </v-btn>
<!-- </template> <!-- </template>

10
packages/nc-gui/components/project/spreadsheet/components/sortListMenu.vue

@ -19,7 +19,8 @@
<v-icon small class="mr-1" color="#777"> <v-icon small class="mr-1" color="#777">
mdi-sort mdi-sort
</v-icon> </v-icon>
Sort <!-- Sort -->
{{ $t('activity.sort') }}
<v-icon small color="#777"> <v-icon small color="#777">
mdi-menu-down mdi-menu-down
</v-icon> </v-icon>
@ -38,7 +39,7 @@
v-model="sort.field" v-model="sort.field"
class="caption nc-sort-field-select" class="caption nc-sort-field-select"
:items="fieldList" :items="fieldList"
label="Field" :label="$t('objects.field')"
solo solo
flat flat
dense dense
@ -54,7 +55,7 @@
v-model="sort.order" v-model="sort.order"
class="flex-shrink-1 flex-grow-0 caption nc-sort-dir-select" class="flex-shrink-1 flex-grow-0 caption nc-sort-dir-select"
:items="[{text : 'A -> Z', value: ''},{text : 'Z -> A', value: '-'}]" :items="[{text : 'A -> Z', value: ''},{text : 'Z -> A', value: '-'}]"
label="Operation" :label="$t('labels.operation')"
solo solo
flat flat
dense dense
@ -71,7 +72,8 @@
<v-icon small color="grey"> <v-icon small color="grey">
mdi-plus mdi-plus
</v-icon> </v-icon>
Add Sort Option <!-- Add Sort Option -->
{{ $t('activity.addSort') }}
</v-btn> </v-btn>
</div> </div>
</v-menu> </v-menu>

30
packages/nc-gui/components/project/spreadsheet/public/xcTable.vue

@ -15,14 +15,19 @@
<span class="font-weight-bold"> {{ viewName }}</span> <span class="font-weight-regular ml-1" /> <span class="font-weight-bold"> {{ viewName }}</span> <span class="font-weight-regular ml-1" />
</div> </div>
<v-toolbar v-if="meta" height="40" dense class="elevation-0 xc-toolbar xc-border-bottom" style="z-index: 7;border-radius: 4px"> <v-toolbar
<!-- v-if="meta"
<div class="d-flex xc-border align-center search-box"> height="32"
dense
class="nc-table-toolbar elevation-0 xc-toolbar xc-border-bottom mx-1"
style="z-index: 7"
>
<div class="d-flex xc-border align-center search-box" style="min-width:156px">
<v-menu bottom offset-y> <v-menu bottom offset-y>
<template #activator="{on}"> <template #activator="{on}">
<div v-on="on"> <div style="min-width: 56px" v-on="on">
<v-icon <v-icon
class="pa-1 pr-0 ml-2" class="ml-2"
small small
color="grey" color="grey"
> >
@ -56,7 +61,7 @@
<v-text-field <v-text-field
v-model="searchQuery" v-model="searchQuery"
autocomplete="off" autocomplete="off"
style="min-width: 300px" style="min-width: 100px ; width: 150px"
flat flat
dense dense
solo solo
@ -74,16 +79,15 @@
>{{ refTable }}({{ >{{ refTable }}({{
relationPrimaryValue relationPrimaryValue
}}) -> {{ relationType === 'hm' ? ' Has Many ' : ' Belongs To ' }} -> {{ table }}</span> }}) -> {{ relationType === 'hm' ? ' Has Many ' : ' Belongs To ' }} -> {{ table }}</span>
-->
<v-spacer /> <div class="d-inline-flex">
<v-btn outlined small text @click="reload"> <!-- <v-btn outlined small text @click="reload">
<v-icon small class="mr-1" color="grey darken-3"> <v-icon small class="mr-1" color="grey darken-3">
mdi-reload mdi-reload
</v-icon> </v-icon>
Reload Reload
</v-btn> </v-btn> -->
<fields-menu v-model="showFields" :field-list="fieldList" is-public /> <fields-menu v-model="showFields" :field-list="fieldList" is-public />
@ -92,7 +96,8 @@
<column-filter-menu v-model="filters" :field-list="realFieldList" /> <column-filter-menu v-model="filters" :field-list="realFieldList" />
<csv-export-import :is-view="isView" :query-params="{...queryParams, showFields}" :public-view-id="$route.params.id" :meta="meta" /> <csv-export-import :is-view="isView" :query-params="{...queryParams, showFields}" :public-view-id="$route.params.id" :meta="meta" />
</div>
<v-spacer class="h-100" @dblclick="debug=true" />
<!-- <v-menu> <!-- <v-menu>
<template #activator="{ on, attrs }"> <template #activator="{ on, attrs }">
<v-icon <v-icon
@ -293,7 +298,7 @@ export default {
concatenatedXWhere() { concatenatedXWhere() {
let where = '' let where = ''
if (this.searchField && this.searchQuery.trim()) { if (this.searchField && this.searchQuery.trim()) {
if (['text', 'string'].includes(this.sqlUi.getAbstractType(this.meta.columns.find(({ cn }) => cn === this.searchField)))) { if (['text', 'string'].includes(this.sqlUi.getAbstractType(this.meta.columns.find(({ _cn }) => _cn === this.searchField)))) {
where = `(${this.searchField},like,%${this.searchQuery.trim()}%)` where = `(${this.searchField},like,%${this.searchQuery.trim()}%)`
} else { } else {
where = `(${this.searchField},eq,${this.searchQuery.trim()})` where = `(${this.searchField},eq,${this.searchQuery.trim()})`
@ -720,6 +725,7 @@ export default {
* *
* @author Naveen MR <oof1lab@gmail.com> * @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com> * @author Pranav C Balan <pranavxc@gmail.com>
* @author Wing-Kam Wong <wingkwong.code@gmail.com>
* *
* @license GNU AGPL version 3 or any later version * @license GNU AGPL version 3 or any later version
* *

25
packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue

@ -50,7 +50,7 @@
dense dense
solo solo
hide-details hide-details
:placeholder="searchField ? `Search '${searchField}' column` : 'Search all columns'" :placeholder="searchField ? $t('placeholder.searchColumn', {searchField}) : 'Search all columns'"
class="elevation-0 pa-0 flex-grow-1 caption search-field" class="elevation-0 pa-0 flex-grow-1 caption search-field"
@keyup.enter="searchQuery = searchQueryVal" @keyup.enter="searchQuery = searchQueryVal"
@blur="searchQuery = searchQueryVal" @blur="searchQuery = searchQueryVal"
@ -110,6 +110,7 @@
:selected-view="selectedView" :selected-view="selectedView"
@showAdditionalFeatOverlay="showAdditionalFeatOverlay($event)" @showAdditionalFeatOverlay="showAdditionalFeatOverlay($event)"
@webhook="showAdditionalFeatOverlay('webhooks')" @webhook="showAdditionalFeatOverlay('webhooks')"
@reload="reload"
/> />
</div> </div>
<v-spacer class="h-100" @dblclick="debug=true" /> <v-spacer class="h-100" @dblclick="debug=true" />
@ -138,6 +139,7 @@
<v-icon small class="mx-n1" color="grey lighten-1"> <v-icon small class="mx-n1" color="grey lighten-1">
mdi-circle-small mdi-circle-small
</v-icon> </v-icon>
<!-- tooltip="Reload view data" -->
<x-icon <x-icon
tooltip="Reload view data" tooltip="Reload view data"
icon.class="nc-table-reload-btn mx-1" icon.class="nc-table-reload-btn mx-1"
@ -165,10 +167,12 @@
<!-- btn.class="nc-add-new-row-btn"--> <!-- btn.class="nc-add-new-row-btn"-->
<!-- @click="insertNewRow(true,true)"--> <!-- @click="insertNewRow(true,true)"-->
<!-- >--> <!-- >-->
<!-- tooltip="Add new row"-->
<x-icon <x-icon
v-if="isEditable && relationType !== 'bt'" v-if="isEditable && relationType !== 'bt'"
icon.class="nc-add-new-row-btn mx-1" icon.class="nc-add-new-row-btn mx-1"
tooltip="Add new row" :tooltip="$t('activity.addRow')"
:disabled="isLocked" :disabled="isLocked"
small small
:color="['success','']" :color="['success','']"
@ -219,7 +223,7 @@
:disabled="isLocked" :disabled="isLocked"
small small
:color="['red',''] " :color="['red',''] "
tooltip="Delete table" :tooltip="$t('activity.deleteTable')"
@click="checkAndDeleteTable" @click="checkAndDeleteTable"
> >
mdi-delete-outline mdi-delete-outline
@ -524,13 +528,22 @@
v-if="relationType !== 'bt'" v-if="relationType !== 'bt'"
@click="insertNewRow(false)" @click="insertNewRow(false)"
> >
<span class="caption">Insert New Row</span> <span class="caption">
<!-- Insert New Row -->
{{ $t('activity.insertRow') }}
</span>
</v-list-item> </v-list-item>
<v-list-item @click="deleteRow"> <v-list-item @click="deleteRow">
<span class="caption">Delete Row</span> <span class="caption">
<!-- Delete Row -->
{{ $t('activity.deleteRow') }}
</span>
</v-list-item> </v-list-item>
<v-list-item @click="deleteSelectedRows"> <v-list-item @click="deleteSelectedRows">
<span class="caption">Delete Selected Rows</span> <span class="caption">
<!-- Delete Selected Rows -->
{{ $t('activity.deleteSelectedRow') }}
</span>
</v-list-item> </v-list-item>
</template> </template>
<template v-if="rowContextMenu.col && !rowContextMenu.col.rqd && !rowContextMenu.col.virtual"> <template v-if="rowContextMenu.col && !rowContextMenu.col.rqd && !rowContextMenu.col.virtual">

4
packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue

@ -244,7 +244,9 @@
<v-icon small color="pink" v-on="on"> <v-icon small color="pink" v-on="on">
mdi-plus mdi-plus
</v-icon> </v-icon>
<span class="ml-1 caption grey--text ">New Row</span> <span class="ml-1 caption grey--text ">
{{ $t('activity.addRow') }}
</span>
</template> </template>
<span class="caption"> Add new row</span> <span class="caption"> Add new row</span>
</v-tooltip> </v-tooltip>

2
packages/nc-gui/components/project/tableTabs/columnsMock.vue

@ -69,7 +69,7 @@
class="error text-right" class="error text-right"
@click="deleteTable('showDialog')" @click="deleteTable('showDialog')"
> >
Delete Table &nbsp; {{ $t('activity.deleteTable') }} &nbsp;
<v-progress-circular <v-progress-circular
v-if="progress.deleteTable" v-if="progress.deleteTable"

2
packages/nc-gui/components/project/tableTabs/constraints.vue

@ -45,7 +45,7 @@
class="error text-right" class="error text-right"
@click="deleteTable('showDialog')" @click="deleteTable('showDialog')"
> >
Delete Table {{ $t('activity.deleteTable') }}
</v-btn> </v-btn>
<v-btn <v-btn
icon icon

2
packages/nc-gui/components/project/tableTabs/indexes.vue

@ -65,7 +65,7 @@
<x-btn <x-btn
v-ge="['indexes','delete-table']" v-ge="['indexes','delete-table']"
outlined outlined
tooltip="Delete Table" :tooltip="$t('activity.deleteTable')"
small small
color="error " color="error "
class="error text-right" class="error text-right"

2
packages/nc-gui/components/project/tableTabs/relations.vue

@ -15,7 +15,7 @@
class=" text-right" class=" text-right"
@click="deleteTable('showDialog')" @click="deleteTable('showDialog')"
> >
Delete Table {{ $t('activity.deleteTable') }}
</v-btn> </v-btn>
<v-btn @click="throwError()"> <v-btn @click="throwError()">
error error

4
packages/nc-gui/components/project/tableTabs/triggers.vue

@ -65,14 +65,14 @@
<x-btn <x-btn
v-ge="['triggers','delete']" v-ge="['triggers','delete']"
outlined outlined
tooltip="Delete Table" :tooltip="$t('activity.deleteTable')"
small small
icon="mdi-delete-outline" icon="mdi-delete-outline"
class="error text-right" class="error text-right"
color="error " color="error "
@click="deleteTable('showDialog')" @click="deleteTable('showDialog')"
> >
Delete Table {{ $t('activity.deleteTable') }}
</x-btn> </x-btn>
</v-toolbar> </v-toolbar>
<v-skeleton-loader v-if="loading" type="table" /> <v-skeleton-loader v-if="loading" type="table" />

104
packages/nc-gui/components/project/viewTabs/viewSpreadsheet.vue

@ -1,16 +1,20 @@
<template> <template>
<v-container class=" j-excel-container pa-0 ma-0" fluid> <v-container class="h-100 j-excel-container backgroundColor pa-0 ma-0" fluid>
<div v-if="modelName" class="model-name text-capitalize"> <div v-if="modelName" class="model-name text-capitalize">
<span class="font-weight-bold"> {{ modelName }}</span> <span class="font-weight-regular ml-1">( Main View )</span> <span class="font-weight-bold"> {{ modelName }}</span> <span class="font-weight-regular ml-1">( Main View )</span>
</div> </div>
<v-toolbar
<v-toolbar height="36" dense class="elevation-0 xc-toolbar xc-border-bottom" style="z-index: 7;border-radius: 4px"> height="32"
<div class="d-flex xc-border align-center search-box"> dense
class="nc-table-toolbar elevation-0 xc-toolbar xc-border-bottom mx-1"
style="z-index: 7"
>
<div class="d-flex xc-border align-center search-box" style="min-width:156px">
<v-menu bottom offset-y> <v-menu bottom offset-y>
<template #activator="{on}"> <template #activator="{on}">
<div v-on="on"> <div style="min-width: 56px" v-on="on">
<v-icon <v-icon
class="pa-1 pr-0 ml-2" class="ml-2"
small small
color="grey" color="grey"
> >
@ -44,7 +48,7 @@
<v-text-field <v-text-field
v-model="searchQuery" v-model="searchQuery"
autocomplete="off" autocomplete="off"
style="min-width: 300px" style="min-width: 100px ; width: 150px"
flat flat
dense dense
solo solo
@ -63,48 +67,50 @@
relationPrimaryValue relationPrimaryValue
}}) -> {{ relationType === 'hm' ? ' Has Many ' : ' Belongs To ' }} -> {{ table }}</span> }}) -> {{ relationType === 'hm' ? ' Has Many ' : ' Belongs To ' }} -> {{ table }}</span>
<v-spacer /> <div class="d-inline-flex">
<v-btn outlined small text @click="loadTableData"> <fields-menu v-model="showFields" :field-list="fieldList" :is-locked="isLocked" />
<v-icon small class="mr-1" color="grey darken-3">
mdi-reload
</v-icon>
Reload
</v-btn>
<fields-menu v-model="showFields" :field-list="fieldList" /> <sort-list-menu v-model="sortList" :field-list="fieldList" :is-locked="isLocked" />
<sort-list-menu v-model="sortList" :field-list="fieldList" /> <column-filter-menu v-model="filters" :field-list="fieldList" :is-locked="isLocked" />
<column-filter-menu v-model="filters" :field-list="fieldList" /> <share-view-menu @share="$refs.drawer && $refs.drawer.genShareLink()" />
<!-- <v-menu> <MoreActions
<template #activator="{ on, attrs }"> ref="csvExportImport"
<v-icon :meta="meta"
v-bind="attrs" :nodes="nodes"
:query-params="{
fieldsOrder,
fieldFilter,
sortList,
showFields
}"
:selected-view="selectedView"
:is-view="true"
@showAdditionalFeatOverlay="showAdditionalFeatOverlay($event)"
@webhook="showAdditionalFeatOverlay('webhooks')"
/>
</div>
<v-spacer class="h-100" @dblclick="debug=true" />
<template>
<debug-metas v-if="debug" class="mr-3" />
<lock-menu v-if="_isUIAllowed('view-type')" v-model="viewStatus.type" />
<v-icon small class="mx-n1" color="grey lighten-1">
mdi-circle-small
</v-icon>
<x-icon
tooltip="Reload view data"
icon.class="nc-table-reload-btn mx-1"
small small
class="mx-2" @click="loadTableData"
color="grey darken-3"
v-on="on"
> >
mdi-arrow-collapse-vertical mdi-reload
</v-icon> </x-icon>
</template> </template>
<v-list dense class="caption">
<v-list-item v-for="h in cellHeights" :key="h.size" dense @click.stop="cellHeight = h.size">
<v-list-item-icon class="mr-1">
<v-icon small :color="cellHeight === h.size && 'primary'">
{{ h.icon }}
</v-icon>
</v-list-item-icon>
<v-list-item-title :class="{'primary&#45;&#45;text' : cellHeight === h.size}" style="text-transform: capitalize">
{{ h.size }}
</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>-->
<x-btn <x-btn
tooltip="Toggle navigation drawer" tooltip="Toggle navigation drawer"
outlined outlined
@ -195,6 +201,7 @@
</div> </div>
<spreadsheet-nav-drawer <spreadsheet-nav-drawer
ref="drawer"
:nodes="nodes" :nodes="nodes"
:table="table" :table="table"
:meta="meta" :meta="meta"
@ -208,6 +215,7 @@
:filters.sync="filters" :filters.sync="filters"
:sort-list.sync="sortList" :sort-list.sync="sortList"
:show-fields.sync="showFields" :show-fields.sync="showFields"
:view-status.sync="viewStatus"
> >
<!-- <v-list-item <!-- <v-list-item
@click="showAdditionalFeatOverlay('view-columns')" @click="showAdditionalFeatOverlay('view-columns')"
@ -239,7 +247,6 @@
<script> <script>
import debounce from 'debounce' import debounce from 'debounce'
import ApiFactory from '@/components/project/spreadsheet/apis/apiFactory'
import { SqlUI } from '@/helpers/sqlUi/SqlUiFactory' import { SqlUI } from '@/helpers/sqlUi/SqlUiFactory'
import FieldsMenu from '@/components/project/spreadsheet/components/fieldsMenu' import FieldsMenu from '@/components/project/spreadsheet/components/fieldsMenu'
import SortListMenu from '@/components/project/spreadsheet/components/sortListMenu' import SortListMenu from '@/components/project/spreadsheet/components/sortListMenu'
@ -251,6 +258,10 @@ import KanbanView from '@/components/project/spreadsheet/views/kanbanView'
import CalendarView from '@/components/project/spreadsheet/views/calendarView' import CalendarView from '@/components/project/spreadsheet/views/calendarView'
import AdditionalFeatures from '@/components/project/spreadsheet/overlay/additinalFeatures' import AdditionalFeatures from '@/components/project/spreadsheet/overlay/additinalFeatures'
import spreadsheet from '@/components/project/spreadsheet/mixins/spreadsheet' import spreadsheet from '@/components/project/spreadsheet/mixins/spreadsheet'
import MoreActions from '@/components/project/spreadsheet/components/moreActions'
import ShareViewMenu from '@/components/project/spreadsheet/components/shareViewMenu'
import LockMenu from '@/components/project/spreadsheet/components/lockMenu'
export default { export default {
name: 'Spreadsheet', name: 'Spreadsheet',
@ -263,7 +274,10 @@ export default {
XcGridView, XcGridView,
ColumnFilterMenu, ColumnFilterMenu,
SortListMenu, SortListMenu,
FieldsMenu FieldsMenu,
ShareViewMenu,
MoreActions,
LockMenu,
}, },
mixins: [spreadsheet], mixins: [spreadsheet],
props: { props: {
@ -340,7 +354,10 @@ export default {
icon: 'mdi-card' icon: 'mdi-card'
}], }],
rowContextMenu: null, rowContextMenu: null,
modelName: null modelName: null,
viewStatus: {
type: null
},
}), }),
computed: { computed: {
meta() { meta() {
@ -638,6 +655,7 @@ export default {
* *
* @author Naveen MR <oof1lab@gmail.com> * @author Naveen MR <oof1lab@gmail.com>
* @author Pranav C Balan <pranavxc@gmail.com> * @author Pranav C Balan <pranavxc@gmail.com>
* @author Wing-Kam Wong <wingkwong.code@gmail.com>
* *
* @license GNU AGPL version 3 or any later version * @license GNU AGPL version 3 or any later version
* *

3
packages/nc-gui/components/projectTabs.vue

@ -253,9 +253,10 @@
<!-- </v-tabs-items>--> <!-- </v-tabs-items>-->
</v-tabs-items> </v-tabs-items>
<!-- tooltip: Add new table -->
<x-icon <x-icon
v-if="_isUIAllowed('addTable')" v-if="_isUIAllowed('addTable')"
tooltip="Create new table" :tooltip="$t('tooltip.addTable')"
icon-class="add-btn" icon-class="add-btn"
:color="[ 'white','grey lighten-2']" :color="[ 'white','grey lighten-2']"
@click="dialogCreateTableShow = true" @click="dialogCreateTableShow = true"

10
packages/nc-gui/components/sponsorMini.vue

@ -14,14 +14,16 @@
/> />
</template> </template>
</v-img> </v-img>
<!-- You can help us! -->
<v-card-title v-if="!nav" class="pb-2" :class="{'body-2 justify-center mt-n2' : nav}"> <v-card-title v-if="!nav" class="pb-2" :class="{'body-2 justify-center mt-n2' : nav}">
You can help us {{ $t('msg.info.sponsor.header') }}
</v-card-title> </v-card-title>
<v-card-text v-if="!nav" class="pb-0"> <v-card-text v-if="!nav" class="pb-0">
<p class="caption text-left body-1 textColor--text text--lighten-1"> <p class="caption text-left body-1 textColor--text text--lighten-1">
<template> <template>
We are a tiny team working full time to make NocoDB open source. We believe a tool like NocoDB should be <!-- We are a tiny team working full time to make NocoDB open source. We believe a tool like NocoDB should be
available freely to every problem solver on internet. available freely to every problem solver on internet. -->
{{ $t('msg.info.sponsor.message') }}
</template> </template>
</p> </p>
</v-card-text> </v-card-text>
@ -30,7 +32,7 @@
<v-icon small color="red" class="mr-2"> <v-icon small color="red" class="mr-2">
mdi-cards-heart mdi-cards-heart
</v-icon> </v-icon>
Sponsor Us {{ $t('activity.sponsorUs') }}
</v-btn> </v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>

5
packages/nc-gui/components/templates/editor.vue

@ -578,7 +578,10 @@
<v-icon>mdi-plus</v-icon> <v-icon>mdi-plus</v-icon>
</v-btn> </v-btn>
</template> </template>
<span class="caption">Add new table</span> <span class="caption">
<!--Add new table-->
{{ $t('tooltip.addTable') }}
</span>
</v-tooltip> </v-tooltip>
</div> </div>
</template> </template>

2
packages/nc-gui/helpers/sqlUi/PgUi.js

@ -1609,7 +1609,7 @@ export class PgUi {
colProp.validate = { func: ['isCurrency'], args: [''], msg: ['Validation failed : Invalid Currency Format'] } colProp.validate = { func: ['isCurrency'], args: [''], msg: ['Validation failed : Invalid Currency Format'] }
break break
case 'Percent': case 'Percent':
colProp.dt = 'double' colProp.dt = 'float8'
break break
case 'Duration': case 'Duration':
colProp.dt = 'int8' colProp.dt = 'int8'

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

@ -260,6 +260,7 @@
"createTable": "Table Create", "createTable": "Table Create",
"refreshTable": "Tables Refresh", "refreshTable": "Tables Refresh",
"renameTable": "Table Rename", "renameTable": "Table Rename",
"deleteTable": "Table Delete",
"addField": "Add new field to this table", "addField": "Add new field to this table",
"setPrimary": "Set as Primary value", "setPrimary": "Set as Primary value",
"addRow": "Add new row", "addRow": "Add new row",
@ -344,7 +345,7 @@
}, },
"searchProjectTree": "Search tables", "searchProjectTree": "Search tables",
"searchFields": "Search fields", "searchFields": "Search fields",
"searchColumn": "Search {search} column", "searchColumn": "Search {searchField} column",
"searchApps": "Search apps", "searchApps": "Search apps",
"searchModels": "Search models", "searchModels": "Search models",
"noItemsFound": "No items found", "noItemsFound": "No items found",

31
packages/nc-gui/layouts/default.vue

@ -22,7 +22,8 @@
><v-icon color="primary">alpha-c-circle </v-icon> --> ><v-icon color="primary">alpha-c-circle </v-icon> -->
</v-btn> </v-btn>
</template> </template>
Home <!-- Home -->
{{ $t('general.home') }}
<span <span
class="caption ml-1 font-weight-light" class="caption ml-1 font-weight-light"
>(v{{ >(v{{
@ -67,7 +68,8 @@
</template> </template>
</v-toolbar-items>--> </v-toolbar-items>-->
<span v-show="$nuxt.$loading.show" class="caption grey--text ml-3">Loading <v-icon small color="grey">mdi-spin mdi-loading</v-icon></span> <!-- loading -->
<span v-show="$nuxt.$loading.show" class="caption grey--text ml-3">{{ $t('general.loading') }} <v-icon small color="grey">mdi-spin mdi-loading</v-icon></span>
<span <span
v-shortkey="[ 'ctrl','shift', 'd']" v-shortkey="[ 'ctrl','shift', 'd']"
@ -121,7 +123,8 @@
<v-icon small class="mr-1"> <v-icon small class="mr-1">
mdi-account-supervisor-outline mdi-account-supervisor-outline
</v-icon> </v-icon>
Share <!-- Share -->
{{ $t('activity.share') }}
</x-btn> </x-btn>
</div> </div>
@ -236,7 +239,9 @@
</v-icon> </v-icon>
</template> </template>
<h3 class="pa-3"> <h3 class="pa-3">
{{ $vuetify.theme.dark ? 'It does come in Black (^⇧B)' : 'Does it come in Black ? (^⇧B)' }} <!-- "dark": "It does come in Black (^⇧B)",
"light": "Does it come in Black ? (^⇧B)" -->
{{ $vuetify.theme.dark ? $t('tooltip.theme.dark') : $t('tooltip.theme.light') }}
<i /> <i />
</h3> </h3>
</v-tooltip> </v-tooltip>
@ -339,17 +344,19 @@
<v-divider /> <v-divider />
<!-- Copy Auth Token -->
<!-- "Auth token copied to clipboard" -->
<v-list-item <v-list-item
v-if="isDashboard" v-if="isDashboard"
v-clipboard="$store.state.users.token" v-clipboard="$store.state.users.token"
dense dense
@click.stop="$toast.success('Auth token copied to clipboard').goAway(3000)" @click.stop="$toast.success($t('msg.toast.authToken')).goAway(3000)"
> >
<v-list-item-title> <v-list-item-title>
<v-icon key="terminal-dash" small> <v-icon key="terminal-dash" small>
mdi-content-copy mdi-content-copy
</v-icon>&nbsp; </v-icon>&nbsp;
<span class="font-weight-regular caption">Copy auth token</span> <span class="font-weight-regular caption">{{ $t('activity.account.authToken') }}</span>
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
@ -374,7 +381,7 @@
{{ isGql ? 'mdi-graphql' : 'mdi-code-json' }} {{ isGql ? 'mdi-graphql' : 'mdi-code-json' }}
</v-icon>&nbsp; </v-icon>&nbsp;
<span class="font-weight-regular caption"> <span class="font-weight-regular caption">
{{ isGql ? 'GraphQL APIs' : 'Swagger APIs Doc' }}</span> {{ isGql ? 'GraphQL APIs' : 'Swagger APIs' }}</span>
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
<v-divider /> <v-divider />
@ -382,7 +389,7 @@
<v-list-item-title> <v-list-item-title>
<v-icon small> <v-icon small>
mdi-information-outline mdi-information-outline
</v-icon>&nbsp; <span class="font-weight-regular caption">Copy Project info</span> </v-icon>&nbsp; <span class="font-weight-regular caption">{{ $t('activity.account.projInfo') }}</span>
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
@ -391,7 +398,7 @@
<v-icon key="terminal-dash" small> <v-icon key="terminal-dash" small>
mdi-palette mdi-palette
</v-icon>&nbsp; </v-icon>&nbsp;
<span class="font-weight-regular caption">Themes</span> <span class="font-weight-regular caption">{{ $t('activity.account.themes') }}</span>
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
@ -401,7 +408,7 @@
<v-list-item-title> <v-list-item-title>
<v-icon small> <v-icon small>
mdi-logout mdi-logout
</v-icon>&nbsp; <span class="font-weight-regular caption">Sign Out</span> </v-icon>&nbsp; <span class="font-weight-regular caption">{{ $t('general.signOut') }}</span>
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
</template> </template>
@ -422,14 +429,14 @@
mdi-account-plus-outline mdi-account-plus-outline
</v-icon> &nbsp; <span </v-icon> &nbsp; <span
class="font-weight-regular caption" class="font-weight-regular caption"
>Sign Up</span> >{{ $t('general.signUp') }}</span>
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
<v-list-item v-if="!user && !isThisMobile" dense to="/user/authentication/signin"> <v-list-item v-if="!user && !isThisMobile" dense to="/user/authentication/signin">
<v-list-item-title> <v-list-item-title>
<v-icon small> <v-icon small>
mdi-login mdi-login
</v-icon> &nbsp; <span class="font-weight-regular caption">Login</span> </v-icon> &nbsp; <span class="font-weight-regular caption">{{ $t('general.signIn') }}</span>
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
<!-- <v-list-item @click="openPricingPage">--> <!-- <v-list-item @click="openPricingPage">-->

2
packages/nc-gui/store/tabs.js

@ -171,7 +171,7 @@ export const actions = {
.list[0] // project .list[0] // project
.children[0] // environment .children[0] // environment
.children[0] // db .children[0] // db
.children.find(n => n.type === 'viewDir') // parent node .children.find(n => n.type === 'tableDir') // parent node
.children.find(t => t.name === name) .children.find(t => t.name === name)
break break

6
packages/noco-docs/content/en/getting-started/installation.md

@ -155,7 +155,7 @@ And connection params for this database can be specified in `NC_DB` environment
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql cd mysql
docker-compose up docker-compose up -d
``` ```
</code-block> </code-block>
@ -167,7 +167,7 @@ And connection params for this database can be specified in `NC_DB` environment
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd pg cd pg
docker-compose up docker-compose up -d
``` ```
</code-block> </code-block>
@ -179,7 +179,7 @@ And connection params for this database can be specified in `NC_DB` environment
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mssql cd mssql
docker-compose up docker-compose up -d
``` ```
</code-block> </code-block>

2
packages/noco-docs/content/en/setup-and-usages/audit.md

@ -2,7 +2,7 @@
title: 'Audit' title: 'Audit'
description: 'Audit log' description: 'Audit log'
position: 590 position: 590
category: 'Usage' category: 'Product'
menuTitle: 'Audit' menuTitle: 'Audit'
--- ---

2
packages/noco-docs/content/en/setup-and-usages/column-operations.md

@ -2,7 +2,7 @@
title: "Column Operations" title: "Column Operations"
description: "Column Operations" description: "Column Operations"
position: 530 position: 530
category: "Usage" category: "Product"
menuTitle: "Column Operations" menuTitle: "Column Operations"
--- ---
## Fields ## Fields

2
packages/noco-docs/content/en/setup-and-usages/column-types.md

@ -2,7 +2,7 @@
title: 'Column Types' title: 'Column Types'
description: 'Column Types' description: 'Column Types'
position: 520 position: 520
category: 'Usage' category: 'Product'
menuTitle: 'Column Types' menuTitle: 'Column Types'
--- ---

2
packages/noco-docs/content/en/setup-and-usages/dashboard.md

@ -2,7 +2,7 @@
title: 'Dashboard' title: 'Dashboard'
description: 'Dashboard' description: 'Dashboard'
position: 500 position: 500
category: 'Usage' category: 'Product'
menuTitle: 'Dashboard' menuTitle: 'Dashboard'
--- ---

2
packages/noco-docs/content/en/setup-and-usages/formulas.md

@ -2,7 +2,7 @@
title: "Formulas" title: "Formulas"
description: "Formulas" description: "Formulas"
position: 570 position: 570
category: "Usage" category: "Product"
menuTitle: "Formulas" menuTitle: "Formulas"
--- ---

2
packages/noco-docs/content/en/setup-and-usages/link-to-another-record.md

@ -2,7 +2,7 @@
title: "Link To Another Record" title: "Link To Another Record"
description: "Link To Another Record" description: "Link To Another Record"
position: 540 position: 540
category: "Usage" category: "Product"
menuTitle: "Link To Another Record" menuTitle: "Link To Another Record"
--- ---

2
packages/noco-docs/content/en/setup-and-usages/lookup.md

@ -2,7 +2,7 @@
title: "Lookup" title: "Lookup"
description: "Lookup" description: "Lookup"
position: 550 position: 550
category: "Usage" category: "Product"
menuTitle: "Lookup" menuTitle: "Lookup"
--- ---

2
packages/noco-docs/content/en/setup-and-usages/meta-management.md

@ -2,7 +2,7 @@
title: 'Metadata' title: 'Metadata'
description: 'Metadata' description: 'Metadata'
position: 600 position: 600
category: 'Usage' category: 'Product'
menuTitle: 'Metadata' menuTitle: 'Metadata'
--- ---

2
packages/noco-docs/content/en/setup-and-usages/primary-value.md

@ -2,7 +2,7 @@
title: "Primary value" title: "Primary value"
description: "Primary value" description: "Primary value"
position: 575 position: 575
category: "Usage" category: "Product"
menuTitle: "Primary value" menuTitle: "Primary value"
--- ---

2
packages/noco-docs/content/en/setup-and-usages/rollup.md

@ -2,7 +2,7 @@
title: "Rollup" title: "Rollup"
description: "Rollup" description: "Rollup"
position: 560 position: 560
category: "Usage" category: "Product"
menuTitle: "Rollup" menuTitle: "Rollup"
--- ---

2
packages/noco-docs/content/en/setup-and-usages/sync-schema.md

@ -2,7 +2,7 @@
title: 'Sync Schema' title: 'Sync Schema'
description: 'Schema changes made to database from outside nocodb GUI can be synced' description: 'Schema changes made to database from outside nocodb GUI can be synced'
position: 610 position: 610
category: 'Usage' category: 'Product'
menuTitle: 'Sync Schema' menuTitle: 'Sync Schema'
--- ---

2
packages/noco-docs/content/en/setup-and-usages/table-operations.md

@ -2,7 +2,7 @@
title: "Table Operations" title: "Table Operations"
description: "Table Operations" description: "Table Operations"
position: 510 position: 510
category: "Usage" category: "Product"
menuTitle: "Table Operations" menuTitle: "Table Operations"
--- ---

2
packages/noco-docs/content/en/setup-and-usages/team-and-auth.md

@ -2,7 +2,7 @@
title: 'Team & Auth' title: 'Team & Auth'
description: 'Breakdown of roles & permissions for team user management' description: 'Breakdown of roles & permissions for team user management'
position: 620 position: 620
category: 'Usage' category: 'Product'
menuTitle: 'Team & Auth' menuTitle: 'Team & Auth'
--- ---

40
packages/noco-docs/content/en/setup-and-usages/usage-information.md

@ -0,0 +1,40 @@
---
title: 'Usage Information'
description: 'Non-sensitive and anonymous usage information'
position: 900
category: 'Product'
menuTitle: 'Usage Information'
---
NocoDB is a fast growing open source project and we are committed to providing a solution that exceeds the expectations of the users and community.
We are also committed to continuing to develop and make NocoDB even better than it is today.
To that end, NocoDB contains a feature in which anonymous and otherwise non-sensitive data is collected.
This anonymous and non-sensitive data gives a better understanding of how users are interacting and using the product.
## Context
We will always continue to do hands-on UI/UX testing, surveys, issue tracking and roadmap.
Otherwise talk with the Community while striving to understand
and deliver what is being asked for and what is needed, by any means available.
However, these above actions alone are often insufficient to maintain an overall picture of the product usage.
## What we collect ?
The following data is collected:
- Unique machine ID (generated with node-machine-id)
- Environment (dev, staging, production)
- System information (OS, node version, docker or npm)
- Failures and errors.
- Create and delete events of a project, table, view, linkToAnotherRecord, sharedView, user, hook, image, sharedBase.
## What we DO NOT collect ?
We do not collect private or sensitive information, such as:
- Personally identifiable information
- Credential information (endpoints, ports, DB connections, username/password)
- User data
## Opt-out
To disable usage information collection please set following environment variable.
> NC_DISABLE_TELE=true

28
packages/nocodb/src/lib/noco/common/BaseApiBuilder.ts

@ -32,6 +32,7 @@ import ncModelsOrderUpgrader from './jobs/ncModelsOrderUpgrader';
import ncParentModelTitleUpgrader from './jobs/ncParentModelTitleUpgrader'; import ncParentModelTitleUpgrader from './jobs/ncParentModelTitleUpgrader';
import ncRemoveDuplicatedRelationRows from './jobs/ncRemoveDuplicatedRelationRows'; import ncRemoveDuplicatedRelationRows from './jobs/ncRemoveDuplicatedRelationRows';
import xcMetaDiffSync from './handlers/xcMetaDiffSync'; import xcMetaDiffSync from './handlers/xcMetaDiffSync';
import UITypes from '../../sqlUi/UITypes';
const log = debug('nc:api:base'); const log = debug('nc:api:base');
@ -755,11 +756,12 @@ export default abstract class BaseApiBuilder<T extends Noco>
const columns = const columns =
changeObj.columns changeObj.columns
.filter(c => c.altered !== 4) .filter(c => c.altered !== 4)
.map(({ altered: _al, ...rest }) => ({ .map(({ altered: _al, ...rest }) =>
...rest, this.mergeUiColAndDbColMetas(
// find and overwrite column property from db rest,
...(columnsFromDb?.find(c => c.cn === rest.cn) || {}) columnsFromDb?.find(c => c.cn === rest.cn)
})) || (await this.getColumnList(tn)); )
) || (await this.getColumnList(tn));
/* Get all relations */ /* Get all relations */
const relations = await this.relationsSyncAndGet(); const relations = await this.relationsSyncAndGet();
@ -1201,6 +1203,22 @@ export default abstract class BaseApiBuilder<T extends Noco>
await NcHelp.executeOperations(aclOper, this.connectionConfig.client); await NcHelp.executeOperations(aclOper, this.connectionConfig.client);
} }
protected mergeUiColAndDbColMetas(uiCol, dbCol) {
return {
...(uiCol || {}),
...(dbCol || {}),
// persist x props for single/multi select
...(uiCol?.uidt === UITypes.SingleSelect ||
uiCol?.uidt === UITypes.MultiSelect
? {
dtx: uiCol.dtx,
dtxp: uiCol.dtxp,
dtxs: uiCol.dtxs
}
: {})
};
}
public async onViewUpdate( public async onViewUpdate(
viewName: string, viewName: string,
beforeMetaUpdate?: (args: any) => Promise<void> beforeMetaUpdate?: (args: any) => Promise<void>

11
packages/nocodb/src/lib/noco/gql/GqlApiBuilder.ts

@ -195,11 +195,12 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
const columns = args.columns const columns = args.columns
? { ? {
[tn]: args.columns?.map(({ altered: _al, ...rest }) => ({ [tn]: args.columns?.map(({ altered: _al, ...rest }) =>
...rest, this.mergeUiColAndDbColMetas(
// find and overwrite column property from db rest,
...columnsFromDb?.find(c => c.cn === rest.cn) columnsFromDb?.find(c => c.cn === rest.cn)
})) )
)
} }
: {}; : {};

11
packages/nocodb/src/lib/noco/rest/RestApiBuilder.ts

@ -881,11 +881,12 @@ export class RestApiBuilder extends BaseApiBuilder<Noco> {
const columns = args.columns const columns = args.columns
? { ? {
[tn]: args.columns?.map(({ altered: _al, ...rest }) => ({ [tn]: args.columns?.map(({ altered: _al, ...rest }) =>
...rest, this.mergeUiColAndDbColMetas(
// find and overwrite column property from db rest,
...(columnsFromDb?.find(c => c.cn === rest.cn) || {}) columnsFromDb?.find(c => c.cn === rest.cn)
})) )
)
} }
: {}; : {};

2
packages/nocodb/src/lib/sqlUi/PgUi.ts

@ -1644,7 +1644,7 @@ export class PgUi {
}; };
break; break;
case 'Percent': case 'Percent':
colProp.dt = 'double'; colProp.dt = 'float8';
break; break;
case 'Duration': case 'Duration':
colProp.dt = 'int8'; colProp.dt = 'int8';

2
scripts/cypress/integration/common/6b_downloadCsv.js

@ -9,10 +9,12 @@ export const genTest = (type, xcdb) => {
before(() => { before(() => {
// loginPage.loginAndOpenProject(type) // loginPage.loginAndOpenProject(type)
cy.openTableTab("Country", 25); cy.openTableTab("Country", 25);
cy.screenshot("6b-before");
}); });
after(() => { after(() => {
cy.closeTableTab("Country"); cy.closeTableTab("Country");
cy.screenshot('6b-after')
}); });
it("Download verification- base view, default columns", () => { it("Download verification- base view, default columns", () => {

3
scripts/cypress/integration/common/6d_language_validation.js

@ -9,6 +9,7 @@ export const genTest = (type, xcdb) => {
before(() => { before(() => {
//loginPage.signIn(roles.owner.credentials) //loginPage.signIn(roles.owner.credentials)
mainPage.toolBarTopLeft(mainPage.HOME).click(); mainPage.toolBarTopLeft(mainPage.HOME).click();
cy.screenshot("6d-1");
}); });
const langVerification = (idx, lang) => { const langVerification = (idx, lang) => {
@ -20,6 +21,8 @@ export const genTest = (type, xcdb) => {
cy.get(".nc-menu-translate").click(); cy.get(".nc-menu-translate").click();
cy.getActiveMenu().find(".v-list-item").eq(idx).click(); cy.getActiveMenu().find(".v-list-item").eq(idx).click();
cy.screenshot("6d-2");
// basic validations // basic validations
// 1. Page title: "My Projects" // 1. Page title: "My Projects"
// 2. Button: "New Project" // 2. Button: "New Project"

2
scripts/markdown/readme/languages/chinese.md

@ -175,7 +175,7 @@ docker run -d -p 8080:8080 \
git clone https://github.com/nocodb/nocodb git clone https://github.com/nocodb/nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## 环境变量 ## 环境变量

2
scripts/markdown/readme/languages/dutch.md

@ -189,7 +189,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Environment variables ## Environment variables

2
scripts/markdown/readme/languages/french.md

@ -180,7 +180,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Variables d'environnement ## Variables d'environnement

2
scripts/markdown/readme/languages/german.md

@ -191,7 +191,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Umgebungsvariablen ## Umgebungsvariablen

2
scripts/markdown/readme/languages/indonesian.md

@ -190,7 +190,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Environment variables ## Environment variables

2
scripts/markdown/readme/languages/italian.md

@ -192,7 +192,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Variabili d'ambiente ## Variabili d'ambiente

2
scripts/markdown/readme/languages/japanese.md

@ -192,7 +192,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Environment variables ## Environment variables

2
scripts/markdown/readme/languages/korean.md

@ -193,7 +193,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## 환경변수 ## 환경변수

2
scripts/markdown/readme/languages/portuguese.md

@ -191,7 +191,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Environment variables ## Environment variables

2
scripts/markdown/readme/languages/russian.md

@ -193,7 +193,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Переменные среды ## Переменные среды

2
scripts/markdown/readme/languages/spanish.md

@ -191,7 +191,7 @@ git clone https://github.com/nocodb/nocodb
cd nocodb cd nocodb
cd docker-compose cd docker-compose
cd mysql or pg or mssql cd mysql or pg or mssql
docker-compose up docker-compose up -d
``` ```
## Variables de entorno ## Variables de entorno

Loading…
Cancel
Save