Browse Source

Merge branch 'develop' into refactor/backend

pull/5269/head
Wing-Kam Wong 2 years ago
parent
commit
06df79b3af
  1. 1
      packages/nc-gui/components/cell/SingleSelect.vue
  2. 3
      packages/nc-gui/components/cell/attachment/utils.ts
  3. 8
      packages/nc-gui/components/dashboard/TreeView.vue
  4. 4
      packages/nc-gui/components/dashboard/settings/AuditTab.vue
  5. 7
      packages/nc-gui/components/dashboard/settings/DataSources.vue
  6. 6
      packages/nc-gui/components/dashboard/settings/Metadata.vue
  7. 6
      packages/nc-gui/components/dashboard/settings/Misc.vue
  8. 3
      packages/nc-gui/components/dashboard/settings/UIAcl.vue
  9. 5
      packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue
  10. 5
      packages/nc-gui/components/dashboard/settings/data-sources/EditBase.vue
  11. 7
      packages/nc-gui/components/dlg/AirtableImport.vue
  12. 3
      packages/nc-gui/components/dlg/QuickImport.vue
  13. 5
      packages/nc-gui/components/dlg/TableRename.vue
  14. 4
      packages/nc-gui/components/erd/View.vue
  15. 4
      packages/nc-gui/components/general/HelpAndSupport.vue
  16. 4
      packages/nc-gui/components/general/MiniSidebar.vue
  17. 3
      packages/nc-gui/components/smartsheet/ApiSnippet.vue
  18. 3
      packages/nc-gui/components/smartsheet/Cell.vue
  19. 16
      packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue
  20. 4
      packages/nc-gui/components/smartsheet/column/LookupOptions.vue
  21. 4
      packages/nc-gui/components/smartsheet/column/RollupOptions.vue
  22. 3
      packages/nc-gui/components/smartsheet/header/CellIcon.ts
  23. 5
      packages/nc-gui/components/smartsheet/sidebar/index.vue
  24. 3
      packages/nc-gui/components/smartsheet/toolbar/ExportSubActions.vue
  25. 4
      packages/nc-gui/components/smartsheet/toolbar/FilterInput.vue
  26. 3
      packages/nc-gui/components/smartsheet/toolbar/MoreActions.vue
  27. 4
      packages/nc-gui/components/smartsheet/toolbar/RowHeight.vue
  28. 3
      packages/nc-gui/components/smartsheet/toolbar/ShareView.vue
  29. 3
      packages/nc-gui/components/smartsheet/toolbar/ViewActions.vue
  30. 4
      packages/nc-gui/components/tabs/auth/ApiTokenManagement.vue
  31. 3
      packages/nc-gui/components/tabs/auth/UserManagement.vue
  32. 14
      packages/nc-gui/components/tabs/auth/user-management/ShareBase.vue
  33. 3
      packages/nc-gui/components/tabs/auth/user-management/UsersModal.vue
  34. 5
      packages/nc-gui/components/template/Editor.vue
  35. 10
      packages/nc-gui/components/webhook/Editor.vue
  36. 5
      packages/nc-gui/composables/useColumnCreateStore.ts
  37. 3
      packages/nc-gui/composables/useExpandedFormStore.ts
  38. 1
      packages/nc-gui/composables/useGlobal/state.ts
  39. 1
      packages/nc-gui/composables/useGlobal/types.ts
  40. 5
      packages/nc-gui/composables/useKanbanViewStore.ts
  41. 3
      packages/nc-gui/composables/useLTARStore.ts
  42. 4
      packages/nc-gui/composables/useMapViewDataStore.ts
  43. 4
      packages/nc-gui/composables/useMetas.ts
  44. 9
      packages/nc-gui/composables/useSharedFormViewStore.ts
  45. 4
      packages/nc-gui/composables/useSharedView.ts
  46. 3
      packages/nc-gui/composables/useSmartsheetRowStore.ts
  47. 16
      packages/nc-gui/composables/useSmartsheetStore.ts
  48. 4
      packages/nc-gui/composables/useTable.ts
  49. 4
      packages/nc-gui/composables/useViewColumns.ts
  50. 3
      packages/nc-gui/composables/useViewData.ts
  51. 3
      packages/nc-gui/composables/useViewFilters.ts
  52. 3
      packages/nc-gui/composables/useViewSorts.ts
  53. 5
      packages/nc-gui/nuxt.config.ts
  54. 1949
      packages/nc-gui/package-lock.json
  55. 5
      packages/nc-gui/package.json
  56. 8
      packages/nc-gui/pages/[projectType]/[projectId]/index.vue
  57. 6
      packages/nc-gui/pages/[projectType]/[projectId]/index/index.vue
  58. 5
      packages/nc-gui/pages/[projectType]/[projectId]/index/index/[type]/[title]/[[viewTitle]].vue
  59. 5
      packages/nc-gui/pages/[projectType]/[projectId]/index/index/index.vue
  60. 5
      packages/nc-gui/pages/account/index.vue
  61. 6
      packages/nc-gui/pages/account/index/[page].vue
  62. 6
      packages/nc-gui/pages/index/index/[projectId].vue
  63. 9
      packages/nc-gui/store/project.ts
  64. 21
      packages/nc-gui/store/tab.ts
  65. 7
      packages/nocodb-sdk/src/lib/formulaHelpers.ts
  66. 13
      packages/nocodb/src/lib/controllers/plugin.ctl.ts
  67. 5
      packages/nocodb/src/lib/services/column.svc.ts
  68. 22
      packages/nocodb/src/lib/services/hook.svc.ts
  69. 1
      packages/nocodb/src/lib/services/util.svc.ts
  70. 67
      packages/nocodb/src/lib/utils/common/helpers/jsepTreeToFormula.ts
  71. 2
      packages/nocodb/src/lib/utils/common/helpers/updateColumnNameInFormula.ts

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

