Browse Source

Merge branch 'develop' into docs/v2

pull/6467/head
Raju Udava 1 year ago
parent
commit
bc8f109ac1
  1. 12
      packages/nc-gui/assets/nc-icons/fields.svg
  2. 2
      packages/nc-gui/assets/nc-icons/filter.svg
  3. 6
      packages/nc-gui/assets/nc-icons/group.svg
  4. 20
      packages/nc-gui/assets/nc-icons/lookup.svg
  5. 18
      packages/nc-gui/assets/nc-icons/super-admin.svg
  6. 8
      packages/nc-gui/components/account/Token.vue
  7. 6
      packages/nc-gui/components/cell/Checkbox.vue
  8. 6
      packages/nc-gui/components/cell/MultiSelect.vue
  9. 4
      packages/nc-gui/components/cell/SingleSelect.vue
  10. 4
      packages/nc-gui/components/dashboard/TreeView/ViewsList.vue
  11. 9
      packages/nc-gui/components/dashboard/settings/DataSources.vue
  12. 4
      packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue
  13. 4
      packages/nc-gui/components/dashboard/settings/data-sources/EditBase.vue
  14. 3
      packages/nc-gui/components/dlg/ProjectDuplicate.vue
  15. 3
      packages/nc-gui/components/dlg/TableCreate.vue
  16. 3
      packages/nc-gui/components/dlg/TableDuplicate.vue
  17. 10
      packages/nc-gui/components/dlg/TableRename.vue
  18. 4
      packages/nc-gui/components/dlg/ViewCreate.vue
  19. 4
      packages/nc-gui/components/dlg/ViewDelete.vue
  20. 4
      packages/nc-gui/components/dlg/WorkspaceDelete.vue
  21. 10
      packages/nc-gui/components/general/WorkspaceIcon.vue
  22. 1
      packages/nc-gui/components/nc/Badge.vue
  23. 17
      packages/nc-gui/components/project/AccessSettings.vue
  24. 1
      packages/nc-gui/components/roles/Badge.vue
  25. 5
      packages/nc-gui/components/smartsheet/Cell.vue
  26. 53
      packages/nc-gui/components/smartsheet/column/DefaultValue.vue
  27. 25
      packages/nc-gui/components/smartsheet/column/SelectOptions.vue
  28. 3
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  29. 104
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  30. 36
      packages/nc-gui/components/smartsheet/grid/index.vue
  31. 2
      packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts
  32. 7
      packages/nc-gui/components/smartsheet/toolbar/ColumnFilterMenu.vue
  33. 4
      packages/nc-gui/components/smartsheet/toolbar/FieldsMenu.vue
  34. 3
      packages/nc-gui/components/smartsheet/toolbar/GroupByMenu.vue
  35. 4
      packages/nc-gui/components/smartsheet/toolbar/SortListMenu.vue
  36. 8
      packages/nc-gui/components/virtual-cell/Links.vue
  37. 11
      packages/nc-gui/components/virtual-cell/QrCode.vue
  38. 12
      packages/nc-gui/components/virtual-cell/barcode/Barcode.vue
  39. 6
      packages/nc-gui/components/virtual-cell/components/ItemChip.vue
  40. 71
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  41. 7
      packages/nc-gui/components/workspace/View.vue
  42. 5
      packages/nc-gui/composables/useExpandedFormStore.ts
  43. 8
      packages/nc-gui/composables/useMultiSelect/convertCellData.ts
  44. 4
      packages/nc-gui/composables/useMultiSelect/index.ts
  45. 14
      packages/nc-gui/composables/useViewData.ts
  46. 5
      packages/nc-gui/lang/en.json
  47. 4
      packages/nc-gui/nuxt.config.ts
  48. 2
      packages/nc-gui/package.json
  49. 5
      packages/nc-gui/store/views.ts
  50. 15
      packages/nc-gui/utils/iconUtils.ts
  51. 12
      packages/nc-gui/windi.config.ts
  52. 4
      packages/nocodb-sdk/src/lib/enums.ts
  53. 2
      packages/nocodb/src/db/BaseModelSqlv2.ts
  54. 6
      packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts
  55. 8
      packages/nocodb/src/helpers/catchError.ts
  56. 5
      packages/nocodb/src/modules/jobs/jobs.module.ts
  57. 2
      packages/nocodb/src/services/api-tokens.service.ts
  58. 63
      packages/nocodb/src/services/columns.service.ts
  59. 2
      packages/nocodb/src/services/org-tokens.service.ts
  60. 320
      pnpm-lock.yaml
  61. 1
      tests/playwright/pages/Dashboard/Command/CmdKPage.ts

12
packages/nc-gui/assets/nc-icons/fields.svg

@ -1,8 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.3335 12H14.0002" stroke="#374151" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M5.3335 12H14.0002" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2 12H2.00667" stroke="#374151" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 12H2.00667" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.3335 8H14.0002" stroke="#4A5268" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M5.3335 8H14.0002" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2 8H2.00667" stroke="#4A5268" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 8H2.00667" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.3335 4H14.0002" stroke="#4A5268" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M5.3335 4H14.0002" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2 4H2.00667" stroke="#4A5268" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2 4H2.00667" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 792 B

After

Width:  |  Height:  |  Size: 822 B

2
packages/nc-gui/assets/nc-icons/filter.svg

@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.6668 2H1.3335L6.66683 8.30667V12.6667L9.3335 14V8.30667L14.6668 2Z" stroke="#374151" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M14.6668 2H1.3335L6.66683 8.30667V12.6667L9.3335 14V8.30667L14.6668 2Z" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 273 B

After

Width:  |  Height:  |  Size: 278 B

6
packages/nc-gui/assets/nc-icons/group.svg

@ -1,5 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 5.33331V14H2V5.33331" stroke="#374151" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M14 5.33331V14H2V5.33331" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.6665 8H9.33317" stroke="#374151" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M6.6665 8H9.33317" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M15.3332 2H0.666504V5.33333H15.3332V2Z" stroke="#4A5268" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/> <path d="M15.3332 2H0.666504V5.33333H15.3332V2Z" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 482 B

After

Width:  |  Height:  |  Size: 497 B

20
packages/nc-gui/assets/nc-icons/lookup.svg

@ -1,15 +1,7 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Field Icons"> <path d="M10 10L14 10" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<mask id="mask0_3_121" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24"> <path d="M10 6L14 6" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<rect id="Bounding box" width="24" height="24" fill="#6a7184"/> <path d="M6 12.5V13C6 13.5523 6.44772 14 7 14H13C13.5523 14 14 13.5523 14 13V3C14 2.44772 13.5523 2 13 2H7C6.44772 2 6 2.44772 6 3V3.5" stroke="currentColor" stroke-width="1.33" stroke-linecap="round"/>
</mask> <path d="M5 11C3.34315 11 2 9.65685 2 8C2 6.34315 3.34315 5 5 5C6.65685 5 8 6.34315 8 8C8 9.65685 6.65685 11 5 11Z" stroke="currentColor" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<g mask="url(#mask0_3_121)"> <path d="M1.4714 12.4714C1.21105 12.7318 0.788945 12.7318 0.528595 12.4714C0.268246 12.2111 0.268246 11.7889 0.528595 11.5286L1.4714 12.4714ZM2.5286 9.5286L3 9.05719L3.94281 10L3.4714 10.4714L2.5286 9.5286ZM0.528595 11.5286L2.5286 9.5286L3.4714 10.4714L1.4714 12.4714L0.528595 11.5286Z" fill="currentColor" stroke="none"/>
<g id="Group 58">
<path id="Vector" d="M15.4615 15.0769L21 15.0769" stroke="#6a7184" stroke-width="1.33333" stroke-linecap="square" stroke-linejoin="round"/>
<path id="Vector_2" d="M15.4615 9.53845L21 9.53845" stroke="#6a7184" stroke-width="1.33333" stroke-linecap="square" stroke-linejoin="round"/>
<rect id="Rectangle 1" width="5.53846" height="16.6154" rx="1" transform="matrix(-1 0 0 1 21 4)" stroke="#6a7184" stroke-width="1.33"/>
<path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="M12.0256 12.3077C12.0256 10.3817 10.4644 8.82049 8.53846 8.82049C6.61254 8.82049 5.05128 10.3817 5.05128 12.3077C5.05128 14.2336 6.61254 15.7948 8.53846 15.7948C10.4644 15.7948 12.0256 14.2336 12.0256 12.3077ZM8.53846 7.48715C11.2008 7.48715 13.359 9.64537 13.359 12.3077C13.359 14.97 11.2008 17.1282 8.53846 17.1282C7.4872 17.1282 6.51454 16.7917 5.72231 16.2205L5.47138 16.4714L3.47138 18.4714C3.21103 18.7318 2.78892 18.7318 2.52858 18.4714C2.26823 18.2111 2.26823 17.789 2.52858 17.5286L4.52858 15.5286L4.75813 15.299C4.10685 14.4771 3.71794 13.4378 3.71794 12.3077C3.71794 9.64537 5.87616 7.48715 8.53846 7.48715Z" fill="#6a7184"/>
</g>
</g>
</g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

18
packages/nc-gui/assets/nc-icons/super-admin.svg

@ -0,0 +1,18 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0_1882_74955" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16">
<rect width="16" height="16" fill="#D9D9D9"/>
</mask>
<g mask="url(#mask0_1882_74955)">
<path d="M7.33333 7.99996C6.6 7.99996 5.97222 7.73885 5.45 7.21663C4.92778 6.6944 4.66667 6.06663 4.66667 5.33329C4.66667 4.59996 4.92778 3.97218 5.45 3.44996C5.97222 2.92774 6.6 2.66663 7.33333 2.66663C8.06667 2.66663 8.69444 2.92774 9.21667 3.44996C9.73889 3.97218 10 4.59996 10 5.33329C10 6.06663 9.73889 6.6944 9.21667 7.21663C8.69444 7.73885 8.06667 7.99996 7.33333 7.99996ZM2 12V11.4666C2 11.1 2.09444 10.7555 2.28333 10.4333C2.47222 10.1111 2.73333 9.86663 3.06667 9.69996C3.63333 9.41107 4.27222 9.16663 4.98333 8.96663C5.69444 8.76663 6.47778 8.66663 7.33333 8.66663H7.56667C7.63333 8.66663 7.7 8.67774 7.76667 8.69996C7.67778 8.89996 7.60278 9.10829 7.54167 9.32496C7.48056 9.54163 7.43333 9.76663 7.4 9.99996H7.33333C6.54444 9.99996 5.83611 10.1 5.20833 10.3C4.58056 10.5 4.06667 10.7 3.66667 10.9C3.56667 10.9555 3.48611 11.0333 3.425 11.1333C3.36389 11.2333 3.33333 11.3444 3.33333 11.4666V12H7.53333C7.6 12.2333 7.68889 12.4638 7.8 12.6916C7.91111 12.9194 8.03333 13.1333 8.16667 13.3333H3.33333C2.96667 13.3333 2.65278 13.2027 2.39167 12.9416C2.13056 12.6805 2 12.3666 2 12ZM7.33333 6.66663C7.7 6.66663 8.01389 6.53607 8.275 6.27496C8.53611 6.01385 8.66667 5.69996 8.66667 5.33329C8.66667 4.96663 8.53611 4.65274 8.275 4.39163C8.01389 4.13051 7.7 3.99996 7.33333 3.99996C6.96667 3.99996 6.65278 4.13051 6.39167 4.39163C6.13056 4.65274 6 4.96663 6 5.33329C6 5.69996 6.13056 6.01385 6.39167 6.27496C6.65278 6.53607 6.96667 6.66663 7.33333 6.66663Z" fill="currentColor" stroke="none"/>
<path d="M11 14C10.9117 14 10.826 13.9815 10.7429 13.9444C10.6597 13.9074 10.587 13.8543 10.5247 13.7852L8.14026 11.0741C8.09351 11.0198 8.05844 10.9605 8.03506 10.8963C8.01169 10.8321 8 10.7654 8 10.6963C8 10.6519 8.0039 10.6062 8.01169 10.5593C8.01948 10.5123 8.03636 10.4691 8.06234 10.4296L8.64675 9.32593C8.7039 9.22716 8.78052 9.14815 8.87662 9.08889C8.97273 9.02963 9.08052 9 9.2 9H12.8C12.9195 9 13.0273 9.02963 13.1234 9.08889C13.2195 9.14815 13.2961 9.22716 13.3532 9.32593L13.9377 10.4296C13.9636 10.4691 13.9805 10.5123 13.9883 10.5593C13.9961 10.6062 14 10.6519 14 10.6963C14 10.7654 13.9883 10.8321 13.9649 10.8963C13.9416 10.9605 13.9065 11.0198 13.8597 11.0741L11.4753 13.7852C11.413 13.8543 11.3403 13.9074 11.2571 13.9444C11.174 13.9815 11.0883 14 11 14ZM10.2597 10.4815H11.7403L11.2727 9.59259H10.7273L10.2597 10.4815ZM10.6883 13.0519V11.0741H8.95844L10.6883 13.0519ZM11.3117 13.0519L13.0416 11.0741H11.3117V13.0519ZM12.4338 10.4815H13.2597L12.7922 9.59259H11.9662L12.4338 10.4815ZM8.74026 10.4815H9.56623L10.0338 9.59259H9.20779L8.74026 10.4815Z" fill="currentColor" stroke="currentColor" stroke-width="0.3"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

8
packages/nc-gui/components/account/Token.vue

@ -2,7 +2,7 @@
import type { VNodeRef } from '@vue/runtime-core' import type { VNodeRef } from '@vue/runtime-core'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import type { ApiTokenType, RequestParams } from 'nocodb-sdk' import type { ApiTokenType, RequestParams } from 'nocodb-sdk'
import { extractSdkResponseErrorMsg, ref, useApi, useCopy, useNuxtApp } from '#imports' import { extractSdkResponseErrorMsg, isEeUI, ref, useApi, useCopy, useNuxtApp } from '#imports'
const { api, isLoading } = useApi() const { api, isLoading } = useApi()
@ -164,12 +164,15 @@ const handleCancel = () => {
<div class="max-w-[810px] mx-auto p-4" data-testid="nc-token-list"> <div class="max-w-[810px] mx-auto p-4" data-testid="nc-token-list">
<div class="py-2 flex gap-4 items-center justify-between"> <div class="py-2 flex gap-4 items-center justify-between">
<h6 class="text-2xl my-4 text-left font-bold">{{ $t('title.apiTokens') }}</h6> <h6 class="text-2xl my-4 text-left font-bold">{{ $t('title.apiTokens') }}</h6>
<NcTooltip :disabled="!(isEeUI && tokens.length)">
<template #title>{{ $t('labels.tokenLimit') }}</template>
<NcButton <NcButton
:disabled="showNewTokenModal" :disabled="showNewTokenModal || (isEeUI && tokens.length)"
class="!rounded-md" class="!rounded-md"
data-testid="nc-token-create" data-testid="nc-token-create"
size="middle" size="middle"
type="primary" type="primary"
tooltip="bottom"
@click="showNewTokenModal = true" @click="showNewTokenModal = true"
> >
<span class="hidden md:block"> <span class="hidden md:block">
@ -179,6 +182,7 @@ const handleCancel = () => {
<component :is="iconMap.plus" /> <component :is="iconMap.plus" />
</span> </span>
</NcButton> </NcButton>
</NcTooltip>
</div> </div>
<span>{{ $t('msg.apiTokenCreate') }}</span> <span>{{ $t('msg.apiTokenCreate') }}</span>
<div class="w-full mt-5 rounded-md h-136 overflow-y-scroll"> <div class="w-full mt-5 rounded-md h-136 overflow-y-scroll">

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

@ -40,6 +40,8 @@ const isGallery = inject(IsGalleryInj, ref(false))
const readOnly = inject(ReadonlyInj) const readOnly = inject(ReadonlyInj)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const checkboxMeta = computed(() => { const checkboxMeta = computed(() => {
return { return {
icon: { icon: {
@ -82,8 +84,8 @@ useSelectedCellKeyupListener(active, (e) => {
<div <div
class="flex cursor-pointer w-full h-full items-center" class="flex cursor-pointer w-full h-full items-center"
:class="{ :class="{
'justify-center': !isForm || !isGallery, 'w-full flex-start pl-2': isForm || isGallery || isExpandedFormOpen,
'w-full flex-start': isForm || isGallery, 'w-full justify-center': !isForm && !isGallery && !isExpandedFormOpen,
'nc-cell-hover-show': !vModel && !readOnly, 'nc-cell-hover-show': !vModel && !readOnly,
'opacity-0': readOnly && !vModel, 'opacity-0': readOnly && !vModel,
}" }"

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

@ -142,8 +142,8 @@ const selectedTitles = computed(() =>
} }
return 0 return 0
}) })
: modelValue.split(',') : modelValue.split(',').map((el) => el.trim())
: modelValue : modelValue.map((el) => el.trim())
: [], : [],
) )
@ -255,7 +255,7 @@ async function addIfMissingAndSave() {
} }
// Mysql escapes single quotes with backslash so we keep quotes but others have to unescaped // Mysql escapes single quotes with backslash so we keep quotes but others have to unescaped
if (!isMysql(column.value.source_id)) { if (!isMysql(column.value.source_id) && !isPg(column.value.source_id)) {
updatedColMeta.cdf = updatedColMeta.cdf.replace(/''/g, "'") updatedColMeta.cdf = updatedColMeta.cdf.replace(/''/g, "'")
} }
} }

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

@ -102,7 +102,7 @@ const hasEditRoles = computed(() => isUIAllowed('dataEdit'))
const editAllowed = computed(() => (hasEditRoles.value || isForm.value) && active.value) const editAllowed = computed(() => (hasEditRoles.value || isForm.value) && active.value)
const vModel = computed({ const vModel = computed({
get: () => tempSelectedOptState.value ?? modelValue, get: () => tempSelectedOptState.value ?? modelValue?.trim(),
set: (val) => { set: (val) => {
if (val && isNewOptionCreateEnabled.value && (options.value ?? []).every((op) => op.title !== val)) { if (val && isNewOptionCreateEnabled.value && (options.value ?? []).every((op) => op.title !== val)) {
tempSelectedOptState.value = val tempSelectedOptState.value = val
@ -183,7 +183,7 @@ async function addIfMissingAndSave() {
} }
// Mysql escapes single quotes with backslash so we keep quotes but others have to unescaped // Mysql escapes single quotes with backslash so we keep quotes but others have to unescaped
if (!isMysql(column.value.source_id)) { if (!isMysql(column.value.source_id) && !isPg(column.value.source_id)) {
updatedColMeta.cdf = updatedColMeta.cdf.replace(/''/g, "'") updatedColMeta.cdf = updatedColMeta.cdf.replace(/''/g, "'")
} }
} }

4
packages/nc-gui/components/dashboard/TreeView/ViewsList.vue

@ -38,7 +38,7 @@ const { $e } = useNuxtApp()
const { t } = useI18n() const { t } = useI18n()
const { viewsByTable, activeView, recentViews } = storeToRefs(useViewsStore()) const { viewsByTable, activeView, allRecentViews } = storeToRefs(useViewsStore())
const { navigateToTable } = useTablesStore() const { navigateToTable } = useTablesStore()
@ -239,7 +239,7 @@ async function onRename(view: ViewType, originalTitle?: string, undo = false) {
}) })
} }
// update view name in recent views // update view name in recent views
recentViews.value = recentViews.value.map((rv) => { allRecentViews.value = allRecentViews.value.map((rv) => {
if (rv.viewId === view.id && rv.tableID === view.fk_model_id) { if (rv.viewId === view.id && rv.tableID === view.fk_model_id) {
rv.viewName = view.title rv.viewName = view.title
} }

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

@ -87,9 +87,11 @@ const deleteBase = async () => {
await loadProject(base.value.id as string, true) await loadProject(base.value.id as string, true)
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} finally {
// TODO @mertmit
refreshCommandPalette()
} }
} }
const toggleBase = async (source: BaseType, state: boolean) => { const toggleBase = async (source: BaseType, state: boolean) => {
try { try {
if (!state && sources.value.filter((src) => src.enabled).length < 2) { if (!state && sources.value.filter((src) => src.enabled).length < 2) {
@ -105,6 +107,8 @@ const toggleBase = async (source: BaseType, state: boolean) => {
await loadProject(base.value.id as string, true) await loadProject(base.value.id as string, true)
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} finally {
refreshCommandPalette()
} }
} }
@ -133,6 +137,8 @@ const moveBase = async (e: any) => {
await loadBases() await loadBases()
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} finally {
await refreshCommandPalette()
} }
} }
@ -210,6 +216,7 @@ watch(
} }
break break
} }
refreshCommandPalette()
}, },
{ immediate: true }, { immediate: true },
) )

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

