Browse Source

Merge branch 'develop' into feat/gui-v2-misc

pull/3157/head
Wing-Kam Wong 2 years ago
parent
commit
4ee0fa2d56
  1. 25
      packages/nc-gui-v2/components.d.ts
  2. 4
      packages/nc-gui-v2/components/api-client/Headers.vue
  3. 15
      packages/nc-gui-v2/components/cell/DatePicker.vue
  4. 67
      packages/nc-gui-v2/components/cell/MultiSelect.vue
  5. 22
      packages/nc-gui-v2/components/cell/SingleSelect.vue
  6. 15
      packages/nc-gui-v2/components/cell/Url.vue
  7. 15
      packages/nc-gui-v2/components/cell/YearPicker.vue
  8. 4
      packages/nc-gui-v2/components/cell/attachment/utils.ts
  9. 2
      packages/nc-gui-v2/components/dashboard/TreeView.vue
  10. 14
      packages/nc-gui-v2/components/dashboard/settings/app-store/AppInstall.vue
  11. 32
      packages/nc-gui-v2/components/general/ColorPicker.vue
  12. 13
      packages/nc-gui-v2/components/smartsheet-column/EditOrAdd.vue
  13. 15
      packages/nc-gui-v2/components/smartsheet-column/FormulaOptions.vue
  14. 17
      packages/nc-gui-v2/components/smartsheet-column/LookupOptions.vue
  15. 6
      packages/nc-gui-v2/components/smartsheet-header/Cell.vue
  16. 34
      packages/nc-gui-v2/components/smartsheet-header/VirtualCell.vue
  17. 17
      packages/nc-gui-v2/components/smartsheet-toolbar/ColumnFilter.vue
  18. 60
      packages/nc-gui-v2/components/smartsheet-toolbar/MoreActions.vue
  19. 12
      packages/nc-gui-v2/components/smartsheet-toolbar/SearchData.vue
  20. 6
      packages/nc-gui-v2/components/smartsheet/Cell.vue
  21. 83
      packages/nc-gui-v2/components/smartsheet/Form.vue
  22. 16
      packages/nc-gui-v2/components/smartsheet/Pagination.vue
  23. 38
      packages/nc-gui-v2/components/smartsheet/VirtualCell.vue
  24. 8
      packages/nc-gui-v2/components/smartsheet/expanded-form/Comments.vue
  25. 8
      packages/nc-gui-v2/components/smartsheet/expanded-form/Header.vue
  26. 47
      packages/nc-gui-v2/components/smartsheet/expanded-form/index.vue
  27. 30
      packages/nc-gui-v2/components/smartsheet/sidebar/menu/ApiSnippet.vue
  28. 9
      packages/nc-gui-v2/components/tabs/auth/user-management/ShareBase.vue
  29. 55
      packages/nc-gui-v2/components/template/Editor.vue
  30. 29
      packages/nc-gui-v2/components/virtual-cell/BelongsTo.vue
  31. 4
      packages/nc-gui-v2/components/virtual-cell/Formula.vue
  32. 27
      packages/nc-gui-v2/components/virtual-cell/HasMany.vue
  33. 12
      packages/nc-gui-v2/components/virtual-cell/Lookup.vue
  34. 24
      packages/nc-gui-v2/components/virtual-cell/ManyToMany.vue
  35. 2
      packages/nc-gui-v2/components/virtual-cell/Rollup.vue
  36. 26
      packages/nc-gui-v2/components/virtual-cell/components/ItemChip.vue
  37. 21
      packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue
  38. 19
      packages/nc-gui-v2/components/virtual-cell/components/ListItems.vue
  39. 66
      packages/nc-gui-v2/components/webhook/ChannelMultiSelect.vue
  40. 2
      packages/nc-gui-v2/components/webhook/Drawer.vue
  41. 93
      packages/nc-gui-v2/components/webhook/Editor.vue
  42. 10
      packages/nc-gui-v2/components/webhook/List.vue
  43. 2
      packages/nc-gui-v2/components/webhook/Test.vue
  44. 14
      packages/nc-gui-v2/composables/useColumnCreateStore.ts
  45. 26
      packages/nc-gui-v2/composables/useExpandedFormStore.ts
  46. 16
      packages/nc-gui-v2/composables/useGlobal/state.ts
  47. 2
      packages/nc-gui-v2/composables/useGlobal/types.ts
  48. 33
      packages/nc-gui-v2/composables/useLTARStore.ts
  49. 16
      packages/nc-gui-v2/composables/useSmartsheetRowStore.ts
  50. 7
      packages/nc-gui-v2/composables/useUIPermission/index.ts
  51. 3
      packages/nc-gui-v2/composables/useViewColumns.ts
  52. 24
      packages/nc-gui-v2/composables/useViewData.ts
  53. 24
      packages/nc-gui-v2/composables/useViewFilters.ts
  54. 5
      packages/nc-gui-v2/composables/useViews.ts
  55. 3
      packages/nc-gui-v2/httpsnippet-shims.d.ts
  56. 1
      packages/nc-gui-v2/just-clone-shims.d.ts
  57. 17
      packages/nc-gui-v2/nuxt.config.ts
  58. 353
      packages/nc-gui-v2/package-lock.json
  59. 5
      packages/nc-gui-v2/package.json
  60. 33
      packages/nc-gui-v2/pages/[projectType]/[projectId]/index/index.vue
  61. 6
      packages/nc-gui-v2/pages/forgot-password.vue
  62. 11
      packages/nc-gui-v2/pages/index/index.vue
  63. 6
      packages/nc-gui-v2/pages/signin.vue
  64. 2
      packages/nc-gui-v2/pages/signup/[[token]].vue
  65. 10
      packages/nc-gui-v2/plugins/a.dayjs.ts
  66. 2
      packages/nc-gui-v2/utils/columnUtils.ts
  67. 2
      packages/nc-gui-v2/utils/dateTimeUtils.ts
  68. 1
      packages/nc-gui-v2/vue-color-shims.d.ts

25
packages/nc-gui-v2/components.d.ts vendored