@ -19,6 +19,7 @@ import {
isDrawerOrModalExist,
ref,
useEventListener,
useProject,
useRoles,
useSelectedCellKeyupListener,
watch,

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

@ -13,6 +13,7 @@ import {
isImage,
message,
ref,
storeToRefs,
useApi,
useAttachment,
useFileDialog,
@ -51,7 +52,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
/** for image carousel */
const selectedImage = ref()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { api, isLoading } = useApi()

8
packages/nc-gui/components/dashboard/TreeView.vue

@ -17,6 +17,7 @@ import {
reactive,
ref,
resolveComponent,
storeToRefs,
useDialog,
useGlobal,
useNuxtApp,
@ -35,9 +36,12 @@ const { addTab, updateTab } = useTabs()
const { $api, $e } = useNuxtApp()
const { bases, tables, loadTables, isSharedBase } = useProject()
const projectStore = useProject()
const { activeTab } = useTabs()
const { loadTables } = projectStore
const { bases, tables, isSharedBase } = storeToRefs(projectStore)
const { activeTab } = storeToRefs(useTabs())
const { deleteTable } = useTable()

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

@ -1,11 +1,11 @@
<script setup lang="ts">
import { Tooltip as ATooltip, Empty } from 'ant-design-vue'
import type { AuditType } from 'nocodb-sdk'
import { h, onMounted, timeAgo, useGlobal, useI18n, useNuxtApp, useProject } from '#imports'
import { h, onMounted, storeToRefs, timeAgo, useGlobal, useI18n, useNuxtApp, useProject } from '#imports'
const { $api } = useNuxtApp()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { t } = useI18n()

7
packages/nc-gui/components/dashboard/settings/DataSources.vue

@ -7,7 +7,7 @@ import Metadata from './Metadata.vue'
import UIAcl from './UIAcl.vue'
import Erd from './Erd.vue'
import { ClientType, DataSourcesSubTab } from '~/lib'
import { useNuxtApp, useProject } from '#imports'
import { storeToRefs, useNuxtApp, useProject } from '#imports'
interface Props {
state: string
@ -23,8 +23,9 @@ const vState = useVModel(props, 'state', emits)
const vReload = useVModel(props, 'reload', emits)
const { $api, $e } = useNuxtApp()
const { project, loadProject } = useProject()
const projectStore = useProject()
const { loadProject } = projectStore
const { project } = storeToRefs(projectStore)
let sources = $ref<BaseType[]>([])

6
packages/nc-gui/components/dashboard/settings/Metadata.vue

@ -1,5 +1,5 @@
<script setup lang="ts">
import { Empty, extractSdkResponseErrorMsg, h, message, useI18n, useNuxtApp, useProject } from '#imports'
import { Empty, extractSdkResponseErrorMsg, h, message, storeToRefs, useI18n, useNuxtApp, useProject } from '#imports'
const props = defineProps<{
baseId: string
@ -9,7 +9,9 @@ const emit = defineEmits(['baseSynced'])
const { $api } = useNuxtApp()
const { project, loadTables } = useProject()
const projectStore = useProject()
const { loadTables } = projectStore
const { project } = storeToRefs(projectStore)
const { t } = useI18n()

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

@ -1,10 +1,12 @@
<script setup lang="ts">
import type { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface'
import { useGlobal, useProject, watch } from '#imports'
import { storeToRefs, useGlobal, useProject, watch } from '#imports'
const { includeM2M, showNull } = useGlobal()
const { project, updateProject, projectMeta, loadTables, hasEmptyOrNullFilters } = useProject()
const projectStore = useProject()
const { updateProject, loadTables, hasEmptyOrNullFilters } = projectStore
const { project, projectMeta } = storeToRefs(projectStore)
watch(includeM2M, async () => await loadTables())

3
packages/nc-gui/components/dashboard/settings/UIAcl.vue

@ -6,6 +6,7 @@ import {
h,
message,
onMounted,
storeToRefs,
useGlobal,
useI18n,
useNuxtApp,
@ -20,7 +21,7 @@ const { t } = useI18n()
const { $api, $e } = useNuxtApp()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { includeM2M } = useGlobal()

5
packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue

@ -20,6 +20,7 @@ import {
projectTitleValidator,
readFile,
ref,
storeToRefs,
useApi,
useGlobal,
useI18n,
@ -33,7 +34,9 @@ const emit = defineEmits(['baseCreated'])
const { appInfo } = useGlobal()
const { project, loadProject } = useProject()
const projectStore = useProject()
const { loadProject } = projectStore
const { project } = storeToRefs(projectStore)
const useForm = Form.useForm

5
packages/nc-gui/components/dashboard/settings/data-sources/EditBase.vue

@ -19,6 +19,7 @@ import {
projectTitleValidator,
readFile,
ref,
storeToRefs,
useApi,
useI18n,
useNuxtApp,
@ -31,7 +32,9 @@ const props = defineProps<{
const emit = defineEmits(['baseUpdated'])
const { project, loadProject } = useProject()
const projectStore = useProject()
const { loadProject } = projectStore
const { project } = storeToRefs(projectStore)
const useForm = Form.useForm

7
packages/nc-gui/components/dlg/AirtableImport.vue

@ -12,6 +12,7 @@ import {
onBeforeUnmount,
onMounted,
ref,
storeToRefs,
useGlobal,
useNuxtApp,
useProject,
@ -31,7 +32,11 @@ const baseURL = appInfo.ncSiteUrl
const { $state } = useNuxtApp()
const { project, loadTables } = useProject()
const projectStore = useProject()
const { loadTables } = projectStore
const { project } = storeToRefs(projectStore)
const showGoToDashboardButton = ref(false)

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

@ -18,6 +18,7 @@ import {
message,
reactive,
ref,
storeToRefs,
useI18n,
useProject,
useVModel,
@ -37,7 +38,7 @@ const emit = defineEmits(['update:modelValue'])
const { t } = useI18n()
const { tables } = useProject()
const { tables } = storeToRefs(useProject())
const activeKey = ref('uploadTab')

5
packages/nc-gui/components/dlg/TableRename.vue

@ -8,6 +8,7 @@ import {
message,
nextTick,
reactive,
storeToRefs,
useI18n,
useMetas,
useNuxtApp,
@ -38,7 +39,9 @@ const dialogShow = useVModel(props, 'modelValue', emit)
const { updateTab } = useTabs()
const { loadTables, tables, project, isMysql, isMssql, isPg } = useProject()
const projectStore = useProject()
const { loadTables, isMysql, isMssql, isPg } = projectStore
const { project } = storeToRefs(projectStore)
const inputEl = $ref<ComponentPublicInstance>()

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

@ -2,11 +2,11 @@
import type { LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import type { ERDConfig } from './utils'
import { reactive, ref, useMetas, useProject, watch } from '#imports'
import { reactive, ref, storeToRefs, useMetas, useProject, watch } from '#imports'
const props = defineProps<{ table?: TableType; baseId?: string }>()
const { tables: projectTables } = useProject()
const { tables: projectTables } = storeToRefs(useProject())
const { metas, getMeta } = useMetas()

4
packages/nc-gui/components/general/HelpAndSupport.vue

@ -1,11 +1,11 @@
<script lang="ts" setup>
import { ref, useGlobal, useProject, useRoute } from '#imports'
import { ref, storeToRefs, useGlobal, useProject, useRoute } from '#imports'
const showDrawer = ref(false)
const { appInfo } = useGlobal()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const route = useRoute()

4
packages/nc-gui/components/general/MiniSidebar.vue

@ -1,11 +1,11 @@
<script lang="ts" setup>
import { computed, navigateTo, useGlobal, useProject, useRoute, useSidebar } from '#imports'
import { computed, navigateTo, storeToRefs, useGlobal, useProject, useRoute, useSidebar } from '#imports'
const { signOut, signedIn, user, currentVersion } = useGlobal()
const { isOpen } = useSidebar('nc-mini-sidebar', { isOpen: true })
const { project } = useProject()
const { project } = storeToRefs(useProject())
const route = useRoute()

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

@ -6,6 +6,7 @@ import {
inject,
message,
ref,
storeToRefs,
useCopy,
useGlobal,
useI18n,
@ -24,7 +25,7 @@ const emits = defineEmits(['update:modelValue'])
const { t } = useI18n()
const { project } = $(useProject())
const { project } = $(storeToRefs(useProject()))
const { appInfo, token } = $(useGlobal())

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

@ -39,6 +39,7 @@ import {
isYear,
provide,
ref,
storeToRefs,
toRef,
useDebounceFn,
useProject,
@ -85,7 +86,7 @@ const isLocked = inject(IsLockedInj, ref(false))
const { currentRow } = useSmartsheetRowStoreOrThrow()
const { sqlUis } = useProject()
const { sqlUis } = storeToRefs(useProject())
const sqlUi = ref(column.value?.base_id ? sqlUis.value[column.value?.base_id] : Object.values(sqlUis.value)[0])

16
packages/nc-gui/components/smartsheet/column/LinkedToAnotherRecordOptions.vue

@ -1,6 +1,6 @@
<script setup lang="ts">
import { ModelTypes, MssqlUi, SqliteUi } from 'nocodb-sdk'
import { MetaInj, inject, ref, useProject, useVModel } from '#imports'
import { MetaInj, inject, ref, storeToRefs, useProject, useVModel } from '#imports'
import MdiPlusIcon from '~icons/mdi/plus-circle-outline'
import MdiMinusIcon from '~icons/mdi/minus-circle-outline'
@ -10,13 +10,15 @@ const props = defineProps<{
const emit = defineEmits(['update:value'])
const { appInfo } = $(useGlobal())
const vModel = useVModel(props, 'value', emit)
const meta = $(inject(MetaInj, ref()))
const { setAdditionalValidations, validateInfos, onDataTypeChange, sqlUi } = useColumnCreateStoreOrThrow()
const { tables } = $(useProject())
const { tables } = $(storeToRefs(useProject()))
setAdditionalValidations({
childId: [{ required: true, message: 'Required' }],
@ -31,10 +33,10 @@ if (!vModel.value.childTable) vModel.value.childTable = meta?.table_name
if (!vModel.value.parentTable) vModel.value.parentTable = vModel.value.rtn || ''
if (!vModel.value.parentColumn) vModel.value.parentColumn = vModel.value.rcn || ''
if (!vModel.value.type) vModel.value.type = 'hm'
if (!vModel.value.type) vModel.value.type = 'mm'
if (!vModel.value.onUpdate) vModel.value.onUpdate = onUpdateDeleteOptions[0]
if (!vModel.value.onDelete) vModel.value.onDelete = onUpdateDeleteOptions[0]
if (!vModel.value.virtual) vModel.value.virtual = sqlUi === SqliteUi
if (!vModel.value.virtual) vModel.value.virtual = appInfo.isCloud || sqlUi === SqliteUi
if (!vModel.value.alias) vModel.value.alias = vModel.value.column_name
const advancedOptions = $(ref(false))
@ -55,7 +57,7 @@ const filterOption = (value: string, option: { key: string }) => option.key.toLo
<div class="border-2 p-6">
<a-form-item v-bind="validateInfos.type" class="nc-ltar-relation-type">
<a-radio-group v-model:value="vModel.type" name="type" v-bind="validateInfos.type">
<a-radio value="hm">Has Many</a-radio>
<a-radio value="hm" :disabled="appInfo.isCloud">Has Many</a-radio>
<a-radio value="mm">Many To Many</a-radio>
</a-radio-group>
</a-form-item>
@ -127,7 +129,9 @@ const filterOption = (value: string, option: { key: string }) => option.key.toLo
<div class="flex flex-row">
<a-form-item>
<a-checkbox v-model:checked="vModel.virtual" name="virtual" @change="onDataTypeChange">Virtual Relation</a-checkbox>
<a-checkbox v-model:checked="vModel.virtual" :disabled="appInfo.isCloud" name="virtual" @change="onDataTypeChange"
>Virtual Relation</a-checkbox
>
</a-form-item>
</div>
</div>

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

@ -3,7 +3,7 @@ import { onMounted } from '@vue/runtime-core'
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes, isSystemColumn } from 'nocodb-sdk'
import { getRelationName } from './utils'
import { MetaInj, inject, ref, useColumnCreateStoreOrThrow, useMetas, useProject, useVModel } from '#imports'
import { MetaInj, inject, ref, storeToRefs, useColumnCreateStoreOrThrow, useMetas, useProject, useVModel } from '#imports'
const props = defineProps<{
value: any
@ -17,7 +17,7 @@ const meta = $(inject(MetaInj, ref()))
const { setAdditionalValidations, validateInfos, onDataTypeChange, isEdit } = useColumnCreateStoreOrThrow()
const { tables } = $(useProject())
const { tables } = $(storeToRefs(useProject()))
const { metas } = $(useMetas())

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

@ -3,7 +3,7 @@ import { onMounted } from '@vue/runtime-core'
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes, isSystemColumn, isVirtualCol } from 'nocodb-sdk'
import { getRelationName } from './utils'
import { MetaInj, inject, ref, useColumnCreateStoreOrThrow, useMetas, useProject, useVModel } from '#imports'
import { MetaInj, inject, ref, storeToRefs, useColumnCreateStoreOrThrow, useMetas, useProject, useVModel } from '#imports'
const props = defineProps<{
value: any
@ -17,7 +17,7 @@ const meta = $(inject(MetaInj, ref()))
const { setAdditionalValidations, validateInfos, onDataTypeChange, isEdit } = useColumnCreateStoreOrThrow()
const { tables } = $(useProject())
const { tables } = $(storeToRefs(useProject()))
const { metas } = $(useMetas())

3
packages/nc-gui/components/smartsheet/header/CellIcon.ts

@ -30,6 +30,7 @@ import {
isTime,
isURL,
isYear,
storeToRefs,
toRef,
useProject,
} from '#imports'
@ -123,7 +124,7 @@ export default defineComponent({
const column = inject(ColumnInj, columnMeta)
const { sqlUis } = useProject()
const { sqlUis } = storeToRefs(useProject())
const sqlUi = ref(column.value?.base_id ? sqlUis.value[column.value?.base_id] : Object.values(sqlUis.value)[0])

5
packages/nc-gui/components/smartsheet/sidebar/index.vue

@ -7,6 +7,7 @@ import {
inject,
ref,
resolveComponent,
storeToRefs,
useDialog,
useNuxtApp,
useRoute,
@ -21,11 +22,11 @@ const meta = inject(MetaInj, ref())
const activeView = inject(ActiveViewInj, ref())
const { activeTab } = useTabs()
const { activeTab } = storeToRefs(useTabs())
const { views, loadViews, isLoading } = useViews(meta)
const { lastOpenedViewMap } = useProject()
const { lastOpenedViewMap } = storeToRefs(useProject())
const setLastOpenedViewId = (viewId?: string) => {
if (viewId && activeTab.value?.id) {

3
packages/nc-gui/components/smartsheet/toolbar/ExportSubActions.vue

@ -10,6 +10,7 @@ import {
inject,
message,
ref,
storeToRefs,
useI18n,
useNuxtApp,
useProject,
@ -22,7 +23,7 @@ const isPublicView = inject(IsPublicInj, ref(false))
const fields = inject(FieldsInj, ref([]))
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { $api } = useNuxtApp()

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

@ -1,5 +1,6 @@
<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import { storeToRefs } from 'pinia'
import {
ColumnInj,
EditModeInj,
@ -83,7 +84,8 @@ const checkTypeFunctions = {
type FilterType = keyof typeof checkTypeFunctions
const { sqlUi } = $(useProject())
// todo: replace with sqlUis
const { sqlUi } = $(storeToRefs(useProject()))
const abstractType = $computed(() => (column.value?.dt && sqlUi ? sqlUi.getAbstractType(column.value) : null))

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

@ -1,6 +1,7 @@
<script lang="ts" setup>
import type { RequestParams } from 'nocodb-sdk'
import { ExportTypes } from 'nocodb-sdk'
import { storeToRefs } from 'pinia'
import {
ActiveViewInj,
FieldsInj,
@ -27,7 +28,7 @@ const isPublicView = inject(IsPublicInj, ref(false))
const isView = false
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { $api } = useNuxtApp()

4
packages/nc-gui/components/smartsheet/toolbar/RowHeight.vue

@ -1,8 +1,8 @@
<script setup lang="ts">
import type { GridType } from 'nocodb-sdk'
import { ActiveViewInj, IsLockedInj, inject, ref, useMenuCloseOnEsc } from '#imports'
import { ActiveViewInj, IsLockedInj, inject, ref, storeToRefs, useMenuCloseOnEsc } from '#imports'
const { isSharedBase } = useProject()
const { isSharedBase } = storeToRefs(useProject())
const view = inject(ActiveViewInj, ref())

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

@ -9,6 +9,7 @@ import {
message,
projectThemeColors,
ref,
storeToRefs,
useCopy,
useDashboard,
useI18n,
@ -32,7 +33,7 @@ const { dashboardUrl } = useDashboard()
const { isUIAllowed } = useUIPermission()
const { isSharedBase } = useProject()
const { isSharedBase } = storeToRefs(useProject())
let showShareModel = $ref(false)

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

@ -9,6 +9,7 @@ import {
inject,
message,
ref,
storeToRefs,
useI18n,
useMenuCloseOnEsc,
useNuxtApp,
@ -58,7 +59,7 @@ const quickImportDialogs: Record<typeof quickImportDialogTypes[number], Ref<bool
const { isUIAllowed } = useUIPermission()
const { isSharedBase } = useProject()
const { isSharedBase } = storeToRefs(useProject())
const meta = inject(MetaInj, ref())

4
packages/nc-gui/components/tabs/auth/ApiTokenManagement.vue

@ -1,6 +1,6 @@
<script setup lang="ts">
import type { ApiTokenType } from 'nocodb-sdk'
import { extractSdkResponseErrorMsg, message, onMounted, useCopy, useI18n, useNuxtApp, useProject } from '#imports'
import { extractSdkResponseErrorMsg, message, onMounted, storeToRefs, useCopy, useI18n, useNuxtApp, useProject } from '#imports'
interface ApiToken extends ApiTokenType {
show?: boolean
@ -10,7 +10,7 @@ const { t } = useI18n()
const { $api, $e } = useNuxtApp()
const { project } = $(useProject())
const { project } = $(storeToRefs(useProject()))
const { copy } = useCopy()

3
packages/nc-gui/components/tabs/auth/UserManagement.vue

@ -7,6 +7,7 @@ import {
onBeforeMount,
projectRoleTagColors,
ref,
storeToRefs,
useApi,
useCopy,
useDashboard,
@ -24,7 +25,7 @@ const { $e } = useNuxtApp()
const { api } = useApi()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { copy } = useCopy()

14
packages/nc-gui/components/tabs/auth/user-management/ShareBase.vue

@ -1,5 +1,15 @@
<script setup lang="ts">
import { extractSdkResponseErrorMsg, message, onMounted, useCopy, useDashboard, useI18n, useNuxtApp, useProject } from '#imports'
import {
extractSdkResponseErrorMsg,
message,
onMounted,
storeToRefs,
useCopy,
useDashboard,
useI18n,
useNuxtApp,
useProject,
} from '#imports'
interface ShareBase {
uuid?: string
@ -22,7 +32,7 @@ let base = $ref<null | ShareBase>(null)
const showEditBaseDropdown = $ref(false)
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { copy } = useCopy()

3
packages/nc-gui/components/tabs/auth/user-management/UsersModal.vue

@ -9,6 +9,7 @@ import {
projectRoleTagColors,
projectRoles,
ref,
storeToRefs,
useActiveKeyupListener,
useCopy,
useDashboard,
@ -37,7 +38,7 @@ const emit = defineEmits(['closed', 'reload'])
const { t } = useI18n()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { $api, $e } = useNuxtApp()

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

@ -24,6 +24,7 @@ import {
parseStringDate,
reactive,
ref,
storeToRefs,
useI18n,
useNuxtApp,
useProject,
@ -67,7 +68,9 @@ const { $api } = useNuxtApp()
const { addTab } = useTabs()
const { sqlUis, project, loadTables } = useProject()
const projectStrore = useProject()
const { loadTables } = projectStrore
const { sqlUis, project } = storeToRefs(projectStrore)
const sqlUi = ref(sqlUis.value[baseId] || Object.values(sqlUis.value)[0])

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

@ -13,6 +13,7 @@ import {
reactive,
ref,
useApi,
useGlobal,
useI18n,
useNuxtApp,
watch,
@ -32,6 +33,8 @@ const { $e } = useNuxtApp()
const { api, isLoading: loading } = useApi()
const { appInfo } = $(useGlobal())
const meta = inject(MetaInj, ref())
const useForm = Form.useForm
@ -170,7 +173,10 @@ const eventList = [
{ text: ['After', 'Delete'], value: ['after', 'delete'] },
]
const notificationList = [
const notificationList = computed(() => {
return appInfo.isCloud
? [{ type: 'URL' }]
: [
{ type: 'URL' },
{ type: 'Email' },
{ type: 'Slack' },
@ -180,6 +186,7 @@ const notificationList = [
{ type: 'Twilio' },
{ type: 'Whatsapp Twilio' },
]
})
const methodList = [
{ title: 'GET' },
@ -306,6 +313,7 @@ async function onEventChange() {
}
async function loadPluginList() {
if (appInfo.isCloud) return
try {
const plugins = (await api.plugin.list()).list!

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

@ -10,6 +10,7 @@ import {
extractSdkResponseErrorMsg,
message,
ref,
storeToRefs,
useI18n,
useMetas,
useNuxtApp,
@ -27,7 +28,9 @@ interface ValidationsObj {
const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState(
(meta: Ref<TableType | undefined>, column: Ref<ColumnType | undefined>) => {
const { project, sqlUis, isMysql: isMysqlFunc, isPg: isPgFunc, isMssql: isMssqlFunc } = useProject()
const projectStore = useProject()
const { isMysql: isMysqlFunc, isPg: isPgFunc, isMssql: isMssqlFunc } = projectStore
const { project, sqlUis } = storeToRefs(projectStore)
const { $api } = useNuxtApp()

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

@ -11,6 +11,7 @@ import {
message,
populateInsertObject,
ref,
storeToRefs,
useApi,
useI18n,
useInjectionState,
@ -42,7 +43,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
const changedColumns = ref(new Set<string>())
const { project } = useProject()
const { project } = storeToRefs(useProject())
const rowStore = useProvideSmartsheetRowStore(meta, row)

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

@ -99,6 +99,7 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
version: '0.0.0',
ncAttachmentFieldSize: 20,
ncMaxAttachmentsAllowed: 10,
isCloud: false,
})
/** reactive token payload */

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

@ -22,6 +22,7 @@ export interface AppInfo {
ee?: boolean
ncAttachmentFieldSize: number
ncMaxAttachmentsAllowed: number
isCloud: boolean
}
export interface StoredState {

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

@ -13,6 +13,7 @@ import {
message,
provide,
ref,
storeToRefs,
useApi,
useFieldQuery,
useI18n,
@ -40,7 +41,7 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState(
const { api } = useApi()
const { project } = useProject()
const { project, sqlUis } = storeToRefs(useProject())
const { $e, $api } = useNuxtApp()
@ -56,8 +57,6 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState(
const { search } = useFieldQuery()
const { sqlUis } = useProject()
const sqlUi = ref(
(meta.value as TableType)?.base_id ? sqlUis.value[(meta.value as TableType).base_id!] : Object.values(sqlUis.value)[0],
)

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

@ -11,6 +11,7 @@ import {
message,
reactive,
ref,
storeToRefs,
useI18n,
useInjectionState,
useMetas,
@ -38,7 +39,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
// state
const { metas, getMeta } = useMetas()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { $api } = useNuxtApp()

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

@ -1,7 +1,7 @@
import { reactive } from 'vue'
import type { ComputedRef, Ref } from 'vue'
import type { ColumnType, MapType, PaginatedType, TableType, ViewType } from 'nocodb-sdk'
import { IsPublicInj, ref, useInjectionState, useMetas, useProject } from '#imports'
import { IsPublicInj, ref, storeToRefs, useInjectionState, useMetas, useProject } from '#imports'
import type { Row } from '~/lib'
const storedValue = localStorage.getItem('geodataToggleState')
@ -35,7 +35,7 @@ const [useProvideMapViewStore, useMapViewStore] = useInjectionState(
const { api } = useApi()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { $api } = useNuxtApp()

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

@ -1,12 +1,12 @@
import { message } from 'ant-design-vue'
import type { WatchStopHandle } from 'vue'
import type { TableInfoType, TableType } from 'nocodb-sdk'
import { extractSdkResponseErrorMsg, useNuxtApp, useProject, useState, watch } from '#imports'
import { extractSdkResponseErrorMsg, storeToRefs, useNuxtApp, useProject, useState, watch } from '#imports'
export function useMetas() {
const { $api } = useNuxtApp()
const { tables } = useProject()
const { tables } = storeToRefs(useProject())
const metas = useState<{ [idOrTitle: string]: TableType | any }>('metas', () => ({}))

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

@ -12,10 +12,12 @@ import {
message,
provide,
ref,
storeToRefs,
useApi,
useI18n,
useInjectionState,
useMetas,
useProject,
useProvideSmartsheetRowStore,
watch,
} from '#imports'
@ -43,7 +45,8 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
const { metas, setMeta } = useMetas()
const { project } = useProject()
const projectStore = useProject()
const { project } = storeToRefs(projectStore)
const { t } = useI18n()
@ -88,14 +91,14 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
// if project is not defined then set it with an object containing base
if (!project.value?.bases)
project.value = {
projectStore.setProject({
bases: [
{
id: viewMeta.base_id,
type: viewMeta.client,
},
],
}
})
const relatedMetas = { ...viewMeta.relatedMetas }

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

@ -1,13 +1,13 @@
import type { ExportTypes, FilterType, KanbanType, PaginatedType, RequestParams, SortType, TableType, ViewType } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk'
import { computed, useGlobal, useMetas, useNuxtApp, useState } from '#imports'
import { computed, storeToRefs, useGlobal, useMetas, useNuxtApp, useState } from '#imports'
export function useSharedView() {
const nestedFilters = ref<(FilterType & { status?: 'update' | 'delete' | 'create'; parentId?: string })[]>([])
const { appInfo } = $(useGlobal())
const { project } = useProject()
const { project } = storeToRefs(useProject())
const appInfoDefaultLimit = appInfo.defaultLimit || 25

3
packages/nc-gui/composables/useSmartsheetRowStore.ts

@ -13,6 +13,7 @@ import {
isMm,
message,
ref,
storeToRefs,
unref,
useI18n,
useInjectionState,
@ -28,7 +29,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
const { t } = useI18n()
const { project } = useProject()
const { project } = storeToRefs(useProject())
const { metas } = useMetas()

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

@ -1,7 +1,17 @@
import { ViewTypes } from 'nocodb-sdk'
import type { FilterType, KanbanType, SortType, TableType, ViewType } from 'nocodb-sdk'
import type { Ref } from 'vue'
import { computed, ref, unref, useEventBus, useFieldQuery, useInjectionState, useNuxtApp, useProject } from '#imports'
import {
computed,
ref,
storeToRefs,
unref,
useEventBus,
useFieldQuery,
useInjectionState,
useNuxtApp,
useProject,
} from '#imports'
import type { SmartsheetStoreEvents } from '~/lib'
const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
@ -14,7 +24,9 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
) => {
const { $api } = useNuxtApp()
const { sqlUis } = useProject()
const projectStore = useProject()
const { sqlUis } = storeToRefs(projectStore)
const sqlUi = ref(
(meta.value as TableType)?.base_id ? sqlUis.value[(meta.value as TableType).base_id!] : Object.values(sqlUis.value)[0],

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

@ -7,6 +7,7 @@ import {
generateUniqueTitle as generateTitle,
message,
reactive,
storeToRefs,
useI18n,
useMetas,
useNuxtApp,
@ -32,7 +33,8 @@ export function useTable(onTableCreate?: (tableMeta: TableType) => void, baseId?
const { loadTables } = useProject()
const { closeTab } = useTabs()
const { sqlUis, project, tables } = useProject()
const projectStore = useProject()
const { sqlUis, project, tables } = storeToRefs(projectStore)
const sqlUi = computed(() => (baseId && sqlUis.value[baseId] ? sqlUis.value[baseId] : Object.values(sqlUis.value)[0]))

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

@ -1,7 +1,7 @@
import { ViewTypes, isSystemColumn } from 'nocodb-sdk'
import type { ColumnType, MapType, TableType, ViewType } from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue'
import { IsPublicInj, computed, inject, ref, useNuxtApp, useProject, useUIPermission, watch } from '#imports'
import { IsPublicInj, computed, inject, ref, storeToRefs, useNuxtApp, useProject, useUIPermission, watch } from '#imports'
import type { Field } from '~/lib'
export function useViewColumns(
@ -19,7 +19,7 @@ export function useViewColumns(
const { isUIAllowed } = useUIPermission()
const { isSharedBase } = useProject()
const { isSharedBase } = storeToRefs(useProject())
const isLocalMode = computed(
() => isPublic.value || !isUIAllowed('hideAllColumns') || !isUIAllowed('showAllColumns') || isSharedBase.value,

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

@ -12,6 +12,7 @@ import {
message,
populateInsertObject,
ref,
storeToRefs,
until,
useApi,
useGlobal,
@ -70,7 +71,7 @@ export function useViewData(
const isPublic = inject(IsPublicInj, ref(false))
const { project, isSharedBase } = useProject()
const { project, isSharedBase } = storeToRefs(useProject())
const { sharedView, fetchSharedViewData, paginationData: sharedPaginationData } = useSharedView()

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

@ -11,6 +11,7 @@ import {
inject,
message,
ref,
storeToRefs,
useDebounceFn,
useMetas,
useNuxtApp,
@ -35,7 +36,7 @@ export function useViewFilters(
const { nestedFilters } = useSmartsheetStoreOrThrow()
const { projectMeta } = useProject()
const { projectMeta } = storeToRefs(useProject())
const isPublic = inject(IsPublicInj, ref(false))

3
packages/nc-gui/composables/useViewSorts.ts

@ -7,6 +7,7 @@ import {
inject,
message,
ref,
storeToRefs,
useNuxtApp,
useProject,
useSharedView,
@ -24,7 +25,7 @@ export function useViewSorts(view: Ref<ViewType | undefined>, reloadData?: () =>
const { isUIAllowed } = useUIPermission()
const { isSharedBase } = useProject()
const { isSharedBase } = storeToRefs(useProject())
const reloadHook = inject(ReloadViewDataHookInj)

5
packages/nc-gui/nuxt.config.ts

@ -12,7 +12,7 @@ import PurgeIcons from 'vite-plugin-purge-icons'
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
modules: ['@vueuse/nuxt', 'nuxt-windicss', '@nuxt/image-edge'],
modules: ['@vueuse/nuxt', 'nuxt-windicss', '@nuxt/image-edge', '@pinia/nuxt'],
ssr: false,
@ -190,7 +190,7 @@ export default defineNuxtConfig({
},
imports: {
dirs: ['./context', './utils/**', './lib', './composables/**'],
dirs: ['./context', './utils/**', './lib', './composables/**', './store/**'],
imports: [
{ name: 'useI18n', from: 'vue-i18n' },
{ name: 'message', from: 'ant-design-vue/es' },
@ -198,6 +198,7 @@ export default defineNuxtConfig({
{ name: 'Empty', from: 'ant-design-vue/es' },
{ name: 'Form', from: 'ant-design-vue/es' },
{ name: 'useJwt', from: '@vueuse/integrations/useJwt' },
{ name: 'storeToRefs', from: 'pinia' },
],
},
})

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

File diff suppressed because it is too large Load Diff

5
packages/nc-gui/package.json

@ -33,6 +33,7 @@
"dependencies": {
"@ckpack/vue-color": "^1.2.0",
"@iconify/vue": "^4.0.1",
"@pinia/nuxt": "^0.4.7",
"@types/file-saver": "^2.0.5",
"@vue-flow/additional-components": "^1.2.0",
"@vue-flow/core": "^1.3.0",
@ -56,6 +57,7 @@
"monaco-editor": "^0.33.0",
"nocodb-sdk": "file:../nocodb-sdk",
"papaparse": "^5.3.2",
"pinia": "^2.0.33",
"qrcode": "^1.5.1",
"socket.io-client": "^4.5.1",
"sortablejs": "^1.15.0",
@ -123,5 +125,8 @@
"vite-plugin-purge-icons": "^0.9.0",
"vitest": "^0.18.0",
"windicss": "^3.5.6"
},
"overrides": {
"vue": "latest"
}
}

8
packages/nc-gui/pages/[projectType]/[projectId]/index.vue

@ -17,6 +17,7 @@ import {
projectThemeColors,
ref,
resolveComponent,
storeToRefs,
useCopy,
useDialog,
useGlobal,
@ -46,7 +47,10 @@ const router = useRouter()
const { appInfo, token, signOut, signedIn, user, currentVersion } = useGlobal()
const { project, isSharedBase, loadProjectMetaInfo, projectMetaInfo, saveTheme, loadProject, reset } = useProject()
const projectStore = useProject()
const { loadProjectMetaInfo, saveTheme, loadProject, reset } = projectStore
const { project, isSharedBase, projectMetaInfo } = storeToRefs(projectStore)
const { clearTabs, addTab } = useTabs()
@ -577,9 +581,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
v-model:open-key="openDialogKey"
v-model:data-sources-state="dataSourcesState"
/>
<NuxtPage :page-key="$route.params.projectId" />
<LazyGeneralPreviewAs float />
</div>
</NuxtLayout>

6
packages/nc-gui/pages/[projectType]/[projectId]/index/index.vue

@ -2,9 +2,11 @@
import { Icon } from '@iconify/vue'
import type { TabItem } from '~/lib'
import { TabType } from '~/lib'
import { TabMetaInj, iconMap, provide, useGlobal, useSidebar, useTabs } from '#imports'
import { TabMetaInj, iconMap, provide, storeToRefs, useGlobal, useSidebar, useTabs } from '#imports'
const { tabs, activeTabIndex, activeTab, closeTab } = useTabs()
const tabStore = useTabs()
const { closeTab } = tabStore
const { tabs, activeTabIndex, activeTab } = storeToRefs(tabStore)
const { isLoading } = useGlobal()

5
packages/nc-gui/pages/[projectType]/[projectId]/index/index/[type]/[title]/[[viewTitle]].vue

@ -1,10 +1,11 @@
<script setup lang="ts">
import type { TabItem } from '~/lib'
import { TabMetaInj, computed, inject, ref, until, useMetas, useProject, useRoute } from '#imports'
import { TabMetaInj, computed, inject, ref, storeToRefs, until, useMetas, useProject, useRoute } from '#imports'
const { getMeta } = useMetas()
const { tables } = useProject()
const projectStore = useProject()
const { tables } = storeToRefs(projectStore)
const route = useRoute()

5
packages/nc-gui/pages/[projectType]/[projectId]/index/index/index.vue

@ -5,6 +5,7 @@ import {
message,
ref,
resolveComponent,
storeToRefs,
useDialog,
useDropZone,
useFileDialog,
@ -20,7 +21,9 @@ const { isOverDropZone } = useDropZone(dropZone, onDrop)
const { files, open, reset } = useFileDialog()
const { bases, isSharedBase } = useProject()
const projectStore = useProject()
const { bases, isSharedBase } = storeToRefs(projectStore)
const { isUIAllowed } = useUIPermission()

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

@ -2,8 +2,11 @@
import { navigateTo, useUIPermission } from '#imports'
const { isUIAllowed } = useUIPermission()
const $route = useRoute()
const { appInfo } = useGlobal()
const selectedKeys = computed(() => [
/^\/account\/users\/?$/.test($route.fullPath)
? isUIAllowed('superAdminUserManagement')
@ -68,7 +71,7 @@ const openKeys = ref([/^\/account\/users/.test($route.fullPath) && 'users'])
</div>
</a-menu-item>
<a-menu-item
v-if="isUIAllowed('appStore')"
v-if="isUIAllowed('appStore') && !appInfo.isCloud"
key="apps"
class="group active:(!ring-0) hover:(!bg-primary !bg-opacity-25)"
@click="navigateTo('/account/apps')"

6
packages/nc-gui/pages/account/index/[page].vue

@ -1,7 +1,11 @@
<script setup lang="ts">
const { appInfo } = useGlobal()
</script>
<template>
<AccountUserManagement v-if="$route.params.page === 'users'" />
<AccountToken v-else-if="$route.params.page === 'tokens'" />
<AccountAppStore v-else-if="$route.params.page === 'apps'" />
<AccountAppStore v-else-if="$route.params.page === 'apps' && !appInfo.isCloud" />
<AccountLicense v-else-if="$route.params.page === 'license'" />
<span v-else></span>
</template>

6
packages/nc-gui/pages/index/index/[projectId].vue

@ -10,13 +10,17 @@ import {
projectTitleValidator,
reactive,
ref,
storeToRefs,
useProject,
useRoute,
} from '#imports'
const route = useRoute()
const { project, loadProject, updateProject, isLoading } = useProject()
const projectStore = useProject()
const { loadProject, updateProject } = projectStore
const { project, isLoading } = storeToRefs(projectStore)
const nameValidationRules = [
{

9
packages/nc-gui/composables/useProject.ts → packages/nc-gui/store/project.ts

@ -1,11 +1,11 @@
import type { BaseType, OracleUi, ProjectType, TableType } from 'nocodb-sdk'
import { SqlUiFactory } from 'nocodb-sdk'
import { isString } from '@vueuse/core'
import { defineStore } from 'pinia'
import {
ClientType,
computed,
createEventHook,
createSharedComposable,
ref,
useApi,
useGlobal,
@ -16,7 +16,7 @@ import {
} from '#imports'
import type { ProjectMetaInfo, ThemeConfig } from '~/lib'
export const useProject = createSharedComposable(() => {
export const useProject = defineStore('projectStore', () => {
const { $e } = useNuxtApp()
const { api, isLoading } = useApi()
@ -186,6 +186,10 @@ export const useProject = createSharedComposable(() => {
setTheme()
}
const setProject = (projectVal: ProjectType) => {
project.value = projectVal
}
watch(
() => route.params.projectType,
(n) => {
@ -217,5 +221,6 @@ export const useProject = createSharedComposable(() => {
lastOpenedViewMap,
isXcdbBase,
hasEmptyOrNullFilters,
setProject,
}
})

21
packages/nc-gui/composables/useTabs.ts → packages/nc-gui/store/tab.ts

@ -1,5 +1,6 @@
import type { WritableComputedRef } from '@vue/reactivity'
import { computed, createSharedComposable, navigateTo, ref, useProject, useRouter, watch } from '#imports'
import { defineStore } from 'pinia'
import { computed, navigateTo, ref, useProject, useRouter, watch } from '#imports'
import type { TabItem } from '~/lib'
import { TabType } from '~/lib'
@ -10,14 +11,14 @@ function getPredicate(key: Partial<TabItem>) {
(!('type' in key) || tab.type === key.type)
}
export const useTabs = createSharedComposable(() => {
export const useTabs = defineStore('tabStore', () => {
const tabs = ref<TabItem[]>([])
const router = useRouter()
const route = $(router.currentRoute)
const { bases, tables } = useProject()
const projectStore = useProject()
const projectType = $computed(() => route.params.projectType as string)
@ -26,14 +27,14 @@ export const useTabs = createSharedComposable(() => {
get() {
const routeName = route.name as string
if (routeName.startsWith('projectType-projectId-index-index-type-title-viewTitle') && tables.value.length) {
if (routeName.startsWith('projectType-projectId-index-index-type-title-viewTitle') && projectStore.tables.length) {
const tab: TabItem = { type: route.params.type as TabType, title: route.params.title as string }
const currentTable = tables.value.find((t) => t.id === tab.title || t.title === tab.title)
const currentTable = projectStore.tables.find((t) => t.id === tab.title || t.title === tab.title)
if (!currentTable) return -1
const currentBase = bases.value.find((b) => b.id === currentTable.base_id)
const currentBase = projectStore.bases.find((b) => b.id === currentTable.base_id)
tab.id = currentTable.id
@ -44,7 +45,7 @@ export const useTabs = createSharedComposable(() => {
tab.meta = currentTable.meta
// append base alias to tab title if duplicate titles exist on other bases
if (tables.value.find((t) => t.title === currentTable?.title && t.base_id !== currentTable?.base_id))
if (projectStore.tables.find((t) => t.title === currentTable?.title && t.base_id !== currentTable?.base_id))
tab.title = `${tab.title}${currentBase?.alias ? ` (${currentBase.alias})` : ``}`
if (index === -1) {
@ -91,13 +92,13 @@ export const useTabs = createSharedComposable(() => {
}
// if tab not found add it
else {
const currentTable = tables.value.find((t) => t.id === tabMeta.id || t.title === tabMeta.id)
const currentBase = bases.value.find((b) => b.id === currentTable?.base_id)
const currentTable = projectStore.tables.find((t) => t.id === tabMeta.id || t.title === tabMeta.id)
const currentBase = projectStore.bases.find((b) => b.id === currentTable?.base_id)
tabMeta.meta = currentTable?.meta
// append base alias to tab title if duplicate titles exist on other bases
if (tables.value.find((t) => t.title === currentTable?.title && t.base_id !== currentTable?.base_id))
if (projectStore.tables.find((t) => t.title === currentTable?.title && t.base_id !== currentTable?.base_id))
tabMeta.title = `${tabMeta.title}${currentBase?.alias ? ` (${currentBase.alias})` : ``}`
tabs.value = [...(tabs.value || []), tabMeta]

7
packages/nocodb-sdk/src/lib/formulaHelpers.ts

@ -179,9 +179,8 @@ export function jsepTreeToFormula(node) {
if (node.type === 'Literal') {
if (typeof node.value === 'string') {
return '"' + node.value + '"';
return String.raw`"${escapeDoubleQuotes(node.value)}"`;
}
return '' + node.value;
}
@ -214,3 +213,7 @@ export function jsepTreeToFormula(node) {
return '';
}
function escapeDoubleQuotes(v: string) {
return v.replace(/"/g, '\\"');
}

13
packages/nocodb/src/lib/controllers/plugin.ctl.ts

@ -17,6 +17,7 @@ export async function pluginTest(req: Request<any, any>, res: Response) {
export async function pluginRead(req: Request, res: Response) {
res.json(await pluginService.pluginRead({ pluginId: req.params.pluginId }));
}
export async function pluginUpdate(
req: Request<any, any, PluginType>,
res: Response
@ -27,36 +28,48 @@ export async function pluginUpdate(
});
res.json(plugin);
}
export async function isPluginActive(req: Request, res: Response) {
res.json(
await pluginService.isPluginActive({ pluginTitle: req.params.pluginTitle })
);
}
const blockInCloudMw = (_req, res, next) => {
if (process.env.NC_CLOUD === 'true') {
res.status(403).send('Not allowed');
} else next();
};
const router = Router({ mergeParams: true });
router.get(
'/api/v1/db/meta/plugins',
blockInCloudMw,
metaApiMetrics,
ncMetaAclMw(pluginList, 'pluginList')
);
router.post(
'/api/v1/db/meta/plugins/test',
metaApiMetrics,
blockInCloudMw,
ncMetaAclMw(pluginTest, 'pluginTest')
);
router.get(
'/api/v1/db/meta/plugins/:pluginId',
metaApiMetrics,
blockInCloudMw,
ncMetaAclMw(pluginRead, 'pluginRead')
);
router.patch(
'/api/v1/db/meta/plugins/:pluginId',
metaApiMetrics,
blockInCloudMw,
ncMetaAclMw(pluginUpdate, 'pluginUpdate')
);
router.get(
'/api/v1/db/meta/plugins/:pluginTitle/status',
metaApiMetrics,
blockInCloudMw,
ncMetaAclMw(isPluginActive, 'isPluginActive')
);
export default router;

5
packages/nocodb/src/lib/services/column.svc.ts

@ -1548,7 +1548,10 @@ async function createLTARColumn(param: {
// todo: create index for virtual relations as well
// create index for foreign key in pg
if (param.base.type === 'pg') {
if (
param.base.type === 'pg' ||
(param.column as LinkToAnotherColumnReqType).virtual
) {
await createColumnIndex({
column: new Column({
...newColumn,

22
packages/nocodb/src/lib/services/hook.svc.ts

@ -1,10 +1,25 @@
import { T } from 'nc-help';
import { validatePayload } from '../meta/api/helpers';
import { NcError } from '../meta/helpers/catchError';
import { Hook, Model } from '../models';
import { invokeWebhook } from '../meta/helpers/webhookHelpers';
import populateSamplePayload from '../meta/helpers/populateSamplePayload';
import type { HookReqType, HookTestReqType } from 'nocodb-sdk';
function validateHookPayload(notificationJsonOrObject: string | object) {
let notification: { type?: string } = {};
try {
notification =
typeof notificationJsonOrObject === 'string'
? JSON.parse(notificationJsonOrObject)
: notificationJsonOrObject;
} catch {}
if (notification.type !== 'URL' && process.env.NC_CLOUD === 'true') {
NcError.badRequest('Only URL notification is supported');
}
}
export async function hookList(param: { tableId: string }) {
return await Hook.list({ fk_model_id: param.tableId });
}
@ -15,6 +30,8 @@ export async function hookCreate(param: {
}) {
validatePayload('swagger.json#/components/schemas/HookReq', param.hook);
validateHookPayload(param.hook.notification);
T.emit('evt', { evt_type: 'webhooks:created' });
// todo: type correction
const hook = await Hook.insert({
@ -35,6 +52,8 @@ export async function hookUpdate(param: { hookId: string; hook: HookReqType }) {
T.emit('evt', { evt_type: 'webhooks:updated' });
validateHookPayload(param.hook.notification);
// todo: correction in swagger
return await Hook.update(param.hookId, param.hook as any);
}
@ -48,6 +67,8 @@ export async function hookTest(param: {
param.hookTest
);
validateHookPayload(param.hookTest.hook?.notification);
const model = await Model.getByIdOrName({ id: param.tableId });
const {
@ -67,6 +88,7 @@ export async function hookTest(param: {
return true;
}
export async function tableSampleData(param: {
tableId: string;
operation: 'insert' | 'update';

1
packages/nocodb/src/lib/services/util.svc.ts

@ -55,6 +55,7 @@ export async function appInfo(param: { req: { ncSiteUrl: string } }) {
ee: Noco.isEE(),
ncAttachmentFieldSize: NC_ATTACHMENT_FIELD_SIZE,
ncMaxAttachmentsAllowed: +(process.env.NC_MAX_ATTACHMENTS_ALLOWED || 10),
isCloud: process.env.NC_CLOUD === 'true',
};
return result;

67
packages/nocodb/src/lib/utils/common/helpers/jsepTreeToFormula.ts

@ -1,67 +0,0 @@
export default function jsepTreeToFormula(node) {
if (node.type === 'BinaryExpression' || node.type === 'LogicalExpression') {
return (
'(' +
jsepTreeToFormula(node.left) +
' ' +
node.operator +
' ' +
jsepTreeToFormula(node.right) +
')'
);
}
if (node.type === 'UnaryExpression') {
return node.operator + jsepTreeToFormula(node.argument);
}
if (node.type === 'MemberExpression') {
return (
jsepTreeToFormula(node.object) +
'[' +
jsepTreeToFormula(node.property) +
']'
);
}
if (node.type === 'Identifier') {
return node.name;
}
if (node.type === 'Literal') {
if (typeof node.value === 'string') {
return '"' + node.value + '"';
}
return '' + node.value;
}
if (node.type === 'CallExpression') {
return (
jsepTreeToFormula(node.callee) +
'(' +
node.arguments.map(jsepTreeToFormula).join(', ') +
')'
);
}
if (node.type === 'ArrayExpression') {
return '[' + node.elements.map(jsepTreeToFormula).join(', ') + ']';
}
if (node.type === 'Compound') {
return node.body.map((e) => jsepTreeToFormula(e)).join(' ');
}
if (node.type === 'ConditionalExpression') {
return (
jsepTreeToFormula(node.test) +
' ? ' +
jsepTreeToFormula(node.consequent) +
' : ' +
jsepTreeToFormula(node.alternate)
);
}
return '';
}

2
packages/nocodb/src/lib/utils/common/helpers/updateColumnNameInFormula.ts

@ -1,4 +1,4 @@
import jsepTreeToFormula from './jsepTreeToFormula';
import { jsepTreeToFormula } from 'nocodb-sdk';
export default function (args: {
virtualColumns;

Loading…
Cancel
Save