Browse Source

Merge branch 'develop' into mvp-mobile-layout-and-code-scanner

pull/5114/head
Daniel Spaude 2 years ago
parent
commit
cc2496e912
No known key found for this signature in database
GPG Key ID: 654A3D1FA4F35FFE
  1. 2
      .github/workflows/ci-cd.yml
  2. 2
      .github/workflows/playwright-test-workflow.yml
  3. 2
      .github/workflows/release-executables.yml
  4. 4
      .github/workflows/release-nocodb.yml
  5. 2
      .github/workflows/release-timely-executables.yml
  6. 11
      packages/nc-gui/assets/style.scss
  7. 6
      packages/nc-gui/components/cell/ClampedText.vue
  8. 5
      packages/nc-gui/components/cell/Duration.vue
  9. 12
      packages/nc-gui/components/cell/MultiSelect.vue
  10. 13
      packages/nc-gui/components/cell/SingleSelect.vue
  11. 8
      packages/nc-gui/components/dashboard/settings/AuditTab.vue
  12. 50
      packages/nc-gui/components/dashboard/settings/Misc.vue
  13. 4
      packages/nc-gui/components/smartsheet/Grid.vue
  14. 4
      packages/nc-gui/components/smartsheet/column/EditOrAdd.vue
  15. 19
      packages/nc-gui/components/smartsheet/column/LookupOptions.vue
  16. 22
      packages/nc-gui/components/smartsheet/column/RollupOptions.vue
  17. 106
      packages/nc-gui/components/smartsheet/expanded-form/Header.vue
  18. 35
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  19. 8
      packages/nc-gui/components/smartsheet/header/Menu.vue
  20. 110
      packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue
  21. 22
      packages/nc-gui/components/smartsheet/toolbar/FieldListAutoCompleteDropdown.vue
  22. 12
      packages/nc-gui/components/smartsheet/toolbar/FieldsMenu.vue
  23. 194
      packages/nc-gui/components/smartsheet/toolbar/FilterInput.vue
  24. 10
      packages/nc-gui/components/template/Editor.vue
  25. 6
      packages/nc-gui/components/virtual-cell/BelongsTo.vue
  26. 6
      packages/nc-gui/components/virtual-cell/HasMany.vue
  27. 6
      packages/nc-gui/components/virtual-cell/ManyToMany.vue
  28. 4
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  29. 4
      packages/nc-gui/components/virtual-cell/components/ListItems.vue
  30. 4
      packages/nc-gui/composables/useColumnCreateStore.ts
  31. 9
      packages/nc-gui/composables/useExpandedFormStore.ts
  32. 1
      packages/nc-gui/composables/useGlobal/state.ts
  33. 1
      packages/nc-gui/composables/useGlobal/types.ts
  34. 22
      packages/nc-gui/composables/useLTARStore.ts
  35. 14
      packages/nc-gui/composables/useProject.ts
  36. 114
      packages/nc-gui/composables/useViewFilters.ts
  37. 7
      packages/nc-gui/lang/ar.json
  38. 7
      packages/nc-gui/lang/bn_IN.json
  39. 7
      packages/nc-gui/lang/cs.json
  40. 7
      packages/nc-gui/lang/da.json
  41. 7
      packages/nc-gui/lang/de.json
  42. 8
      packages/nc-gui/lang/en.json
  43. 7
      packages/nc-gui/lang/es.json
  44. 7
      packages/nc-gui/lang/eu.json
  45. 7
      packages/nc-gui/lang/fa.json
  46. 7
      packages/nc-gui/lang/fi.json
  47. 7
      packages/nc-gui/lang/fr.json
  48. 7
      packages/nc-gui/lang/he.json
  49. 7
      packages/nc-gui/lang/hi.json
  50. 7
      packages/nc-gui/lang/hr.json
  51. 7
      packages/nc-gui/lang/id.json
  52. 7
      packages/nc-gui/lang/it.json
  53. 7
      packages/nc-gui/lang/ja.json
  54. 7
      packages/nc-gui/lang/ko.json
  55. 7
      packages/nc-gui/lang/lv.json
  56. 7
      packages/nc-gui/lang/nl.json
  57. 7
      packages/nc-gui/lang/no.json
  58. 7
      packages/nc-gui/lang/pl.json
  59. 7
      packages/nc-gui/lang/pt.json
  60. 7
      packages/nc-gui/lang/pt_BR.json
  61. 7
      packages/nc-gui/lang/ru.json
  62. 7
      packages/nc-gui/lang/sk.json
  63. 7
      packages/nc-gui/lang/sl.json
  64. 7
      packages/nc-gui/lang/sv.json
  65. 7
      packages/nc-gui/lang/th.json
  66. 7
      packages/nc-gui/lang/tr.json
  67. 7
      packages/nc-gui/lang/uk.json
  68. 7
      packages/nc-gui/lang/vi.json
  69. 7
      packages/nc-gui/lang/zh-Hans.json
  70. 7
      packages/nc-gui/lang/zh-Hant.json
  71. 33
      packages/nc-gui/package-lock.json
  72. 1
      packages/nc-gui/package.json
  73. 116
      packages/nc-gui/utils/filterUtils.ts
  74. 26
      packages/nc-gui/utils/validation.ts
  75. 2
      packages/nc-lib-gui/package.json
  76. 3401
      packages/nc-plugin/package-lock.json
  77. 2
      packages/nc-plugin/package.json
  78. 16
      packages/noco-docs/content/en/FAQs.md
  79. 18
      packages/noco-docs/content/en/developer-resources/accessing-apis.md
  80. 4
      packages/noco-docs/content/en/engineering/playwright.md
  81. 103
      packages/noco-docs/content/en/getting-started/environment-variables.md
  82. 12
      packages/noco-docs/content/en/index.md
  83. 10
      packages/noco-docs/content/en/setup-and-usages/account-settings.md
  84. 22
      packages/noco-docs/content/en/setup-and-usages/app-store.md
  85. 4
      packages/noco-docs/content/en/setup-and-usages/audit.md
  86. 14
      packages/noco-docs/content/en/setup-and-usages/column-operations.md
  87. 11
      packages/noco-docs/content/en/setup-and-usages/dashboard.md
  88. 36
      packages/noco-docs/content/en/setup-and-usages/display-value.md
  89. 46
      packages/noco-docs/content/en/setup-and-usages/meta-management.md
  90. 6
      packages/noco-docs/content/en/setup-and-usages/project-settings.md
  91. 10
      packages/noco-docs/content/en/setup-and-usages/sync-schema.md
  92. 4
      packages/noco-docs/content/en/setup-and-usages/table-operations.md
  93. 38
      packages/noco-docs/content/en/setup-and-usages/team-and-auth.md
  94. 4
      packages/nocodb-sdk/package-lock.json
  95. 2
      packages/nocodb-sdk/package.json
  96. 7
      packages/nocodb-sdk/src/index.ts
  97. 16
      packages/nocodb-sdk/src/lib/Api.ts
  98. 22
      packages/nocodb-sdk/src/lib/UITypes.ts
  99. 6
      packages/nocodb/Dockerfile
  100. 7
      packages/nocodb/docker/index.js
  101. Some files were not shown because too many files have changed in this diff Show More

2
.github/workflows/ci-cd.yml

@ -27,7 +27,7 @@ concurrency:
jobs: jobs:
unit-tests: unit-tests:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
timeout-minutes: 30 timeout-minutes: 40
if: ${{ github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'trigger-CI') || !github.event.pull_request.draft }} if: ${{ github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'trigger-CI') || !github.event.pull_request.draft }}
steps: steps:
- name: Setup Node - name: Setup Node

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

@ -14,7 +14,7 @@ on:
jobs: jobs:
playwright: playwright:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
timeout-minutes: 30 timeout-minutes: 40
steps: steps:
# Reference: https://github.com/pierotofy/set-swap-space/blob/master/action.yml # Reference: https://github.com/pierotofy/set-swap-space/blob/master/action.yml
- name: Set 5gb swap - name: Set 5gb swap

2
.github/workflows/release-executables.yml

@ -87,7 +87,7 @@ jobs:
./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=arm64 --target_libc=musl ./node_modules/.bin/node-pre-gyp install --directory=./node_modules/sqlite3 --target_platform=linux --fallback-to-build --target_arch=arm64 --target_libc=musl
# clean up code to optimize size # clean up code to optimize size
npx modclean --patterns="default:*" --ignore="nc-lib-gui/**,dayjs/**,express-status-monitor/**,sqlite3/**" --run npx modclean --patterns="default:*" --ignore="nc-lib-gui/**,nocodb/**,dayjs/**,express-status-monitor/**,sqlite3/**" --run
# build executables # build executables
npm run build npm run build

4
.github/workflows/release-nocodb.yml

@ -112,12 +112,12 @@ jobs:
# Publish Docs # Publish Docs
publish-docs: publish-docs:
needs: close-issues needs: release-docker
uses: ./.github/workflows/publish-docs.yml uses: ./.github/workflows/publish-docs.yml
secrets: secrets:
GH_TOKEN: "${{ secrets.GH_TOKEN }}" GH_TOKEN: "${{ secrets.GH_TOKEN }}"
# Sync changes to develop # Sync changes to develop
sync-to-develop: sync-to-develop:
needs: close-issues needs: publish-docs
uses: ./.github/workflows/sync-to-develop.yml uses: ./.github/workflows/sync-to-develop.yml

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

@ -103,7 +103,7 @@ jobs:
# clean up code to optimize size # clean up code to optimize size
npx modclean --patterns="default:*" --ignore="nc-lib-gui-daily/**,dayjs/**,express-status-monitor/**,sqlite3/**" --run npx modclean --patterns="default:*" --ignore="nc-lib-gui-daily/**,nocodb-daily/**,dayjs/**,express-status-monitor/**,sqlite3/**" --run
# build executables # build executables
npm run build npm run build

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

@ -318,3 +318,14 @@ a {
white-space: pre; white-space: pre;
user-select: auto; user-select: auto;
} }
.nc-drawer-expanded-form .ant-drawer-content-wrapper {
transition: width 0.3s !important;
}
.nc-icon-transition {
@apply transform transition-transform !hover:(scale-115) !active:(scale-100)
}

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