@ -39,6 +39,8 @@ const { base } = storeToRefs(baseStore)
const { loadProjectTables } = useTablesStore() const { loadProjectTables } = useTablesStore()
const { refreshCommandPalette } = useCommandPalette()
const _projectId = inject(ProjectIdInj, undefined) const _projectId = inject(ProjectIdInj, undefined)
const baseId = computed(() => _projectId?.value ?? base.value?.id) const baseId = computed(() => _projectId?.value ?? base.value?.id)
@ -293,6 +295,8 @@ const createSource = async () => {
) )
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} finally {
refreshCommandPalette()
} }
} }

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

@ -39,6 +39,8 @@ const { base } = storeToRefs(baseStore)
const _projectId = inject(ProjectIdInj, undefined) const _projectId = inject(ProjectIdInj, undefined)
const baseId = computed(() => _projectId?.value ?? base.value?.id) const baseId = computed(() => _projectId?.value ?? base.value?.id)
const { refreshCommandPalette } = useCommandPalette()
const useForm = Form.useForm const useForm = Form.useForm
const testSuccess = ref(false) const testSuccess = ref(false)
@ -235,6 +237,8 @@ const editBase = async () => {
emit('close') emit('close')
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} finally {
refreshCommandPalette()
} }
} }

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

@ -11,6 +11,8 @@ const props = defineProps<{
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const { refreshCommandPalette } = useCommandPalette()
const { api } = useApi() const { api } = useApi()
const dialogShow = useVModel(props, 'modelValue', emit) const dialogShow = useVModel(props, 'modelValue', emit)
@ -60,6 +62,7 @@ const _duplicate = async () => {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} finally { } finally {
isLoading.value = false isLoading.value = false
refreshCommandPalette()
dialogShow.value = false dialogShow.value = false
} }
} }

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

@ -34,6 +34,8 @@ const { isMysql, isMssql, isPg } = useBase()
const { loadProjectTables, addTable } = useTablesStore() const { loadProjectTables, addTable } = useTablesStore()
const { refreshCommandPalette } = useCommandPalette()
const { table, createTable, generateUniqueTitle, tables, base } = useTableNew({ const { table, createTable, generateUniqueTitle, tables, base } = useTableNew({
async onTableCreate(table) { async onTableCreate(table) {
// await loadProject(props.baseId) // await loadProject(props.baseId)
@ -120,6 +122,7 @@ const _createTable = async () => {
setTimeout(() => { setTimeout(() => {
creating.value = false creating.value = false
}, 500) }, 500)
refreshCommandPalette()
} }
} }

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

@ -14,6 +14,8 @@ const { api } = useApi()
const dialogShow = useVModel(props, 'modelValue', emit) const dialogShow = useVModel(props, 'modelValue', emit)
const { refreshCommandPalette } = useCommandPalette()
const options = ref({ const options = ref({
includeData: true, includeData: true,
includeViews: true, includeViews: true,
@ -41,6 +43,7 @@ const _duplicate = async () => {
} finally { } finally {
isLoading.value = false isLoading.value = false
dialogShow.value = false dialogShow.value = false
refreshCommandPalette()
} }
} }

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

@ -46,6 +46,8 @@ const baseStore = useBase()
const { loadTables, isMysql, isMssql, isPg } = baseStore const { loadTables, isMysql, isMssql, isPg } = baseStore
const { tables, base } = storeToRefs(baseStore) const { tables, base } = storeToRefs(baseStore)
const { allRecentViews } = storeToRefs(useViewsStore())
const { refreshCommandPalette } = useCommandPalette() const { refreshCommandPalette } = useCommandPalette()
const { addUndo, defineProjectScope } = useUndoRedo() const { addUndo, defineProjectScope } = useUndoRedo()
@ -158,6 +160,14 @@ const renameTable = async (undo = false, disableTitleDiffCheck?: boolean | undef
await loadTables() await loadTables()
// update recent views if default view is renamed
allRecentViews.value = allRecentViews.value.map((v) => {
if (v.tableID === tableMeta.id && v.isDefault) {
v.viewName = formState.title
}
return v
})
// update metas // update metas
const newMeta = await $api.dbTable.read(tableMeta.id as string) const newMeta = await $api.dbTable.read(tableMeta.id as string)
await setMeta(newMeta) await setMeta(newMeta)

4
packages/nc-gui/components/dlg/ViewCreate.vue

@ -42,6 +42,8 @@ const { getMeta } = useMetas()
const { viewsByTable } = storeToRefs(useViewsStore()) const { viewsByTable } = storeToRefs(useViewsStore())
const { refreshCommandPalette } = useCommandPalette()
const { selectedViewId, groupingFieldColumnId, geoDataFieldColumnId, tableId } = toRefs(props) const { selectedViewId, groupingFieldColumnId, geoDataFieldColumnId, tableId } = toRefs(props)
const meta = ref<TableType | undefined>() const meta = ref<TableType | undefined>()
@ -171,6 +173,8 @@ async function onSubmit() {
} }
} catch (e: any) { } catch (e: any) {
message.error(e.message) message.error(e.message)
} finally {
refreshCommandPalette()
} }
vModel.value = false vModel.value = false

4
packages/nc-gui/components/dlg/ViewDelete.vue

@ -15,6 +15,8 @@ const props = defineProps<Props>()
const emits = defineEmits<Emits>() const emits = defineEmits<Emits>()
const { refreshCommandPalette } = useCommandPalette()
const { view } = props const { view } = props
const vModel = useVModel(props, 'modelValue', emits) const vModel = useVModel(props, 'modelValue', emits)
@ -35,6 +37,8 @@ async function onDelete() {
$e('a:view:delete', { view: props.view.type }) $e('a:view:delete', { view: props.view.type })
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} finally {
refreshCommandPalette()
} }
// telemetry event // telemetry event

4
packages/nc-gui/components/dlg/WorkspaceDelete.vue

@ -13,6 +13,8 @@ const { deleteWorkspace: _deleteWorkspace, loadWorkspaces, navigateToWorkspace }
const { workspaces, workspacesList } = storeToRefs(workspaceStore) const { workspaces, workspacesList } = storeToRefs(workspaceStore)
const { refreshCommandPalette } = useCommandPalette()
const workspace = computed(() => workspaces.value.get(props.workspaceId)) const workspace = computed(() => workspaces.value.get(props.workspaceId))
const onDelete = async () => { const onDelete = async () => {
@ -29,6 +31,8 @@ const onDelete = async () => {
await navigateToWorkspace(workspacesList.value?.[0]?.id) await navigateToWorkspace(workspacesList.value?.[0]?.id)
} catch (e: any) { } catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e)) message.error(await extractSdkResponseErrorMsg(e))
} finally {
refreshCommandPalette()
} }
} }
</script> </script>