@ -12,7 +12,6 @@ declare module '@vue/runtime-core' {
ABadgeRibbon: typeof import('ant-design-vue/es')['BadgeRibbon'] ABadgeRibbon: typeof import('ant-design-vue/es')['BadgeRibbon']
AButton: typeof import('ant-design-vue/es')['Button'] AButton: typeof import('ant-design-vue/es')['Button']
ACard: typeof import('ant-design-vue/es')['Card'] ACard: typeof import('ant-design-vue/es')['Card']
ACardMeta: typeof import('ant-design-vue/es')['CardMeta']
ACarousel: typeof import('ant-design-vue/es')['Carousel'] ACarousel: typeof import('ant-design-vue/es')['Carousel']
ACheckbox: typeof import('ant-design-vue/es')['Checkbox'] ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
ACol: typeof import('ant-design-vue/es')['Col'] ACol: typeof import('ant-design-vue/es')['Col']
@ -65,6 +64,7 @@ declare module '@vue/runtime-core' {
AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger'] AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']
CilFullscreen: typeof import('~icons/cil/fullscreen')['default'] CilFullscreen: typeof import('~icons/cil/fullscreen')['default']
CilFullscreenExit: typeof import('~icons/cil/fullscreen-exit')['default'] CilFullscreenExit: typeof import('~icons/cil/fullscreen-exit')['default']
ClaritySuccessLine: typeof import('~icons/clarity/success-line')['default']
EvaEmailOutline: typeof import('~icons/eva/email-outline')['default'] EvaEmailOutline: typeof import('~icons/eva/email-outline')['default']
IcBaselineMoreVert: typeof import('~icons/ic/baseline-more-vert')['default'] IcBaselineMoreVert: typeof import('~icons/ic/baseline-more-vert')['default']
IcOutlineInsertDriveFile: typeof import('~icons/ic/outline-insert-drive-file')['default'] IcOutlineInsertDriveFile: typeof import('~icons/ic/outline-insert-drive-file')['default']
@ -76,15 +76,14 @@ declare module '@vue/runtime-core' {
MaterialSymbolsChevronRightRounded: typeof import('~icons/material-symbols/chevron-right-rounded')['default'] MaterialSymbolsChevronRightRounded: typeof import('~icons/material-symbols/chevron-right-rounded')['default']
MaterialSymbolsCloseRounded: typeof import('~icons/material-symbols/close-rounded')['default'] MaterialSymbolsCloseRounded: typeof import('~icons/material-symbols/close-rounded')['default']
MaterialSymbolsFileCopyOutline: typeof import('~icons/material-symbols/file-copy-outline')['default'] MaterialSymbolsFileCopyOutline: typeof import('~icons/material-symbols/file-copy-outline')['default']
MaterialSymbolsRocketLaunchOutline: typeof import('~icons/material-symbols/rocket-launch-outline')['default']
MaterialSymbolsSendOutline: typeof import('~icons/material-symbols/send-outline')['default'] MaterialSymbolsSendOutline: typeof import('~icons/material-symbols/send-outline')['default']
MaterialSymbolsTranslate: typeof import('~icons/material-symbols/translate')['default'] MaterialSymbolsTranslate: typeof import('~icons/material-symbols/translate')['default']
MaterialSymbolsWarning: typeof import('~icons/material-symbols/warning')['default'] MaterialSymbolsWarning: typeof import('~icons/material-symbols/warning')['default']
MdiAccountCircle: typeof import('~icons/mdi/account-circle')['default'] MdiAccountCircle: typeof import('~icons/mdi/account-circle')['default']
MdiAccountGroup: typeof import('~icons/mdi/account-group')['default'] MdiAccountGroup: typeof import('~icons/mdi/account-group')['default']
MdiAccountIcon: typeof import('~icons/mdi/account-icon')['default']
MdiAccountOutline: typeof import('~icons/mdi/account-outline')['default'] MdiAccountOutline: typeof import('~icons/mdi/account-outline')['default']
MdiAccountPlusOutline: typeof import('~icons/mdi/account-plus-outline')['default'] MdiAccountPlusOutline: typeof import('~icons/mdi/account-plus-outline')['default']
MdiAccountSupervisorOutline: typeof import('~icons/mdi/account-supervisor-outline')['default']
MdiAlphaA: typeof import('~icons/mdi/alpha-a')['default'] MdiAlphaA: typeof import('~icons/mdi/alpha-a')['default']
MdiApi: typeof import('~icons/mdi/api')['default'] MdiApi: typeof import('~icons/mdi/api')['default']
MdiArrowExpand: typeof import('~icons/mdi/arrow-expand')['default'] MdiArrowExpand: typeof import('~icons/mdi/arrow-expand')['default']
@ -92,7 +91,6 @@ declare module '@vue/runtime-core' {
MdiAt: typeof import('~icons/mdi/at')['default'] MdiAt: typeof import('~icons/mdi/at')['default']
MdiBugOutline: typeof import('~icons/mdi/bug-outline')['default'] MdiBugOutline: typeof import('~icons/mdi/bug-outline')['default']
MdiCalculator: typeof import('~icons/mdi/calculator')['default'] MdiCalculator: typeof import('~icons/mdi/calculator')['default']
MdiCalendarMonth: typeof import('~icons/mdi/calendar-month')['default']
MdiCardsHeart: typeof import('~icons/mdi/cards-heart')['default'] MdiCardsHeart: typeof import('~icons/mdi/cards-heart')['default']
MdiCellphoneMessage: typeof import('~icons/mdi/cellphone-message')['default'] MdiCellphoneMessage: typeof import('~icons/mdi/cellphone-message')['default']
MdiChat: typeof import('~icons/mdi/chat')['default'] MdiChat: typeof import('~icons/mdi/chat')['default']
@ -101,27 +99,30 @@ declare module '@vue/runtime-core' {
MdiClose: typeof import('~icons/mdi/close')['default'] MdiClose: typeof import('~icons/mdi/close')['default']
MdiCloseCircle: typeof import('~icons/mdi/close-circle')['default'] MdiCloseCircle: typeof import('~icons/mdi/close-circle')['default']
MdiCloseThick: typeof import('~icons/mdi/close-thick')['default'] MdiCloseThick: typeof import('~icons/mdi/close-thick')['default']
MdiCodeJson: typeof import('~icons/mdi/code-json')['default']
MdiContentCopy: typeof import('~icons/mdi/content-copy')['default'] MdiContentCopy: typeof import('~icons/mdi/content-copy')['default']
MdiContentSave: typeof import('~icons/mdi/content-save')['default'] MdiContentSave: typeof import('~icons/mdi/content-save')['default']
MdiDelete: typeof import('~icons/mdi/delete')['default'] MdiDatabaseOutline: typeof import('~icons/mdi/database-outline')['default']
MdiDeleteOutline: typeof import('~icons/mdi/delete-outline')['default'] MdiDeleteOutline: typeof import('~icons/mdi/delete-outline')['default']
MdiDiscord: typeof import('~icons/mdi/discord')['default'] MdiDiscord: typeof import('~icons/mdi/discord')['default']
MdiDotsHorizontal: typeof import('~icons/mdi/dots-horizontal')['default']
MdiDotsVertical: typeof import('~icons/mdi/dots-vertical')['default'] MdiDotsVertical: typeof import('~icons/mdi/dots-vertical')['default']
MdiDownload: typeof import('~icons/mdi/download')['default'] MdiDownload: typeof import('~icons/mdi/download')['default']
MdiDownloadOutline: typeof import('~icons/mdi/download-outline')['default']
MdiDrag: typeof import('~icons/mdi/drag')['default'] MdiDrag: typeof import('~icons/mdi/drag')['default']
MdiDragVertical: typeof import('~icons/mdi/drag-vertical')['default'] MdiDragVertical: typeof import('~icons/mdi/drag-vertical')['default']
MdiDramaMasks: typeof import('~icons/mdi/drama-masks')['default'] MdiDramaMasks: typeof import('~icons/mdi/drama-masks')['default']
MdiEditOutline: typeof import('~icons/mdi/edit-outline')['default']
MdiEmail: typeof import('~icons/mdi/email')['default'] MdiEmail: typeof import('~icons/mdi/email')['default']
MdiEmailArrowRightOutline: typeof import('~icons/mdi/email-arrow-right-outline')['default'] MdiEmailArrowRightOutline: typeof import('~icons/mdi/email-arrow-right-outline')['default']
MdiExitToApp: typeof import('~icons/mdi/exit-to-app')['default'] MdiExitToApp: typeof import('~icons/mdi/exit-to-app')['default']
MdiExport: typeof import('~icons/mdi/export')['default']
MdiEyeOffOutline: typeof import('~icons/mdi/eye-off-outline')['default'] MdiEyeOffOutline: typeof import('~icons/mdi/eye-off-outline')['default']
MdiFileDocumentOutline: typeof import('~icons/mdi/file-document-outline')['default']
MdiFileExcel: typeof import('~icons/mdi/file-excel')['default']
MdiFlag: typeof import('~icons/mdi/flag')['default'] MdiFlag: typeof import('~icons/mdi/flag')['default']
MdiFlashOutline: typeof import('~icons/mdi/flash-outline')['default']
MdiFolder: typeof import('~icons/mdi/folder')['default'] MdiFolder: typeof import('~icons/mdi/folder')['default']
MdiFunction: typeof import('~icons/mdi/function')['default'] MdiFunction: typeof import('~icons/mdi/function')['default']
MdiGestureDoubleTap: typeof import('~icons/mdi/gesture-double-tap')['default'] MdiGestureDoubleTap: typeof import('~icons/mdi/gesture-double-tap')['default']
MdiGithub: typeof import('~icons/mdi/github')['default']
MdiHeart: typeof import('~icons/mdi/heart')['default'] MdiHeart: typeof import('~icons/mdi/heart')['default']
MdiHook: typeof import('~icons/mdi/hook')['default'] MdiHook: typeof import('~icons/mdi/hook')['default']
MdiInformation: typeof import('~icons/mdi/information')['default'] MdiInformation: typeof import('~icons/mdi/information')['default']
@ -139,22 +140,22 @@ declare module '@vue/runtime-core' {
MdiNumeric: typeof import('~icons/mdi/numeric')['default'] MdiNumeric: typeof import('~icons/mdi/numeric')['default']
MdiOpenInNew: typeof import('~icons/mdi/open-in-new')['default'] MdiOpenInNew: typeof import('~icons/mdi/open-in-new')['default']
MdiPlus: typeof import('~icons/mdi/plus')['default'] MdiPlus: typeof import('~icons/mdi/plus')['default']
MdiPlusIconOutline: typeof import('~icons/mdi/plus-icon-outline')['default']
MdiPlusOutline: typeof import('~icons/mdi/plus-outline')['default'] MdiPlusOutline: typeof import('~icons/mdi/plus-outline')['default']
MdiRefresh: typeof import('~icons/mdi/refresh')['default']
MdiReload: typeof import('~icons/mdi/reload')['default'] MdiReload: typeof import('~icons/mdi/reload')['default']
MdiSearch: typeof import('~icons/mdi/search')['default'] MdiSearch: typeof import('~icons/mdi/search')['default']
MdiShieldLockOutline: typeof import('~icons/mdi/shield-lock-outline')['default']
MdiSlack: typeof import('~icons/mdi/slack')['default'] MdiSlack: typeof import('~icons/mdi/slack')['default']
MdiStar: typeof import('~icons/mdi/star')['default'] MdiStar: typeof import('~icons/mdi/star')['default']
MdiStarOutline: typeof import('~icons/mdi/star-outline')['default']
MdiStore: typeof import('~icons/mdi/store')['default'] MdiStore: typeof import('~icons/mdi/store')['default']
MdiTable: typeof import('~icons/mdi/table')['default'] MdiTable: typeof import('~icons/mdi/table')['default']
MdiTableArrowRight: typeof import('~icons/mdi/table-arrow-right')['default'] MdiTableArrowRight: typeof import('~icons/mdi/table-arrow-right')['default']
MdiTableBorder: typeof import('~icons/mdi/table-border')['default'] MdiTableBorder: typeof import('~icons/mdi/table-border')['default']
MdiTableLarge: typeof import('~icons/mdi/table-large')['default']
MdiText: typeof import('~icons/mdi/text')['default'] MdiText: typeof import('~icons/mdi/text')['default']
MdiThumbUp: typeof import('~icons/mdi/thumb-up')['default'] MdiThumbUp: typeof import('~icons/mdi/thumb-up')['default']
MdiTrashCan: typeof import('~icons/mdi/trash-can')['default'] MdiTrashCan: typeof import('~icons/mdi/trash-can')['default']
MdiTwitter: typeof import('~icons/mdi/twitter')['default'] MdiUploadOutline: typeof import('~icons/mdi/upload-outline')['default']
MdiViewListOutline: typeof import('~icons/mdi/view-list-outline')['default']
MdiWhatsapp: typeof import('~icons/mdi/whatsapp')['default'] MdiWhatsapp: typeof import('~icons/mdi/whatsapp')['default']
MdiXml: typeof import('~icons/mdi/xml')['default'] MdiXml: typeof import('~icons/mdi/xml')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']

4
packages/nc-gui-v2/components/api-client/Headers.vue

@ -85,7 +85,7 @@ const deleteHeaderRow = (idx: number) => vModel.value.splice(idx, 1)
<a-checkbox v-model:checked="headerRow.enabled" /> <a-checkbox v-model:checked="headerRow.enabled" />
</a-form-item> </a-form-item>
</td> </td>
<td class="px-2"> <td class="px-2 w-min-[400px]">
<a-form-item> <a-form-item>
<a-select v-model:value="headerRow.name" size="large" placeholder="Key"> <a-select v-model:value="headerRow.name" size="large" placeholder="Key">
<a-select-option v-for="(header, i) in headerList" :key="i" :value="header"> <a-select-option v-for="(header, i) in headerList" :key="i" :value="header">
@ -94,7 +94,7 @@ const deleteHeaderRow = (idx: number) => vModel.value.splice(idx, 1)
</a-select> </a-select>
</a-form-item> </a-form-item>
</td> </td>
<td class="px-2"> <td class="px-2 w-min-[400px]">
<a-form-item> <a-form-item>
<a-input v-model:value="headerRow.value" size="large" placeholder="Value" /> <a-input v-model:value="headerRow.value" size="large" placeholder="Value" />
</a-form-item> </a-form-item>

15
packages/nc-gui-v2/components/cell/DatePicker.vue

@ -1,19 +1,18 @@
<script setup lang="ts"> <script setup lang="ts">
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { ColumnInj } from '#imports' import { ColumnInj, EditModeInj, computed, inject, ref, watch } from '#imports'
import { EditModeInj } from '~/context'
interface Props { interface Props {
modelValue: string | null | undefined modelValue?: string | null
} }
const { modelValue } = defineProps<Props>() const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const columnMeta = inject(ColumnInj, null) const columnMeta = inject(ColumnInj, null)!
const editEnabled = inject(EditModeInj) const editEnabled = inject(EditModeInj)!
let isDateInvalid = $ref(false) let isDateInvalid = $ref(false)
@ -43,7 +42,7 @@ const localState = $computed({
} }
}, },
}) })
const open = ref(false) const open = ref<boolean>(false)
const randomClass = `picker_${Math.floor(Math.random() * 99999)}` const randomClass = `picker_${Math.floor(Math.random() * 99999)}`
watch( watch(
@ -55,6 +54,8 @@ watch(
}, },
{ flush: 'post' }, { flush: 'post' },
) )
const placeholder = computed(() => (isDateInvalid ? 'Invalid date' : editEnabled.value ? 'Select date' : ''))
</script> </script>
<template> <template>
@ -63,7 +64,7 @@ watch(
:bordered="false" :bordered="false"
class="!w-full px-1" class="!w-full px-1"
:format="dateFormat" :format="dateFormat"
:placeholder="isDateInvalid ? 'Invalid date' : !readOnlyMode ? 'Select date' : ''" :placeholder="placeholder"
:allow-clear="!editEnabled" :allow-clear="!editEnabled"
:input-read-only="true" :input-read-only="true"
:dropdown-class-name="randomClass" :dropdown-class-name="randomClass"

67
packages/nc-gui-v2/components/cell/MultiSelect.vue

@ -1,12 +1,23 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Select as AntSelect } from 'ant-design-vue' import type { Select as AntSelect } from 'ant-design-vue'
import type { SelectOptionType } from 'nocodb-sdk' import type { SelectOptionsType } from 'nocodb-sdk'
import { ActiveCellInj, ColumnInj, computed, inject } from '#imports' import {
import { EditModeInj } from '~/context' ActiveCellInj,
ColumnInj,
EditModeInj,
computed,
h,
inject,
onMounted,
ref,
useEventListener,
useProject,
watch,
} from '#imports'
import MdiCloseCircle from '~icons/mdi/close-circle' import MdiCloseCircle from '~icons/mdi/close-circle'
interface Props { interface Props {
modelValue?: string | string[] | undefined modelValue?: string | string[]
} }
const { modelValue } = defineProps<Props>() const { modelValue } = defineProps<Props>()
@ -15,11 +26,9 @@ const emit = defineEmits(['update:modelValue'])
const { isMysql } = useProject() const { isMysql } = useProject()
const column = inject(ColumnInj) const column = inject(ColumnInj)!
// const isForm = inject<boolean>('isForm', false) const editEnabled = inject(EditModeInj)!
const editEnabled = inject(EditModeInj)
const active = inject(ActiveCellInj, ref(false)) const active = inject(ActiveCellInj, ref(false))
@ -29,12 +38,12 @@ const aselect = ref<typeof AntSelect>()
const isOpen = ref(false) const isOpen = ref(false)
const options = computed(() => { const options = computed<SelectOptionsType[]>(() => {
if (column?.value.colOptions) { if (column?.value.colOptions) {
const opts = column.value.colOptions const opts = column.value.colOptions
? column.value.colOptions.options.filter((el: SelectOptionType) => el.title !== '') || [] ? (column.value.colOptions as any).options.filter((el: any) => el.title !== '') || []
: [] : []
for (const op of opts.filter((el: SelectOptionType) => el.order === null)) { for (const op of opts.filter((el: any) => el.order === null)) {
op.title = op.title.replace(/^'/, '').replace(/'$/, '') op.title = op.title.replace(/^'/, '').replace(/'$/, '')
} }
return opts return opts
@ -43,7 +52,7 @@ const options = computed(() => {
}) })
const vModel = computed({ const vModel = computed({
get: () => selectedIds.value.map((el) => options.value.find((op: SelectOptionType) => op.id === el)?.title), get: () => selectedIds.value.map((el) => options.value.find((op) => op.id === el)?.title),
set: (val) => emit('update:modelValue', val.length === 0 ? null : val.join(',')), set: (val) => emit('update:modelValue', val.length === 0 ? null : val.join(',')),
}) })
@ -52,10 +61,10 @@ const selectedTitles = computed(() =>
? typeof modelValue === 'string' ? typeof modelValue === 'string'
? isMysql ? isMysql
? modelValue.split(',').sort((a, b) => { ? modelValue.split(',').sort((a, b) => {
const opa = options.value.find((el: SelectOptionType) => el.title === a) const opa = options.value.find((el) => el.title === a)
const opb = options.value.find((el: SelectOptionType) => el.title === b) const opb = options.value.find((el) => el.title === b)
if (opa && opb) { if (opa && opb) {
return opa.order - opb.order return opa.order! - opb.order!
} }
return 0 return 0
}) })
@ -83,8 +92,13 @@ const handleClose = (e: MouseEvent) => {
} }
onMounted(() => { onMounted(() => {
selectedIds.value = selectedTitles.value.map((el) => { selectedIds.value = selectedTitles.value.flatMap((el) => {
return options.value.find((op: SelectOptionType) => op.title === el).id const item = options.value.find((op) => op.title === el)?.id
if (item) {
return [item]
}
return []
}) })
}) })
@ -92,17 +106,20 @@ useEventListener(document, 'click', handleClose)
watch( watch(
() => modelValue, () => modelValue,
(_n, _o) => { () => {
selectedIds.value = selectedTitles.value.map((el) => { selectedIds.value = selectedIds.value = selectedTitles.value.flatMap((el) => {
return options.value.find((op: SelectOptionType) => op.title === el).id const item = options.value.find((op) => op.title === el)?.id
if (item) {
return [item]
}
return []
}) })
}, },
) )
watch(isOpen, (n, _o) => { watch(isOpen, (n, _o) => {
if (n === false) { if (!n) aselect.value?.$el.blur()
aselect.value.blur()
}
}) })
</script> </script>
@ -128,10 +145,10 @@ watch(isOpen, (n, _o) => {
</a-select-option> </a-select-option>
<template #tagRender="{ value: val, onClose }"> <template #tagRender="{ value: val, onClose }">
<a-tag <a-tag
v-if="options.find((el: SelectOptionType) => el.title === val)" v-if="options.find((el) => el.title === val)"
class="rounded-tag" class="rounded-tag"
:style="{ display: 'flex', alignItems: 'center' }" :style="{ display: 'flex', alignItems: 'center' }"
:color="options.find((el: SelectOptionType) => el.title === val).color" :color="options.find((el) => el.title === val).color"
:closable="active && (vModel.length > 1 || !column?.rqd)" :closable="active && (vModel.length > 1 || !column?.rqd)"
:close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })" :close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })"
@close="onClose" @close="onClose"

22
packages/nc-gui-v2/components/cell/SingleSelect.vue

@ -1,8 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Select as AntSelect } from 'ant-design-vue' import type { Select as AntSelect } from 'ant-design-vue'
import type { SelectOptionType } from 'nocodb-sdk' import type { SelectOptionsType } from 'nocodb-sdk'
import { ActiveCellInj, ColumnInj, computed, inject } from '#imports' import { ActiveCellInj, ColumnInj, EditModeInj, computed, inject, ref, useEventListener, watch } from '#imports'
import { EditModeInj } from '~/context'
interface Props { interface Props {
modelValue?: string | undefined modelValue?: string | undefined
@ -12,11 +11,9 @@ const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const column = inject(ColumnInj) const column = inject(ColumnInj)!
// const isForm = inject<boolean>('isForm', false) const editEnabled = inject(EditModeInj)!
const editEnabled = inject(EditModeInj)
const active = inject(ActiveCellInj, ref(false)) const active = inject(ActiveCellInj, ref(false))
@ -29,12 +26,13 @@ const vModel = computed({
set: (val) => emit('update:modelValue', val || null), set: (val) => emit('update:modelValue', val || null),
}) })
const options = computed(() => { const options = computed<SelectOptionsType[]>(() => {
if (column?.value.colOptions) { if (column?.value.colOptions) {
const opts = column.value.colOptions const opts = column.value.colOptions
? column.value.colOptions.options.filter((el: SelectOptionType) => el.title !== '') || [] ? // todo: fix colOptions type, options does not exist as a property
(column.value.colOptions as any).options.filter((el: SelectOptionsType) => el.title !== '') || []
: [] : []
for (const op of opts.filter((el: SelectOptionType) => el.order === null)) { for (const op of opts.filter((el: any) => el.order === null)) {
op.title = op.title.replace(/^'/, '').replace(/'$/, '') op.title = op.title.replace(/^'/, '').replace(/'$/, '')
} }
return opts return opts
@ -61,9 +59,7 @@ const handleClose = (e: MouseEvent) => {
useEventListener(document, 'click', handleClose) useEventListener(document, 'click', handleClose)
watch(isOpen, (n, _o) => { watch(isOpen, (n, _o) => {
if (n === false) { if (!n) aselect.value?.$el.blur()
aselect.value.blur()
}
}) })
</script> </script>

15
packages/nc-gui-v2/components/cell/Url.vue

@ -1,10 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core' import type { VNodeRef } from '@vue/runtime-core'
import { ColumnInj, computed, inject, isValidURL } from '#imports' import { ColumnInj, EditModeInj, computed, inject, isValidURL } from '#imports'
import { EditModeInj } from '~/context'
interface Props { interface Props {
modelValue: string | null | undefined modelValue?: string | null
} }
const { modelValue: value } = defineProps<Props>() const { modelValue: value } = defineProps<Props>()
@ -13,7 +12,7 @@ const emit = defineEmits(['update:modelValue'])
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
const editEnabled = inject(EditModeInj) const editEnabled = inject(EditModeInj)!
const vModel = computed({ const vModel = computed({
get: () => value, get: () => value,
@ -26,10 +25,12 @@ const vModel = computed({
const isValid = computed(() => value && isValidURL(value)) const isValid = computed(() => value && isValidURL(value))
const url = computed<string | null>(() => { const url = computed(() => {
if (!value || !isValidURL(value)) return null if (!value || !isValidURL(value)) return ''
/** add url scheme if missing */ /** add url scheme if missing */
if (/^https?:\/\//.test(value)) return value if (/^https?:\/\//.test(value)) return value
return `https://${value}` return `https://${value}`
}) })
@ -38,7 +39,9 @@ const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
<template> <template>
<input v-if="editEnabled" :ref="focus" v-model="vModel" class="outline-none text-sm" @blur="editEnabled = false" /> <input v-if="editEnabled" :ref="focus" v-model="vModel" class="outline-none text-sm" @blur="editEnabled = false" />
<nuxt-link v-else-if="isValid" class="text-sm underline hover:opacity-75" :to="url" target="_blank">{{ value }} </nuxt-link> <nuxt-link v-else-if="isValid" class="text-sm underline hover:opacity-75" :to="url" target="_blank">{{ value }} </nuxt-link>
<span v-else>{{ value }}</span> <span v-else>{{ value }}</span>
</template> </template>

15
packages/nc-gui-v2/components/cell/YearPicker.vue

@ -1,17 +1,16 @@
<script setup lang="ts"> <script setup lang="ts">
import { onClickOutside } from '@vueuse/core'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { EditModeInj } from '~/context' import { EditModeInj, computed, inject, onClickOutside, ref, watch } from '#imports'
interface Props { interface Props {
modelValue: number | string | null | undefined modelValue?: number | string | null
} }
const { modelValue } = defineProps<Props>() const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const editEnabled = inject(EditModeInj) const editEnabled = inject(EditModeInj)!
let isYearInvalid = $ref(false) let isYearInvalid = $ref(false)
@ -41,7 +40,7 @@ const localState = $computed({
}, },
}) })
const open = ref(false) const open = ref<boolean>(false)
const randomClass = `picker_${Math.floor(Math.random() * 99999)}` const randomClass = `picker_${Math.floor(Math.random() * 99999)}`
watch( watch(
@ -53,6 +52,8 @@ watch(
}, },
{ flush: 'post' }, { flush: 'post' },
) )
const placeholder = computed(() => (isYearInvalid ? 'Invalid year' : editEnabled.value ? 'Select year' : ''))
</script> </script>
<template> <template>
@ -61,7 +62,7 @@ watch(
picker="year" picker="year"
:bordered="false" :bordered="false"
class="!w-full px-1" class="!w-full px-1"
:placeholder="isYearInvalid ? 'Invalid year' : !readOnlyMode ? 'Select year' : ''" :placeholder="placeholder"
:allow-clear="!editEnabled" :allow-clear="!editEnabled"
:input-read-only="true" :input-read-only="true"
:open="editEnabled ? false : open" :open="editEnabled ? false : open"
@ -72,5 +73,3 @@ watch(
<template #suffixIcon></template> <template #suffixIcon></template>
</a-date-picker> </a-date-picker>
</template> </template>
<style scoped></style>

4
packages/nc-gui-v2/components/cell/attachment/utils.ts

@ -141,7 +141,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
editEnabled, editEnabled,
isLoading, isLoading,
api, api,
open, open: () => open(),
onDrop, onDrop,
modalVisible, modalVisible,
FileIcon, FileIcon,
@ -151,5 +151,5 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
selectedImage, selectedImage,
} }
}, },
'attachmentCell', 'useAttachmentCell',
) )

2
packages/nc-gui-v2/components/dashboard/TreeView.vue

@ -3,7 +3,7 @@ import type { TableType } from 'nocodb-sdk'
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
import { Empty } from 'ant-design-vue' import { Empty } from 'ant-design-vue'
import { useNuxtApp } from '#app' import { useNuxtApp } from '#app'
import { computed, useProject, useTable, useTabs, watchEffect } from '#imports' import { computed, useProject, useTable, useTabs, useUIPermission, watchEffect } from '#imports'
import { TabType } from '~/composables' import { TabType } from '~/composables'
import MdiView from '~icons/mdi/eye-circle-outline' import MdiView from '~icons/mdi/eye-circle-outline'
import MdiTableLarge from '~icons/mdi/table-large' import MdiTableLarge from '~icons/mdi/table-large'

14
packages/nc-gui-v2/components/dashboard/settings/app-store/AppInstall.vue

@ -1,11 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import type { PluginType } from 'nocodb-sdk' import type { PluginType } from 'nocodb-sdk'
import MdiDeleteOutlineIcon from '~icons/mdi/delete-outline' import { extractSdkResponseErrorMsg, ref, useNuxtApp } from '#imports'
import CloseIcon from '~icons/material-symbols/close-rounded'
import MdiPlusIcon from '~icons/mdi/plus'
import { extractSdkResponseErrorMsg } from '~/utils/errorUtils'
interface Props { interface Props {
id: string id: string
@ -139,7 +135,7 @@ onMounted(async () => {
class="mr-1 flex items-center justify-center" class="mr-1 flex items-center justify-center"
:class="[plugin.title === 'SES' ? 'p-2 bg-[#242f3e]' : '']" :class="[plugin.title === 'SES' ? 'p-2 bg-[#242f3e]' : '']"
> >
<img :src="`/${plugin.logo}`" class="h-6" /> <img :alt="plugin.title || 'plugin'" :src="`/${plugin.logo}`" class="h-6" />
</div> </div>
<span class="font-semibold text-lg">{{ plugin.formDetails.title }}</span> <span class="font-semibold text-lg">{{ plugin.formDetails.title }}</span>
@ -147,7 +143,7 @@ onMounted(async () => {
<div class="absolute -right-2 -top-0.5"> <div class="absolute -right-2 -top-0.5">
<a-button type="text" class="!rounded-md mr-1" @click="emits('close')"> <a-button type="text" class="!rounded-md mr-1" @click="emits('close')">
<template #icon> <template #icon>
<CloseIcon class="flex mx-auto" /> <MaterialSymbolsCloseRounded class="flex mx-auto" />
</template> </template>
</a-button> </a-button>
</div> </div>
@ -194,7 +190,7 @@ onMounted(async () => {
v-if="itemIndex !== 0 && columnIndex === plugin.formDetails.items.length - 1" v-if="itemIndex !== 0 && columnIndex === plugin.formDetails.items.length - 1"
class="absolute flex flex-col justify-start mt-2 -right-6 top-0" class="absolute flex flex-col justify-start mt-2 -right-6 top-0"
> >
<MdiDeleteOutlineIcon class="hover:text-red-400 cursor-pointer" @click="deleteFormRow(itemIndex)" /> <MdiDeleteOutline class="hover:text-red-400 cursor-pointer" @click="deleteFormRow(itemIndex)" />
</div> </div>
</a-form-item> </a-form-item>
</td> </td>
@ -205,7 +201,7 @@ onMounted(async () => {
<td :colspan="plugin.formDetails.items.length" class="text-center"> <td :colspan="plugin.formDetails.items.length" class="text-center">
<a-button type="default" class="!bg-gray-100 rounded-md border-none mr-1" @click="addSetting"> <a-button type="default" class="!bg-gray-100 rounded-md border-none mr-1" @click="addSetting">
<template #icon> <template #icon>
<MdiPlusIcon class="flex mx-auto" /> <MdiPlus class="flex mx-auto" />
</template> </template>
</a-button> </a-button>
</td> </td>

32
packages/nc-gui-v2/components/general/ColorPicker.vue

@ -1,21 +1,22 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Chrome } from '@ckpack/vue-color' import { Chrome } from '@ckpack/vue-color'
import { enumColor } from '@/utils' import { enumColor } from '@/utils'
import { computed, ref, watch } from '#imports'
interface Props { interface Props {
modelValue: string | any modelValue?: string | any
colors?: string[] colors?: string[]
rowSize?: number rowSize?: number
advanced?: Boolean advanced?: boolean
pickButton?: Boolean pickButton?: boolean
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
modelValue: () => enumColor.light[0], modelValue: () => enumColor.light[0],
colors: () => enumColor.light.concat(enumColor.dark), colors: () => enumColor.light.concat(enumColor.dark),
rowSize: () => 10, rowSize: 10,
advanced: () => true, advanced: true,
pickButton: () => false, pickButton: false,
}) })
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
@ -27,23 +28,18 @@ const vModel = computed({
}, },
}) })
const picked = ref(props.modelValue || enumColor.light[0]) const picked = ref<string | Record<string, any>>(props.modelValue || enumColor.light[0])
const selectColor = (color: any) => { const selectColor = (color: string | Record<string, any>) => {
picked.value = color.hex ? color.hex : color picked.value = typeof color === 'string' ? color : color.hex ? color.hex : color
vModel.value = color.hex ? color.hex : color vModel.value = typeof color === 'string' ? color : color.hex ? color.hex : color
} }
const compare = (colorA: String, colorB: String) => { const compare = (colorA: string, colorB: string) => colorA.toLowerCase() === colorB.toLowerCase()
if ((typeof colorA === 'string' || colorA instanceof String) && (typeof colorB === 'string' || colorB instanceof String)) {
return colorA.toLowerCase() === colorB.toLowerCase()
}
return false
}
watch(picked, (n, _o) => { watch(picked, (n, _o) => {
if (!props.pickButton) { if (!props.pickButton) {
vModel.value = n.hex ? n.hex : n vModel.value = typeof n === 'string' ? n : n.hex ? n.hex : n
} }
}) })
</script> </script>
@ -52,7 +48,7 @@ watch(picked, (n, _o) => {
<div class="color-picker"> <div class="color-picker">
<div v-for="colId in Math.ceil(props.colors.length / props.rowSize)" :key="colId" class="color-picker-row"> <div v-for="colId in Math.ceil(props.colors.length / props.rowSize)" :key="colId" class="color-picker-row">
<button <button
v-for="(color, i) in colors.slice((colId - 1) * rowSize, colId * rowSize)" v-for="(color, i) of colors.slice((colId - 1) * rowSize, colId * rowSize)"
:key="`color-${colId}-${i}`" :key="`color-${colId}-${i}`"
class="color-selector" class="color-selector"
:class="compare(picked, color) ? 'selected' : ''" :class="compare(picked, color) ? 'selected' : ''"

13
packages/nc-gui-v2/components/smartsheet-column/EditOrAdd.vue

@ -81,17 +81,20 @@ onMounted(() => {
}) })
const handleClose = (e: MouseEvent) => { const handleClose = (e: MouseEvent) => {
const target = e.target as HTMLElement
if ( if (
e.target && target &&
editOrAddRef?.value && editOrAddRef?.value &&
!editOrAddRef.value.contains(e.target) && !editOrAddRef.value.contains(target) &&
!e.target.closest('.ant-dropdown') && !target.closest('.ant-dropdown') &&
!e.target.closest('.ant-select') && !target.closest('.ant-select') &&
!e.target.closest('.ant-select-item') !target.closest('.ant-select-item')
) { ) {
emit('cancel') emit('cancel')
} }
} }
useEventListener(document, 'click', handleClose) useEventListener(document, 'click', handleClose)
</script> </script>

15
packages/nc-gui-v2/components/smartsheet-column/FormulaOptions.vue

@ -4,9 +4,8 @@ import type { ListItem as AntListItem } from 'ant-design-vue'
import jsep from 'jsep' import jsep from 'jsep'
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { UITypes, jsepCurlyHook } from 'nocodb-sdk' import { UITypes, jsepCurlyHook } from 'nocodb-sdk'
import { onMounted, useDebounceFn } from '#imports'
import { MetaInj } from '~/context'
import { import {
MetaInj,
NcAutocompleteTree, NcAutocompleteTree,
formulaList, formulaList,
formulaTypes, formulaTypes,
@ -14,8 +13,11 @@ import {
getUIDTIcon, getUIDTIcon,
getWordUntilCaret, getWordUntilCaret,
insertAtCursor, insertAtCursor,
onMounted,
useColumnCreateStoreOrThrow,
useDebounceFn,
validateDateWithUnknownFormat, validateDateWithUnknownFormat,
} from '@/utils' } from '#imports'
interface Props { interface Props {
value: Record<string, any> value: Record<string, any>
@ -615,10 +617,11 @@ onMounted(() => {
</a-form-item> </a-form-item>
<div class="text-gray-600 mt-2 mb-4 prose-sm"> <div class="text-gray-600 mt-2 mb-4 prose-sm">
Hint: Use {} to reference columns, e.g: {column_name}. For more, please check out Hint: Use {} to reference columns, e.g: {column_name}. For more, please check out
<a class="prose-sm" href="https://docs.nocodb.com/setup-and-usages/formulas#available-formula-features" target="_blank" <a class="prose-sm" href="https://docs.nocodb.com/setup-and-usages/formulas#available-formula-features" target="_blank">
>Formulas</a Formulas.
>. </a>
</div> </div>
<div class="h-[250px] overflow-auto scrollbar-thin-primary"> <div class="h-[250px] overflow-auto scrollbar-thin-primary">
<a-list ref="sugListRef" :data-source="suggestion" :locale="{ emptyText: 'No suggested formula was found' }"> <a-list ref="sugListRef" :data-source="suggestion" :locale="{ emptyText: 'No suggested formula was found' }">
<template #renderItem="{ item, index }"> <template #renderItem="{ item, index }">

17
packages/nc-gui-v2/components/smartsheet-column/LookupOptions.vue

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType } from 'nocodb-sdk'
import { UITypes, isSystemColumn } from 'nocodb-sdk' import { UITypes, isSystemColumn } from 'nocodb-sdk'
import { MetaInj } from '~/context' import { MetaInj } from '#imports'
interface Props { interface Props {
value: Record<string, any> value: Record<string, any>
@ -39,25 +39,22 @@ const refTables = $computed(() => {
} }
return meta.columns return meta.columns
.filter((c: ColumnType) => c.uidt === UITypes.LinkToAnotherRecord && !c.system) ?.filter((c: any) => c.uidt === UITypes.LinkToAnotherRecord && !c.system)
.map<TableType & { col: LinkToAnotherRecordType; column: ColumnType }>((c: ColumnType) => ({ .map((c: ColumnType) => ({
col: c.colOptions, col: c.colOptions,
column: c, column: c,
...tables.find((t) => t.id === (c.colOptions as LinkToAnotherRecordType).fk_related_model_id), ...tables.find((t) => t.id === (c.colOptions as LinkToAnotherRecordType).fk_related_model_id),
})) }))
.filter( .filter((table: any) => table.col.fk_related_model_id === table.id && !table.mm)
(table: TableType & { col: LinkToAnotherRecordType; column: ColumnType }) =>
table.col.fk_related_model_id === table.id && !table.mm,
)
}) })
const columns = $computed(() => { const columns = $computed(() => {
const selectedTable = refTables.find((t) => t.column.id === vModel.value.fk_relation_column_id) const selectedTable = refTables?.find((t) => t.column.id === vModel.value.fk_relation_column_id)
if (!selectedTable?.id) { if (!selectedTable?.id) {
return [] return []
} }
return metas[selectedTable.id].columns.filter((c) => !isSystemColumn(c)) return metas[selectedTable.id].columns.filter((c: any) => !isSystemColumn(c))
}) })
</script> </script>

6
packages/nc-gui-v2/components/smartsheet-header/Cell.vue

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { inject, toRef } from 'vue' import { ColumnInj, IsFormInj, inject, provide, ref, toRef, useUIPermission } from '#imports'
import { ColumnInj, IsFormInj } from '~/context'
const props = defineProps<{ column: ColumnType & { meta: any }; required?: boolean; hideMenu?: boolean }>() const props = defineProps<{ column: ColumnType & { meta: any }; required?: boolean; hideMenu?: boolean }>()
const hideMenu = toRef(props, 'hideMenu') const hideMenu = toRef(props, 'hideMenu')
@ -24,7 +24,7 @@ function onVisibleChange() {
</script> </script>
<template> <template>
<div class="flex align-center w-full text-xs font-weight-regular"> <div class="flex items-center w-full text-xs text-normal">
<SmartsheetHeaderCellIcon v-if="column" /> <SmartsheetHeaderCellIcon v-if="column" />
<span v-if="column" class="name" style="white-space: nowrap" :title="column.title">{{ column.title }}</span> <span v-if="column" class="name" style="white-space: nowrap" :title="column.title">{{ column.title }}</span>
<span v-if="(column.rqd && !column.cdf) || required" class="text-red-500">&nbsp;*</span> <span v-if="(column.rqd && !column.cdf) || required" class="text-red-500">&nbsp;*</span>

34
packages/nc-gui-v2/components/smartsheet-header/VirtualCell.vue

@ -1,8 +1,19 @@
<script setup lang="ts"> <script setup lang="ts">
import { substituteColumnIdWithAliasInFormula } from 'nocodb-sdk'
import type { ColumnType, FormulaType, LinkToAnotherRecordType, LookupType, RollupType } from 'nocodb-sdk' import type { ColumnType, FormulaType, LinkToAnotherRecordType, LookupType, RollupType } from 'nocodb-sdk'
import { ColumnInj, IsFormInj, MetaInj } from '~/context' import { substituteColumnIdWithAliasInFormula } from 'nocodb-sdk'
import { provide, toRef, useMetas } from '#imports' import {
ColumnInj,
IsFormInj,
MetaInj,
computed,
inject,
provide,
ref,
toRef,
useMetas,
useUIPermission,
useVirtualCell,
} from '#imports'
const props = defineProps<{ column: ColumnType & { meta: any }; hideMenu?: boolean; required?: boolean }>() const props = defineProps<{ column: ColumnType & { meta: any }; hideMenu?: boolean; required?: boolean }>()
@ -48,12 +59,10 @@ const relatedTableTitle = $computed(() => relatedTableMeta?.title)
const childColumn = $computed(() => { const childColumn = $computed(() => {
if (relatedTableMeta?.columns) { if (relatedTableMeta?.columns) {
if (isRollup.value) { if (isRollup.value) {
const ch = relatedTableMeta?.columns.find((c: ColumnType) => c.id === (colOptions as RollupType).fk_rollup_column_id) return relatedTableMeta?.columns.find((c: ColumnType) => c.id === (colOptions as RollupType).fk_rollup_column_id)
return ch
} }
if (isLookup.value) { if (isLookup.value) {
const ch = relatedTableMeta?.columns.find((c: ColumnType) => c.id === (colOptions as LookupType).fk_lookup_column_id) return relatedTableMeta?.columns.find((c: ColumnType) => c.id === (colOptions as LookupType).fk_lookup_column_id)
return ch
} }
} }
return '' return ''
@ -92,11 +101,7 @@ function onVisibleChange() {
</script> </script>
<template> <template>
<div class="d-flex align-center w-full text-xs font-weight-regular"> <div class="flex items-center w-full text-xs text-normal">
<!-- <v-tooltip bottom>
<template #activator="{ on }">
todo: bring tooltip
-->
<SmartsheetHeaderVirtualCellIcon v-if="column" /> <SmartsheetHeaderVirtualCellIcon v-if="column" />
<a-tooltip placement="bottom"> <a-tooltip placement="bottom">
@ -105,13 +110,10 @@ function onVisibleChange() {
</template> </template>
<span class="name" style="white-space: nowrap" :title="column.title"> {{ column.title }}</span> <span class="name" style="white-space: nowrap" :title="column.title"> {{ column.title }}</span>
</a-tooltip> </a-tooltip>
<span v-if="column.rqd || required" class="text-red-500">&nbsp;*</span>
<!-- <span class="caption" v-html="tooltipMsg" /> --> <span v-if="column.rqd || required" class="text-red-500">&nbsp;*</span>
<!-- </v-tooltip> -->
<template v-if="!hideMenu"> <template v-if="!hideMenu">
<v-spacer />
<SmartsheetHeaderMenu v-if="!isForm && isUIAllowed('edit-column')" :virtual="true" @edit="editColumnDropdown = true" /> <SmartsheetHeaderMenu v-if="!isForm && isUIAllowed('edit-column')" :virtual="true" @edit="editColumnDropdown = true" />
</template> </template>

17
packages/nc-gui-v2/components/smartsheet-toolbar/ColumnFilter.vue

@ -9,12 +9,19 @@ import { ActiveViewInj, MetaInj, ReloadViewDataHookInj } from '~/context'
import MdiDeleteIcon from '~icons/mdi/close-box' import MdiDeleteIcon from '~icons/mdi/close-box'
import MdiAddIcon from '~icons/mdi/plus' import MdiAddIcon from '~icons/mdi/plus'
const { nested = false, parentId, autoSave = true } = defineProps<{ nested?: boolean; parentId?: string; autoSave: boolean }>() const {
nested = false,
parentId,
autoSave = true,
hookId = null,
} = defineProps<{ nested?: boolean; parentId?: string; autoSave: boolean; hookId?: string }>()
const emit = defineEmits(['update:filtersLength']) const emit = defineEmits(['update:filtersLength'])
const meta = inject(MetaInj) const meta = inject(MetaInj)
const activeView = inject(ActiveViewInj) const activeView = inject(ActiveViewInj)
const reloadDataHook = inject(ReloadViewDataHookInj) const reloadDataHook = inject(ReloadViewDataHookInj)
// todo: replace with inject or get from state // todo: replace with inject or get from state
@ -76,7 +83,7 @@ const types = computed(() => {
watch( watch(
() => (activeView?.value as any)?.id, () => (activeView?.value as any)?.id,
(n, o) => { (n, o) => {
if (n !== o) loadFilters() if (n !== o) loadFilters(hookId as string)
}, },
{ immediate: true }, { immediate: true },
) )
@ -95,11 +102,11 @@ watch(
}, },
) )
const applyChanges = async () => { const applyChanges = async (hookId?: string) => {
await sync() await sync(hookId)
for (const nestedFilter of nestedFilters?.value || []) { for (const nestedFilter of nestedFilters?.value || []) {
if (nestedFilter.parentId) { if (nestedFilter.parentId) {
await nestedFilter.applyChanges(true) await nestedFilter.applyChanges(hookId, true)
} }
} }
} }

60
packages/nc-gui-v2/components/smartsheet-toolbar/MoreActions.vue

@ -1,18 +1,24 @@
<script lang="ts" setup> <script lang="ts" setup>
import * as XLSX from 'xlsx' import * as XLSX from 'xlsx'
import { ExportTypes } from 'nocodb-sdk' // todo: export types is missing EXCEL
// import { ExportTypes } from 'nocodb-sdk'
import FileSaver from 'file-saver' import FileSaver from 'file-saver'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { useNuxtApp } from '#app' import {
import { useProject } from '#imports' ActiveViewInj,
import { ActiveViewInj, MetaInj } from '~/context' MetaInj,
import { extractSdkResponseErrorMsg } from '~/utils' extractSdkResponseErrorMsg,
import MdiFlashIcon from '~icons/mdi/flash-outline' inject,
import MdiMenuDownIcon from '~icons/mdi/menu-down' ref,
import MdiDownloadIcon from '~icons/mdi/download-outline' useNuxtApp,
import MdiUploadIcon from '~icons/mdi/upload-outline' useProject,
import MdiHookIcon from '~icons/mdi/hook' useUIPermission,
import MdiViewListIcon from '~icons/mdi/view-list-outline' } from '#imports'
enum ExportTypes {
EXCEL = 'excel',
CSV = 'csv',
}
const sharedViewListDlg = ref(false) const sharedViewListDlg = ref(false)
@ -22,14 +28,6 @@ const isView = false
// TODO: pending for shared view // TODO: pending for shared view
// interface Props {
// publicViewId?: string
// queryParams?: Record<string, any>
// reqPayload?: Record<string, any>
// }
// const { publicViewId, queryParams, reqPayload } = defineProps<Props>()
const { project } = useProject() const { project } = useProject()
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
@ -44,7 +42,7 @@ const quickImportDialog = ref(false)
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const exportFile = async (exportType: ExportTypes.EXCEL | ExportTypes.CSV) => { const exportFile = async (exportType: ExportTypes) => {
let offset = 0 let offset = 0
let c = 1 let c = 1
const responseType = exportType === ExportTypes.EXCEL ? 'base64' : 'blob' const responseType = exportType === ExportTypes.EXCEL ? 'base64' : 'blob'
@ -114,52 +112,59 @@ const exportFile = async (exportType: ExportTypes.EXCEL | ExportTypes.CSV) => {
<a-dropdown> <a-dropdown>
<a-button v-t="['c:actions']" class="nc-actions-menu-btn nc-toolbar-btn"> <a-button v-t="['c:actions']" class="nc-actions-menu-btn nc-toolbar-btn">
<div class="flex gap-1 align-center"> <div class="flex gap-1 align-center">
<MdiFlashIcon /> <MdiFlashOutline />
<!-- More --> <!-- More -->
<span class="!text-sm font-weight-medium">{{ $t('general.more') }}</span> <span class="!text-sm font-weight-medium">{{ $t('general.more') }}</span>
<MdiMenuDownIcon class="text-grey" />
<MdiMenuDown class="text-grey" />
</div> </div>
</a-button> </a-button>
<template #overlay> <template #overlay>
<div class="bg-white shadow-lg !border"> <div class="bg-white shadow-lg !border">
<div> <div>
<div v-t="['a:actions:download-csv']" class="nc-menu-item" @click="exportFile(ExportTypes.CSV)"> <div v-t="['a:actions:download-csv']" class="nc-menu-item" @click="exportFile(ExportTypes.CSV)">
<MdiDownloadIcon /> <MdiDownloadOutline />
<!-- Download as CSV --> <!-- Download as CSV -->
{{ $t('activity.downloadCSV') }} {{ $t('activity.downloadCSV') }}
</div> </div>
<div v-t="['a:actions:download-excel']" class="nc-menu-item" @click="exportFile(ExportTypes.EXCEL)"> <div v-t="['a:actions:download-excel']" class="nc-menu-item" @click="exportFile(ExportTypes.EXCEL)">
<MdiDownloadIcon /> <MdiDownloadOutline />
<!-- Download as XLSX --> <!-- Download as XLSX -->
{{ $t('activity.downloadExcel') }} {{ $t('activity.downloadExcel') }}
</div> </div>
<div <div
v-if="isUIAllowed('csvImport') && !isView" v-if="isUIAllowed('csvImport') && !isView"
v-t="['a:actions:upload-csv']" v-t="['a:actions:upload-csv']"
class="nc-menu-item" class="nc-menu-item"
@click="quickImportDialog = true" @click="quickImportDialog = true"
> >
<MdiUploadIcon /> <MdiUploadOutline />
<!-- Upload CSV --> <!-- Upload CSV -->
{{ $t('activity.uploadCSV') }} {{ $t('activity.uploadCSV') }}
</div> </div>
<div <div
v-if="isUIAllowed('SharedViewList') && !isView" v-if="isUIAllowed('SharedViewList') && !isView"
v-t="['a:actions:shared-view-list']" v-t="['a:actions:shared-view-list']"
class="nc-menu-item" class="nc-menu-item"
@click="sharedViewListDlg = true" @click="sharedViewListDlg = true"
> >
<MdiViewListIcon /> <MdiViewListOutline />
<!-- Shared View List --> <!-- Shared View List -->
{{ $t('activity.listSharedView') }} {{ $t('activity.listSharedView') }}
</div> </div>
<div <div
v-if="isUIAllowed('webhook') && !isView" v-if="isUIAllowed('webhook') && !isView"
v-t="['c:actions:webhook']" v-t="['c:actions:webhook']"
class="nc-menu-item" class="nc-menu-item"
@click="showWebhookDrawer = true" @click="showWebhookDrawer = true"
> >
<MdiHookIcon /> <MdiHook />
{{ $t('objects.webhooks') }} {{ $t('objects.webhooks') }}
</div> </div>
</div> </div>
@ -168,6 +173,7 @@ const exportFile = async (exportType: ExportTypes.EXCEL | ExportTypes.CSV) => {
</a-dropdown> </a-dropdown>
<DlgQuickImport v-if="quickImportDialog" v-model="quickImportDialog" import-type="csv" :import-only="true" /> <DlgQuickImport v-if="quickImportDialog" v-model="quickImportDialog" import-type="csv" :import-only="true" />
<WebhookDrawer v-if="showWebhookDrawer" v-model="showWebhookDrawer" /> <WebhookDrawer v-if="showWebhookDrawer" v-model="showWebhookDrawer" />
<a-modal v-model:visible="sharedViewListDlg" title="Shared view list" width="max(900px,60vw)" :footer="null"> <a-modal v-model:visible="sharedViewListDlg" title="Shared view list" width="max(900px,60vw)" :footer="null">

12
packages/nc-gui-v2/components/smartsheet-toolbar/SearchData.vue

@ -15,16 +15,14 @@ const columns = computed(() =>
label: c.title, label: c.title,
})), })),
) )
function onPressEnter() {
reloadData.trigger()
}
</script> </script>
<template> <template>
<a-input <a-input v-model:value="search.query" size="small" class="max-w-[200px]" placeholder="Filter query" @press-enter="onPressEnter">
v-model:value="search.query"
size="small"
class="max-w-[200px]"
placeholder="Filter query"
@press-enter="reloadData.trigger(null)"
>
<template #addonBefore> <template #addonBefore>
<div class="flex align-center relative" @click="isDropdownOpen = true"> <div class="flex align-center relative" @click="isDropdownOpen = true">
<MdiMagnify class="text-grey" /> <MdiMagnify class="text-grey" />

6
packages/nc-gui-v2/components/smartsheet/Cell.vue

@ -1,16 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk' import { UITypes } from 'nocodb-sdk'
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { provide, toRef } from 'vue' import { ActiveCellInj, ColumnInj, EditModeInj, computed, provide, toRef, useColumn, useDebounceFn, useVModel } from '#imports'
import { computed, useColumn, useDebounceFn, useVModel } from '#imports'
import { ActiveCellInj, ColumnInj, EditModeInj } from '~/context'
import { NavigateDir } from '~/lib' import { NavigateDir } from '~/lib'
interface Props { interface Props {
column: ColumnType column: ColumnType
modelValue: any modelValue: any
editEnabled: boolean editEnabled: boolean
rowIndex: number rowIndex?: number
active?: boolean active?: boolean
} }

83
packages/nc-gui-v2/components/smartsheet/Form.vue

@ -3,11 +3,27 @@ import Draggable from 'vuedraggable'
import { RelationTypes, UITypes, getSystemColumns, isVirtualCol } from 'nocodb-sdk' import { RelationTypes, UITypes, getSystemColumns, isVirtualCol } from 'nocodb-sdk'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import type { Permission } from '~/composables/useUIPermission/rolePermissions' import type { Permission } from '~/composables/useUIPermission/rolePermissions'
import { computed, inject, onClickOutside, useDebounceFn } from '#imports' import {
import { ActiveViewInj, IsFormInj, MetaInj } from '~/context' ActiveViewInj,
import { extractSdkResponseErrorMsg } from '~/utils' IsFormInj,
MetaInj,
provide(IsFormInj, true) computed,
extractSdkResponseErrorMsg,
inject,
onClickOutside,
provide,
reactive,
ref,
useDebounceFn,
useGlobal,
useNuxtApp,
useUIPermission,
useViewColumns,
useViewData,
watch,
} from '#imports'
provide(IsFormInj, ref(true))
// todo: generate hideCols based on default values // todo: generate hideCols based on default values
const hiddenCols = ['created_at', 'updated_at'] const hiddenCols = ['created_at', 'updated_at']
@ -20,7 +36,7 @@ const { $api, $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const formState = reactive({}) const formState: Record<any, any> = reactive({})
const secondsRemain = ref(0) const secondsRemain = ref(0)
@ -39,13 +55,13 @@ const { showAll, hideAll, saveOrUpdate } = useViewColumns(view, meta as any, fal
const columns = computed(() => meta?.value?.columns || []) const columns = computed(() => meta?.value?.columns || [])
const localColumns = ref<Record<string, any>>([]) const localColumns = ref<Record<string, any>[]>([])
const hiddenColumns = ref<Record<string, any>>([]) const hiddenColumns = ref<Record<string, any>[]>([])
const draggableRef = ref() const draggableRef = ref()
const systemFieldsIds = ref<Record<string, any>>([]) const systemFieldsIds = ref<Record<string, any>[]>([])
const showColumnDropdown = ref(false) const showColumnDropdown = ref(false)
@ -76,7 +92,8 @@ async function submitForm() {
return return
} }
insertRow(formState) await insertRow(formState)
submitted.value = true submitted.value = true
} }
@ -199,17 +216,23 @@ function setFormData() {
formViewData.value = { formViewData.value = {
...formViewData.value, ...formViewData.value,
submit_another_form: !!(formViewData?.value?.submit_another_form ?? 0), submit_another_form: !!(formViewData?.value?.submit_another_form ?? 0),
show_blank_form: !!(formViewData?.value?.show_blank_form ?? 0), // todo: show_blank_form missing from FormType
} show_blank_form: !!((formViewData?.value as any)?.show_blank_form ?? 0),
} as any
{ {
// email me // email me
let data: Record<string, boolean> = {} let data: Record<string, boolean> = {}
try { try {
data = JSON.parse(formViewData.value.email as string) || {} data = JSON.parse(formViewData.value?.email || '') || {}
} catch (e) {} } catch (e) {
// noop
}
data[state.user.value?.email as string] = emailMe.value data[state.user.value?.email as string] = emailMe.value
formViewData.value.email = JSON.stringify(data)
formViewData.value!.email = JSON.stringify(data)
checkSMTPStatus() checkSMTPStatus()
} }
@ -257,7 +280,7 @@ async function submitCallback() {
const updateColMeta = useDebounceFn(async (col: Record<string, any>) => { const updateColMeta = useDebounceFn(async (col: Record<string, any>) => {
if (col.id) { if (col.id) {
try { try {
$api.dbView.formColumnUpdate(col.id, col) await $api.dbView.formColumnUpdate(col.id, col)
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} }
@ -265,7 +288,7 @@ const updateColMeta = useDebounceFn(async (col: Record<string, any>) => {
}, 250) }, 250)
watch(submitted, (v) => { watch(submitted, (v) => {
if (v && formViewData?.value?.show_blank_form) { if (v && (formViewData?.value as any)?.show_blank_form) {
secondsRemain.value = 5 secondsRemain.value = 5
const intvl = setInterval(() => { const intvl = setInterval(() => {
if (--secondsRemain.value < 0) { if (--secondsRemain.value < 0) {
@ -406,7 +429,14 @@ onMounted(async () => {
<div class="h-[200px] !bg-[#dbdad7]"> <div class="h-[200px] !bg-[#dbdad7]">
<!-- for future implementation of cover image --> <!-- for future implementation of cover image -->
</div> </div>
<a-card class="h-full ma-0 rounded-b-0 pa-4" body-style="max-width: 700px; margin: 0 auto; margin-top: -200px;"> <a-card
class="h-full ma-0 rounded-b-0 pa-4"
:body-style="{
maxWidth: '700px',
margin: '0 auto',
marginTop: '-200px',
}"
>
<a-form ref="formRef" :model="formState"> <a-form ref="formRef" :model="formState">
<a-card class="rounded ma-2 py-10 px-5"> <a-card class="rounded ma-2 py-10 px-5">
<!-- Header --> <!-- Header -->
@ -422,7 +452,9 @@ onMounted(async () => {
@keydown.enter="updateView" @keydown.enter="updateView"
/> />
</a-form-item> </a-form-item>
<div v-else class="ml-3 w-full text-bold text-h3">{{ formViewData.heading }}</div> <div v-else class="ml-3 w-full text-bold text-h3">{{ formViewData.heading }}</div>
<!-- Sub Header --> <!-- Sub Header -->
<a-form-item v-if="isEditable" class="ma-0 gap-0 pa-0"> <a-form-item v-if="isEditable" class="ma-0 gap-0 pa-0">
<a-input <a-input
@ -437,7 +469,9 @@ onMounted(async () => {
@click="updateView" @click="updateView"
/> />
</a-form-item> </a-form-item>
<div v-else class="ml-3 mb-5 w-full text-bold text-h3">{{ formViewData.subheading }}</div> <div v-else class="ml-3 mb-5 w-full text-bold text-h3">{{ formViewData.subheading }}</div>
<Draggable <Draggable
ref="draggableRef" ref="draggableRef"
:list="localColumns" :list="localColumns"
@ -473,6 +507,7 @@ onMounted(async () => {
<mdi-eye-off-outline class="opacity-0 nc-field-remove-icon" @click.stop="hideColumn(index)" /> <mdi-eye-off-outline class="opacity-0 nc-field-remove-icon" @click.stop="hideColumn(index)" />
</div> </div>
</div> </div>
<a-form-item <a-form-item
v-if="isVirtualCol(element)" v-if="isVirtualCol(element)"
class="ma-0 gap-0 pa-0" class="ma-0 gap-0 pa-0"
@ -481,6 +516,7 @@ onMounted(async () => {
> >
<SmartsheetVirtualCell v-model="formState[element.title]" class="nc-input" :column="element" /> <SmartsheetVirtualCell v-model="formState[element.title]" class="nc-input" :column="element" />
</a-form-item> </a-form-item>
<a-form-item <a-form-item
v-else v-else
class="ma-0 gap-0 pa-0" class="ma-0 gap-0 pa-0"
@ -489,6 +525,7 @@ onMounted(async () => {
> >
<SmartsheetCell v-model="formState[element.title]" class="nc-input" :column="element" :edit-enabled="true" /> <SmartsheetCell v-model="formState[element.title]" class="nc-input" :column="element" :edit-enabled="true" />
</a-form-item> </a-form-item>
<div v-if="activeRow === element.title"> <div v-if="activeRow === element.title">
<a-form-item class="my-0 w-1/2"> <a-form-item class="my-0 w-1/2">
<a-input <a-input
@ -500,6 +537,7 @@ onMounted(async () => {
> >
</a-input> </a-input>
</a-form-item> </a-form-item>
<a-form-item class="mt-2 mb-0 w-1/2"> <a-form-item class="mt-2 mb-0 w-1/2">
<a-input <a-input
v-model:value="element.description" v-model:value="element.description"
@ -509,14 +547,18 @@ onMounted(async () => {
@change="updateColMeta(element)" @change="updateColMeta(element)"
/> />
</a-form-item> </a-form-item>
<div class="items-center flex"> <div class="items-center flex">
<span class="text-sm text-gray-500 mr-2">{{ $t('general.required') }}</span> <span class="text-sm text-gray-500 mr-2">{{ $t('general.required') }}</span>
<a-switch v-model:checked="element.required" size="small" class="my-2" @change="updateColMeta(element)" /> <a-switch v-model:checked="element.required" size="small" class="my-2" @change="updateColMeta(element)" />
</div> </div>
</div> </div>
<span class="text-gray-500">{{ element.description }}</span> <span class="text-gray-500">{{ element.description }}</span>
</div> </div>
</template> </template>
<template #footer> <template #footer>
<div <div
v-if="!localColumns.length" v-if="!localColumns.length"
@ -541,9 +583,11 @@ onMounted(async () => {
<div class="text-gray-500 mt-4 mb-2"> <div class="text-gray-500 mt-4 mb-2">
{{ $t('msg.info.afterFormSubmitted') }} {{ $t('msg.info.afterFormSubmitted') }}
</div> </div>
<!-- Show this message --> <!-- Show this message -->
<label class="text-gray-600 text-bold"> {{ $t('msg.info.showMessage') }}: </label> <label class="text-gray-600 text-bold"> {{ $t('msg.info.showMessage') }}: </label>
<a-textarea v-model:value="formViewData.success_msg" rows="3" hide-details @change="updateView" />
<a-textarea v-model:value="formViewData.success_msg" :rows="3" hide-details @change="updateView" />
<!-- Other options --> <!-- Other options -->
<div class="mt-4"> <div class="mt-4">
@ -568,6 +612,7 @@ onMounted(async () => {
/> />
<span class="ml-4">{{ $t('msg.info.showBlankForm') }}</span> <span class="ml-4">{{ $t('msg.info.showBlankForm') }}</span>
</div> </div>
<div class="my-4"> <div class="my-4">
<a-switch v-model:checked="emailMe" v-t="[`a:form-view:email-me`]" size="small" @change="onEmailChange" /> <a-switch v-model:checked="emailMe" v-t="[`a:form-view:email-me`]" size="small" @change="onEmailChange" />
<!-- Email me at <email> --> <!-- Email me at <email> -->

16
packages/nc-gui-v2/components/smartsheet/Pagination.vue

@ -1,15 +1,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, inject } from 'vue' import { computed, inject } from '#imports'
import { ChangePageInj, PaginationDataInj } from '~/context' import { ChangePageInj, PaginationDataInj } from '~/context'
import MdiKeyboardIcon from '~icons/mdi/keyboard-return'
const paginatedData = inject(PaginationDataInj) const paginatedData = inject(PaginationDataInj)!
const changePage = inject(ChangePageInj) const changePage = inject(ChangePageInj)!
const count = computed(() => paginatedData?.value?.totalRows ?? Infinity) const count = computed(() => paginatedData.value?.totalRows ?? Infinity)
const size = computed(() => paginatedData?.value?.pageSize ?? 25) const size = computed(() => paginatedData.value?.pageSize ?? 25)
const page = computed({ const page = computed({
get: () => paginatedData?.value?.page ?? 1, get: () => paginatedData?.value?.page ?? 1,
@ -39,7 +38,7 @@ const page = computed({
<span class="text-xs" style="white-space: nowrap"> Change page:</span> <span class="text-xs" style="white-space: nowrap"> Change page:</span>
<a-input :value="page" size="small" class="ml-1 !text-xs" type="number" @keydown.enter="changePage(page)"> <a-input :value="page" size="small" class="ml-1 !text-xs" type="number" @keydown.enter="changePage(page)">
<template #suffix> <template #suffix>
<MdiKeyboardIcon class="mt-1" @click="changePage(page)" /> <MdiKeyboardReturn class="mt-1" @click="changePage(page)" />
</template> </template>
</a-input> </a-input>
</div> </div>
@ -50,8 +49,7 @@ const page = computed({
<style scoped> <style scoped>
:deep(.ant-pagination-item a) { :deep(.ant-pagination-item a) {
line-height: 21px !important; @apply text-sm !leading-[21px];
@apply text-sm;
} }
:deep(.ant-pagination-item:not(.ant-pagination-item-active) a) { :deep(.ant-pagination-item:not(.ant-pagination-item-active) a) {
line-height: 21px !important; line-height: 21px !important;

38
packages/nc-gui-v2/components/smartsheet/VirtualCell.vue

@ -1,10 +1,27 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { provide, toRef, useVirtualCell } from '#imports' import { ActiveCellInj, CellValueInj, ColumnInj, RowInj, provide, toRef, useVirtualCell } from '#imports'
import type { Row } from '~/composables' import type { Row } from '~/composables'
import { ActiveCellInj, CellValueInj, ColumnInj, RowInj } from '~/context'
import { NavigateDir } from '~/lib' import { NavigateDir } from '~/lib'
const props = defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'navigate'])
const HasMany = defineAsyncComponent(() => import('../virtual-cell/HasMany.vue'))
const ManyToMany = defineAsyncComponent(() => import('../virtual-cell/ManyToMany.vue'))
const BelongsTo = defineAsyncComponent(() => import('../virtual-cell/BelongsTo.vue'))
const Rollup = defineAsyncComponent(() => import('../virtual-cell/HasMany.vue'))
const Formula = defineAsyncComponent(() => import('../virtual-cell/ManyToMany.vue'))
const Count = defineAsyncComponent(() => import('../virtual-cell/BelongsTo.vue'))
const Lookup = defineAsyncComponent(() => import('../virtual-cell/BelongsTo.vue'))
interface Props { interface Props {
column: ColumnType column: ColumnType
modelValue: any modelValue: any
@ -12,9 +29,6 @@ interface Props {
active?: boolean active?: boolean
} }
const props = defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'navigate'])
const column = toRef(props, 'column') const column = toRef(props, 'column')
const active = toRef(props, 'active', false) const active = toRef(props, 'active', false)
const row = toRef(props, 'row') const row = toRef(props, 'row')
@ -33,12 +47,12 @@ const { isLookup, isBt, isRollup, isMm, isHm, isFormula, isCount } = useVirtualC
@keydown.stop.enter.exact="emit('navigate', NavigateDir.NEXT)" @keydown.stop.enter.exact="emit('navigate', NavigateDir.NEXT)"
@keydown.stop.shift.enter.exact="emit('navigate', NavigateDir.PREV)" @keydown.stop.shift.enter.exact="emit('navigate', NavigateDir.PREV)"
> >
<VirtualCellHasMany v-if="isHm" /> <HasMany v-if="isHm" />
<VirtualCellManyToMany v-else-if="isMm" /> <ManyToMany v-else-if="isMm" />
<VirtualCellBelongsTo v-else-if="isBt" /> <BelongsTo v-else-if="isBt" />
<VirtualCellRollup v-else-if="isRollup" /> <Rollup v-else-if="isRollup" />
<VirtualCellFormula v-else-if="isFormula" /> <Formula v-else-if="isFormula" />
<VirtualCellCount v-else-if="isCount" /> <Count v-else-if="isCount" />
<VirtualCellLookup v-else-if="isLookup" /> <Lookup v-else-if="isLookup" />
</div> </div>
</template> </template>

8
packages/nc-gui-v2/components/smartsheet/expanded-form/Comments.vue

@ -1,7 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { nextTick, useExpandedFormStoreOrThrow } from '#imports' import { enumColor, nextTick, ref, timeAgo, useExpandedFormStoreOrThrow, watch } from '#imports'
import { enumColor, timeAgo } from '~/utils'
import MdiAccountIcon from '~icons/mdi/account-circle'
const { loadCommentsAndLogs, commentsAndLogs, isCommentsLoading, commentsOnly, saveComment, isYou, comment } = const { loadCommentsAndLogs, commentsAndLogs, isCommentsLoading, commentsOnly, saveComment, isYou, comment } =
useExpandedFormStoreOrThrow() useExpandedFormStoreOrThrow()
@ -10,6 +8,8 @@ const commentsWrapperEl = ref<HTMLDivElement>()
await loadCommentsAndLogs() await loadCommentsAndLogs()
const showborder = ref(false)
watch( watch(
commentsAndLogs, commentsAndLogs,
() => { () => {
@ -28,7 +28,7 @@ watch(
<template v-else> <template v-else>
<div v-for="log of commentsAndLogs" :key="log.id" class="flex gap-1 text-xs"> <div v-for="log of commentsAndLogs" :key="log.id" class="flex gap-1 text-xs">
<MdiAccountIcon class="row-span-2" :class="isYou(log.user) ? 'text-pink-300' : 'text-blue-300 '" /> <MdiAccountCircle class="row-span-2" :class="isYou(log.user) ? 'text-pink-300' : 'text-blue-300 '" />
<div class="flex-grow"> <div class="flex-grow">
<p class="mb-1 caption edited-text text-[10px] text-gray"> <p class="mb-1 caption edited-text text-[10px] text-gray">
{{ isYou(log.user) ? 'You' : log.user == null ? 'Shared base' : log.user }} {{ isYou(log.user) ? 'You' : log.user == null ? 'Shared base' : log.user }}

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

@ -42,23 +42,31 @@ const iconColor = '#1890ff'
<template v-if="meta"> <template v-if="meta">
{{ meta.title }} {{ meta.title }}
</template> </template>
<!-- todo: table doesn't exist?
<template v-else> <template v-else>
{{ table }} {{ table }}
</template> </template>
-->
<template v-if="primaryValue">: {{ primaryValue }}</template> <template v-if="primaryValue">: {{ primaryValue }}</template>
</h5> </h5>
<div class="flex-grow" /> <div class="flex-grow" />
<mdi-reload class="cursor-pointer select-none" /> <mdi-reload class="cursor-pointer select-none" />
<component <component
:is="drawerToggleIcon" :is="drawerToggleIcon"
v-if="isUIAllowed('rowComments')" v-if="isUIAllowed('rowComments')"
class="cursor-pointer select-none" class="cursor-pointer select-none"
@click="commentsDrawer = !commentsDrawer" @click="commentsDrawer = !commentsDrawer"
/> />
<a-button class="!text" @click="emit('cancel')"> <a-button class="!text" @click="emit('cancel')">
<!-- Cancel --> <!-- Cancel -->
{{ $t('general.cancel') }} {{ $t('general.cancel') }}
</a-button> </a-button>
<a-button :disabled="!isUIAllowed('tableRowUpdate')" type="primary" @click="save"> <a-button :disabled="!isUIAllowed('tableRowUpdate')" type="primary" @click="save">
<!-- Save Row --> <!-- Save Row -->
{{ $t('activity.saveRow') }} {{ $t('activity.saveRow') }}

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

@ -1,25 +1,32 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType, TableType } from 'nocodb-sdk' import type { ColumnType, TableType, ViewType } from 'nocodb-sdk'
import { isVirtualCol } from 'nocodb-sdk' import { isVirtualCol } from 'nocodb-sdk'
import type { Ref } from 'vue'
import Cell from '../Cell.vue'
import VirtualCell from '../VirtualCell.vue'
import Comments from './Comments.vue' import Comments from './Comments.vue'
import Header from './Header.vue' import Header from './Header.vue'
import { import {
FieldsInj,
IsFormInj,
MetaInj,
NOCO,
computedInject, computedInject,
extractPkFromRow,
provide, provide,
ref,
toRef, toRef,
useNuxtApp, useNuxtApp,
useProject,
useProvideExpandedFormStore, useProvideExpandedFormStore,
useProvideSmartsheetStore, useProvideSmartsheetStore,
useVModel, useVModel,
watch, watch,
} from '#imports' } from '#imports'
import { NOCO } from '~/lib'
import { extractPkFromRow } from '~/utils'
import type { Row } from '~/composables' import type { Row } from '~/composables'
import { FieldsInj, IsFormInj, MetaInj } from '~/context'
interface Props { interface Props {
modelValue: string | null modelValue?: boolean
row: Row row: Row
state?: Record<string, any> | null state?: Record<string, any> | null
meta: TableType meta: TableType
@ -28,9 +35,13 @@ interface Props {
} }
const props = defineProps<Props>() const props = defineProps<Props>()
const emits = defineEmits(['update:modelValue']) const emits = defineEmits(['update:modelValue'])
const row = toRef(props, 'row') const row = toRef(props, 'row')
const state = toRef(props, 'state') const state = toRef(props, 'state')
const meta = toRef(props, 'meta') const meta = toRef(props, 'meta')
const fields = computedInject(FieldsInj, (_fields) => { const fields = computedInject(FieldsInj, (_fields) => {
@ -45,25 +56,26 @@ provide(MetaInj, meta)
const { commentsDrawer, changedColumns, state: rowState } = useProvideExpandedFormStore(meta, row) const { commentsDrawer, changedColumns, state: rowState } = useProvideExpandedFormStore(meta, row)
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
if (props.loadRow) { if (props.loadRow) {
const { project } = useProject() const { project } = useProject()
row.value.row = await $api.dbTableRow.read( row.value.row = await $api.dbTableRow.read(
NOCO, NOCO,
project.value.id as string, project.value.id as string,
meta.value.title, meta.value.title,
extractPkFromRow(row.value.row, meta.value.columns as ColumnType[]), extractPkFromRow(row.value.row, meta.value.columns as ColumnType[]),
) )
row.value.oldRow = { ...row.value.row } row.value.oldRow = { ...row.value.row }
row.value.rowMeta = {} row.value.rowMeta = {}
} }
useProvideSmartsheetStore(ref({}) as any, meta) useProvideSmartsheetStore(ref({}) as Ref<ViewType>, meta)
provide(IsFormInj, ref(true)) provide(IsFormInj, ref(true))
// accept as a prop
// const row: Row = { row: {}, rowMeta: {}, oldRow: {} }
watch( watch(
state, state,
() => { () => {
@ -76,7 +88,15 @@ watch(
{ immediate: true }, { immediate: true },
) )
const isExpanded = useVModel(props, 'modelValue', emits) const isExpanded = useVModel(props, 'modelValue', emits, {
defaultValue: false,
})
</script>
<script lang="ts">
export default {
name: 'ExpandedForm',
}
</script> </script>
<template> <template>
@ -86,13 +106,14 @@ const isExpanded = useVModel(props, 'modelValue', emits)
<div class="flex h-full nc-form-wrapper items-stretch min-h-[70vh]"> <div class="flex h-full nc-form-wrapper items-stretch min-h-[70vh]">
<div class="flex-grow overflow-auto scrollbar-thin-primary"> <div class="flex-grow overflow-auto scrollbar-thin-primary">
<div class="w-[500px] mx-auto"> <div class="w-[500px] mx-auto">
<div v-for="col in fields" :key="col.title" class="mt-2 py-2" :class="`nc-expand-col-${col.title}`"> <div v-for="col of fields" :key="col.title" class="mt-2 py-2" :class="`nc-expand-col-${col.title}`">
<SmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" /> <SmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" />
<SmartsheetHeaderCell v-else :column="col" /> <SmartsheetHeaderCell v-else :column="col" />
<div class="!bg-white rounded px-1 min-h-[35px] flex align-center mt-2"> <div class="!bg-white rounded px-1 min-h-[35px] flex align-center mt-2">
<SmartsheetVirtualCell v-if="isVirtualCol(col)" v-model="row.row[col.title]" :row="row" :column="col" /> <VirtualCell v-if="isVirtualCol(col)" v-model="row.row[col.title]" :row="row" :column="col" />
<SmartsheetCell
<Cell
v-else v-else
v-model="row.row[col.title]" v-model="row.row[col.title]"
:column="col" :column="col"

30
packages/nc-gui-v2/components/smartsheet/sidebar/menu/ApiSnippet.vue

@ -1,8 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import HTTPSnippet from 'httpsnippet' // import HTTPSnippet from 'httpsnippet'
import { useClipboard } from '@vueuse/core' import { useClipboard } from '@vueuse/core'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { ActiveViewInj, MetaInj } from '~/context' import { ActiveViewInj, MetaInj } from '~/context'
import { inject, useGlobal, useProject, useSmartsheetStoreOrThrow, useVModel, useViewData } from '#imports'
const props = defineProps<Props>() const props = defineProps<Props>()
@ -13,11 +14,17 @@ interface Props {
} }
const { project } = $(useProject()) const { project } = $(useProject())
const { appInfo, token } = $(useGlobal()) const { appInfo, token } = $(useGlobal())
const meta = $(inject(MetaInj))
const view = $(inject(ActiveViewInj)) const meta = $(inject(MetaInj)!)
const view = $(inject(ActiveViewInj)!)
const { xWhere } = useSmartsheetStoreOrThrow() const { xWhere } = useSmartsheetStoreOrThrow()
const { queryParams } = $(useViewData(meta, view as any, xWhere))
const { queryParams } = $(useViewData($$(meta), view as any, xWhere))
const { copy } = useClipboard() const { copy } = useClipboard()
let vModel = $(useVModel(props, 'modelValue', emits)) let vModel = $(useVModel(props, 'modelValue', emits))
@ -66,20 +73,7 @@ const apiUrl = $computed(
new URL(`/api/v1/db/data/noco/${project.id}/${meta.title}/views/${view.title}`, (appInfo && appInfo.ncSiteUrl) || '/').href, new URL(`/api/v1/db/data/noco/${project.id}/${meta.title}/views/${view.title}`, (appInfo && appInfo.ncSiteUrl) || '/').href,
) )
const snippet = $computed( const snippet = $computed(() => '')
() =>
new HTTPSnippet({
method: 'GET',
headers: [{ name: 'xc-auth', value: token as string, comment: 'JWT Auth token' }],
url: apiUrl,
queryString: Object.entries(queryParams || {}).map(([name, value]) => {
return {
name,
value: String(value),
}
}),
}),
)
const activeLang = $computed(() => langs.find((lang) => lang.name === selectedLangName)) const activeLang = $computed(() => langs.find((lang) => lang.name === selectedLangName))

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

@ -32,7 +32,9 @@ const loadBase = async () => {
try { try {
if (!project.value.id) return if (!project.value.id) return
const res = await $api.project.sharedBaseGet(project.value.id) // todo: response is missing roles in type
const res = (await $api.project.sharedBaseGet(project.value.id)) as any
base = { base = {
uuid: res.uuid, uuid: res.uuid,
url: res.url, url: res.url,
@ -47,9 +49,10 @@ const createShareBase = async (role = ShareBaseRole.Viewer) => {
try { try {
if (!project.value.id) return if (!project.value.id) return
const res = await $api.project.sharedBaseUpdate(project.value.id, { // todo: return type void?
const res = (await $api.project.sharedBaseUpdate(project.value.id, {
roles: role, roles: role,
}) })) as any
base = res ?? {} base = res ?? {}
base!.role = role base!.role = role

55
packages/nc-gui-v2/components/template/Editor.vue

@ -3,14 +3,27 @@ import type { ColumnType, TableType } from 'nocodb-sdk'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import { UITypes, isVirtualCol } from 'nocodb-sdk'
import { Form, message } from 'ant-design-vue' import { Form, message } from 'ant-design-vue'
import { srcDestMappingColumns, tableColumns } from './utils' import { srcDestMappingColumns, tableColumns } from './utils'
import { computed, onMounted } from '#imports' import {
import { extractSdkResponseErrorMsg, fieldRequiredValidator, getUIDTIcon } from '~/utils' MetaInj,
import { MetaInj, ReloadViewDataHookInj } from '~/context' ReloadViewDataHookInj,
computed,
extractSdkResponseErrorMsg,
fieldRequiredValidator,
getUIDTIcon,
nextTick,
onMounted,
reactive,
ref,
useProject,
useTabs,
useTemplateRefsList,
} from '#imports'
import { TabType } from '~/composables'
interface Props { interface Props {
quickImportType: 'csv' | 'excel' | 'json' quickImportType: 'csv' | 'excel' | 'json'
projectTemplate: Record<string, any> projectTemplate: Record<string, any>
importData: Record<string, any>[] importData: Record<string, any>
importColumns: any[] importColumns: any[]
importOnly: boolean importOnly: boolean
maxRowsToParse: number maxRowsToParse: number
@ -41,7 +54,7 @@ const expansionPanel = ref<number[]>([])
const editableTn = ref<boolean[]>([]) const editableTn = ref<boolean[]>([])
const inputRefs = ref<HTMLInputElement[]>([]) const inputRefs = useTemplateRefsList<HTMLInputElement>()
const isImporting = ref(false) const isImporting = ref(false)
@ -74,6 +87,7 @@ const { sqlUi, project, loadTables } = useProject()
onMounted(() => { onMounted(() => {
parseAndLoadTemplate() parseAndLoadTemplate()
nextTick(() => { nextTick(() => {
inputRefs.value[0]?.focus() inputRefs.value[0]?.focus()
}) })
@ -409,7 +423,7 @@ async function importTemplate() {
await loadTables() await loadTables()
addTab({ addTab({
...tab, ...tab,
type: 'table', type: TabType.TABLE,
}) })
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
@ -476,13 +490,15 @@ onMounted(() => {
</p> </p>
</a-form> </a-form>
<a-collapse v-if="data.tables && data.tables.length" v-model:activeKey="expansionPanel" class="template-collapse" accordion> <a-collapse v-if="data.tables && data.tables.length" v-model:activeKey="expansionPanel" class="template-collapse" accordion>
<a-collapse-panel v-for="(table, tableIdx) in data.tables" :key="tableIdx"> <a-collapse-panel v-for="(table, tableIdx) of data.tables" :key="tableIdx">
<template #header> <template #header>
<span class="font-weight-bold text-lg flex items-center gap-2"> <span class="font-weight-bold text-lg flex items-center gap-2">
<mdi-table class="text-primary" /> <mdi-table class="text-primary" />
{{ table.ref_table_name }} {{ table.ref_table_name }}
</span> </span>
</template> </template>
<a-table <a-table
v-if="srcDestMapping" v-if="srcDestMapping"
class="template-form" class="template-form"
@ -496,10 +512,12 @@ onMounted(() => {
{{ column.name }} {{ column.name }}
</span> </span>
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'source_column'"> <template v-if="column.key === 'source_column'">
<span>{{ record.srcCn }}</span> <span>{{ record.srcCn }}</span>
</template> </template>
<template v-else-if="column.key === 'destination_column'"> <template v-else-if="column.key === 'destination_column'">
<a-select v-model:value="record.destCn" class="w-52" show-search :filter-option="filterOption"> <a-select v-model:value="record.destCn" class="w-52" show-search :filter-option="filterOption">
<a-select-option v-for="(col, i) of columns" :key="i" :value="col.title"> <a-select-option v-for="(col, i) of columns" :key="i" :value="col.title">
@ -525,13 +543,14 @@ onMounted(() => {
{{ data.tables.length }} sheet{{ data.tables.length > 1 ? 's' : '' }} {{ data.tables.length }} sheet{{ data.tables.length > 1 ? 's' : '' }}
available for import available for import
</p> </p>
<a-collapse <a-collapse
v-if="data.tables && data.tables.length" v-if="data.tables && data.tables.length"
v-model:activeKey="expansionPanel" v-model:activeKey="expansionPanel"
class="template-collapse" class="template-collapse"
accordion accordion
> >
<a-collapse-panel v-for="(table, tableIdx) in data.tables" :key="tableIdx"> <a-collapse-panel v-for="(table, tableIdx) of data.tables" :key="tableIdx">
<template #header> <template #header>
<a-form-item v-if="editableTn[tableIdx]" v-bind="validateInfos[`tables.${tableIdx}.table_name`]" no-style> <a-form-item v-if="editableTn[tableIdx]" v-bind="validateInfos[`tables.${tableIdx}.table_name`]" no-style>
<a-input <a-input
@ -539,16 +558,18 @@ onMounted(() => {
class="max-w-xs" class="max-w-xs"
size="large" size="large"
hide-details hide-details
@click="(e) => e.stopPropagation()" @click="$event.stopPropagation()"
@blur="setEditableTn(tableIdx, false)" @blur="setEditableTn(tableIdx, false)"
@keydown.enter="setEditableTn(tableIdx, false)" @keydown.enter="setEditableTn(tableIdx, false)"
/> />
</a-form-item> </a-form-item>
<span v-else class="font-weight-bold text-lg flex items-center gap-2" @click="setEditableTn(tableIdx, true)"> <span v-else class="font-weight-bold text-lg flex items-center gap-2" @click="setEditableTn(tableIdx, true)">
<mdi-table class="text-primary" /> <mdi-table class="text-primary" />
{{ table.table_name }} {{ table.table_name }}
</span> </span>
</template> </template>
<template #extra> <template #extra>
<a-tooltip bottom> <a-tooltip bottom>
<template #title> <template #title>
@ -560,7 +581,7 @@ onMounted(() => {
</template> </template>
<a-table <a-table
v-if="table.columns.length" v-if="table.columns && table.columns.length"
class="template-form" class="template-form"
row-class-name="template-form-row" row-class-name="template-form-row"
:data-source="table.columns" :data-source="table.columns"
@ -573,11 +594,13 @@ onMounted(() => {
{{ $t('labels.columnName') }} {{ $t('labels.columnName') }}
</span> </span>
</template> </template>
<template v-else-if="column.key === 'uidt'"> <template v-else-if="column.key === 'uidt'">
<span> <span>
{{ $t('labels.columnType') }} {{ $t('labels.columnType') }}
</span> </span>
</template> </template>
<template v-else-if="column.key === 'dtxp' && hasSelectColumn[tableIdx]"> <template v-else-if="column.key === 'dtxp' && hasSelectColumn[tableIdx]">
<span> <span>
<!-- TODO: i18n --> <!-- TODO: i18n -->
@ -585,19 +608,14 @@ onMounted(() => {
</span> </span>
</template> </template>
</template> </template>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'column_name'"> <template v-if="column.key === 'column_name'">
<a-form-item v-bind="validateInfos[`tables.${tableIdx}.columns.${record.key}.${column.key}`]"> <a-form-item v-bind="validateInfos[`tables.${tableIdx}.columns.${record.key}.${column.key}`]">
<a-input <a-input :ref="inputRefs.set" v-model:value="record.column_name" />
:ref="
(el) => {
inputRefs[record.key] = el
}
"
v-model:value="record.column_name"
/>
</a-form-item> </a-form-item>
</template> </template>
<template v-else-if="column.key === 'uidt'"> <template v-else-if="column.key === 'uidt'">
<a-form-item v-bind="validateInfos[`tables.${tableIdx}.columns.${record.key}.${column.key}`]"> <a-form-item v-bind="validateInfos[`tables.${tableIdx}.columns.${record.key}.${column.key}`]">
<a-select <a-select
@ -622,6 +640,7 @@ onMounted(() => {
<!-- TODO: i18n --> <!-- TODO: i18n -->
<span>Primary Value</span> <span>Primary Value</span>
</template> </template>
<div class="flex items-center float-right mr-4"> <div class="flex items-center float-right mr-4">
<mdi-key-star class="text-lg" /> <mdi-key-star class="text-lg" />
</div> </div>

29
packages/nc-gui-v2/components/virtual-cell/BelongsTo.vue

@ -1,22 +1,35 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import ItemChip from './components/ItemChip.vue' import {
import ListItems from './components/ListItems.vue' ActiveCellInj,
import { inject, ref, useProvideLTARStore, useSmartsheetRowStoreOrThrow } from '#imports' CellValueInj,
import { ActiveCellInj, CellValueInj, ColumnInj, EditModeInj, ReloadViewDataHookInj, RowInj } from '~/context' ColumnInj,
EditModeInj,
ReloadViewDataHookInj,
RowInj,
defineAsyncComponent,
inject,
ref,
useProvideLTARStore,
useSmartsheetRowStoreOrThrow,
} from '#imports'
import MdiArrowExpand from '~icons/mdi/arrow-expand' import MdiArrowExpand from '~icons/mdi/arrow-expand'
import MdiPlus from '~icons/mdi/plus' import MdiPlus from '~icons/mdi/plus'
const column = inject(ColumnInj) const ItemChip = defineAsyncComponent(() => import('./components/ItemChip.vue'))
const ListItems = defineAsyncComponent(() => import('./components/ListItems.vue'))
const column = inject(ColumnInj)!
const reloadTrigger = inject(ReloadViewDataHookInj)! const reloadTrigger = inject(ReloadViewDataHookInj)!
const cellValue = inject(CellValueInj, ref<any>(null)) const cellValue = inject(CellValueInj, ref<any>(null))
const row = inject(RowInj) const row = inject(RowInj)!
const active = inject(ActiveCellInj) const active = inject(ActiveCellInj)!
const editEnabled = inject(EditModeInj) const editEnabled = inject(EditModeInj)
@ -55,7 +68,7 @@ const unlinkRef = async (rec: Record<string, any>) => {
<template> <template>
<div class="flex w-full chips-wrapper align-center" :class="{ active }"> <div class="flex w-full chips-wrapper align-center" :class="{ active }">
<div class="chips d-flex align-center flex-grow"> <div class="chips d-flex align-center flex-grow">
<template v-if="value"> <template v-if="value && relatedTablePrimaryValueProp">
<ItemChip :item="value" :value="value[relatedTablePrimaryValueProp]" @unlink="unlinkRef(value)" /> <ItemChip :item="value" :value="value[relatedTablePrimaryValueProp]" @unlink="unlinkRef(value)" />
</template> </template>
</div> </div>

4
packages/nc-gui-v2/components/virtual-cell/Formula.vue

@ -1,7 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, inject, ref, useProject } from '#imports' import { CellValueInj, ColumnInj, computed, handleTZ, inject, ref, replaceUrlsWithLink, useProject } from '#imports'
import { CellValueInj, ColumnInj } from '~/context'
import { handleTZ, replaceUrlsWithLink } from '~/utils'
// todo: column type doesn't have required property `error` - throws in typecheck // todo: column type doesn't have required property `error` - throws in typecheck
const column: any = inject(ColumnInj) const column: any = inject(ColumnInj)

27
packages/nc-gui-v2/components/virtual-cell/HasMany.vue

@ -1,11 +1,26 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import ItemChip from './components/ItemChip.vue' import {
import ListChildItems from './components/ListChildItems.vue' CellValueInj,
import ListItems from './components/ListItems.vue' ColumnInj,
import { computed, inject, ref, useProvideLTARStore, useSmartsheetRowStoreOrThrow } from '#imports' EditModeInj,
import { CellValueInj, ColumnInj, EditModeInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context' IsFormInj,
ReloadViewDataHookInj,
RowInj,
computed,
defineAsyncComponent,
inject,
ref,
useProvideLTARStore,
useSmartsheetRowStoreOrThrow,
} from '#imports'
const ItemChip = defineAsyncComponent(() => import('./components/ItemChip.vue'))
const ListItems = defineAsyncComponent(() => import('./components/ListItems.vue'))
const ListChildItems = defineAsyncComponent(() => import('./components/ListChildItems.vue'))
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
@ -85,7 +100,9 @@ const unlinkRef = async (rec: Record<string, any>) => {
/> />
</div> </div>
</template> </template>
<ListItems v-model="listItemsDlg" /> <ListItems v-model="listItemsDlg" />
<ListChildItems <ListChildItems
v-model="childListDlg" v-model="childListDlg"
@attach-record=" @attach-record="

12
packages/nc-gui-v2/components/virtual-cell/Lookup.vue

@ -2,17 +2,19 @@
import type { ColumnType, LinkToAnotherRecordType, LookupType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, LookupType } from 'nocodb-sdk'
import { RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk' import { RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { CellValueInj, ColumnInj, MetaInj, ReadonlyInj } from '~/context' import { CellValueInj, ColumnInj, MetaInj, ReadonlyInj, computed, inject, provide, useColumn, useMetas } from '#imports'
import { computed, inject, provide, useColumn, useMetas } from '#imports'
const { metas, getMeta } = useMetas() const { metas, getMeta } = useMetas()
provide(ReadonlyInj, true) provide(ReadonlyInj, true)
const column = inject(ColumnInj)! as Ref<ColumnType & { colOptions: LookupType }> const column = inject(ColumnInj)! as Ref<ColumnType & { colOptions: LookupType }>
const meta = inject(MetaInj) const meta = inject(MetaInj)
const value = inject(CellValueInj) const value = inject(CellValueInj)
const arrValue = computed(() => (Array.isArray(value?.value) ? value?.value : [value?.value]))
const arrValue = computed(() => (Array.isArray(value?.value) ? value?.value : [value?.value]) ?? [])
const relationColumn = meta?.value.columns?.find((c) => c.id === column.value.colOptions?.fk_relation_column_id) as ColumnType & { const relationColumn = meta?.value.columns?.find((c) => c.id === column.value.colOptions?.fk_relation_column_id) as ColumnType & {
colOptions: LinkToAnotherRecordType colOptions: LinkToAnotherRecordType
@ -22,7 +24,7 @@ await getMeta(relationColumn.colOptions.fk_related_model_id!)
const lookupTableMeta = computed(() => metas.value[relationColumn.colOptions.fk_related_model_id!]) const lookupTableMeta = computed(() => metas.value[relationColumn.colOptions.fk_related_model_id!])
const lookupColumn = computed( const lookupColumn = computed<any>(
() => () =>
lookupTableMeta.value.columns?.find( lookupTableMeta.value.columns?.find(
(c: Record<string, any>) => c.id === column.value.colOptions?.fk_lookup_column_id, (c: Record<string, any>) => c.id === column.value.colOptions?.fk_lookup_column_id,
@ -58,7 +60,7 @@ const lookupColumnMetaProps = useColumn(lookupColumn)
<template v-else> <template v-else>
<!-- For attachment cell avoid adding chip style --> <!-- For attachment cell avoid adding chip style -->
<div <div
v-for="(v, i) in arrValue" v-for="(v, i) of arrValue"
:key="i" :key="i"
:class="{ 'bg-gray-100 px-2 rounded-full': !lookupColumnMetaProps.isAttachment }" :class="{ 'bg-gray-100 px-2 rounded-full': !lookupColumnMetaProps.isAttachment }"
> >

24
packages/nc-gui-v2/components/virtual-cell/ManyToMany.vue

@ -1,11 +1,25 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import ItemChip from './components/ItemChip.vue' import {
import ListChildItems from './components/ListChildItems.vue' CellValueInj,
import ListItems from './components/ListItems.vue' ColumnInj,
import { computed, inject, ref, useProvideLTARStore, useSmartsheetRowStoreOrThrow } from '#imports' EditModeInj,
import { CellValueInj, ColumnInj, EditModeInj, IsFormInj, ReloadViewDataHookInj, RowInj } from '~/context' IsFormInj,
ReloadViewDataHookInj,
RowInj,
computed,
inject,
ref,
useProvideLTARStore,
useSmartsheetRowStoreOrThrow,
} from '#imports'
const ItemChip = defineAsyncComponent(() => import('./components/ItemChip.vue'))
const ListItems = defineAsyncComponent(() => import('./components/ListItems.vue'))
const ListChildItems = defineAsyncComponent(() => import('./components/ListChildItems.vue'))
const column = inject(ColumnInj)! const column = inject(ColumnInj)!

2
packages/nc-gui-v2/components/virtual-cell/Rollup.vue

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { CellValueInj } from '~/context' import { CellValueInj, inject } from '#imports'
const value = inject(CellValueInj) const value = inject(CellValueInj)
</script> </script>

26
packages/nc-gui-v2/components/virtual-cell/components/ItemChip.vue

@ -1,6 +1,5 @@
<script setup lang="ts"> <script lang="ts" setup>
import { useLTARStoreOrThrow } from '#imports' import { ActiveCellInj, EditModeInj, IsFormInj, defineAsyncComponent, inject, ref, useLTARStoreOrThrow } from '#imports'
import { ActiveCellInj, EditModeInj, IsFormInj } from '~/context'
interface Props { interface Props {
value?: string | number | boolean value?: string | number | boolean
@ -11,17 +10,25 @@ const { value, item } = defineProps<Props>()
const emit = defineEmits(['unlink']) const emit = defineEmits(['unlink'])
const { relatedTableMeta } = useLTARStoreOrThrow() const ExpandedForm: any = defineAsyncComponent(() => import('../../smartsheet/expanded-form/index.vue'))
const editEnabled = inject(EditModeInj) const { relatedTableMeta } = useLTARStoreOrThrow()!
const editEnabled = inject(EditModeInj)!
const active = inject(ActiveCellInj, ref(false)) const active = inject(ActiveCellInj, ref(false))
const isForm = inject(IsFormInj) const isForm = inject(IsFormInj)!
const expandedFormDlg = ref(false) const expandedFormDlg = ref(false)
</script> </script>
<script lang="ts">
export default {
name: 'ItemChip',
}
</script>
<template> <template>
<div <div
class="group py-1 px-2 flex align-center gap-1 bg-gray-200/50 hover:bg-gray-200 rounded-[20px]" class="group py-1 px-2 flex align-center gap-1 bg-gray-200/50 hover:bg-gray-200 rounded-[20px]"
@ -29,18 +36,21 @@ const expandedFormDlg = ref(false)
@click="expandedFormDlg = true" @click="expandedFormDlg = true"
> >
<span class="name">{{ value }}</span> <span class="name">{{ value }}</span>
<div v-show="active || isForm" v-if="editEnabled" class="flex align-center"> <div v-show="active || isForm" v-if="editEnabled" class="flex align-center">
<MdiCloseThick class="unlink-icon text-xs text-gray-500/50 group-hover:text-gray-500" @click.stop="emit('unlink')" /> <MdiCloseThick class="unlink-icon text-xs text-gray-500/50 group-hover:text-gray-500" @click.stop="emit('unlink')" />
</div> </div>
<SmartsheetExpandedForm <Suspense>
v-if="expandedFormDlg && editEnabled" <ExpandedForm
v-if="editEnabled"
v-model="expandedFormDlg" v-model="expandedFormDlg"
:row="{ row: item }" :row="{ row: item }"
:meta="relatedTableMeta" :meta="relatedTableMeta"
load-row load-row
use-meta-fields use-meta-fields
/> />
</Suspense>
</div> </div>
</template> </template>

21
packages/nc-gui-v2/components/virtual-cell/components/ListChildItems.vue

@ -1,12 +1,23 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Empty, Modal } from 'ant-design-vue' import { Empty, Modal } from 'ant-design-vue'
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { computed, useLTARStoreOrThrow, useSmartsheetRowStoreOrThrow, useVModel, watch } from '#imports' import {
import { ColumnInj, EditModeInj, IsFormInj } from '~/context' ColumnInj,
EditModeInj,
IsFormInj,
computed,
useLTARStoreOrThrow,
useSmartsheetRowStoreOrThrow,
useVModel,
watch,
} from '#imports'
const props = defineProps<{ modelValue?: boolean }>() const props = defineProps<{ modelValue?: boolean }>()
const emit = defineEmits(['update:modelValue', 'attachRecord']) const emit = defineEmits(['update:modelValue', 'attachRecord'])
const ExpandedForm: any = defineAsyncComponent(() => import('../../smartsheet/expanded-form/index.vue'))
const vModel = useVModel(props, 'modelValue', emit) const vModel = useVModel(props, 'modelValue', emit)
const isForm = inject(IsFormInj, ref(false)) const isForm = inject(IsFormInj, ref(false))
@ -120,14 +131,16 @@ const expandedFormRow = ref()
<a-empty v-else class="my-10" :image="Empty.PRESENTED_IMAGE_SIMPLE" /> <a-empty v-else class="my-10" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
</div> </div>
<SmartsheetExpandedForm <Suspense>
v-if="expandedFormDlg && expandedFormRow" <ExpandedForm
v-if="expandedFormRow"
v-model="expandedFormDlg" v-model="expandedFormDlg"
:row="{ row: expandedFormRow }" :row="{ row: expandedFormRow }"
:meta="relatedTableMeta" :meta="relatedTableMeta"
load-row load-row
use-meta-fields use-meta-fields
/> />
</Suspense>
</component> </component>
</template> </template>

19
packages/nc-gui-v2/components/virtual-cell/components/ListItems.vue

@ -2,13 +2,24 @@
import { RelationTypes, UITypes } from 'nocodb-sdk' import { RelationTypes, UITypes } from 'nocodb-sdk'
import type { ColumnType, LinkToAnotherRecordType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType } from 'nocodb-sdk'
import { Empty } from 'ant-design-vue' import { Empty } from 'ant-design-vue'
import { computed, useLTARStoreOrThrow, useSmartsheetRowStoreOrThrow, useVModel } from '#imports' import {
import { ColumnInj } from '~/context' ColumnInj,
computed,
defineAsyncComponent,
inject,
ref,
useLTARStoreOrThrow,
useSmartsheetRowStoreOrThrow,
useVModel,
watch,
} from '#imports'
const props = defineProps<{ modelValue: boolean }>() const props = defineProps<{ modelValue: boolean }>()
const emit = defineEmits(['update:modelValue', 'addNewRecord']) const emit = defineEmits(['update:modelValue', 'addNewRecord'])
const ExpandedForm: any = defineAsyncComponent(() => import('../../smartsheet/expanded-form/index.vue'))
const vModel = useVModel(props, 'modelValue', emit) const vModel = useVModel(props, 'modelValue', emit)
const column = inject(ColumnInj) const column = inject(ColumnInj)
@ -118,7 +129,8 @@ const newRowState = computed(() => {
</template> </template>
<a-empty v-else class="my-10" :image="Empty.PRESENTED_IMAGE_SIMPLE" /> <a-empty v-else class="my-10" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
<SmartsheetExpandedForm <Suspense>
<ExpandedForm
v-if="expandedFormDlg" v-if="expandedFormDlg"
v-model="expandedFormDlg" v-model="expandedFormDlg"
:meta="relatedTableMeta" :meta="relatedTableMeta"
@ -126,6 +138,7 @@ const newRowState = computed(() => {
:state="newRowState" :state="newRowState"
use-meta-fields use-meta-fields
/> />
</Suspense>
</div> </div>
</a-modal> </a-modal>
</template> </template>

66
packages/nc-gui-v2/components/webhook/ChannelMultiSelect.vue

@ -0,0 +1,66 @@
<script setup lang="ts">
import { onMounted } from '@vue/runtime-core'
interface Props {
modelValue: Record<string, any>[]
availableChannelList: Record<string, any>[]
placeholder: string
}
const { availableChannelList, placeholder, ...rest } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const vModel = useVModel(rest, 'modelValue', emit)
// idx of selected channels
const localChannelValues = $ref<number[]>([])
// availableChannelList with idx enriched
let availableChannelWithIdxList = $ref<Record<string, any>[]>()
watch(
() => localChannelValues,
(v) => {
const res = []
for (const channelIdx of v) {
const target = availableChannelWithIdxList.find((availableChannel) => availableChannel.idx === channelIdx)
if (target) {
// push without target.idx
res.push({ webhook_url: target.webhook_url, channel: target.channel })
}
}
vModel.value = res
},
)
onMounted(() => {
if (availableChannelList.length) {
// enrich idx
let idx = 0
availableChannelWithIdxList = availableChannelList.map((channel) => ({
...channel,
idx: idx++,
}))
// build localChannelValues from modelValue
for (const channel of rest.modelValue || []) {
const target = availableChannelWithIdxList.find(
(availableChannelWithIdx) =>
availableChannelWithIdx.webhook_url === channel.webhook_url && availableChannelWithIdx.channel === channel.channel,
)
if (target) {
localChannelValues.push(target.idx)
}
}
}
})
</script>
<template>
<a-select v-model:value="localChannelValues" mode="multiple" :placeholder="placeholder" max-tag-count="responsive">
<a-select-option v-for="channel of availableChannelWithIdxList" :key="channel.idx" :value="channel.idx">{{
channel.channel
}}</a-select-option>
</a-select>
</template>

2
packages/nc-gui-v2/components/webhook/Drawer.vue

@ -31,8 +31,10 @@ async function editHook(hook: Record<string, any>) {
:body-style="{ background: 'rgba(67, 81, 232, 0.05)', padding: '50px' }" :body-style="{ background: 'rgba(67, 81, 232, 0.05)', padding: '50px' }"
@keydown.esc="vModel = false" @keydown.esc="vModel = false"
> >
<div>
<WebhookEditor v-if="editOrAdd" ref="webhookEditorRef" @back-to-list="editOrAdd = false" /> <WebhookEditor v-if="editOrAdd" ref="webhookEditorRef" @back-to-list="editOrAdd = false" />
<WebhookList v-else @edit="editHook" @add="editOrAdd = true" /> <WebhookList v-else @edit="editHook" @add="editOrAdd = true" />
</div>
<div class="self-center flex flex-column flex-wrap gap-4 items-center mt-4 md:mx-8 md:justify-between justify-center"> <div class="self-center flex flex-column flex-wrap gap-4 items-center mt-4 md:mx-8 md:justify-between justify-center">
<a-button v-t="['e:hiring']" href="https://angel.co/company/nocodb" target="_blank" size="large"> <a-button v-t="['e:hiring']" href="https://angel.co/company/nocodb" target="_blank" size="large">
🚀 We are Hiring! 🚀 🚀 We are Hiring! 🚀

93
packages/nc-gui-v2/components/webhook/Editor.vue

@ -1,13 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { Form, message } from 'ant-design-vue' import { Form, message } from 'ant-design-vue'
import { MetaInj } from '~/context' import { MetaInj, extractSdkResponseErrorMsg, fieldRequiredValidator, inject, reactive, useApi, useNuxtApp } from '#imports'
import { extractSdkResponseErrorMsg, fieldRequiredValidator } from '~/utils'
import { inject, reactive, useApi, useNuxtApp } from '#imports'
interface Option {
label: string
value: string
}
const emit = defineEmits(['backToList', 'editOrAdd']) const emit = defineEmits(['backToList', 'editOrAdd'])
@ -51,7 +44,7 @@ const discordChannels = ref<Record<string, any>[]>([])
const mattermostChannels = ref<Record<string, any>[]>([]) const mattermostChannels = ref<Record<string, any>[]>([])
const filters = ref([]) const filterRef = ref()
const formInput = ref({ const formInput = ref({
'Email': [ 'Email': [
@ -205,21 +198,27 @@ const validators = computed(() => {
}) })
const { validate, validateInfos } = useForm(hook, validators) const { validate, validateInfos } = useForm(hook, validators)
function onNotTypeChange() { function onNotTypeChange(reset = false) {
hook.notification.payload = {} as any if (reset) {
hook.notification.payload = {} as Record<string, any>
}
if (hook.notification.type === 'Slack') { if (hook.notification.type === 'Slack') {
slackChannels.value = (apps && apps?.Slack && apps.Slack.parsedInput) || [] slackChannels.value = (apps.value && apps.value.Slack && apps.Slack.parsedInput) || []
} }
if (hook.notification.type === 'Microsoft Teams') { if (hook.notification.type === 'Microsoft Teams') {
teamsChannels.value = (apps && apps['Microsoft Teams'] && apps['Microsoft Teams'].parsedInput) || [] teamsChannels.value = (apps.value && apps.value['Microsoft Teams'] && apps.value['Microsoft Teams'].parsedInput) || []
} }
if (hook.notification.type === 'Discord') { if (hook.notification.type === 'Discord') {
discordChannels.value = (apps && apps.Discord && apps.Discord.parsedInput) || [] discordChannels.value = (apps.value && apps.value.Discord && apps.value.Discord.parsedInput) || []
} }
if (hook.notification.type === 'Mattermost') { if (hook.notification.type === 'Mattermost') {
mattermostChannels.value = (apps && apps.Mattermost && apps.Mattermost.parsedInput) || [] mattermostChannels.value = (apps.value && apps.value.Mattermost && apps.value.Mattermost.parsedInput) || []
} }
if (hook.notification.type === 'URL') { if (hook.notification.type === 'URL') {
hook.notification.payload.body = '{{ json data }}' hook.notification.payload.body = '{{ json data }}'
hook.notification.payload.parameters = [{}] hook.notification.payload.parameters = [{}]
@ -228,10 +227,6 @@ function onNotTypeChange() {
} }
} }
function filterOption(input: string, option: Option) {
return option.value.toUpperCase().includes(input.toUpperCase())
}
function setHook(newHook: any) { function setHook(newHook: any) {
Object.assign(hook, { Object.assign(hook, {
...newHook, ...newHook,
@ -301,6 +296,8 @@ async function loadPluginList() {
if (hook.event && hook.operation) { if (hook.event && hook.operation) {
hook.eventOperation = `${hook.event} ${hook.operation}` hook.eventOperation = `${hook.event} ${hook.operation}`
} }
onNotTypeChange()
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} }
@ -342,12 +339,9 @@ async function saveHooks() {
hook.id = res.id hook.id = res.id
} }
// TODO: wait for filter implementation if (filterRef.value) {
// if ($refs.filter) { await filterRef.value.applyChanges(hook.id)
// await $refs.filter.applyChanges(false, { }
// hookId: hook.id,
// });
// }
message.success('Webhook details updated successfully') message.success('Webhook details updated successfully')
} catch (e: any) { } catch (e: any) {
@ -383,8 +377,8 @@ watch(
}, },
) )
onMounted(() => { onMounted(async () => {
loadPluginList() await loadPluginList()
}) })
</script> </script>
@ -439,7 +433,7 @@ onMounted(() => {
v-model:value="hook.notification.type" v-model:value="hook.notification.type"
size="large" size="large"
:placeholder="$t('general.notification')" :placeholder="$t('general.notification')"
@change="onNotTypeChange" @change="onNotTypeChange(true)"
> >
<a-select-option v-for="(notificationOption, i) in notificationList" :key="i" :value="notificationOption.type"> <a-select-option v-for="(notificationOption, i) in notificationList" :key="i" :value="notificationOption.type">
<div class="flex items-center"> <div class="flex items-center">
@ -505,12 +499,12 @@ onMounted(() => {
<a-row v-if="hook.notification.type === 'Slack'" type="flex"> <a-row v-if="hook.notification.type === 'Slack'" type="flex">
<a-col :span="24"> <a-col :span="24">
<a-form-item v-bind="validateInfos['notification.channels']"> <a-form-item v-bind="validateInfos['notification.channels']">
<a-auto-complete <WebhookChannelMultiSelect
v-model:value="hook.notification.payload.channels" v-if="slackChannels.length > 0"
size="large" v-model="hook.notification.payload.channels"
:options="slackChannels" :selected-channel-list="hook.notification.payload.channels"
:available-channel-list="slackChannels"
placeholder="Select Slack channels" placeholder="Select Slack channels"
:filter-option="filterOption"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -519,12 +513,12 @@ onMounted(() => {
<a-row v-if="hook.notification.type === 'Microsoft Teams'" type="flex"> <a-row v-if="hook.notification.type === 'Microsoft Teams'" type="flex">
<a-col :span="24"> <a-col :span="24">
<a-form-item v-bind="validateInfos['notification.channels']"> <a-form-item v-bind="validateInfos['notification.channels']">
<a-auto-complete <WebhookChannelMultiSelect
v-model:value="hook.notification.payload.channels" v-if="teamsChannels.length > 0"
size="large" v-model="hook.notification.payload.channels"
:options="teamsChannels" :selected-channel-list="hook.notification.payload.channels"
:available-channel-list="teamsChannels"
placeholder="Select Microsoft Teams channels" placeholder="Select Microsoft Teams channels"
:filter-option="filterOption"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -533,12 +527,12 @@ onMounted(() => {
<a-row v-if="hook.notification.type === 'Discord'" type="flex"> <a-row v-if="hook.notification.type === 'Discord'" type="flex">
<a-col :span="24"> <a-col :span="24">
<a-form-item v-bind="validateInfos['notification.channels']"> <a-form-item v-bind="validateInfos['notification.channels']">
<a-auto-complete <WebhookChannelMultiSelect
v-model:value="hook.notification.payload.channels" v-if="discordChannels.length > 0"
size="large" v-model="hook.notification.payload.channels"
:options="discordChannels" :selected-channel-list="hook.notification.payload.channels"
:available-channel-list="discordChannels"
placeholder="Select Discord channels" placeholder="Select Discord channels"
:filter-option="filterOption"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -547,12 +541,12 @@ onMounted(() => {
<a-row v-if="hook.notification.type === 'Mattermost'" type="flex"> <a-row v-if="hook.notification.type === 'Mattermost'" type="flex">
<a-col :span="24"> <a-col :span="24">
<a-form-item v-bind="validateInfos['notification.channels']"> <a-form-item v-bind="validateInfos['notification.channels']">
<a-auto-complete <WebhookChannelMultiSelect
v-model:value="hook.notification.payload.channels" v-if="mattermostChannels.length > 0"
size="large" v-model="hook.notification.payload.channels"
:options="mattermostChannels" :selected-channel-list="hook.notification.payload.channels"
:available-channel-list="mattermostChannels"
placeholder="Select Mattermost channels" placeholder="Select Mattermost channels"
:filter-option="filterOption"
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -573,7 +567,7 @@ onMounted(() => {
<a-col :span="24"> <a-col :span="24">
<a-card> <a-card>
<a-checkbox v-model:checked="hook.condition">On Condition</a-checkbox> <a-checkbox v-model:checked="hook.condition">On Condition</a-checkbox>
<SmartsheetToolbarColumnFilter v-if="hook.condition" /> <SmartsheetToolbarColumnFilter v-if="hook.condition" ref="filterRef" :auto-save="false" :hook-id="hook.id" />
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
@ -601,7 +595,6 @@ onMounted(() => {
ref="webhookTestRef" ref="webhookTestRef"
:hook="{ :hook="{
...hook, ...hook,
filters,
notification: { notification: {
...hook.notification, ...hook.notification,
payload: hook.notification.payload, payload: hook.notification.payload,

10
packages/nc-gui-v2/components/webhook/List.vue

@ -4,13 +4,13 @@ import { MetaInj } from '~/context'
import { inject, onMounted, ref, useNuxtApp } from '#imports' import { inject, onMounted, ref, useNuxtApp } from '#imports'
import { extractSdkResponseErrorMsg } from '~/utils' import { extractSdkResponseErrorMsg } from '~/utils'
const emit = defineEmits(['edit']) const emit = defineEmits(['edit', 'add'])
const { $api, $e } = useNuxtApp() const { $api, $e } = useNuxtApp()
const hooks = ref<Record<string, any>[]>([]) const hooks = ref<Record<string, any>[]>([])
const meta = inject(MetaInj) const meta = inject(MetaInj)!
async function loadHooksList() { async function loadHooksList() {
try { try {
@ -58,7 +58,11 @@ onMounted(() => {
</div> </div>
<a-divider /> <a-divider />
<div v-if="hooks.length"> <div v-if="hooks.length">
<a-list item-layout="horizontal" :data-source="hooks" class="cursor-pointer pl-5 pr-5 pt-2 pb-2"> <a-list
item-layout="horizontal"
:data-source="hooks"
class="cursor-pointer max-h-[75vh] overflow-y-auto scrollbar-thin-primary"
>
<template #renderItem="{ item, index }"> <template #renderItem="{ item, index }">
<a-list-item class="pa-2" @click="emit('edit', item)"> <a-list-item class="pa-2" @click="emit('edit', item)">
<a-list-item-meta> <a-list-item-meta>

2
packages/nc-gui-v2/components/webhook/Test.vue

@ -28,7 +28,7 @@ watch(
async function loadSampleData() { async function loadSampleData() {
sampleData.value = { sampleData.value = {
data: await $api.dbTableWebhook.samplePayloadGet(meta?.value?.id as string, hook?.operation), data: await $api.dbTableWebhook.samplePayloadGet(meta?.value?.id as string, hook?.operation || 'insert'),
} }
} }

14
packages/nc-gui-v2/composables/useColumnCreateStore.ts

@ -1,23 +1,13 @@
import { createInjectionState } from '@vueuse/core'
import clone from 'just-clone' import clone from 'just-clone'
import { Form, message } from 'ant-design-vue' import { Form, message } from 'ant-design-vue'
import type { ColumnType, TableType } from 'nocodb-sdk' import type { ColumnType, TableType } from 'nocodb-sdk'
import { UITypes } from 'nocodb-sdk' import { UITypes } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { useColumn } from './useColumn' import { useColumn } from './useColumn'
import { computed } from '#imports' import { computed, createInjectionState, extractSdkResponseErrorMsg, useNuxtApp } from '#imports'
import { useNuxtApp } from '#app'
import { extractSdkResponseErrorMsg } from '~/utils/errorUtils'
const useForm = Form.useForm const useForm = Form.useForm
// enum ColumnAlterType {
// NEW=4,
// EDIT=2,
// RENAME=8,
// DELETE=0,
// }
const columnToValidate = [UITypes.Email, UITypes.URL, UITypes.PhoneNumber] const columnToValidate = [UITypes.Email, UITypes.URL, UITypes.PhoneNumber]
const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState( const [useProvideColumnCreateStore, useColumnCreateStore] = createInjectionState(
@ -242,6 +232,6 @@ export { useProvideColumnCreateStore }
export function useColumnCreateStoreOrThrow() { export function useColumnCreateStoreOrThrow() {
const columnCreateStore = useColumnCreateStore() const columnCreateStore = useColumnCreateStore()
if (columnCreateStore == null) throw new Error('Please call `useColumnCreateStore` on the appropriate parent component') if (columnCreateStore == null) throw new Error('Please call `useProvideColumnCreateStore` on the appropriate parent component')
return columnCreateStore return columnCreateStore
} }

26
packages/nc-gui-v2/composables/useExpandedFormStore.ts

@ -3,19 +3,24 @@ import type { ColumnType, TableType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { useApi, useInjectionState, useProject, useProvideSmartsheetRowStore } from '#imports' import {
import { NOCO } from '~/lib' NOCO,
import { useNuxtApp } from '#app' extractPkFromRow,
import type { Row } from '~/composables/useViewData' extractSdkResponseErrorMsg,
import { extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils' useApi,
useInjectionState,
useNuxtApp,
useProject,
useProvideSmartsheetRowStore,
} from '#imports'
import type { Row } from '~/composables'
const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((meta: Ref<TableType>, row: Ref<Row>) => { const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((meta: Ref<TableType>, row: Ref<Row>) => {
const { $e, $state, $api } = useNuxtApp() const { $e, $state, $api } = useNuxtApp()
const { api, isLoading: isCommentsLoading, error: commentsError } = useApi() const { api, isLoading: isCommentsLoading, error: commentsError } = useApi()
// { useGlobalInstance: true },
// state
const commentsOnly = ref(false) const commentsOnly = ref(false)
const commentsAndLogs = ref([]) const commentsAndLogs = ref<any[]>([])
const comment = ref('') const comment = ref('')
const commentsDrawer = ref(false) const commentsDrawer = ref(false)
const changedColumns = ref(new Set<string>()) const changedColumns = ref(new Set<string>())
@ -84,11 +89,14 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
await api.utils.commentRow({ await api.utils.commentRow({
fk_model_id: meta.value?.id as string, fk_model_id: meta.value?.id as string,
row_id: rowId, row_id: rowId,
// todo: description missing from argument type
description: comment.value, description: comment.value,
}) } as any)
comment.value = '' comment.value = ''
message.success('Comment added successfully') message.success('Comment added successfully')
await loadCommentsAndLogs() await loadCommentsAndLogs()
} catch (e: any) { } catch (e: any) {
message.error(e.message) message.error(e.message)

16
packages/nc-gui-v2/composables/useGlobal/state.ts

@ -73,7 +73,21 @@ export function useGlobalState(storageKey = 'nocodb-gui-v2'): State {
set: (val) => (storage.value.token = val), set: (val) => (storage.value.token = val),
}) })
const appInfo = ref<AppInfo>({ ncSiteUrl: 'localhost:8080' }) const appInfo = ref<AppInfo>({
ncSiteUrl: 'localhost:8080',
authType: 'jwt',
connectToExternalDB: false,
defaultLimit: 0,
firstUser: true,
githubAuthEnabled: false,
googleAuthEnabled: true,
ncMin: false,
oneClick: false,
projectHasAdmin: false,
teleEnabled: true,
type: 'nocodb',
version: '0.0.0',
})
/** reactive token payload */ /** reactive token payload */
const { payload } = useJwt<JwtPayload & User>(token) const { payload } = useJwt<JwtPayload & User>(token)

2
packages/nc-gui-v2/composables/useGlobal/types.ts

@ -13,7 +13,7 @@ export interface FeedbackForm {
export interface AppInfo { export interface AppInfo {
ncSiteUrl: string ncSiteUrl: string
authType: 'jwt' | 'masterKey' | 'none' authType: 'jwt' | 'none'
connectToExternalDB: boolean connectToExternalDB: boolean
defaultLimit: number defaultLimit: number
firstUser: boolean firstUser: boolean

33
packages/nc-gui-v2/composables/useLTARStore.ts

@ -1,10 +1,18 @@
import type { ColumnType, LinkToAnotherRecordType, PaginatedType, TableType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, PaginatedType, TableType } from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import { Modal, message } from 'ant-design-vue' import { Modal, message } from 'ant-design-vue'
import { useInjectionState, useMetas, useProject } from '#imports' import {
import { NOCO } from '~/lib' NOCO,
computed,
extractSdkResponseErrorMsg,
reactive,
ref,
useInjectionState,
useMetas,
useNuxtApp,
useProject,
} from '#imports'
import type { Row } from '~/composables' import type { Row } from '~/composables'
import { extractSdkResponseErrorMsg } from '~/utils'
interface DataApiResponse { interface DataApiResponse {
list: Record<string, any> list: Record<string, any>
@ -13,13 +21,13 @@ interface DataApiResponse {
/** Store for managing Link to another cells */ /** Store for managing Link to another cells */
const [useProvideLTARStore, useLTARStore] = useInjectionState( const [useProvideLTARStore, useLTARStore] = useInjectionState(
(column: Ref<Required<ColumnType>>, row?: Ref<Row>, isNewRow: ComputedRef<boolean> | Ref<boolean>, reloadData = () => {}) => { (column: Ref<Required<ColumnType>>, row: Ref<Row>, isNewRow: ComputedRef<boolean> | Ref<boolean>, reloadData = () => {}) => {
// state // state
const { metas, getMeta } = useMetas() const { metas, getMeta } = useMetas()
const { project } = useProject() const { project } = useProject()
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const childrenExcludedList: Ref<DataApiResponse | undefined> = ref() const childrenExcludedList = ref<DataApiResponse | undefined>()
const childrenList: Ref<DataApiResponse | undefined> = ref() const childrenList = ref<DataApiResponse | undefined>()
const childrenExcludedListPagination = reactive({ const childrenExcludedListPagination = reactive({
page: 1, page: 1,
query: '', query: '',
@ -95,12 +103,13 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
colOptions.type as 'mm' | 'hm', colOptions.type as 'mm' | 'hm',
column?.value?.title, column?.value?.title,
{ {
limit: childrenExcludedListPagination.size, limit: String(childrenExcludedListPagination.size),
offset: childrenExcludedListPagination.size * (childrenExcludedListPagination.page - 1), offset: String(childrenExcludedListPagination.size * (childrenExcludedListPagination.page - 1)),
// todo: where clause is missing from type
where: where:
childrenExcludedListPagination.query && childrenExcludedListPagination.query &&
`(${relatedTablePrimaryValueProp.value},like,${childrenExcludedListPagination.query})`, `(${relatedTablePrimaryValueProp.value},like,${childrenExcludedListPagination.query})`,
}, } as any,
) )
} }
} catch (e: any) { } catch (e: any) {
@ -120,10 +129,10 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
colOptions.type as 'mm' | 'hm', colOptions.type as 'mm' | 'hm',
column?.value?.title, column?.value?.title,
{ {
limit: childrenListPagination.size, limit: String(childrenListPagination.size),
offset: childrenListPagination.size * (childrenListPagination.page - 1), offset: String(childrenListPagination.size * (childrenListPagination.page - 1)),
where: childrenListPagination.query && `(${relatedTablePrimaryValueProp.value},like,${childrenListPagination.query})`, where: childrenListPagination.query && `(${relatedTablePrimaryValueProp.value},like,${childrenListPagination.query})`,
}, } as any,
) )
} catch (e: any) { } catch (e: any) {
message.error(`Failed to load children list: ${await extractSdkResponseErrorMsg(e)}`) message.error(`Failed to load children list: ${await extractSdkResponseErrorMsg(e)}`)

16
packages/nc-gui-v2/composables/useSmartsheetRowStore.ts

@ -2,9 +2,8 @@ import { message } from 'ant-design-vue'
import { UITypes } from 'nocodb-sdk' import { UITypes } from 'nocodb-sdk'
import type { ColumnType, LinkToAnotherRecordType, RelationTypes, TableType } from 'nocodb-sdk' import type { ColumnType, LinkToAnotherRecordType, RelationTypes, TableType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { useNuxtApp } from '#app' import type { Row } from './useViewData'
import { useInjectionState, useMetas, useProject, useVirtualCell } from '#imports' import { useInjectionState, useMetas, useNuxtApp, useProject, useVirtualCell } from '#imports'
import type { Row } from '~/composables/useViewData'
import { NOCO } from '~/lib' import { NOCO } from '~/lib'
import { extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils' import { extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils'
@ -47,7 +46,7 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
project.value.title as string, project.value.title as string,
meta.value.title as string, meta.value.title as string,
rowId, rowId,
type, type as 'mm' | 'hm',
column.title as string, column.title as string,
relatedRowId, relatedRowId,
) )
@ -69,14 +68,19 @@ const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState(
if (isHm || isMm) { if (isHm || isMm) {
const relatedRows = (state.value?.[column.title!] ?? []) as Record<string, any>[] const relatedRows = (state.value?.[column.title!] ?? []) as Record<string, any>[]
for (const relatedRow of relatedRows) { for (const relatedRow of relatedRows) {
await linkRecord(id, extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]), column, colOptions.type) await linkRecord(
id,
extractPkFromRow(relatedRow, relatedTableMeta.columns as ColumnType[]),
column,
colOptions.type as RelationTypes,
)
} }
} else if (isBt && state?.value?.[column.title!]) { } else if (isBt && state?.value?.[column.title!]) {
await linkRecord( await linkRecord(
id, id,
extractPkFromRow(state.value?.[column.title!] as Record<string, any>, relatedTableMeta.columns as ColumnType[]), extractPkFromRow(state.value?.[column.title!] as Record<string, any>, relatedTableMeta.columns as ColumnType[]),
column, column,
colOptions.type, colOptions.type as RelationTypes,
) )
} }
} }

7
packages/nc-gui-v2/composables/useUIPermission/index.ts

@ -1,13 +1,12 @@
import type { Permission } from './rolePermissions' import type { Permission } from './rolePermissions'
import rolePermissions from './rolePermissions' import rolePermissions from './rolePermissions'
import { useState } from '#app' import { USER_PROJECT_ROLES, useNuxtApp, useState } from '#imports'
import { USER_PROJECT_ROLES } from '~/lib/constants'
export function useUIPermission() { export function useUIPermission() {
const { $state } = useNuxtApp() const { $state } = useNuxtApp()
const projectRoles = useState<Record<string, boolean>>(USER_PROJECT_ROLES, () => ({})) const projectRoles = useState<Record<string, boolean>>(USER_PROJECT_ROLES, () => ({}))
const isUIAllowed = (permission: Permission, skipPreviewAs = false) => { const isUIAllowed = (permission: Permission | string, skipPreviewAs = false) => {
const user = $state.user const user = $state.user
let userRoles = user?.value?.roles || {} let userRoles = user?.value?.roles || {}
// if string populate key-value paired object // if string populate key-value paired object
@ -33,7 +32,7 @@ export function useUIPermission() {
return Object.entries<boolean>(roles).some(([role, hasRole]) => { return Object.entries<boolean>(roles).some(([role, hasRole]) => {
const rolePermission = rolePermissions[role as keyof typeof rolePermissions] as '*' | Record<Permission, true> const rolePermission = rolePermissions[role as keyof typeof rolePermissions] as '*' | Record<Permission, true>
return hasRole && (rolePermission === '*' || rolePermission?.[permission]) return hasRole && (rolePermission === '*' || rolePermission?.[permission as Permission])
}) })
} }

3
packages/nc-gui-v2/composables/useViewColumns.ts

@ -113,7 +113,8 @@ export function useViewColumns(
const showSystemFields = computed({ const showSystemFields = computed({
get() { get() {
return view?.value?.show_system_fields || false // todo: show_system_fields missing from ViewType
return (view?.value as any)?.show_system_fields || false
}, },
set(v: boolean) { set(v: boolean) {
if (view?.value?.id) { if (view?.value?.id) {

24
packages/nc-gui-v2/composables/useViewData.ts

@ -1,10 +1,7 @@
import type { Api, ColumnType, FormType, GalleryType, PaginatedType, TableType, ViewType } from 'nocodb-sdk' import type { Api, ColumnType, FormType, GalleryType, PaginatedType, TableType, ViewType } from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { useNuxtApp } from '#app' import { NOCO, computed, extractPkFromRow, extractSdkResponseErrorMsg, ref, useNuxtApp, useProject } from '#imports'
import { useProject } from '#imports'
import { NOCO } from '~/lib'
import { extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils'
const formatData = (list: Record<string, any>[]) => const formatData = (list: Record<string, any>[]) =>
list.map((row) => ({ list.map((row) => ({
@ -35,9 +32,10 @@ export function useViewData(
const formattedData = ref<Row[]>([]) const formattedData = ref<Row[]>([])
const paginationData = ref<PaginatedType>({ page: 1, pageSize: 25 }) const paginationData = ref<PaginatedType>({ page: 1, pageSize: 25 })
const aggCommentCount = ref<{ row_id: string; count: number }[]>([]) const aggCommentCount = ref<{ row_id: string; count: number }[]>([])
const galleryData = ref<GalleryType | undefined>(undefined) const galleryData = ref<GalleryType>()
const formColumnData = ref<FormType | undefined>(undefined) const formColumnData = ref<FormType>()
const formViewData = ref<FormType | undefined>(undefined) // todo: missing properties on FormType (success_msg, show_blank_form,
const formViewData = ref<FormType & { success_msg?: string; show_blank_form?: boolean }>()
const { project } = useProject() const { project } = useProject()
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
@ -102,7 +100,7 @@ export function useViewData(
formattedData.value = formatData(response.list) formattedData.value = formatData(response.list)
paginationData.value = response.pageInfo paginationData.value = response.pageInfo
loadAggCommentsCount() await loadAggCommentsCount()
} }
const loadGalleryData = async () => { const loadGalleryData = async () => {
@ -133,7 +131,8 @@ export function useViewData(
rowMeta: {}, rowMeta: {},
oldRow: { ...insertedData }, oldRow: { ...insertedData },
}) })
syncCount()
await syncCount()
} catch (error: any) { } catch (error: any) {
message.error(await extractSdkResponseErrorMsg(error)) message.error(await extractSdkResponseErrorMsg(error))
} }
@ -241,8 +240,10 @@ export function useViewData(
return return
} }
} }
formattedData.value.splice(rowIndex, 1) formattedData.value.splice(rowIndex, 1)
syncCount()
await syncCount()
} catch (e: any) { } catch (e: any) {
message.error(`Failed to delete row: ${await extractSdkResponseErrorMsg(e)}`) message.error(`Failed to delete row: ${await extractSdkResponseErrorMsg(e)}`)
} }
@ -272,7 +273,8 @@ export function useViewData(
return message.error(`Failed to delete row: ${await extractSdkResponseErrorMsg(e)}`) return message.error(`Failed to delete row: ${await extractSdkResponseErrorMsg(e)}`)
} }
} }
syncCount()
await syncCount()
} }
const loadFormView = async () => { const loadFormView = async () => {

24
packages/nc-gui-v2/composables/useViewFilters.ts

@ -16,15 +16,23 @@ export function useViewFilters(
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const { metas } = useMetas() const { metas } = useMetas()
const loadFilters = async () => { const loadFilters = async (hookId?: string) => {
if (hookId) {
if (parentId) {
filters.value = await $api.dbTableFilter.childrenRead(parentId)
} else {
filters.value = (await $api.dbTableWebhookFilter.read(hookId as string)) as any
}
} else {
if (parentId) { if (parentId) {
filters.value = await $api.dbTableFilter.childrenRead(parentId) filters.value = await $api.dbTableFilter.childrenRead(parentId)
} else { } else {
filters.value = await $api.dbTableFilter.read(view?.value?.id as string) filters.value = await $api.dbTableFilter.read(view?.value?.id as string)
} }
} }
}
const sync = async (_nested = false) => { const sync = async (hookId?: string, _nested = false) => {
for (const [i, filter] of Object.entries(filters.value)) { for (const [i, filter] of Object.entries(filters.value)) {
if (filter.status === 'delete') { if (filter.status === 'delete') {
await $api.dbTableFilter.delete(filter.id as string) await $api.dbTableFilter.delete(filter.id as string)
@ -34,12 +42,19 @@ export function useViewFilters(
fk_parent_id: parentId, fk_parent_id: parentId,
}) })
} else if (filter.status === 'create') { } else if (filter.status === 'create') {
if (hookId) {
filters.value[+i] = (await $api.dbTableWebhookFilter.create(hookId, {
...filter,
fk_parent_id: parentId,
})) as any
} else {
filters.value[+i] = (await $api.dbTableFilter.create(view?.value?.id as string, { filters.value[+i] = (await $api.dbTableFilter.create(view?.value?.id as string, {
...filter, ...filter,
fk_parent_id: parentId, fk_parent_id: parentId,
})) as any })) as any
} }
} }
}
reloadData?.() reloadData?.()
} }
@ -78,10 +93,11 @@ export function useViewFilters(
fk_parent_id: parentId, fk_parent_id: parentId,
}) })
} else { } else {
filters.value[i] = await $api.dbTableFilter.create(view?.value?.id as string, { // todo: return type of dbTableFilter is void?
filters.value[i] = (await $api.dbTableFilter.create(view?.value?.id as string, {
...filter, ...filter,
fk_parent_id: parentId, fk_parent_id: parentId,
}) })) as any
} }
reloadData?.() reloadData?.()
} }

5
packages/nc-gui-v2/composables/useViews.ts

@ -1,16 +1,17 @@
import type { TableType, ViewType } from 'nocodb-sdk' import type { TableType, ViewType } from 'nocodb-sdk'
import type { MaybeRef } from '@vueuse/core' import type { MaybeRef } from '@vueuse/core'
import { useNuxtApp } from '#app' import { unref, useNuxtApp, watch } from '#imports'
export function useViews(meta: MaybeRef<TableType | undefined>) { export function useViews(meta: MaybeRef<TableType | undefined>) {
let views = $ref<ViewType[]>([]) let views = $ref<ViewType[]>([])
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const loadViews = async () => { const loadViews = async () => {
const _meta = unref(meta) const _meta = unref(meta)
if (_meta && _meta.id) { if (_meta && _meta.id) {
const response = (await $api.dbView.list(_meta.id)).list const response = (await $api.dbView.list(_meta.id)).list as ViewType[]
if (response) { if (response) {
views = response.sort((a, b) => a.order! - b.order!) views = response.sort((a, b) => a.order! - b.order!)
} }

3
packages/nc-gui-v2/httpsnippet-shims.d.ts vendored

@ -0,0 +1,3 @@
declare module 'httpsnippet' {
export default new ((): any => {})()
}

1
packages/nc-gui-v2/just-clone-shims.d.ts vendored

@ -0,0 +1 @@
declare module 'just-clone'

17
packages/nc-gui-v2/nuxt.config.ts

@ -48,6 +48,10 @@ export default defineNuxtConfig({
}, },
vite: { vite: {
// todo: minifiy again
build: {
minify: false,
},
css: { css: {
preprocessorOptions: { preprocessorOptions: {
less: { less: {
@ -59,6 +63,7 @@ export default defineNuxtConfig({
plugins: [ plugins: [
vueI18n({ vueI18n({
include: path.resolve(__dirname, './lang'), include: path.resolve(__dirname, './lang'),
runtimeOnly: false,
}), }),
Icons({ Icons({
autoInstall: true, autoInstall: true,
@ -81,7 +86,6 @@ export default defineNuxtConfig({
], ],
define: { define: {
'process.env.DEBUG': 'false', 'process.env.DEBUG': 'false',
'global': {},
}, },
server: { server: {
watch: { watch: {
@ -91,17 +95,6 @@ export default defineNuxtConfig({
}, },
experimental: { experimental: {
reactivityTransform: true, reactivityTransform: true,
viteNode: false,
},
typescript: {
typeCheck: true,
strict: true,
tsConfig: {
compilerOptions: {
types: ['@intlify/vite-plugin-vue-i18n/client', 'vue-i18n', 'unplugin-icons/types/vue', 'nuxt-windicss'],
},
},
}, },
image: { image: {

353
packages/nc-gui-v2/package-lock.json generated

@ -12,6 +12,7 @@
"dayjs": "^1.11.3", "dayjs": "^1.11.3",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"jsep": "^1.3.6", "jsep": "^1.3.6",
"just-clone": "^6.1.1",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"locale-codes": "^1.3.1", "locale-codes": "^1.3.1",
"monaco-editor": "^0.33.0", "monaco-editor": "^0.33.0",
@ -20,8 +21,6 @@
"socket.io-client": "^4.5.1", "socket.io-client": "^4.5.1",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.0",
"unique-names-generator": "^4.7.1", "unique-names-generator": "^4.7.1",
"url": "^0.11.0",
"util": "^0.12.4",
"vue-dompurify-html": "^3.0.0", "vue-dompurify-html": "^3.0.0",
"vue-github-button": "^3.0.3", "vue-github-button": "^3.0.3",
"vue-i18n": "^9.1.10", "vue-i18n": "^9.1.10",
@ -39,13 +38,12 @@
"@iconify-json/material-symbols": "^1.1.8", "@iconify-json/material-symbols": "^1.1.8",
"@iconify-json/mdi": "^1.1.25", "@iconify-json/mdi": "^1.1.25",
"@iconify-json/ri": "^1.1.3", "@iconify-json/ri": "^1.1.3",
"@intlify/vite-plugin-vue-i18n": "^4.0.0", "@intlify/vite-plugin-vue-i18n": "^6.0.1",
"@nuxt/image-edge": "^1.0.0-27657146.da85542", "@nuxt/image-edge": "^1.0.0-27657146.da85542",
"@types/axios": "^0.14.0", "@types/axios": "^0.14.0",
"@types/file-saver": "^2.0.5", "@types/file-saver": "^2.0.5",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.2",
"@types/sortablejs": "^1.13.0", "@types/sortablejs": "^1.13.0",
"@vitejs/plugin-vue": "^2.3.3",
"@vitest/ui": "^0.18.0", "@vitest/ui": "^0.18.0",
"@vue/compiler-sfc": "^3.2.37", "@vue/compiler-sfc": "^3.2.37",
"@vue/test-utils": "^2.0.2", "@vue/test-utils": "^2.0.2",
@ -1284,30 +1282,33 @@
} }
}, },
"node_modules/@intlify/vite-plugin-vue-i18n": { "node_modules/@intlify/vite-plugin-vue-i18n": {
"version": "4.0.0", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/@intlify/vite-plugin-vue-i18n/-/vite-plugin-vue-i18n-4.0.0.tgz", "resolved": "https://registry.npmjs.org/@intlify/vite-plugin-vue-i18n/-/vite-plugin-vue-i18n-6.0.1.tgz",
"integrity": "sha512-bX7WgJAnYAbhmfvMp17TjCzg4e4T68O7iqAcNo6TOS+oHK0kAJAN9AJfEMTdpDrAwURCw0VwZ0kgMFWDbJkY4g==", "integrity": "sha512-FFVcxVU4bR9vdDLNbltM5mrhndnXMErO01i0RrpdyMegEt3Nu/YLoH0sFdjRun7/RY4vaEnhTnFvVf9uO0dQvg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@intlify/bundle-utils": "next", "@intlify/bundle-utils": "next",
"@intlify/shared": "next", "@intlify/shared": "next",
"@rollup/pluginutils": "^4.1.0", "@rollup/pluginutils": "^4.2.0",
"debug": "^4.3.1", "debug": "^4.3.1",
"fast-glob": "^3.2.5", "fast-glob": "^3.2.5",
"source-map": "0.6.1" "source-map": "0.6.1"
}, },
"engines": { "engines": {
"node": ">= 12" "node": ">= 14.6"
}, },
"peerDependencies": { "peerDependencies": {
"petite-vue-i18n": "next", "petite-vue-i18n": "*",
"vite": "^2.9.0", "vite": "^2.9.0 || ^3.0.0",
"vue-i18n": "next" "vue-i18n": "*"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"petite-vue-i18n": { "petite-vue-i18n": {
"optional": true "optional": true
}, },
"vite": {
"optional": true
},
"vue-i18n": { "vue-i18n": {
"optional": true "optional": true
} }
@ -3797,17 +3798,6 @@
"postcss": "^8.1.0" "postcss": "^8.1.0"
} }
}, },
"node_modules/available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/axios": { "node_modules/axios": {
"version": "0.27.2", "version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
@ -4044,6 +4034,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2" "get-intrinsic": "^1.0.2"
@ -5214,6 +5205,7 @@
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
"integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"dependencies": { "dependencies": {
"has-property-descriptors": "^1.0.0", "has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1" "object-keys": "^1.1.1"
@ -5583,6 +5575,7 @@
"version": "1.20.1", "version": "1.20.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
"integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1", "es-to-primitive": "^1.2.1",
@ -5636,6 +5629,7 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true,
"dependencies": { "dependencies": {
"is-callable": "^1.1.4", "is-callable": "^1.1.4",
"is-date-object": "^1.0.1", "is-date-object": "^1.0.1",
@ -7272,14 +7266,6 @@
} }
} }
}, },
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"dependencies": {
"is-callable": "^1.1.3"
}
},
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
@ -7422,12 +7408,14 @@
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"devOptional": true
}, },
"node_modules/function.prototype.name": { "node_modules/function.prototype.name": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
"integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.3", "define-properties": "^1.1.3",
@ -7451,6 +7439,7 @@
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@ -7506,6 +7495,7 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
"dev": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
"has": "^1.0.3", "has": "^1.0.3",
@ -7558,6 +7548,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1" "get-intrinsic": "^1.1.1"
@ -7816,6 +7807,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"devOptional": true,
"dependencies": { "dependencies": {
"function-bind": "^1.1.1" "function-bind": "^1.1.1"
}, },
@ -7848,6 +7840,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
"dev": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@ -7865,6 +7858,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
"integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
"dev": true,
"dependencies": { "dependencies": {
"get-intrinsic": "^1.1.1" "get-intrinsic": "^1.1.1"
}, },
@ -7876,6 +7870,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@ -7887,6 +7882,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"dependencies": { "dependencies": {
"has-symbols": "^1.0.2" "has-symbols": "^1.0.2"
}, },
@ -8401,7 +8397,8 @@
"node_modules/inherits": { "node_modules/inherits": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
}, },
"node_modules/ini": { "node_modules/ini": {
"version": "1.3.8", "version": "1.3.8",
@ -8455,6 +8452,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
"dev": true,
"dependencies": { "dependencies": {
"get-intrinsic": "^1.1.0", "get-intrinsic": "^1.1.0",
"has": "^1.0.3", "has": "^1.0.3",
@ -8535,21 +8533,6 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"dependencies": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-arrayish": { "node_modules/is-arrayish": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@ -8560,6 +8543,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dev": true,
"dependencies": { "dependencies": {
"has-bigints": "^1.0.1" "has-bigints": "^1.0.1"
}, },
@ -8583,6 +8567,7 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
@ -8610,6 +8595,7 @@
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@ -8633,6 +8619,7 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
"dev": true,
"dependencies": { "dependencies": {
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
}, },
@ -8686,20 +8673,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"dependencies": {
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-glob": { "node_modules/is-glob": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@ -8741,6 +8714,7 @@
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
"integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@ -8761,6 +8735,7 @@
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
"integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
"dev": true,
"dependencies": { "dependencies": {
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
}, },
@ -8824,6 +8799,7 @@
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
@ -8848,6 +8824,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
"integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2" "call-bind": "^1.0.2"
}, },
@ -8880,6 +8857,7 @@
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
"dev": true,
"dependencies": { "dependencies": {
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
}, },
@ -8894,6 +8872,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"dev": true,
"dependencies": { "dependencies": {
"has-symbols": "^1.0.2" "has-symbols": "^1.0.2"
}, },
@ -8904,24 +8883,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/is-typed-array": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz",
"integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==",
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-unicode-supported": { "node_modules/is-unicode-supported": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@ -8938,6 +8899,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2" "call-bind": "^1.0.2"
}, },
@ -9227,6 +9189,11 @@
"node": ">=4.0" "node": ">=4.0"
} }
}, },
"node_modules/just-clone": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/just-clone/-/just-clone-6.1.1.tgz",
"integrity": "sha512-V24KLIid8uaG7ayOymGfheNHtxgrbpzj1UznQnF9vQZMHlKGTSLT3WWmFx62OXSQPwk1Tn+uo+H5/Xhb4bL9pA=="
},
"node_modules/jwt-decode": { "node_modules/jwt-decode": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
@ -10563,6 +10530,7 @@
"version": "1.12.2", "version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
"dev": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@ -10571,6 +10539,7 @@
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
} }
@ -10579,6 +10548,7 @@
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz",
"integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.4", "define-properties": "^1.1.4",
@ -11944,15 +11914,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
"deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
"engines": {
"node": ">=0.4.x"
}
},
"node_modules/queue-microtask": { "node_modules/queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -12243,6 +12204,7 @@
"version": "1.4.3", "version": "1.4.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
"integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.3", "define-properties": "^1.1.3",
@ -12470,7 +12432,8 @@
"node_modules/safe-buffer": { "node_modules/safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
}, },
"node_modules/safe-regex": { "node_modules/safe-regex": {
"version": "2.1.1", "version": "2.1.1",
@ -12779,6 +12742,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.0", "call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2", "get-intrinsic": "^1.0.2",
@ -13149,6 +13113,7 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
"integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.4", "define-properties": "^1.1.4",
@ -13162,6 +13127,7 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
"integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.4", "define-properties": "^1.1.4",
@ -13852,6 +13818,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
"integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"has-bigints": "^1.0.2", "has-bigints": "^1.0.2",
@ -14188,33 +14155,6 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/url": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
"integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
"dependencies": {
"punycode": "1.3.2",
"querystring": "0.2.0"
}
},
"node_modules/url/node_modules/punycode": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
"integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
},
"node_modules/util": {
"version": "0.12.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz",
"integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==",
"dependencies": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"safe-buffer": "^5.1.2",
"which-typed-array": "^1.1.2"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -14903,6 +14843,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"dev": true,
"dependencies": { "dependencies": {
"is-bigint": "^1.0.1", "is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0", "is-boolean-object": "^1.1.0",
@ -14914,25 +14855,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/which-typed-array": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz",
"integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==",
"dependencies": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0",
"is-typed-array": "^1.1.9"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/wide-align": { "node_modules/wide-align": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
@ -16189,14 +16111,14 @@
"integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA==" "integrity": "sha512-Om54xJeo1Vw+K1+wHYyXngE8cAbrxZHpWjYzMR9wCkqbhGtRV5VLhVc214Ze2YatPrWlS2WSMOWXR8JktX/IgA=="
}, },
"@intlify/vite-plugin-vue-i18n": { "@intlify/vite-plugin-vue-i18n": {
"version": "4.0.0", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/@intlify/vite-plugin-vue-i18n/-/vite-plugin-vue-i18n-4.0.0.tgz", "resolved": "https://registry.npmjs.org/@intlify/vite-plugin-vue-i18n/-/vite-plugin-vue-i18n-6.0.1.tgz",
"integrity": "sha512-bX7WgJAnYAbhmfvMp17TjCzg4e4T68O7iqAcNo6TOS+oHK0kAJAN9AJfEMTdpDrAwURCw0VwZ0kgMFWDbJkY4g==", "integrity": "sha512-FFVcxVU4bR9vdDLNbltM5mrhndnXMErO01i0RrpdyMegEt3Nu/YLoH0sFdjRun7/RY4vaEnhTnFvVf9uO0dQvg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@intlify/bundle-utils": "next", "@intlify/bundle-utils": "next",
"@intlify/shared": "next", "@intlify/shared": "next",
"@rollup/pluginutils": "^4.1.0", "@rollup/pluginutils": "^4.2.0",
"debug": "^4.3.1", "debug": "^4.3.1",
"fast-glob": "^3.2.5", "fast-glob": "^3.2.5",
"source-map": "0.6.1" "source-map": "0.6.1"
@ -18117,11 +18039,6 @@
"postcss-value-parser": "^4.2.0" "postcss-value-parser": "^4.2.0"
} }
}, },
"available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
},
"axios": { "axios": {
"version": "0.27.2", "version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
@ -18293,6 +18210,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"dev": true,
"requires": { "requires": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2" "get-intrinsic": "^1.0.2"
@ -19193,6 +19111,7 @@
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
"integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dev": true,
"requires": { "requires": {
"has-property-descriptors": "^1.0.0", "has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1" "object-keys": "^1.1.1"
@ -19469,6 +19388,7 @@
"version": "1.20.1", "version": "1.20.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
"integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"es-to-primitive": "^1.2.1", "es-to-primitive": "^1.2.1",
@ -19516,6 +19436,7 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true,
"requires": { "requires": {
"is-callable": "^1.1.4", "is-callable": "^1.1.4",
"is-date-object": "^1.0.1", "is-date-object": "^1.0.1",
@ -20631,14 +20552,6 @@
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"devOptional": true "devOptional": true
}, },
"for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"requires": {
"is-callable": "^1.1.3"
}
},
"form-data": { "form-data": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
@ -20749,12 +20662,14 @@
"function-bind": { "function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"devOptional": true
}, },
"function.prototype.name": { "function.prototype.name": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
"integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.3", "define-properties": "^1.1.3",
@ -20771,7 +20686,8 @@
"functions-have-names": { "functions-have-names": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true
}, },
"gauge": { "gauge": {
"version": "3.0.2", "version": "3.0.2",
@ -20812,6 +20728,7 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
"integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
"dev": true,
"requires": { "requires": {
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
"has": "^1.0.3", "has": "^1.0.3",
@ -20849,6 +20766,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
"integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"get-intrinsic": "^1.1.1" "get-intrinsic": "^1.1.1"
@ -21050,6 +20968,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"devOptional": true,
"requires": { "requires": {
"function-bind": "^1.1.1" "function-bind": "^1.1.1"
} }
@ -21074,7 +20993,8 @@
"has-bigints": { "has-bigints": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
"dev": true
}, },
"has-flag": { "has-flag": {
"version": "4.0.0", "version": "4.0.0",
@ -21086,6 +21006,7 @@
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
"integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
"dev": true,
"requires": { "requires": {
"get-intrinsic": "^1.1.1" "get-intrinsic": "^1.1.1"
} }
@ -21093,12 +21014,14 @@
"has-symbols": { "has-symbols": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true
}, },
"has-tostringtag": { "has-tostringtag": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dev": true,
"requires": { "requires": {
"has-symbols": "^1.0.2" "has-symbols": "^1.0.2"
} }
@ -21482,7 +21405,8 @@
"inherits": { "inherits": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
}, },
"ini": { "ini": {
"version": "1.3.8", "version": "1.3.8",
@ -21529,6 +21453,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
"dev": true,
"requires": { "requires": {
"get-intrinsic": "^1.1.0", "get-intrinsic": "^1.1.0",
"has": "^1.0.3", "has": "^1.0.3",
@ -21588,15 +21513,6 @@
"is-decimal": "^1.0.0" "is-decimal": "^1.0.0"
} }
}, },
"is-arguments": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"requires": {
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-arrayish": { "is-arrayish": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@ -21607,6 +21523,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
"dev": true,
"requires": { "requires": {
"has-bigints": "^1.0.1" "has-bigints": "^1.0.1"
} }
@ -21624,6 +21541,7 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
@ -21641,7 +21559,8 @@
"is-callable": { "is-callable": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
"dev": true
}, },
"is-core-module": { "is-core-module": {
"version": "2.9.0", "version": "2.9.0",
@ -21656,6 +21575,7 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
"dev": true,
"requires": { "requires": {
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
} }
@ -21684,14 +21604,6 @@
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true "dev": true
}, },
"is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"requires": {
"has-tostringtag": "^1.0.0"
}
},
"is-glob": { "is-glob": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@ -21722,7 +21634,8 @@
"is-negative-zero": { "is-negative-zero": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
"integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
"dev": true
}, },
"is-number": { "is-number": {
"version": "7.0.0", "version": "7.0.0",
@ -21734,6 +21647,7 @@
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
"integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
"dev": true,
"requires": { "requires": {
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
} }
@ -21782,6 +21696,7 @@
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
@ -21797,6 +21712,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
"integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2" "call-bind": "^1.0.2"
} }
@ -21820,6 +21736,7 @@
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
"dev": true,
"requires": { "requires": {
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.0"
} }
@ -21828,22 +21745,11 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
"dev": true,
"requires": { "requires": {
"has-symbols": "^1.0.2" "has-symbols": "^1.0.2"
} }
}, },
"is-typed-array": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz",
"integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==",
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0"
}
},
"is-unicode-supported": { "is-unicode-supported": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@ -21854,6 +21760,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2" "call-bind": "^1.0.2"
} }
@ -22074,6 +21981,11 @@
"object.assign": "^4.1.2" "object.assign": "^4.1.2"
} }
}, },
"just-clone": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/just-clone/-/just-clone-6.1.1.tgz",
"integrity": "sha512-V24KLIid8uaG7ayOymGfheNHtxgrbpzj1UznQnF9vQZMHlKGTSLT3WWmFx62OXSQPwk1Tn+uo+H5/Xhb4bL9pA=="
},
"jwt-decode": { "jwt-decode": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
@ -23164,17 +23076,20 @@
"object-inspect": { "object-inspect": {
"version": "1.12.2", "version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
"integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
"dev": true
}, },
"object-keys": { "object-keys": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true
}, },
"object.assign": { "object.assign": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.3.tgz",
"integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==", "integrity": "sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.4", "define-properties": "^1.1.4",
@ -24140,11 +24055,6 @@
"strict-uri-encode": "^2.0.0" "strict-uri-encode": "^2.0.0"
} }
}, },
"querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g=="
},
"queue-microtask": { "queue-microtask": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -24367,6 +24277,7 @@
"version": "1.4.3", "version": "1.4.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
"integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.3", "define-properties": "^1.1.3",
@ -24521,7 +24432,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
}, },
"safe-regex": { "safe-regex": {
"version": "2.1.1", "version": "2.1.1",
@ -24780,6 +24692,7 @@
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.0", "call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2", "get-intrinsic": "^1.0.2",
@ -25059,6 +24972,7 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
"integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.4", "define-properties": "^1.1.4",
@ -25069,6 +24983,7 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
"integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"define-properties": "^1.1.4", "define-properties": "^1.1.4",
@ -25595,6 +25510,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
"integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
"dev": true,
"requires": { "requires": {
"call-bind": "^1.0.2", "call-bind": "^1.0.2",
"has-bigints": "^1.0.2", "has-bigints": "^1.0.2",
@ -25811,35 +25727,6 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"url": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
"integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
"requires": {
"punycode": "1.3.2",
"querystring": "0.2.0"
},
"dependencies": {
"punycode": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
"integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
}
}
},
"util": {
"version": "0.12.4",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz",
"integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==",
"requires": {
"inherits": "^2.0.3",
"is-arguments": "^1.0.4",
"is-generator-function": "^1.0.7",
"is-typed-array": "^1.1.3",
"safe-buffer": "^5.1.2",
"which-typed-array": "^1.1.2"
}
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -26322,6 +26209,7 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
"dev": true,
"requires": { "requires": {
"is-bigint": "^1.0.1", "is-bigint": "^1.0.1",
"is-boolean-object": "^1.1.0", "is-boolean-object": "^1.1.0",
@ -26330,19 +26218,6 @@
"is-symbol": "^1.0.3" "is-symbol": "^1.0.3"
} }
}, },
"which-typed-array": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz",
"integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==",
"requires": {
"available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
"es-abstract": "^1.20.0",
"for-each": "^0.3.3",
"has-tostringtag": "^1.0.0",
"is-typed-array": "^1.1.9"
}
},
"wide-align": { "wide-align": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",

5
packages/nc-gui-v2/package.json

@ -27,8 +27,6 @@
"socket.io-client": "^4.5.1", "socket.io-client": "^4.5.1",
"sortablejs": "^1.15.0", "sortablejs": "^1.15.0",
"unique-names-generator": "^4.7.1", "unique-names-generator": "^4.7.1",
"url": "^0.11.0",
"util": "^0.12.4",
"vue-dompurify-html": "^3.0.0", "vue-dompurify-html": "^3.0.0",
"vue-github-button": "^3.0.3", "vue-github-button": "^3.0.3",
"vue-i18n": "^9.1.10", "vue-i18n": "^9.1.10",
@ -46,13 +44,12 @@
"@iconify-json/material-symbols": "^1.1.8", "@iconify-json/material-symbols": "^1.1.8",
"@iconify-json/mdi": "^1.1.25", "@iconify-json/mdi": "^1.1.25",
"@iconify-json/ri": "^1.1.3", "@iconify-json/ri": "^1.1.3",
"@intlify/vite-plugin-vue-i18n": "^4.0.0", "@intlify/vite-plugin-vue-i18n": "^6.0.1",
"@nuxt/image-edge": "^1.0.0-27657146.da85542", "@nuxt/image-edge": "^1.0.0-27657146.da85542",
"@types/axios": "^0.14.0", "@types/axios": "^0.14.0",
"@types/file-saver": "^2.0.5", "@types/file-saver": "^2.0.5",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.2",
"@types/sortablejs": "^1.13.0", "@types/sortablejs": "^1.13.0",
"@vitejs/plugin-vue": "^2.3.3",
"@vitest/ui": "^0.18.0", "@vitest/ui": "^0.18.0",
"@vue/compiler-sfc": "^3.2.37", "@vue/compiler-sfc": "^3.2.37",
"@vue/test-utils": "^2.0.2", "@vue/test-utils": "^2.0.2",

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

@ -1,15 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import type { TabItem } from '~/composables' import type { TabItem } from '~/composables'
import { TabType } from '~/composables' import { TabType } from '~/composables'
import { TabMetaInj } from '~/context' import { TabMetaInj, useTabs, useUIPermission } from '#imports'
import { useTabs, useUIPermission } from '#imports'
import MdiPlusBoxOutline from '~icons/mdi/plus-box-outline'
import MdiTableIcon from '~icons/mdi/table'
import MdiCsvIcon from '~icons/mdi/file-document-outline'
import MdiExcelIcon from '~icons/mdi/file-excel'
import MdiJSONIcon from '~icons/mdi/code-json'
import MdiAirTableIcon from '~icons/mdi/table-large' import MdiAirTableIcon from '~icons/mdi/table-large'
import MdiRequestDataSourceIcon from '~icons/mdi/open-in-new'
import MdiView from '~icons/mdi/eye-circle-outline' import MdiView from '~icons/mdi/eye-circle-outline'
import MdiAccountGroup from '~icons/mdi/account-group' import MdiAccountGroup from '~icons/mdi/account-group'
@ -46,7 +39,7 @@ const icon = (tab: TabItem) => {
<div class="h-full w-full nc-container pt-[9px]"> <div class="h-full w-full nc-container pt-[9px]">
<div class="h-full w-full flex flex-col"> <div class="h-full w-full flex flex-col">
<div> <div>
<a-tabs v-model:activeKey="activeTabIndex" class="nc-root-tabs" type="editable-card" @edit="closeTab"> <a-tabs v-model:activeKey="activeTabIndex" class="nc-root-tabs" type="editable-card" @edit="closeTab(activeTabIndex)">
<a-tab-pane v-for="(tab, i) in tabs" :key="i"> <a-tab-pane v-for="(tab, i) in tabs" :key="i">
<template #tab> <template #tab>
<div class="flex align-center gap-2"> <div class="flex align-center gap-2">
@ -65,15 +58,17 @@ const icon = (tab: TabItem) => {
Add / Import Add / Import
</div> </div>
</template> </template>
<a-menu-item-group v-if="isUIAllowed('addTable')"> <a-menu-item-group v-if="isUIAllowed('addTable')">
<a-menu-item key="add-new-table" v-t="['a:actions:create-table']" @click="tableCreateDialog = true"> <a-menu-item key="add-new-table" v-t="['a:actions:create-table']" @click="tableCreateDialog = true">
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
<MdiTableIcon class="text-primary" /> <MdiTable class="text-primary" />
<!-- Add new table --> <!-- Add new table -->
{{ $t('tooltip.addTable') }} {{ $t('tooltip.addTable') }}
</span> </span>
</a-menu-item> </a-menu-item>
</a-menu-item-group> </a-menu-item-group>
<a-menu-item-group title="QUICK IMPORT FROM"> <a-menu-item-group title="QUICK IMPORT FROM">
<a-menu-item <a-menu-item
v-if="isUIAllowed('airtableImport')" v-if="isUIAllowed('airtableImport')"
@ -82,7 +77,7 @@ const icon = (tab: TabItem) => {
@click="airtableImportDialog = true" @click="airtableImportDialog = true"
> >
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
<MdiAirTableIcon class="text-primary" /> <MdiTableLarge class="text-primary" />
<!-- TODO: i18n --> <!-- TODO: i18n -->
Airtable Airtable
</span> </span>
@ -94,11 +89,12 @@ const icon = (tab: TabItem) => {
@click="openQuickImportDialog('csv')" @click="openQuickImportDialog('csv')"
> >
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
<MdiCsvIcon class="text-primary" /> <MdiFileDocumentOutline class="text-primary" />
<!-- TODO: i18n --> <!-- TODO: i18n -->
CSV file CSV file
</span> </span>
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
v-if="isUIAllowed('jsonImport')" v-if="isUIAllowed('jsonImport')"
key="quick-import-json" key="quick-import-json"
@ -106,11 +102,12 @@ const icon = (tab: TabItem) => {
@click="openQuickImportDialog('json')" @click="openQuickImportDialog('json')"
> >
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
<MdiJSONIcon class="text-primary" /> <MdiCodeJson class="text-primary" />
<!-- TODO: i18n --> <!-- TODO: i18n -->
JSON file JSON file
</span> </span>
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
v-if="isUIAllowed('excelImport')" v-if="isUIAllowed('excelImport')"
key="quick-import-excel" key="quick-import-excel"
@ -118,13 +115,15 @@ const icon = (tab: TabItem) => {
@click="openQuickImportDialog('excel')" @click="openQuickImportDialog('excel')"
> >
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
<MdiExcelIcon class="text-primary" /> <MdiFileExcel class="text-primary" />
<!-- TODO: i18n --> <!-- TODO: i18n -->
Microsoft Excel Microsoft Excel
</span> </span>
</a-menu-item> </a-menu-item>
</a-menu-item-group> </a-menu-item-group>
<a-divider class="ma-0 mb-2" />
<a-menu-divider class="ma-0 mb-2" />
<a-menu-item <a-menu-item
v-if="isUIAllowed('importRequest')" v-if="isUIAllowed('importRequest')"
key="add-new-table" key="add-new-table"
@ -133,7 +132,7 @@ const icon = (tab: TabItem) => {
> >
<a href="https://github.com/nocodb/nocodb/issues/2052" target="_blank" class="prose-sm pa-0"> <a href="https://github.com/nocodb/nocodb/issues/2052" target="_blank" class="prose-sm pa-0">
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
<MdiRequestDataSourceIcon class="text-primary" /> <MdiOpenInNew class="text-primary" />
<!-- TODO: i18n --> <!-- TODO: i18n -->
Request a data source you need? Request a data source you need?
</span> </span>
@ -150,7 +149,9 @@ const icon = (tab: TabItem) => {
</div> </div>
<DlgTableCreate v-if="tableCreateDialog" v-model="tableCreateDialog" /> <DlgTableCreate v-if="tableCreateDialog" v-model="tableCreateDialog" />
<DlgQuickImport v-if="quickImportDialog" v-model="quickImportDialog" :import-type="importType" /> <DlgQuickImport v-if="quickImportDialog" v-model="quickImportDialog" :import-type="importType" />
<DlgAirtableImport v-if="airtableImportDialog" v-model="airtableImportDialog" /> <DlgAirtableImport v-if="airtableImportDialog" v-model="airtableImportDialog" />
</div> </div>
</template> </template>

6
packages/nc-gui-v2/pages/forgot-password.vue

@ -63,10 +63,10 @@ function resetError() {
ref="formValidator" ref="formValidator"
layout="vertical" layout="vertical"
:model="form" :model="form"
class="bg-primary/5 forgot-password h-full min-h-[600px] flex justify-center items-center" class="bg-primary/5 forgot-password h-full flex justify-center items-center nc-form-signin"
@finish="resetPassword" @finish="resetPassword"
> >
<div class="h-full w-full flex flex-col flex-wrap justify-center items-center"> <div class="h-full w-full flex flex-col items-center justify-center pt-[50px]">
<div <div
class="color-transition bg-white dark:(!bg-gray-900 !text-white) relative flex flex-col justify-center gap-2 w-full max-w-[500px] mx-auto p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)" class="color-transition bg-white dark:(!bg-gray-900 !text-white) relative flex flex-col justify-center gap-2 w-full max-w-[500px] mx-auto p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
> >
@ -96,7 +96,7 @@ function resetError() {
<div v-if="error" class="self-center mb-4 bg-red-500 text-white rounded-lg w-3/4 mx-auto p-1"> <div v-if="error" class="self-center mb-4 bg-red-500 text-white rounded-lg w-3/4 mx-auto p-1">
<div class="flex items-center gap-2 justify-center"> <div class="flex items-center gap-2 justify-center">
<MaterialSymbolsWarning /> <MaterialSymbolsWarning />
<div style="flex: 0 0 auto" class="break-words">{{ error }}</div> <div class="break-words">{{ error }}</div>
</div> </div>
</div> </div>
</Transition> </Transition>

11
packages/nc-gui-v2/pages/index/index.vue

@ -1,15 +1,8 @@
<script lang="ts" setup> <script lang="ts" setup>
import { Modal, message } from 'ant-design-vue' import { Modal, message } from 'ant-design-vue'
import type { ProjectType } from 'nocodb-sdk' import type { ProjectType } from 'nocodb-sdk'
import { navigateTo } from '#app' import { computed, navigateTo, onMounted, ref, useApi, useNuxtApp, useSidebar } from '#imports'
import { computed, onMounted, ref, useApi, useNuxtApp, useSidebar } from '#imports'
import { extractSdkResponseErrorMsg } from '~/utils' import { extractSdkResponseErrorMsg } from '~/utils'
import MdiDeleteOutline from '~icons/mdi/delete-outline'
import MdiEditOutline from '~icons/mdi/edit-outline'
import MdiRefresh from '~icons/mdi/refresh'
import MdiMenuDown from '~icons/mdi/menu-down'
import MdiPlus from '~icons/mdi/plus'
import MdiDatabaseOutline from '~icons/mdi/database-outline'
const { $e } = useNuxtApp() const { $e } = useNuxtApp()
@ -64,7 +57,7 @@ onMounted(() => {
<a-row> <a-row>
<a-col :span="8"></a-col> <a-col :span="8"></a-col>
<a-col :span="8" class="!bg-red"> <a-col :span="8" class="!bg-red">
<a-card class="mx-auto mt-10 !max-w-[600px] shadow-lg"> <a-card :loading="isLoading" class="mx-auto mt-10 !max-w-[600px] shadow-lg">
<h1 class="text-center text-4xl pa-2 nc-project-page-title flex align-center justify-center gap-2 text-gray-600"> <h1 class="text-center text-4xl pa-2 nc-project-page-title flex align-center justify-center gap-2 text-gray-600">
<!-- My Projects --> <!-- My Projects -->
<b>{{ $t('title.myProject') }}</b> <b>{{ $t('title.myProject') }}</b>

6
packages/nc-gui-v2/pages/signin.vue

@ -84,10 +84,10 @@ function resetError() {
ref="formValidator" ref="formValidator"
:model="form" :model="form"
layout="vertical" layout="vertical"
class="bg-primary/5 signin h-full min-h-[600px] flex justify-center items-center nc-form-signin" class="bg-primary/5 signin h-full flex justify-center items-center nc-form-signin"
@finish="signIn" @finish="signIn"
> >
<div class="h-full w-full flex flex-col flex-wrap items-center pt-[100px]"> <div class="h-full w-full flex flex-col items-center justify-center pt-[50px]">
<div <div
class="bg-white dark:(!bg-gray-900 !text-white) relative flex flex-col justify-center gap-2 w-full max-w-[500px] mx-auto p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)" class="bg-white dark:(!bg-gray-900 !text-white) relative flex flex-col justify-center gap-2 w-full max-w-[500px] mx-auto p-8 md:(rounded-lg border-1 border-gray-200 shadow-xl)"
> >
@ -102,7 +102,7 @@ function resetError() {
<div v-if="error" class="self-center mb-4 bg-red-500 text-white rounded-lg w-3/4 mx-auto p-1"> <div v-if="error" class="self-center mb-4 bg-red-500 text-white rounded-lg w-3/4 mx-auto p-1">
<div class="flex items-center gap-2 justify-center"> <div class="flex items-center gap-2 justify-center">
<MaterialSymbolsWarning /> <MaterialSymbolsWarning />
<div style="flex: 0 0 auto" class="break-words">{{ error }}</div> <div class="break-words">{{ error }}</div>
</div> </div>
</div> </div>
</Transition> </Transition>

2
packages/nc-gui-v2/pages/signup/[[token]].vue

@ -114,7 +114,7 @@ function resetError() {
<div v-if="error" class="self-center mb-4 bg-red-500 text-white rounded-lg w-3/4 mx-auto p-1"> <div v-if="error" class="self-center mb-4 bg-red-500 text-white rounded-lg w-3/4 mx-auto p-1">
<div class="flex items-center gap-2 justify-center"> <div class="flex items-center gap-2 justify-center">
<MaterialSymbolsWarning /> <MaterialSymbolsWarning />
<div style="flex: 0 0 auto" class="break-words">{{ error }}</div> <div class="break-words">{{ error }}</div>
</div> </div>
</div> </div>
</Transition> </Transition>

10
packages/nc-gui-v2/plugins/a.dayjs.ts

@ -1,8 +1,9 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime' import relativeTime from 'dayjs/plugin/relativeTime.js'
import customParseFormat from 'dayjs/plugin/customParseFormat' import customParseFormat from 'dayjs/plugin/customParseFormat.js'
import duration from 'dayjs/plugin/duration' import duration from 'dayjs/plugin/duration.js'
import utc from 'dayjs/plugin/utc' import utc from 'dayjs/plugin/utc.js'
import weekday from 'dayjs/plugin/weekday.js'
import { defineNuxtPlugin } from '#imports' import { defineNuxtPlugin } from '#imports'
export default defineNuxtPlugin(() => { export default defineNuxtPlugin(() => {
@ -10,4 +11,5 @@ export default defineNuxtPlugin(() => {
dayjs.extend(relativeTime) dayjs.extend(relativeTime)
dayjs.extend(customParseFormat) dayjs.extend(customParseFormat)
dayjs.extend(duration) dayjs.extend(duration)
dayjs.extend(weekday)
}) })

2
packages/nc-gui-v2/utils/columnUtils.ts

@ -147,7 +147,7 @@ const uiTypes = [
}, },
] ]
const getUIDTIcon = (uidt: UITypes) => { const getUIDTIcon = (uidt: UITypes | string) => {
return ( return (
[ [
...uiTypes, ...uiTypes,

2
packages/nc-gui-v2/utils/dateTimeUtils.ts

@ -1,6 +1,4 @@
import dayjs from 'dayjs' import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
dayjs.extend(customParseFormat)
export const timeAgo = (date: any) => { export const timeAgo = (date: any) => {
return dayjs.utc(date).fromNow() return dayjs.utc(date).fromNow()

1
packages/nc-gui-v2/vue-color-shims.d.ts vendored

@ -1,4 +1,5 @@
declare module '@ckpack/vue-color' { declare module '@ckpack/vue-color' {
import type { Component } from '@vue/runtime-core' import type { Component } from '@vue/runtime-core'
const Sketch: Component const Sketch: Component
const Chrome: Component
} }

Loading…
Cancel
Save