@ -23,10 +23,14 @@ onMounted(() => {
<template> <template>
<div ref="wrapper"> <div ref="wrapper">
<!--
using '' for :text in text-clamp would keep the previous cell value after changing a filter
use ' ' instead of '' to trigger update
-->
<text-clamp <text-clamp
:key="`clamp-${key}-${props.value?.toString().length || 0}`" :key="`clamp-${key}-${props.value?.toString().length || 0}`"
class="w-full h-full break-all" class="w-full h-full break-all"
:text="`${props.value || ''}`" :text="`${props.value || ' '}`"
:max-lines="props.lines" :max-lines="props.lines"
/> />
</div> </div>

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

@ -13,9 +13,10 @@ import {
interface Props { interface Props {
modelValue: number | string | null | undefined modelValue: number | string | null | undefined
showValidationError: boolean
} }
const { modelValue } = defineProps<Props>() const { modelValue, showValidationError = true } = defineProps<Props>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
@ -99,7 +100,7 @@ const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
<span v-else> {{ localState }}</span> <span v-else> {{ localState }}</span>
<div v-if="showWarningMessage" class="duration-warning"> <div v-if="showWarningMessage && showValidationError" class="duration-warning">
<!-- TODO: i18n --> <!-- TODO: i18n -->
Please enter a number Please enter a number
</div> </div>

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

@ -31,9 +31,10 @@ import MdiCloseCircle from '~icons/mdi/close-circle'
interface Props { interface Props {
modelValue?: string | string[] modelValue?: string | string[]
rowIndex?: number rowIndex?: number
disableOptionCreation?: boolean
} }
const { modelValue } = defineProps<Props>() const { modelValue, disableOptionCreation } = defineProps<Props>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
@ -336,6 +337,7 @@ useEventListener(document, 'click', handleClose, true)
:key="op.id || op.title" :key="op.id || op.title"
:value="op.title" :value="op.title"
:data-testid="`select-option-${column.title}-${rowIndex}`" :data-testid="`select-option-${column.title}-${rowIndex}`"
:class="`nc-select-option-${column.title}-${op.title}`"
@click.stop @click.stop
> >
<a-tag class="rounded-tag" :color="op.color"> <a-tag class="rounded-tag" :color="op.color">
@ -354,7 +356,13 @@ useEventListener(document, 'click', handleClose, true)
</a-select-option> </a-select-option>
<a-select-option <a-select-option
v-if="searchVal && isOptionMissing && !isPublic && (hasRole('owner', true) || hasRole('creator', true))" v-if="
searchVal &&
isOptionMissing &&
!isPublic &&
!disableOptionCreation &&
(hasRole('owner', true) || hasRole('creator', true))
"
:key="searchVal" :key="searchVal"
:value="searchVal" :value="searchVal"
> >

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

@ -18,6 +18,7 @@ import {
inject, inject,
isDrawerOrModalExist, isDrawerOrModalExist,
ref, ref,
useEventListener,
useRoles, useRoles,
useSelectedCellKeyupListener, useSelectedCellKeyupListener,
watch, watch,
@ -26,9 +27,10 @@ import {
interface Props { interface Props {
modelValue?: string | undefined modelValue?: string | undefined
rowIndex?: number rowIndex?: number
disableOptionCreation?: boolean
} }
const { modelValue } = defineProps<Props>() const { modelValue, disableOptionCreation } = defineProps<Props>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
@ -263,6 +265,7 @@ useEventListener(document, 'click', handleClose, true)
:key="op.title" :key="op.title"
:value="op.title" :value="op.title"
:data-testid="`select-option-${column.title}-${rowIndex}`" :data-testid="`select-option-${column.title}-${rowIndex}`"
:class="`nc-select-option-${column.title}-${op.title}`"
@click.stop @click.stop
> >
<a-tag class="rounded-tag" :color="op.color"> <a-tag class="rounded-tag" :color="op.color">
@ -280,7 +283,13 @@ useEventListener(document, 'click', handleClose, true)
</a-tag> </a-tag>
</a-select-option> </a-select-option>
<a-select-option <a-select-option
v-if="searchVal && isOptionMissing && !isPublic && (hasRole('owner', true) || hasRole('creator', true))" v-if="
searchVal &&
isOptionMissing &&
!isPublic &&
!disableOptionCreation &&
(hasRole('owner', true) || hasRole('creator', true))
"
:key="searchVal" :key="searchVal"
:value="searchVal" :value="searchVal"
> >

8
packages/nc-gui/components/dashboard/settings/AuditTab.vue

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Tooltip as ATooltip, Empty } from 'ant-design-vue' import { Tooltip as ATooltip, Empty } from 'ant-design-vue'
import type { AuditType } from 'nocodb-sdk' import type { AuditType } from 'nocodb-sdk'
import { h, onMounted, timeAgo, useI18n, useNuxtApp, useProject } from '#imports' import { h, onMounted, timeAgo, useGlobal, useI18n, useNuxtApp, useProject } from '#imports'
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
@ -16,8 +16,11 @@ let audits = $ref<null | Array<AuditType>>(null)
let totalRows = $ref(0) let totalRows = $ref(0)
const currentPage = $ref(1) const currentPage = $ref(1)
const currentLimit = $ref(25) const currentLimit = $ref(25)
const { appInfo } = useGlobal()
async function loadAudits(page = currentPage, limit = currentLimit) { async function loadAudits(page = currentPage, limit = currentLimit) {
try { try {
if (!project.value?.id) return if (!project.value?.id) return
@ -86,9 +89,10 @@ const columns = [
<template> <template>
<div class="flex flex-col gap-4 w-full"> <div class="flex flex-col gap-4 w-full">
<div v-if="!appInfo.auditEnabled" class="text-red-500">Audit logs are currently disabled by administrators.</div>
<div class="flex flex-row justify-between items-center"> <div class="flex flex-row justify-between items-center">
<a-button class="self-start" @click="loadAudits"> <a-button class="self-start" @click="loadAudits">
<!-- Reload --> <!-- Reload -->
<div class="flex items-center gap-2 text-gray-600 font-light"> <div class="flex items-center gap-2 text-gray-600 font-light">
<MdiReload :class="{ 'animate-infinite animate-spin !text-success': isLoading }" /> <MdiReload :class="{ 'animate-infinite animate-spin !text-success': isLoading }" />

50
packages/nc-gui/components/dashboard/settings/Misc.vue

@ -1,24 +1,64 @@
<script setup lang="ts"> <script setup lang="ts">
import type { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface'
import { useGlobal, useProject, watch } from '#imports' import { useGlobal, useProject, watch } from '#imports'
const { includeM2M, showNull } = useGlobal() const { includeM2M, showNull } = useGlobal()
const { loadTables } = useProject()
const { project, updateProject, projectMeta, loadTables, hasEmptyOrNullFilters } = useProject()
watch(includeM2M, async () => await loadTables()) watch(includeM2M, async () => await loadTables())
const showNullAndEmptyInFilter = ref(projectMeta.value.showNullAndEmptyInFilter)
async function showNullAndEmptyInFilterOnChange(evt: CheckboxChangeEvent) {
// users cannot hide null & empty option if there is existing null / empty filters
if (!evt.target.checked) {
if (await hasEmptyOrNullFilters()) {
showNullAndEmptyInFilter.value = true
message.warning('Null / Empty filters exist. Please remove them first.')
}
}
const newProjectMeta = {
...projectMeta.value,
showNullAndEmptyInFilter: showNullAndEmptyInFilter.value,
}
// update local state
project.value.meta = newProjectMeta
// update db
await updateProject({
meta: newProjectMeta,
})
}
</script> </script>
<template> <template>
<div class="flex flex-row w-full"> <div class="flex flex-row w-full">
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<div class="flex flex-row items-center w-full mb-4 gap-2"> <div class="flex flex-row items-center w-full mb-4 gap-2">
<!-- Show M2M Tables --> <!-- Show M2M Tables -->
<a-checkbox v-model:checked="includeM2M" v-e="['c:themes:show-m2m-tables']" class="nc-settings-meta-misc"> <a-checkbox v-model:checked="includeM2M" v-e="['c:themes:show-m2m-tables']" class="nc-settings-meta-misc">
{{ $t('msg.info.showM2mTables') }} {{ $t('msg.info.showM2mTables') }} <br />
<span class="text-gray-500">{{ $t('msg.info.showM2mTablesDesc') }}</span>
</a-checkbox> </a-checkbox>
</div> </div>
<div class="flex flex-row items-center w-full mb-4 gap-2"> <div class="flex flex-row items-center w-full mb-4 gap-2">
<!-- Show NULL --> <!-- Show NULL -->
<a-checkbox v-model:checked="showNull" v-e="['c:settings:show-null']" class="nc-settings-show-null">Show NULL</a-checkbox> <a-checkbox v-model:checked="showNull" v-e="['c:settings:show-null']" class="nc-settings-show-null">
{{ $t('msg.info.showNullInCells') }} <br />
<span class="text-gray-500">{{ $t('msg.info.showNullInCellsDesc') }}</span>
</a-checkbox>
</div>
<div class="flex flex-row items-center w-full mb-4 gap-2">
<!-- Show NULL and EMPTY in Filters -->
<a-checkbox
v-model:checked="showNullAndEmptyInFilter"
v-e="['c:settings:show-null-and-empty-in-filter']"
class="nc-settings-show-null-and-empty-in-filter"
@change="showNullAndEmptyInFilterOnChange"
>
{{ $t('msg.info.showNullAndEmptyInFilter') }} <br />
<span class="text-gray-500">{{ $t('msg.info.showNullAndEmptyInFilterDesc') }}</span>
</a-checkbox>
</div> </div>
</div> </div>
</div> </div>

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

@ -1056,7 +1056,7 @@ const closeAddColumnDropdown = () => {
position: sticky !important; position: sticky !important;
left: 80px; left: 80px;
z-index: 5; z-index: 5;
@apply border-r-2 border-r-gray-300; @apply border-r-1 border-r-gray-300;
} }
tbody td:nth-child(2) { tbody td:nth-child(2) {
@ -1064,7 +1064,7 @@ const closeAddColumnDropdown = () => {
left: 80px; left: 80px;
z-index: 4; z-index: 4;
background: white; background: white;
@apply shadow-lg border-r-2 border-r-gray-300; @apply shadow-lg border-r-1 border-r-gray-300;
} }
} }

4
packages/nc-gui/components/smartsheet/column/EditOrAdd.vue

@ -181,10 +181,10 @@ useEventListener('keydown', (e: KeyboardEvent) => {
<LazySmartsheetColumnDurationOptions v-if="formState.uidt === UITypes.Duration" v-model:value="formState" /> <LazySmartsheetColumnDurationOptions v-if="formState.uidt === UITypes.Duration" v-model:value="formState" />
<LazySmartsheetColumnRatingOptions v-if="formState.uidt === UITypes.Rating" v-model:value="formState" /> <LazySmartsheetColumnRatingOptions v-if="formState.uidt === UITypes.Rating" v-model:value="formState" />
<LazySmartsheetColumnCheckboxOptions v-if="formState.uidt === UITypes.Checkbox" v-model:value="formState" /> <LazySmartsheetColumnCheckboxOptions v-if="formState.uidt === UITypes.Checkbox" v-model:value="formState" />
<LazySmartsheetColumnLookupOptions v-if="!isEdit && formState.uidt === UITypes.Lookup" v-model:value="formState" /> <LazySmartsheetColumnLookupOptions v-if="formState.uidt === UITypes.Lookup" v-model:value="formState" />
<LazySmartsheetColumnDateOptions v-if="formState.uidt === UITypes.Date" v-model:value="formState" /> <LazySmartsheetColumnDateOptions v-if="formState.uidt === UITypes.Date" v-model:value="formState" />
<LazySmartsheetColumnDateTimeOptions v-if="formState.uidt === UITypes.DateTime" v-model:value="formState" /> <LazySmartsheetColumnDateTimeOptions v-if="formState.uidt === UITypes.DateTime" v-model:value="formState" />
<LazySmartsheetColumnRollupOptions v-if="!isEdit && formState.uidt === UITypes.Rollup" v-model:value="formState" /> <LazySmartsheetColumnRollupOptions v-if="formState.uidt === UITypes.Rollup" v-model:value="formState" />
<LazySmartsheetColumnLinkedToAnotherRecordOptions <LazySmartsheetColumnLinkedToAnotherRecordOptions
v-if="!isEdit && formState.uidt === UITypes.LinkToAnotherRecord" v-if="!isEdit && formState.uidt === UITypes.LinkToAnotherRecord"
v-model:value="formState" v-model:value="formState"

19
packages/nc-gui/components/smartsheet/column/LookupOptions.vue

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from '@vue/runtime-core'
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes, isSystemColumn } from 'nocodb-sdk' import { UITypes, isSystemColumn } from 'nocodb-sdk'
import { getRelationName } from './utils' import { getRelationName } from './utils'
@ -14,7 +15,7 @@ const vModel = useVModel(props, 'value', emit)
const meta = $(inject(MetaInj, ref())) const meta = $(inject(MetaInj, ref()))
const { setAdditionalValidations, validateInfos, onDataTypeChange } = useColumnCreateStoreOrThrow() const { setAdditionalValidations, validateInfos, onDataTypeChange, isEdit } = useColumnCreateStoreOrThrow()
const { tables } = $(useProject()) const { tables } = $(useProject())
@ -49,8 +50,20 @@ const columns = $computed<ColumnType[]>(() => {
if (!selectedTable?.id) { if (!selectedTable?.id) {
return [] return []
} }
return metas[selectedTable.id].columns.filter((c: ColumnType) => !isSystemColumn(c)) return metas[selectedTable.id].columns.filter((c: ColumnType) => !isSystemColumn(c) && c.id !== vModel.value.id)
}) })
onMounted(() => {
if (isEdit.value) {
vModel.value.fk_lookup_column_id = vModel.value.colOptions?.fk_lookup_column_id
vModel.value.fk_relation_column_id = vModel.value.colOptions?.fk_relation_column_id
}
})
const onRelationColChange = () => {
vModel.value.fk_lookup_column_id = columns?.[0]?.id
onDataTypeChange()
}
</script> </script>
<template> <template>
@ -60,7 +73,7 @@ const columns = $computed<ColumnType[]>(() => {
<a-select <a-select
v-model:value="vModel.fk_relation_column_id" v-model:value="vModel.fk_relation_column_id"
dropdown-class-name="!w-64 nc-dropdown-relation-table" dropdown-class-name="!w-64 nc-dropdown-relation-table"
@change="onDataTypeChange" @change="onRelationColChange"
> >
<a-select-option v-for="(table, i) of refTables" :key="i" :value="table.col.fk_column_id"> <a-select-option v-for="(table, i) of refTables" :key="i" :value="table.col.fk_column_id">
<div class="flex flex-row space-x-0.5 h-full pb-0.5 items-center justify-between"> <div class="flex flex-row space-x-0.5 h-full pb-0.5 items-center justify-between">

22
packages/nc-gui/components/smartsheet/column/RollupOptions.vue

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from '@vue/runtime-core'
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes, isSystemColumn, isVirtualCol } from 'nocodb-sdk' import { UITypes, isSystemColumn, isVirtualCol } from 'nocodb-sdk'
import { getRelationName } from './utils' import { getRelationName } from './utils'
@ -14,7 +15,7 @@ const vModel = useVModel(props, 'value', emit)
const meta = $(inject(MetaInj, ref())) const meta = $(inject(MetaInj, ref()))
const { setAdditionalValidations, validateInfos, onDataTypeChange } = useColumnCreateStoreOrThrow() const { setAdditionalValidations, validateInfos, onDataTypeChange, isEdit } = useColumnCreateStoreOrThrow()
const { tables } = $(useProject()) const { tables } = $(useProject())
@ -69,8 +70,23 @@ const columns = $computed(() => {
return [] return []
} }
return metas[selectedTable.id].columns.filter((c: ColumnType) => !isVirtualCol(c.uidt as UITypes) && !isSystemColumn(c)) return metas[selectedTable.id].columns.filter(
(c: ColumnType) => !isVirtualCol(c.uidt as UITypes) && (!isSystemColumn(c) || c.pk),
)
}) })
onMounted(() => {
if (isEdit.value) {
vModel.value.fk_relation_column_id = vModel.value.colOptions?.fk_relation_column_id
vModel.value.fk_rollup_column_id = vModel.value.colOptions?.fk_rollup_column_id
vModel.value.rollup_function = vModel.value.colOptions?.rollup_function
}
})
const onRelationColChange = () => {
vModel.value.fk_rollup_column_id = columns?.[0]?.id
onDataTypeChange()
}
</script> </script>
<template> <template>
@ -80,7 +96,7 @@ const columns = $computed(() => {
<a-select <a-select
v-model:value="vModel.fk_relation_column_id" v-model:value="vModel.fk_relation_column_id"
dropdown-class-name="!w-64 nc-dropdown-relation-table" dropdown-class-name="!w-64 nc-dropdown-relation-table"
@change="onDataTypeChange" @change="onRelationColChange"
> >
<a-select-option v-for="(table, i) of refTables" :key="i" :value="table.col.fk_column_id"> <a-select-option v-for="(table, i) of refTables" :key="i" :value="table.col.fk_column_id">
<div class="flex flex-row space-x-0.5 h-full pb-0.5 items-center justify-between"> <div class="flex flex-row space-x-0.5 h-full pb-0.5 items-center justify-between">

106
packages/nc-gui/components/smartsheet/expanded-form/Header.vue

@ -18,7 +18,7 @@ const route = useRoute()
const { meta, isSqlView } = useSmartsheetStoreOrThrow() const { meta, isSqlView } = useSmartsheetStoreOrThrow()
const { commentsDrawer, primaryValue, primaryKey, save: _save, loadRow } = useExpandedFormStoreOrThrow() const { commentsDrawer, displayValue, primaryKey, save: _save, loadRow } = useExpandedFormStoreOrThrow()
const { isNew, syncLTARRefs, state } = useSmartsheetRowStoreOrThrow() const { isNew, syncLTARRefs, state } = useSmartsheetRowStoreOrThrow()
@ -99,7 +99,7 @@ const onConfirmDeleteRowClick = async () => {
{{ meta.title }} {{ meta.title }}
</template> </template>
<template v-if="primaryValue">: {{ primaryValue }}</template> <template v-if="displayValue">: {{ displayValue }}</template>
</h5> </h5>
<div class="flex-1" /> <div class="flex-1" />
@ -108,7 +108,11 @@ const onConfirmDeleteRowClick = async () => {
<template #title> <template #title>
<div class="text-center w-full">{{ $t('general.reload') }}</div> <div class="text-center w-full">{{ $t('general.reload') }}</div>
</template> </template>
<mdi-reload v-if="!isNew" class="cursor-pointer select-none text-gray-500 mx-1 min-w-4" @click="loadRow" /> <mdi-reload
v-if="!isNew"
class="nc-icon-transition cursor-pointer select-none text-gray-500 mx-1 min-w-4"
@click="loadRow"
/>
</a-tooltip> </a-tooltip>
<a-tooltip placement="bottom"> <a-tooltip placement="bottom">
<template #title> <template #title>
@ -117,7 +121,7 @@ const onConfirmDeleteRowClick = async () => {
</template> </template>
<mdi-link <mdi-link
v-if="!isNew" v-if="!isNew"
class="cursor-pointer select-none text-gray-500 mx-1 nc-copy-row-url min-w-4" class="nc-icon-transition cursor-pointer select-none text-gray-500 mx-1 nc-copy-row-url min-w-4"
@click="copyRecordUrl" @click="copyRecordUrl"
/> />
</a-tooltip> </a-tooltip>
@ -130,61 +134,40 @@ const onConfirmDeleteRowClick = async () => {
<MdiCommentTextOutline <MdiCommentTextOutline
v-if="isUIAllowed('rowComments') && !isNew" v-if="isUIAllowed('rowComments') && !isNew"
v-e="['c:row-expand:comment-toggle']" v-e="['c:row-expand:comment-toggle']"
class="cursor-pointer select-none nc-toggle-comments text-gray-500 mx-1 min-w-4" class="nc-icon-transition cursor-pointer select-none nc-toggle-comments text-gray-500 mx-1 min-w-4"
@click="commentsDrawer = !commentsDrawer" @click="commentsDrawer = !commentsDrawer"
/> />
</a-tooltip> </a-tooltip>
<a-button class="!text mx-1 nc-expand-form-close-btn" @click="emit('cancel')"> <a-tooltip v-if="!isSqlView" placement="bottom">
<div class="flex items-center"> <!-- Duplicate row -->
<MdiCloseCircleOutline class="mr-1" /> <template #title>
<!-- Close --> <div class="text-center w-full">{{ $t('activity.duplicateRow') }}</div>
{{ $t('general.close') }} </template>
</div> <MdiContentCopy
</a-button> v-if="isUIAllowed('xcDatatableEditable') && !isNew"
v-e="['c:row-expand:duplicate']"
<a-dropdown> class="nc-icon-transition cursor-pointer select-none nc-duplicate-row text-gray-500 mx-1 min-w-4"
<a-button v-e="['c:actions']" class="nc-actions-menu-btn nc-toolbar-btn"> @click="!isNew && emit('duplicateRow')"
<div class="flex gap-1 items-center"> />
<!-- More --> </a-tooltip>
<span class="!text-sm font-weight-medium">{{ $t('general.more') }}</span>
<MdiMenuDown class="text-grey" />
</div>
</a-button>
<template #overlay>
<div class="bg-gray-50 py-2 shadow-lg !border">
<div>
<div
v-e="['a:actions:duplicate-row']"
class="nc-menu-item"
:class="{ disabled: isNew }"
@click="!isNew && emit('duplicateRow')"
>
<MdiContentCopy class="text-gray-500" />
{{ $t('activity.duplicateRow') }}
</div>
<a-modal v-model:visible="showDeleteRowModal" title="Delete row?" @ok="onConfirmDeleteRowClick"> <a-tooltip v-if="!isSqlView" placement="bottom">
<p>Are you sure you want to delete this row?</p> <!-- Delete row -->
</a-modal> <template #title>
<div class="text-center w-full">{{ $t('activity.deleteRow') }}</div>
<div
v-e="['a:actions:delete-row']"
class="nc-menu-item"
:class="{ disabled: isNew }"
@click="!isNew && onDeleteRowClick()"
>
<MdiDelete class="text-gray-500" />
{{ $t('activity.deleteRow') }}
</div>
</div>
</div>
</template> </template>
</a-dropdown> <MdiDeleteOutline
v-if="isUIAllowed('xcDatatableEditable') && !isNew"
v-e="['c:row-expand:delete']"
class="nc-icon-transition cursor-pointer select-none nc-delete-row text-gray-500 mx-1 min-w-4"
@click="!isNew && onDeleteRowClick()"
/>
</a-tooltip>
<a-dropdown-button class="nc-expand-form-save-btn" type="primary" :disabled="!isUIAllowed('tableRowUpdate')" @click="save"> <a-dropdown-button class="nc-expand-form-save-btn" type="primary" :disabled="!isUIAllowed('tableRowUpdate')" @click="save">
<template #icon><MdiMenuDown /></template>
<template #overlay> <template #overlay>
<a-menu class="nc-expand-form-save-dropdown-menu"> <a-menu class="nc-expand-form-save-dropdown-menu">
<a-menu-item key="0" class="!py-2 flex gap-2" @click="saveRowAndStay = 0"> <a-menu-item key="0" class="!py-2 flex gap-2" @click="saveRowAndStay = 0">
@ -210,5 +193,26 @@ const onConfirmDeleteRowClick = async () => {
{{ $t('activity.saveAndStay') }} {{ $t('activity.saveAndStay') }}
</div> </div>
</a-dropdown-button> </a-dropdown-button>
<a-tooltip placement="bottom">
<!-- Close -->
<template #title>
<div class="text-center w-full">{{ $t('general.close') }}</div>
</template>
<MdiCloseCircleOutline
class="nc-icon-transition cursor-pointer select-none nc-close-form text-gray-500 mx-1 min-w-4"
@click="emit('cancel')"
/>
</a-tooltip>
<a-modal v-model:visible="showDeleteRowModal" title="Delete row?" @ok="onConfirmDeleteRowClick">
<p>Are you sure you want to delete this row?</p>
</a-modal>
</div> </div>
</template> </template>
<style scoped>
:deep(svg) {
@apply outline-none;
}
</style>

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

@ -163,7 +163,7 @@ export default {
<a-drawer <a-drawer
v-model:visible="isExpanded" v-model:visible="isExpanded"
:footer="null" :footer="null"
width="min(90vw,800px)" :width="commentsDrawer ? 'min(90vw,900px)' : 'min(90vw,700px)'"
:body-style="{ 'padding': 0, 'display': 'flex', 'flex-direction': 'column' }" :body-style="{ 'padding': 0, 'display': 'flex', 'flex-direction': 'column' }"
:closable="false" :closable="false"
class="nc-drawer-expanded-form" class="nc-drawer-expanded-form"
@ -171,24 +171,23 @@ export default {
> >
<SmartsheetExpandedFormHeader :view="props.view" @cancel="onClose" @duplicate-row="onDuplicateRow" /> <SmartsheetExpandedFormHeader :view="props.view" @cancel="onClose" @duplicate-row="onDuplicateRow" />
<div class="!bg-gray-100 rounded flex-1 relative"> <div class="!bg-gray-100 rounded flex-1">
<template v-if="props.showNextPrevIcons">
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.nextRow') }}
</template>
<MdiChevronRight class="cursor-pointer nc-next-arrow" @click="$emit('next')" />
</a-tooltip>
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.prevRow') }}
</template>
<MdiChevronLeft class="cursor-pointer nc-prev-arrow" @click="$emit('prev')" />
</a-tooltip>
</template>
<div class="flex h-full nc-form-wrapper items-stretch min-h-[max(70vh,100%)]"> <div class="flex h-full nc-form-wrapper items-stretch min-h-[max(70vh,100%)]">
<div class="flex-1 overflow-auto scrollbar-thin-dull nc-form-fields-container"> <div class="flex-1 overflow-auto scrollbar-thin-dull nc-form-fields-container relative">
<template v-if="props.showNextPrevIcons">
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.nextRow') }}
</template>
<MdiChevronRight class="cursor-pointer nc-next-arrow" @click="$emit('next')" />
</a-tooltip>
<a-tooltip placement="bottom">
<template #title>
{{ $t('labels.prevRow') }}
</template>
<MdiChevronLeft class="cursor-pointer nc-prev-arrow" @click="$emit('prev')" />
</a-tooltip>
</template>
<div class="w-[500px] mx-auto"> <div class="w-[500px] mx-auto">
<div v-if="duplicatingRowInProgress" class="flex items-center justify-center h-[100px]"> <div v-if="duplicatingRowInProgress" class="flex items-center justify-center h-[100px]">
<a-spin size="large" /> <a-spin size="large" />

8
packages/nc-gui/components/smartsheet/header/Menu.vue

@ -68,7 +68,7 @@ const deleteColumn = () =>
}, },
}) })
const setAsPrimaryValue = async () => { const setAsDisplayValue = async () => {
try { try {
await $api.dbTableColumn.primaryColumnSet(column?.value?.id as string) await $api.dbTableColumn.primaryColumnSet(column?.value?.id as string)
@ -280,13 +280,13 @@ const hideField = async () => {
</a-menu-item> </a-menu-item>
<a-divider class="!my-0" /> <a-divider class="!my-0" />
<a-menu-item v-if="(!virtual || column?.uidt === UITypes.Formula) && !column?.pv" @click="setAsPrimaryValue"> <a-menu-item v-if="(!virtual || column?.uidt === UITypes.Formula) && !column?.pv" @click="setAsDisplayValue">
<div class="nc-column-set-primary nc-header-menu-item"> <div class="nc-column-set-primary nc-header-menu-item">
<MdiStar class="text-primary" /> <MdiStar class="text-primary" />
<!-- todo : tooltip --> <!-- todo : tooltip -->
<!-- Set as Primary value --> <!-- Set as Display value -->
{{ $t('activity.setPrimary') }} {{ $t('activity.setDisplay') }}
</div> </div>
</a-menu-item> </a-menu-item>

110
packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { FilterType } from 'nocodb-sdk' import type { ColumnType, FilterType } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import { import {
ActiveViewInj, ActiveViewInj,
MetaInj, MetaInj,
@ -42,7 +43,18 @@ const reloadDataHook = inject(ReloadViewDataHookInj)!
const { $e } = useNuxtApp() const { $e } = useNuxtApp()
const { nestedFilters } = useSmartsheetStoreOrThrow() const { nestedFilters } = useSmartsheetStoreOrThrow()
const { filters, nonDeletedFilters, deleteFilter, saveOrUpdate, loadFilters, addFilter, addFilterGroup, sync } = useViewFilters( const {
filters,
nonDeletedFilters,
deleteFilter,
saveOrUpdate,
loadFilters,
addFilter,
addFilterGroup,
sync,
saveOrUpdateDebounced,
isComparisonOpAllowed,
} = useViewFilters(
activeView, activeView,
parentId, parentId,
computed(() => autoSave), computed(() => autoSave),
@ -53,16 +65,37 @@ const { filters, nonDeletedFilters, deleteFilter, saveOrUpdate, loadFilters, add
const localNestedFilters = ref() const localNestedFilters = ref()
const columns = computed(() => meta.value?.columns)
const getColumn = (filter: Filter) => {
return columns.value?.find((col: ColumnType) => col.id === filter.fk_column_id)
}
const filterPrevComparisonOp = ref<Record<string, string>>({})
const filterUpdateCondition = (filter: FilterType, i: number) => { const filterUpdateCondition = (filter: FilterType, i: number) => {
const col = getColumn(filter)
if (
col.uidt === UITypes.SingleSelect &&
['anyof', 'nanyof'].includes(filterPrevComparisonOp.value[filter.id]) &&
['eq', 'neq'].includes(filter.comparison_op!)
) {
// anyof and nanyof can allow multiple selections,
// while `eq` and `neq` only allow one selection
filter.value = ''
} else if (['blank', 'notblank', 'empty', 'notempty', 'null', 'notnull'].includes(filter.comparison_op!)) {
// since `blank`, `empty`, `null` doesn't require value,
// hence remove the previous value
filter.value = ''
}
saveOrUpdate(filter, i) saveOrUpdate(filter, i)
filterPrevComparisonOp.value[filter.id] = filter.comparison_op
$e('a:filter:update', { $e('a:filter:update', {
logical: filter.logical_op, logical: filter.logical_op,
comparison: filter.comparison_op, comparison: filter.comparison_op,
}) })
} }
const columns = computed(() => meta.value?.columns)
const types = computed(() => { const types = computed(() => {
if (!meta.value?.columns?.length) { if (!meta.value?.columns?.length) {
return {} return {}
@ -76,7 +109,7 @@ const types = computed(() => {
watch( watch(
() => activeView.value?.id, () => activeView.value?.id,
(n, o) => { (n: string, o: string) => {
// if nested no need to reload since it will get reloaded from parent // if nested no need to reload since it will get reloaded from parent
if (!nested && n !== o && (hookId || !webHook)) loadFilters(hookId as string) if (!nested && n !== o && (hookId || !webHook)) loadFilters(hookId as string)
}, },
@ -86,7 +119,7 @@ loadFilters(hookId as string)
watch( watch(
() => nonDeletedFilters.value.length, () => nonDeletedFilters.value.length,
(length) => { (length: number) => {
emit('update:filtersLength', length ?? 0) emit('update:filtersLength', length ?? 0)
}, },
) )
@ -103,19 +136,23 @@ const applyChanges = async (hookId?: string, _nested = false) => {
} }
} }
const isComparisonOpAllowed = (filter: FilterType, compOp: typeof comparisonOpList[number]) => { const selectFilterField = (filter: Filter, index: number) => {
// show current selected value in list even if not allowed // when we change the field,
if (filter.comparison_op === compOp.value) return true // the corresponding default filter operator needs to be changed as well
// since the existing one may not be supported for the new field
// e.g. `eq` operator is not supported in checkbox field
// hence, get the first option of the supported operators of the new field
filter.comparison_op = comparisonOpList(getColumn(filter)!.uidt as UITypes).filter((compOp) =>
isComparisonOpAllowed(filter, compOp),
)?.[0].value
// reset filter value as well
filter.value = ''
saveOrUpdate(filter, index)
}
// include allowed values only if selected column type matches const updateFilterValue = (value: string, filter: Filter, index: number) => {
if (compOp.includedTypes) { filter.value = value
return filter.fk_column_id && compOp.includedTypes.includes(types.value[filter.fk_column_id]) saveOrUpdateDebounced(filter, index)
}
// include not allowed values only if selected column type not matches
else if (compOp.excludedTypes) {
return filter.fk_column_id && !compOp.excludedTypes.includes(types.value[filter.fk_column_id])
}
return true
} }
defineExpose({ defineExpose({
@ -127,7 +164,7 @@ defineExpose({
<template> <template>
<div <div
class="p-4 menu-filter-dropdown bg-gray-50 !border mt-4" class="p-4 menu-filter-dropdown bg-gray-50 !border mt-4"
:class="{ 'shadow min-w-[430px] max-w-[630px] max-h-[max(80vh,500px)] overflow-auto': !nested, 'border-1 w-full': nested }" :class="{ 'shadow min-w-[430px] max-h-[max(80vh,500px)] overflow-auto': !nested, 'border-1 w-full': nested }"
> >
<div v-if="filters && filters.length" class="nc-filter-grid mb-2" @click.stop> <div v-if="filters && filters.length" class="nc-filter-grid mb-2" @click.stop>
<template v-for="(filter, i) in filters" :key="i"> <template v-for="(filter, i) in filters" :key="i">
@ -189,14 +226,13 @@ defineExpose({
hide-details hide-details
:disabled="filter.readOnly" :disabled="filter.readOnly"
dropdown-class-name="nc-dropdown-filter-logical-op" dropdown-class-name="nc-dropdown-filter-logical-op"
@click.stop
@change="filterUpdateCondition(filter, i)" @change="filterUpdateCondition(filter, i)"
@click.stop
> >
<a-select-option v-for="op of logicalOps" :key="op.value" :value="op.value"> <a-select-option v-for="op of logicalOps" :key="op.value" :value="op.value">
{{ op.text }} {{ op.text }}
</a-select-option> </a-select-option>
</a-select> </a-select>
<LazySmartsheetToolbarFieldListAutoCompleteDropdown <LazySmartsheetToolbarFieldListAutoCompleteDropdown
:key="`${i}_6`" :key="`${i}_6`"
v-model="filter.fk_column_id" v-model="filter.fk_column_id"
@ -204,9 +240,8 @@ defineExpose({
:columns="columns" :columns="columns"
:disabled="filter.readOnly" :disabled="filter.readOnly"
@click.stop @click.stop
@change="saveOrUpdate(filter, i)" @change="selectFilterField(filter, i)"
/> />
<a-select <a-select
v-model:value="filter.comparison_op" v-model:value="filter.comparison_op"
:dropdown-match-select-width="false" :dropdown-match-select-width="false"
@ -219,7 +254,7 @@ defineExpose({
dropdown-class-name="nc-dropdown-filter-comp-op" dropdown-class-name="nc-dropdown-filter-comp-op"
@change="filterUpdateCondition(filter, i)" @change="filterUpdateCondition(filter, i)"
> >
<template v-for="compOp of comparisonOpList" :key="compOp.value"> <template v-for="compOp of comparisonOpList(getColumn(filter)?.uidt)" :key="compOp.value">
<a-select-option v-if="isComparisonOpAllowed(filter, compOp)" :value="compOp.value"> <a-select-option v-if="isComparisonOpAllowed(filter, compOp)" :value="compOp.value">
{{ compOp.text }} {{ compOp.text }}
</a-select-option> </a-select-option>
@ -229,19 +264,28 @@ defineExpose({
<span <span
v-if=" v-if="
filter.comparison_op && filter.comparison_op &&
['null', 'notnull', 'checked', 'notchecked', 'empty', 'notempty'].includes(filter.comparison_op) ['null', 'notnull', 'checked', 'notchecked', 'empty', 'notempty', 'blank', 'notblank'].includes(
filter.comparison_op,
)
" "
:key="`span${i}`" :key="`span${i}`"
/> />
<a-input <a-checkbox
v-else-if="filter.field && types[filter.field] === 'boolean'"
v-model:checked="filter.value"
dense
:disabled="filter.readOnly"
@change="saveOrUpdate(filter, i)"
/>
<LazySmartsheetToolbarFilterInput
v-else v-else
:key="`${i}_7`" class="nc-filter-value-select min-w-[120px]"
v-model:value="filter.value" :column="getColumn(filter)"
class="nc-filter-value-select" :filter="filter"
:disabled="filter.readOnly || !filter.fk_column_id" @update-filter-value="(value) => updateFilterValue(value, filter, i)"
@click.stop @click.stop
@input="saveOrUpdate(filter, i)"
/> />
</template> </template>
</template> </template>
@ -259,7 +303,7 @@ defineExpose({
<a-button v-if="!webHook" class="text-capitalize !text-gray-500" @click.stop="addFilterGroup"> <a-button v-if="!webHook" class="text-capitalize !text-gray-500" @click.stop="addFilterGroup">
<div class="flex items-center gap-1"> <div class="flex items-center gap-1">
<!-- Add Filter Group --> <!-- Add Filter Group -->
<MdiPlus /> <MdiPlus />
{{ $t('activity.addFilterGroup') }} {{ $t('activity.addFilterGroup') }}
</div> </div>
@ -271,7 +315,7 @@ defineExpose({
<style scoped> <style scoped>
.nc-filter-grid { .nc-filter-grid {
grid-template-columns: 18px 83px 160px auto auto; grid-template-columns: auto auto auto auto auto;
@apply grid gap-[12px] items-center; @apply grid gap-[12px] items-center;
} }

22
packages/nc-gui/components/smartsheet/toolbar/FieldListAutoCompleteDropdown.vue

@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { SelectProps } from 'ant-design-vue' import type { SelectProps } from 'ant-design-vue'
import type { ColumnType, LinkToAnotherRecordType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType } from 'nocodb-sdk'
import { RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk' import { RelationTypes, UITypes, isSystemColumn, isVirtualCol } from 'nocodb-sdk'
import { MetaInj, computed, inject, ref, resolveComponent } from '#imports' import { ActiveViewInj, MetaInj, computed, inject, ref, resolveComponent, useViewColumns } from '#imports'
const { modelValue, isSort } = defineProps<{ const { modelValue, isSort } = defineProps<{
modelValue?: string modelValue?: string
@ -18,10 +18,21 @@ const localValue = computed({
set: (val) => emit('update:modelValue', val), set: (val) => emit('update:modelValue', val),
}) })
const activeView = inject(ActiveViewInj, ref())
const { showSystemFields, metaColumnById } = useViewColumns(activeView, meta)
const options = computed<SelectProps['options']>(() => const options = computed<SelectProps['options']>(() =>
meta.value?.columns meta.value?.columns
?.filter((c: ColumnType) => { ?.filter((c: ColumnType) => {
if (c.uidt === UITypes.QrCode || c.uidt === UITypes.Barcode) { if (isSystemColumn(metaColumnById?.value?.[c.id!])) {
return (
/** if the field is used in filter, then show it anyway */
localValue.value === c.id ||
/** hide system columns if not enabled */
showSystemFields.value
)
} else if (c.uidt === UITypes.QrCode || c.uidt === UITypes.Barcode || c.uidt === UITypes.ID) {
return false return false
} else if (isSort) { } else if (isSort) {
/** ignore hasmany and manytomany relations if it's using within sort menu */ /** ignore hasmany and manytomany relations if it's using within sort menu */
@ -48,6 +59,11 @@ const options = computed<SelectProps['options']>(() =>
) )
const filterOption = (input: string, option: any) => option.label.toLowerCase()?.includes(input.toLowerCase()) const filterOption = (input: string, option: any) => option.label.toLowerCase()?.includes(input.toLowerCase())
// when a new filter is created, select a field by default
if (!localValue.value) {
localValue.value = (options.value?.[0].value as string) || ''
}
</script> </script>
<template> <template>

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

@ -70,7 +70,7 @@ watch(
const numberOfHiddenFields = computed(() => filteredFieldList.value?.filter((field) => !field.show)?.length) const numberOfHiddenFields = computed(() => filteredFieldList.value?.filter((field) => !field.show)?.length)
const gridPrimaryValueField = computed(() => { const gridDisplayValueField = computed(() => {
if (activeView.value?.type !== ViewTypes.GRID) return null if (activeView.value?.type !== ViewTypes.GRID) return null
const pvCol = Object.values(metaColumnById.value)?.find((col) => col?.pv) const pvCol = Object.values(metaColumnById.value)?.find((col) => col?.pv)
return filteredFieldList.value?.find((field) => field.fk_column_id === pvCol?.id) return filteredFieldList.value?.find((field) => field.fk_column_id === pvCol?.id)
@ -196,7 +196,7 @@ useMenuCloseOnEsc(open)
<Draggable v-model="fields" item-key="id" @change="onMove($event)"> <Draggable v-model="fields" item-key="id" @change="onMove($event)">
<template #item="{ element: field, index: index }"> <template #item="{ element: field, index: index }">
<div <div
v-if="filteredFieldList.filter((el) => el !== gridPrimaryValueField).includes(field)" v-if="filteredFieldList.filter((el) => el !== gridDisplayValueField).includes(field)"
:key="field.id" :key="field.id"
class="px-2 py-1 flex items-center" class="px-2 py-1 flex items-center"
:data-testid="`nc-fields-menu-${field.title}`" :data-testid="`nc-fields-menu-${field.title}`"
@ -222,15 +222,15 @@ useMenuCloseOnEsc(open)
</template> </template>
<template v-if="activeView?.type === ViewTypes.GRID" #header> <template v-if="activeView?.type === ViewTypes.GRID" #header>
<div <div
v-if="gridPrimaryValueField" v-if="gridDisplayValueField"
:key="`pv-${gridPrimaryValueField.id}`" :key="`pv-${gridDisplayValueField.id}`"
class="px-2 py-1 flex items-center" class="px-2 py-1 flex items-center"
:data-testid="`nc-fields-menu-${gridPrimaryValueField.title}`" :data-testid="`nc-fields-menu-${gridDisplayValueField.title}`"
@click.stop @click.stop
> >
<a-tooltip placement="bottom"> <a-tooltip placement="bottom">
<template #title> <template #title>
<span class="text-sm">Primary Value</span> <span class="text-sm">Display Value</span>
</template> </template>
<MdiTableKey class="text-xs" /> <MdiTableKey class="text-xs" />

194
packages/nc-gui/components/smartsheet/toolbar/FilterInput.vue

@ -0,0 +1,194 @@
<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import {
ColumnInj,
EditModeInj,
ReadonlyInj,
computed,
isBoolean,
isCurrency,
isDate,
isDateTime,
isDecimal,
isDuration,
isFloat,
isInt,
isMultiSelect,
isPercent,
isRating,
isSingleSelect,
isTextArea,
isTime,
isYear,
provide,
ref,
toRef,
useProject,
} from '#imports'
import type { Filter } from '~/lib'
import SingleSelect from '~/components/cell/SingleSelect.vue'
import MultiSelect from '~/components/cell/MultiSelect.vue'
import DatePicker from '~/components/cell/DatePicker.vue'
import YearPicker from '~/components/cell/YearPicker.vue'
import DateTimePicker from '~/components/cell/DateTimePicker.vue'
import TimePicker from '~/components/cell/TimePicker.vue'
import Rating from '~/components/cell/Rating.vue'
import Duration from '~/components/cell/Duration.vue'
import Percent from '~/components/cell/Percent.vue'
import Currency from '~/components/cell/Currency.vue'
import Decimal from '~/components/cell/Decimal.vue'
import Integer from '~/components/cell/Integer.vue'
import Float from '~/components/cell/Float.vue'
import Text from '~/components/cell/Text.vue'
interface Props {
column: ColumnType
filter: Filter
}
interface Emits {
(event: 'updateFilterValue', model: any): void
}
const props = defineProps<Props>()
const emit = defineEmits<Emits>()
const column = toRef(props, 'column')
const editEnabled = ref(true)
provide(ColumnInj, column)
provide(EditModeInj, readonly(editEnabled))
provide(ReadonlyInj, ref(false))
const checkTypeFunctions = {
isSingleSelect,
isMultiSelect,
isDate,
isYear,
isDateTime,
isTime,
isRating,
isDuration,
isPercent,
isCurrency,
isDecimal,
isInt,
isFloat,
isTextArea,
}
type FilterType = keyof typeof checkTypeFunctions
const { sqlUi } = $(useProject())
const abstractType = $computed(() => (column.value?.dt && sqlUi ? sqlUi.getAbstractType(column.value) : null))
const checkType = (filterType: FilterType) => {
const checkTypeFunction = checkTypeFunctions[filterType]
if (!column.value || !checkTypeFunction) {
return false
}
return checkTypeFunction(column.value, abstractType)
}
const filterInput = computed({
get: () => {
return props.filter.value
},
set: (value) => {
emit('updateFilterValue', value)
},
})
const booleanOptions = [
{ value: true, label: 'true' },
{ value: false, label: 'false' },
{ value: null, label: 'unset' },
]
const componentMap: Partial<Record<FilterType, any>> = $computed(() => {
return {
// use MultiSelect for SingleSelect columns for anyof / nanyof filters
isSingleSelect: ['anyof', 'nanyof'].includes(props.filter.comparison_op!) ? MultiSelect : SingleSelect,
isMultiSelect: MultiSelect,
isDate: DatePicker,
isYear: YearPicker,
isDateTime: DateTimePicker,
isTime: TimePicker,
isRating: Rating,
isDuration: Duration,
isPercent: Percent,
isCurrency: Currency,
isDecimal: Decimal,
isInt: Integer,
isFloat: Float,
}
})
const filterType = $computed(() => {
return Object.keys(componentMap).find((key) => checkType(key as FilterType))
})
const componentProps = $computed(() => {
switch (filterType) {
case 'isSingleSelect':
case 'isMultiSelect': {
return { disableOptionCreation: true }
}
case 'isPercent':
case 'isDecimal':
case 'isFloat':
case 'isInt': {
return { class: 'h-32px' }
}
case 'isDuration': {
return { showValidationError: false }
}
default: {
return {}
}
}
})
const hasExtraPadding = $computed(() => {
return (
column.value &&
(isInt(column.value, abstractType) ||
isDate(column.value, abstractType) ||
isDateTime(column.value, abstractType) ||
isTime(column.value, abstractType) ||
isYear(column.value, abstractType))
)
})
</script>
<template>
<a-select
v-if="column && isBoolean(column, abstractType)"
v-model:value="filterInput"
:disabled="filter.readOnly"
:options="booleanOptions"
/>
<div
v-else
class="bg-white border-1 flex min-w-120px max-w-170px min-h-32px h-full"
:class="{ 'px-2': hasExtraPadding }"
@mouseup.stop
>
<component
:is="filterType ? componentMap[filterType] : Text"
v-model="filterInput"
:disabled="filter.readOnly"
placeholder="Enter a value"
:column="column"
class="flex"
v-bind="componentProps"
/>
</div>
</template>

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

@ -12,6 +12,7 @@ import {
computed, computed,
createEventHook, createEventHook,
extractSdkResponseErrorMsg, extractSdkResponseErrorMsg,
fieldLengthValidator,
fieldRequiredValidator, fieldRequiredValidator,
getDateFormat, getDateFormat,
getDateTimeFormat, getDateTimeFormat,
@ -110,12 +111,15 @@ const data = reactive<{
}) })
const validators = computed(() => const validators = computed(() =>
data.tables.reduce<Record<string, [ReturnType<typeof fieldRequiredValidator>]>>((acc, table, tableIdx) => { data.tables.reduce<Record<string, [ReturnType<typeof fieldRequiredValidator>]>>((acc: Record<string, any>, table, tableIdx) => {
acc[`tables.${tableIdx}.table_name`] = [fieldRequiredValidator()] acc[`tables.${tableIdx}.table_name`] = [fieldRequiredValidator()]
hasSelectColumn.value[tableIdx] = false hasSelectColumn.value[tableIdx] = false
table.columns?.forEach((column, columnIdx) => { table.columns?.forEach((column, columnIdx) => {
acc[`tables.${tableIdx}.columns.${columnIdx}.column_name`] = [fieldRequiredValidator()] acc[`tables.${tableIdx}.columns.${columnIdx}.column_name`] = [
fieldRequiredValidator(),
fieldLengthValidator(project.value?.bases?.[0].type || ClientType.MYSQL),
]
acc[`tables.${tableIdx}.columns.${columnIdx}.uidt`] = [fieldRequiredValidator()] acc[`tables.${tableIdx}.columns.${columnIdx}.uidt`] = [fieldRequiredValidator()]
if (isSelect(column)) { if (isSelect(column)) {
hasSelectColumn.value[tableIdx] = true hasSelectColumn.value[tableIdx] = true
@ -516,7 +520,7 @@ async function importTemplate() {
tab.title = createdTable.title as string tab.title = createdTable.title as string
} }
// set primary value // set display value
if (createdTable?.columns?.[0]?.id) { if (createdTable?.columns?.[0]?.id) {
await $api.dbTableColumn.primaryColumnSet(createdTable.columns[0].id as string) await $api.dbTableColumn.primaryColumnSet(createdTable.columns[0].id as string)
} }

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

@ -44,7 +44,7 @@ const listItemsDlg = ref(false)
const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow() const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow()
const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore( const { loadRelatedTableMeta, relatedTableDisplayValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>, column as Ref<Required<ColumnType>>,
row, row,
isNew, isNew,
@ -85,8 +85,8 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
<template> <template>
<div class="flex w-full chips-wrapper items-center" :class="{ active }"> <div class="flex w-full chips-wrapper items-center" :class="{ active }">
<div class="chips flex items-center flex-1"> <div class="chips flex items-center flex-1">
<template v-if="value && relatedTablePrimaryValueProp"> <template v-if="value && relatedTableDisplayValueProp">
<VirtualCellComponentsItemChip :item="value" :value="value[relatedTablePrimaryValueProp]" @unlink="unlinkRef(value)" /> <VirtualCellComponentsItemChip :item="value" :value="value[relatedTableDisplayValueProp]" @unlink="unlinkRef(value)" />
</template> </template>
</div> </div>

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

@ -40,7 +40,7 @@ const { isUIAllowed } = useUIPermission()
const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow() const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow()
const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore( const { loadRelatedTableMeta, relatedTableDisplayValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>, column as Ref<Required<ColumnType>>,
row, row,
isNew, isNew,
@ -60,9 +60,9 @@ const localCellValue = computed<any[]>(() => {
const cells = computed(() => const cells = computed(() =>
localCellValue.value.reduce((acc, curr) => { localCellValue.value.reduce((acc, curr) => {
if (!relatedTablePrimaryValueProp.value) return acc if (!relatedTableDisplayValueProp.value) return acc
const value = curr[relatedTablePrimaryValueProp.value] const value = curr[relatedTableDisplayValueProp.value]
if (!value) return acc if (!value) return acc

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

@ -42,7 +42,7 @@ const { isUIAllowed } = useUIPermission()
const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow() const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow()
const { loadRelatedTableMeta, relatedTablePrimaryValueProp, unlink } = useProvideLTARStore( const { loadRelatedTableMeta, relatedTableDisplayValueProp, unlink } = useProvideLTARStore(
column as Ref<Required<ColumnType>>, column as Ref<Required<ColumnType>>,
row, row,
isNew, isNew,
@ -62,9 +62,9 @@ const localCellValue = computed<any[]>(() => {
const cells = computed(() => const cells = computed(() =>
localCellValue.value.reduce((acc, curr) => { localCellValue.value.reduce((acc, curr) => {
if (!relatedTablePrimaryValueProp.value) return acc if (!relatedTableDisplayValueProp.value) return acc
const value = curr[relatedTablePrimaryValueProp.value] const value = curr[relatedTableDisplayValueProp.value]
if (!value) return acc if (!value) return acc

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

@ -37,7 +37,7 @@ const {
deleteRelatedRow, deleteRelatedRow,
loadChildrenList, loadChildrenList,
childrenListPagination, childrenListPagination,
relatedTablePrimaryValueProp, relatedTableDisplayValueProp,
unlink, unlink,
getRelatedTableRowId, getRelatedTableRowId,
relatedTableMeta, relatedTableMeta,
@ -146,7 +146,7 @@ const onClick = (row: Row) => {
> >
<div class="flex items-center"> <div class="flex items-center">
<div class="flex-1 overflow-hidden min-w-0"> <div class="flex-1 overflow-hidden min-w-0">
{{ row[relatedTablePrimaryValueProp] }} {{ row[relatedTableDisplayValueProp] }}
<span class="text-gray-400 text-[11px] ml-1">(Primary key : {{ getRelatedTableRowId(row) }})</span> <span class="text-gray-400 text-[11px] ml-1">(Primary key : {{ getRelatedTableRowId(row) }})</span>
</div> </div>

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

@ -32,7 +32,7 @@ const {
childrenExcludedList, childrenExcludedList,
loadChildrenExcludedList, loadChildrenExcludedList,
childrenExcludedListPagination, childrenExcludedListPagination,
relatedTablePrimaryValueProp, relatedTableDisplayValueProp,
link, link,
getRelatedTableRowId, getRelatedTableRowId,
relatedTableMeta, relatedTableMeta,
@ -201,7 +201,7 @@ const activeRow = (vNode?: InstanceType<typeof Card>) => {
:class="{ 'nc-selected-row': selectedRowIndex === i }" :class="{ 'nc-selected-row': selectedRowIndex === i }"
@click="linkRow(refRow)" @click="linkRow(refRow)"
> >
{{ refRow[relatedTablePrimaryValueProp] }} {{ refRow[relatedTableDisplayValueProp] }}
<span class="hidden group-hover:(inline) text-gray-400 text-[11px] ml-1"> <span class="hidden group-hover:(inline) text-gray-400 text-[11px] ml-1">
({{ $t('labels.primaryKey') }} : {{ getRelatedTableRowId(refRow) }}) ({{ $t('labels.primaryKey') }} : {{ getRelatedTableRowId(refRow) }})
</span> </span>

4
packages/nc-gui/composables/useColumnCreateStore.ts

@ -27,7 +27,8 @@ interface ValidationsObj {
const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState( const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState(
(meta: Ref<TableType | undefined>, column: Ref<ColumnType | undefined>) => { (meta: Ref<TableType | undefined>, column: Ref<ColumnType | undefined>) => {
const { sqlUis, isMysql: isMysqlFunc, isPg: isPgFunc, isMssql: isMssqlFunc } = useProject() const { project, sqlUis, isMysql: isMysqlFunc, isPg: isPgFunc, isMssql: isMssqlFunc } = useProject()
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { getMeta } = useMetas() const { getMeta } = useMetas()
@ -93,6 +94,7 @@ const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState
}) })
}, },
}, },
fieldLengthValidator(project.value?.bases?.[0].type || ClientType.MYSQL),
], ],
uidt: [ uidt: [
{ {

9
packages/nc-gui/composables/useExpandedFormStore.ts

@ -49,7 +49,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
const { sharedView } = useSharedView() const { sharedView } = useSharedView()
// getters // getters
const primaryValue = computed(() => { const displayValue = computed(() => {
if (row?.value?.row) { if (row?.value?.row) {
const col = meta?.value?.columns?.find((c) => c.pv) const col = meta?.value?.columns?.find((c) => c.pv)
@ -190,7 +190,8 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
} }
} else { } else {
// No columns to update // No columns to update
return message.info(t('msg.info.noColumnsToUpdate')) message.info(t('msg.info.noColumnsToUpdate'))
return
} }
} }
@ -199,7 +200,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
addOrEditStackRow(row.value, isNewRow) addOrEditStackRow(row.value, isNewRow)
} }
message.success(`${primaryValue.value || 'Row'} updated successfully.`) message.success(`${displayValue.value || 'Row'} updated successfully.`)
changedColumns.value = new Set() changedColumns.value = new Set()
} catch (e: any) { } catch (e: any) {
@ -237,7 +238,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
isYou, isYou,
commentsDrawer, commentsDrawer,
row, row,
primaryValue, displayValue,
save, save,
changedColumns, changedColumns,
loadRow, loadRow,

1
packages/nc-gui/composables/useGlobal/state.ts

@ -95,6 +95,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
oneClick: false, oneClick: false,
projectHasAdmin: false, projectHasAdmin: false,
teleEnabled: true, teleEnabled: true,
auditEnabled: true,
type: 'nocodb', type: 'nocodb',
version: '0.0.0', version: '0.0.0',
ncAttachmentFieldSize: 20, ncAttachmentFieldSize: 20,

1
packages/nc-gui/composables/useGlobal/types.ts

@ -16,6 +16,7 @@ export interface AppInfo {
oneClick: boolean oneClick: boolean
projectHasAdmin: boolean projectHasAdmin: boolean
teleEnabled: boolean teleEnabled: boolean
auditEnabled: boolean
type: string type: string
version: string version: string
ee?: boolean ee?: boolean

22
packages/nc-gui/composables/useLTARStore.ts

@ -94,14 +94,14 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
await getMeta(colOptions.fk_related_model_id as string) await getMeta(colOptions.fk_related_model_id as string)
} }
const relatedTablePrimaryValueProp = computed(() => { const relatedTableDisplayValueProp = computed(() => {
return (relatedTableMeta.value?.columns?.find((c) => c.pv) || relatedTableMeta?.value?.columns?.[0])?.title || '' return (relatedTableMeta.value?.columns?.find((c) => c.pv) || relatedTableMeta?.value?.columns?.[0])?.title || ''
}) })
const relatedTablePrimaryKeyProps = computed(() => { const relatedTablePrimaryKeyProps = computed(() => {
return relatedTableMeta.value?.columns?.filter((c) => c.pk)?.map((c) => c.title) ?? [] return relatedTableMeta.value?.columns?.filter((c) => c.pk)?.map((c) => c.title) ?? []
}) })
const primaryValueProp = computed(() => { const displayValueProp = computed(() => {
return (meta.value?.columns?.find((c: Required<ColumnType>) => c.pv) || relatedTableMeta?.value?.columns?.[0])?.title return (meta.value?.columns?.find((c: Required<ColumnType>) => c.pv) || relatedTableMeta?.value?.columns?.[0])?.title
}) })
@ -125,8 +125,8 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
offset: childrenExcludedListPagination.size * (childrenExcludedListPagination.page - 1), offset: childrenExcludedListPagination.size * (childrenExcludedListPagination.page - 1),
where: where:
childrenExcludedListPagination.query && childrenExcludedListPagination.query &&
`(${relatedTablePrimaryValueProp.value},like,${childrenExcludedListPagination.query})`, `(${relatedTableDisplayValueProp.value},like,${childrenExcludedListPagination.query})`,
fields: [relatedTablePrimaryValueProp.value, ...relatedTablePrimaryKeyProps.value], fields: [relatedTableDisplayValueProp.value, ...relatedTablePrimaryKeyProps.value],
} as RequestParams, } as RequestParams,
}, },
) )
@ -142,8 +142,8 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
offset: childrenExcludedListPagination.size * (childrenExcludedListPagination.page - 1), offset: childrenExcludedListPagination.size * (childrenExcludedListPagination.page - 1),
where: where:
childrenExcludedListPagination.query && childrenExcludedListPagination.query &&
`(${relatedTablePrimaryValueProp.value},like,${childrenExcludedListPagination.query})`, `(${relatedTableDisplayValueProp.value},like,${childrenExcludedListPagination.query})`,
fields: [relatedTablePrimaryValueProp.value, ...relatedTablePrimaryKeyProps.value], fields: [relatedTableDisplayValueProp.value, ...relatedTablePrimaryKeyProps.value],
} as any, } as any,
) )
} else { } else {
@ -160,7 +160,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
// todo: where clause is missing from type // todo: where clause is missing from type
where: where:
childrenExcludedListPagination.query && childrenExcludedListPagination.query &&
`(${relatedTablePrimaryValueProp.value},like,${childrenExcludedListPagination.query})`, `(${relatedTableDisplayValueProp.value},like,${childrenExcludedListPagination.query})`,
} as any, } as any,
) )
} }
@ -183,7 +183,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
limit: String(childrenListPagination.size), limit: String(childrenListPagination.size),
offset: String(childrenListPagination.size * (childrenListPagination.page - 1)), offset: String(childrenListPagination.size * (childrenListPagination.page - 1)),
where: where:
childrenListPagination.query && `(${relatedTablePrimaryValueProp.value},like,${childrenListPagination.query})`, childrenListPagination.query && `(${relatedTableDisplayValueProp.value},like,${childrenListPagination.query})`,
} as any, } as any,
) )
} else { } else {
@ -198,7 +198,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
limit: String(childrenListPagination.size), limit: String(childrenListPagination.size),
offset: String(childrenListPagination.size * (childrenListPagination.page - 1)), offset: String(childrenListPagination.size * (childrenListPagination.page - 1)),
where: where:
childrenListPagination.query && `(${relatedTablePrimaryValueProp.value},like,${childrenListPagination.query})`, childrenListPagination.query && `(${relatedTableDisplayValueProp.value},like,${childrenListPagination.query})`,
} as any, } as any,
) )
} }
@ -320,13 +320,13 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
return { return {
relatedTableMeta, relatedTableMeta,
loadRelatedTableMeta, loadRelatedTableMeta,
relatedTablePrimaryValueProp, relatedTableDisplayValueProp,
childrenExcludedList, childrenExcludedList,
childrenList, childrenList,
rowId, rowId,
childrenExcludedListPagination, childrenExcludedListPagination,
childrenListPagination, childrenListPagination,
primaryValueProp, displayValueProp,
meta, meta,
unlink, unlink,
link, link,

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

@ -34,7 +34,9 @@ export const useProject = createSharedComposable(() => {
const projectLoadedHook = createEventHook<ProjectType>() const projectLoadedHook = createEventHook<ProjectType>()
const project = ref<ProjectType>({}) const project = ref<ProjectType>({})
const bases = computed<BaseType[]>(() => project.value?.bases || []) const bases = computed<BaseType[]>(() => project.value?.bases || [])
const tables = ref<TableType[]>([]) const tables = ref<TableType[]>([])
const projectMetaInfo = ref<ProjectMetaInfo | undefined>() const projectMetaInfo = ref<ProjectMetaInfo | undefined>()
@ -49,10 +51,13 @@ export const useProject = createSharedComposable(() => {
const projectType = $computed(() => route.params.projectType as string) const projectType = $computed(() => route.params.projectType as string)
const projectMeta = computed<Record<string, any>>(() => { const projectMeta = computed<Record<string, any>>(() => {
const defaultMeta = {
showNullAndEmptyInFilter: false,
}
try { try {
return isString(project.value.meta) ? JSON.parse(project.value.meta) : project.value.meta return (isString(project.value.meta) ? JSON.parse(project.value.meta) : project.value.meta) ?? defaultMeta
} catch (e) { } catch (e) {
return {} return defaultMeta
} }
}) })
@ -169,6 +174,10 @@ export const useProject = createSharedComposable(() => {
$e('c:themes:change') $e('c:themes:change')
} }
async function hasEmptyOrNullFilters() {
return await api.project.hasEmptyOrNullFilters(projectId.value)
}
const reset = () => { const reset = () => {
project.value = {} project.value = {}
tables.value = [] tables.value = []
@ -207,5 +216,6 @@ export const useProject = createSharedComposable(() => {
isLoading, isLoading,
lastOpenedViewMap, lastOpenedViewMap,
isXcdbBase, isXcdbBase,
hasEmptyOrNullFilters,
} }
}) })

114
packages/nc-gui/composables/useViewFilters.ts

@ -1,15 +1,20 @@
import type { FilterType, ViewType } from 'nocodb-sdk' import type { ColumnType, FilterType, ViewType } from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import type { SelectProps } from 'ant-design-vue'
import { UITypes, isSystemColumn } from 'nocodb-sdk'
import { import {
ActiveViewInj,
IsPublicInj, IsPublicInj,
ReloadViewDataHookInj, MetaInj,
computed, computed,
extractSdkResponseErrorMsg, extractSdkResponseErrorMsg,
inject, inject,
message, message,
ref, ref,
useDebounceFn,
useMetas, useMetas,
useNuxtApp, useNuxtApp,
useProject,
useUIPermission, useUIPermission,
watch, watch,
} from '#imports' } from '#imports'
@ -30,6 +35,8 @@ export function useViewFilters(
const { nestedFilters } = useSmartsheetStoreOrThrow() const { nestedFilters } = useSmartsheetStoreOrThrow()
const { projectMeta } = useProject()
const isPublic = inject(IsPublicInj, ref(false)) const isPublic = inject(IsPublicInj, ref(false))
const { $api, $e } = useNuxtApp() const { $api, $e } = useNuxtApp()
@ -68,11 +75,80 @@ export function useViewFilters(
// nonDeletedFilters are those filters that are not deleted physically & virtually // nonDeletedFilters are those filters that are not deleted physically & virtually
const nonDeletedFilters = computed(() => filters.value.filter((f) => f.status !== 'delete')) const nonDeletedFilters = computed(() => filters.value.filter((f) => f.status !== 'delete'))
const placeholderFilter: Filter = { const meta = inject(MetaInj, ref())
comparison_op: 'eq',
value: '', const activeView = inject(ActiveViewInj, ref())
status: 'create',
logical_op: 'and', const { showSystemFields, metaColumnById } = useViewColumns(activeView, meta)
const options = computed<SelectProps['options']>(() =>
meta.value?.columns?.filter((c: ColumnType) => {
if (isSystemColumn(metaColumnById?.value?.[c.id!])) {
/** hide system columns if not enabled */
return showSystemFields.value
} else if (c.uidt === UITypes.QrCode || c.uidt === UITypes.Barcode || c.uidt === UITypes.ID || c.system) {
return false
} else {
const isVirtualSystemField = c.colOptions && c.system
return !isVirtualSystemField
}
}),
)
const types = computed(() => {
if (!meta.value?.columns?.length) {
return {}
}
return meta.value?.columns?.reduce((obj: any, col: any) => {
obj[col.id] = col.uidt
return obj
}, {})
})
const isComparisonOpAllowed = (
filter: FilterType,
compOp: {
text: string
value: string
ignoreVal?: boolean
includedTypes?: UITypes[]
excludedTypes?: UITypes[]
},
) => {
const isNullOrEmptyOp = ['empty', 'notempty', 'null', 'notnull'].includes(compOp.value)
if (compOp.includedTypes) {
// include allowed values only if selected column type matches
if (filter.fk_column_id && compOp.includedTypes.includes(types.value[filter.fk_column_id])) {
// for 'empty', 'notempty', 'null', 'notnull',
// show them based on `showNullAndEmptyInFilter` in Project Settings
return isNullOrEmptyOp ? projectMeta.value.showNullAndEmptyInFilter : true
} else {
return false
}
} else if (compOp.excludedTypes) {
// include not allowed values only if selected column type not matches
if (filter.fk_column_id && !compOp.excludedTypes.includes(types.value[filter.fk_column_id])) {
// for 'empty', 'notempty', 'null', 'notnull',
// show them based on `showNullAndEmptyInFilter` in Project Settings
return isNullOrEmptyOp ? projectMeta.value.showNullAndEmptyInFilter : true
} else {
return false
}
}
// explicitly include for non-null / non-empty ops
return isNullOrEmptyOp ? projectMeta.value.showNullAndEmptyInFilter : true
}
const placeholderFilter = (): Filter => {
return {
comparison_op: comparisonOpList(options.value?.[0].uidt as UITypes).filter((compOp) =>
isComparisonOpAllowed({ fk_column_id: options.value?.[0].id }, compOp),
)?.[0].value,
value: '',
status: 'create',
logical_op: 'and',
}
} }
const loadFilters = async (hookId?: string) => { const loadFilters = async (hookId?: string) => {
@ -191,8 +267,6 @@ export function useViewFilters(
fk_parent_id: parentId, fk_parent_id: parentId,
}) })
} }
reloadHook?.trigger()
} catch (e: any) { } catch (e: any) {
console.log(e) console.log(e)
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
@ -201,13 +275,16 @@ export function useViewFilters(
reloadData?.() reloadData?.()
} }
const saveOrUpdateDebounced = useDebounceFn(saveOrUpdate, 500)
const addFilter = () => { const addFilter = () => {
filters.value.push({ ...placeholderFilter }) filters.value.push(placeholderFilter())
$e('a:filter:add', { length: filters.value.length }) $e('a:filter:add', { length: filters.value.length })
} }
const addFilterGroup = async () => { const addFilterGroup = async () => {
const child = { ...placeholderFilter } const child = placeholderFilter()
const placeHolderGroupFilter: Filter = { const placeHolderGroupFilter: Filter = {
is_group: true, is_group: true,
status: 'create', status: 'create',
@ -234,10 +311,21 @@ export function useViewFilters(
return metas?.value?.[view?.value?.fk_model_id as string]?.columns?.length || 0 return metas?.value?.[view?.value?.fk_model_id as string]?.columns?.length || 0
}, },
async (nextColsLength, oldColsLength) => { async (nextColsLength: number, oldColsLength: number) => {
if (nextColsLength && nextColsLength < oldColsLength) await loadFilters() if (nextColsLength && nextColsLength < oldColsLength) await loadFilters()
}, },
) )
return { filters, nonDeletedFilters, loadFilters, sync, deleteFilter, saveOrUpdate, addFilter, addFilterGroup } return {
filters,
nonDeletedFilters,
loadFilters,
sync,
deleteFilter,
saveOrUpdate,
addFilter,
addFilterGroup,
saveOrUpdateDebounced,
isComparisonOpAllowed,
}
} }

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

@ -380,7 +380,7 @@
"renameTable": "إعادة تسمية الجدول", "renameTable": "إعادة تسمية الجدول",
"deleteTable": "حذف الجدول", "deleteTable": "حذف الجدول",
"addField": "إضافة حقل جديد إلى هذا الجدول", "addField": "إضافة حقل جديد إلى هذا الجدول",
"setPrimary": "تعيين كقيمة أساسية", "setDisplay": "Set as Display value",
"addRow": "إضافة صف جديد", "addRow": "إضافة صف جديد",
"saveRow": "حفظ الصف", "saveRow": "حفظ الصف",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "هل أنت متأكد من أنك تريد حذف هذا العرض؟", "deleteViewConfirmation": "هل أنت متأكد من أنك تريد حذف هذا العرض؟",
"deleteTableConfirmation": "هل تريد حذف الجدول", "deleteTableConfirmation": "هل تريد حذف الجدول",
"showM2mTables": "إظهار جداول M2M", "showM2mTables": "إظهار جداول M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "টিল নম পরিবরতন", "renameTable": "টিল নম পরিবরতন",
"deleteTable": "टबल मि", "deleteTable": "टबल मि",
"addField": "এই টি নতন কর যত করন", "addField": "এই টি নতন কর যত করন",
"setPrimary": "পথমিক মন হিট কর", "setDisplay": "Set as Display value",
"addRow": "নতন সিত করন", "addRow": "নতন সিত করন",
"saveRow": "সিরকষণ করন", "saveRow": "সিরকষণ করন",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "Přejmenování tabulky", "renameTable": "Přejmenování tabulky",
"deleteTable": "Tabulka Odstranit", "deleteTable": "Tabulka Odstranit",
"addField": "Přidání nového pole do této tabulky", "addField": "Přidání nového pole do této tabulky",
"setPrimary": "Nastavit jako primární hodnotu", "setDisplay": "Set as Display value",
"addRow": "Přidat nový řádek", "addRow": "Přidat nový řádek",
"saveRow": "Uložit řádek", "saveRow": "Uložit řádek",
"saveAndExit": "Uložit a odejít", "saveAndExit": "Uložit a odejít",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Opravdu chcete toto zobrazení odstranit?", "deleteViewConfirmation": "Opravdu chcete toto zobrazení odstranit?",
"deleteTableConfirmation": "Chcete odstranit tabulku", "deleteTableConfirmation": "Chcete odstranit tabulku",
"showM2mTables": "Zobrazit tabulky M2M", "showM2mTables": "Zobrazit tabulky M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Odstraněním tohoto zásobníku se také odstraní možnost výběru `{stackToBeDeleted}` z `{groupingField}`. Záznamy se přesunou do zásobníku nezařazených záznamů.", "deleteKanbanStackConfirmation": "Odstraněním tohoto zásobníku se také odstraní možnost výběru `{stackToBeDeleted}` z `{groupingField}`. Záznamy se přesunou do zásobníku nezařazených záznamů.",
"computedFieldEditWarning": "Vypočtené pole: obsah je určen pouze pro čtení. Ke změně konfigurace sloupce použijte nabídku úprav sloupce", "computedFieldEditWarning": "Vypočtené pole: obsah je určen pouze pro čtení. Ke změně konfigurace sloupce použijte nabídku úprav sloupce",
"computedFieldDeleteWarning": "Vypočtené pole: obsah je určen pouze pro čtení. Nelze vymazat obsah.", "computedFieldDeleteWarning": "Vypočtené pole: obsah je určen pouze pro čtení. Nelze vymazat obsah.",

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

@ -380,7 +380,7 @@
"renameTable": "Bord omdøb", "renameTable": "Bord omdøb",
"deleteTable": "TABEL DELETE.", "deleteTable": "TABEL DELETE.",
"addField": "Tilføj nyt felt til denne tabel", "addField": "Tilføj nyt felt til denne tabel",
"setPrimary": "Indstil som primær værdi", "setDisplay": "Set as Display value",
"addRow": "Tilføj ny række", "addRow": "Tilføj ny række",
"saveRow": "Gem ro", "saveRow": "Gem ro",
"saveAndExit": "Gem og afslutning", "saveAndExit": "Gem og afslutning",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Er du sikker på, at du vil slette denne visning?", "deleteViewConfirmation": "Er du sikker på, at du vil slette denne visning?",
"deleteTableConfirmation": "Ønsker du at slette tabellen", "deleteTableConfirmation": "Ønsker du at slette tabellen",
"showM2mTables": "Vis M2M-tabeller", "showM2mTables": "Vis M2M-tabeller",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Hvis du sletter denne stak, fjernes også valgmuligheden `{stackToBeDeleted}` fra `{groupingField}`. Posterne vil blive flyttet til stakken \"uncategorized\".", "deleteKanbanStackConfirmation": "Hvis du sletter denne stak, fjernes også valgmuligheden `{stackToBeDeleted}` fra `{groupingField}`. Posterne vil blive flyttet til stakken \"uncategorized\".",
"computedFieldEditWarning": "Beregnet felt: indholdet er skrivebeskyttet. Brug kolonne-redigeringsmenuen til at omkonfigurere", "computedFieldEditWarning": "Beregnet felt: indholdet er skrivebeskyttet. Brug kolonne-redigeringsmenuen til at omkonfigurere",
"computedFieldDeleteWarning": "Beregnet felt: indholdet er skrivebeskyttet. Det er ikke muligt at slette indholdet.", "computedFieldDeleteWarning": "Beregnet felt: indholdet er skrivebeskyttet. Det er ikke muligt at slette indholdet.",

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

@ -380,7 +380,7 @@
"renameTable": "Tabelle umbenennen", "renameTable": "Tabelle umbenennen",
"deleteTable": "Tabelle löschen", "deleteTable": "Tabelle löschen",
"addField": "Neues Feld zu dieser Tabelle hinzufügen", "addField": "Neues Feld zu dieser Tabelle hinzufügen",
"setPrimary": "Als Primärwert festlegen", "setDisplay": "Set as Display value",
"addRow": "Neue Zeile hinzufügen", "addRow": "Neue Zeile hinzufügen",
"saveRow": "Zeile speichern", "saveRow": "Zeile speichern",
"saveAndExit": "Speichern & Verlassen", "saveAndExit": "Speichern & Verlassen",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Sind Sie sicher, dass Sie diese Ansicht löschen möchten?", "deleteViewConfirmation": "Sind Sie sicher, dass Sie diese Ansicht löschen möchten?",
"deleteTableConfirmation": "Möchten Sie die Tabelle löschen", "deleteTableConfirmation": "Möchten Sie die Tabelle löschen",
"showM2mTables": "M2M Tabellen anzeigen", "showM2mTables": "M2M Tabellen anzeigen",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Wenn Sie diesen Stapel löschen, wird auch die Auswahloption \"{stackToBeDeleted}\" von der Seite \"{groupingField}\" entfernt. Die Datensätze werden in den nicht kategorisierten Stapel verschoben.", "deleteKanbanStackConfirmation": "Wenn Sie diesen Stapel löschen, wird auch die Auswahloption \"{stackToBeDeleted}\" von der Seite \"{groupingField}\" entfernt. Die Datensätze werden in den nicht kategorisierten Stapel verschoben.",
"computedFieldEditWarning": "Berechnetes Feld: Der Inhalt ist schreibgeschützt. Verwenden Sie das Menü \"Spalten bearbeiten\", um das Feld neu zu konfigurieren.", "computedFieldEditWarning": "Berechnetes Feld: Der Inhalt ist schreibgeschützt. Verwenden Sie das Menü \"Spalten bearbeiten\", um das Feld neu zu konfigurieren.",
"computedFieldDeleteWarning": "Berechnetes Feld: Inhalt ist schreibgeschützt. Inhalt kann nicht gelöscht werden.", "computedFieldDeleteWarning": "Berechnetes Feld: Inhalt ist schreibgeschützt. Inhalt kann nicht gelöscht werden.",

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

@ -381,7 +381,7 @@
"renameTable": "Table Rename", "renameTable": "Table Rename",
"deleteTable": "Table Delete", "deleteTable": "Table Delete",
"addField": "Add new field to this table", "addField": "Add new field to this table",
"setPrimary": "Set as Primary value", "setDisplay": "Set as Display value",
"addRow": "Add new row", "addRow": "Add new row",
"saveRow": "Save row", "saveRow": "Save row",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -640,6 +640,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",
@ -694,6 +699,7 @@
"nameShouldStartWithAnAlphabetOr_": "Name should start with an alphabet or _", "nameShouldStartWithAnAlphabetOr_": "Name should start with an alphabet or _",
"followingCharactersAreNotAllowed": "Following characters are not allowed", "followingCharactersAreNotAllowed": "Following characters are not allowed",
"columnNameRequired": "Column name is required", "columnNameRequired": "Column name is required",
"columnNameExceedsCharacters": "The length of column name exceeds the max {value} characters",
"projectNameExceeds50Characters": "Project name exceeds 50 characters", "projectNameExceeds50Characters": "Project name exceeds 50 characters",
"projectNameCannotStartWithSpace": "Project name cannot start with space", "projectNameCannotStartWithSpace": "Project name cannot start with space",
"requiredField": "Required field", "requiredField": "Required field",

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

@ -380,7 +380,7 @@
"renameTable": "Cambiar el nombre de la tabla", "renameTable": "Cambiar el nombre de la tabla",
"deleteTable": "Borrar tabla", "deleteTable": "Borrar tabla",
"addField": "Añadir nuevo campo a esta tabla", "addField": "Añadir nuevo campo a esta tabla",
"setPrimary": "Establecido como clave primaria", "setDisplay": "Set as Display value",
"addRow": "Añadir nueva fila", "addRow": "Añadir nueva fila",
"saveRow": "Grabar la fila", "saveRow": "Grabar la fila",
"saveAndExit": "Guardar y salir", "saveAndExit": "Guardar y salir",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "¿Está seguro de que desea eliminar esta vista?", "deleteViewConfirmation": "¿Está seguro de que desea eliminar esta vista?",
"deleteTableConfirmation": "¿Desea eliminar la tabla", "deleteTableConfirmation": "¿Desea eliminar la tabla",
"showM2mTables": "Mostrar tablas M2M", "showM2mTables": "Mostrar tablas M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Al eliminar esta pila también se eliminará la opción de selección `{stackToBeDeleted}` de la `{groupingField}`. Los registros pasarán a la pila de no categorizados.", "deleteKanbanStackConfirmation": "Al eliminar esta pila también se eliminará la opción de selección `{stackToBeDeleted}` de la `{groupingField}`. Los registros pasarán a la pila de no categorizados.",
"computedFieldEditWarning": "Campo calculado: el contenido es de sólo lectura. Utilice el menú de edición de columnas para reconfigurar", "computedFieldEditWarning": "Campo calculado: el contenido es de sólo lectura. Utilice el menú de edición de columnas para reconfigurar",
"computedFieldDeleteWarning": "Campo calculado: el contenido es de sólo lectura. No se puede borrar el contenido.", "computedFieldDeleteWarning": "Campo calculado: el contenido es de sólo lectura. No se puede borrar el contenido.",

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

@ -380,7 +380,7 @@
"renameTable": "Table Rename", "renameTable": "Table Rename",
"deleteTable": "Table Delete", "deleteTable": "Table Delete",
"addField": "Add new field to this table", "addField": "Add new field to this table",
"setPrimary": "Set as Primary value", "setDisplay": "Set as Display value",
"addRow": "Add new row", "addRow": "Add new row",
"saveRow": "Save row", "saveRow": "Save row",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "تغییر نام جدول", "renameTable": "تغییر نام جدول",
"deleteTable": "حذف جدول", "deleteTable": "حذف جدول",
"addField": "اضافه کردن فیلد جدید به این جدول", "addField": "اضافه کردن فیلد جدید به این جدول",
"setPrimary": "تنظیم به عنوان مقدار اولیه", "setDisplay": "Set as Display value",
"addRow": "اضافه کردن ردیف جدید", "addRow": "اضافه کردن ردیف جدید",
"saveRow": "دخیره ردیف", "saveRow": "دخیره ردیف",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "Taulukko uudelleen", "renameTable": "Taulukko uudelleen",
"deleteTable": "Taulukko poistaa", "deleteTable": "Taulukko poistaa",
"addField": "Lisää uusi kenttä tähän taulukkoon", "addField": "Lisää uusi kenttä tähän taulukkoon",
"setPrimary": "Aseta ensisijainen arvo", "setDisplay": "Set as Display value",
"addRow": "Lisää uusi rivi", "addRow": "Lisää uusi rivi",
"saveRow": "Tallenna rivi", "saveRow": "Tallenna rivi",
"saveAndExit": "Tallenna & poistu", "saveAndExit": "Tallenna & poistu",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Haluatko varmasti poistaa tämän näkymän?", "deleteViewConfirmation": "Haluatko varmasti poistaa tämän näkymän?",
"deleteTableConfirmation": "Haluatko poistaa taulukon", "deleteTableConfirmation": "Haluatko poistaa taulukon",
"showM2mTables": "Näytä M2M-taulukot", "showM2mTables": "Näytä M2M-taulukot",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Tämän pinon poistaminen poistaa myös valintavaihtoehdon `{stackToBeDeleted}` valikosta `{groupingField}`. Tietueet siirtyvät luokittelemattomaan pinoon.", "deleteKanbanStackConfirmation": "Tämän pinon poistaminen poistaa myös valintavaihtoehdon `{stackToBeDeleted}` valikosta `{groupingField}`. Tietueet siirtyvät luokittelemattomaan pinoon.",
"computedFieldEditWarning": "Laskettu kenttä: sisältö on vain luettavissa. Käytä sarakkeen muokkausvalikkoa uudelleenmäärittämiseen", "computedFieldEditWarning": "Laskettu kenttä: sisältö on vain luettavissa. Käytä sarakkeen muokkausvalikkoa uudelleenmäärittämiseen",
"computedFieldDeleteWarning": "Laskettu kenttä: sisältö on vain luettavissa. Sisältöä ei voi tyhjentää.", "computedFieldDeleteWarning": "Laskettu kenttä: sisältö on vain luettavissa. Sisältöä ei voi tyhjentää.",

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

@ -380,7 +380,7 @@
"renameTable": "Renommer le tableau", "renameTable": "Renommer le tableau",
"deleteTable": "Supprimer le tableau", "deleteTable": "Supprimer le tableau",
"addField": "Ajouter un nouveau champ à ce tableau", "addField": "Ajouter un nouveau champ à ce tableau",
"setPrimary": "Définir comme valeur primaire", "setDisplay": "Set as Display value",
"addRow": "Ajouter une nouvelle ligne", "addRow": "Ajouter une nouvelle ligne",
"saveRow": "Enregistrer la ligne", "saveRow": "Enregistrer la ligne",
"saveAndExit": "Enregistrer et quitter", "saveAndExit": "Enregistrer et quitter",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Êtes-vous sûr de vouloir effacer cette vue ?", "deleteViewConfirmation": "Êtes-vous sûr de vouloir effacer cette vue ?",
"deleteTableConfirmation": "Voulez-vous supprimer ce tableau", "deleteTableConfirmation": "Voulez-vous supprimer ce tableau",
"showM2mTables": "Afficher les tables plusieurs à plusieurs", "showM2mTables": "Afficher les tables plusieurs à plusieurs",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "La suppression de cette pile entraînera également la suppression de l'option de sélection `{stackToBeDeleted}` de la pile `{groupingField}`. Les enregistrements seront déplacés vers la pile non catégorisée.", "deleteKanbanStackConfirmation": "La suppression de cette pile entraînera également la suppression de l'option de sélection `{stackToBeDeleted}` de la pile `{groupingField}`. Les enregistrements seront déplacés vers la pile non catégorisée.",
"computedFieldEditWarning": "Champ calculé : le contenu est en lecture seule. Utilisez le menu d'édition des colonnes pour reconfigurer", "computedFieldEditWarning": "Champ calculé : le contenu est en lecture seule. Utilisez le menu d'édition des colonnes pour reconfigurer",
"computedFieldDeleteWarning": "Champ calculé : le contenu est en lecture seule. Impossible d'effacer le contenu.", "computedFieldDeleteWarning": "Champ calculé : le contenu est en lecture seule. Impossible d'effacer le contenu.",

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

@ -380,7 +380,7 @@
"renameTable": "שולחן שינוי שם", "renameTable": "שולחן שינוי שם",
"deleteTable": "טבלה מחיקה", "deleteTable": "טבלה מחיקה",
"addField": "הוסף שדה חדש לטבלה זו", "addField": "הוסף שדה חדש לטבלה זו",
"setPrimary": "להגדיר כערך ראשי", "setDisplay": "Set as Display value",
"addRow": "הוסף שורה חדשה", "addRow": "הוסף שורה חדשה",
"saveRow": "שמור שורה", "saveRow": "שמור שורה",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "तिम", "renameTable": "तिम",
"deleteTable": "टबल मि", "deleteTable": "टबल मि",
"addField": "इस ति नयड ज", "addField": "इस ति नयड ज",
"setPrimary": "पथमिक मय कप मट कर", "setDisplay": "Set as Display value",
"addRow": "नई पि", "addRow": "नई पि",
"saveRow": "पि सह", "saveRow": "पि सह",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "Preimenovati stolom", "renameTable": "Preimenovati stolom",
"deleteTable": "Obriši tablicu", "deleteTable": "Obriši tablicu",
"addField": "Dodajte novo polje na ovu tablicu", "addField": "Dodajte novo polje na ovu tablicu",
"setPrimary": "Postavite kao primarnu vrijednost", "setDisplay": "Set as Display value",
"addRow": "Dodaj novi red", "addRow": "Dodaj novi red",
"saveRow": "Spremanje retka", "saveRow": "Spremanje retka",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "Ganti nama meja", "renameTable": "Ganti nama meja",
"deleteTable": "Table Delete.", "deleteTable": "Table Delete.",
"addField": "Tambahkan bidang baru ke tabel ini", "addField": "Tambahkan bidang baru ke tabel ini",
"setPrimary": "Tetapkan sebagai nilai utama", "setDisplay": "Set as Display value",
"addRow": "Tambahkan baris baru", "addRow": "Tambahkan baris baru",
"saveRow": "Hemat Baris", "saveRow": "Hemat Baris",
"saveAndExit": "Simpan & Keluar", "saveAndExit": "Simpan & Keluar",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Apakah Anda yakin ingin menghapus tampilan ini?", "deleteViewConfirmation": "Apakah Anda yakin ingin menghapus tampilan ini?",
"deleteTableConfirmation": "Apakah Anda ingin menghapus tabel", "deleteTableConfirmation": "Apakah Anda ingin menghapus tabel",
"showM2mTables": "Tampilkan Tabel M2M", "showM2mTables": "Tampilkan Tabel M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Menghapus tumpukan ini juga akan menghapus opsi pilihan `{stackToBeDeleted}` dari `{groupingField}`. Catatan akan berpindah ke tumpukan yang tidak dikategorikan.", "deleteKanbanStackConfirmation": "Menghapus tumpukan ini juga akan menghapus opsi pilihan `{stackToBeDeleted}` dari `{groupingField}`. Catatan akan berpindah ke tumpukan yang tidak dikategorikan.",
"computedFieldEditWarning": "Bidang yang dihitung: isinya hanya dapat dibaca. Gunakan menu edit kolom untuk mengkonfigurasi ulang", "computedFieldEditWarning": "Bidang yang dihitung: isinya hanya dapat dibaca. Gunakan menu edit kolom untuk mengkonfigurasi ulang",
"computedFieldDeleteWarning": "Bidang yang dihitung: isinya hanya dapat dibaca. Tidak dapat menghapus konten.", "computedFieldDeleteWarning": "Bidang yang dihitung: isinya hanya dapat dibaca. Tidak dapat menghapus konten.",

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

@ -380,7 +380,7 @@
"renameTable": "Rinomina tabella", "renameTable": "Rinomina tabella",
"deleteTable": "Elimina tabella", "deleteTable": "Elimina tabella",
"addField": "Aggiungi un nuovo campo a questa tabella", "addField": "Aggiungi un nuovo campo a questa tabella",
"setPrimary": "Impostare come valore primario", "setDisplay": "Set as Display value",
"addRow": "Aggiungi nuova riga", "addRow": "Aggiungi nuova riga",
"saveRow": "Salva riga", "saveRow": "Salva riga",
"saveAndExit": "Salvare e uscire", "saveAndExit": "Salvare e uscire",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "È sicuro di voler eliminare questa vista?", "deleteViewConfirmation": "È sicuro di voler eliminare questa vista?",
"deleteTableConfirmation": "Vuole eliminare la tabella", "deleteTableConfirmation": "Vuole eliminare la tabella",
"showM2mTables": "Mostra tabelle M2M", "showM2mTables": "Mostra tabelle M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "L'eliminazione di questa pila rimuoverà anche l'opzione di selezione `{stackToBeDeleted}` da `{groupingField}`. I record si sposteranno nella pila non categorizzata.", "deleteKanbanStackConfirmation": "L'eliminazione di questa pila rimuoverà anche l'opzione di selezione `{stackToBeDeleted}` da `{groupingField}`. I record si sposteranno nella pila non categorizzata.",
"computedFieldEditWarning": "Campo calcolato: il contenuto è di sola lettura. Utilizzi il menu di modifica della colonna per riconfigurare", "computedFieldEditWarning": "Campo calcolato: il contenuto è di sola lettura. Utilizzi il menu di modifica della colonna per riconfigurare",
"computedFieldDeleteWarning": "Campo calcolato: il contenuto è di sola lettura. Impossibile cancellare il contenuto.", "computedFieldDeleteWarning": "Campo calcolato: il contenuto è di sola lettura. Impossibile cancellare il contenuto.",

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

@ -380,7 +380,7 @@
"renameTable": "テーブル名の変更", "renameTable": "テーブル名の変更",
"deleteTable": "テーブルを削除", "deleteTable": "テーブルを削除",
"addField": "新しいフィールドを追加", "addField": "新しいフィールドを追加",
"setPrimary": "プライマリ値として設定", "setDisplay": "Set as Display value",
"addRow": "行を追加", "addRow": "行を追加",
"saveRow": "行を保存", "saveRow": "行を保存",
"saveAndExit": "保存して終了", "saveAndExit": "保存して終了",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "このビューを本当に削除しますか?", "deleteViewConfirmation": "このビューを本当に削除しますか?",
"deleteTableConfirmation": "テーブルを削除しますか?", "deleteTableConfirmation": "テーブルを削除しますか?",
"showM2mTables": "M2Mテーブルを表示する", "showM2mTables": "M2Mテーブルを表示する",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "スタックを削除すると、`{stackToBeDeleted}`から選択肢`{groupingField}`も削除されます。レコードは未分類スタックに移動します。", "deleteKanbanStackConfirmation": "スタックを削除すると、`{stackToBeDeleted}`から選択肢`{groupingField}`も削除されます。レコードは未分類スタックに移動します。",
"computedFieldEditWarning": "計算フィールド: コンテンツは読み取り専用です。列編集メニューを使用して再設定してください。", "computedFieldEditWarning": "計算フィールド: コンテンツは読み取り専用です。列編集メニューを使用して再設定してください。",
"computedFieldDeleteWarning": "計算フィールド: コンテンツは読み取り専用です。コンテンツを消去できません。", "computedFieldDeleteWarning": "計算フィールド: コンテンツは読み取り専用です。コンテンツを消去できません。",

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

@ -380,7 +380,7 @@
"renameTable": "테이블 이름 바꾸기", "renameTable": "테이블 이름 바꾸기",
"deleteTable": "테이블 삭제", "deleteTable": "테이블 삭제",
"addField": "테이블에 새 필드 추가", "addField": "테이블에 새 필드 추가",
"setPrimary": "Primary value로 설정", "setDisplay": "Set as Display value",
"addRow": "행 추가", "addRow": "행 추가",
"saveRow": "행 저장", "saveRow": "행 저장",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "Tabulas pārdēvēšana", "renameTable": "Tabulas pārdēvēšana",
"deleteTable": "Tabulas dzēšana", "deleteTable": "Tabulas dzēšana",
"addField": "Jauna lauka pievienošana", "addField": "Jauna lauka pievienošana",
"setPrimary": "Uzstādīt kā primāro atslēgu", "setDisplay": "Set as Display value",
"addRow": "Pievienot ierakstu", "addRow": "Pievienot ierakstu",
"saveRow": "Saglabāt ierakstu", "saveRow": "Saglabāt ierakstu",
"saveAndExit": "Saglabāt un iziet", "saveAndExit": "Saglabāt un iziet",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Vai esat pārliecināts, ka vēlaties dzēst šo skatījumu?", "deleteViewConfirmation": "Vai esat pārliecināts, ka vēlaties dzēst šo skatījumu?",
"deleteTableConfirmation": "Vai vēlaties izdzēst tabulu", "deleteTableConfirmation": "Vai vēlaties izdzēst tabulu",
"showM2mTables": "Rādīt M2M tabulas", "showM2mTables": "Rādīt M2M tabulas",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Dzēšot šo kaudzīti, no `{groupingField}` tiks noņemta arī atlases opcija `{stackToBeDeleted}`. Ieraksti tiks pārvietoti uz neklasificēto kaudzi.", "deleteKanbanStackConfirmation": "Dzēšot šo kaudzīti, no `{groupingField}` tiks noņemta arī atlases opcija `{stackToBeDeleted}`. Ieraksti tiks pārvietoti uz neklasificēto kaudzi.",
"computedFieldEditWarning": "Izrēķināts lauks: saturs ir tikai lasāms. Izmantojiet kolonnas rediģēšanas izvēlni, lai mainītu konfigurāciju", "computedFieldEditWarning": "Izrēķināts lauks: saturs ir tikai lasāms. Izmantojiet kolonnas rediģēšanas izvēlni, lai mainītu konfigurāciju",
"computedFieldDeleteWarning": "Izrēķināts lauks: saturs ir tikai lasāms. Nevar dzēst saturu.", "computedFieldDeleteWarning": "Izrēķināts lauks: saturs ir tikai lasāms. Nevar dzēst saturu.",

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

@ -380,7 +380,7 @@
"renameTable": "Tabel hernoemen", "renameTable": "Tabel hernoemen",
"deleteTable": "Tabel verwijderen", "deleteTable": "Tabel verwijderen",
"addField": "Voeg nieuw veld toe aan deze tabel", "addField": "Voeg nieuw veld toe aan deze tabel",
"setPrimary": "Instellen als primaire waarde", "setDisplay": "Set as Display value",
"addRow": "Nieuwe rij toevoegen", "addRow": "Nieuwe rij toevoegen",
"saveRow": "Sla rij op", "saveRow": "Sla rij op",
"saveAndExit": "Opslaan en afsluiten", "saveAndExit": "Opslaan en afsluiten",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Weet u zeker dat u deze weergave wilt verwijderen?", "deleteViewConfirmation": "Weet u zeker dat u deze weergave wilt verwijderen?",
"deleteTableConfirmation": "Wilt u de tabel verwijderen", "deleteTableConfirmation": "Wilt u de tabel verwijderen",
"showM2mTables": "Toon M2M-tabellen", "showM2mTables": "Toon M2M-tabellen",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Door deze stapel te verwijderen wordt ook de selectieoptie `{stackToBeDeleted}` van de `{groupingField}` verwijderd. De records worden verplaatst naar de ongecategoriseerde stapel.", "deleteKanbanStackConfirmation": "Door deze stapel te verwijderen wordt ook de selectieoptie `{stackToBeDeleted}` van de `{groupingField}` verwijderd. De records worden verplaatst naar de ongecategoriseerde stapel.",
"computedFieldEditWarning": "Berekend veld: de inhoud is alleen leesbaar. Gebruik het kolombewerkingsmenu om opnieuw te configureren", "computedFieldEditWarning": "Berekend veld: de inhoud is alleen leesbaar. Gebruik het kolombewerkingsmenu om opnieuw te configureren",
"computedFieldDeleteWarning": "Berekend veld: inhoud is alleen-lezen. Kan inhoud niet wissen.", "computedFieldDeleteWarning": "Berekend veld: inhoud is alleen-lezen. Kan inhoud niet wissen.",

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

@ -380,7 +380,7 @@
"renameTable": "Tabell omdøpe", "renameTable": "Tabell omdøpe",
"deleteTable": "Bordet slett", "deleteTable": "Bordet slett",
"addField": "Legg til nytt felt i denne tabellen", "addField": "Legg til nytt felt i denne tabellen",
"setPrimary": "Sett som primærverdi", "setDisplay": "Set as Display value",
"addRow": "Legg til ny rad", "addRow": "Legg til ny rad",
"saveRow": "Lagre rad", "saveRow": "Lagre rad",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "Zmień nazwę tabeli.", "renameTable": "Zmień nazwę tabeli.",
"deleteTable": "Usuń tabelę", "deleteTable": "Usuń tabelę",
"addField": "Dodaj nowe pole do tej tabeli", "addField": "Dodaj nowe pole do tej tabeli",
"setPrimary": "Ustaw jako wartość podstawowa", "setDisplay": "Set as Display value",
"addRow": "Dodaj nowy rząd", "addRow": "Dodaj nowy rząd",
"saveRow": "Zapisz wiersz", "saveRow": "Zapisz wiersz",
"saveAndExit": "Zapisz i wyjdź", "saveAndExit": "Zapisz i wyjdź",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Czy na pewno chcesz usunąć ten widok?", "deleteViewConfirmation": "Czy na pewno chcesz usunąć ten widok?",
"deleteTableConfirmation": "Czy chcesz usunąć tabelę", "deleteTableConfirmation": "Czy chcesz usunąć tabelę",
"showM2mTables": "Pokaż tabele M2M", "showM2mTables": "Pokaż tabele M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Usunięcie tego stosu spowoduje również usunięcie wybranej opcji `{stackToBeDeleted}` z `{groupingField}`. Rekordy przeniosą się do nieskategoryzowanego stosu.", "deleteKanbanStackConfirmation": "Usunięcie tego stosu spowoduje również usunięcie wybranej opcji `{stackToBeDeleted}` z `{groupingField}`. Rekordy przeniosą się do nieskategoryzowanego stosu.",
"computedFieldEditWarning": "Pole obliczeniowe: zawartość jest tylko do odczytu. Do rekonfiguracji należy użyć menu edycji kolumny", "computedFieldEditWarning": "Pole obliczeniowe: zawartość jest tylko do odczytu. Do rekonfiguracji należy użyć menu edycji kolumny",
"computedFieldDeleteWarning": "Pole obliczeniowe: zawartość jest tylko do odczytu. Nie można wyczyścić zawartości.", "computedFieldDeleteWarning": "Pole obliczeniowe: zawartość jest tylko do odczytu. Nie można wyczyścić zawartości.",

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

@ -380,7 +380,7 @@
"renameTable": "Tabela Renomear", "renameTable": "Tabela Renomear",
"deleteTable": "Tabela Delete.", "deleteTable": "Tabela Delete.",
"addField": "Adicionar novo campo a esta tabela", "addField": "Adicionar novo campo a esta tabela",
"setPrimary": "Definido como valor primário", "setDisplay": "Set as Display value",
"addRow": "Adicionar nova linha", "addRow": "Adicionar nova linha",
"saveRow": "Salvar linha", "saveRow": "Salvar linha",
"saveAndExit": "Salvar & Sair", "saveAndExit": "Salvar & Sair",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Tem a certeza de que quer apagar esta vista?", "deleteViewConfirmation": "Tem a certeza de que quer apagar esta vista?",
"deleteTableConfirmation": "Deseja apagar a tabela", "deleteTableConfirmation": "Deseja apagar a tabela",
"showM2mTables": "Mostrar Mesas M2M", "showM2mTables": "Mostrar Mesas M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "A eliminação desta pilha irá também remover a opção seleccionada `{stackToBeDeleted}` do `{groupingField}`. Os registos serão movidos para a pilha não categorizada.", "deleteKanbanStackConfirmation": "A eliminação desta pilha irá também remover a opção seleccionada `{stackToBeDeleted}` do `{groupingField}`. Os registos serão movidos para a pilha não categorizada.",
"computedFieldEditWarning": "Campo computorizado: o conteúdo é apenas de leitura. Utilizar o menu de edição de colunas para reconfigurar", "computedFieldEditWarning": "Campo computorizado: o conteúdo é apenas de leitura. Utilizar o menu de edição de colunas para reconfigurar",
"computedFieldDeleteWarning": "Campo computorizado: o conteúdo é apenas de leitura. Incapaz de limpar o conteúdo.", "computedFieldDeleteWarning": "Campo computorizado: o conteúdo é apenas de leitura. Incapaz de limpar o conteúdo.",

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

@ -380,7 +380,7 @@
"renameTable": "Tabela Renomear", "renameTable": "Tabela Renomear",
"deleteTable": "Tabela Delete.", "deleteTable": "Tabela Delete.",
"addField": "Adicionar novo campo a esta tabela", "addField": "Adicionar novo campo a esta tabela",
"setPrimary": "Definido como valor primário", "setDisplay": "Set as Display value",
"addRow": "Adicionar nova linha", "addRow": "Adicionar nova linha",
"saveRow": "Salvar linha", "saveRow": "Salvar linha",
"saveAndExit": "Salvar & Sair", "saveAndExit": "Salvar & Sair",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Tem a certeza de que quer apagar esta vista?", "deleteViewConfirmation": "Tem a certeza de que quer apagar esta vista?",
"deleteTableConfirmation": "Deseja apagar a tabela", "deleteTableConfirmation": "Deseja apagar a tabela",
"showM2mTables": "Mostrar Mesas M2M", "showM2mTables": "Mostrar Mesas M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "A eliminação desta pilha irá também remover a opção seleccionada `{stackToBeDeleted}` do `{groupingField}`. Os registos serão movidos para a pilha não categorizada.", "deleteKanbanStackConfirmation": "A eliminação desta pilha irá também remover a opção seleccionada `{stackToBeDeleted}` do `{groupingField}`. Os registos serão movidos para a pilha não categorizada.",
"computedFieldEditWarning": "Campo computorizado: o conteúdo é apenas de leitura. Utilizar o menu de edição de colunas para reconfigurar", "computedFieldEditWarning": "Campo computorizado: o conteúdo é apenas de leitura. Utilizar o menu de edição de colunas para reconfigurar",
"computedFieldDeleteWarning": "Campo computorizado: o conteúdo é apenas de leitura. Incapaz de limpar o conteúdo.", "computedFieldDeleteWarning": "Campo computorizado: o conteúdo é apenas de leitura. Incapaz de limpar o conteúdo.",

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

@ -380,7 +380,7 @@
"renameTable": "Переименовать таблицу", "renameTable": "Переименовать таблицу",
"deleteTable": "Удалить таблицу", "deleteTable": "Удалить таблицу",
"addField": "Добавить новое поле в эту таблицу", "addField": "Добавить новое поле в эту таблицу",
"setPrimary": "Установить в качестве основного значения", "setDisplay": "Set as Display value",
"addRow": "Добавить новую строку", "addRow": "Добавить новую строку",
"saveRow": "Сохранить строку", "saveRow": "Сохранить строку",
"saveAndExit": "Сохранить и выйти", "saveAndExit": "Сохранить и выйти",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Вы действительно хотите удалить это представление?", "deleteViewConfirmation": "Вы действительно хотите удалить это представление?",
"deleteTableConfirmation": "Вы действительно хотите удалить эту таблицу", "deleteTableConfirmation": "Вы действительно хотите удалить эту таблицу",
"showM2mTables": "Показать таблицы M2M", "showM2mTables": "Показать таблицы M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Удаление этого стека также удалит опцию выбора `{stackToBeDeleted}` из `{groupingField}`. Записи переместятся в стек без категории.", "deleteKanbanStackConfirmation": "Удаление этого стека также удалит опцию выбора `{stackToBeDeleted}` из `{groupingField}`. Записи переместятся в стек без категории.",
"computedFieldEditWarning": "Вычисляемое поле: содержимое доступно только для чтения. Используйте меню редактирования столбцов для изменения конфигурации", "computedFieldEditWarning": "Вычисляемое поле: содержимое доступно только для чтения. Используйте меню редактирования столбцов для изменения конфигурации",
"computedFieldDeleteWarning": "Вычисляемое поле: содержимое доступно только для чтения. Невозможно очистить содержимое.", "computedFieldDeleteWarning": "Вычисляемое поле: содержимое доступно только для чтения. Невозможно очистить содержимое.",

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

@ -380,7 +380,7 @@
"renameTable": "Premenovanie tabuľky", "renameTable": "Premenovanie tabuľky",
"deleteTable": "Tabuľka Vymazať", "deleteTable": "Tabuľka Vymazať",
"addField": "Pridanie nového poľa do tejto tabuľky", "addField": "Pridanie nového poľa do tejto tabuľky",
"setPrimary": "Nastaviť ako primárnu hodnotu", "setDisplay": "Set as Display value",
"addRow": "Pridanie nového riadku", "addRow": "Pridanie nového riadku",
"saveRow": "Uložiť riadok", "saveRow": "Uložiť riadok",
"saveAndExit": "Uložiť a ukončiť", "saveAndExit": "Uložiť a ukončiť",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Ste si istí, že chcete toto zobrazenie odstrániť?", "deleteViewConfirmation": "Ste si istí, že chcete toto zobrazenie odstrániť?",
"deleteTableConfirmation": "Chcete odstrániť tabuľku", "deleteTableConfirmation": "Chcete odstrániť tabuľku",
"showM2mTables": "Zobraziť tabuľky M2M", "showM2mTables": "Zobraziť tabuľky M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Odstránením tohto zásobníka sa odstráni aj možnosť výberu `{stackToBeDeleted}` z `{groupingField}`. Záznamy sa presunú do zásobníka bez kategórií.", "deleteKanbanStackConfirmation": "Odstránením tohto zásobníka sa odstráni aj možnosť výberu `{stackToBeDeleted}` z `{groupingField}`. Záznamy sa presunú do zásobníka bez kategórií.",
"computedFieldEditWarning": "Vypočítané pole: obsah je len na čítanie. Na zmenu konfigurácie použite ponuku úprav stĺpcov", "computedFieldEditWarning": "Vypočítané pole: obsah je len na čítanie. Na zmenu konfigurácie použite ponuku úprav stĺpcov",
"computedFieldDeleteWarning": "Vypočítané pole: obsah je len na čítanie. Nie je možné vymazať obsah.", "computedFieldDeleteWarning": "Vypočítané pole: obsah je len na čítanie. Nie je možné vymazať obsah.",

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

@ -380,7 +380,7 @@
"renameTable": "Preimenuj tabele", "renameTable": "Preimenuj tabele",
"deleteTable": "Tabela Delete.", "deleteTable": "Tabela Delete.",
"addField": "V to tabelo dodajte novo polje", "addField": "V to tabelo dodajte novo polje",
"setPrimary": "Kot primarna vrednost", "setDisplay": "Set as Display value",
"addRow": "Dodaj novo vrstico", "addRow": "Dodaj novo vrstico",
"saveRow": "Shrani vrstico", "saveRow": "Shrani vrstico",
"saveAndExit": "Shranjevanje in izhod", "saveAndExit": "Shranjevanje in izhod",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Ste prepričani, da želite izbrisati ta pogled?", "deleteViewConfirmation": "Ste prepričani, da želite izbrisati ta pogled?",
"deleteTableConfirmation": "Ali želite izbrisati tabelo", "deleteTableConfirmation": "Ali želite izbrisati tabelo",
"showM2mTables": "Prikaži tabele M2M", "showM2mTables": "Prikaži tabele M2M",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Z brisanjem tega sklada se odstrani tudi možnost izbire `{stackToBeDeleted}` iz `{groupingField}`. Zapisi se bodo premaknili v kup nekategoriziranih zapisov.", "deleteKanbanStackConfirmation": "Z brisanjem tega sklada se odstrani tudi možnost izbire `{stackToBeDeleted}` iz `{groupingField}`. Zapisi se bodo premaknili v kup nekategoriziranih zapisov.",
"computedFieldEditWarning": "Izračunano polje: vsebina je namenjena samo branju. Uporabite meni za urejanje stolpcev, da ponovno konfigurirate", "computedFieldEditWarning": "Izračunano polje: vsebina je namenjena samo branju. Uporabite meni za urejanje stolpcev, da ponovno konfigurirate",
"computedFieldDeleteWarning": "Izračunano polje: vsebina je namenjena samo branju. Vsebine ni mogoče izbrisati.", "computedFieldDeleteWarning": "Izračunano polje: vsebina je namenjena samo branju. Vsebine ni mogoče izbrisati.",

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

@ -380,7 +380,7 @@
"renameTable": "Bordsbyte", "renameTable": "Bordsbyte",
"deleteTable": "Bord radera", "deleteTable": "Bord radera",
"addField": "Lägg till nytt fält till den här tabellen", "addField": "Lägg till nytt fält till den här tabellen",
"setPrimary": "Ange som primärt värde", "setDisplay": "Set as Display value",
"addRow": "Lägg till ny rad", "addRow": "Lägg till ny rad",
"saveRow": "Spara rad", "saveRow": "Spara rad",
"saveAndExit": "Spara och avsluta", "saveAndExit": "Spara och avsluta",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Är du säker på att du vill ta bort den här vyn?", "deleteViewConfirmation": "Är du säker på att du vill ta bort den här vyn?",
"deleteTableConfirmation": "Vill du radera tabellen?", "deleteTableConfirmation": "Vill du radera tabellen?",
"showM2mTables": "Visa M2M-tabeller", "showM2mTables": "Visa M2M-tabeller",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Om du raderar denna stapel kommer även alternativet \"{stackToBeDeleted}\" att tas bort från \"{groupingField}\". Posterna kommer att flyttas till stapeln \"uncategorized\".", "deleteKanbanStackConfirmation": "Om du raderar denna stapel kommer även alternativet \"{stackToBeDeleted}\" att tas bort från \"{groupingField}\". Posterna kommer att flyttas till stapeln \"uncategorized\".",
"computedFieldEditWarning": "Beräknat fält: innehållet är skrivskyddat. Använd kolumnredigeringsmenyn för att konfigurera om.", "computedFieldEditWarning": "Beräknat fält: innehållet är skrivskyddat. Använd kolumnredigeringsmenyn för att konfigurera om.",
"computedFieldDeleteWarning": "Beräknat fält: innehållet är skrivskyddat. Det går inte att rensa innehållet.", "computedFieldDeleteWarning": "Beräknat fält: innehållet är skrivskyddat. Det går inte att rensa innehållet.",

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

@ -380,7 +380,7 @@
"renameTable": "ตารางเปลยนชอ", "renameTable": "ตารางเปลยนชอ",
"deleteTable": "ลบตาราง", "deleteTable": "ลบตาราง",
"addField": "เพมฟลดใหมลงในตารางน", "addField": "เพมฟลดใหมลงในตารางน",
"setPrimary": "ตงคาเปนคาปฐมภ", "setDisplay": "Set as Display value",
"addRow": "เพมแถวใหม", "addRow": "เพมแถวใหม",
"saveRow": "บนทกแถว", "saveRow": "บนทกแถว",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

7
packages/nc-gui/lang/tr.json

@ -380,7 +380,7 @@
"renameTable": "Tabloyu Yeniden Adlandır", "renameTable": "Tabloyu Yeniden Adlandır",
"deleteTable": "Tabloyu Sil", "deleteTable": "Tabloyu Sil",
"addField": "Tabloya yeni alan ekle", "addField": "Tabloya yeni alan ekle",
"setPrimary": "Birincil değer yap", "setDisplay": "Set as Display value",
"addRow": "Yeni satır ekle", "addRow": "Yeni satır ekle",
"saveRow": "Satırı kaydet", "saveRow": "Satırı kaydet",
"saveAndExit": "Kaydet ve Çık", "saveAndExit": "Kaydet ve Çık",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Bu görünümü silmek istediğinizden emin misiniz?", "deleteViewConfirmation": "Bu görünümü silmek istediğinizden emin misiniz?",
"deleteTableConfirmation": "Tabloyu silmek istiyor musunuz", "deleteTableConfirmation": "Tabloyu silmek istiyor musunuz",
"showM2mTables": "M2M Tablolarını Göster", "showM2mTables": "M2M Tablolarını Göster",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Bu yığının silinmesi `{stackToBeDeleted}` seçim seçeneğini `{groupingField}` adresinden de kaldıracaktır. Kayıtlar kategorize edilmemiş yığına taşınacaktır.", "deleteKanbanStackConfirmation": "Bu yığının silinmesi `{stackToBeDeleted}` seçim seçeneğini `{groupingField}` adresinden de kaldıracaktır. Kayıtlar kategorize edilmemiş yığına taşınacaktır.",
"computedFieldEditWarning": "Hesaplanan alan: içerik salt okunurdur. Yeniden yapılandırmak için sütun düzenleme menüsünü kullanın", "computedFieldEditWarning": "Hesaplanan alan: içerik salt okunurdur. Yeniden yapılandırmak için sütun düzenleme menüsünü kullanın",
"computedFieldDeleteWarning": "Hesaplanan alan: içerik salt okunurdur. İçerik temizlenemiyor.", "computedFieldDeleteWarning": "Hesaplanan alan: içerik salt okunurdur. İçerik temizlenemiyor.",

7
packages/nc-gui/lang/uk.json

@ -380,7 +380,7 @@
"renameTable": "Перейменувати таблицю", "renameTable": "Перейменувати таблицю",
"deleteTable": "Видалити таблицю", "deleteTable": "Видалити таблицю",
"addField": "Додати нове поле до цієї таблиці", "addField": "Додати нове поле до цієї таблиці",
"setPrimary": "Встановити як основне значення", "setDisplay": "Set as Display value",
"addRow": "Додати новий рядок", "addRow": "Додати новий рядок",
"saveRow": "Зберегти рядок", "saveRow": "Зберегти рядок",
"saveAndExit": "Зберегти та вийти", "saveAndExit": "Зберегти та вийти",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Ви впевнені, що хочете видалити цей вигляд?", "deleteViewConfirmation": "Ви впевнені, що хочете видалити цей вигляд?",
"deleteTableConfirmation": "Ви хочете видалити таблицю", "deleteTableConfirmation": "Ви хочете видалити таблицю",
"showM2mTables": "Показати M2M таблиці", "showM2mTables": "Показати M2M таблиці",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Видалення цього стека також вилучить опцію вибору `{stackToBeDeleted}` зі стека `{groupingField}`. Записи буде переміщено до не категоризованого стека.", "deleteKanbanStackConfirmation": "Видалення цього стека також вилучить опцію вибору `{stackToBeDeleted}` зі стека `{groupingField}`. Записи буде переміщено до не категоризованого стека.",
"computedFieldEditWarning": "Обчислюване поле: вміст доступний лише для читання. Використовуйте меню редагування стовпця для зміни конфігурації", "computedFieldEditWarning": "Обчислюване поле: вміст доступний лише для читання. Використовуйте меню редагування стовпця для зміни конфігурації",
"computedFieldDeleteWarning": "Обчислюване поле: вміст доступний лише для читання. Не вдалося очистити вміст.", "computedFieldDeleteWarning": "Обчислюване поле: вміст доступний лише для читання. Не вдалося очистити вміст.",

7
packages/nc-gui/lang/vi.json

@ -380,7 +380,7 @@
"renameTable": "Đổi tên bảng.", "renameTable": "Đổi tên bảng.",
"deleteTable": "Bảng xóa", "deleteTable": "Bảng xóa",
"addField": "Thêm trường mới vào bảng này", "addField": "Thêm trường mới vào bảng này",
"setPrimary": "Đặt dưới dạng giá trị chính", "setDisplay": "Set as Display value",
"addRow": "Thêm hàng mới", "addRow": "Thêm hàng mới",
"saveRow": "Lưu hàng.", "saveRow": "Lưu hàng.",
"saveAndExit": "Save & Exit", "saveAndExit": "Save & Exit",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?", "deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table", "deleteTableConfirmation": "Do you want to delete the table",
"showM2mTables": "Show M2M Tables", "showM2mTables": "Show M2M Tables",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,7 +380,7 @@
"renameTable": "重命名表格", "renameTable": "重命名表格",
"deleteTable": "删除表格", "deleteTable": "删除表格",
"addField": "添加新字段", "addField": "添加新字段",
"setPrimary": "设置为主要值", "setDisplay": "Set as Display value",
"addRow": "添加新行", "addRow": "添加新行",
"saveRow": "保存行", "saveRow": "保存行",
"saveAndExit": "保存并退出", "saveAndExit": "保存并退出",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "您确定要删除此视图?", "deleteViewConfirmation": "您确定要删除此视图?",
"deleteTableConfirmation": "您想要删除该表吗?", "deleteTableConfirmation": "您想要删除该表吗?",
"showM2mTables": "显示中间表", "showM2mTables": "显示中间表",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "删除这个类别标签也将从 \"{groupingField}\"中删除选择选项 \"{stackToBeDeleted}\"。这类记录将移到未分类的类别中。", "deleteKanbanStackConfirmation": "删除这个类别标签也将从 \"{groupingField}\"中删除选择选项 \"{stackToBeDeleted}\"。这类记录将移到未分类的类别中。",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

7
packages/nc-gui/lang/zh-Hant.json

@ -380,7 +380,7 @@
"renameTable": "表重命名", "renameTable": "表重命名",
"deleteTable": "表刪除", "deleteTable": "表刪除",
"addField": "將新字段添加到此表", "addField": "將新字段添加到此表",
"setPrimary": "設置為主要值", "setDisplay": "Set as Display value",
"addRow": "新增行", "addRow": "新增行",
"saveRow": "儲存行", "saveRow": "儲存行",
"saveAndExit": "儲存並結束", "saveAndExit": "儲存並結束",
@ -631,6 +631,11 @@
"deleteViewConfirmation": "是否確定要刪除此檢視?", "deleteViewConfirmation": "是否確定要刪除此檢視?",
"deleteTableConfirmation": "你想刪除此資料表", "deleteTableConfirmation": "你想刪除此資料表",
"showM2mTables": "顯示多對多資料表", "showM2mTables": "顯示多對多資料表",
"showM2mTablesDesc": "Many-to-many relation is supported via a junction table & is hidden by default. Enable this option to list all such tables along with existing tables.",
"showNullInCells": "Show NULL in Cells",
"showNullInCellsDesc": "Display 'NULL' tag in cells holding NULL value. This helps differentiate against cells holding EMPTY string.",
"showNullAndEmptyInFilter": "Show NULL and EMPTY in Filter",
"showNullAndEmptyInFilterDesc": "Enable 'additional' filters to differentiate fields containing NULL & Empty Strings. Default support for Blank treats both NULL & Empty strings alike.",
"deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.", "deleteKanbanStackConfirmation": "Deleting this stack will also remove the select option `{stackToBeDeleted}` from the `{groupingField}`. The records will move to the uncategorized stack.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure", "computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.", "computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -56,6 +56,7 @@
"@iconify-json/clarity": "^1.1.4", "@iconify-json/clarity": "^1.1.4",
"@iconify-json/eva": "^1.1.2", "@iconify-json/eva": "^1.1.2",
"@iconify-json/ic": "^1.1.7", "@iconify-json/ic": "^1.1.7",
"@iconify-json/la": "^1.1.2",
"@iconify-json/logos": "^1.1.14", "@iconify-json/logos": "^1.1.14",
"@iconify-json/lucide": "^1.1.36", "@iconify-json/lucide": "^1.1.36",
"@iconify-json/material-symbols": "^1.1.8", "@iconify-json/material-symbols": "^1.1.8",
@ -100,7 +101,7 @@
} }
}, },
"../nocodb-sdk": { "../nocodb-sdk": {
"version": "0.104.3", "version": "0.105.2",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
@ -1123,6 +1124,15 @@
"@iconify/types": "*" "@iconify/types": "*"
} }
}, },
"node_modules/@iconify-json/la": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@iconify-json/la/-/la-1.1.2.tgz",
"integrity": "sha512-Cv93a5X5n9gYeUeQ7h9z5tmoZzChvwvbCorBQwMQgwCnMQynH6dCKdtbtYsZyT5wH4QYwywv7xgvpBIkqvZgqg==",
"dev": true,
"dependencies": {
"@iconify/types": "*"
}
},
"node_modules/@iconify-json/logos": { "node_modules/@iconify-json/logos": {
"version": "1.1.18", "version": "1.1.18",
"resolved": "https://registry.npmjs.org/@iconify-json/logos/-/logos-1.1.18.tgz", "resolved": "https://registry.npmjs.org/@iconify-json/logos/-/logos-1.1.18.tgz",
@ -16077,9 +16087,9 @@
} }
}, },
"node_modules/undici": { "node_modules/undici": {
"version": "5.12.0", "version": "5.19.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.12.0.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-5.19.1.tgz",
"integrity": "sha512-zMLamCG62PGjd9HHMpo05bSLvvwWOZgGeiWlN/vlqu3+lRo3elxktVGEyLMX+IO7c2eflLjcW74AlkhEZm15mg==", "integrity": "sha512-YiZ61LPIgY73E7syxCDxxa3LV2yl3sN8spnIuTct60boiiRaE1J8mNWHO8Im2Zi/sFrPusjLlmRPrsyraSqX6A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"busboy": "^1.6.0" "busboy": "^1.6.0"
@ -18926,6 +18936,15 @@
"@iconify/types": "*" "@iconify/types": "*"
} }
}, },
"@iconify-json/la": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@iconify-json/la/-/la-1.1.2.tgz",
"integrity": "sha512-Cv93a5X5n9gYeUeQ7h9z5tmoZzChvwvbCorBQwMQgwCnMQynH6dCKdtbtYsZyT5wH4QYwywv7xgvpBIkqvZgqg==",
"dev": true,
"requires": {
"@iconify/types": "*"
}
},
"@iconify-json/logos": { "@iconify-json/logos": {
"version": "1.1.18", "version": "1.1.18",
"resolved": "https://registry.npmjs.org/@iconify-json/logos/-/logos-1.1.18.tgz", "resolved": "https://registry.npmjs.org/@iconify-json/logos/-/logos-1.1.18.tgz",
@ -29897,9 +29916,9 @@
} }
}, },
"undici": { "undici": {
"version": "5.12.0", "version": "5.19.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-5.12.0.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-5.19.1.tgz",
"integrity": "sha512-zMLamCG62PGjd9HHMpo05bSLvvwWOZgGeiWlN/vlqu3+lRo3elxktVGEyLMX+IO7c2eflLjcW74AlkhEZm15mg==", "integrity": "sha512-YiZ61LPIgY73E7syxCDxxa3LV2yl3sN8spnIuTct60boiiRaE1J8mNWHO8Im2Zi/sFrPusjLlmRPrsyraSqX6A==",
"dev": true, "dev": true,
"requires": { "requires": {
"busboy": "^1.6.0" "busboy": "^1.6.0"

1
packages/nc-gui/package.json

@ -79,6 +79,7 @@
"@iconify-json/clarity": "^1.1.4", "@iconify-json/clarity": "^1.1.4",
"@iconify-json/eva": "^1.1.2", "@iconify-json/eva": "^1.1.2",
"@iconify-json/ic": "^1.1.7", "@iconify-json/ic": "^1.1.7",
"@iconify-json/la": "^1.1.2",
"@iconify-json/logos": "^1.1.14", "@iconify-json/logos": "^1.1.14",
"@iconify-json/lucide": "^1.1.36", "@iconify-json/lucide": "^1.1.36",
"@iconify-json/material-symbols": "^1.1.8", "@iconify-json/material-symbols": "^1.1.8",

116
packages/nc-gui/utils/filterUtils.ts

@ -1,12 +1,46 @@
import { UITypes } from 'nocodb-sdk' import { UITypes, isNumericCol, numericUITypes } from 'nocodb-sdk'
export const comparisonOpList: { const getEqText = (fieldUiType: UITypes) => {
if (isNumericCol(fieldUiType)) {
return '='
} else if ([UITypes.SingleSelect, UITypes.Collaborator, UITypes.LinkToAnotherRecord].includes(fieldUiType)) {
return 'is'
}
return 'is equal'
}
const getNeqText = (fieldUiType: UITypes) => {
if (isNumericCol(fieldUiType)) {
return '!='
} else if ([UITypes.SingleSelect, UITypes.Collaborator, UITypes.LinkToAnotherRecord].includes(fieldUiType)) {
return 'is not'
}
return 'is not equal'
}
const getLikeText = (fieldUiType: UITypes) => {
if (fieldUiType === UITypes.Attachment) {
return 'filenames contain'
}
return 'is like'
}
const getNotLikeText = (fieldUiType: UITypes) => {
if (fieldUiType === UITypes.Attachment) {
return "filenames doesn't contain"
}
return 'is not like'
}
export const comparisonOpList = (
fieldUiType: UITypes,
): {
text: string text: string
value: string value: string
ignoreVal?: boolean ignoreVal?: boolean
includedTypes?: UITypes[] includedTypes?: UITypes[]
excludedTypes?: UITypes[] excludedTypes?: UITypes[]
}[] = [ }[] => [
{ {
text: 'is checked', text: 'is checked',
value: 'checked', value: 'checked',
@ -20,44 +54,84 @@ export const comparisonOpList: {
includedTypes: [UITypes.Checkbox], includedTypes: [UITypes.Checkbox],
}, },
{ {
text: 'is equal', text: getEqText(fieldUiType),
value: 'eq', value: 'eq',
excludedTypes: [UITypes.Checkbox, UITypes.MultiSelect, UITypes.Attachment],
}, },
{ {
text: 'is not equal', text: getNeqText(fieldUiType),
value: 'neq', value: 'neq',
excludedTypes: [UITypes.Checkbox, UITypes.MultiSelect, UITypes.Attachment],
}, },
{ {
text: 'is like', text: getLikeText(fieldUiType),
value: 'like', value: 'like',
excludedTypes: [UITypes.Checkbox], excludedTypes: [UITypes.Checkbox, UITypes.SingleSelect, UITypes.MultiSelect, UITypes.Collaborator, ...numericUITypes],
}, },
{ {
text: 'is not like', text: getNotLikeText(fieldUiType),
value: 'nlike', value: 'nlike',
excludedTypes: [UITypes.Checkbox], excludedTypes: [UITypes.Checkbox, UITypes.SingleSelect, UITypes.MultiSelect, UITypes.Collaborator, ...numericUITypes],
}, },
{ {
text: 'is empty', text: 'is empty',
value: 'empty', value: 'empty',
ignoreVal: true, ignoreVal: true,
excludedTypes: [UITypes.Checkbox, UITypes.Rating, UITypes.Number, UITypes.Decimal, UITypes.Percent, UITypes.Currency], excludedTypes: [
UITypes.Checkbox,
UITypes.SingleSelect,
UITypes.MultiSelect,
UITypes.Collaborator,
UITypes.Attachment,
UITypes.LinkToAnotherRecord,
UITypes.Lookup,
...numericUITypes,
],
}, },
{ {
text: 'is not empty', text: 'is not empty',
value: 'notempty', value: 'notempty',
ignoreVal: true, ignoreVal: true,
excludedTypes: [UITypes.Checkbox, UITypes.Rating, UITypes.Number, UITypes.Decimal, UITypes.Percent, UITypes.Currency], excludedTypes: [
UITypes.Checkbox,
UITypes.SingleSelect,
UITypes.MultiSelect,
UITypes.Collaborator,
UITypes.Attachment,
UITypes.LinkToAnotherRecord,
UITypes.Lookup,
...numericUITypes,
],
}, },
{ {
text: 'is null', text: 'is null',
value: 'null', value: 'null',
ignoreVal: true, ignoreVal: true,
excludedTypes: [
...numericUITypes,
UITypes.Checkbox,
UITypes.SingleSelect,
UITypes.MultiSelect,
UITypes.Collaborator,
UITypes.Attachment,
UITypes.LinkToAnotherRecord,
UITypes.Lookup,
],
}, },
{ {
text: 'is not null', text: 'is not null',
value: 'notnull', value: 'notnull',
ignoreVal: true, ignoreVal: true,
excludedTypes: [
...numericUITypes,
UITypes.Checkbox,
UITypes.SingleSelect,
UITypes.MultiSelect,
UITypes.Collaborator,
UITypes.Attachment,
UITypes.LinkToAnotherRecord,
UITypes.Lookup,
],
}, },
{ {
text: 'contains all of', text: 'contains all of',
@ -82,21 +156,33 @@ export const comparisonOpList: {
{ {
text: '>', text: '>',
value: 'gt', value: 'gt',
excludedTypes: [UITypes.Checkbox, UITypes.MultiSelect, UITypes.SingleSelect], includedTypes: [...numericUITypes],
}, },
{ {
text: '<', text: '<',
value: 'lt', value: 'lt',
excludedTypes: [UITypes.Checkbox, UITypes.MultiSelect, UITypes.SingleSelect], includedTypes: [...numericUITypes],
}, },
{ {
text: '>=', text: '>=',
value: 'gte', value: 'gte',
excludedTypes: [UITypes.Checkbox, UITypes.MultiSelect, UITypes.SingleSelect], includedTypes: [...numericUITypes],
}, },
{ {
text: '<=', text: '<=',
value: 'lte', value: 'lte',
excludedTypes: [UITypes.Checkbox, UITypes.MultiSelect, UITypes.SingleSelect], includedTypes: [...numericUITypes],
},
{
text: 'is blank',
value: 'blank',
ignoreVal: true,
excludedTypes: [UITypes.Checkbox],
},
{
text: 'is not blank',
value: 'notblank',
ignoreVal: true,
excludedTypes: [UITypes.Checkbox],
}, },
] ]

26
packages/nc-gui/utils/validation.ts

@ -80,6 +80,32 @@ export const fieldRequiredValidator = () => {
} }
} }
export const fieldLengthValidator = (sqlClientType: string) => {
return {
validator: (rule: any, value: any) => {
const { t } = getI18n().global
// no limit for sqlite but set as 255
let fieldLengthLimit = 255
if (sqlClientType === 'mysql2' || sqlClientType === 'mysql') {
fieldLengthLimit = 64
} else if (sqlClientType === 'pg') {
fieldLengthLimit = 59
} else if (sqlClientType === 'mssql') {
fieldLengthLimit = 128
}
return new Promise((resolve, reject) => {
if (value?.length > fieldLengthLimit) {
reject(new Error(t('msg.error.columnNameExceedsCharacters', { value: fieldLengthLimit })))
}
resolve(true)
})
},
}
}
export const importUrlValidator = { export const importUrlValidator = {
validator: (rule: any, value: any) => { validator: (rule: any, value: any) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

2
packages/nc-lib-gui/package.json

@ -1,6 +1,6 @@
{ {
"name": "nc-lib-gui", "name": "nc-lib-gui",
"version": "0.104.3", "version": "0.105.2",
"description": "NocoDB GUI", "description": "NocoDB GUI",
"author": { "author": {
"name": "NocoDB", "name": "NocoDB",

3401
packages/nc-plugin/package-lock.json generated

File diff suppressed because it is too large Load Diff

2
packages/nc-plugin/package.json

@ -60,7 +60,7 @@
"@istanbuljs/nyc-config-typescript": "^1.0.1", "@istanbuljs/nyc-config-typescript": "^1.0.1",
"@typescript-eslint/eslint-plugin": "^4.0.1", "@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1", "@typescript-eslint/parser": "^4.0.1",
"ava": "^3.12.1", "ava": "^5.2.0",
"codecov": "^3.5.0", "codecov": "^3.5.0",
"cspell": "^4.1.0", "cspell": "^4.1.0",
"cz-conventional-changelog": "^3.3.0", "cz-conventional-changelog": "^3.3.0",

16
packages/noco-docs/content/en/FAQs.md

@ -65,7 +65,7 @@ Auth Token is a JWT Token generated based on the logged-in user. By default, the
API Token is a Nano ID with a length of 40. If you are passing API Token, make sure that the header is called `xc-token`. API Token is a Nano ID with a length of 40. If you are passing API Token, make sure that the header is called `xc-token`.
## Do you plan to have Enterprise Edition ? ## Do we plan to have an Enterprise Edition?
For features that make sense for enterprises like below - yes For features that make sense for enterprises like below - yes
- SSO, SLA, Organisation wide reports and analytics, - SSO, SLA, Organisation wide reports and analytics,
- Advanced Audit or ACL, - Advanced Audit or ACL,
@ -78,3 +78,17 @@ And increasing number of our customers are requesting it.
- Depends on the effort and whether the intended users are enterprises. - Depends on the effort and whether the intended users are enterprises.
## What are the official socials for NocoDB?
- Youtube: https://www.youtube.com/@nocodb
- Twitter: https://twitter.com/nocodb
- Discord: http://discord.nocodb.com/
- GitHub: https://github.com/nocodb/nocodb
- Community Forums: https://community.nocodb.com/
- LinkedIn: https://www.linkedin.com/company/nocodb
- Reddit: https://www.reddit.com/r/NocoDB/
## Is NocoDB available on the cloud?
Soon! NocoDB is currently developing cloud infrastructure.
To join the upcoming FREE private beta program, [fill out this form here](https://docs.google.com/forms/d/e/1FAIpQLSfKLe8Rcrq0uo2_jM5W1kbVBbzDiQ3IvlP8Iov61FTekVAvzA/viewform) and be the first to try it!

18
packages/noco-docs/content/en/developer-resources/accessing-apis.md

@ -18,23 +18,7 @@ Auth Token is a JWT Token generated based on the logged-in user. By default, the
## API Token ## API Token
NocoDB allows creating API tokens which allow it to be integrated seamlessly with 3rd party apps. API Token is a Nano ID with a length of 40. If you are passing API Token, make sure that the header is called `xc-token`. API tokens allows us to integrate seamlessly with 3rd party apps. See [API Tokens Management](../setup-and-usages/team-and-auth#api-tokens-management) for more.
- Open `Project Menu`, click on `Team & Settings`
<img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png">
- Click `API Tokens Management` tab under `Team & Auth` section
- Click Add New Token
![Screenshot 2022-09-14 at 10 20 00 AM](https://user-images.githubusercontent.com/86527202/190062728-9c09934f-b5e4-4fec-b4d2-0cd3648bbb39.png)
- Type an recognizable name for your token and click `Generate`
![Screenshot 2022-09-14 at 10 20 10 AM](https://user-images.githubusercontent.com/86527202/190062801-db3fab83-7974-4dfe-9c83-bf0d8a7dba1e.png)
- Copy API token to your clipboard; use action menu to the right of token list
## Swagger UI ## Swagger UI

4
packages/noco-docs/content/en/engineering/playwright.md

@ -189,7 +189,7 @@ This a method which will reset/clear all the filters. Since this is an action me
```js ```js
async resetFilter() { async resetFilter() {
await this.waitForResponse({ await this.waitForResponse({
uiAction: this.get().locator('.nc-filter-item-remove-btn').click(), uiAction: () => this.get().locator('.nc-filter-item-remove-btn').click(),
httpMethodsToMatch: ['DELETE'], httpMethodsToMatch: ['DELETE'],
requestUrlPathToMatch: '/api/v1/db/meta/filters/', requestUrlPathToMatch: '/api/v1/db/meta/filters/',
}); });
@ -221,4 +221,4 @@ async verifyFilter({ title }: { title: string }) {
- Open `Summary` tab in the CI workflow in github actions. - Open `Summary` tab in the CI workflow in github actions.
- Scroll down to `Artifacts` section. - Scroll down to `Artifacts` section.
- Access reports which suffixed with the db type and shard number(corresponding to the CI workerflow name). i.e `playwright-report-mysql-2` is for `playwright-mysql-2` workflow. - Access reports which suffixed with the db type and shard number(corresponding to the CI workerflow name). i.e `playwright-report-mysql-2` is for `playwright-mysql-2` workflow.
- Download it and run `npm install -D @playwright/test && npx playwright show-report ./` inside the downloaded folder. - Download it and run `npm install -D @playwright/test && npx playwright show-report ./` inside the downloaded folder.

103
packages/noco-docs/content/en/getting-started/environment-variables.md

@ -13,54 +13,55 @@ For production usecases, it is **recommended** to configure
- `NC_PUBLIC_URL`, - `NC_PUBLIC_URL`,
- `NC_REDIS_URL` - `NC_REDIS_URL`
| Variable | Comments | If absent | | | Variable | Comments | If absent | |
|------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|---| |---|---|---|---|
| NC_DB | See our database URLs | A local SQLite will be created in root folder if `NC_DB` is not provided | | | NC_DB | See our database URLs | A local SQLite will be created in root folder if `NC_DB` is not provided | |
| NC_DB_JSON | Can be used instead of `NC_DB` and value should be valid knex connection JSON | | | | NC_DB_JSON | Can be used instead of `NC_DB` and value should be valid knex connection JSON | | |
| NC_DB_JSON_FILE | Can be used instead of `NC_DB` and value should be a valid path to knex connection JSON | | | | NC_DB_JSON_FILE | Can be used instead of `NC_DB` and value should be a valid path to knex connection JSON | | |
| DATABASE_URL | JDBC URL Format. Can be used instead of NC_DB. | | | | DATABASE_URL | JDBC URL Format. Can be used instead of NC_DB. | | |
| DATABASE_URL_FILE | Can be used instead of DATABASE_URL: path to file containing JDBC URL Format. | | | | DATABASE_URL_FILE | Can be used instead of DATABASE_URL: path to file containing JDBC URL Format. | | |
| NC_AUTH_JWT_SECRET | JWT secret used for auth and storing other secrets | A random secret will be generated | | | NC_AUTH_JWT_SECRET | JWT secret used for auth and storing other secrets | A random secret will be generated | |
| PORT | For setting app running port | `8080` | | | PORT | For setting app running port | `8080` | |
| DB_QUERY_LIMIT_DEFAULT | Default pagination limit | 25 | | | DB_QUERY_LIMIT_DEFAULT | Default pagination limit | 25 | |
| DB_QUERY_LIMIT_MAX | Maximum allowed pagination limit | 1000 | | | DB_QUERY_LIMIT_MAX | Maximum allowed pagination limit | 1000 | |
| DB_QUERY_LIMIT_MIN | Minimum allowed pagination limit | 1 | | | DB_QUERY_LIMIT_MIN | Minimum allowed pagination limit | 1 | |
| NC_TOOL_DIR | App directory to keep metadata and app related files | Defaults to current working directory. In docker maps to `/usr/app/data/` for mounting volume. | | | NC_TOOL_DIR | App directory to keep metadata and app related files | Defaults to current working directory. In docker maps to `/usr/app/data/` for mounting volume. | |
| NC_PUBLIC_URL | Used for sending Email invitations | Best guess from http request params | | | NC_PUBLIC_URL | Used for sending Email invitations | Best guess from http request params | |
| NC_JWT_EXPIRES_IN | JWT token expiry time | `10h` | | | NC_JWT_EXPIRES_IN | JWT token expiry time | `10h` | |
| NC_CONNECT_TO_EXTERNAL_DB_DISABLED | Disable Project creation with external database | | | | NC_CONNECT_TO_EXTERNAL_DB_DISABLED | Disable Project creation with external database | | |
| NC_INVITE_ONLY_SIGNUP | Removed since version 0.99.0 and now it's recommended to use [super admin settings menu](/setup-and-usages/account-settings#enable--disable-signup). Allow users to signup only via invite url, value should be any non-empty string. | | | | NC_INVITE_ONLY_SIGNUP | Removed since version 0.99.0 and now it's recommended to use [super admin settings menu](/setup-and-usages/account-settings#enable--disable-signup). Allow users to signup only via invite url, value should be any non-empty string. | | |
| NUXT_PUBLIC_NC_BACKEND_URL | Custom Backend URL | ``http://localhost:8080`` will be used | | | NUXT_PUBLIC_NC_BACKEND_URL | Custom Backend URL | ``http://localhost:8080`` will be used | |
| NC_REQUEST_BODY_SIZE | Request body size [limit](https://expressjs.com/en/resources/middleware/body-parser.html#limit) | `1048576` | | | NC_REQUEST_BODY_SIZE | Request body size [limit](https://expressjs.com/en/resources/middleware/body-parser.html#limit) | `1048576` | |
| NC_EXPORT_MAX_TIMEOUT | After NC_EXPORT_MAX_TIMEOUT csv gets downloaded in batches | Default value 5000(in millisecond) will be used | | | NC_EXPORT_MAX_TIMEOUT | After NC_EXPORT_MAX_TIMEOUT csv gets downloaded in batches | Default value 5000(in millisecond) will be used | |
| NC_DISABLE_TELE | Disable telemetry | | | | NC_DISABLE_TELE | Disable telemetry | | |
| NC_DASHBOARD_URL | Custom dashboard url path | `/dashboard` | | | NC_DASHBOARD_URL | Custom dashboard url path | `/dashboard` | |
| NC_GOOGLE_CLIENT_ID | Google client id to enable google authentication | | | | NC_GOOGLE_CLIENT_ID | Google client id to enable google authentication | | |
| NC_GOOGLE_CLIENT_SECRET | Google client secret to enable google authentication | | | | NC_GOOGLE_CLIENT_SECRET | Google client secret to enable google authentication | | |
| NC_MIGRATIONS_DISABLED | Disable NocoDB migration | | | | NC_MIGRATIONS_DISABLED | Disable NocoDB migration | | |
| NC_MIN | If set to any non-empty string the default splash screen(initial welcome animation) and matrix screensaver will disable | | | | NC_MIN | If set to any non-empty string the default splash screen(initial welcome animation) and matrix screensaver will disable | | |
| NC_SENTRY_DSN | For Sentry monitoring | | | | NC_SENTRY_DSN | For Sentry monitoring | | |
| NC_REDIS_URL | Custom Redis URL. Example: `redis://:authpassword@127.0.0.1:6380/4` | Meta data will be stored in memory | | | NC_REDIS_URL | Custom Redis URL. Example: `redis://:authpassword@127.0.0.1:6380/4` | Meta data will be stored in memory | |
| NC_DISABLE_ERR_REPORT | Disable error reporting | | | | NC_DISABLE_ERR_REPORT | Disable error reporting | | |
| NC_DISABLE_CACHE | To be used only while debugging. On setting this to `true` - meta data be fetched from db instead of redis/cache. | `false` | | | NC_DISABLE_CACHE | To be used only while debugging. On setting this to `true` - meta data be fetched from db instead of redis/cache. | `false` | |
| NC_BASEURL_INTERNAL | Used as base url for internal(server) API calls | Default value in docker will be `http://localhost:$PORT` and in all other case it's populated from request object | | | NC_BASEURL_INTERNAL | Used as base url for internal(server) API calls | Default value in docker will be `http://localhost:$PORT` and in all other case it's populated from request object | |
| AWS_ACCESS_KEY_ID | For Litestream - S3 access key id | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | | | AWS_ACCESS_KEY_ID | For Litestream - S3 access key id | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
| AWS_SECRET_ACCESS_KEY | For Litestream - S3 secret access key | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | | | AWS_SECRET_ACCESS_KEY | For Litestream - S3 secret access key | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
| AWS_BUCKET | For Litestream - S3 bucket | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | | | AWS_BUCKET | For Litestream - S3 bucket | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
| AWS_BUCKET_PATH | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | | | AWS_BUCKET_PATH | For Litestream - S3 bucket path (like folder within S3 bucket) | If Litestream is configured and `NC_DB` is not present. SQLite gets backed up to S3 | |
| NC_SMTP_FROM | For SMTP plugin - Email sender address | | | | NC_SMTP_FROM | For SMTP plugin - Email sender address | | |
| NC_SMTP_HOST | For SMTP plugin - SMTP host value | | | | NC_SMTP_HOST | For SMTP plugin - SMTP host value | | |
| NC_SMTP_PORT | For SMTP plugin - SMTP port value | | | | NC_SMTP_PORT | For SMTP plugin - SMTP port value | | |
| NC_SMTP_USERNAME | For SMTP plugin (Optional) - SMTP username value for authentication | | | | NC_SMTP_USERNAME | For SMTP plugin (Optional) - SMTP username value for authentication | | |
| NC_SMTP_PASSWORD | For SMTP plugin (Optional) - SMTP password value for authentication | | | | NC_SMTP_PASSWORD | For SMTP plugin (Optional) - SMTP password value for authentication | | |
| NC_SMTP_SECURE | For SMTP plugin (Optional) - To enable secure set value as `true` any other value treated as false | | | | NC_SMTP_SECURE | For SMTP plugin (Optional) - To enable secure set value as `true` any other value treated as false | | |
| NC_SMTP_IGNORE_TLS | For SMTP plugin (Optional) - To ignore tls set value as `true` any other value treated as false. For more info visit https://nodemailer.com/smtp/ | | | | NC_SMTP_IGNORE_TLS | For SMTP plugin (Optional) - To ignore tls set value as `true` any other value treated as false. For more info visit https://nodemailer.com/smtp/ | | |
| NC_S3_BUCKET_NAME | For S3 storage plugin - AWS S3 bucket name | | | | NC_S3_BUCKET_NAME | For S3 storage plugin - AWS S3 bucket name | | |
| NC_S3_REGION | For S3 storage plugin - AWS S3 region | | | | NC_S3_REGION | For S3 storage plugin - AWS S3 region | | |
| NC_S3_ACCESS_KEY | For S3 storage plugin - AWS access key credential for accessing resource | | | | NC_S3_ACCESS_KEY | For S3 storage plugin - AWS access key credential for accessing resource | | |
| NC_S3_ACCESS_SECRET | For S3 storage plugin - AWS access secret credential for accessing resource | | | | NC_S3_ACCESS_SECRET | For S3 storage plugin - AWS access secret credential for accessing resource | | |
| NC_ADMIN_EMAIL | For updating/creating super admin with provided email and password | | | | NC_ADMIN_EMAIL | For updating/creating super admin with provided email and password | | |
| NC_ATTACHMENT_FIELD_SIZE | For setting the attachment field size(in Bytes) | Defaults to 20MB | | | NC_ATTACHMENT_FIELD_SIZE | For setting the attachment field size(in Bytes) | Defaults to 20MB | |
| NC_ADMIN_PASSWORD | For updating/creating super admin with provided email and password. Your password should have at least 8 letters with one uppercase, one number and one special letter(Allowed special chars $&+,:;=?@#\|'.^*()%!_-" ) | | | | NC_ADMIN_PASSWORD | For updating/creating super admin with provided email and password. Your password should have at least 8 letters with one uppercase, one number and one special letter(Allowed special chars $&+,:;=?@#\|'.^*()%!_-" ) | | |
| NODE_OPTIONS | For passing Node.js [options](https://nodejs.org/api/cli.html#node_optionsoptions) to instance | | | | NODE_OPTIONS | For passing Node.js [options](https://nodejs.org/api/cli.html#node_optionsoptions) to instance | | |
| NC_MINIMAL_DBS | Create a new SQLite file for each project. All the db files are stored in `nc_minimal_dbs` folder in current working directory. (This option restricts project creation on external sources) | | | | NC_MINIMAL_DBS | Create a new SQLite file for each project. All the db files are stored in `nc_minimal_dbs` folder in current working directory. (This option restricts project creation on external sources) | | |
| NC_DISABLE_AUDIT | Disable Audit Log | `false` | |

12
packages/noco-docs/content/en/index.md

@ -63,3 +63,15 @@ Our mission is to provide the most powerful no-code interface for databases whic
Please refer to [here](https://github.com/nocodb/nocodb/blob/develop/.github/CONTRIBUTING.md) for the contribution guidelines. Please refer to [here](https://github.com/nocodb/nocodb/blob/develop/.github/CONTRIBUTING.md) for the contribution guidelines.
<img src="https://static.scarf.sh/a.png?x-pxid=c12a77cc-855e-4602-8a0f-614b2d0da56a" style="margin: 0px;" /> <img src="https://static.scarf.sh/a.png?x-pxid=c12a77cc-855e-4602-8a0f-614b2d0da56a" style="margin: 0px;" />
## Where can I join the NocoDB community?
Follow us for daily updates, content, and other activities with our community:
- [Youtube](https://www.youtube.com/@nocodb)
- [Twitter](https://twitter.com/nocodb)
- [Discord](http://discord.nocodb.com/)
- [GitHub](https://github.com/nocodb/nocodb)
- [Community Forums](https://community.nocodb.com/)
- [LinkedIn](https://www.linkedin.com/company/nocodb)
- [Reddit](https://www.reddit.com/r/NocoDB/)

10
packages/noco-docs/content/en/setup-and-usages/account-settings.md

@ -54,10 +54,16 @@ Signup without an invitation is disabled by default and can be managed from UI b
## App Store ## App Store
You can also manage the app store plugins here.
![image](https://user-images.githubusercontent.com/35857179/203267619-24a8f5f5-1c8c-4419-a7a1-be4377fe6216.png) ![image](https://user-images.githubusercontent.com/35857179/203267619-24a8f5f5-1c8c-4419-a7a1-be4377fe6216.png)
We provide different integrations in three main categories.
| Category | App Name |
|---|---|
| Chat | Microsoft Teams <br/> Discord <br/> Twilio <br/> Whatsapp Twilio<br/> Mattermost<br/> Slack |
| Email | SMTP<br/> MailerSend<br/> AWS SES |
| Storage | AWS S3 <br/> Minio <br/> Google Cloud Storage <br/> Spaces <br/> Backblaze B2 <br/> Vultr Object Storage <br/> OvhCloud Object Storage <br/> Linode Object Storage <br/> UpCloud Object Storage <br/> Scaleway Object Storage |
## License ## License
You can configure NocoDB Enterprise `License key` here You can configure NocoDB Enterprise `License key` here

22
packages/noco-docs/content/en/setup-and-usages/app-store.md

@ -1,22 +0,0 @@
---
title: 'Account Settings > App Store'
description: 'NocoDB provides different integrations in three main categories in App Store'
position: 590
category: 'Product'
menuTitle: 'Account Settings > App Store'
---
## Overview
To access it, click the down arrow button next to Project Name on the top left side, then select `Account Settings` and clicking `App Store`.
<img width="304" alt="Screenshot 2023-02-07 at 5 14 11 PM" src="https://user-images.githubusercontent.com/43586156/217380060-bc654146-233c-4f8a-9a7d-bb0d30a2eac9.png"> | <img width="200" alt="Screenshot 2023-02-07 at 5 14 30 PM" src="https://user-images.githubusercontent.com/43586156/217380195-dfe5de7f-0ad9-4af8-ba24-33805f72c32d.png">
|--|--|
We provide different integrations in three main categories.
| Category | App Name |
|---|---|
| Chat | Microsoft Teams <br/> Discord <br/> Twilio <br/> Whatsapp Twilio<br/> Mattermost<br/> Slack |
| Email | SMTP<br/> MailerSend<br/> AWS SES |
| Storage | AWS S3 <br/> Minio <br/> Google Cloud Storage <br/> Spaces <br/> Backblaze B2 <br/> Vultr Object Storage <br/> OvhCloud Object Storage <br/> Linode Object Storage <br/> UpCloud Object Storage <br/> Scaleway Object Storage |

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

@ -10,6 +10,10 @@ menuTitle: 'Team & Settings > Audit'
We are keeping all the user operation logs under Audit. To access it, click the down arrow button next to Project Name on the top left side, then select `Team & Settings`. We are keeping all the user operation logs under Audit. To access it, click the down arrow button next to Project Name on the top left side, then select `Team & Settings`.
<alert>
We can disable audit logs by setting `NC_DISABLE_AUDIT` to `true`.
</alert>
<img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png"> <img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png">
Then, under SETTINGS, click `Audit`. Then, under SETTINGS, click `Audit`.

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

@ -71,6 +71,16 @@ You can also group several filters together using Filter Group.
<img width="1025" alt="image" src="https://user-images.githubusercontent.com/35857179/189102932-aa0e31ef-554f-4e8b-ae0e-2024b7f4d35b.png"> <img width="1025" alt="image" src="https://user-images.githubusercontent.com/35857179/189102932-aa0e31ef-554f-4e8b-ae0e-2024b7f4d35b.png">
### Supported filters ### Enable NULL and EMPTY Filters
Currently we support filter types - `is equal`, `is not equal`, `is like`, `is not like`, `is null`, `is not null` for string fields. We also support filter types - `>`, `<`, `>=`, and `<=` for numeric fields. Also we provide `is empty` and `is not empty` for checking if the column is empty or not. NULL filters (`is null` & `is not null`) and EMPTY filters (`is empty` & `is not empty`) are hidden by default. If you wish to filter out either one only, you may enable `Show NULL and EMPTY Filter` in Project Settings.
![image](https://user-images.githubusercontent.com/35857179/219009085-0308b2a9-10af-4afe-84b6-df52e42fb1a8.png)
Otherwise, we can use Blank filters to filter out cells with NULL values and EMPTY values.
### Supported Filters
Currently we support different types of filters for corresponding columns. Please refer the below matrix for details.
<iframe width="100%" height="700vh" src="https://docs.google.com/spreadsheets/d/e/2PACX-1vTpCNKtA-szaXUKJEO5uuSIRnzUOK793MKnyBz9m2rQcwn7HqK19jPHeER-IIRWH9X56J78wfxXZuuv/pubhtml?gid=427284630&amp;single=true&amp;widget=true&amp;headers=false"></iframe>

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

@ -44,19 +44,16 @@ Click on three-dot menu adjacent to `BASES`. Pick required database option from
<alert type="success"> <alert type="success">
Tip: If you are running NocoDB on Docker and your local DB is running on your host machine, your Host Address would be host.docker.internal instead of localhost. Tip: If you are running NocoDB on Docker and your local DB is running on your host machine, your Host Address would be host.docker.internal instead of localhost.
</alert> </alert>
<!-- <img width="1500" alt="image" src="https://user-images.githubusercontent.com/35857179/194793497-3b740bf2-ffc7-48bf-836e-e4cd26631568.png"> -->
![Screenshot 2022-12-29 at 2 55 39 PM](https://user-images.githubusercontent.com/86527202/209933294-9327ff16-21db-4aca-bf16-8cea8a1eb415.png) ![Screenshot 2022-12-29 at 2 55 39 PM](https://user-images.githubusercontent.com/86527202/209933294-9327ff16-21db-4aca-bf16-8cea8a1eb415.png)
Above menu is also accessible from `Team & Settings` > `Data Sources`. Click on `New` button to add existing database. Above menu is also accessible from `Team & Settings` > `Data Sources`. Click on `New` button to add existing database.
![image](https://user-images.githubusercontent.com/35857179/219841162-6456c5cf-fd26-4a88-8de6-e8742c043607.png)
![Screenshot 2022-12-29 at 3 16 36 PM](https://user-images.githubusercontent.com/86527202/209936942-f82a293f-2e91-48da-b9cd-79ec143d7d6f.png)
You need to specify the project name, API type, and other database parameters. You need to specify the project name, API type, and other database parameters.
![Screenshot 2022-12-29 at 2 56 25 PM](https://user-images.githubusercontent.com/86527202/209933326-e76eee13-4942-4ba8-b184-a28099c089ab.png) ![image](https://user-images.githubusercontent.com/35857179/219841283-1a42f9f6-4677-4e25-8ca9-a060753d1e1e.png)
Currently it supports MySQL, Postgres, MSSQL and SQLite. Currently it supports MySQL, Postgres, MSSQL and SQLite.

36
packages/noco-docs/content/en/setup-and-usages/primary-value.md → packages/noco-docs/content/en/setup-and-usages/display-value.md

@ -1,40 +1,42 @@
--- ---
title: "Primary Value" title: "Display Value"
description: "Understanding Primary Value in NocoDB!" description: "Understanding Display Value in NocoDB!"
position: 580 position: 580
category: "Product" category: "Product"
menuTitle: "Primary Value" menuTitle: "Display Value"
--- ---
## What is a Primary Value ? ## What is a Display Value ?
- Primary value as the name stands is the primary or main value within a row of a table that you generally associate that row with.
- Display Value as the name stands is the primary or main value within a row of a table that you generally associate that row with.
- It should be usually associated with a column which is uniquely identifiable. However, this uniqueness is not enforced at the database level. - It should be usually associated with a column which is uniquely identifiable. However, this uniqueness is not enforced at the database level.
- Before v0.105.0, Display Value was known as Primary Value.
## What is the use of Primary Value ? ## What is the use of Display Value ?
- Within a spreadsheet, primary value are always highlighted so that it is easier to recognise what row we are in. - Within a spreadsheet, Display Value are always highlighted so that it is easier to recognise what row we are in.
- And when LinkToAnotherRecord is created between two tables - it is the primary value that appears in LinkToAnotheRecord column. - And when LinkToAnotherRecord is created between two tables - it is the Display Value that appears in LinkToAnotheRecord column.
#### Example : Primary Value highlighted in Actor table #### Example : Display Value highlighted in Actor table
<img width="646" alt="image" src="https://user-images.githubusercontent.com/35857179/189114321-58ebaa16-20e2-4615-abda-39417a5df5bf.png"> <img width="646" alt="image" src="https://user-images.githubusercontent.com/35857179/189114321-58ebaa16-20e2-4615-abda-39417a5df5bf.png">
#### Example : Primary Value highlighted in Film table #### Example : Display Value highlighted in Film table
<img width="643" alt="image" src="https://user-images.githubusercontent.com/35857179/189114462-a7fef0e2-f9ac-4943-98d5-fee9f60a4ab5.png"> <img width="643" alt="image" src="https://user-images.githubusercontent.com/35857179/189114462-a7fef0e2-f9ac-4943-98d5-fee9f60a4ab5.png">
#### Example : Primary Value associated when LinkToAnotherRecord is created #### Example : Display Value associated when LinkToAnotherRecord is created
<img width="311" alt="image" src="https://user-images.githubusercontent.com/35857179/189114548-193acc4d-f714-4204-a560-97668db7884c.png"> <img width="311" alt="image" src="https://user-images.githubusercontent.com/35857179/189114548-193acc4d-f714-4204-a560-97668db7884c.png">
## How to set Primary Value ? ## How to set Display Value ?
Click down arrow in the target column. Click `Set as Primary Value`. Click down arrow in the target column. Click `Set as Display Value`.
<img width="251" alt="image" src="https://user-images.githubusercontent.com/35857179/189114857-b452aa6b-5cdb-4a74-9980-cb839d7d15fd.png"> ![image](https://user-images.githubusercontent.com/35857179/219339727-dee5fdea-6db7-4a06-9e48-df7113cc63b1.png)
## How is Primary Value identfied for existing database tables ? ## How is Display Value identfied for existing database tables ?
- It is usually the first column after the primary key which is not a number. - It is usually the first column after the primary key which is not a number.
- If there is no column which is not a number then the column adjacent to primary key is chosen. - If there is no column which is not a number then the column adjacent to primary key is chosen.
## Can I change the Primary Value to another column within tables ? ## Can I change the Display Value to another column within tables ?
- Yes, you can use the same way mentioned above to set Primary Value. - Yes, you can use the same way mentioned above to set Display Value.

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

@ -6,6 +6,8 @@ category: 'Product'
menuTitle: 'Team & Settings > Data Sources' menuTitle: 'Team & Settings > Data Sources'
--- ---
## Overview
`Data Sources` sub-menu includes `Data Sources` sub-menu includes
- Database Metadata - Database Metadata
- UI Access Control - UI Access Control
@ -14,46 +16,33 @@ menuTitle: 'Team & Settings > Data Sources'
- Edit existing data source configuration - Edit existing data source configuration
- Edit data source visibility options - Edit data source visibility options
Note that, currently only one external data source can be added per project. Note that, currently only one external data source can be added per project.
To access it, click the down arrow button next to Project Name on the top left side, then select `Team & Settings` and clicking `Data Sources`. ## Accessing Data Sources
<!-- ![Screenshot 2022-12-29 at 4 26 27 PM](https://user-images.githubusercontent.com/86527202/209941709-1bfdbb01-ebd0-4c85-a966-2a8b4fc6ade7.png) -->
![Screenshot 2022-12-29 at 4 29 24 PM](https://user-images.githubusercontent.com/86527202/209941906-a9c8d48d-d604-4a2f-8ffb-7a9a494bac6b.png)
![Screenshot 2022-12-29 at 4 27 14 PM](https://user-images.githubusercontent.com/86527202/209941716-70f2aaa7-b035-42b2-835e-eb2ca348be42.png)
To access it, click the down arrow button next to Project Name on the top left side, then select `Team & Settings` and clicking `Data Sources`.
<!-- ![Screenshot 2022-12-29 at 3 54 55 PM](https://user-images.githubusercontent.com/86527202/209938195-7384b4d8-0289-447f-bd39-1ec600cd1723.png) --> <img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png">
<!-- <img width="322" alt="image" src="https://user-images.githubusercontent.com/86527202/209941709-1bfdbb01-ebd0-4c85-a966-2a8b4fc6ade7.png"> | <img alt="image" src="https://user-images.githubusercontent.com/86527202/209941716-70f2aaa7-b035-42b2-835e-eb2ca348be42.png"> -->
<!-- |--|--| -->
![Screenshot 2022-12-29 at 4 15 00 PM](https://user-images.githubusercontent.com/86527202/209940452-5b867b71-b9f1-4e64-af69-14715ab73be7.png)
![image](https://user-images.githubusercontent.com/35857179/219833316-1fb234f0-583f-4ab8-b8d7-a6e249e7cd97.png)
## Sync Metadata ## Sync Metadata
Go to `Data Sources`, click ``Sync Metadata``, you can see your metadata sync status. If it is out of sync, you can sync the schema. See <a href="./sync-schema">Sync Schema</a> for more.0 Go to `Data Sources`, click ``Sync Metadata``, you can see your metadata sync status. If it is out of sync, you can sync the schema. See <a href="./sync-schema">Sync Schema</a> for more.0
![Screenshot 2022-12-29 at 4 19 35 PM](https://user-images.githubusercontent.com/86527202/209940903-396650b4-e219-494a-863f-c3f1beb51c5e.png) ![image](https://user-images.githubusercontent.com/35857179/219833485-3bcaa6ec-88bc-47cc-b938-5abb4835dc31.png)
<!-- <img width="1333" alt="image" src="https://user-images.githubusercontent.com/35857179/194850034-5330458e-85a9-4a3c-87a3-dd2f3edc5b46.png"> -->
## UI Access Control ## UI Access Control
Go to `Data Sources`, click ``UI ACL``, you can control the access to each table by roles. Go to `Data Sources`, click ``UI ACL``, you can control the access to each table by roles.
<!-- <img width="1336" alt="image" src="https://user-images.githubusercontent.com/35857179/194850281-9030f4c5-06bc-4780-b8fd-5d0c209867e0.png"> --> ![image](https://user-images.githubusercontent.com/35857179/219833072-20e9f4ad-fd1c-4e96-9112-6edda1447ec6.png)
![Screenshot 2022-12-29 at 4 20 57 PM](https://user-images.githubusercontent.com/86527202/209941141-deed80a9-7682-48e1-8de9-9c965c990d2d.png)
## ERD ## ERD
Go to `Data Sources`, click ``ERD``, you can see the ERD of your database. Go to `Data Sources`, click ``ERD``, you can see the ERD of your database.
![Screenshot 2022-12-29 at 4 21 55 PM](https://user-images.githubusercontent.com/86527202/209941168-b53d2898-8448-47fa-a8b3-6f3572f6b3a2.png) ![image](https://user-images.githubusercontent.com/35857179/219832288-f6266544-a259-4667-95d9-0e5ce7ac5d27.png)
<!-- <img width="1338" alt="image" src="https://user-images.githubusercontent.com/35857179/194850416-54bc49cf-c32f-45e8-aea1-62b07645c26e.png"> -->
### Junction table names within ERD ### Junction table names within ERD
@ -61,32 +50,23 @@ Go to `Data Sources`, click ``ERD``, you can see the ERD of your database.
- Double click on `Show Columns` to see additional checkboxes get enabled. - Double click on `Show Columns` to see additional checkboxes get enabled.
- Enabling which you should be able to see junction tables and their table names. - Enabling which you should be able to see junction tables and their table names.
<img width="1681" alt="Show Junction table names for many to many table" src="https://user-images.githubusercontent.com/5435402/192140913-9da37700-28fe-404d-88e8-35ba0c8e2f53.png"> ![image](https://user-images.githubusercontent.com/35857179/219832436-9c1311c3-854c-4b31-9c94-8035dfba2a2b.png)
## Edit external database configuration parameters ## Edit external database configuration parameters
Go to `Data Sources`, click ``Edit``, you can re-configure database credentials. Go to `Data Sources`, click ``Edit``, you can re-configure database credentials.
Please make sure database configuration parameters are valid. Any incorrect parameters could lead to schema loss! Please make sure database configuration parameters are valid. Any incorrect parameters could lead to schema loss!
![image](https://user-images.githubusercontent.com/35857179/219832592-14209cbf-d980-4e14-9a59-bda1b778a74e.png)
![Screenshot 2022-12-29 at 4 22 08 PM](https://user-images.githubusercontent.com/86527202/209941211-de9670c9-a73c-4719-9957-eeaf05f3a7ee.png)
## Unlink data source ## Unlink data source
Go to `Data Sources`, click ``Delete`` against the data source that you wish to un-link. Go to `Data Sources`, click ``Delete`` against the data source that you wish to un-link.
![Screenshot 2022-12-29 at 4 31 16 PM](https://user-images.githubusercontent.com/86527202/209942178-5ae40f14-0e87-41f7-9630-e2bf6f59a906.png) ![image](https://user-images.githubusercontent.com/35857179/219832810-a3e9ed88-f732-4f30-9228-ff782be0b9d6.png)
## Data source visibility ## Data source visibility
Go to `Data Sources`, toggle ``Radio-button`` against the data source that you wish to hide/un-hide. Go to `Data Sources`, toggle ``Radio-button`` against the data source that you wish to hide/un-hide.
![Screenshot 2022-12-29 at 4 31 16 PM 2](https://user-images.githubusercontent.com/86527202/209942198-627f7f14-761b-4709-b9ca-fde5111fa207.png) ![image](https://user-images.githubusercontent.com/35857179/219832914-f485099c-423f-4df8-bf00-b509288efe6d.png)
<!-- ## Miscellaneous
- Enabling, `Show M2M Tables` will show junction tables between many to many tables.
<img width="1340" alt="image" src="https://user-images.githubusercontent.com/35857179/194850461-3e88752a-ba4f-4ead-9426-9a9e57020061.png">
-->

6
packages/noco-docs/content/en/setup-and-usages/project-settings.md

@ -14,8 +14,4 @@ Generic project configuration options are retained under `Project Settings` menu
Then, under SETTINGS, click `Project Settings`. Then, under SETTINGS, click `Project Settings`.
## Miscellaneous ![image](https://user-images.githubusercontent.com/35857179/219830971-9518fa21-a45c-4d49-af3f-2f933d779ecd.png)
- Enabling, `Show M2M Tables` will show junction tables between many to many tables.
![Screenshot 2022-12-29 at 7 05 04 PM](https://user-images.githubusercontent.com/86527202/209961654-ffe8ddc6-c7e2-4c0d-9762-2b57fb883cfa.png)

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

@ -16,17 +16,19 @@ Below are the steps to sync schema changes.
<img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png"> <img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png">
### 2. Click `Project Metadata` under SETTINGS, access `Metadata` tab ### 2. Click `Data Source` under SETTINGS, click `Sync Metadata` on the target base
<img width="1333" alt="image" src="https://user-images.githubusercontent.com/35857179/194850034-5330458e-85a9-4a3c-87a3-dd2f3edc5b46.png"> ![image](https://user-images.githubusercontent.com/35857179/219831352-e6692ba5-5c94-4331-94ce-5796e57f87a1.png)
![image](https://user-images.githubusercontent.com/35857179/219831634-bbb6f256-45fb-4224-9f82-bc1bed6082db.png)
### 3. Changes carried outside GUI, identified by NocoDB are listed under `Sync state` ### 3. Changes carried outside GUI, identified by NocoDB are listed under `Sync state`
- If changes made to the database are not visible, click `Reload` - If changes made to the database are not visible, click `Reload`
- Identified schema changes are identified for each table in `red` - Identified schema changes are identified for each table in `red`
- `Sync now` button gets activated, if Schema changes are identified by NocoDB - `Sync now` button gets activated, if Schema changes are identified by NocoDB
![Screenshot 2022-09-13 at 10 42 12 AM](https://user-images.githubusercontent.com/86527202/189814648-ca28f28d-b0ed-4652-a5da-e6472bfd9407.png) ![image](https://user-images.githubusercontent.com/35857179/219831855-bcac229c-41b6-4689-b7e1-c3cdfe23a0a1.png)
<!-- ![image](https://user-images.githubusercontent.com/35857179/161957119-f66f22ad-9d37-45ed-84ca-35c99726078c.png) -->
### 4. Click `Sync Now` to complete Schema sync procedure ### 4. Click `Sync Now` to complete Schema sync procedure

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

@ -159,7 +159,7 @@ You can use Quick Import when you have data from external sources such as Airtab
- **Use First Row as Headers**: If it is checked, the first row will be treated as header row. - **Use First Row as Headers**: If it is checked, the first row will be treated as header row.
- **Import Data**: If it is checked, all data will be imported. Otherwise, only table will be created. - **Import Data**: If it is checked, all data will be imported. Otherwise, only table will be created.
![image](https://user-images.githubusercontent.com/35857179/197454479-1ed18dce-1d0b-4ee3-88b3-9b6a132dea2a.png) ![image](https://user-images.githubusercontent.com/35857179/197454479-1ed18dce-1d0b-4ee3-88b3-9b6a132dea2a.png)
- You can revise the table name by double clicking it, column name and column type. By default, the first column will be chosen as <a href="./primary-value" target="_blank">Primary Value</a> and cannot be deleted. - You can revise the table name by double clicking it, column name and column type. By default, the first column will be chosen as <a href="./display-value" target="_blank">Display Value</a> and cannot be deleted.
![image](https://user-images.githubusercontent.com/35857179/197454633-5b30323e-2b13-4c55-843a-948c093d373e.png) ![image](https://user-images.githubusercontent.com/35857179/197454633-5b30323e-2b13-4c55-843a-948c093d373e.png)
- Click `Import` to start importing process. The table will be created and the data will be imported. - Click `Import` to start importing process. The table will be created and the data will be imported.
![image](https://user-images.githubusercontent.com/35857179/197455547-2d93df5e-a7f0-4c88-af53-990067625967.png) ![image](https://user-images.githubusercontent.com/35857179/197455547-2d93df5e-a7f0-4c88-af53-990067625967.png)
@ -172,7 +172,7 @@ You can use Quick Import when you have data from external sources such as Airtab
- **Use First Row as Headers**: If it is checked, the first row will be treated as header row. - **Use First Row as Headers**: If it is checked, the first row will be treated as header row.
- **Import Data**: If it is checked, all data will be imported. Otherwise, only table will be created. - **Import Data**: If it is checked, all data will be imported. Otherwise, only table will be created.
![image](https://user-images.githubusercontent.com/35857179/197455788-8dd8a7d1-38f3-48c3-a05e-6ab0cf25045c.png) ![image](https://user-images.githubusercontent.com/35857179/197455788-8dd8a7d1-38f3-48c3-a05e-6ab0cf25045c.png)
- You can revise the table name, column name and column type. By default, the first column will be chosen as <a href="./primary-value" target="_blank">Primary Value</a> and cannot be deleted. - You can revise the table name, column name and column type. By default, the first column will be chosen as <a href="./display-value" target="_blank">Display Value</a> and cannot be deleted.
<alert> <alert>
Note: If your Excel file contains multiple sheets, each sheet will be stored in a separate table. Note: If your Excel file contains multiple sheets, each sheet will be stored in a separate table.
</alert> </alert>

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

@ -6,18 +6,21 @@ category: 'Product'
menuTitle: 'Team & Settings > Team & Auth' menuTitle: 'Team & Settings > Team & Auth'
--- ---
# Accessing Team & Auth ## Accessing Team & Auth
- Click on `Team & Settings` from the `Project Menu` - Click on `Team & Settings` from the `Project Menu`
- Access `Team & Auth` under `Settings` - Access `Team & Auth` under `Settings`
<img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png"> <img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png">
## How to Add a User ## User Management
### How to Add a User
1. Go to `Team & Auth`, click on `Invite Team` 1. Go to `Team & Auth`, click on `Invite Team`
<img width="1336" alt="image" src="https://user-images.githubusercontent.com/35857179/194849838-f936128a-3f8a-46ef-a4e3-fdc14b633874.png"> ![image](https://user-images.githubusercontent.com/35857179/219830800-481f372f-86b1-4e2f-865d-3fb7c10663f7.png)
2. Enter the user's `E-mail`. Select `User Role`, and Click `Invite`. 2. Enter the user's `E-mail`. Select `User Role`, and Click `Invite`.
@ -32,18 +35,16 @@ If you do not have an SMTP sender configured, make sure to copy the invite link
![Screenshot 2022-09-13 at 10 54 22 AM](https://user-images.githubusercontent.com/86527202/189817156-f3dab634-dc25-4f9b-8126-865187aae254.png) ![Screenshot 2022-09-13 at 10 54 22 AM](https://user-images.githubusercontent.com/86527202/189817156-f3dab634-dc25-4f9b-8126-865187aae254.png)
## How to Update user permissions ### How to Update user permissions
1. Use `Edit` <1> menu to assign a different role to existing user 1. Use `Edit` <1> menu to assign a different role to existing user
2. Use `Delete` <2> menu to remove a user from accessing current project 2. Use `Delete` <2> menu to remove a user from accessing current project
![Screenshot 2022-09-13 at 11 06 16 AM](https://user-images.githubusercontent.com/86527202/189818302-80a05245-9dc1-4364-b380-7bd698e5b9e0.png) ![image](https://user-images.githubusercontent.com/35857179/219830858-be7a4656-9f3b-440c-9a79-165f919223d7.png)
------ ------
### User Role Permissions
# User Role Permissions
### Advanced Options & Configurations ### Advanced Options & Configurations
| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; Owner &nbsp; &nbsp;| &nbsp; &nbsp; Creator &nbsp; &nbsp; | &nbsp; &nbsp; Editor &nbsp; &nbsp;| Commenter | &nbsp; &nbsp; Viewer &nbsp; &nbsp;| | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; Owner &nbsp; &nbsp;| &nbsp; &nbsp; Creator &nbsp; &nbsp; | &nbsp; &nbsp; Editor &nbsp; &nbsp;| Commenter | &nbsp; &nbsp; Viewer &nbsp; &nbsp;|
@ -106,6 +107,25 @@ If you do not have an SMTP sender configured, make sure to copy the invite link
| Project Info | ✅ | ✅ | ✅ | ✅ | ✅ | | Project Info | ✅ | ✅ | ✅ | ✅ | ✅ |
| Swagger API | ✅ | ✅ | ✅ | ✅ | ✅ | | Swagger API | ✅ | ✅ | ✅ | ✅ | ✅ |
## API Tokens Management
NocoDB allows creating API tokens which allow it to be integrated seamlessly with 3rd party apps. API Token is a Nano ID with a length of 40. If you are passing API Token, make sure that the header is called `xc-token`.
- Open `Project Menu`, click on `Team & Settings`
<img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png">
- Click `API Tokens Management` tab under `Team & Auth` section
- Click Add New Token
![image](https://user-images.githubusercontent.com/35857179/219835108-037127bd-4bf6-4d96-b691-139bd141631c.png)
- Type an recognizable name for your token and click `Generate`
![Screenshot 2022-09-14 at 10 20 10 AM](https://user-images.githubusercontent.com/86527202/190062801-db3fab83-7974-4dfe-9c83-bf0d8a7dba1e.png)
- Copy API token to your clipboard; use action menu to the right of token list
<!-- TODO: --> <!-- TODO: -->
<!-- ### Automations <!-- ### Automations
@ -116,4 +136,4 @@ If you do not have an SMTP sender configured, make sure to copy the invite link
| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; Owner &nbsp; &nbsp;| &nbsp; &nbsp; Creator &nbsp; &nbsp; | &nbsp; &nbsp; Editor &nbsp; &nbsp;| Commenter | &nbsp; &nbsp; Viewer &nbsp; &nbsp;| | &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | &nbsp; &nbsp; Owner &nbsp; &nbsp;| &nbsp; &nbsp; Creator &nbsp; &nbsp; | &nbsp; &nbsp; Editor &nbsp; &nbsp;| Commenter | &nbsp; &nbsp; Viewer &nbsp; &nbsp;|
| :-- | :-: | :-: | :-: | :-: | :-: | | :-- | :-: | :-: | :-: | :-: | :-: |
--> -->

4
packages/nocodb-sdk/package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "nocodb-sdk", "name": "nocodb-sdk",
"version": "0.104.3", "version": "0.105.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "nocodb-sdk", "name": "nocodb-sdk",
"version": "0.104.3", "version": "0.105.2",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",

2
packages/nocodb-sdk/package.json

@ -1,6 +1,6 @@
{ {
"name": "nocodb-sdk", "name": "nocodb-sdk",
"version": "0.104.3", "version": "0.105.2",
"description": "NocoDB SDK", "description": "NocoDB SDK",
"main": "build/main/index.js", "main": "build/main/index.js",
"typings": "build/main/index.d.ts", "typings": "build/main/index.d.ts",

7
packages/nocodb-sdk/src/index.ts

@ -7,7 +7,12 @@ export * from './lib/globals';
export * from './lib/helperFunctions'; export * from './lib/helperFunctions';
export * from './lib/enums'; export * from './lib/enums';
export * from './lib/formulaHelpers'; export * from './lib/formulaHelpers';
export { default as UITypes, isVirtualCol } from './lib/UITypes'; export {
default as UITypes,
numericUITypes,
isNumericCol,
isVirtualCol,
} from './lib/UITypes';
export { default as CustomAPI } from './lib/CustomAPI'; export { default as CustomAPI } from './lib/CustomAPI';
export { default as TemplateGenerator } from './lib/TemplateGenerator'; export { default as TemplateGenerator } from './lib/TemplateGenerator';
export * from './lib/passwordHelpers'; export * from './lib/passwordHelpers';

16
packages/nocodb-sdk/src/lib/Api.ts

@ -1866,6 +1866,22 @@ export class Api<
}), }),
/** /**
* No description
*
* @tags Project
* @name HasEmptyOrNullFilters
* @request GET:/api/v1/db/meta/projects/{projectId}/has-empty-or-null-filters
* @response `200` `any` OK
*/
hasEmptyOrNullFilters: (projectId: string, params: RequestParams = {}) =>
this.request<any, any>({
path: `/api/v1/db/meta/projects/${projectId}/has-empty-or-null-filters`,
method: 'GET',
format: 'json',
...params,
}),
/**
* No description * No description
* *
* @tags Project * @tags Project

22
packages/nocodb-sdk/src/lib/UITypes.ts

@ -39,6 +39,28 @@ enum UITypes {
Button = 'Button', Button = 'Button',
} }
export const numericUITypes = [
UITypes.Duration,
UITypes.Currency,
UITypes.Percent,
UITypes.Number,
UITypes.Decimal,
UITypes.Rating,
UITypes.Rollup,
];
export function isNumericCol(
col:
| UITypes
| { readonly uidt: UITypes | string }
| ColumnReqType
| ColumnType
) {
return numericUITypes.includes(
<UITypes>(typeof col === 'object' ? col?.uidt : col)
);
}
export function isVirtualCol( export function isVirtualCol(
col: col:
| UITypes | UITypes

6
packages/nocodb/Dockerfile

@ -31,9 +31,9 @@ COPY ./package*.json ./
COPY ./docker/main.js ./docker/main.js COPY ./docker/main.js ./docker/main.js
#COPY ./docker/start.sh /usr/src/appEntry/start.sh #COPY ./docker/start.sh /usr/src/appEntry/start.sh
COPY ./docker/start-litestream.sh /usr/src/appEntry/start.sh COPY ./docker/start-litestream.sh /usr/src/appEntry/start.sh
COPY ./src/lib/public/css/*.css /usr/src/appEntry/public/css/ COPY ./src/lib/public/css/*.css ./docker/public/css/
COPY ./src/lib/public/js/*.js /usr/src/appEntry/public/js/ COPY ./src/lib/public/js/*.js ./docker/public/js/
COPY ./src/lib/public/favicon.ico /usr/src/appEntry/public/ COPY ./src/lib/public/favicon.ico ./docker/public/
# install production dependencies, # install production dependencies,
# reduce node_module size with modclean & removing sqlite deps, # reduce node_module size with modclean & removing sqlite deps,

7
packages/nocodb/docker/index.js

@ -10,10 +10,7 @@ server.set('view engine', 'ejs');
(async () => { (async () => {
const httpServer = server.listen(process.env.PORT || 8080, () => { const httpServer = server.listen(process.env.PORT || 8080, async () => {
console.log(`App started successfully.\nVisit -> ${Noco.dashboardUrl}`); server.use(await Noco.init({}, httpServer, server));
}) })
server.use(await Noco.init({}, httpServer, server));
})().catch(e => console.log(e)) })().catch(e => console.log(e))

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

Loading…
Cancel
Save