10
packages/nc-gui/components/general/WorkspaceIcon.vue

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { WorkspaceType } from 'nocodb-sdk' import type { WorkspaceType } from 'nocodb-sdk'
import { stringToColor } from '~/utils/colorsUtils' import { isColorDark, stringToColor } from '~/utils/colorsUtils'
const props = defineProps<{ const props = defineProps<{
workspace: WorkspaceType | undefined workspace: WorkspaceType | undefined
@ -26,7 +26,13 @@ const size = computed(() => props.size || 'medium')
:style="{ backgroundColor: workspaceColor }" :style="{ backgroundColor: workspaceColor }"
> >
<template v-if="!props.hideLabel"> <template v-if="!props.hideLabel">
<div class="font-black"> <div
class="font-semibold"
:class="{
'text-white': isColorDark(workspaceColor),
'text-black': !isColorDark(workspaceColor),
}"
>
{{ props.workspace?.title?.slice(0, 2) }} {{ props.workspace?.title?.slice(0, 2) }}
</div> </div>
</template> </template>

1
packages/nc-gui/components/nc/Badge.vue

@ -22,6 +22,7 @@ const props = withDefaults(
'border-orange-500 bg-orange-100': props.color === 'orange', 'border-orange-500 bg-orange-100': props.color === 'orange',
'border-yellow-500 bg-yellow-100': props.color === 'yellow', 'border-yellow-500 bg-yellow-100': props.color === 'yellow',
'border-red-500 bg-red-100': props.color === 'red', 'border-red-500 bg-red-100': props.color === 'red',
'border-maroon-500 bg-maroon-50': props.color === 'maroon',
'border-gray-300': !props.color, 'border-gray-300': !props.color,
'border-1': props.border, 'border-1': props.border,
'h-6': props.size === 'sm', 'h-6': props.size === 'sm',

17
packages/nc-gui/components/project/AccessSettings.vue

@ -1,6 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { OrgUserRoles, WorkspaceUserRoles } from 'nocodb-sdk' import type { WorkspaceUserRoles } from 'nocodb-sdk'
import { OrderedProjectRoles, ProjectRoles, WorkspaceRolesToProjectRoles } from 'nocodb-sdk' import { OrderedProjectRoles, OrgUserRoles, ProjectRoles, WorkspaceRolesToProjectRoles, extractRolesObj } from 'nocodb-sdk'
import InfiniteLoading from 'v3-infinite-loading' import InfiniteLoading from 'v3-infinite-loading'
import { isEeUI, storeToRefs, timeAgo } from '#imports' import { isEeUI, storeToRefs, timeAgo } from '#imports'
@ -8,7 +8,9 @@ const basesStore = useBases()
const { getProjectUsers, createProjectUser, updateProjectUser, removeProjectUser } = basesStore const { getProjectUsers, createProjectUser, updateProjectUser, removeProjectUser } = basesStore
const { activeProjectId } = storeToRefs(basesStore) const { activeProjectId } = storeToRefs(basesStore)
const { baseRoles } = useRoles() const { orgRoles, baseRoles } = useRoles()
const isSuper = computed(() => orgRoles.value?.[OrgUserRoles.SUPER_ADMIN])
interface Collaborators { interface Collaborators {
id: string id: string
@ -44,8 +46,9 @@ const loadCollaborators = async () => {
...users.map((user: any) => ({ ...users.map((user: any) => ({
...user, ...user,
base_roles: user.roles, base_roles: user.roles,
roles: roles: extractRolesObj(user.main_roles)?.[OrgUserRoles.SUPER_ADMIN]
user.roles ?? ? OrgUserRoles.SUPER_ADMIN
: user.roles ??
(user.workspace_roles (user.workspace_roles
? WorkspaceRolesToProjectRoles[user.workspace_roles as WorkspaceUserRoles] ?? ProjectRoles.NO_ACCESS ? WorkspaceRolesToProjectRoles[user.workspace_roles as WorkspaceUserRoles] ?? ProjectRoles.NO_ACCESS
: ProjectRoles.NO_ACCESS), : ProjectRoles.NO_ACCESS),
@ -135,7 +138,9 @@ onMounted(async () => {
const currentRoleIndex = OrderedProjectRoles.findIndex( const currentRoleIndex = OrderedProjectRoles.findIndex(
(role) => baseRoles.value && Object.keys(baseRoles.value).includes(role), (role) => baseRoles.value && Object.keys(baseRoles.value).includes(role),
) )
if (currentRoleIndex !== -1) { if (isSuper.value) {
accessibleRoles.value = OrderedProjectRoles.slice(1)
} else if (currentRoleIndex !== -1) {
accessibleRoles.value = OrderedProjectRoles.slice(currentRoleIndex + 1) accessibleRoles.value = OrderedProjectRoles.slice(currentRoleIndex + 1)
} }
} catch (e: any) { } catch (e: any) {

1
packages/nc-gui/components/roles/Badge.vue

@ -56,6 +56,7 @@ const roleProperties = computed(() => {
'text-orange-700': roleProperties.color === 'orange', 'text-orange-700': roleProperties.color === 'orange',
'text-yellow-700': roleProperties.color === 'yellow', 'text-yellow-700': roleProperties.color === 'yellow',
'text-red-700': roleProperties.color === 'red', 'text-red-700': roleProperties.color === 'red',
'text-maroon-700': roleProperties.color === 'maroon',
'text-gray-300': !roleProperties.color, 'text-gray-300': !roleProperties.color,
sizeSelect, sizeSelect,
}" }"

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

@ -63,7 +63,7 @@ interface Props {
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'save', 'navigate', 'update:editEnabled', 'update:value']) const emit = defineEmits(['update:modelValue', 'save', 'navigate', 'update:editEnabled', 'update:cdf'])
const column = toRef(props, 'column') const column = toRef(props, 'column')
@ -118,8 +118,7 @@ const vModel = computed({
}, },
set: (val) => { set: (val) => {
if (isEditColumnMenu.value) { if (isEditColumnMenu.value) {
column.value.cdf = val emit('update:cdf', val)
emit('update:value', val)
} else if (val !== props.modelValue) { } else if (val !== props.modelValue) {
currentRow.value.rowMeta.changed = true currentRow.value.rowMeta.changed = true
emit('update:modelValue', val) emit('update:modelValue', val)

53
packages/nc-gui/components/smartsheet/column/DefaultValue.vue

@ -5,59 +5,52 @@ import { iconMap } from '#imports'
const props = defineProps<{ const props = defineProps<{
value: any value: any
}>() }>()
const emit = defineEmits(['update:value']) const emits = defineEmits(['update:value'])
const meta = inject(MetaInj, ref())
provide(EditColumnInj, ref(true)) provide(EditColumnInj, ref(true))
const vModel = useVModel(props, 'value', emit) const vModel = useVModel(props, 'value', emits)
const rowRef = ref({ const rowRef = ref({
row: {}, row: {},
oldRow: {}, oldRow: {},
rowMeta: { rowMeta: {
isUpdatedFromCopyNPaste: [vModel?.value.title], isUpdatedFromCopyNPaste: [vModel.value?.title],
}, },
}) })
const cdfValue = computed({ useProvideSmartsheetRowStore(meta, rowRef)
get: () => {
if (vModel.value.uidt === UITypes.MultiSelect || vModel.value.uidt === UITypes.SingleSelect) { const cdfValue = ref<string | null>(null)
return (vModel.value.cdf ?? '').replaceAll("'", '')
} else if ( const updateCdfValue = (cdf: string | null) => {
vModel.value.uidt === UITypes.SingleLineText || vModel.value.cdf = cdf
vModel.value.uidt === UITypes.LongText || cdfValue.value = vModel.value.cdf
vModel.value.uidt === UITypes.Email ||
vModel.value.uidt === UITypes.URL ||
vModel.value.uidt === UITypes.JSON ||
vModel.value.uidt === UITypes.DateTime ||
vModel.value.uidt === UITypes.Time ||
vModel.value.uidt === UITypes.Year ||
vModel.value.uidt === UITypes.Date
) {
return (vModel.value.cdf ?? '').replace(/^'/, '').replace(/'$/, '')
} }
return vModel.value.cdf
},
set: (value) => {
vModel.value.cdf = value
},
})
useProvideSmartsheetRowStore(vModel, rowRef) onMounted(() => {
updateCdfValue(vModel.value?.cdf ? vModel.value.cdf : null)
})
</script> </script>
<template> <template>
<div class="!my-3 text-xs">{{ $t('placeholder.defaultValue') }}</div> <div class="!my-3 text-xs">{{ $t('placeholder.defaultValue') }}</div>
<div class="flex flex-row gap-2"> <div class="flex flex-row gap-2">
<div class="border-1 flex items-center w-full px-3 my-[-4px] border-gray-300 rounded-md"> <div class="border-1 flex items-center w-full px-3 my-[-4px] border-gray-300 rounded-md">
<LazySmartsheetCell :column="vModel" :model-value="cdfValue" :edit-enabled="true" class="!border-none" /> <LazySmartsheetCell
:model-value="cdfValue"
:column="vModel"
:edit-enabled="true"
class="!border-none"
@update:cdf="updateCdfValue"
/>
<component <component
:is="iconMap.close" :is="iconMap.close"
v-if="vModel.uidt !== UITypes.Year" v-if="![UITypes.Year, UITypes.SingleSelect, UITypes.MultiSelect].includes(vModel.uidt)"
class="w-4 h-4 cursor-pointer rounded-full !text-black-500 text-gray-500 cursor-pointer hover:bg-gray-50" class="w-4 h-4 cursor-pointer rounded-full !text-black-500 text-gray-500 cursor-pointer hover:bg-gray-50"
@click="cdfValue = null" @click="cdfValue = null"
/> />
</div> </div>
</div> </div>
</template> </template>
<style scoped></style>

25
packages/nc-gui/components/smartsheet/column/SelectOptions.vue

@ -21,7 +21,7 @@ const emit = defineEmits(['update:value'])
const vModel = useVModel(props, 'value', emit) const vModel = useVModel(props, 'value', emit)
const { setAdditionalValidations, validateInfos, isMysql } = useColumnCreateStoreOrThrow() const { setAdditionalValidations, validateInfos, isMysql, isPg } = useColumnCreateStoreOrThrow()
// const { base } = storeToRefs(useBase()) // const { base } = storeToRefs(useBase())
@ -101,9 +101,9 @@ onMounted(() => {
} }
if (vModel.value.cdf) { if (vModel.value.cdf) {
// Mysql escapes single quotes with backslash so we keep quotes but others have to unescaped const fndDefaultOption = options.value.find((el) => el.title === vModel.value.cdf)
if (!isMysql.value) { if (!fndDefaultOption) {
vModel.value.cdf = vModel.value.cdf.replace(/''/g, "'") vModel.value.cdf = vModel.value.cdf.replace(/^'/, '').replace(/'$/, '')
} }
} }
@ -181,23 +181,6 @@ const undoRemoveRenderedOption = (index: number) => {
} }
} }
// focus last created input
// watch(inputs, () => {
// if (inputs.value?.$el) {
// inputs.value.$el.focus()
// }
// })
// Removes the Select Option from cdf if the option is removed
watch(vModel.value, (next) => {
const cdfs = (next.cdf ?? '').split(',')
const values = (next.colOptions.options ?? []).map((col) => {
return col.title.replace(/^'/, '').replace(/'$/, '')
})
const newCdf = cdfs.filter((c: string) => values.includes(c)).join(',')
next.cdf = newCdf.length === 0 ? null : newCdf
})
const loadListData = async ($state: any) => { const loadListData = async ($state: any) => {
if (loadedOptionCount.value === options.value.length) { if (loadedOptionCount.value === options.value.length) {
$state.complete() $state.complete()

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

@ -194,7 +194,7 @@ watch(commentsWrapperEl, () => {
</div> </div>
<div v-if="hasEditPermission" class="p-2 bg-gray-50 gap-2 flex"> <div v-if="hasEditPermission" class="p-2 bg-gray-50 gap-2 flex">
<div class="h-14 flex flex-row w-full bg-white py-2.75 px-1.5 items-center rounded-xl border-1 border-gray-200"> <div class="h-14 flex flex-row w-full bg-white py-2.75 px-1.5 items-center rounded-xl border-1 border-gray-200">
<GeneralUserIcon size="base" class="!w-10" /> <GeneralUserIcon size="base" class="!w-10" :email="user?.email" />
<a-input <a-input
v-model:value="comment" v-model:value="comment"
class="!rounded-lg border-1 bg-white !px-2.5 !py-2 !border-gray-200 nc-comment-box !outline-none" class="!rounded-lg border-1 bg-white !px-2.5 !py-2 !border-gray-200 nc-comment-box !outline-none"
@ -230,6 +230,7 @@ watch(commentsWrapperEl, () => {
<div class="flex justify-between"> <div class="flex justify-between">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<GeneralUserIcon size="base" :email="log.user" /> <GeneralUserIcon size="base" :email="log.user" />
<div class="flex flex-col"> <div class="flex flex-col">
<span class="truncate font-bold max-w-50"> <span class="truncate font-bold max-w-50">
{{ log.display_name ?? log.user.split('@')[0].slice(0, 2) ?? 'Shared source' }} {{ log.display_name ?? log.user.split('@')[0].slice(0, 2) ?? 'Shared source' }}

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

@ -67,6 +67,10 @@ const state = toRef(props, 'state')
const meta = toRef(props, 'meta') const meta = toRef(props, 'meta')
const islastRow = toRef(props, 'lastRow')
const isFirstRow = toRef(props, 'firstRow')
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
@ -76,6 +80,8 @@ const isPublic = inject(IsPublicInj, ref(false))
// to check if a expanded form which is not yet saved exist or not // to check if a expanded form which is not yet saved exist or not
const isUnsavedFormExist = ref(false) const isUnsavedFormExist = ref(false)
const isRecordLinkCopied = ref(false)
const { isUIAllowed } = useRoles() const { isUIAllowed } = useRoles()
const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook()) const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook())
@ -120,6 +126,7 @@ const {
syncLTARRefs, syncLTARRefs,
save: _save, save: _save,
loadCommentsAndLogs, loadCommentsAndLogs,
clearColumns,
} = useProvideExpandedFormStore(meta, row) } = useProvideExpandedFormStore(meta, row)
const duplicatingRowInProgress = ref(false) const duplicatingRowInProgress = ref(false)
@ -143,9 +150,13 @@ const isExpanded = useVModel(props, 'modelValue', emits, {
}) })
const onClose = () => { const onClose = () => {
if (changedColumns.value.size > 0) {
isCloseModalOpen.value = true
} else {
if (_row.value?.rowMeta?.new) emits('cancel') if (_row.value?.rowMeta?.new) emits('cancel')
isExpanded.value = false isExpanded.value = false
} }
}
const onDuplicateRow = () => { const onDuplicateRow = () => {
duplicatingRowInProgress.value = true duplicatingRowInProgress.value = true
@ -180,35 +191,57 @@ const save = async () => {
} }
const isPreventChangeModalOpen = ref(false) const isPreventChangeModalOpen = ref(false)
const isCloseModalOpen = ref(false)
const discardPreventModal = () => { const discardPreventModal = () => {
// when user click on next or previous button
if (isPreventChangeModalOpen.value) {
emits('next') emits('next')
if (_row.value?.rowMeta?.new) emits('cancel')
isPreventChangeModalOpen.value = false isPreventChangeModalOpen.value = false
} }
// when user click on close button
if (isCloseModalOpen.value) {
isCloseModalOpen.value = false
if (_row.value?.rowMeta?.new) emits('cancel')
isExpanded.value = false
}
// clearing all new modifed change on close
clearColumns()
}
const onNext = async () => { const onNext = async () => {
if (changedColumns.value.size > 0) { if (changedColumns.value.size > 0) {
isPreventChangeModalOpen.value = true isPreventChangeModalOpen.value = true
} else { return
emits('next')
} }
emits('next')
} }
const copyRecordUrl = () => { const copyRecordUrl = async () => {
copy( await copy(
encodeURI( encodeURI(
`${dashboardUrl?.value}#/${route.params.typeOrId}/${route.params.projectId}/${meta.value?.id}${ `${dashboardUrl?.value}#/${route.params.typeOrId}/${route.params.baseId}/${meta.value?.id}${
props.view ? `/${props.view.title}` : '' props.view ? `/${props.view.title}` : ''
}?rowId=${primaryKey.value}`, }?rowId=${primaryKey.value}`,
), ),
) )
message.success('Copied to clipboard')
isRecordLinkCopied.value = true
} }
const saveChanges = async () => { const saveChanges = async () => {
if (isPreventChangeModalOpen.value) {
isUnsavedFormExist.value = false isUnsavedFormExist.value = false
await save() await save()
emits('next') emits('next')
isPreventChangeModalOpen.value = false
}
if (isCloseModalOpen.value) {
isCloseModalOpen.value = false
await save()
isExpanded.value = false
}
} }
const reloadParentRowHook = inject(ReloadRowDataHookInj, createEventHook()) const reloadParentRowHook = inject(ReloadRowDataHookInj, createEventHook())
@ -235,6 +268,7 @@ provide(IsExpandedFormOpenInj, isExpanded)
const cellWrapperEl = ref() const cellWrapperEl = ref()
onMounted(async () => { onMounted(async () => {
isRecordLinkCopied.value = false
isLoading.value = true isLoading.value = true
if (props.loadRow) { if (props.loadRow) {
await _loadRow() await _loadRow()
@ -369,6 +403,8 @@ watch(rowId, async (nRow) => {
const showRightSections = computed(() => { const showRightSections = computed(() => {
return !isNew.value && commentsDrawer.value && isUIAllowed('commentList') return !isNew.value && commentsDrawer.value && isUIAllowed('commentList')
}) })
const preventModalStatus = computed(() => isCloseModalOpen.value || isPreventChangeModalOpen.value)
</script> </script>
<script lang="ts"> <script lang="ts">
@ -395,7 +431,7 @@ export default {
<div class="flex gap-2"> <div class="flex gap-2">
<NcButton <NcButton
v-if="props.showNextPrevIcons" v-if="props.showNextPrevIcons"
:disabled="props.firstRow" :disabled="isFirstRow"
type="secondary" type="secondary"
class="nc-prev-arrow !w-10" class="nc-prev-arrow !w-10"
@click="$emit('prev')" @click="$emit('prev')"
@ -404,7 +440,7 @@ export default {
</NcButton> </NcButton>
<NcButton <NcButton
v-if="props.showNextPrevIcons" v-if="props.showNextPrevIcons"
:disabled="props.lastRow" :disabled="islastRow"
type="secondary" type="secondary"
class="nc-next-arrow !w-10" class="nc-next-arrow !w-10"
@click="onNext" @click="onNext"
@ -423,6 +459,18 @@ export default {
<div v-if="row.rowMeta?.new" class="flex items-center truncate font-bold text-gray-800 text-xl">New Record</div> <div v-if="row.rowMeta?.new" class="flex items-center truncate font-bold text-gray-800 text-xl">New Record</div>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<NcButton
v-if="!isNew"
type="secondary"
class="!xs:hidden text-gray-700"
@click="!isNew ? copyRecordUrl() : () => {}"
>
<div v-e="['c:row-expand:copy-url']" data-testid="nc-expanded-form-copy-url" class="flex gap-2 items-center">
<component :is="iconMap.check" v-if="isRecordLinkCopied" class="cursor-pointer nc-duplicate-row" />
<component :is="iconMap.link" v-else class="cursor-pointer nc-duplicate-row" />
{{ isRecordLinkCopied ? $t('labels.copiedRecordURL') : $t('labels.copyRecordURL') }}
</div>
</NcButton>
<NcDropdown v-if="!isNew"> <NcDropdown v-if="!isNew">
<NcButton type="secondary" class="nc-expand-form-more-actions w-10"> <NcButton type="secondary" class="nc-expand-form-more-actions w-10">
<GeneralIcon icon="threeDotVertical" class="text-md text-gray-700" /> <GeneralIcon icon="threeDotVertical" class="text-md text-gray-700" />
@ -435,10 +483,10 @@ export default {
{{ $t('general.reload') }} {{ $t('general.reload') }}
</div> </div>
</NcMenuItem> </NcMenuItem>
<NcMenuItem v-if="!isNew" class="text-gray-700" @click="!isNew ? copyRecordUrl() : () => {}"> <NcMenuItem v-if="!isNew && isMobileMode" class="text-gray-700" @click="!isNew ? copyRecordUrl() : () => {}">
<div v-e="['c:row-expand:copy-url']" data-testid="nc-expanded-form-copy-url" class="flex gap-2 items-center"> <div v-e="['c:row-expand:copy-url']" data-testid="nc-expanded-form-copy-url" class="flex gap-2 items-center">
<component :is="iconMap.link" class="cursor-pointer nc-duplicate-row" /> <component :is="iconMap.link" class="cursor-pointer nc-duplicate-row" />
Copy record URL {{ $t('labels.copyRecordURL') }}
</div> </div>
</NcMenuItem> </NcMenuItem>
<NcMenuItem <NcMenuItem
@ -452,7 +500,9 @@ export default {
class="flex gap-2 items-center" class="flex gap-2 items-center"
> >
<component :is="iconMap.copy" class="cursor-pointer nc-duplicate-row" /> <component :is="iconMap.copy" class="cursor-pointer nc-duplicate-row" />
Duplicate record <span class="-ml-0.25">
{{ $t('labels.duplicateRecord') }}
</span>
</div> </div>
</NcMenuItem> </NcMenuItem>
<NcDivider v-if="isUIAllowed('dataEdit') && !isNew" /> <NcDivider v-if="isUIAllowed('dataEdit') && !isNew" />
@ -463,7 +513,9 @@ export default {
@click="!isNew && onDeleteRowClick()" @click="!isNew && onDeleteRowClick()"
> >
<component :is="iconMap.delete" data-testid="nc-expanded-form-delete" class="cursor-pointer nc-delete-row" /> <component :is="iconMap.delete" data-testid="nc-expanded-form-delete" class="cursor-pointer nc-delete-row" />
Delete record <span class="-ml-0.5">
{{ $t('activity.deleteRecord') }}
</span>
</NcMenuItem> </NcMenuItem>
</NcMenu> </NcMenu>
</template> </template>
@ -524,15 +576,15 @@ export default {
:col-id="col.id" :col-id="col.id"
:data-testid="`nc-expand-col-${col.title}`" :data-testid="`nc-expand-col-${col.title}`"
> >
<div class="flex items-start flex-row xs:(flex-col w-full) nc-expanded-cell min-h-10"> <div class="flex items-start flex-row sm:(gap-x-6) xs:(flex-col w-full) nc-expanded-cell min-h-10">
<div class="w-[12rem] xs:(w-full) mt-1.5 !h-[35px]"> <div class="w-[12rem] xs:(w-full) mt-0.25 !h-[35px]">
<LazySmartsheetHeaderVirtualCell <LazySmartsheetHeaderVirtualCell
v-if="isVirtualCol(col)" v-if="isVirtualCol(col)"
class="nc-expanded-cell-header !text-gray-600" class="nc-expanded-cell-header h-full !text-gray-500"
:column="col" :column="col"
/> />
<LazySmartsheetHeaderCell v-else class="nc-expanded-cell-header !text-gray-600" :column="col" /> <LazySmartsheetHeaderCell v-else class="nc-expanded-cell-header !text-gray-500" :column="col" />
</div> </div>
<template v-if="isLoading"> <template v-if="isLoading">
@ -706,7 +758,6 @@ export default {
<template #entity-preview> <template #entity-preview>
<span> <span>
<div class="flex flex-row items-center py-2.25 px-2.5 bg-gray-50 rounded-lg text-gray-700 mb-4"> <div class="flex flex-row items-center py-2.25 px-2.5 bg-gray-50 rounded-lg text-gray-700 mb-4">
<component :is="iconMap.record" class="nc-view-icon" />
<div class="capitalize text-ellipsis overflow-hidden select-none w-full pl-1.75 break-keep whitespace-nowrap"> <div class="capitalize text-ellipsis overflow-hidden select-none w-full pl-1.75 break-keep whitespace-nowrap">
{{ displayValue }} {{ displayValue }}
</div> </div>
@ -716,16 +767,19 @@ export default {
</GeneralDeleteModal> </GeneralDeleteModal>
<!-- Prevent unsaved change modal --> <!-- Prevent unsaved change modal -->
<NcModal v-model:visible="isPreventChangeModalOpen" size="small"> <NcModal v-model:visible="preventModalStatus" size="small">
<template #header> <div class="">
<div class="flex flex-row items-center gap-x-2">Do you want to save the changes ?</div> <div class="flex flex-row items-center gap-x-2 text-base font-bold">
</template> {{ $t('tooltip.saveChanges') }}
<div class="mt-2"> </div>
<div class="flex flex-row justify-end gap-x-2 mt-6"> <div class="flex font-medium mt-2">
<NcButton type="secondary" @click="discardPreventModal">{{ $t('general.quit') }}</NcButton> {{ $t('activity.doYouWantToSaveTheChanges') }}
</div>
<div class="flex flex-row justify-end gap-x-2 mt-5">
<NcButton type="secondary" @click="discardPreventModal">{{ $t('labels.discard') }}</NcButton>
<NcButton key="submit" type="primary" label="Rename Table" loading-label="Renaming Table" @click="saveChanges"> <NcButton key="submit" type="primary" label="Rename Table" loading-label="Renaming Table" @click="saveChanges">
{{ $t('activity.saveAndQuit') }} {{ $t('tooltip.saveChanges') }}
</NcButton> </NcButton>
</div> </div>
</div> </div>

36
packages/nc-gui/components/smartsheet/grid/index.vue

@ -68,6 +68,8 @@ const {
bulkUpdateRows, bulkUpdateRows,
bulkUpdateView, bulkUpdateView,
optimisedQuery, optimisedQuery,
islastRow,
isFirstRow,
} = useViewData(meta, view, xWhere) } = useViewData(meta, view, xWhere)
const rowHeight = computed(() => { const rowHeight = computed(() => {
@ -183,6 +185,30 @@ onMounted(() => {
if (coreWrapperRef.value) resizeObserver.observe(coreWrapperRef.value) if (coreWrapperRef.value) resizeObserver.observe(coreWrapperRef.value)
}) })
}) })
const goToNextRow = () => {
const currentIndex = getExpandedRowIndex()
/* when last index of current page is reached we should move to next page */
if (!paginationData.value.isLastPage && currentIndex === paginationData.value.pageSize) {
const nextPage = paginationData.value?.page ? paginationData.value?.page + 1 : 1
changePage(nextPage)
}
navigateToSiblingRow(NavigateDir.NEXT)
}
const goToPreviousRow = () => {
const currentIndex = getExpandedRowIndex()
/* when first index of current page is reached and then clicked back
previos page should be loaded
*/
if (!paginationData.value.isFirstPage && currentIndex === 1) {
const nextPage = paginationData.value?.page ? paginationData.value?.page - 1 : 1
changePage(nextPage)
}
navigateToSiblingRow(NavigateDir.PREV)
}
</script> </script>
<template> <template>
@ -226,7 +252,6 @@ onMounted(() => {
:expand-form="expandForm" :expand-form="expandForm"
:view-width="viewWidth" :view-width="viewWidth"
/> />
<Suspense> <Suspense>
<LazySmartsheetExpandedForm <LazySmartsheetExpandedForm
v-if="expandedFormRow && expandedFormDlg" v-if="expandedFormRow && expandedFormDlg"
@ -238,7 +263,6 @@ onMounted(() => {
@update:model-value="addRowExpandOnClose(expandedFormRow)" @update:model-value="addRowExpandOnClose(expandedFormRow)"
/> />
</Suspense> </Suspense>
<SmartsheetExpandedForm <SmartsheetExpandedForm
v-if="expandedFormOnRowIdDlg" v-if="expandedFormOnRowIdDlg"
v-model="expandedFormOnRowIdDlg" v-model="expandedFormOnRowIdDlg"
@ -248,10 +272,10 @@ onMounted(() => {
:row-id="routeQuery.rowId" :row-id="routeQuery.rowId"
:view="view" :view="view"
show-next-prev-icons show-next-prev-icons
:first-row="getExpandedRowIndex() === 0" :first-row="isFirstRow"
:last-row="getExpandedRowIndex() === data.length - 1" :last-row="islastRow"
@next="navigateToSiblingRow(NavigateDir.NEXT)" @next="goToNextRow()"
@prev="navigateToSiblingRow(NavigateDir.PREV)" @prev="goToPreviousRow()"
/> />
<Suspense> <Suspense>

2
packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts

@ -39,7 +39,7 @@ const renderIcon = (column: ColumnType, relationColumn?: ColumnType) => {
case UITypes.QrCode: case UITypes.QrCode:
return { icon: iconMap.qrCode, color: 'text-grey' } return { icon: iconMap.qrCode, color: 'text-grey' }
case UITypes.Barcode: case UITypes.Barcode:
return { icon: iconMap.qrCode, color: 'text-grey' } return { icon: iconMap.barCode, color: 'text-grey' }
case UITypes.Lookup: case UITypes.Lookup:
switch ((relationColumn?.colOptions as LinkToAnotherRecordType)?.type) { switch ((relationColumn?.colOptions as LinkToAnotherRecordType)?.type) {
case RelationTypes.MANY_TO_MANY: case RelationTypes.MANY_TO_MANY:

7
packages/nc-gui/components/smartsheet/toolbar/ColumnFilterMenu.vue

@ -1,5 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import type ColumnFilter from './ColumnFilter.vue'
import { import {
ActiveViewInj, ActiveViewInj,
IsLockedInj, IsLockedInj,
@ -11,10 +10,9 @@ import {
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useViewFilters, useViewFilters,
watch, watch,
iconMap,
} from '#imports' } from '#imports'
import FilterIcon from '~icons/nc-icons/filter'
const isLocked = inject(IsLockedInj, ref(false)) const isLocked = inject(IsLockedInj, ref(false))
const activeView = inject(ActiveViewInj, ref()) const activeView = inject(ActiveViewInj, ref())
@ -63,8 +61,7 @@ useMenuCloseOnEsc(open)
<div :class="{ 'nc-active-btn': filtersLength }"> <div :class="{ 'nc-active-btn': filtersLength }">
<a-button v-e="['c:filter']" class="nc-filter-menu-btn nc-toolbar-btn txt-sm" :disabled="isLocked"> <a-button v-e="['c:filter']" class="nc-filter-menu-btn nc-toolbar-btn txt-sm" :disabled="isLocked">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<FilterIcon class="h-4 w-4" /> <component :is="iconMap.filter" class="h-4 w-4" />
<!-- Filter --> <!-- Filter -->
<span v-if="!isMobileMode" class="text-capitalize !text-sm font-medium">{{ $t('activity.filter') }}</span> <span v-if="!isMobileMode" class="text-capitalize !text-sm font-medium">{{ $t('activity.filter') }}</span>

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

@ -2,8 +2,8 @@
import type { ColumnType, GalleryType, KanbanType } from 'nocodb-sdk' import type { ColumnType, GalleryType, KanbanType } from 'nocodb-sdk'
import { UITypes, ViewTypes, isVirtualCol } from 'nocodb-sdk' import { UITypes, ViewTypes, isVirtualCol } from 'nocodb-sdk'
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
import type { SelectProps } from 'ant-design-vue' import type { SelectProps } from 'ant-design-vue'
import FieldsIcon from '~icons/nc-icons/fields'
import { import {
ActiveViewInj, ActiveViewInj,
@ -300,7 +300,7 @@ useMenuCloseOnEsc(open)
icon="creditCard" icon="creditCard"
class="h-4 w-4" class="h-4 w-4"
/> />
<FieldsIcon v-else class="h-4 w-4" /> <component :is="iconMap.fields" v-else class="h-4 w-4" />
<!-- Fields --> <!-- Fields -->
<span v-if="!isMobileMode" class="text-capitalize text-sm font-medium"> <span v-if="!isMobileMode" class="text-capitalize text-sm font-medium">

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

@ -15,7 +15,6 @@ import {
useNuxtApp, useNuxtApp,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
} from '#imports' } from '#imports'
import GroupIcon from '~icons/nc-icons/group'
const groupingUidt = [ const groupingUidt = [
UITypes.SingleSelect, UITypes.SingleSelect,
@ -220,7 +219,7 @@ onMounted(async () => {
<div :class="{ 'nc-active-btn': groupedByColumnIds?.length }"> <div :class="{ 'nc-active-btn': groupedByColumnIds?.length }">
<a-button v-e="['c:group-by']" class="nc-group-by-menu-btn nc-toolbar-btn" :disabled="isLocked"> <a-button v-e="['c:group-by']" class="nc-group-by-menu-btn nc-toolbar-btn" :disabled="isLocked">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<GroupIcon class="h-4 w-4" /> <component :is="iconMap.group" class="h-4 w-4" />
<!-- Group By --> <!-- Group By -->
<span v-if="!isMobileMode" class="text-capitalize !text-sm font-medium">{{ $t('activity.groupBy') }}</span> <span v-if="!isMobileMode" class="text-capitalize !text-sm font-medium">{{ $t('activity.groupBy') }}</span>

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

@ -17,8 +17,6 @@ import {
watch, watch,
} from '#imports' } from '#imports'
import SortIcon from '~icons/nc-icons/sort'
const meta = inject(MetaInj, ref()) const meta = inject(MetaInj, ref())
const view = inject(ActiveViewInj, ref()) const view = inject(ActiveViewInj, ref())
const isLocked = inject(IsLockedInj, ref(false)) const isLocked = inject(IsLockedInj, ref(false))
@ -115,7 +113,7 @@ watch(open, () => {
<div :class="{ 'nc-active-btn': sorts?.length }"> <div :class="{ 'nc-active-btn': sorts?.length }">
<a-button v-e="['c:sort']" class="nc-sort-menu-btn nc-toolbar-btn" :disabled="isLocked"> <a-button v-e="['c:sort']" class="nc-sort-menu-btn nc-toolbar-btn" :disabled="isLocked">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<SortIcon class="h-4 w-4" /> <component :is="iconMap.sort" class="h-4 w-4" />
<!-- Sort --> <!-- Sort -->
<span v-if="!isMobileMode" class="text-capitalize !text-sm font-medium">{{ $t('activity.sort') }}</span> <span v-if="!isMobileMode" class="text-capitalize !text-sm font-medium">{{ $t('activity.sort') }}</span>

8
packages/nc-gui/components/virtual-cell/Links.vue

@ -64,6 +64,13 @@ const textVal = computed(() => {
} }
}) })
const toatlRecordsLinked = computed(() => {
if (isForm?.value) {
return state.value?.[colTitle.value]?.length
}
return +value?.value || 0
})
const onAttachRecord = () => { const onAttachRecord = () => {
childListDlg.value = false childListDlg.value = false
listItemsDlg.value = true listItemsDlg.value = true
@ -126,6 +133,7 @@ const localCellValue = computed<any[]>(() => {
<LazyVirtualCellComponentsListChildItems <LazyVirtualCellComponentsListChildItems
v-if="listItemsDlg || childListDlg" v-if="listItemsDlg || childListDlg"
v-model="childListDlg" v-model="childListDlg"
:items="toatlRecordsLinked"
:column="relatedTableDisplayColumn" :column="relatedTableDisplayColumn"
:cell-value="localCellValue" :cell-value="localCellValue"
@attach-record="onAttachRecord" @attach-record="onAttachRecord"

11
packages/nc-gui/components/virtual-cell/QrCode.vue

@ -11,6 +11,8 @@ const isGallery = inject(IsGalleryInj, ref(false))
const qrValue = computed(() => String(cellValue?.value)) const qrValue = computed(() => String(cellValue?.value))
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const tooManyCharsForQrCode = computed(() => qrValue?.value.length > maxNumberOfAllowedCharsForQrValue) const tooManyCharsForQrCode = computed(() => qrValue?.value.length > maxNumberOfAllowedCharsForQrValue)
const showQrCode = computed(() => qrValue?.value?.length > 0 && !tooManyCharsForQrCode.value) const showQrCode = computed(() => qrValue?.value?.length > 0 && !tooManyCharsForQrCode.value)
@ -66,15 +68,22 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us
<div v-if="tooManyCharsForQrCode" class="text-left text-wrap mt-2 text-[#e65100] text-[10px]"> <div v-if="tooManyCharsForQrCode" class="text-left text-wrap mt-2 text-[#e65100] text-[10px]">
{{ $t('labels.qrCodeValueTooLong') }} {{ $t('labels.qrCodeValueTooLong') }}
</div> </div>
<div
class="pl-2 w-full flex"
:class="{
'flex-start': isExpandedFormOpen,
'justify-center': !isExpandedFormOpen,
}"
>
<img <img
v-if="showQrCode && rowHeight" v-if="showQrCode && rowHeight"
:class="{ 'mx-auto': !isGallery }"
:style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem` }" :style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem` }"
:src="qrCode" :src="qrCode"
:alt="$t('title.qrCode')" :alt="$t('title.qrCode')"
@click="showQrModal" @click="showQrModal"
/> />
<img v-else-if="showQrCode" class="mx-auto" :src="qrCode" :alt="$t('title.qrCode')" @click="showQrModal" /> <img v-else-if="showQrCode" class="mx-auto" :src="qrCode" :alt="$t('title.qrCode')" @click="showQrModal" />
</div>
<div v-if="showEditNonEditableFieldWarning" class="text-left text-wrap mt-2 text-[#e65100] text-xs"> <div v-if="showEditNonEditableFieldWarning" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('msg.warning.nonEditableFields.computedFieldUnableToClear') }} {{ $t('msg.warning.nonEditableFields.computedFieldUnableToClear') }}
</div> </div>

12
packages/nc-gui/components/virtual-cell/barcode/Barcode.vue

@ -15,6 +15,8 @@ const tooManyCharsForBarcode = computed(() => barcodeValue.value.length > maxNum
const modalVisible = ref(false) const modalVisible = ref(false)
const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))
const showBarcodeModal = () => { const showBarcodeModal = () => {
modalVisible.value = true modalVisible.value = true
} }
@ -46,11 +48,18 @@ const rowHeight = inject(RowHeightInj, ref(undefined))
> >
<JsBarcodeWrapper v-if="showBarcode" :barcode-value="barcodeValue" :barcode-format="barcodeMeta.barcodeFormat" /> <JsBarcodeWrapper v-if="showBarcode" :barcode-value="barcodeValue" :barcode-format="barcodeMeta.barcodeFormat" />
</a-modal> </a-modal>
<div
class="flex ml-2 w-full items-center"
:class="{
'justify-start': isExpandedFormOpen,
'justify-center': !isExpandedFormOpen,
}"
>
<JsBarcodeWrapper <JsBarcodeWrapper
v-if="showBarcode && rowHeight" v-if="showBarcode && rowHeight"
:barcode-value="barcodeValue" :barcode-value="barcodeValue"
:barcode-format="barcodeMeta.barcodeFormat" :barcode-format="barcodeMeta.barcodeFormat"
:custom-style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem` }" :custom-style="{ height: rowHeight ? `${rowHeight * 1.4}rem` : `1.4rem`, width: 40 }"
@on-click-barcode="showBarcodeModal" @on-click-barcode="showBarcodeModal"
> >
<template #barcodeRenderError> <template #barcodeRenderError>
@ -71,6 +80,7 @@ const rowHeight = inject(RowHeightInj, ref(undefined))
</div> </div>
</template> </template>
</JsBarcodeWrapper> </JsBarcodeWrapper>
</div>
<div v-if="tooManyCharsForBarcode" class="text-left text-wrap mt-2 text-[#e65100] text-xs"> <div v-if="tooManyCharsForBarcode" class="text-left text-wrap mt-2 text-[#e65100] text-xs">
{{ $t('labels.barcodeValueTooLong') }} {{ $t('labels.barcodeValueTooLong') }}

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

@ -1,4 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { ColumnType } from 'nocodb-sdk'
import { UITypes, isVirtualCol } from 'nocodb-sdk' import { UITypes, isVirtualCol } from 'nocodb-sdk'
import { import {
ActiveCellInj, ActiveCellInj,
@ -41,12 +42,13 @@ const isLocked = inject(IsLockedInj, ref(false))
const { open } = useExpandedFormDetached() const { open } = useExpandedFormDetached()
function openExpandedForm() { function openExpandedForm() {
if (!readOnly.value && !isLocked.value && !readonlyProp) { const rowId = extractPkFromRow(item, relatedTableMeta.value.columns as ColumnType[])
if (!readOnly.value && !isLocked.value && !readonlyProp && rowId) {
open({ open({
isOpen: true, isOpen: true,
row: { row: item, rowMeta: {}, oldRow: { ...item } }, row: { row: item, rowMeta: {}, oldRow: { ...item } },
meta: relatedTableMeta.value, meta: relatedTableMeta.value,
loadRow: true, rowId,
useMetaFields: true, useMetaFields: true,
}) })
} }

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

@ -18,7 +18,14 @@ import {
useVModel, useVModel,
} from '#imports' } from '#imports'
const props = defineProps<{ modelValue?: boolean; cellValue: any; column: any }>() interface Prop {
modelValue?: boolean
cellValue: any
column: any
items: number
}
const props = defineProps<Prop>()
const emit = defineEmits(['update:modelValue', 'attachRecord']) const emit = defineEmits(['update:modelValue', 'attachRecord'])
@ -126,25 +133,45 @@ onKeyStroke('Escape', () => {
vModel.value = false vModel.value = false
}) })
const skeltonAmountToShow = ref(childrenListCount.value === 0 ? 10 : childrenListCount.value)
/* /*
to render same number of skelton as the number of cards to render same number of skelton as the number of cards
displayed displayed
*/ */
watch(childrenListPagination, () => { const skeltonCount = computed(() => {
if (props.items < 10 && childrenListPagination.page === 1) {
return props.items
}
if (childrenListCount.value < 10 && childrenListPagination.page === 1) { if (childrenListCount.value < 10 && childrenListPagination.page === 1) {
skeltonAmountToShow.value = childrenListCount.value === 0 ? 10 : childrenListCount.value return childrenListCount.value || 10
} }
const totalRows = Math.ceil(childrenListCount.value / 10)
const totlaRows = Math.ceil(childrenListCount.value / 10) if (totalRows === childrenListPagination.page) {
return childrenListCount.value % 10
}
return 10
})
if (totlaRows === childrenListPagination.page) { const totalItemsToShow = computed(() => {
skeltonAmountToShow.value = childrenListCount.value % 10 if (isChildrenLoading.value) {
} else { return props.items
skeltonAmountToShow.value = 10
} }
return childrenListCount.value
})
const isDataExist = computed<boolean>(() => {
return childrenList.value?.pageInfo?.totalRows || (isNew.value && state.value?.[colTitle.value]?.length)
}) })
const linkOrUnLink = (rowRef: Record<string, string>, id: string) => {
if (isPublic.value && !isForm.value) return
if (isNew.value || isChildrenListLinked.value[parseInt(id)]) {
unlinkRow(rowRef, parseInt(id))
} else {
linkRow(rowRef, parseInt(id))
}
}
</script> </script>
<template> <template>
@ -188,13 +215,12 @@ watch(childrenListPagination, () => {
</a-input> </a-input>
</div> </div>
</div> </div>
<div class="flex flex-col flex-grow nc-scrollbar-md cursor-pointer pr-1">
<div class="flex flex-col flex-grow nc-scrollbar-md"> <div v-if="isDataExist || isChildrenLoading" class="mt-2 mb-2">
<template v-if="(isNew && state?.[colTitle]?.length) || childrenList?.pageInfo?.totalRows">
<div class="cursor-pointer pr-1"> <div class="cursor-pointer pr-1">
<template v-if="isChildrenLoading"> <template v-if="isChildrenLoading">
<div <div
v-for="(x, i) in Array.from({ length: 10 })" v-for="(x, i) in Array.from({ length: skeltonCount })"
:key="i" :key="i"
class="!border-2 flex flex-row gap-2 mb-2 transition-all !rounded-xl relative !border-gray-200 hover:bg-gray-50" class="!border-2 flex flex-row gap-2 mb-2 transition-all !rounded-xl relative !border-gray-200 hover:bg-gray-50"
> >
@ -234,20 +260,11 @@ watch(childrenListPagination, () => {
:is-linked="childrenList?.list ? isChildrenListLinked[Number.parseInt(id)] : true" :is-linked="childrenList?.list ? isChildrenListLinked[Number.parseInt(id)] : true"
:is-loading="isChildrenListLoading[Number.parseInt(id)]" :is-loading="isChildrenListLoading[Number.parseInt(id)]"
@expand="onClick(refRow)" @expand="onClick(refRow)"
@click=" @click="linkOrUnLink(refRow, id)"
() => {
if (isPublic && !isForm) return
isNew
? unlinkRow(refRow, Number.parseInt(id))
: isChildrenListLinked[Number.parseInt(id)]
? unlinkRow(refRow, Number.parseInt(id))
: linkRow(refRow, Number.parseInt(id))
}
"
/> />
</template> </template>
</div> </div>
</template> </div>
<div v-else class="pt-1 flex flex-col gap-3 my-auto items-center justify-center text-gray-500"> <div v-else class="pt-1 flex flex-col gap-3 my-auto items-center justify-center text-gray-500">
<InboxIcon class="w-16 h-16 mx-auto" /> <InboxIcon class="w-16 h-16 mx-auto" />
<p> <p>
@ -278,8 +295,8 @@ watch(childrenListPagination, () => {
<div class="flex flex-row justify-between bg-white relative pt-1"> <div class="flex flex-row justify-between bg-white relative pt-1">
<div v-if="!isForm" class="flex items-center justify-center px-2 rounded-md text-gray-500 bg-brand-50"> <div v-if="!isForm" class="flex items-center justify-center px-2 rounded-md text-gray-500 bg-brand-50">
{{ childrenListCount || 0 }} {{ !isMobileMode ? $t('objects.records') : '' }} {{ totalItemsToShow || 0 }} {{ !isMobileMode ? $t('objects.records') : '' }}
{{ !isMobileMode && childrenListCount !== 0 ? $t('general.are') : '' }} {{ !isMobileMode && totalItemsToShow !== 0 ? $t('general.are') : '' }}
{{ $t('general.linked') }} {{ $t('general.linked') }}
</div> </div>
<div v-else class="flex items-center justify-center px-2 rounded-md text-gray-500 bg-brand-50"> <div v-else class="flex items-center justify-center px-2 rounded-md text-gray-500 bg-brand-50">

7
packages/nc-gui/components/workspace/View.vue

@ -1,6 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useTitle } from '@vueuse/core' import { useTitle } from '@vueuse/core'
import type { WorkspaceType } from 'nocodb-sdk'
const router = useRouter() const router = useRouter()
const route = router.currentRoute const route = router.currentRoute
@ -21,8 +20,6 @@ const tab = computed({
}, },
}) })
const getWorkspaceColor = (workspace: WorkspaceType) => workspace.meta?.color || stringToColor(workspace.id!)
watch( watch(
() => activeWorkspace.value?.title, () => activeWorkspace.value?.title,
(title: string) => { (title: string) => {
@ -53,9 +50,7 @@ onMounted(() => {
<template> <template>
<div v-if="activeWorkspace" class="flex flex-col nc-workspace-settings"> <div v-if="activeWorkspace" class="flex flex-col nc-workspace-settings">
<div class="flex gap-2 items-center min-w-0 p-6"> <div class="flex gap-2 items-center min-w-0 p-6">
<span class="nc-workspace-avatar !w-8 !h-8" :style="{ backgroundColor: getWorkspaceColor(activeWorkspace) }"> <GeneralWorkspaceIcon :workspace="activeWorkspace" />
{{ activeWorkspace?.title?.slice(0, 2) }}
</span>
<h1 class="text-3xl font-weight-bold tracking-[0.5px] mb-0 nc-workspace-title truncate min-w-10 capitalize"> <h1 class="text-3xl font-weight-bold tracking-[0.5px] mb-0 nc-workspace-title truncate min-w-10 capitalize">
{{ activeWorkspace?.title }} {{ activeWorkspace?.title }}
</h1> </h1>

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

@ -279,6 +279,10 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
return data return data
} }
const clearColumns = () => {
changedColumns.value = new Set()
}
const loadRow = async (rowId?: string) => { const loadRow = async (rowId?: string) => {
const record = await $api.dbTableRow.read( const record = await $api.dbTableRow.read(
NOCO, NOCO,
@ -344,6 +348,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
primaryKey, primaryKey,
saveRowAndStay, saveRowAndStay,
updateComment, updateComment,
clearColumns,
} }
}, 'expanded-form-store') }, 'expanded-form-store')

8
packages/nc-gui/composables/useMultiSelect/convertCellData.ts

@ -17,6 +17,14 @@ export default function convertCellData(
if (value === '') return null if (value === '') return null
switch (to) { switch (to) {
case UITypes.SingleLineText:
case UITypes.LongText:
// This is to remove the quotes added from LongText
// TODO (refactor): remove this when we have a better way to handle this
if (value.match(/^".*"$/)) {
return value.slice(1, -1)
}
return value
case UITypes.Number: { case UITypes.Number: {
const parsedNumber = Number(value) const parsedNumber = Number(value)
if (isNaN(parsedNumber)) { if (isNaN(parsedNumber)) {

4
packages/nc-gui/composables/useMultiSelect/index.ts

@ -184,7 +184,7 @@ export function useMultiSelect(
} }
if (columnObj.uidt === UITypes.LongText) { if (columnObj.uidt === UITypes.LongText) {
textToCopy = `"${textToCopy.replace(/\"/g, '""')}"` textToCopy = `"${textToCopy.replace(/"/g, '\\"')}"`
} }
return textToCopy return textToCopy
@ -202,7 +202,7 @@ export function useMultiSelect(
const value = valueToCopy(row, col) const value = valueToCopy(row, col)
copyRow += `<td>${value}</td>` copyRow += `<td>${value}</td>`
text = `${text}${value}${cols.length - 1 !== i ? '\t' : ''}` text = `${text}${value}${cols.length - 1 !== i ? '\t' : ''}`
jsonRow.push(col.uidt === UITypes.LongText ? value.replace(/^"/, '').replace(/"$/, '').replace(/""/g, '"') : value) jsonRow.push(value)
}) })
html += `${copyRow}</tr>` html += `${copyRow}</tr>`
if (rows.length - 1 !== i) { if (rows.length - 1 !== i) {

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

@ -99,6 +99,16 @@ export function useViewData(
}, },
}) })
const islastRow = computed(() => {
const currentIndex = getExpandedRowIndex()
return paginationData.value?.isLastPage && currentIndex === formattedData.value.length - 1
})
const isFirstRow = computed(() => {
const currentIndex = getExpandedRowIndex()
return paginationData.value?.isFirstPage && currentIndex === 0
})
const queryParams = computed(() => ({ const queryParams = computed(() => ({
offset: ((paginationData.value.page ?? 0) - 1) * (paginationData.value.pageSize ?? appInfoDefaultLimit), offset: ((paginationData.value.page ?? 0) - 1) * (paginationData.value.pageSize ?? appInfoDefaultLimit),
limit: paginationData.value.pageSize ?? appInfoDefaultLimit, limit: paginationData.value.pageSize ?? appInfoDefaultLimit,
@ -303,6 +313,8 @@ export function useViewData(
} }
const navigateToSiblingRow = async (dir: NavigateDir) => { const navigateToSiblingRow = async (dir: NavigateDir) => {
console.log('test')
const expandedRowIndex = getExpandedRowIndex() const expandedRowIndex = getExpandedRowIndex()
// calculate next row index based on direction // calculate next row index based on direction
@ -378,5 +390,7 @@ export function useViewData(
navigateToSiblingRow, navigateToSiblingRow,
getExpandedRowIndex, getExpandedRowIndex,
optimisedQuery, optimisedQuery,
islastRow,
isFirstRow,
} }
} }

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

@ -388,6 +388,7 @@
} }
}, },
"labels": { "labels": {
"tokenLimit": "Only one token per user is allowed",
"duplicateAttachment": "File with name {filename} already attached", "duplicateAttachment": "File with name {filename} already attached",
"toAddress": "To Address", "toAddress": "To Address",
"subject": "Subject", "subject": "Subject",
@ -396,6 +397,9 @@
"headerName": "Header Name", "headerName": "Header Name",
"icon": "Icon", "icon": "Icon",
"max": "Max", "max": "Max",
"copiedRecordURL": "Copied Record URL",
"copyRecordURL": "Copy Record URL",
"duplicateRecord": "Duplicate record",
"binaryEncodingFormat": "Binary encoding format", "binaryEncodingFormat": "Binary encoding format",
"syntax": "Syntax", "syntax": "Syntax",
"examples": "Examples", "examples": "Examples",
@ -605,6 +609,7 @@
"newSource": "New Data Source", "newSource": "New Data Source",
"newWebhook": "New Webhook", "newWebhook": "New Webhook",
"enablePublicAccess": "Enable Public Access", "enablePublicAccess": "Enable Public Access",
"doYouWantToSaveTheChanges": "Do you want to save the changes ?",
"editingAccess": "Editing access", "editingAccess": "Editing access",
"enabledPublicViewing": "Enable public viewing", "enabledPublicViewing": "Enable public viewing",
"restrictAccessWithPassword": "Restrict access with password", "restrictAccessWithPassword": "Restrict access with password",

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

@ -112,7 +112,9 @@ export default defineNuxtConfig({
compiler: 'vue3', compiler: 'vue3',
defaultClass: 'nc-icon', defaultClass: 'nc-icon',
customCollections: { customCollections: {
'nc-icons': FileSystemIconLoader('./assets/nc-icons', (svg) => svg.replace(/^<svg /, '<svg stroke="currentColor" ')), 'nc-icons': FileSystemIconLoader('./assets/nc-icons', (svg) =>
svg.replace(/^<svg (?!=\s*data-ignore)/, '<svg stroke="currentColor" '),
),
}, },
}), }),
Components({ Components({

2
packages/nc-gui/package.json

@ -55,7 +55,7 @@
"emoji-mart-vue-fast": "^15.0.0", "emoji-mart-vue-fast": "^15.0.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"fuse.js": "^6.6.2", "fuse.js": "^6.6.2",
"httpsnippet": "^3.0.1", "httpsnippet": "^2.0.0",
"jsbarcode": "^3.11.5", "jsbarcode": "^3.11.5",
"jsep": "^1.3.6", "jsep": "^1.3.6",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",

5
packages/nc-gui/store/views.ts

@ -6,7 +6,9 @@ export const useViewsStore = defineStore('viewsStore', () => {
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const router = useRouter() const router = useRouter()
const recentViews = ref<any>([]) const recentViews = computed(() => [])
const allRecentViews = ref<any>([])
const route = router.currentRoute const route = router.currentRoute
const tablesStore = useTablesStore() const tablesStore = useTablesStore()
@ -237,6 +239,7 @@ export const useViewsStore = defineStore('viewsStore', () => {
isPaginationLoading, isPaginationLoading,
loadViews, loadViews,
recentViews, recentViews,
allRecentViews,
views, views,
activeView, activeView,
openedViewsTab, openedViewsTab,

15
packages/nc-gui/utils/iconUtils.ts

@ -40,7 +40,6 @@ import PlusSquare from '~icons/nc-icons/plus-square'
import MobileShare from '~icons/nc-icons/share' import MobileShare from '~icons/nc-icons/share'
import PhLayout from '~icons/ph/layout' import PhLayout from '~icons/ph/layout'
import Delete from '~icons/material-symbols/delete-outline-rounded' import Delete from '~icons/material-symbols/delete-outline-rounded'
import CiFilter from '~icons/mdi/filter-outline'
import Minus from '~icons/material-symbols/remove-rounded' import Minus from '~icons/material-symbols/remove-rounded'
import Code from '~icons/material-symbols/code-rounded' import Code from '~icons/material-symbols/code-rounded'
import Palette from '~icons/material-symbols/palette-outline' import Palette from '~icons/material-symbols/palette-outline'
@ -92,6 +91,7 @@ import Project from '~icons/nc-icons/project'
import LookupIcon from '~icons/nc-icons/lookup' import LookupIcon from '~icons/nc-icons/lookup'
// Roles // Roles
import SuperAdmin from '~icons/nc-icons/super-admin'
import Owner from '~icons/nc-icons/owner' import Owner from '~icons/nc-icons/owner'
import Creator from '~icons/nc-icons/creator' import Creator from '~icons/nc-icons/creator'
import Editor from '~icons/nc-icons/editor' import Editor from '~icons/nc-icons/editor'
@ -99,6 +99,12 @@ import Commentor from '~icons/nc-icons/commentor'
import Viewer from '~icons/nc-icons/viewer' import Viewer from '~icons/nc-icons/viewer'
import NoAccess from '~icons/nc-icons/no-access' import NoAccess from '~icons/nc-icons/no-access'
// toolbar
import Fields from '~icons/nc-icons/fields'
import Filter from '~icons/nc-icons/filter'
import Group from '~icons/nc-icons/group'
import Sort from '~icons/nc-icons/sort'
// keep it for reference // keep it for reference
// todo: remove it after all icons are migrated // todo: remove it after all icons are migrated
/* export const iconMapOld = { /* export const iconMapOld = {
@ -247,6 +253,10 @@ import NoAccess from '~icons/nc-icons/no-access'
} as const */ } as const */
export const iconMap = { export const iconMap = {
sort: Sort,
group: Group,
filter: Filter,
fields: Fields,
mm: ManytoManyIcon, mm: ManytoManyIcon,
hm: HasManyIcon, hm: HasManyIcon,
bt: BelongsToIcon, bt: BelongsToIcon,
@ -289,7 +299,6 @@ export const iconMap = {
viewList: h('span', { class: 'material-symbols' }, 'view_list'), viewList: h('span', { class: 'material-symbols' }, 'view_list'),
cloud: h('span', { class: 'material-symbols' }, 'cloud'), cloud: h('span', { class: 'material-symbols' }, 'cloud'),
apiAndSupport: h('span', { class: 'material-symbols' }, 'api'), apiAndSupport: h('span', { class: 'material-symbols' }, 'api'),
sort: h('span', { class: 'material-symbols', style: { transform: 'scaleY(-1)' } }, 'sort'),
translate: h('span', { class: 'material-symbols' }, 'translate'), translate: h('span', { class: 'material-symbols' }, 'translate'),
preview: h('span', { class: 'material-symbols' }, 'visibility'), preview: h('span', { class: 'material-symbols' }, 'visibility'),
link: h('span', { class: 'material-symbols' }, 'link'), link: h('span', { class: 'material-symbols' }, 'link'),
@ -405,7 +414,6 @@ export const iconMap = {
view: h('span', { class: 'material-symbols' }, 'visibility'), view: h('span', { class: 'material-symbols' }, 'visibility'),
// rowHeight: h('span', { class: 'material-symbols' }, 'height'), // rowHeight: h('span', { class: 'material-symbols' }, 'height'),
rowHeight: h(PhSplitVerticalThin, { style: { fontSize: '14px' } }), rowHeight: h(PhSplitVerticalThin, { style: { fontSize: '14px' } }),
filter: CiFilter,
closeCircle: h('span', { class: 'material-symbols' }, 'cancel'), closeCircle: h('span', { class: 'material-symbols' }, 'cancel'),
closeBox: h('span', { class: 'material-symbols' }, 'close'), closeBox: h('span', { class: 'material-symbols' }, 'close'),
close: MSCloseRounded, close: MSCloseRounded,
@ -439,6 +447,7 @@ export const iconMap = {
role_editor: Editor, role_editor: Editor,
role_commenter: Commentor, role_commenter: Commentor,
role_viewer: Viewer, role_viewer: Viewer,
role_super: SuperAdmin,
role_no_access: NoAccess, role_no_access: NoAccess,
commentHere: NcCommentHere, commentHere: NcCommentHere,
} }

12
packages/nc-gui/windi.config.ts

@ -186,6 +186,18 @@ export default defineConfig({
800: '#654c17', 800: '#654c17',
900: '#32260c', 900: '#32260c',
}, },
maroon: {
50: '#FFF0F7',
100: '#FFCFE6',
200: '#FFABD2',
300: '#EC7DB1',
400: '#D45892',
500: '#B33771',
600: '#9D255D',
700: '#801044',
800: '#690735',
900: '#42001F',
},
primary: 'rgba(var(--color-primary), var(--tw-bg-opacity))', primary: 'rgba(var(--color-primary), var(--tw-bg-opacity))',
accent: 'rgba(var(--color-accent), var(--tw-bg-opacity))', accent: 'rgba(var(--color-accent), var(--tw-bg-opacity))',

4
packages/nocodb-sdk/src/lib/enums.ts

@ -188,7 +188,7 @@ export const RoleColors = {
[ProjectRoles.EDITOR]: 'green', [ProjectRoles.EDITOR]: 'green',
[ProjectRoles.COMMENTER]: 'orange', [ProjectRoles.COMMENTER]: 'orange',
[ProjectRoles.VIEWER]: 'yellow', [ProjectRoles.VIEWER]: 'yellow',
[OrgUserRoles.SUPER_ADMIN]: 'purple', [OrgUserRoles.SUPER_ADMIN]: 'maroon',
[ProjectRoles.NO_ACCESS]: 'red', [ProjectRoles.NO_ACCESS]: 'red',
[OrgUserRoles.CREATOR]: 'blue', [OrgUserRoles.CREATOR]: 'blue',
[OrgUserRoles.VIEWER]: 'yellow', [OrgUserRoles.VIEWER]: 'yellow',
@ -223,7 +223,7 @@ export const RoleIcons = {
[ProjectRoles.COMMENTER]: 'role_commenter', [ProjectRoles.COMMENTER]: 'role_commenter',
[ProjectRoles.VIEWER]: 'role_viewer', [ProjectRoles.VIEWER]: 'role_viewer',
[ProjectRoles.NO_ACCESS]: 'role_no_access', [ProjectRoles.NO_ACCESS]: 'role_no_access',
[OrgUserRoles.SUPER_ADMIN]: 'role_owner', [OrgUserRoles.SUPER_ADMIN]: 'role_super',
[OrgUserRoles.CREATOR]: 'role_creator', [OrgUserRoles.CREATOR]: 'role_creator',
[OrgUserRoles.VIEWER]: 'role_viewer', [OrgUserRoles.VIEWER]: 'role_viewer',
}; };

2
packages/nocodb/src/db/BaseModelSqlv2.ts

@ -3458,7 +3458,7 @@ class BaseModelSqlv2 {
} }
public async afterDelete(data: any, _trx: any, req): Promise<void> { public async afterDelete(data: any, _trx: any, req): Promise<void> {
const id = req?.params?.id; const id = this._extractPksValues(data);
await Audit.insert({ await Audit.insert({
fk_model_id: this.model.id, fk_model_id: this.model.id,
row_id: id, row_id: id,

6
packages/nocodb/src/db/sql-client/lib/sqlite/SqliteClient.ts

@ -2090,7 +2090,7 @@ class SqliteClient extends KnexClient {
addNewColumnQuery += addNewColumnQuery +=
n.dtxp && n.dt !== 'text' ? `(${this.genRaw(n.dtxp)})` : ''; n.dtxp && n.dt !== 'text' ? `(${this.genRaw(n.dtxp)})` : '';
addNewColumnQuery += n.cdf addNewColumnQuery += n.cdf
? ` DEFAULT ${this.sanitiseDefaultValue(n.cdf)}` ? ` DEFAULT ${this.genValue(n.cdf)}`
: !n.rqd : !n.rqd
? ' ' ? ' '
: ` DEFAULT ''`; : ` DEFAULT ''`;
@ -2122,7 +2122,7 @@ class SqliteClient extends KnexClient {
shouldSanitize, shouldSanitize,
); );
query += n.dtxp && n.dt !== 'text' ? `(${this.genRaw(n.dtxp)})` : ''; query += n.dtxp && n.dt !== 'text' ? `(${this.genRaw(n.dtxp)})` : '';
query += n.cdf ? ` DEFAULT ${this.sanitiseDefaultValue(n.cdf)}` : ' '; query += n.cdf ? ` DEFAULT ${this.genValue(n.cdf)}` : ' ';
query += n.rqd ? ` NOT NULL` : ' '; query += n.rqd ? ` NOT NULL` : ' ';
} else if (change === 1) { } else if (change === 1) {
shouldSanitize = true; shouldSanitize = true;
@ -2133,7 +2133,7 @@ class SqliteClient extends KnexClient {
); );
query += n.dtxp && n.dt !== 'text' ? `(${this.genRaw(n.dtxp)})` : ''; query += n.dtxp && n.dt !== 'text' ? `(${this.genRaw(n.dtxp)})` : '';
query += n.cdf query += n.cdf
? ` DEFAULT ${this.sanitiseDefaultValue(n.cdf)}` ? ` DEFAULT ${this.genValue(n.cdf)}`
: !n.rqd : !n.rqd
? ' ' ? ' '
: ` DEFAULT ''`; : ` DEFAULT ''`;

8
packages/nocodb/src/helpers/catchError.ts

@ -415,6 +415,8 @@ export default function (
return res.status(400).json({ msg: e.message, errors: e.errors }); return res.status(400).json({ msg: e.message, errors: e.errors });
} else if (e instanceof UnprocessableEntity) { } else if (e instanceof UnprocessableEntity) {
return res.status(422).json({ msg: e.message }); return res.status(422).json({ msg: e.message });
} else if (e instanceof NotAllowed) {
return res.status(405).json({ msg: e.message });
} }
next(e); next(e);
} }
@ -423,6 +425,8 @@ export default function (
export class BadRequest extends Error {} export class BadRequest extends Error {}
export class NotAllowed extends Error {}
export class Unauthorized extends Error {} export class Unauthorized extends Error {}
export class Forbidden extends Error {} export class Forbidden extends Error {}
@ -476,4 +480,8 @@ export class NcError {
static unprocessableEntity(message = 'Unprocessable entity') { static unprocessableEntity(message = 'Unprocessable entity') {
throw new UnprocessableEntity(message); throw new UnprocessableEntity(message);
} }
static notAllowed(message = 'Not allowed') {
throw new NotAllowed(message);
}
} }

5
packages/nocodb/src/modules/jobs/jobs.module.ts

@ -1,4 +1,4 @@
import { Module } from '@nestjs/common'; import { forwardRef, Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
// Jobs // Jobs
@ -34,7 +34,7 @@ import { GlobalModule } from '~/modules/global/global.module';
@Module({ @Module({
imports: [ imports: [
GlobalModule, forwardRef(() => GlobalModule),
DatasModule, DatasModule,
MetasModule, MetasModule,
...(process.env.NC_REDIS_JOB_URL ...(process.env.NC_REDIS_JOB_URL
@ -80,5 +80,6 @@ import { GlobalModule } from '~/modules/global/global.module';
SourceCreateProcessor, SourceCreateProcessor,
SourceDeleteProcessor, SourceDeleteProcessor,
], ],
exports: ['JobsService'],
}) })
export class JobsModule {} export class JobsModule {}

2
packages/nocodb/src/services/api-tokens.service.ts

@ -9,7 +9,7 @@ import { ApiToken } from '~/models';
@Injectable() @Injectable()
export class ApiTokensService { export class ApiTokensService {
constructor(private readonly appHooksService: AppHooksService) {} constructor(protected readonly appHooksService: AppHooksService) {}
async apiTokenList(param: { userId: string }) { async apiTokenList(param: { userId: string }) {
return await ApiToken.list(param.userId); return await ApiToken.list(param.userId);

63
packages/nocodb/src/services/columns.service.ts

@ -303,9 +303,14 @@ export class ColumnsService {
); );
} }
} else if ( } else if (
[UITypes.SingleLineText, UITypes.LongText].includes(column.uidt) [
UITypes.SingleLineText,
UITypes.Email,
UITypes.PhoneNumber,
UITypes.URL,
].includes(column.uidt)
) { ) {
// SingleLineText/LongText to SingleSelect/MultiSelect // Text to SingleSelect/MultiSelect
const dbDriver = await reuseOrSave('dbDriver', reuse, async () => const dbDriver = await reuseOrSave('dbDriver', reuse, async () =>
NcConnectionMgrv2.get(source), NcConnectionMgrv2.get(source),
); );
@ -371,12 +376,22 @@ export class ColumnsService {
); );
if (colBody.cdf) { if (colBody.cdf) {
if (colBody.uidt === UITypes.SingleSelect) { if (colBody.uidt === UITypes.SingleSelect) {
try {
if (!optionTitles.includes(colBody.cdf.replace(/'/g, "''"))) { if (!optionTitles.includes(colBody.cdf.replace(/'/g, "''"))) {
NcError.badRequest( NcError.badRequest(
`Default value '${colBody.cdf}' is not a select option.`, `Default value '${colBody.cdf}' is not a select option.`,
); );
} }
} catch (e) {
colBody.cdf = colBody.cdf.replace(/^'/, '').replace(/'$/, '');
if (!optionTitles.includes(colBody.cdf.replace(/'/g, "''"))) {
NcError.badRequest(
`Default value '${colBody.cdf}' is not a select option.`,
);
}
}
} else { } else {
try {
for (const cdf of colBody.cdf.split(',')) { for (const cdf of colBody.cdf.split(',')) {
if (!optionTitles.includes(cdf.replace(/'/g, "''"))) { if (!optionTitles.includes(cdf.replace(/'/g, "''"))) {
NcError.badRequest( NcError.badRequest(
@ -384,10 +399,25 @@ export class ColumnsService {
); );
} }
} }
} catch (e) {
colBody.cdf = colBody.cdf.replace(/^'/, '').replace(/'$/, '');
for (const cdf of colBody.cdf.split(',')) {
if (!optionTitles.includes(cdf.replace(/'/g, "''"))) {
NcError.badRequest(
`Default value '${cdf}' is not a select option.`,
);
}
}
}
} }
// handle single quote for default value // handle single quote for default value
if (driverType === 'mysql' || driverType === 'mysql2') { if (
driverType === 'mysql' ||
driverType === 'mysql2' ||
driverType === 'pg' ||
driverType === 'sqlite3'
) {
colBody.cdf = colBody.cdf.replace(/'/g, "'"); colBody.cdf = colBody.cdf.replace(/'/g, "'");
} else { } else {
colBody.cdf = colBody.cdf.replace(/'/g, "''"); colBody.cdf = colBody.cdf.replace(/'/g, "''");
@ -1142,12 +1172,31 @@ export class ColumnsService {
// Handle default values // Handle default values
if (colBody.cdf) { if (colBody.cdf) {
if (colBody.uidt === UITypes.SingleSelect) { if (colBody.uidt === UITypes.SingleSelect) {
try {
if (!optionTitles.includes(colBody.cdf.replace(/'/g, "''"))) { if (!optionTitles.includes(colBody.cdf.replace(/'/g, "''"))) {
NcError.badRequest( NcError.badRequest(
`Default value '${colBody.cdf}' is not a select option.`, `Default value '${colBody.cdf}' is not a select option.`,
); );
} }
} catch (e) {
colBody.cdf = colBody.cdf.replace(/^'/, '').replace(/'$/, '');
if (!optionTitles.includes(colBody.cdf.replace(/'/g, "''"))) {
NcError.badRequest(
`Default value '${colBody.cdf}' is not a select option.`,
);
}
}
} else { } else {
try {
for (const cdf of colBody.cdf.split(',')) {
if (!optionTitles.includes(cdf.replace(/'/g, "''"))) {
NcError.badRequest(
`Default value '${cdf}' is not a select option.`,
);
}
}
} catch (e) {
colBody.cdf = colBody.cdf.replace(/^'/, '').replace(/'$/, '');
for (const cdf of colBody.cdf.split(',')) { for (const cdf of colBody.cdf.split(',')) {
if (!optionTitles.includes(cdf.replace(/'/g, "''"))) { if (!optionTitles.includes(cdf.replace(/'/g, "''"))) {
NcError.badRequest( NcError.badRequest(
@ -1156,9 +1205,15 @@ export class ColumnsService {
} }
} }
} }
}
// handle single quote for default value // handle single quote for default value
if (driverType === 'mysql' || driverType === 'mysql2') { if (
driverType === 'mysql' ||
driverType === 'mysql2' ||
driverType === 'pg' ||
driverType === 'sqlite3'
) {
colBody.cdf = colBody.cdf.replace(/'/g, "'"); colBody.cdf = colBody.cdf.replace(/'/g, "'");
} else { } else {
colBody.cdf = colBody.cdf.replace(/'/g, "''"); colBody.cdf = colBody.cdf.replace(/'/g, "''");

2
packages/nocodb/src/services/org-tokens.service.ts

@ -10,7 +10,7 @@ import { ApiToken } from '~/models';
@Injectable() @Injectable()
export class OrgTokensService { export class OrgTokensService {
constructor(private readonly appHooksService: AppHooksService) {} constructor(protected readonly appHooksService: AppHooksService) {}
async apiTokenList(param: { user: User; query: any }) { async apiTokenList(param: { user: User; query: any }) {
const fk_user_id = param.user.id; const fk_user_id = param.user.id;

320
pnpm-lock.yaml

@ -38,7 +38,7 @@ importers:
version: 4.1.1(vue@3.3.4) version: 4.1.1(vue@3.3.4)
'@pinia/nuxt': '@pinia/nuxt':
specifier: ^0.4.11 specifier: ^0.4.11
version: 0.4.11(vue@3.3.4) version: 0.4.11(typescript@5.2.2)(vue@3.3.4)
'@vue-flow/additional-components': '@vue-flow/additional-components':
specifier: ^1.2.0 specifier: ^1.2.0
version: 1.2.0(@vue-flow/core@1.3.0)(vue@3.3.4) version: 1.2.0(@vue-flow/core@1.3.0)(vue@3.3.4)
@ -85,8 +85,8 @@ importers:
specifier: ^6.6.2 specifier: ^6.6.2
version: 6.6.2 version: 6.6.2
httpsnippet: httpsnippet:
specifier: ^3.0.1 specifier: ^2.0.0
version: 3.0.1 version: 2.0.0(mkdirp@2.1.3)
jsbarcode: jsbarcode:
specifier: ^3.11.5 specifier: ^3.11.5
version: 3.11.5 version: 3.11.5
@ -122,7 +122,7 @@ importers:
version: 1.0.2 version: 1.0.2
pinia: pinia:
specifier: ^2.1.4 specifier: ^2.1.4
version: 2.1.4(vue@3.3.4) version: 2.1.4(typescript@5.2.2)(vue@3.3.4)
qrcode: qrcode:
specifier: ^1.5.1 specifier: ^1.5.1
version: 1.5.1 version: 1.5.1
@ -192,7 +192,7 @@ importers:
devDependencies: devDependencies:
'@antfu/eslint-config': '@antfu/eslint-config':
specifier: ^0.26.0 specifier: ^0.26.0
version: 0.26.0(eslint@8.33.0) version: 0.26.0(eslint@8.33.0)(typescript@5.2.2)
'@esbuild-plugins/node-modules-polyfill': '@esbuild-plugins/node-modules-polyfill':
specifier: ^0.2.2 specifier: ^0.2.2
version: 0.2.2(esbuild@0.19.2) version: 0.2.2(esbuild@0.19.2)
@ -342,7 +342,7 @@ importers:
version: 6.0.3 version: 6.0.3
nuxt: nuxt:
specifier: ^3.6.5 specifier: ^3.6.5
version: 3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4) version: 3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4)(typescript@5.2.2)
nuxt-windicss: nuxt-windicss:
specifier: ^2.6.1 specifier: ^2.6.1
version: 2.6.1(vite@4.4.9) version: 2.6.1(vite@4.4.9)
@ -354,7 +354,7 @@ importers:
version: 1.63.4 version: 1.63.4
ts-loader: ts-loader:
specifier: ^9.4.4 specifier: ^9.4.4
version: 9.4.4(webpack@5.88.2) version: 9.4.4(typescript@5.2.2)(webpack@5.88.2)
unplugin-icons: unplugin-icons:
specifier: ^0.14.15 specifier: ^0.14.15
version: 0.14.15(@vue/compiler-sfc@3.2.37) version: 0.14.15(@vue/compiler-sfc@3.2.37)
@ -1113,20 +1113,20 @@ packages:
/@ant-design/icons-vue@6.1.0(vue@3.3.4): /@ant-design/icons-vue@6.1.0(vue@3.3.4):
resolution: {integrity: sha512-EX6bYm56V+ZrKN7+3MT/ubDkvJ5rK/O2t380WFRflDcVFgsvl3NLH7Wxeau6R8DbrO5jWR6DSTC3B6gYFp77AA==} resolution: {integrity: sha512-EX6bYm56V+ZrKN7+3MT/ubDkvJ5rK/O2t380WFRflDcVFgsvl3NLH7Wxeau6R8DbrO5jWR6DSTC3B6gYFp77AA==}
peerDependencies: peerDependencies:
vue: latest vue: '>=3.0.3'
dependencies: dependencies:
'@ant-design/colors': 6.0.0 '@ant-design/colors': 6.0.0
'@ant-design/icons-svg': 4.3.1 '@ant-design/icons-svg': 4.3.1
vue: 3.3.4 vue: 3.3.4
dev: false dev: false
/@antfu/eslint-config-basic@0.26.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0): /@antfu/eslint-config-basic@0.26.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0)(typescript@5.2.2):
resolution: {integrity: sha512-l/Omn5HuI3VgHPGJ13pqdGEdF7D7HSzN85KF0HaR/jm24QzL2kkFeZJuglv+YSXyVDI1eAbzF52TlJUz1cxqzQ==} resolution: {integrity: sha512-l/Omn5HuI3VgHPGJ13pqdGEdF7D7HSzN85KF0HaR/jm24QzL2kkFeZJuglv+YSXyVDI1eAbzF52TlJUz1cxqzQ==}
peerDependencies: peerDependencies:
eslint: '>=7.4.0' eslint: '>=7.4.0'
dependencies: dependencies:
eslint: 8.33.0 eslint: 8.33.0
eslint-plugin-antfu: 0.26.0(eslint@8.33.0) eslint-plugin-antfu: 0.26.0(eslint@8.33.0)(typescript@5.2.2)
eslint-plugin-eslint-comments: 3.2.0(eslint@8.33.0) eslint-plugin-eslint-comments: 3.2.0(eslint@8.33.0)
eslint-plugin-html: 7.1.0 eslint-plugin-html: 7.1.0
eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0)(eslint@8.33.0) eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0)(eslint@8.33.0)
@ -1146,12 +1146,12 @@ packages:
- typescript - typescript
dev: true dev: true
/@antfu/eslint-config-react@0.26.0(eslint@8.33.0): /@antfu/eslint-config-react@0.26.0(eslint@8.33.0)(typescript@5.2.2):
resolution: {integrity: sha512-QkRhzivKAtTVtLMFXt7Sl+hBM/LCAU+EUpIxTqw/h0uufYmzIrbdVwkxPntZaXl5p/qLZqQOZG3Iu7oek+MNeA==} resolution: {integrity: sha512-QkRhzivKAtTVtLMFXt7Sl+hBM/LCAU+EUpIxTqw/h0uufYmzIrbdVwkxPntZaXl5p/qLZqQOZG3Iu7oek+MNeA==}
peerDependencies: peerDependencies:
eslint: '>=7.4.0' eslint: '>=7.4.0'
dependencies: dependencies:
'@antfu/eslint-config-ts': 0.26.0(eslint@8.33.0) '@antfu/eslint-config-ts': 0.26.0(eslint@8.33.0)(typescript@5.2.2)
eslint: 8.33.0 eslint: 8.33.0
eslint-plugin-react: 7.33.2(eslint@8.33.0) eslint-plugin-react: 7.33.2(eslint@8.33.0)
transitivePeerDependencies: transitivePeerDependencies:
@ -1161,28 +1161,29 @@ packages:
- typescript - typescript
dev: true dev: true
/@antfu/eslint-config-ts@0.26.0(eslint@8.33.0): /@antfu/eslint-config-ts@0.26.0(eslint@8.33.0)(typescript@5.2.2):
resolution: {integrity: sha512-LnJgBP+XAsGijfmjAZk6BDxlt7UYGiXyCIviLDgg8bmPaLAX3I+i0wmj9DwhDIYeXForeP/Io+dBT63k5BheBw==} resolution: {integrity: sha512-LnJgBP+XAsGijfmjAZk6BDxlt7UYGiXyCIviLDgg8bmPaLAX3I+i0wmj9DwhDIYeXForeP/Io+dBT63k5BheBw==}
peerDependencies: peerDependencies:
eslint: '>=7.4.0' eslint: '>=7.4.0'
typescript: latest typescript: '>=3.9'
dependencies: dependencies:
'@antfu/eslint-config-basic': 0.26.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0) '@antfu/eslint-config-basic': 0.26.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0)(typescript@5.2.2)
'@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0) '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0)(typescript@5.2.2)
'@typescript-eslint/parser': 5.62.0(eslint@8.33.0) '@typescript-eslint/parser': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
eslint: 8.33.0 eslint: 8.33.0
typescript: 5.2.2
transitivePeerDependencies: transitivePeerDependencies:
- eslint-import-resolver-typescript - eslint-import-resolver-typescript
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
- supports-color - supports-color
dev: true dev: true
/@antfu/eslint-config-vue@0.26.0(eslint@8.33.0): /@antfu/eslint-config-vue@0.26.0(eslint@8.33.0)(typescript@5.2.2):
resolution: {integrity: sha512-a4ov8vzOzV5WPBSXIwg1oDnpSEOaxpvqz9cZK/lwqDsS+tk2QAI6yfcxwbhMIDUy3pA3u9B62K9tP+9HhqncIw==} resolution: {integrity: sha512-a4ov8vzOzV5WPBSXIwg1oDnpSEOaxpvqz9cZK/lwqDsS+tk2QAI6yfcxwbhMIDUy3pA3u9B62K9tP+9HhqncIw==}
peerDependencies: peerDependencies:
eslint: '>=7.4.0' eslint: '>=7.4.0'
dependencies: dependencies:
'@antfu/eslint-config-ts': 0.26.0(eslint@8.33.0) '@antfu/eslint-config-ts': 0.26.0(eslint@8.33.0)(typescript@5.2.2)
eslint: 8.33.0 eslint: 8.33.0
eslint-plugin-vue: 9.17.0(eslint@8.33.0) eslint-plugin-vue: 9.17.0(eslint@8.33.0)
transitivePeerDependencies: transitivePeerDependencies:
@ -1192,15 +1193,15 @@ packages:
- typescript - typescript
dev: true dev: true
/@antfu/eslint-config@0.26.0(eslint@8.33.0): /@antfu/eslint-config@0.26.0(eslint@8.33.0)(typescript@5.2.2):
resolution: {integrity: sha512-3f+JKBYPZZot5cdS4gkZxuiytUTfHWhsKS1UmNhqEn11G5BmzYSu1LRf0K/n10hb/u+GUtZJwKAovu6qnQBM9w==} resolution: {integrity: sha512-3f+JKBYPZZot5cdS4gkZxuiytUTfHWhsKS1UmNhqEn11G5BmzYSu1LRf0K/n10hb/u+GUtZJwKAovu6qnQBM9w==}
peerDependencies: peerDependencies:
eslint: '>=7.4.0' eslint: '>=7.4.0'
dependencies: dependencies:
'@antfu/eslint-config-react': 0.26.0(eslint@8.33.0) '@antfu/eslint-config-react': 0.26.0(eslint@8.33.0)(typescript@5.2.2)
'@antfu/eslint-config-vue': 0.26.0(eslint@8.33.0) '@antfu/eslint-config-vue': 0.26.0(eslint@8.33.0)(typescript@5.2.2)
'@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0) '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0)(typescript@5.2.2)
'@typescript-eslint/parser': 5.62.0(eslint@8.33.0) '@typescript-eslint/parser': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
eslint: 8.33.0 eslint: 8.33.0
eslint-plugin-eslint-comments: 3.2.0(eslint@8.33.0) eslint-plugin-eslint-comments: 3.2.0(eslint@8.33.0)
eslint-plugin-html: 7.1.0 eslint-plugin-html: 7.1.0
@ -3225,7 +3226,7 @@ packages:
resolution: {integrity: sha512-wmsfNHJQgSX0HFA726r+cm6ixYs+z/KLxfg1cx6xZ1PBGeZsuQCACdNdoKckyr/IH8FgIbBoIH0/6QiSbW3tEQ==} resolution: {integrity: sha512-wmsfNHJQgSX0HFA726r+cm6ixYs+z/KLxfg1cx6xZ1PBGeZsuQCACdNdoKckyr/IH8FgIbBoIH0/6QiSbW3tEQ==}
peerDependencies: peerDependencies:
'@vue/composition-api': ^1.0.0-rc.1 '@vue/composition-api': ^1.0.0-rc.1
vue: latest vue: ^2.0.0 || >=3.0.5
peerDependenciesMeta: peerDependenciesMeta:
'@vue/composition-api': '@vue/composition-api':
optional: true optional: true
@ -3239,7 +3240,7 @@ packages:
resolution: {integrity: sha512-c9X82nppYjSxjlITO6jdLLdt9HoyZzqEWpqDL2V6NJd859d6GCh/2AHeRXk+37uRJ1UdTkCuty93WOEqja8quw==} resolution: {integrity: sha512-c9X82nppYjSxjlITO6jdLLdt9HoyZzqEWpqDL2V6NJd859d6GCh/2AHeRXk+37uRJ1UdTkCuty93WOEqja8quw==}
engines: {node: '>=12'} engines: {node: '>=12'}
peerDependencies: peerDependencies:
vue: latest vue: ^3.2.0
dependencies: dependencies:
'@ctrl/tinycolor': 3.6.1 '@ctrl/tinycolor': 3.6.1
lodash-es: 4.17.21 lodash-es: 4.17.21
@ -4376,7 +4377,7 @@ packages:
/@iconify/vue@4.1.1(vue@3.3.4): /@iconify/vue@4.1.1(vue@3.3.4):
resolution: {integrity: sha512-RL85Bm/DAe8y6rT6pux7D2FJSiUEM/TPfyK7GrbAOfTSwrhvwJW+S5yijdGcmtXouA8MtuH9C7l4hiSE4mLMjg==} resolution: {integrity: sha512-RL85Bm/DAe8y6rT6pux7D2FJSiUEM/TPfyK7GrbAOfTSwrhvwJW+S5yijdGcmtXouA8MtuH9C7l4hiSE4mLMjg==}
peerDependencies: peerDependencies:
vue: latest vue: '>=3'
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
vue: 3.3.4 vue: 3.3.4
@ -5228,7 +5229,7 @@ packages:
/@nestjs/schematics@10.0.1(chokidar@3.5.3)(typescript@5.2.2): /@nestjs/schematics@10.0.1(chokidar@3.5.3)(typescript@5.2.2):
resolution: {integrity: sha512-buxpYtSwOmWyf0nUJWJCkCkYITwbOfIEKHTnGS7sDbcfaajrOFXb5pPAGD2E1CUb3C1+NkQIURPKzs0IouZTQg==} resolution: {integrity: sha512-buxpYtSwOmWyf0nUJWJCkCkYITwbOfIEKHTnGS7sDbcfaajrOFXb5pPAGD2E1CUb3C1+NkQIURPKzs0IouZTQg==}
peerDependencies: peerDependencies:
typescript: latest typescript: '>=4.8.2'
dependencies: dependencies:
'@angular-devkit/core': 16.1.0(chokidar@3.5.3) '@angular-devkit/core': 16.1.0(chokidar@3.5.3)
'@angular-devkit/schematics': 16.1.0(chokidar@3.5.3) '@angular-devkit/schematics': 16.1.0(chokidar@3.5.3)
@ -5652,11 +5653,11 @@ packages:
/@nuxt/ui-templates@1.3.1: /@nuxt/ui-templates@1.3.1:
resolution: {integrity: sha512-5gc02Pu1HycOVUWJ8aYsWeeXcSTPe8iX8+KIrhyEtEoOSkY0eMBuo0ssljB8wALuEmepv31DlYe5gpiRwkjESA==} resolution: {integrity: sha512-5gc02Pu1HycOVUWJ8aYsWeeXcSTPe8iX8+KIrhyEtEoOSkY0eMBuo0ssljB8wALuEmepv31DlYe5gpiRwkjESA==}
/@nuxt/vite-builder@3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4)(vue@3.3.4): /@nuxt/vite-builder@3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4)(typescript@5.2.2)(vue@3.3.4):
resolution: {integrity: sha512-pwSpt257ApCp3XWUs8vrC7X9QHeHUv5PbbIR3+5w0n5f95XPNOQWDJa2fTPX/H6oaRJCPYAsBPqiQhQ7qW/NZQ==} resolution: {integrity: sha512-pwSpt257ApCp3XWUs8vrC7X9QHeHUv5PbbIR3+5w0n5f95XPNOQWDJa2fTPX/H6oaRJCPYAsBPqiQhQ7qW/NZQ==}
engines: {node: ^14.18.0 || >=16.10.0} engines: {node: ^14.18.0 || >=16.10.0}
peerDependencies: peerDependencies:
vue: latest vue: ^3.3.4
dependencies: dependencies:
'@nuxt/kit': 3.6.5 '@nuxt/kit': 3.6.5
'@rollup/plugin-replace': 5.0.2(rollup@3.28.1) '@rollup/plugin-replace': 5.0.2(rollup@3.28.1)
@ -5691,7 +5692,7 @@ packages:
unplugin: 1.4.0 unplugin: 1.4.0
vite: 4.3.9(@types/node@20.3.1)(sass@1.63.4) vite: 4.3.9(@types/node@20.3.1)(sass@1.63.4)
vite-node: 0.33.0(@types/node@20.3.1)(sass@1.63.4) vite-node: 0.33.0(@types/node@20.3.1)(sass@1.63.4)
vite-plugin-checker: 0.6.2(eslint@8.33.0)(vite@4.3.9) vite-plugin-checker: 0.6.2(eslint@8.33.0)(typescript@5.2.2)(vite@4.3.9)
vue: 3.3.4 vue: 3.3.4
vue-bundle-renderer: 1.0.3 vue-bundle-renderer: 1.0.3
transitivePeerDependencies: transitivePeerDependencies:
@ -6115,11 +6116,11 @@ packages:
'@parcel/watcher-win32-x64': 2.3.0 '@parcel/watcher-win32-x64': 2.3.0
dev: true dev: true
/@pinia/nuxt@0.4.11(vue@3.3.4): /@pinia/nuxt@0.4.11(typescript@5.2.2)(vue@3.3.4):
resolution: {integrity: sha512-bhuNFngJpmBCdAqWguezNJ/oJFR7wvKieqiZrmmdmPR07XjsidAw8RLXHMZE9kUm32M9E6T057OBbG/22jERTg==} resolution: {integrity: sha512-bhuNFngJpmBCdAqWguezNJ/oJFR7wvKieqiZrmmdmPR07XjsidAw8RLXHMZE9kUm32M9E6T057OBbG/22jERTg==}
dependencies: dependencies:
'@nuxt/kit': 3.7.0 '@nuxt/kit': 3.7.0
pinia: 2.1.4(vue@3.3.4) pinia: 2.1.4(typescript@5.2.2)(vue@3.3.4)
transitivePeerDependencies: transitivePeerDependencies:
- '@vue/composition-api' - '@vue/composition-api'
- rollup - rollup
@ -7809,7 +7810,7 @@ packages:
dev: false dev: false
optional: true optional: true
/@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0): /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.33.0)(typescript@5.2.2):
resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -7821,7 +7822,7 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@eslint-community/regexpp': 4.8.0 '@eslint-community/regexpp': 4.8.0
'@typescript-eslint/parser': 5.62.0(eslint@8.33.0) '@typescript-eslint/parser': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
'@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/scope-manager': 5.62.0
'@typescript-eslint/type-utils': 5.62.0(eslint@8.33.0)(typescript@5.2.2) '@typescript-eslint/type-utils': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
'@typescript-eslint/utils': 5.62.0(eslint@8.33.0)(typescript@5.2.2) '@typescript-eslint/utils': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
@ -7832,6 +7833,7 @@ packages:
natural-compare-lite: 1.4.0 natural-compare-lite: 1.4.0
semver: 7.5.4 semver: 7.5.4
tsutils: 3.21.0(typescript@5.2.2) tsutils: 3.21.0(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
@ -7895,7 +7897,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/parser@5.62.0(eslint@8.33.0): /@typescript-eslint/parser@5.62.0(eslint@8.33.0)(typescript@5.2.2):
resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -7910,6 +7912,7 @@ packages:
'@typescript-eslint/typescript-estree': 5.62.0(typescript@5.2.2) '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.2.2)
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.33.0 eslint: 8.33.0
typescript: 5.2.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
@ -8230,7 +8233,7 @@ packages:
/@unhead/vue@1.3.9(vue@3.3.4): /@unhead/vue@1.3.9(vue@3.3.4):
resolution: {integrity: sha512-rVAsRLBc+3Y//NRmr7vmRs5yhIf65jYSvcj0V5DtDfDwql7BbGgc3VIIEvY0+EjLQuNsS5kxwm78LSPCIl/3Xw==} resolution: {integrity: sha512-rVAsRLBc+3Y//NRmr7vmRs5yhIf65jYSvcj0V5DtDfDwql7BbGgc3VIIEvY0+EjLQuNsS5kxwm78LSPCIl/3Xw==}
peerDependencies: peerDependencies:
vue: latest vue: '>=2.7 || >=3'
dependencies: dependencies:
'@unhead/schema': 1.3.9 '@unhead/schema': 1.3.9
'@unhead/shared': 1.3.9 '@unhead/shared': 1.3.9
@ -8498,7 +8501,7 @@ packages:
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies: peerDependencies:
vite: ^4.0.0 vite: ^4.0.0
vue: latest vue: ^3.0.0
dependencies: dependencies:
'@babel/core': 7.22.11 '@babel/core': 7.22.11
'@babel/plugin-transform-typescript': 7.22.11(@babel/core@7.22.11) '@babel/plugin-transform-typescript': 7.22.11(@babel/core@7.22.11)
@ -8514,7 +8517,7 @@ packages:
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies: peerDependencies:
vite: ^4.0.0 vite: ^4.0.0
vue: latest vue: ^3.2.25
dependencies: dependencies:
vite: 4.3.9(@types/node@20.3.1)(sass@1.63.4) vite: 4.3.9(@types/node@20.3.1)(sass@1.63.4)
vue: 3.3.4 vue: 3.3.4
@ -8569,7 +8572,7 @@ packages:
resolution: {integrity: sha512-a5F2y0WdPxaxTAcN7mSYVZ6A2kDSxenp+YwMt/2ldFRmCIP4jCbXEsTZfcpUe5zhlehfbyTTYbEw03w3YW24aA==} resolution: {integrity: sha512-a5F2y0WdPxaxTAcN7mSYVZ6A2kDSxenp+YwMt/2ldFRmCIP4jCbXEsTZfcpUe5zhlehfbyTTYbEw03w3YW24aA==}
peerDependencies: peerDependencies:
'@vue-flow/core': ^1.0.0 '@vue-flow/core': ^1.0.0
vue: latest vue: ^3.2.37
dependencies: dependencies:
'@types/d3-selection': 3.0.6 '@types/d3-selection': 3.0.6
'@types/d3-zoom': 3.0.4 '@types/d3-zoom': 3.0.4
@ -8582,7 +8585,7 @@ packages:
/@vue-flow/core@1.3.0(vue@3.3.4): /@vue-flow/core@1.3.0(vue@3.3.4):
resolution: {integrity: sha512-hitjBy8RTw8gixcgJ9sjfZWyI6KNyKp4ffxTz/O4ZN/7TMwunEdc3cFHuU7R6J1OEhZ+HnlMRGrXmzXiIfdJow==} resolution: {integrity: sha512-hitjBy8RTw8gixcgJ9sjfZWyI6KNyKp4ffxTz/O4ZN/7TMwunEdc3cFHuU7R6J1OEhZ+HnlMRGrXmzXiIfdJow==}
peerDependencies: peerDependencies:
vue: latest vue: ^3.2.25
dependencies: dependencies:
'@vueuse/core': 9.13.0(vue@3.3.4) '@vueuse/core': 9.13.0(vue@3.3.4)
d3-drag: 3.0.0 d3-drag: 3.0.0
@ -8597,7 +8600,7 @@ packages:
resolution: {integrity: sha512-0/2A4kWLTCNEx+DDQKLvs7zXpfjgAbGBZ58SIvDN1DjGXhG4WaIUZtgMqzA6bvc5dNN7RaOatZYubkVumwmjWA==} resolution: {integrity: sha512-0/2A4kWLTCNEx+DDQKLvs7zXpfjgAbGBZ58SIvDN1DjGXhG4WaIUZtgMqzA6bvc5dNN7RaOatZYubkVumwmjWA==}
engines: {node: '>=16.14.0'} engines: {node: '>=16.14.0'}
peerDependencies: peerDependencies:
vue: latest vue: ^2.7.0 || ^3.2.25
peerDependenciesMeta: peerDependenciesMeta:
vue: vue:
optional: true optional: true
@ -8639,7 +8642,7 @@ packages:
/@vue/compat@3.3.4(vue@3.3.4): /@vue/compat@3.3.4(vue@3.3.4):
resolution: {integrity: sha512-VwAsPqUqRJVxeLQPUC03Sa5d+T8UG2Qv4VItq74KmNvtQlRXICpa/sqq12BcyBB4Tz1U5paOEZxWCUoXkrZ9QQ==} resolution: {integrity: sha512-VwAsPqUqRJVxeLQPUC03Sa5d+T8UG2Qv4VItq74KmNvtQlRXICpa/sqq12BcyBB4Tz1U5paOEZxWCUoXkrZ9QQ==}
peerDependencies: peerDependencies:
vue: latest vue: 3.3.4
dependencies: dependencies:
'@babel/parser': 7.22.11 '@babel/parser': 7.22.11
estree-walker: 2.0.2 estree-walker: 2.0.2
@ -8762,7 +8765,7 @@ packages:
/@vue/server-renderer@3.3.4(vue@3.3.4): /@vue/server-renderer@3.3.4(vue@3.3.4):
resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==}
peerDependencies: peerDependencies:
vue: latest vue: 3.3.4
dependencies: dependencies:
'@vue/compiler-ssr': 3.3.4 '@vue/compiler-ssr': 3.3.4
'@vue/shared': 3.3.4 '@vue/shared': 3.3.4
@ -8778,7 +8781,7 @@ packages:
/@vue/test-utils@2.0.2(vue@3.3.4): /@vue/test-utils@2.0.2(vue@3.3.4):
resolution: {integrity: sha512-E2P4oXSaWDqTZNbmKZFVLrNN/siVN78YkEqs7pHryWerrlZR9bBFLWdJwRoguX45Ru6HxIflzKl4vQvwRMwm5g==} resolution: {integrity: sha512-E2P4oXSaWDqTZNbmKZFVLrNN/siVN78YkEqs7pHryWerrlZR9bBFLWdJwRoguX45Ru6HxIflzKl4vQvwRMwm5g==}
peerDependencies: peerDependencies:
vue: latest vue: ^3.0.1
dependencies: dependencies:
vue: 3.3.4 vue: 3.3.4
dev: true dev: true
@ -8816,7 +8819,7 @@ packages:
resolution: {integrity: sha512-PRRgbATMpoeUmkCEBtUeJgOwtew8s+4UsEd+Pm7MhkjL2ihCNrSqxNVtM6NFE4uP2sWnkGcZpCjPuNSxowJ1Ow==} resolution: {integrity: sha512-PRRgbATMpoeUmkCEBtUeJgOwtew8s+4UsEd+Pm7MhkjL2ihCNrSqxNVtM6NFE4uP2sWnkGcZpCjPuNSxowJ1Ow==}
peerDependencies: peerDependencies:
'@vue/composition-api': ^1.1.0 '@vue/composition-api': ^1.1.0
vue: latest vue: ^2.6.0 || ^3.2.0
peerDependenciesMeta: peerDependenciesMeta:
'@vue/composition-api': '@vue/composition-api':
optional: true optional: true
@ -8909,7 +8912,7 @@ packages:
'@vueuse/core': 10.2.1(vue@3.3.4) '@vueuse/core': 10.2.1(vue@3.3.4)
'@vueuse/metadata': 10.2.1 '@vueuse/metadata': 10.2.1
local-pkg: 0.4.3 local-pkg: 0.4.3
nuxt: 3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4) nuxt: 3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4)(typescript@5.2.2)
vue-demi: 0.14.5(vue@3.3.4) vue-demi: 0.14.5(vue@3.3.4)
transitivePeerDependencies: transitivePeerDependencies:
- '@vue/composition-api' - '@vue/composition-api'
@ -8930,7 +8933,7 @@ packages:
resolution: {integrity: sha512-rN2qd22AUl7VdBxihagWyhUNHCyVk9IpvBTTfHoLH9G7rGE552X1f+zeCfehuno0zXif13jPw+icW/wn2a0rnQ==} resolution: {integrity: sha512-rN2qd22AUl7VdBxihagWyhUNHCyVk9IpvBTTfHoLH9G7rGE552X1f+zeCfehuno0zXif13jPw+icW/wn2a0rnQ==}
peerDependencies: peerDependencies:
'@vue/composition-api': ^1.1.0 '@vue/composition-api': ^1.1.0
vue: latest vue: ^2.6.0 || ^3.2.0
peerDependenciesMeta: peerDependenciesMeta:
'@vue/composition-api': '@vue/composition-api':
optional: true optional: true
@ -9396,6 +9399,11 @@ packages:
type-fest: 0.21.3 type-fest: 0.21.3
dev: true dev: true
/ansi-regex@2.1.1:
resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==}
engines: {node: '>=0.10.0'}
dev: false
/ansi-regex@5.0.1: /ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -9405,6 +9413,11 @@ packages:
engines: {node: '>=12'} engines: {node: '>=12'}
dev: true dev: true
/ansi-styles@2.2.1:
resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==}
engines: {node: '>=0.10.0'}
dev: false
/ansi-styles@3.2.1: /ansi-styles@3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -9431,7 +9444,7 @@ packages:
resolution: {integrity: sha512-QKCAcOY5EJF0PepiVGA4X5PzUetYUvG5qALmA+2TON40pc2+brOEiVTwr3kjF9N+f7q4MpyiLPu4pIErwoajOQ==} resolution: {integrity: sha512-QKCAcOY5EJF0PepiVGA4X5PzUetYUvG5qALmA+2TON40pc2+brOEiVTwr3kjF9N+f7q4MpyiLPu4pIErwoajOQ==}
engines: {node: '>=12.22.0'} engines: {node: '>=12.22.0'}
peerDependencies: peerDependencies:
vue: latest vue: '>=3.2.0'
dependencies: dependencies:
'@ant-design/colors': 6.0.0 '@ant-design/colors': 6.0.0
'@ant-design/icons-vue': 6.1.0(vue@3.3.4) '@ant-design/icons-vue': 6.1.0(vue@3.3.4)
@ -10467,6 +10480,17 @@ packages:
type-detect: 4.0.8 type-detect: 4.0.8
dev: true dev: true
/chalk@1.1.3:
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
engines: {node: '>=0.10.0'}
dependencies:
ansi-styles: 2.2.1
escape-string-regexp: 1.0.5
has-ansi: 2.0.0
strip-ansi: 3.0.1
supports-color: 2.0.0
dev: false
/chalk@2.4.2: /chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -10720,6 +10744,7 @@ packages:
string-width: 4.2.3 string-width: 4.2.3
strip-ansi: 6.0.1 strip-ansi: 6.0.1
wrap-ansi: 7.0.0 wrap-ansi: 7.0.0
dev: true
/clone-deep@4.0.1: /clone-deep@4.0.1:
resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==}
@ -10854,7 +10879,6 @@ packages:
/commander@2.20.3: /commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
dev: true
/commander@4.1.1: /commander@4.1.1:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
@ -12083,7 +12107,7 @@ packages:
/emoji-mart-vue-fast@15.0.0(vue@3.3.4): /emoji-mart-vue-fast@15.0.0(vue@3.3.4):
resolution: {integrity: sha512-3BzkDrs60JyT00dLHMAxWKbpFhbyaW9C+q1AjtqGovSxTu8TC2mYAGsvTmXNYKm39IRRAS56v92TihOcB98IsQ==} resolution: {integrity: sha512-3BzkDrs60JyT00dLHMAxWKbpFhbyaW9C+q1AjtqGovSxTu8TC2mYAGsvTmXNYKm39IRRAS56v92TihOcB98IsQ==}
peerDependencies: peerDependencies:
vue: latest vue: '>2.0.0'
dependencies: dependencies:
'@babel/runtime': 7.22.11 '@babel/runtime': 7.22.11
core-js: 3.32.1 core-js: 3.32.1
@ -12534,7 +12558,7 @@ packages:
eslint-import-resolver-webpack: eslint-import-resolver-webpack:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/parser': 5.62.0(eslint@8.33.0) '@typescript-eslint/parser': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
debug: 3.2.7(supports-color@5.5.0) debug: 3.2.7(supports-color@5.5.0)
eslint: 8.33.0 eslint: 8.33.0
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
@ -12600,7 +12624,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/eslint-plugin-antfu@0.26.0(eslint@8.33.0): /eslint-plugin-antfu@0.26.0(eslint@8.33.0)(typescript@5.2.2):
resolution: {integrity: sha512-hc5Bb6EH6zM/Vjy0scOQydlG9I1DDocG4AikyUfqjSFneWv6eNItej9LHYTXEGc0iGosCysNS4tPUAPuhBHkCA==} resolution: {integrity: sha512-hc5Bb6EH6zM/Vjy0scOQydlG9I1DDocG4AikyUfqjSFneWv6eNItej9LHYTXEGc0iGosCysNS4tPUAPuhBHkCA==}
dependencies: dependencies:
'@typescript-eslint/utils': 5.62.0(eslint@8.33.0)(typescript@5.2.2) '@typescript-eslint/utils': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
@ -12637,7 +12661,7 @@ packages:
engines: {node: '>=16.10.0'} engines: {node: '>=16.10.0'}
peerDependencies: peerDependencies:
eslint: ^8.0.0 eslint: ^8.0.0
typescript: latest typescript: '>=4.0.2'
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
@ -12736,7 +12760,7 @@ packages:
'@typescript-eslint/parser': '@typescript-eslint/parser':
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/parser': 5.62.0(eslint@8.33.0) '@typescript-eslint/parser': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
array-includes: 3.1.6 array-includes: 3.1.6
array.prototype.findlastindex: 1.2.2 array.prototype.findlastindex: 1.2.2
array.prototype.flat: 1.3.1 array.prototype.flat: 1.3.1
@ -13104,15 +13128,15 @@ packages:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
/event-stream@4.0.1: /event-stream@3.3.4:
resolution: {integrity: sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==} resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==}
dependencies: dependencies:
duplexer: 0.1.2 duplexer: 0.1.2
from: 0.1.7 from: 0.1.7
map-stream: 0.0.7 map-stream: 0.1.0
pause-stream: 0.0.11 pause-stream: 0.0.11
split: 1.0.1 split: 0.3.3
stream-combiner: 0.2.2 stream-combiner: 0.0.4
through: 2.3.8 through: 2.3.8
dev: false dev: false
@ -13650,7 +13674,7 @@ packages:
resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==}
engines: {node: '>=12.13.0', yarn: '>=1.0.0'} engines: {node: '>=12.13.0', yarn: '>=1.0.0'}
peerDependencies: peerDependencies:
typescript: latest typescript: '>3.6.0'
webpack: ^5.11.0 webpack: ^5.11.0
dependencies: dependencies:
'@babel/code-frame': 7.22.10 '@babel/code-frame': 7.22.10
@ -13687,6 +13711,15 @@ packages:
mime-types: 2.1.35 mime-types: 2.1.35
dev: true dev: true
/form-data@3.0.0:
resolution: {integrity: sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==}
engines: {node: '>= 6'}
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.35
dev: false
/form-data@3.0.1: /form-data@3.0.1:
resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -13815,6 +13848,22 @@ packages:
resolution: {integrity: sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==} resolution: {integrity: sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==}
dev: true dev: true
/fs-readfile-promise@2.0.1:
resolution: {integrity: sha512-7+P9eOOMnkIOmtxrBWTzWOBQlE7Nz/cBx9EYTX5hm8DzmZ/Fj9YWeUY2O9G+Q8YblScd1hyEkcmNcZMDj5U8Ug==}
dependencies:
graceful-fs: 4.2.11
dev: false
/fs-writefile-promise@1.0.3(mkdirp@2.1.3):
resolution: {integrity: sha512-yI+wDwj0FsgX7tyIQJR+EP60R64evMSixtGb9AzGWjJVKlF5tCet95KomfqGBg/aIAG1Dhd6wjCOQe5HbX/qLA==}
engines: {node: '>=0.10'}
dependencies:
mkdirp-promise: 1.1.0(mkdirp@2.1.3)
pinkie-promise: 1.0.0
transitivePeerDependencies:
- mkdirp
dev: false
/fs.realpath@1.0.0: /fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@ -14470,6 +14519,13 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: true dev: true
/has-ansi@2.0.0:
resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==}
engines: {node: '>=0.10.0'}
dependencies:
ansi-regex: 2.1.1
dev: false
/has-bigints@1.0.2: /has-bigints@1.0.2:
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
@ -14678,17 +14734,23 @@ packages:
- supports-color - supports-color
dev: false dev: false
/httpsnippet@3.0.1: /httpsnippet@2.0.0(mkdirp@2.1.3):
resolution: {integrity: sha512-RJbzVu9Gq97Ti76MPKAb9AknKbRluRbzOqswM2qgEW48QUShVEIuJjl43dZG5q0Upj2SZlKqzR6B6ah1q5znfg==} resolution: {integrity: sha512-Hb2ttfB5OhasYxwChZ8QKpYX3v4plNvwMaMulUIC7M3RHRDf1Op6EMp47LfaU2sgQgfvo5spWK4xRAirMEisrg==}
engines: {node: ^14.19.1 || ^16.14.2 || ^18.0.0} engines: {node: '>=10'}
hasBin: true hasBin: true
dependencies: dependencies:
chalk: 4.1.2 chalk: 1.1.3
event-stream: 4.0.1 commander: 2.20.3
form-data: 4.0.0 debug: 2.6.9
har-schema: 2.0.0 event-stream: 3.3.4
form-data: 3.0.0
fs-readfile-promise: 2.0.1
fs-writefile-promise: 1.0.3(mkdirp@2.1.3)
har-validator: 5.1.5
stringify-object: 3.3.0 stringify-object: 3.3.0
yargs: 17.7.2 transitivePeerDependencies:
- mkdirp
- supports-color
dev: false dev: false
/httpxy@0.1.4: /httpxy@0.1.4:
@ -15197,7 +15259,7 @@ packages:
resolution: {integrity: sha512-DDx04RjLpGNT4vtF49vGW5CECP6lAx8SL2keq99ogIxwLvJPBvgThdhb43ED5uYO4nq0kZ51tMj7VdCCQgdZ5Q==} resolution: {integrity: sha512-DDx04RjLpGNT4vtF49vGW5CECP6lAx8SL2keq99ogIxwLvJPBvgThdhb43ED5uYO4nq0kZ51tMj7VdCCQgdZ5Q==}
peerDependencies: peerDependencies:
eslint: '*' eslint: '*'
typescript: latest typescript: '>=4.7.4'
dependencies: dependencies:
'@typescript-eslint/type-utils': 5.62.0(eslint@8.33.0)(typescript@5.2.2) '@typescript-eslint/type-utils': 5.62.0(eslint@8.33.0)(typescript@5.2.2)
eslint: 8.33.0 eslint: 8.33.0
@ -17003,8 +17065,8 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/map-stream@0.0.7: /map-stream@0.1.0:
resolution: {integrity: sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==} resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==}
dev: false dev: false
/marked@4.3.0: /marked@4.3.0:
@ -17353,6 +17415,16 @@ packages:
dev: true dev: true
optional: true optional: true
/mkdirp-promise@1.1.0(mkdirp@2.1.3):
resolution: {integrity: sha512-xzB0UZFcW1UGS2xkXeDh39jzTP282lb3Vwp4QzCQYmkTn4ysaV5dBdbkOXmhkcE1TQlZebQlgTceaWvDr3oFgw==}
engines: {node: '>=4'}
deprecated: This package is broken and no longer maintained. 'mkdirp' itself supports promises now, please switch to that.
peerDependencies:
mkdirp: '>=0.5.0'
dependencies:
mkdirp: 2.1.3
dev: false
/mkdirp@0.5.6: /mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true hasBin: true
@ -18240,7 +18312,7 @@ packages:
- vite - vite
dev: true dev: true
/nuxt@3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4): /nuxt@3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4)(typescript@5.2.2):
resolution: {integrity: sha512-0A7V8B1HrIXX9IlqPc2w+5ZPXi+7MYa9QVhtuGYuLvjRKoSFANhCoMPRP6pKdoxigM1MBxhLue2VmHA/VbtJCw==} resolution: {integrity: sha512-0A7V8B1HrIXX9IlqPc2w+5ZPXi+7MYa9QVhtuGYuLvjRKoSFANhCoMPRP6pKdoxigM1MBxhLue2VmHA/VbtJCw==}
engines: {node: ^14.18.0 || >=16.10.0} engines: {node: ^14.18.0 || >=16.10.0}
hasBin: true hasBin: true
@ -18256,7 +18328,7 @@ packages:
'@nuxt/schema': 3.6.5 '@nuxt/schema': 3.6.5
'@nuxt/telemetry': 2.4.1 '@nuxt/telemetry': 2.4.1
'@nuxt/ui-templates': 1.3.1 '@nuxt/ui-templates': 1.3.1
'@nuxt/vite-builder': 3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4)(vue@3.3.4) '@nuxt/vite-builder': 3.6.5(@types/node@20.3.1)(eslint@8.33.0)(sass@1.63.4)(typescript@5.2.2)(vue@3.3.4)
'@types/node': 20.3.1 '@types/node': 20.3.1
'@unhead/ssr': 1.3.9 '@unhead/ssr': 1.3.9
'@unhead/vue': 1.3.9(vue@3.3.4) '@unhead/vue': 1.3.9(vue@3.3.4)
@ -19130,12 +19202,12 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/pinia@2.1.4(vue@3.3.4): /pinia@2.1.4(typescript@5.2.2)(vue@3.3.4):
resolution: {integrity: sha512-vYlnDu+Y/FXxv1ABo1vhjC+IbqvzUdiUC3sfDRrRyY2CQSrqqaa+iiHmqtARFxJVqWQMCJfXx1PBvFs9aJVLXQ==} resolution: {integrity: sha512-vYlnDu+Y/FXxv1ABo1vhjC+IbqvzUdiUC3sfDRrRyY2CQSrqqaa+iiHmqtARFxJVqWQMCJfXx1PBvFs9aJVLXQ==}
peerDependencies: peerDependencies:
'@vue/composition-api': ^1.4.0 '@vue/composition-api': ^1.4.0
typescript: latest typescript: '>=4.4.4'
vue: latest vue: ^2.6.14 || ^3.3.0
peerDependenciesMeta: peerDependenciesMeta:
'@vue/composition-api': '@vue/composition-api':
optional: true optional: true
@ -19143,10 +19215,23 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@vue/devtools-api': 6.5.0 '@vue/devtools-api': 6.5.0
typescript: 5.2.2
vue: 3.3.4 vue: 3.3.4
vue-demi: 0.14.5(vue@3.3.4) vue-demi: 0.14.5(vue@3.3.4)
dev: false dev: false
/pinkie-promise@1.0.0:
resolution: {integrity: sha512-5mvtVNse2Ml9zpFKkWBpGsTPwm3DKhs+c95prO/F6E7d6DN0FPqxs6LONpLNpyD7Iheb7QN4BbUoKJgo+DnkQA==}
engines: {node: '>=0.10.0'}
dependencies:
pinkie: 1.0.0
dev: false
/pinkie@1.0.0:
resolution: {integrity: sha512-VFVaU1ysKakao68ktZm76PIdOhvEfoNNRaGkyLln9Os7r0/MCxqHjHyBM7dT3pgTiBybqiPtpqKfpENwdBp50Q==}
engines: {node: '>=0.10.0'}
dev: false
/pirates@4.0.6: /pirates@4.0.6:
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -21024,10 +21109,17 @@ packages:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'} engines: {node: '>= 10.x'}
/split@0.3.3:
resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==}
dependencies:
through: 2.3.8
dev: false
/split@1.0.1: /split@1.0.1:
resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==} resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==}
dependencies: dependencies:
through: 2.3.8 through: 2.3.8
dev: true
/splitpanes@3.1.5: /splitpanes@3.1.5:
resolution: {integrity: sha512-r3Mq2ITFQ5a2VXLOy4/Sb2Ptp7OfEO8YIbhVJqJXoFc9hc5nTXXkCvtVDjIGbvC0vdE7tse+xTM9BMjsszP6bw==} resolution: {integrity: sha512-r3Mq2ITFQ5a2VXLOy4/Sb2Ptp7OfEO8YIbhVJqJXoFc9hc5nTXXkCvtVDjIGbvC0vdE7tse+xTM9BMjsszP6bw==}
@ -21149,11 +21241,10 @@ packages:
engines: {node: '>=4', npm: '>=6'} engines: {node: '>=4', npm: '>=6'}
dev: false dev: false
/stream-combiner@0.2.2: /stream-combiner@0.0.4:
resolution: {integrity: sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==} resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==}
dependencies: dependencies:
duplexer: 0.1.2 duplexer: 0.1.2
through: 2.3.8
dev: false dev: false
/stream-events@1.0.5: /stream-events@1.0.5:
@ -21281,6 +21372,13 @@ packages:
is-regexp: 1.0.0 is-regexp: 1.0.0
dev: false dev: false
/strip-ansi@3.0.1:
resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==}
engines: {node: '>=0.10.0'}
dependencies:
ansi-regex: 2.1.1
dev: false
/strip-ansi@6.0.1: /strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -21395,6 +21493,11 @@ packages:
- supports-color - supports-color
dev: true dev: true
/supports-color@2.0.0:
resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==}
engines: {node: '>=0.8.0'}
dev: false
/supports-color@5.5.0: /supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -21887,7 +21990,7 @@ packages:
resolution: {integrity: sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==} resolution: {integrity: sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==}
engines: {node: '>=16.13.0'} engines: {node: '>=16.13.0'}
peerDependencies: peerDependencies:
typescript: latest typescript: '>=4.2.0'
dependencies: dependencies:
typescript: 5.2.2 typescript: 5.2.2
dev: true dev: true
@ -21907,7 +22010,7 @@ packages:
babel-jest: ^29.0.0 babel-jest: ^29.0.0
esbuild: '*' esbuild: '*'
jest: ^29.0.0 jest: ^29.0.0
typescript: latest typescript: '>=4.3'
peerDependenciesMeta: peerDependenciesMeta:
'@babel/core': '@babel/core':
optional: true optional: true
@ -21935,7 +22038,7 @@ packages:
resolution: {integrity: sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==} resolution: {integrity: sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
peerDependencies: peerDependencies:
typescript: latest typescript: '*'
webpack: ^5.0.0 webpack: ^5.0.0
dependencies: dependencies:
chalk: 4.1.2 chalk: 4.1.2
@ -21943,20 +22046,6 @@ packages:
micromatch: 4.0.5 micromatch: 4.0.5
semver: 7.5.4 semver: 7.5.4
typescript: 5.2.2 typescript: 5.2.2
webpack: 5.88.2(webpack-cli@5.1.4)
dev: true
/ts-loader@9.4.4(webpack@5.88.2):
resolution: {integrity: sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==}
engines: {node: '>=12.0.0'}
peerDependencies:
typescript: latest
webpack: ^5.0.0
dependencies:
chalk: 4.1.2
enhanced-resolve: 5.15.0
micromatch: 4.0.5
semver: 7.5.4
webpack: 5.88.2(esbuild@0.19.2) webpack: 5.88.2(esbuild@0.19.2)
dev: true dev: true
@ -21981,7 +22070,7 @@ packages:
'@swc/core': '>=1.2.50' '@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50' '@swc/wasm': '>=1.2.50'
'@types/node': '*' '@types/node': '*'
typescript: latest typescript: '>=2.7'
peerDependenciesMeta: peerDependenciesMeta:
'@swc/core': '@swc/core':
optional: true optional: true
@ -22071,7 +22160,7 @@ packages:
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
peerDependencies: peerDependencies:
typescript: latest typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
dependencies: dependencies:
tslib: 1.14.1 tslib: 1.14.1
typescript: 5.2.2 typescript: 5.2.2
@ -22229,7 +22318,6 @@ packages:
resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==}
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
dev: true
/ufo@1.3.0: /ufo@1.3.0:
resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==} resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==}
@ -22491,7 +22579,7 @@ packages:
engines: {node: '>=14'} engines: {node: '>=14'}
peerDependencies: peerDependencies:
'@babel/parser': ^7.15.8 '@babel/parser': ^7.15.8
vue: latest vue: 2 || 3
peerDependenciesMeta: peerDependenciesMeta:
'@babel/parser': '@babel/parser':
optional: true optional: true
@ -22844,7 +22932,7 @@ packages:
- terser - terser
dev: true dev: true
/vite-plugin-checker@0.6.2(eslint@8.33.0)(vite@4.3.9): /vite-plugin-checker@0.6.2(eslint@8.33.0)(typescript@5.2.2)(vite@4.3.9):
resolution: {integrity: sha512-YvvvQ+IjY09BX7Ab+1pjxkELQsBd4rPhWNw8WLBeFVxu/E7O+n6VYAqNsKdK/a2luFlX/sMpoWdGFfg4HvwdJQ==} resolution: {integrity: sha512-YvvvQ+IjY09BX7Ab+1pjxkELQsBd4rPhWNw8WLBeFVxu/E7O+n6VYAqNsKdK/a2luFlX/sMpoWdGFfg4HvwdJQ==}
engines: {node: '>=14.16'} engines: {node: '>=14.16'}
peerDependencies: peerDependencies:
@ -22852,7 +22940,7 @@ packages:
meow: ^9.0.0 meow: ^9.0.0
optionator: ^0.9.1 optionator: ^0.9.1
stylelint: '>=13' stylelint: '>=13'
typescript: latest typescript: '*'
vite: '>=2.0.0' vite: '>=2.0.0'
vls: '*' vls: '*'
vti: '*' vti: '*'
@ -22889,6 +22977,7 @@ packages:
semver: 7.5.4 semver: 7.5.4
strip-ansi: 6.0.1 strip-ansi: 6.0.1
tiny-invariant: 1.3.1 tiny-invariant: 1.3.1
typescript: 5.2.2
vite: 4.3.9(@types/node@20.3.1)(sass@1.63.4) vite: 4.3.9(@types/node@20.3.1)(sass@1.63.4)
vscode-languageclient: 7.0.0 vscode-languageclient: 7.0.0
vscode-languageserver: 7.0.0 vscode-languageserver: 7.0.0
@ -23147,7 +23236,7 @@ packages:
resolution: {integrity: sha512-d3zpKmGZr2OWHQ1xmxBcAn5ShTG917+/UCLaSpaCDDqT0U7DBsvFzTs69ZnHCgKoXT55GZDW8YEj9Av+dlONLA==} resolution: {integrity: sha512-d3zpKmGZr2OWHQ1xmxBcAn5ShTG917+/UCLaSpaCDDqT0U7DBsvFzTs69ZnHCgKoXT55GZDW8YEj9Av+dlONLA==}
peerDependencies: peerDependencies:
chart.js: ^4.1.1 chart.js: ^4.1.1
vue: latest vue: ^3.0.0-0 || ^2.7.0
dependencies: dependencies:
chart.js: 4.3.0 chart.js: 4.3.0
vue: 3.3.4 vue: 3.3.4
@ -23160,7 +23249,7 @@ packages:
requiresBuild: true requiresBuild: true
peerDependencies: peerDependencies:
'@vue/composition-api': ^1.0.0-rc.1 '@vue/composition-api': ^1.0.0-rc.1
vue: latest vue: ^3.0.0-0 || ^2.6.0
peerDependenciesMeta: peerDependenciesMeta:
'@vue/composition-api': '@vue/composition-api':
optional: true optional: true
@ -23175,7 +23264,7 @@ packages:
requiresBuild: true requiresBuild: true
peerDependencies: peerDependencies:
'@vue/composition-api': ^1.0.0-rc.1 '@vue/composition-api': ^1.0.0-rc.1
vue: latest vue: ^3.0.0-0 || ^2.6.0
peerDependenciesMeta: peerDependenciesMeta:
'@vue/composition-api': '@vue/composition-api':
optional: true optional: true
@ -23189,7 +23278,7 @@ packages:
requiresBuild: true requiresBuild: true
peerDependencies: peerDependencies:
'@vue/composition-api': ^1.0.0-rc.1 '@vue/composition-api': ^1.0.0-rc.1
vue: latest vue: ^3.0.0-0 || ^2.6.0
peerDependenciesMeta: peerDependenciesMeta:
'@vue/composition-api': '@vue/composition-api':
optional: true optional: true
@ -23203,7 +23292,7 @@ packages:
/vue-dompurify-html@3.0.0(vue@3.3.4): /vue-dompurify-html@3.0.0(vue@3.3.4):
resolution: {integrity: sha512-S6PMeJU7S3w0TnxMWWd4iydc7oPdOER1GmW9rsgiRwHvcw+nUi2v6BgERcFBULlM+x6PXsfu5P/Rm4reVvWH5A==} resolution: {integrity: sha512-S6PMeJU7S3w0TnxMWWd4iydc7oPdOER1GmW9rsgiRwHvcw+nUi2v6BgERcFBULlM+x6PXsfu5P/Rm4reVvWH5A==}
peerDependencies: peerDependencies:
vue: latest vue: ^3.0.0
dependencies: dependencies:
dompurify: 2.4.7 dompurify: 2.4.7
vue: 3.3.4 vue: 3.3.4
@ -23237,7 +23326,7 @@ packages:
resolution: {integrity: sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==} resolution: {integrity: sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
peerDependencies: peerDependencies:
vue: latest vue: ^3.0.0
dependencies: dependencies:
'@intlify/core-base': 9.2.2 '@intlify/core-base': 9.2.2
'@intlify/shared': 9.2.2 '@intlify/shared': 9.2.2
@ -23259,7 +23348,7 @@ packages:
/vue-router@4.2.4(vue@3.3.4): /vue-router@4.2.4(vue@3.3.4):
resolution: {integrity: sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==} resolution: {integrity: sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==}
peerDependencies: peerDependencies:
vue: latest vue: ^3.2.0
dependencies: dependencies:
'@vue/devtools-api': 6.5.0 '@vue/devtools-api': 6.5.0
vue: 3.3.4 vue: 3.3.4
@ -23269,7 +23358,7 @@ packages:
resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==} resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==}
engines: {node: '>=10.15.0'} engines: {node: '>=10.15.0'}
peerDependencies: peerDependencies:
vue: latest vue: ^3.0.0
dependencies: dependencies:
is-plain-object: 3.0.1 is-plain-object: 3.0.1
vue: 3.3.4 vue: 3.3.4
@ -23279,7 +23368,7 @@ packages:
resolution: {integrity: sha512-BchyC33WiZryYatFINj3LWqgyE6X82Huzf7abA23tsF/IbaRZVwZzie8SmGaYvezEBiPXhJogQ3dtxIuXFjkBw==} resolution: {integrity: sha512-BchyC33WiZryYatFINj3LWqgyE6X82Huzf7abA23tsF/IbaRZVwZzie8SmGaYvezEBiPXhJogQ3dtxIuXFjkBw==}
engines: {node: '>=12'} engines: {node: '>=12'}
peerDependencies: peerDependencies:
vue: latest vue: ^3.2.24
dependencies: dependencies:
tippy.js: 6.3.7 tippy.js: 6.3.7
vue: 3.3.4 vue: 3.3.4
@ -23314,7 +23403,7 @@ packages:
resolution: {integrity: sha512-l/30RvXLkw50axAjswAK1DmvbUc5Oyhq9GkvD98p8pykrLkIajRi3evVsMnahMBK0O7+EGIK9RbIOKPyRfuw7w==} resolution: {integrity: sha512-l/30RvXLkw50axAjswAK1DmvbUc5Oyhq9GkvD98p8pykrLkIajRi3evVsMnahMBK0O7+EGIK9RbIOKPyRfuw7w==}
peerDependencies: peerDependencies:
resize-detector: ^0.3.0 resize-detector: ^0.3.0
vue: latest vue: ^3.2.37
dependencies: dependencies:
resize-detector: 0.3.0 resize-detector: 0.3.0
vue: 3.3.4 vue: 3.3.4
@ -23332,7 +23421,7 @@ packages:
/vuedraggable@4.1.0(vue@3.3.4): /vuedraggable@4.1.0(vue@3.3.4):
resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==} resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
peerDependencies: peerDependencies:
vue: latest vue: ^3.0.1
dependencies: dependencies:
sortablejs: 1.14.0 sortablejs: 1.14.0
vue: 3.3.4 vue: 3.3.4
@ -24050,6 +24139,7 @@ packages:
/y18n@5.0.8: /y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true
/yallist@3.1.1: /yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
@ -24100,6 +24190,7 @@ packages:
/yargs-parser@21.1.1: /yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'} engines: {node: '>=12'}
dev: true
/yargs-unparser@2.0.0: /yargs-unparser@2.0.0:
resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
@ -24152,6 +24243,7 @@ packages:
string-width: 4.2.3 string-width: 4.2.3
y18n: 5.0.8 y18n: 5.0.8
yargs-parser: 21.1.1 yargs-parser: 21.1.1
dev: true
/yauzl@2.10.0: /yauzl@2.10.0:
resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==}

1
tests/playwright/pages/Dashboard/Command/CmdKPage.ts

@ -21,6 +21,7 @@ export class CmdK extends BasePage {
async searchText(text: string) { async searchText(text: string) {
await this.dashboardPage.rootPage.fill('.cmdk-input', text); await this.dashboardPage.rootPage.fill('.cmdk-input', text);
await this.rootPage.keyboard.press('Enter'); await this.rootPage.keyboard.press('Enter');
await this.rootPage.keyboard.press('Enter');
} }
async isCmdKVisible() { async isCmdKVisible() {

Loading…
Cancel
Save