Browse Source

Merge pull request #5175 from nocodb/develop

pull/5176/head 0.105.3
github-actions[bot] 2 years ago committed by GitHub
parent
commit
b37acb2dbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      packages/nc-gui/components/dashboard/settings/AuditTab.vue
  2. 35
      packages/nc-gui/components/virtual-cell/components/ListItems.vue
  3. 1
      packages/nc-gui/composables/useGlobal/state.ts
  4. 1
      packages/nc-gui/composables/useGlobal/types.ts
  5. 6
      packages/nc-gui/lang/ar.json
  6. 6
      packages/nc-gui/lang/bn_IN.json
  7. 6
      packages/nc-gui/lang/cs.json
  8. 6
      packages/nc-gui/lang/da.json
  9. 6
      packages/nc-gui/lang/de.json
  10. 6
      packages/nc-gui/lang/es.json
  11. 6
      packages/nc-gui/lang/eu.json
  12. 6
      packages/nc-gui/lang/fa.json
  13. 6
      packages/nc-gui/lang/fi.json
  14. 6
      packages/nc-gui/lang/fr.json
  15. 6
      packages/nc-gui/lang/he.json
  16. 6
      packages/nc-gui/lang/hi.json
  17. 6
      packages/nc-gui/lang/hr.json
  18. 6
      packages/nc-gui/lang/id.json
  19. 6
      packages/nc-gui/lang/it.json
  20. 6
      packages/nc-gui/lang/ja.json
  21. 6
      packages/nc-gui/lang/ko.json
  22. 6
      packages/nc-gui/lang/lv.json
  23. 6
      packages/nc-gui/lang/nl.json
  24. 6
      packages/nc-gui/lang/no.json
  25. 6
      packages/nc-gui/lang/pl.json
  26. 6
      packages/nc-gui/lang/pt.json
  27. 6
      packages/nc-gui/lang/pt_BR.json
  28. 6
      packages/nc-gui/lang/ru.json
  29. 6
      packages/nc-gui/lang/sk.json
  30. 6
      packages/nc-gui/lang/sl.json
  31. 6
      packages/nc-gui/lang/sv.json
  32. 6
      packages/nc-gui/lang/th.json
  33. 6
      packages/nc-gui/lang/tr.json
  34. 6
      packages/nc-gui/lang/uk.json
  35. 6
      packages/nc-gui/lang/vi.json
  36. 6
      packages/nc-gui/lang/zh-Hans.json
  37. 6
      packages/nc-gui/lang/zh-Hant.json
  38. 1
      packages/nc-gui/lib/constants.ts
  39. 52
      packages/nc-gui/package-lock.json
  40. 2
      packages/nc-gui/package.json
  41. 16
      packages/noco-docs/content/en/FAQs.md
  42. 18
      packages/noco-docs/content/en/developer-resources/accessing-apis.md
  43. 103
      packages/noco-docs/content/en/getting-started/environment-variables.md
  44. 12
      packages/noco-docs/content/en/index.md
  45. 10
      packages/noco-docs/content/en/setup-and-usages/account-settings.md
  46. 22
      packages/noco-docs/content/en/setup-and-usages/app-store.md
  47. 4
      packages/noco-docs/content/en/setup-and-usages/audit.md
  48. 11
      packages/noco-docs/content/en/setup-and-usages/dashboard.md
  49. 46
      packages/noco-docs/content/en/setup-and-usages/meta-management.md
  50. 6
      packages/noco-docs/content/en/setup-and-usages/project-settings.md
  51. 10
      packages/noco-docs/content/en/setup-and-usages/sync-schema.md
  52. 38
      packages/noco-docs/content/en/setup-and-usages/team-and-auth.md
  53. 4
      packages/nocodb-sdk/package-lock.json
  54. 2
      packages/nocodb-sdk/src/lib/Api.ts
  55. 30
      packages/nocodb/package-lock.json
  56. 4
      packages/nocodb/package.json
  57. 2
      packages/nocodb/src/lib/Noco.ts
  58. 2
      packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts
  59. 19
      packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts
  60. 2
      packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2.ts
  61. 2
      packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2Trans.ts
  62. 7
      packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts
  63. 18
      packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2Tans.ts
  64. 2
      packages/nocodb/src/lib/meta/NcMetaMgr.ts
  65. 55
      packages/nocodb/src/lib/meta/api/attachmentApis.ts
  66. 13
      packages/nocodb/src/lib/meta/api/helpers/cacheHelpers.ts
  67. 1
      packages/nocodb/src/lib/meta/api/helpers/index.ts
  68. 2
      packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts
  69. 3
      packages/nocodb/src/lib/meta/api/utilApis.ts
  70. 28
      packages/nocodb/src/lib/meta/helpers/mapDefaultDisplayValue.ts
  71. 41
      packages/nocodb/src/lib/models/Audit.ts
  72. 15
      packages/nocodb/src/lib/models/BarcodeColumn.ts
  73. 139
      packages/nocodb/src/lib/models/Column.ts
  74. 43
      packages/nocodb/src/lib/models/Filter.ts
  75. 93
      packages/nocodb/src/lib/models/FormView.ts
  76. 53
      packages/nocodb/src/lib/models/FormViewColumn.ts
  77. 17
      packages/nocodb/src/lib/models/FormulaColumn.ts
  78. 65
      packages/nocodb/src/lib/models/GalleryView.ts
  79. 23
      packages/nocodb/src/lib/models/GalleryViewColumn.ts
  80. 37
      packages/nocodb/src/lib/models/GridView.ts
  81. 25
      packages/nocodb/src/lib/models/GridViewColumn.ts
  82. 120
      packages/nocodb/src/lib/models/Hook.ts
  83. 43
      packages/nocodb/src/lib/models/HookFilter.ts
  84. 40
      packages/nocodb/src/lib/models/KanbanView.ts
  85. 23
      packages/nocodb/src/lib/models/KanbanViewColumn.ts
  86. 38
      packages/nocodb/src/lib/models/LinkToAnotherRecordColumn.ts
  87. 14
      packages/nocodb/src/lib/models/LookupColumn.ts
  88. 52
      packages/nocodb/src/lib/models/Model.ts
  89. 21
      packages/nocodb/src/lib/models/ModelRoleVisibility.ts
  90. 14
      packages/nocodb/src/lib/models/Plugin.ts
  91. 24
      packages/nocodb/src/lib/models/Project.ts
  92. 17
      packages/nocodb/src/lib/models/ProjectUser.ts
  93. 14
      packages/nocodb/src/lib/models/QrCodeColumn.ts
  94. 14
      packages/nocodb/src/lib/models/RollupColumn.ts
  95. 11
      packages/nocodb/src/lib/models/SelectOption.ts
  96. 24
      packages/nocodb/src/lib/models/Sort.ts
  97. 15
      packages/nocodb/src/lib/models/SyncLogs.ts
  98. 18
      packages/nocodb/src/lib/models/SyncSource.ts
  99. 34
      packages/nocodb/src/lib/models/View.ts
  100. 2
      packages/nocodb/src/lib/utils/common/BaseApiBuilder.ts
  101. Some files were not shown because too many files have changed in this diff Show More

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

@ -1,7 +1,7 @@
<script setup lang="ts">
import { Tooltip as ATooltip, Empty } from 'ant-design-vue'
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()
@ -16,8 +16,11 @@ let audits = $ref<null | Array<AuditType>>(null)
let totalRows = $ref(0)
const currentPage = $ref(1)
const currentLimit = $ref(25)
const { appInfo } = useGlobal()
async function loadAudits(page = currentPage, limit = currentLimit) {
try {
if (!project.value?.id) return
@ -86,9 +89,10 @@ const columns = [
<template>
<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">
<a-button class="self-start" @click="loadAudits">
<!-- Reload -->
<!-- Reload -->
<div class="flex items-center gap-2 text-gray-600 font-light">
<MdiReload :class="{ 'animate-infinite animate-spin !text-success': isLoading }" />

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

@ -48,14 +48,20 @@ const saveRow = inject(SaveRowInj, () => {})
const selectedRowIndex = ref(0)
const isAltKeyDown = ref(false)
const linkRow = async (row: Record<string, any>) => {
if (isNew.value) {
addLTARRef(row, column?.value as ColumnType)
saveRow()
saveRow!()
} else {
await link(row)
}
vModel.value = false
if (isAltKeyDown.value) {
loadChildrenExcludedList()
} else {
vModel.value = false
}
}
/** reload list on modal open */
@ -159,6 +165,27 @@ useSelectedCellKeyupListener(vModel, (e: KeyboardEvent) => {
const activeRow = (vNode?: InstanceType<typeof Card>) => {
vNode?.$el?.scrollIntoView({ block: 'nearest', inline: 'nearest' })
}
// set variable to true when alt key is pressed
const keyDownHandler = (e: KeyboardEvent) => {
isAltKeyDown.value = e.altKey
}
// set variable to false when key is released
const keyUpHandler = (e: KeyboardEvent) => {
isAltKeyDown.value = e.altKey
}
// add event listeners when vModel is true and remove when false
watch(vModel, (nextVal) => {
if (nextVal) {
document.addEventListener('keydown', keyDownHandler)
document.addEventListener('keyup', keyUpHandler)
} else {
document.removeEventListener('keydown', keyDownHandler)
document.removeEventListener('keyup', keyUpHandler)
}
})
</script>
<template>
@ -219,6 +246,10 @@ const activeRow = (vNode?: InstanceType<typeof Card>) => {
show-less-items
/>
</div>
<div class="text-xs text-gray-400 text-center px-2 mt-4 pb-0">
* Use <kbd>ALT</kbd> / <kbd>OPT</kbd> + <kbd>Click</kbd> to select multiple records
</div>
</template>
<a-empty v-else class="my-10" :image="Empty.PRESENTED_IMAGE_SIMPLE" />

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

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

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

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

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

@ -380,6 +380,7 @@
"renameTable": "إعادة تسمية الجدول",
"deleteTable": "حذف الجدول",
"addField": "إضافة حقل جديد إلى هذا الجدول",
"setDisplay": "Set as Display value",
"addRow": "إضافة صف جديد",
"saveRow": "حفظ الصف",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "هل أنت متأكد من أنك تريد حذف هذا العرض؟",
"deleteTableConfirmation": "هل تريد حذف الجدول",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "টিল নম পরিবরতন",
"deleteTable": "टबल मि",
"addField": "এই টি নতন কর যত করন",
"setDisplay": "Set as Display value",
"addRow": "নতন সিত করন",
"saveRow": "সিরকষণ করন",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "Přejmenování tabulky",
"deleteTable": "Tabulka Odstranit",
"addField": "Přidání nového pole do této tabulky",
"setDisplay": "Set as Display value",
"addRow": "Přidat nový řádek",
"saveRow": "Uložit řádek",
"saveAndExit": "Uložit a odejít",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Opravdu chcete toto zobrazení odstranit?",
"deleteTableConfirmation": "Chcete odstranit tabulku",
"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ů.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Bord omdøb",
"deleteTable": "TABEL DELETE.",
"addField": "Tilføj nyt felt til denne tabel",
"setDisplay": "Set as Display value",
"addRow": "Tilføj ny række",
"saveRow": "Gem ro",
"saveAndExit": "Gem og afslutning",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Er du sikker på, at du vil slette denne visning?",
"deleteTableConfirmation": "Ønsker du at slette tabellen",
"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\".",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Tabelle umbenennen",
"deleteTable": "Tabelle löschen",
"addField": "Neues Feld zu dieser Tabelle hinzufügen",
"setDisplay": "Set as Display value",
"addRow": "Neue Zeile hinzufügen",
"saveRow": "Zeile speichern",
"saveAndExit": "Speichern & Verlassen",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Sind Sie sicher, dass Sie diese Ansicht löschen möchten?",
"deleteTableConfirmation": "Möchten Sie die Tabelle löschen",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Cambiar el nombre de la tabla",
"deleteTable": "Borrar tabla",
"addField": "Añadir nuevo campo a esta tabla",
"setDisplay": "Set as Display value",
"addRow": "Añadir nueva fila",
"saveRow": "Grabar la fila",
"saveAndExit": "Guardar y salir",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "¿Está seguro de que desea eliminar esta vista?",
"deleteTableConfirmation": "¿Desea eliminar la tabla",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Table Rename",
"deleteTable": "Table Delete",
"addField": "Add new field to this table",
"setDisplay": "Set as Display value",
"addRow": "Add new row",
"saveRow": "Save row",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "تغییر نام جدول",
"deleteTable": "حذف جدول",
"addField": "اضافه کردن فیلد جدید به این جدول",
"setDisplay": "Set as Display value",
"addRow": "اضافه کردن ردیف جدید",
"saveRow": "دخیره ردیف",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "Taulukko uudelleen",
"deleteTable": "Taulukko poistaa",
"addField": "Lisää uusi kenttä tähän taulukkoon",
"setDisplay": "Set as Display value",
"addRow": "Lisää uusi rivi",
"saveRow": "Tallenna rivi",
"saveAndExit": "Tallenna & poistu",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Haluatko varmasti poistaa tämän näkymän?",
"deleteTableConfirmation": "Haluatko poistaa taulukon",
"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.",
"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ää.",

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

@ -380,6 +380,7 @@
"renameTable": "Renommer le tableau",
"deleteTable": "Supprimer le tableau",
"addField": "Ajouter un nouveau champ à ce tableau",
"setDisplay": "Set as Display value",
"addRow": "Ajouter une nouvelle ligne",
"saveRow": "Enregistrer la ligne",
"saveAndExit": "Enregistrer et quitter",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Êtes-vous sûr de vouloir effacer cette vue ?",
"deleteTableConfirmation": "Voulez-vous supprimer ce tableau",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "שולחן שינוי שם",
"deleteTable": "טבלה מחיקה",
"addField": "הוסף שדה חדש לטבלה זו",
"setDisplay": "Set as Display value",
"addRow": "הוסף שורה חדשה",
"saveRow": "שמור שורה",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "तिम",
"deleteTable": "टबल मि",
"addField": "इस ति नयड ज",
"setDisplay": "Set as Display value",
"addRow": "नई पि",
"saveRow": "पि सह",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "Preimenovati stolom",
"deleteTable": "Obriši tablicu",
"addField": "Dodajte novo polje na ovu tablicu",
"setDisplay": "Set as Display value",
"addRow": "Dodaj novi red",
"saveRow": "Spremanje retka",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "Ganti nama meja",
"deleteTable": "Table Delete.",
"addField": "Tambahkan bidang baru ke tabel ini",
"setDisplay": "Set as Display value",
"addRow": "Tambahkan baris baru",
"saveRow": "Hemat Baris",
"saveAndExit": "Simpan & Keluar",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Apakah Anda yakin ingin menghapus tampilan ini?",
"deleteTableConfirmation": "Apakah Anda ingin menghapus tabel",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Rinomina tabella",
"deleteTable": "Elimina tabella",
"addField": "Aggiungi un nuovo campo a questa tabella",
"setDisplay": "Set as Display value",
"addRow": "Aggiungi nuova riga",
"saveRow": "Salva riga",
"saveAndExit": "Salvare e uscire",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "È sicuro di voler eliminare questa vista?",
"deleteTableConfirmation": "Vuole eliminare la tabella",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "テーブル名の変更",
"deleteTable": "テーブルを削除",
"addField": "新しいフィールドを追加",
"setDisplay": "Set as Display value",
"addRow": "行を追加",
"saveRow": "行を保存",
"saveAndExit": "保存して終了",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "このビューを本当に削除しますか?",
"deleteTableConfirmation": "テーブルを削除しますか?",
"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}`も削除されます。レコードは未分類スタックに移動します。",
"computedFieldEditWarning": "計算フィールド: コンテンツは読み取り専用です。列編集メニューを使用して再設定してください。",
"computedFieldDeleteWarning": "計算フィールド: コンテンツは読み取り専用です。コンテンツを消去できません。",

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

@ -380,6 +380,7 @@
"renameTable": "테이블 이름 바꾸기",
"deleteTable": "테이블 삭제",
"addField": "테이블에 새 필드 추가",
"setDisplay": "Set as Display value",
"addRow": "행 추가",
"saveRow": "행 저장",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "Tabulas pārdēvēšana",
"deleteTable": "Tabulas dzēšana",
"addField": "Jauna lauka pievienošana",
"setDisplay": "Set as Display value",
"addRow": "Pievienot ierakstu",
"saveRow": "Saglabāt ierakstu",
"saveAndExit": "Saglabāt un iziet",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Vai esat pārliecināts, ka vēlaties dzēst šo skatījumu?",
"deleteTableConfirmation": "Vai vēlaties izdzēst tabulu",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Tabel hernoemen",
"deleteTable": "Tabel verwijderen",
"addField": "Voeg nieuw veld toe aan deze tabel",
"setDisplay": "Set as Display value",
"addRow": "Nieuwe rij toevoegen",
"saveRow": "Sla rij op",
"saveAndExit": "Opslaan en afsluiten",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Weet u zeker dat u deze weergave wilt verwijderen?",
"deleteTableConfirmation": "Wilt u de tabel verwijderen",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Tabell omdøpe",
"deleteTable": "Bordet slett",
"addField": "Legg til nytt felt i denne tabellen",
"setDisplay": "Set as Display value",
"addRow": "Legg til ny rad",
"saveRow": "Lagre rad",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "Zmień nazwę tabeli.",
"deleteTable": "Usuń tabelę",
"addField": "Dodaj nowe pole do tej tabeli",
"setDisplay": "Set as Display value",
"addRow": "Dodaj nowy rząd",
"saveRow": "Zapisz wiersz",
"saveAndExit": "Zapisz i wyjdź",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Czy na pewno chcesz usunąć ten widok?",
"deleteTableConfirmation": "Czy chcesz usunąć tabelę",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Tabela Renomear",
"deleteTable": "Tabela Delete.",
"addField": "Adicionar novo campo a esta tabela",
"setDisplay": "Set as Display value",
"addRow": "Adicionar nova linha",
"saveRow": "Salvar linha",
"saveAndExit": "Salvar & Sair",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Tem a certeza de que quer apagar esta vista?",
"deleteTableConfirmation": "Deseja apagar a tabela",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Tabela Renomear",
"deleteTable": "Tabela Delete.",
"addField": "Adicionar novo campo a esta tabela",
"setDisplay": "Set as Display value",
"addRow": "Adicionar nova linha",
"saveRow": "Salvar linha",
"saveAndExit": "Salvar & Sair",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Tem a certeza de que quer apagar esta vista?",
"deleteTableConfirmation": "Deseja apagar a tabela",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Переименовать таблицу",
"deleteTable": "Удалить таблицу",
"addField": "Добавить новое поле в эту таблицу",
"setDisplay": "Set as Display value",
"addRow": "Добавить новую строку",
"saveRow": "Сохранить строку",
"saveAndExit": "Сохранить и выйти",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Вы действительно хотите удалить это представление?",
"deleteTableConfirmation": "Вы действительно хотите удалить эту таблицу",
"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}`. Записи переместятся в стек без категории.",
"computedFieldEditWarning": "Вычисляемое поле: содержимое доступно только для чтения. Используйте меню редактирования столбцов для изменения конфигурации",
"computedFieldDeleteWarning": "Вычисляемое поле: содержимое доступно только для чтения. Невозможно очистить содержимое.",

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

@ -380,6 +380,7 @@
"renameTable": "Premenovanie tabuľky",
"deleteTable": "Tabuľka Vymazať",
"addField": "Pridanie nového poľa do tejto tabuľky",
"setDisplay": "Set as Display value",
"addRow": "Pridanie nového riadku",
"saveRow": "Uložiť riadok",
"saveAndExit": "Uložiť a ukončiť",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Ste si istí, že chcete toto zobrazenie odstrániť?",
"deleteTableConfirmation": "Chcete odstrániť tabuľku",
"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í.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Preimenuj tabele",
"deleteTable": "Tabela Delete.",
"addField": "V to tabelo dodajte novo polje",
"setDisplay": "Set as Display value",
"addRow": "Dodaj novo vrstico",
"saveRow": "Shrani vrstico",
"saveAndExit": "Shranjevanje in izhod",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Ste prepričani, da želite izbrisati ta pogled?",
"deleteTableConfirmation": "Ali želite izbrisati tabelo",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Bordsbyte",
"deleteTable": "Bord radera",
"addField": "Lägg till nytt fält till den här tabellen",
"setDisplay": "Set as Display value",
"addRow": "Lägg till ny rad",
"saveRow": "Spara rad",
"saveAndExit": "Spara och avsluta",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Är du säker på att du vill ta bort den här vyn?",
"deleteTableConfirmation": "Vill du radera tabellen?",
"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\".",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "ตารางเปลยนชอ",
"deleteTable": "ลบตาราง",
"addField": "เพมฟลดใหมลงในตารางน",
"setDisplay": "Set as Display value",
"addRow": "เพมแถวใหม",
"saveRow": "บนทกแถว",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "Tabloyu Yeniden Adlandır",
"deleteTable": "Tabloyu Sil",
"addField": "Tabloya yeni alan ekle",
"setDisplay": "Set as Display value",
"addRow": "Yeni satır ekle",
"saveRow": "Satırı kaydet",
"saveAndExit": "Kaydet ve Çık",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Bu görünümü silmek istediğinizden emin misiniz?",
"deleteTableConfirmation": "Tabloyu silmek istiyor musunuz",
"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.",
"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.",

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

@ -380,6 +380,7 @@
"renameTable": "Перейменувати таблицю",
"deleteTable": "Видалити таблицю",
"addField": "Додати нове поле до цієї таблиці",
"setDisplay": "Set as Display value",
"addRow": "Додати новий рядок",
"saveRow": "Зберегти рядок",
"saveAndExit": "Зберегти та вийти",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Ви впевнені, що хочете видалити цей вигляд?",
"deleteTableConfirmation": "Ви хочете видалити таблицю",
"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}`. Записи буде переміщено до не категоризованого стека.",
"computedFieldEditWarning": "Обчислюване поле: вміст доступний лише для читання. Використовуйте меню редагування стовпця для зміни конфігурації",
"computedFieldDeleteWarning": "Обчислюване поле: вміст доступний лише для читання. Не вдалося очистити вміст.",

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

@ -380,6 +380,7 @@
"renameTable": "Đổi tên bảng.",
"deleteTable": "Bảng xóa",
"addField": "Thêm trường mới vào bảng này",
"setDisplay": "Set as Display value",
"addRow": "Thêm hàng mới",
"saveRow": "Lưu hàng.",
"saveAndExit": "Save & Exit",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "Are you sure you want to delete this view?",
"deleteTableConfirmation": "Do you want to delete the table",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "重命名表格",
"deleteTable": "删除表格",
"addField": "添加新字段",
"setDisplay": "Set as Display value",
"addRow": "添加新行",
"saveRow": "保存行",
"saveAndExit": "保存并退出",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "您确定要删除此视图?",
"deleteTableConfirmation": "您想要删除该表吗?",
"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}\"。这类记录将移到未分类的类别中。",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

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

@ -380,6 +380,7 @@
"renameTable": "表重命名",
"deleteTable": "表刪除",
"addField": "將新字段添加到此表",
"setDisplay": "Set as Display value",
"addRow": "新增行",
"saveRow": "儲存行",
"saveAndExit": "儲存並結束",
@ -630,6 +631,11 @@
"deleteViewConfirmation": "是否確定要刪除此檢視?",
"deleteTableConfirmation": "你想刪除此資料表",
"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.",
"computedFieldEditWarning": "Computed field: contents are read-only. Use column edit menu to reconfigure",
"computedFieldDeleteWarning": "Computed field: contents are read-only. Unable to clear content.",

1
packages/nc-gui/lib/constants.ts

@ -57,6 +57,7 @@ export const rolePermissions = {
fieldsSync: true,
gridColUpdate: true,
filterSync: true,
filterChildrenRead: true,
csvImport: true,
apiDocs: true,
projectSettings: true,

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

@ -29,7 +29,7 @@
"jwt-decode": "^3.1.2",
"locale-codes": "^1.3.1",
"monaco-editor": "^0.33.0",
"nocodb-sdk": "0.105.2",
"nocodb-sdk": "file:../nocodb-sdk",
"papaparse": "^5.3.2",
"qrcode": "^1.5.1",
"socket.io-client": "^4.5.1",
@ -98,7 +98,6 @@
},
"../nocodb-sdk": {
"version": "0.105.2",
"extraneous": true,
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
@ -8555,6 +8554,7 @@
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true,
"funding": [
{
"type": "individual",
@ -11970,21 +11970,8 @@
}
},
"node_modules/nocodb-sdk": {
"version": "0.105.2",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.105.2.tgz",
"integrity": "sha512-Mvk8JKgDT53aVYJbA6FwGlZyDOpVKmmrPUPopXeTL4wfiztkGD2/roUq+3pt6x9/STkOTdsUI5R1D4Kjle7XSA==",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
}
},
"node_modules/nocodb-sdk/node_modules/axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.14.0"
}
"resolved": "../nocodb-sdk",
"link": true
},
"node_modules/node-abi": {
"version": "3.23.0",
@ -23975,7 +23962,8 @@
"follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true
},
"form-data": {
"version": "4.0.0",
@ -26448,22 +26436,22 @@
}
},
"nocodb-sdk": {
"version": "0.105.2",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.105.2.tgz",
"integrity": "sha512-Mvk8JKgDT53aVYJbA6FwGlZyDOpVKmmrPUPopXeTL4wfiztkGD2/roUq+3pt6x9/STkOTdsUI5R1D4Kjle7XSA==",
"version": "file:../nocodb-sdk",
"requires": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"axios": "^0.21.1",
"jsep": "^1.3.6"
},
"dependencies": {
"axios": {
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"requires": {
"follow-redirects": "^1.14.0"
}
}
"cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
}
},
"node-abi": {

2
packages/nc-gui/package.json

@ -52,7 +52,7 @@
"jwt-decode": "^3.1.2",
"locale-codes": "^1.3.1",
"monaco-editor": "^0.33.0",
"nocodb-sdk": "0.105.2",
"nocodb-sdk": "file:../nocodb-sdk",
"papaparse": "^5.3.2",
"qrcode": "^1.5.1",
"socket.io-client": "^4.5.1",

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`.
## 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
- SSO, SLA, Organisation wide reports and analytics,
- 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.
## 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
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
![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
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.
## Swagger UI

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_REDIS_URL`
| 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_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 | | |
| 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. | | |
| 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` | |
| DB_QUERY_LIMIT_DEFAULT | Default pagination limit | 25 | |
| DB_QUERY_LIMIT_MAX | Maximum allowed pagination limit | 1000 | |
| 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_PUBLIC_URL | Used for sending Email invitations | Best guess from http request params | |
| NC_JWT_EXPIRES_IN | JWT token expiry time | `10h` | |
| 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. | | |
| 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_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_DASHBOARD_URL | Custom dashboard url path | `/dashboard` | |
| NC_GOOGLE_CLIENT_ID | Google client id to enable google authentication | | |
| NC_GOOGLE_CLIENT_SECRET | Google client secret to enable google authentication | | |
| 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_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_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_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_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_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_HOST | For SMTP plugin - SMTP host value | | |
| NC_SMTP_PORT | For SMTP plugin - SMTP port value | | |
| 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_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_S3_BUCKET_NAME | For S3 storage plugin - AWS S3 bucket name | | |
| 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_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_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 $&+,:;=?@#\|'.^*()%!_-" ) | | |
| 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) | | |
| 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_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 | | |
| 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. | | |
| 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` | |
| DB_QUERY_LIMIT_DEFAULT | Default pagination limit | 25 | |
| DB_QUERY_LIMIT_MAX | Maximum allowed pagination limit | 1000 | |
| 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_PUBLIC_URL | Used for sending Email invitations | Best guess from http request params | |
| NC_JWT_EXPIRES_IN | JWT token expiry time | `10h` | |
| 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. | | |
| 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_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_DASHBOARD_URL | Custom dashboard url path | `/dashboard` | |
| NC_GOOGLE_CLIENT_ID | Google client id to enable google authentication | | |
| NC_GOOGLE_CLIENT_SECRET | Google client secret to enable google authentication | | |
| 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_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_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_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_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_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_HOST | For SMTP plugin - SMTP host value | | |
| NC_SMTP_PORT | For SMTP plugin - SMTP port value | | |
| 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_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_S3_BUCKET_NAME | For S3 storage plugin - AWS S3 bucket name | | |
| 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_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_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 $&+,:;=?@#\|'.^*()%!_-" ) | | |
| 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_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.
<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
You can also manage the app store plugins here.
![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
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`.
<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">
Then, under SETTINGS, click `Audit`.

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">
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>
<!-- <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)
Above menu is also accessible from `Team & Settings` > `Data Sources`. Click on `New` button to add existing database.
![Screenshot 2022-12-29 at 3 16 36 PM](https://user-images.githubusercontent.com/86527202/209936942-f82a293f-2e91-48da-b9cd-79ec143d7d6f.png)
![image](https://user-images.githubusercontent.com/35857179/219841162-6456c5cf-fd26-4a88-8de6-e8742c043607.png)
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.

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

@ -6,6 +6,8 @@ category: 'Product'
menuTitle: 'Team & Settings > Data Sources'
---
## Overview
`Data Sources` sub-menu includes
- Database Metadata
- UI Access Control
@ -14,46 +16,33 @@ menuTitle: 'Team & Settings > Data Sources'
- Edit existing data source configuration
- Edit data source visibility options
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`.
<!-- ![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)
## Accessing Data Sources
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/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)
<img width="322" alt="image" src="https://user-images.githubusercontent.com/35857179/194856648-67936db0-ee4d-4060-be3d-af9f86ef8fc6.png">
![image](https://user-images.githubusercontent.com/35857179/219833316-1fb234f0-583f-4ab8-b8d7-a6e249e7cd97.png)
## 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
![Screenshot 2022-12-29 at 4 19 35 PM](https://user-images.githubusercontent.com/86527202/209940903-396650b4-e219-494a-863f-c3f1beb51c5e.png)
<!-- <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/219833485-3bcaa6ec-88bc-47cc-b938-5abb4835dc31.png)
## UI Access Control
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"> -->
![Screenshot 2022-12-29 at 4 20 57 PM](https://user-images.githubusercontent.com/86527202/209941141-deed80a9-7682-48e1-8de9-9c965c990d2d.png)
![image](https://user-images.githubusercontent.com/35857179/219833072-20e9f4ad-fd1c-4e96-9112-6edda1447ec6.png)
## ERD
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)
<!-- <img width="1338" alt="image" src="https://user-images.githubusercontent.com/35857179/194850416-54bc49cf-c32f-45e8-aea1-62b07645c26e.png"> -->
![image](https://user-images.githubusercontent.com/35857179/219832288-f6266544-a259-4667-95d9-0e5ce7ac5d27.png)
### 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.
- 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
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!
![Screenshot 2022-12-29 at 4 22 08 PM](https://user-images.githubusercontent.com/86527202/209941211-de9670c9-a73c-4719-9957-eeaf05f3a7ee.png)
![image](https://user-images.githubusercontent.com/35857179/219832592-14209cbf-d980-4e14-9a59-bda1b778a74e.png)
## Unlink data source
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
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)
<!-- ## 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">
-->
![image](https://user-images.githubusercontent.com/35857179/219832914-f485099c-423f-4df8-bf00-b509288efe6d.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`.
## Miscellaneous
- 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)
![image](https://user-images.githubusercontent.com/35857179/219830971-9518fa21-a45c-4d49-af3f-2f933d779ecd.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">
### 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`
- If changes made to the database are not visible, click `Reload`
- Identified schema changes are identified for each table in `red`
- `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/161957119-f66f22ad-9d37-45ed-84ca-35c99726078c.png) -->
![image](https://user-images.githubusercontent.com/35857179/219831855-bcac229c-41b6-4689-b7e1-c3cdfe23a0a1.png)
### 4. Click `Sync Now` to complete Schema sync procedure

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

@ -6,18 +6,21 @@ category: 'Product'
menuTitle: 'Team & Settings > Team & Auth'
---
# Accessing Team & Auth
## Accessing Team & Auth
- Click on `Team & Settings` from the `Project Menu`
- Access `Team & Auth` under `Settings`
<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`
<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`.
@ -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)
## How to Update user permissions
### How to Update user permissions
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
![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
| &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 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 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: -->
<!-- ### 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;|
| :-- | :-: | :-: | :-: | :-: | :-: |
-->
-->

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

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

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

@ -502,7 +502,7 @@ export interface HookType {
description?: string;
env?: string;
type?: string;
event?: 'After' | 'Before';
event?: 'after' | 'before';
operation?: 'insert' | 'delete' | 'update';
async?: boolean;
payload?: string;

30
packages/nocodb/package-lock.json generated

@ -68,7 +68,7 @@
"nc-lib-gui": "0.105.2",
"nc-plugin": "0.1.2",
"ncp": "^2.0.0",
"nocodb-sdk": "0.105.2",
"nocodb-sdk": "file:../nocodb-sdk",
"nodemailer": "^6.4.10",
"object-hash": "^3.0.0",
"os-locale": "^5.0.0",
@ -155,7 +155,6 @@
},
"../nocodb-sdk": {
"version": "0.105.2",
"extraneous": true,
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
@ -11319,13 +11318,8 @@
"dev": true
},
"node_modules/nocodb-sdk": {
"version": "0.105.2",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.105.2.tgz",
"integrity": "sha512-Mvk8JKgDT53aVYJbA6FwGlZyDOpVKmmrPUPopXeTL4wfiztkGD2/roUq+3pt6x9/STkOTdsUI5R1D4Kjle7XSA==",
"dependencies": {
"axios": "^0.21.1",
"jsep": "^1.3.6"
}
"resolved": "../nocodb-sdk",
"link": true
},
"node_modules/node-abort-controller": {
"version": "3.0.1",
@ -27930,12 +27924,22 @@
"dev": true
},
"nocodb-sdk": {
"version": "0.105.2",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.105.2.tgz",
"integrity": "sha512-Mvk8JKgDT53aVYJbA6FwGlZyDOpVKmmrPUPopXeTL4wfiztkGD2/roUq+3pt6x9/STkOTdsUI5R1D4Kjle7XSA==",
"version": "file:../nocodb-sdk",
"requires": {
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"axios": "^0.21.1",
"jsep": "^1.3.6"
"cspell": "^4.1.0",
"eslint": "^7.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-functional": "^3.0.2",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^4.0.0",
"jsep": "^1.3.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"typescript": "^4.0.2"
}
},
"node-abort-controller": {

4
packages/nocodb/package.json

@ -108,7 +108,7 @@
"nc-lib-gui": "0.105.2",
"nc-plugin": "0.1.2",
"ncp": "^2.0.0",
"nocodb-sdk": "0.105.2",
"nocodb-sdk": "file:../nocodb-sdk",
"nodemailer": "^6.4.10",
"object-hash": "^3.0.0",
"os-locale": "^5.0.0",
@ -184,4 +184,4 @@
"prettier": {
"singleQuote": true
}
}
}

2
packages/nocodb/src/lib/Noco.ts

@ -105,7 +105,7 @@ export default class Noco {
constructor() {
process.env.PORT = process.env.PORT || '8080';
// todo: move
process.env.NC_VERSION = '0104004';
process.env.NC_VERSION = '0105002';
// if env variable NC_MINIMAL_DBS is set, then disable project creation with external sources
if (process.env.NC_MINIMAL_DBS) {

2
packages/nocodb/src/lib/db/sql-client/lib/oracle/OracleClient.ts

@ -1913,7 +1913,7 @@ class OracleClient extends KnexClient {
* @returns {Number} code
* @returns {String} message
*/
async totalRecords(_args: any = {}) {
async totalRecords(_args: any = {}): Promise<Result> {
// @ts-ignore
const func = this.totalRecords.name;
throw new Error('Function not supported for oracle yet');

19
packages/nocodb/src/lib/db/sql-mgr/SqlMgr.ts

@ -17,6 +17,14 @@ import NcConnectionMgr from '../../utils/common/NcConnectionMgr';
import { customAlphabet } from 'nanoid';
import Debug from '../util/Debug';
import Result from '../util/Result';
import type MssqlClient from '../sql-client/lib/mssql/MssqlClient';
import type MysqlClient from '../sql-client/lib/mysql/MysqlClient';
import type OracleClient from '../sql-client/lib/oracle/OracleClient';
import type PGClient from '../sql-client/lib/pg/PgClient';
import type SnowflakeClient from '../sql-client/lib/snowflake/SnowflakeClient';
import type SqliteClient from '../sql-client/lib/sqlite/SqliteClient';
const randomID = customAlphabet('1234567890abcdefghijklmnopqrstuvwxyz_', 20);
const log = new Debug('SqlMgr');
@ -337,7 +345,16 @@ export default class SqlMgr {
* @returns
* @memberof SqlMgr
*/
public async projectGetSqlClient(args) {
public async projectGetSqlClient(
args
): Promise<
| SnowflakeClient
| MysqlClient
| SqliteClient
| MssqlClient
| OracleClient
| PGClient
> {
const func = this.projectGetSqlClient.name;
log.api(`${func}:args:`, args);

2
packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2.ts

@ -118,7 +118,7 @@ export default class SqlMgrv2 {
return sqlMigrationStatements;
}
protected async getSqlClient(base: Base): Promise<any> {
protected async getSqlClient(base: Base) {
return NcConnectionMgrv2.getSqlClient(base);
}
}

2
packages/nocodb/src/lib/db/sql-mgr/v2/SqlMgrv2Trans.ts

@ -52,7 +52,7 @@ export default class SqlMgrv2Trans extends SqlMgrv2 {
}
}
protected async getSqlClient(base: Base): Promise<any> {
protected async getSqlClient(base: Base) {
return NcConnectionMgrv2.getSqlClient(base, this.trx);
}

7
packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2.ts

@ -1,6 +1,7 @@
import fs from 'fs';
import path from 'path';
import { promisify } from 'util';
import { Knex } from 'knex';
import glob from 'glob';
import SqlClientFactory from '../../sql-client/lib/SqlClientFactory';
@ -428,7 +429,7 @@ export default class KnexMigratorv2 {
// }
}
protected async getSqlClient(base: Base): Promise<any> {
protected async getSqlClient(base: Base) {
return NcConnectionMgrv2.getSqlClient(base);
}
@ -753,7 +754,7 @@ export default class KnexMigratorv2 {
const vm = this;
const trx = sqlClient.knex.isTransaction
? sqlClient.knex
? (sqlClient.knex as Knex.Transaction)
: await sqlClient.knex.transaction();
try {
for (const query of upStatements) {
@ -920,7 +921,7 @@ export default class KnexMigratorv2 {
const vm = this;
const trx = sqlClient.knex.isTransaction
? sqlClient.knex
? (sqlClient.knex as Knex.Transaction)
: await sqlClient.knex.transaction();
try {
for (const query of downStatements) {

18
packages/nocodb/src/lib/db/sql-migrator/lib/KnexMigratorv2Tans.ts

@ -11,6 +11,13 @@ import Noco from '../../../Noco';
import { XKnex } from '../../sql-data-mapper';
import NcMetaIO from '../../../meta/NcMetaIO';
import type MssqlClient from '../../sql-client/lib/mssql/MssqlClient';
import type MysqlClient from '../../sql-client/lib/mysql/MysqlClient';
import type OracleClient from '../../sql-client/lib/oracle/OracleClient';
import type PGClient from '../../sql-client/lib/pg/PgClient';
import type SnowflakeClient from '../../sql-client/lib/snowflake/SnowflakeClient';
import type SqliteClient from '../../sql-client/lib/sqlite/SqliteClient';
export default class KnexMigratorv2Tans extends KnexMigratorv2 {
protected sqlClient: any;
protected ncMeta: NcMetaIO;
@ -24,7 +31,16 @@ export default class KnexMigratorv2Tans extends KnexMigratorv2 {
protected get metaDb(): XKnex {
return this.ncMeta.knex || Noco.ncMeta.knex;
}
protected async getSqlClient(base: Base): Promise<any> {
protected async getSqlClient(
base: Base
): Promise<
| SnowflakeClient
| MysqlClient
| SqliteClient
| MssqlClient
| OracleClient
| PGClient
> {
return this.sqlClient || NcConnectionMgrv2.getSqlClient(base);
}
}

2
packages/nocodb/src/lib/meta/NcMetaMgr.ts

@ -2909,7 +2909,7 @@ export default class NcMetaMgr {
}
}
protected async projectGetSqlClient(args): Promise<any> {
protected async projectGetSqlClient(args) {
const builder = this.getBuilder(args);
return builder?.getSqlClient();
}

55
packages/nocodb/src/lib/meta/api/attachmentApis.ts

@ -14,6 +14,7 @@ import catchError, { NcError } from '../helpers/catchError';
import NcPluginMgrv2 from '../helpers/NcPluginMgrv2';
import Local from '../../v1-legacy/plugins/adapters/storage/Local';
import { NC_ATTACHMENT_FIELD_SIZE } from '../../constants';
import { getCacheMiddleware } from './helpers';
const isUploadAllowed = async (req: Request, _res: Response, next: any) => {
if (!req['user']?.id) {
@ -161,32 +162,36 @@ export async function fileRead(req, res) {
const router = Router({ mergeParams: true });
router.get(/^\/dl\/([^/]+)\/([^/]+)\/(.+)$/, async (req, res) => {
try {
// const type = mimetypes[path.extname(req.params.fileName).slice(1)] || 'text/plain';
const type =
mimetypes[path.extname(req.params[2]).split('/').pop().slice(1)] ||
'text/plain';
const storageAdapter = await NcPluginMgrv2.storageAdapter();
// const img = await this.storageAdapter.fileRead(slash(path.join('nc', req.params.projectId, req.params.dbAlias, 'uploads', req.params.fileName)));
const img = await storageAdapter.fileRead(
slash(
path.join(
'nc',
req.params[0],
req.params[1],
'uploads',
...req.params[2].split('/')
router.get(
/^\/dl\/([^/]+)\/([^/]+)\/(.+)$/,
getCacheMiddleware(),
async (req, res) => {
try {
// const type = mimetypes[path.extname(req.params.fileName).slice(1)] || 'text/plain';
const type =
mimetypes[path.extname(req.params[2]).split('/').pop().slice(1)] ||
'text/plain';
const storageAdapter = await NcPluginMgrv2.storageAdapter();
// const img = await this.storageAdapter.fileRead(slash(path.join('nc', req.params.projectId, req.params.dbAlias, 'uploads', req.params.fileName)));
const img = await storageAdapter.fileRead(
slash(
path.join(
'nc',
req.params[0],
req.params[1],
'uploads',
...req.params[2].split('/')
)
)
)
);
res.writeHead(200, { 'Content-Type': type });
res.end(img, 'binary');
} catch (e) {
res.status(404).send('Not found');
);
res.writeHead(200, { 'Content-Type': type });
res.end(img, 'binary');
} catch (e) {
res.status(404).send('Not found');
}
}
});
);
export function sanitizeUrlPath(paths) {
return paths.map((url) => url.replace(/[/.?#]+/g, '_'));
@ -217,6 +222,6 @@ router.post(
]
);
router.get(/^\/download\/(.+)$/, catchError(fileRead));
router.get(/^\/download\/(.+)$/, getCacheMiddleware(), catchError(fileRead));
export default router;

13
packages/nocodb/src/lib/meta/api/helpers/cacheHelpers.ts

@ -0,0 +1,13 @@
// return a middleware to set cache-control header
// default period is 30 days
export const getCacheMiddleware = (period: string | number = 2592000) => {
return async (req, res, next) => {
const { method } = req;
// only cache GET requests
if (method === 'GET') {
// set cache-control header
res.set('Cache-Control', `public, max-age=${period}`);
}
next();
};
};

1
packages/nocodb/src/lib/meta/api/helpers/index.ts

@ -1,5 +1,6 @@
import { populateMeta } from './populateMeta';
export * from './columnHelpers';
export * from './apiHelpers';
export * from './cacheHelpers';
export { populateMeta };

2
packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts

@ -229,6 +229,8 @@ export async function populateMeta(base: Base, project: Project): Promise<any> {
const columns = (await sqlClient.columnList({ tn: table.table_name }))
?.data?.list;
mapDefaultDisplayValue(columns);
/* create nc_models and its rows if it doesn't exists */
models2[table.table_name] = await Model.insert(project.id, base.id, {
table_name: table.table_name,

3
packages/nocodb/src/lib/meta/api/utilApis.ts

@ -53,7 +53,8 @@ export async function appInfo(req: Request, res: Response) {
),
timezone: defaultConnectionConfig.timezone,
ncMin: !!process.env.NC_MIN,
teleEnabled: !process.env.NC_DISABLE_TELE,
teleEnabled: process.env.NC_DISABLE_TELE === 'true' ? false : true,
auditEnabled: process.env.NC_DISABLE_AUDIT === 'true' ? false : true,
ncSiteUrl: (req as any).ncSiteUrl,
ee: Noco.isEE(),
ncAttachmentFieldSize: NC_ATTACHMENT_FIELD_SIZE,

28
packages/nocodb/src/lib/meta/helpers/mapDefaultDisplayValue.ts

@ -4,31 +4,27 @@ export default function mapDefaultDisplayValue<T extends ColumnType>(
columnsArr: Array<T>
): void | T {
if (!columnsArr.some((column) => column.pv)) {
let len = columnsArr.length;
let pkIndex = -1;
while (len--) {
if (columnsArr[len].pk) {
pkIndex = len;
break;
}
}
const pkIndex = columnsArr.findIndex((column) => column.pk);
// if PK is at the end of table
if (pkIndex === columnsArr.length - 1) {
if (pkIndex > 0) {
columnsArr[pkIndex - 1].pv = true;
return columnsArr[pkIndex - 1];
} else if (columnsArr.length > 0) {
columnsArr[0].pv = true;
return columnsArr[0];
}
}
// pk is not at the end of table
else if (pkIndex > -1) {
// pk is not at the end of table
} else if (pkIndex > -1) {
columnsArr[pkIndex + 1].pv = true;
return columnsArr[pkIndex + 1];
}
// no pk at all
else {
// todo:
// no pk at all
} else {
if (columnsArr.length > 0) {
columnsArr[0].pv = true;
return columnsArr[0];
}
}
}
}

41
packages/nocodb/src/lib/models/Audit.ts

@ -2,6 +2,7 @@ import { AuditOperationTypes, AuditType } from 'nocodb-sdk';
import { MetaTable } from '../utils/globals';
import Noco from '../Noco';
import Model from './Model';
import { extractProps } from '../meta/helpers/extractProps';
export default class Audit implements AuditType {
id?: string;
@ -44,28 +45,32 @@ export default class Audit implements AuditType {
forceAwait: process.env['TEST'] === 'true',
}
) {
if (process.env.NC_DISABLE_AUDIT === 'true') {
return;
}
const insertAudit = async () => {
if (!audit.project_id && audit.fk_model_id) {
audit.project_id = (
await Model.getByIdOrName({ id: audit.fk_model_id }, ncMeta)
const insertObj = extractProps(audit, [
'user',
'ip',
'base_id',
'project_id',
'row_id',
'fk_model_id',
'op_type',
'op_sub_type',
'status',
'description',
'details',
'created_at',
'updated_at',
]);
if (!insertObj.project_id && insertObj.fk_model_id) {
insertObj.project_id = (
await Model.getByIdOrName({ id: insertObj.fk_model_id }, ncMeta)
).project_id;
}
return await ncMeta.metaInsert2(null, null, MetaTable.AUDIT, {
user: audit.user,
ip: audit.ip,
base_id: audit.base_id,
project_id: audit.project_id,
row_id: audit.row_id,
fk_model_id: audit.fk_model_id,
op_type: audit.op_type,
op_sub_type: audit.op_sub_type,
status: audit.status,
description: audit.description,
details: audit.details,
created_at: audit.created_at,
updated_at: audit.updated_at,
});
return await ncMeta.metaInsert2(null, null, MetaTable.AUDIT, insertObj);
};
if (forceAwait) {

15
packages/nocodb/src/lib/models/BarcodeColumn.ts

@ -14,16 +14,17 @@ export default class BarcodeColumn {
}
public static async insert(
data: Partial<BarcodeColumn>,
barcodeColumn: Partial<BarcodeColumn>,
ncMeta = Noco.ncMeta
) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_BARCODE, {
fk_column_id: data.fk_column_id,
fk_barcode_value_column_id: data.fk_barcode_value_column_id,
barcode_format: data.barcode_format,
});
const insertObj = extractProps(barcodeColumn, [
'fk_column_id',
'fk_barcode_value_column_id',
'barcode_format',
]);
await ncMeta.metaInsert2(null, null, MetaTable.COL_BARCODE, insertObj);
return this.read(data.fk_column_id, ncMeta);
return this.read(barcodeColumn.fk_column_id, ncMeta);
}
public static async read(columnId: string, ncMeta = Noco.ncMeta) {
let column =

139
packages/nocodb/src/lib/models/Column.ts

@ -25,6 +25,7 @@ import addFormulaErrorIfMissingColumn from '../meta/helpers/addFormulaErrorIfMis
import { NcError } from '../meta/helpers/catchError';
import QrCodeColumn from './QrCodeColumn';
import BarcodeColumn from './BarcodeColumn';
import { extractProps } from '../meta/helpers/extractProps';
export default class Column<T = any> implements ColumnType {
public fk_model_id: string;
@ -85,41 +86,50 @@ export default class Column<T = any> implements ColumnType {
) {
if (!column.fk_model_id) NcError.badRequest('Missing model id');
const insertObj: any = {
id: column?.id,
fk_model_id: column.fk_model_id,
column_name: column.column_name || column.cn,
title: column.title || column._cn,
uidt: column.uidt,
dt: column.dt,
np: column.np,
ns: column.ns,
clen: column.clen,
cop: column.cop,
pk: column.pk,
rqd: column.rqd,
un: column.un,
ct: column.ct,
ai: column.ai,
unique: column.unique,
cdf: column.cdf,
cc: column.cc,
csn: column.csn,
dtx: column.dtx,
dtxp: column.dtxp,
dtxs: column.dtxs,
au: column.au,
pv: column.pv,
order: column.order,
project_id: column.project_id,
base_id: column.base_id,
system: column.system,
meta:
column.meta && typeof column.meta === 'object'
? JSON.stringify(column.meta)
: column.meta,
};
// TODO: fix type
const insertObj = extractProps(column as any, [
'id',
'fk_model_id',
'column_name',
'title',
'uidt',
'dt',
'np',
'ns',
'clen',
'cop',
'pk',
'rqd',
'un',
'ct',
'ai',
'unique',
'cdf',
'cc',
'csn',
'dtx',
'dtxp',
'dtxs',
'au',
'pv',
'order',
'project_id',
'base_id',
'system',
'meta',
]);
if (!insertObj.column_name) {
insertObj.column_name = column.cn;
}
if (!insertObj.title) {
insertObj.title = column._cn;
}
if (insertObj.meta && typeof insertObj.meta === 'object') {
insertObj.meta = JSON.stringify(insertObj.meta);
}
if (column.validate) {
if (typeof column.validate === 'string')
insertObj.validate = column.validate;
@ -873,7 +883,11 @@ export default class Column<T = any> implements ColumnType {
);
}
static async update(colId: string, column: any, ncMeta = Noco.ncMeta) {
static async update(
colId: string,
column: Partial<Column>,
ncMeta = Noco.ncMeta
) {
const oldCol = await Column.get({ colId }, ncMeta);
switch (oldCol.uidt) {
@ -965,33 +979,34 @@ export default class Column<T = any> implements ColumnType {
break;
}
}
const updateObj = {
column_name: column.column_name,
title: column.title,
uidt: column.uidt,
dt: column.dt,
np: column.np,
ns: column.ns,
clen: column.clen,
cop: column.cop,
pk: column.pk,
rqd: column.rqd,
un: column.un,
ct: column.ct,
ai: column.ai,
unique: column.unique,
cdf: column.cdf,
cc: column.cc,
csn: column.csn,
dtx: column.dtx,
dtxp: column.dtxp,
dtxs: column.dtxs,
au: column.au,
pv: column.pv,
system: column.system,
validate: null,
meta: column.meta,
};
const updateObj = extractProps(column, [
'column_name',
'title',
'uidt',
'dt',
'np',
'ns',
'clen',
'cop',
'pk',
'rqd',
'un',
'ct',
'ai',
'unique',
'cdf',
'cc',
'csn',
'dtx',
'dtxp',
'dtxs',
'au',
'pv',
'system',
'validate',
'meta',
]);
if (column.validate) {
if (typeof column.validate === 'string')

43
packages/nocodb/src/lib/models/Filter.ts

@ -77,29 +77,30 @@ export default class Filter {
}
public static async insert(
filter: Partial<FilterType>,
filter: Partial<FilterType> & { order?: number },
ncMeta = Noco.ncMeta
) {
const insertObj = {
id: filter.id,
fk_view_id: filter.fk_view_id,
fk_hook_id: filter.fk_hook_id,
fk_column_id: filter.fk_column_id,
comparison_op: filter.comparison_op,
value: filter.value,
fk_parent_id: filter.fk_parent_id,
is_group: filter.is_group,
logical_op: filter.logical_op,
project_id: filter.project_id,
base_id: filter.base_id,
order: await ncMeta.metaGetNextOrder(MetaTable.FILTER_EXP, {
[filter.fk_hook_id ? 'fk_hook_id' : 'fk_view_id']: filter.fk_hook_id
? filter.fk_hook_id
: filter.fk_view_id,
}),
};
const insertObj = extractProps(filter, [
'id',
'fk_view_id',
'fk_hook_id',
'fk_column_id',
'comparison_op',
'value',
'fk_parent_id',
'is_group',
'logical_op',
'project_id',
'base_id',
'order',
]);
insertObj.order = await ncMeta.metaGetNextOrder(MetaTable.FILTER_EXP, {
[filter.fk_hook_id ? 'fk_hook_id' : 'fk_view_id']: filter.fk_hook_id
? filter.fk_hook_id
: filter.fk_view_id,
});
if (!(filter.project_id && filter.base_id)) {
let model: { project_id?: string; base_id?: string };
if (filter.fk_view_id) {

93
packages/nocodb/src/lib/models/FormView.ts

@ -5,6 +5,7 @@ import { deserializeJSON, serializeJSON } from '../utils/serialize';
import FormViewColumn from './FormViewColumn';
import View from './View';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class FormView implements FormType {
show: boolean;
@ -53,22 +54,25 @@ export default class FormView implements FormType {
}
static async insert(view: Partial<FormView>, ncMeta = Noco.ncMeta) {
const insertObj = {
fk_view_id: view.fk_view_id,
project_id: view.project_id,
base_id: view.base_id,
heading: view.heading,
subheading: view.subheading,
success_msg: view.success_msg,
redirect_url: view.redirect_url,
redirect_after_secs: view.redirect_after_secs,
email: view.email,
banner_image_url: view.banner_image_url,
logo_url: view.logo_url,
submit_another_form: view.submit_another_form,
show_blank_form: view.show_blank_form,
meta: serializeJSON(view.meta),
};
const insertObj = extractProps(view, [
'fk_view_id',
'project_id',
'base_id',
'heading',
'subheading',
'success_msg',
'redirect_url',
'redirect_after_secs',
'email',
'banner_image_url',
'logo_url',
'submit_another_form',
'show_blank_form',
'meta',
]);
if (insertObj.meta) {
insertObj.meta = serializeJSON(insertObj.meta);
}
if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.fk_view_id);
insertObj.project_id = viewRef.project_id;
@ -86,44 +90,35 @@ export default class FormView implements FormType {
) {
// get existing cache
const key = `${CacheScope.FORM_VIEW}:${formId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, [
'heading',
'subheading',
'success_msg',
'redirect_url',
'redirect_after_secs',
'email',
'banner_image_url',
'logo_url',
'submit_another_form',
'show_blank_form',
'meta',
]);
if (o) {
o.heading = body.heading;
o.subheading = body.subheading;
o.success_msg = body.success_msg;
o.redirect_url = body.redirect_url;
o.redirect_after_secs = body.redirect_after_secs;
o.email = body.email;
o.banner_image_url = body.banner_image_url;
o.logo_url = body.logo_url;
o.submit_another_form = body.submit_another_form;
o.show_blank_form = body.show_blank_form;
o.meta = body.meta;
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
o.meta = serializeJSON(body.meta);
}
if (updateObj.meta) {
updateObj.meta = serializeJSON(updateObj.meta);
}
// update meta
return await ncMeta.metaUpdate(
null,
null,
MetaTable.FORM_VIEW,
{
heading: body.heading,
subheading: body.subheading,
success_msg: body.success_msg,
redirect_url: body.redirect_url,
redirect_after_secs: body.redirect_after_secs,
email: body.email,
banner_image_url: body.banner_image_url,
logo_url: body.logo_url,
submit_another_form: body.submit_another_form,
show_blank_form: body.show_blank_form,
},
{
fk_view_id: formId,
}
);
return await ncMeta.metaUpdate(null, null, MetaTable.FORM_VIEW, updateObj, {
fk_view_id: formId,
});
}
async getColumns(ncMeta = Noco.ncMeta) {

53
packages/nocodb/src/lib/models/FormViewColumn.ts

@ -55,27 +55,32 @@ export default class FormViewColumn implements FormColumnType {
}
static async insert(column: Partial<FormViewColumn>, ncMeta = Noco.ncMeta) {
const insertObj: Partial<FormViewColumn> = {
fk_view_id: column.fk_view_id,
fk_column_id: column.fk_column_id,
order: await ncMeta.metaGetNextOrder(MetaTable.FORM_VIEW_COLUMNS, {
fk_view_id: column.fk_view_id,
}),
show: column.show,
project_id: column.project_id,
base_id: column.base_id,
label: column.label,
help: column.help,
description: column.description,
required: column.required,
};
if (column.meta) {
insertObj.meta = serializeJSON(column.meta);
const insertObj = extractProps(column, [
'fk_view_id',
'fk_column_id',
'show',
'project_id',
'base_id',
'label',
'help',
'description',
'required',
'meta',
]);
insertObj.order = await ncMeta.metaGetNextOrder(
MetaTable.FORM_VIEW_COLUMNS,
{
fk_view_id: insertObj.fk_view_id,
}
);
if (insertObj.meta) {
insertObj.meta = serializeJSON(insertObj.meta);
}
if (!(column.project_id && column.base_id)) {
const viewRef = await View.get(column.fk_view_id, ncMeta);
if (!(insertObj.project_id && insertObj.base_id)) {
const viewRef = await View.get(insertObj.fk_view_id, ncMeta);
insertObj.project_id = viewRef.project_id;
insertObj.base_id = viewRef.base_id;
}
@ -150,7 +155,7 @@ export default class FormViewColumn implements FormColumnType {
body: Partial<FormViewColumn>,
ncMeta = Noco.ncMeta
) {
const insertObj = extractProps(body, [
const updateObj = extractProps(body, [
'label',
'help',
'description',
@ -164,13 +169,13 @@ export default class FormViewColumn implements FormColumnType {
const key = `${CacheScope.FORM_VIEW_COLUMN}:${columnId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
Object.assign(o, insertObj);
Object.assign(o, updateObj);
// set cache
await NocoCache.set(key, o);
}
if (insertObj.meta) {
insertObj.meta = serializeJSON(insertObj.meta);
if (updateObj.meta) {
updateObj.meta = serializeJSON(updateObj.meta);
}
// update meta
@ -178,7 +183,7 @@ export default class FormViewColumn implements FormColumnType {
null,
null,
MetaTable.FORM_VIEW_COLUMNS,
insertObj,
updateObj,
columnId
);
}

17
packages/nocodb/src/lib/models/FormulaColumn.ts

@ -14,17 +14,18 @@ export default class FormulaColumn {
}
public static async insert(
data: Partial<FormulaColumn>,
formulaColumn: Partial<FormulaColumn>,
ncMeta = Noco.ncMeta
) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_FORMULA, {
fk_column_id: data.fk_column_id,
formula_raw: data.formula_raw,
formula: data.formula,
error: data.error,
});
const insertObj = extractProps(formulaColumn, [
'fk_column_id',
'formula_raw',
'formula',
'error',
]);
await ncMeta.metaInsert2(null, null, MetaTable.COL_FORMULA, insertObj);
return this.read(data.fk_column_id, ncMeta);
return this.read(formulaColumn.fk_column_id, ncMeta);
}
public static async read(columnId: string, ncMeta = Noco.ncMeta) {
let column =

65
packages/nocodb/src/lib/models/GalleryView.ts

@ -3,6 +3,7 @@ import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import { GalleryColumnType, GalleryType, UITypes } from 'nocodb-sdk';
import View from './View';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class GalleryView implements GalleryType {
fk_view_id?: string;
@ -51,21 +52,23 @@ export default class GalleryView implements GalleryType {
.then((v) => v?.getModel(ncMeta))
.then((m) => m.getColumns(ncMeta));
const insertObj = {
project_id: view.project_id,
base_id: view.base_id,
fk_view_id: view.fk_view_id,
fk_cover_image_col_id:
view?.fk_cover_image_col_id ||
columns?.find((c) => c.uidt === UITypes.Attachment)?.id,
next_enabled: view.next_enabled,
prev_enabled: view.prev_enabled,
cover_image_idx: view.cover_image_idx,
cover_image: view.cover_image,
restrict_types: view.restrict_types,
restrict_size: view.restrict_size,
restrict_number: view.restrict_number,
};
const insertObj = extractProps(view, [
'project_id',
'base_id',
'fk_view_id',
'next_enabled',
'prev_enabled',
'cover_image_idx',
'cover_image',
'restrict_types',
'restrict_size',
'restrict_number',
]);
insertObj.fk_cover_image_col_id =
view?.fk_cover_image_col_id ||
columns?.find((c) => c.uidt === UITypes.Attachment)?.id;
if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.fk_view_id);
insertObj.project_id = viewRef.project_id;
@ -90,16 +93,19 @@ export default class GalleryView implements GalleryType {
) {
// get existing cache
const key = `${CacheScope.GALLERY_VIEW}:${galleryId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, [
'next_enabled',
'prev_enabled',
'cover_image_idx',
'cover_image',
'restrict_types',
'restrict_size',
'restrict_number',
'fk_cover_image_col_id',
]);
if (o) {
o.next_enabled = body.next_enabled;
o.prev_enabled = body.prev_enabled;
o.cover_image_idx = body.cover_image_idx;
o.cover_image = body.cover_image;
o.restrict_types = body.restrict_types;
o.restrict_size = body.restrict_size;
o.restrict_number = body.restrict_number;
o.fk_cover_image_col_id = body.fk_cover_image_col_id;
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
@ -108,16 +114,7 @@ export default class GalleryView implements GalleryType {
null,
null,
MetaTable.GALLERY_VIEW,
{
next_enabled: body.next_enabled,
prev_enabled: body.prev_enabled,
cover_image_idx: body.cover_image_idx,
cover_image: body.cover_image,
restrict_types: body.restrict_types,
restrict_size: body.restrict_size,
restrict_number: body.restrict_number,
fk_cover_image_col_id: body.fk_cover_image_col_id,
},
updateObj,
{
fk_view_id: galleryId,
}

23
packages/nocodb/src/lib/models/GalleryViewColumn.ts

@ -2,6 +2,7 @@ import Noco from '../Noco';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class GalleryViewColumn {
id: string;
@ -43,16 +44,20 @@ export default class GalleryViewColumn {
column: Partial<GalleryViewColumn>,
ncMeta = Noco.ncMeta
) {
const insertObj = {
fk_view_id: column.fk_view_id,
fk_column_id: column.fk_column_id,
order: await ncMeta.metaGetNextOrder(MetaTable.GALLERY_VIEW_COLUMNS, {
const insertObj = extractProps(column, [
'fk_view_id',
'fk_column_id',
'show',
'project_id',
'base_id',
]);
insertObj.order = await ncMeta.metaGetNextOrder(
MetaTable.GALLERY_VIEW_COLUMNS,
{
fk_view_id: column.fk_view_id,
}),
show: column.show,
project_id: column.project_id,
base_id: column.base_id,
};
}
);
if (!(column.project_id && column.base_id)) {
const viewRef = await View.get(column.fk_view_id, ncMeta);

37
packages/nocodb/src/lib/models/GridView.ts

@ -3,6 +3,7 @@ import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import GridViewColumn from './GridViewColumn';
import View from './View';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class GridView {
fk_view_id: string;
@ -40,14 +41,15 @@ export default class GridView {
}
static async insert(view: Partial<GridView>, ncMeta = Noco.ncMeta) {
const insertObj = {
fk_view_id: view.fk_view_id,
project_id: view.project_id,
base_id: view.base_id,
row_height: view.row_height,
};
if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.fk_view_id, ncMeta);
const insertObj = extractProps(view, [
'fk_view_id',
'project_id',
'base_id',
'row_height',
]);
if (!(insertObj.project_id && insertObj.base_id)) {
const viewRef = await View.get(insertObj.fk_view_id, ncMeta);
insertObj.project_id = viewRef.project_id;
insertObj.base_id = viewRef.base_id;
}
@ -69,23 +71,16 @@ export default class GridView {
) {
// get existing cache
const key = `${CacheScope.GRID_VIEW}:${viewId}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = extractProps(body, ['row_height']);
if (o) {
o.row_height = body.row_height;
o = { ...o, ...updateObj };
// set cache
await NocoCache.set(key, o);
}
// update meta
return await ncMeta.metaUpdate(
null,
null,
MetaTable.GRID_VIEW,
{
row_height: body.row_height,
},
{
fk_view_id: viewId,
}
);
return await ncMeta.metaUpdate(null, null, MetaTable.GRID_VIEW, updateObj, {
fk_view_id: viewId,
});
}
}

25
packages/nocodb/src/lib/models/GridViewColumn.ts

@ -67,18 +67,19 @@ export default class GridViewColumn implements GridColumnType {
}
static async insert(column: Partial<GridViewColumn>, ncMeta = Noco.ncMeta) {
const insertObj = {
fk_view_id: column.fk_view_id,
fk_column_id: column.fk_column_id,
order:
column?.order ??
(await ncMeta.metaGetNextOrder(MetaTable.GRID_VIEW_COLUMNS, {
fk_view_id: column.fk_view_id,
})),
show: column.show,
project_id: column.project_id,
base_id: column.base_id,
};
const insertObj = extractProps(column, [
'fk_view_id',
'fk_column_id',
'show',
'project_id',
'base_id',
]);
insertObj.order =
column?.order ??
(await ncMeta.metaGetNextOrder(MetaTable.GRID_VIEW_COLUMNS, {
fk_view_id: column.fk_view_id,
}));
if (!(column.project_id && column.base_id)) {
const viewRef = await View.get(column.fk_view_id, ncMeta);

120
packages/nocodb/src/lib/models/Hook.ts

@ -10,6 +10,7 @@ import Model from './Model';
import NocoCache from '../cache/NocoCache';
import Filter from './Filter';
import HookFilter from './HookFilter';
import { extractProps } from '../meta/helpers/extractProps';
export default class Hook implements HookType {
id?: string;
@ -18,7 +19,7 @@ export default class Hook implements HookType {
description?: string;
env?: string;
type?: string;
event?: 'After' | 'Before';
event?: 'after' | 'before';
operation?: 'insert' | 'delete' | 'update';
async?: boolean;
payload?: string;
@ -121,32 +122,42 @@ export default class Hook implements HookType {
>,
ncMeta = Noco.ncMeta
) {
const insertObj = {
fk_model_id: hook.fk_model_id,
title: hook.title,
description: hook.description,
env: hook.env,
type: hook.type,
event: hook.event?.toLowerCase?.(),
operation: hook.operation?.toLowerCase?.(),
async: hook.async,
payload: !!hook.payload,
url: hook.url,
headers: hook.headers,
condition: hook.condition,
notification:
hook.notification && typeof hook.notification === 'object'
? JSON.stringify(hook.notification)
: hook.notification,
retries: hook.retries,
retry_interval: hook.retry_interval,
timeout: hook.timeout,
active: hook.active,
project_id: hook.project_id,
base_id: hook.base_id,
created_at: hook.created_at,
updated_at: hook.updated_at,
};
const insertObj = extractProps(hook, [
'fk_model_id',
'title',
'description',
'env',
'type',
'event',
'operation',
'async',
'url',
'headers',
'notification',
'retries',
'retry_interval',
'timeout',
'active',
'project_id',
'base_id',
'created_at',
'updated_at',
]);
if (insertObj.event) {
insertObj.event = insertObj.event.toLowerCase() as 'after' | 'before';
}
if (insertObj.operation) {
insertObj.operation = insertObj.operation.toLowerCase() as
| 'insert'
| 'delete'
| 'update';
}
if (insertObj.notification && typeof insertObj.notification === 'object') {
insertObj.notification = JSON.stringify(insertObj.notification);
}
if (!(hook.project_id && hook.base_id)) {
const model = await Model.getByIdOrName({ id: hook.fk_model_id }, ncMeta);
@ -175,27 +186,39 @@ export default class Hook implements HookType {
hook: Partial<Hook>,
ncMeta = Noco.ncMeta
) {
const updateObj = {
title: hook.title,
description: hook.description,
env: hook.env,
type: hook.type,
event: hook.event?.toLowerCase?.(),
operation: hook.operation?.toLowerCase?.(),
async: hook.async,
payload: !!hook.payload,
url: hook.url,
headers: hook.headers,
condition: !!hook.condition,
notification:
hook.notification && typeof hook.notification === 'object'
? JSON.stringify(hook.notification)
: hook.notification,
retries: hook.retries,
retry_interval: hook.retry_interval,
timeout: hook.timeout,
active: hook.active,
};
const updateObj = extractProps(hook, [
'title',
'description',
'env',
'type',
'event',
'operation',
'async',
'payload',
'url',
'headers',
'condition',
'notification',
'retries',
'retry_interval',
'timeout',
'active',
]);
if (updateObj.event) {
updateObj.event = updateObj.event.toLowerCase() as 'after' | 'before';
}
if (updateObj.operation) {
updateObj.operation = updateObj.operation.toLowerCase() as
| 'insert'
| 'delete'
| 'update';
}
if (updateObj.notification && typeof updateObj.notification === 'object') {
updateObj.notification = JSON.stringify(updateObj.notification);
}
// get existing cache
const key = `${CacheScope.HOOK}:${hookId}`;
@ -203,6 +226,7 @@ export default class Hook implements HookType {
if (o) {
// update data
o = { ...o, ...updateObj };
// replace notification
o.notification = updateObj.notification;
// set cache
await NocoCache.set(key, o);

43
packages/nocodb/src/lib/models/HookFilter.ts

@ -10,6 +10,7 @@ import {
import View from './View';
import { FilterType, UITypes } from 'nocodb-sdk';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class Filter {
id: string;
@ -48,20 +49,19 @@ export default class Filter {
filter: Partial<FilterType>,
ncMeta = Noco.ncMeta
) {
const insertObj = {
id: filter.id,
fk_view_id: filter.fk_view_id,
fk_column_id: filter.fk_column_id,
comparison_op: filter.comparison_op,
value: filter.value,
fk_parent_id: filter.fk_parent_id,
is_group: filter.is_group,
logical_op: filter.logical_op,
const insertObj = extractProps(filter, [
'id',
'fk_view_id',
'fk_column_id',
'comparison_op',
'value',
'fk_parent_id',
'is_group',
'logical_op',
'project_id',
'base_id',
]);
project_id: filter.project_id,
base_id: filter.base_id,
};
if (!(filter.project_id && filter.base_id)) {
const model = await Column.get({ colId: filter.fk_column_id }, ncMeta);
insertObj.project_id = model.project_id;
@ -138,15 +138,14 @@ export default class Filter {
}
static async update(id, filter: Partial<Filter>, ncMeta = Noco.ncMeta) {
const updateObj = {
fk_column_id: filter.fk_column_id,
comparison_op: filter.comparison_op,
value: filter.value,
fk_parent_id: filter.fk_parent_id,
is_group: filter.is_group,
logical_op: filter.logical_op,
};
const updateObj = extractProps(filter, [
'fk_column_id',
'comparison_op',
'value',
'fk_parent_id',
'is_group',
'logical_op',
]);
// get existing cache
const key = `${CacheScope.FILTER_EXP}:${id}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);

40
packages/nocodb/src/lib/models/KanbanView.ts

@ -3,6 +3,7 @@ import { KanbanType, UITypes } from 'nocodb-sdk';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class KanbanView implements KanbanType {
fk_view_id: string;
@ -63,16 +64,17 @@ export default class KanbanView implements KanbanType {
.then((v) => v?.getModel(ncMeta))
.then((m) => m.getColumns(ncMeta));
const insertObj = {
project_id: view.project_id,
base_id: view.base_id,
fk_view_id: view.fk_view_id,
fk_grp_col_id: view.fk_grp_col_id,
fk_cover_image_col_id:
view?.fk_cover_image_col_id ||
columns?.find((c) => c.uidt === UITypes.Attachment)?.id,
meta: view.meta,
};
const insertObj = extractProps(view, [
'project_id',
'base_id',
'fk_view_id',
'fk_grp_col_id',
'meta',
]);
insertObj.fk_cover_image_col_id =
view?.fk_cover_image_col_id ||
columns?.find((c) => c.uidt === UITypes.Attachment)?.id;
if (!(view.project_id && view.base_id)) {
const viewRef = await View.get(view.fk_view_id);
@ -99,13 +101,17 @@ export default class KanbanView implements KanbanType {
// get existing cache
const key = `${CacheScope.KANBAN_VIEW}:${kanbanId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
const updateObj = {
...body,
meta:
typeof body.meta === 'string'
? body.meta
: JSON.stringify(body.meta ?? {}),
};
const updateObj = extractProps(body, [
'title',
'fk_cover_image_col_id',
'meta',
]);
if (updateObj.meta && typeof updateObj.meta === 'object') {
updateObj.meta = JSON.stringify(updateObj.meta ?? {});
}
if (o) {
o = { ...o, ...updateObj };
// set cache

23
packages/nocodb/src/lib/models/KanbanViewColumn.ts

@ -2,6 +2,7 @@ import Noco from '../Noco';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import View from './View';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class KanbanViewColumn {
id: string;
@ -40,16 +41,20 @@ export default class KanbanViewColumn {
return view && new KanbanViewColumn(view);
}
static async insert(column: Partial<KanbanViewColumn>, ncMeta = Noco.ncMeta) {
const insertObj = {
fk_view_id: column.fk_view_id,
fk_column_id: column.fk_column_id,
order: await ncMeta.metaGetNextOrder(MetaTable.KANBAN_VIEW_COLUMNS, {
const insertObj = extractProps(column, [
'fk_view_id',
'fk_column_id',
'show',
'project_id',
'base_id',
]);
insertObj.order = await ncMeta.metaGetNextOrder(
MetaTable.KANBAN_VIEW_COLUMNS,
{
fk_view_id: column.fk_view_id,
}),
show: column.show,
project_id: column.project_id,
base_id: column.base_id,
};
}
);
if (!(column.project_id && column.base_id)) {
const viewRef = await View.get(column.fk_view_id, ncMeta);

38
packages/nocodb/src/lib/models/LinkToAnotherRecordColumn.ts

@ -1,9 +1,9 @@
import Noco from '../Noco';
import Column from './Column';
import Model from './Model';
// import NocoCache from '../cache/NocoCache';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class LinkToAnotherRecordColumn {
fk_column_id?: string;
@ -89,27 +89,21 @@ export default class LinkToAnotherRecordColumn {
data: Partial<LinkToAnotherRecordColumn>,
ncMeta = Noco.ncMeta
) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_RELATIONS, {
fk_column_id: data.fk_column_id,
// ref_db_alias
type: data.type,
// db_type:
fk_child_column_id: data.fk_child_column_id,
fk_parent_column_id: data.fk_parent_column_id,
fk_mm_model_id: data.fk_mm_model_id,
fk_mm_child_column_id: data.fk_mm_child_column_id,
fk_mm_parent_column_id: data.fk_mm_parent_column_id,
ur: data.ur,
dr: data.dr,
fk_index_name: data.fk_index_name,
fk_related_model_id: data.fk_related_model_id,
virtual: data.virtual,
});
const insertObj = extractProps(data, [
'fk_column_id',
'type',
'fk_child_column_id',
'fk_parent_column_id',
'fk_mm_model_id',
'fk_mm_child_column_id',
'fk_mm_parent_column_id',
'ur',
'dr',
'fk_index_name',
'fk_related_model_id',
'virtual',
]);
await ncMeta.metaInsert2(null, null, MetaTable.COL_RELATIONS, insertObj);
return this.read(data.fk_column_id, ncMeta);
}

14
packages/nocodb/src/lib/models/LookupColumn.ts

@ -1,8 +1,8 @@
import Noco from '../Noco';
// import NocoCache from '../cache/NocoCache';
import Column from './Column';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class LookupColumn {
fk_relation_column_id: string;
@ -29,11 +29,13 @@ export default class LookupColumn {
data: Partial<LookupColumn>,
ncMeta = Noco.ncMeta
) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_LOOKUP, {
fk_column_id: data.fk_column_id,
fk_relation_column_id: data.fk_relation_column_id,
fk_lookup_column_id: data.fk_lookup_column_id,
});
const insertObj = extractProps(data, [
'fk_column_id',
'fk_relation_column_id',
'fk_lookup_column_id',
]);
await ncMeta.metaInsert2(null, null, MetaTable.COL_LOOKUP, insertObj);
await NocoCache.appendToList(
CacheScope.COL_LOOKUP,

52
packages/nocodb/src/lib/models/Model.ts

@ -22,6 +22,7 @@ import View from './View';
import { NcError } from '../meta/helpers/catchError';
import Audit from './Audit';
import { sanitize } from '../db/sql-data-mapper/lib/sql/helpers/sanitize';
import { extractProps } from '../meta/helpers/extractProps';
export default class Model implements TableType {
copy_enabled: boolean;
@ -103,25 +104,38 @@ export default class Model implements TableType {
},
ncMeta = Noco.ncMeta
) {
const insertObj = extractProps(model, [
'table_name',
'title',
'mm',
'order',
'type',
'created_at',
'updated_at',
'id',
]);
insertObj.mm = !!insertObj.mm;
if (!insertObj.order) {
insertObj.order = await ncMeta.metaGetNextOrder(
MetaTable.FORM_VIEW_COLUMNS,
{
project_id: projectId,
base_id: baseId,
}
);
}
if (!insertObj.type) {
insertObj.type = ModelTypes.TABLE;
}
const { id } = await ncMeta.metaInsert2(
projectId,
baseId,
MetaTable.MODELS,
{
table_name: model.table_name,
title: model.title,
mm: !!model.mm,
order:
model.order ||
(await ncMeta.metaGetNextOrder(MetaTable.FORM_VIEW_COLUMNS, {
project_id: projectId,
base_id: baseId,
})),
type: model.type || ModelTypes.TABLE,
created_at: model.created_at,
updated_at: model.updated_at,
id: model.id,
}
insertObj
);
await NocoCache.appendToList(
@ -561,14 +575,14 @@ export default class Model implements TableType {
ncMeta = Noco.ncMeta
) {
const model = await this.getWithInfo({ id: tableId });
const currentPvCol = model.displayValue;
const newPvCol = model.columns.find((c) => c.id === columnId);
if (!newPvCol) NcError.badRequest('Column not found');
if (currentPvCol) {
// drop existing primary column/s
for (const col of model.columns?.filter((c) => c.pv) || []) {
// get existing cache
const key = `${CacheScope.COLUMN}:${currentPvCol.id}`;
const key = `${CacheScope.COLUMN}:${col.id}`;
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) {
o.pv = false;
@ -583,7 +597,7 @@ export default class Model implements TableType {
{
pv: false,
},
currentPvCol.id
col.id
);
}

21
packages/nocodb/src/lib/models/ModelRoleVisibility.ts

@ -8,6 +8,7 @@ import {
} from '../utils/globals';
import NocoCache from '../cache/NocoCache';
import View from './View';
import { extractProps } from '../meta/helpers/extractProps';
export default class ModelRoleVisibility implements ModelRoleVisibilityType {
id?: string;
@ -134,17 +135,17 @@ export default class ModelRoleVisibility implements ModelRoleVisibilityType {
>,
ncMeta = Noco.ncMeta
) {
const insertObj = {
role: body.role,
disabled: body.disabled,
fk_view_id: body.fk_view_id,
project_id: body.project_id,
base_id: body.base_id,
created_at: body.created_at,
updated_at: body.updated_at,
};
const insertObj = extractProps(body, [
'role',
'disabled',
'fk_view_id',
'project_id',
'base_id',
'created_at',
'updated_at',
]);
if (!(body.project_id && body.base_id)) {
if (!(insertObj.project_id && insertObj.base_id)) {
const view = await View.get(body.fk_view_id, ncMeta);
insertObj.project_id = view.project_id;
insertObj.base_id = view.base_id;

14
packages/nocodb/src/lib/models/Plugin.ts

@ -2,6 +2,7 @@ import { PluginType } from 'nocodb-sdk';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import Noco from '../Noco';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class Plugin implements PluginType {
id?: string;
@ -56,13 +57,12 @@ export default class Plugin implements PluginType {
}
public static async update(pluginId: string, plugin: Partial<PluginType>) {
const updateObj = {
input:
plugin.input && typeof plugin.input === 'object'
? JSON.stringify(plugin.input)
: plugin.input,
active: plugin.active,
};
const updateObj = extractProps(plugin, ['input', 'active']);
if (updateObj.input && typeof updateObj.input === 'object') {
updateObj.input = JSON.stringify(updateObj.input);
}
// get existing cache
const key = `${CacheScope.PLUGIN}:${pluginId}`;
let o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);

24
packages/nocodb/src/lib/models/Project.ts

@ -36,25 +36,27 @@ export default class Project implements ProjectType {
}
public static async createProject(
projectBody: ProjectType & {
project: ProjectType & {
created_at?;
updated_at?;
},
ncMeta = Noco.ncMeta
): Promise<Project> {
const insertObj = extractProps(project, [
'id',
'title',
'prefix',
'description',
'is_meta',
'created_at',
'updated_at',
]);
const { id: projectId } = await ncMeta.metaInsert2(
null,
null,
MetaTable.PROJECT,
{
id: projectBody?.id,
title: projectBody.title,
prefix: projectBody.prefix,
description: projectBody.description,
is_meta: projectBody.is_meta,
created_at: projectBody.created_at,
updated_at: projectBody.updated_at,
}
insertObj
);
await NocoCache.appendToList(
@ -63,7 +65,7 @@ export default class Project implements ProjectType {
`${CacheScope.PROJECT}:${projectId}`
);
for (const base of projectBody.bases) {
for (const base of project.bases) {
await Base.createBase(
{
type: base.config?.client,

17
packages/nocodb/src/lib/models/ProjectUser.ts

@ -8,6 +8,7 @@ import {
import Noco from '../Noco';
import NocoCache from '../cache/NocoCache';
import User from './User';
import { extractProps } from '../meta/helpers/extractProps';
export default class ProjectUser {
project_id: string;
@ -22,17 +23,19 @@ export default class ProjectUser {
projectUser: Partial<ProjectUser & { created_at?: any; updated_at?: any }>,
ncMeta = Noco.ncMeta
) {
const insertObj = extractProps(projectUser, [
'fk_user_id',
'project_id',
'roles',
'created_at',
'updated_at',
]);
const { project_id, fk_user_id } = await ncMeta.metaInsert2(
null,
null,
MetaTable.PROJECT_USERS,
{
fk_user_id: projectUser.fk_user_id,
project_id: projectUser.project_id,
roles: projectUser.roles,
created_at: projectUser.created_at,
updated_at: projectUser.updated_at,
},
insertObj,
true
);

14
packages/nocodb/src/lib/models/QrCodeColumn.ts

@ -12,15 +12,17 @@ export default class QrCodeColumn {
}
public static async insert(
data: Partial<QrCodeColumn>,
qrCode: Partial<QrCodeColumn>,
ncMeta = Noco.ncMeta
) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_QRCODE, {
fk_column_id: data.fk_column_id,
fk_qr_value_column_id: data.fk_qr_value_column_id,
});
const insertObj = extractProps(qrCode, [
'fk_column_id',
'fk_qr_value_column_id',
]);
await ncMeta.metaInsert2(null, null, MetaTable.COL_QRCODE, insertObj);
return this.read(data.fk_column_id, ncMeta);
return this.read(qrCode.fk_column_id, ncMeta);
}
public static async read(columnId: string, ncMeta = Noco.ncMeta) {
let column =

14
packages/nocodb/src/lib/models/RollupColumn.ts

@ -2,6 +2,7 @@ import Noco from '../Noco';
import Column from './Column';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import NocoCache from '../cache/NocoCache';
import { extractProps } from '../meta/helpers/extractProps';
export default class RollupColumn {
fk_column_id;
@ -20,12 +21,13 @@ export default class RollupColumn {
data: Partial<RollupColumn>,
ncMeta = Noco.ncMeta
) {
await ncMeta.metaInsert2(null, null, MetaTable.COL_ROLLUP, {
fk_column_id: data.fk_column_id,
fk_relation_column_id: data.fk_relation_column_id,
fk_rollup_column_id: data.fk_rollup_column_id,
rollup_function: data.rollup_function,
});
const insertObj = extractProps(data, [
'fk_column_id',
'fk_relation_column_id',
'fk_rollup_column_id',
'rollup_function',
]);
await ncMeta.metaInsert2(null, null, MetaTable.COL_ROLLUP, insertObj);
await NocoCache.appendToList(
CacheScope.COL_ROLLUP,

11
packages/nocodb/src/lib/models/SelectOption.ts

@ -1,6 +1,7 @@
import Noco from '../Noco';
import NocoCache from '../cache/NocoCache';
import { CacheGetType, CacheScope, MetaTable } from '../utils/globals';
import { extractProps } from '../meta/helpers/extractProps';
export default class SelectOption {
title: string;
@ -16,11 +17,19 @@ export default class SelectOption {
data: Partial<SelectOption>,
ncMeta = Noco.ncMeta
) {
const insertObj = extractProps(data, [
'id',
'title',
'fk_column_id',
'color',
'order',
]);
const { id } = await ncMeta.metaInsert2(
null,
null,
MetaTable.COL_SELECT_OPTIONS,
data
insertObj
);
await NocoCache.appendToList(

24
packages/nocodb/src/lib/models/Sort.ts

@ -9,6 +9,7 @@ import {
} from '../utils/globals';
import NocoCache from '../cache/NocoCache';
import { SortType } from 'nocodb-sdk';
import { extractProps } from '../meta/helpers/extractProps';
export default class Sort {
id: string;
@ -35,11 +36,20 @@ export default class Sort {
}
public static async insert(
sortObj: Partial<Sort> & { push_to_top?: boolean },
sortObj: Partial<Sort> & { push_to_top?: boolean; order?: number },
ncMeta = Noco.ncMeta
) {
const insertObj = extractProps(sortObj, [
'id',
'fk_view_id',
'fk_column_id',
'direction',
'project_id',
'base_id',
]);
// todo: implement a generic function
const order = sortObj.push_to_top
insertObj.order = sortObj.push_to_top
? 1
: (+(
await ncMeta
@ -50,16 +60,6 @@ export default class Sort {
})
.first()
)?.order || 0) + 1;
const insertObj = {
id: sortObj.id,
fk_view_id: sortObj.fk_view_id,
fk_column_id: sortObj.fk_column_id,
direction: sortObj.direction,
project_id: sortObj.project_id,
base_id: sortObj.base_id,
order,
};
if (!(sortObj.project_id && sortObj.base_id)) {
const model = await Column.get({ colId: sortObj.fk_column_id }, ncMeta);
insertObj.project_id = model.project_id;

15
packages/nocodb/src/lib/models/SyncLogs.ts

@ -1,5 +1,6 @@
import Noco from '../Noco';
import { MetaTable } from '../utils/globals';
import { extractProps } from '../meta/helpers/extractProps';
export default class SyncLogs {
id?: string;
@ -34,13 +35,13 @@ export default class SyncLogs {
>,
ncMeta = Noco.ncMeta
) {
const insertObj = {
project_id: syncLog?.project_id,
fk_sync_source_id: syncLog?.fk_sync_source_id,
time_taken: syncLog?.time_taken,
status: syncLog?.status,
status_details: syncLog?.status_details,
};
const insertObj = extractProps(syncLog, [
'project_id',
'fk_sync_source_id',
'time_taken',
'status',
'status_details',
]);
const { id } = await ncMeta.metaInsert2(
null,

18
packages/nocodb/src/lib/models/SyncSource.ts

@ -73,15 +73,15 @@ export default class SyncSource {
>,
ncMeta = Noco.ncMeta
) {
const insertObj = {
id: syncSource?.id,
title: syncSource?.title,
type: syncSource?.type,
details: syncSource?.details,
project_id: syncSource?.project_id,
base_id: syncSource?.base_id,
fk_user_id: syncSource?.fk_user_id,
};
const insertObj = extractProps(syncSource, [
'id',
'title',
'type',
'details',
'project_id',
'base_id',
'fk_user_id',
]);
if (insertObj.details && typeof insertObj.details === 'object') {
insertObj.details = JSON.stringify(insertObj.details);

34
packages/nocodb/src/lib/models/View.ts

@ -244,25 +244,29 @@ export default class View implements ViewType {
},
ncMeta = Noco.ncMeta
) {
const insertObj = extractProps(view, [
'id',
'title',
'is_default',
'type',
'fk_model_id',
'project_id',
'base_id',
'created_at',
'updated_at',
'meta',
]);
// get order value
const order = await ncMeta.metaGetNextOrder(MetaTable.VIEWS, {
insertObj.order = await ncMeta.metaGetNextOrder(MetaTable.VIEWS, {
fk_model_id: view.fk_model_id,
});
const insertObj = {
id: view.id,
title: view.title,
show: true,
is_default: view.is_default,
order,
type: view.type,
fk_model_id: view.fk_model_id,
project_id: view.project_id,
base_id: view.base_id,
created_at: view.created_at,
updated_at: view.updated_at,
meta: view.meta ?? {},
};
insertObj.show = true;
if (!insertObj.meta) {
insertObj.meta = {};
}
insertObj.meta = stringifyMetaProp(insertObj);

2
packages/nocodb/src/lib/utils/common/BaseApiBuilder.ts

@ -187,7 +187,7 @@ export default abstract class BaseApiBuilder<T extends Noco>
return this.connectionConfig?.meta?.dbAlias;
}
public async getSqlClient(): Promise<any> {
public async getSqlClient() {
return NcConnectionMgr.getSqlClient({
dbAlias: this.dbAlias,
env: this.config.env,

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

Loading…
Cancel
Save