Browse Source

fix(nc-gui): disable add filter from context menu if limit exceed

pull/8309/head
Ramesh Mane 5 months ago
parent
commit
61bab38907
  1. 43
      packages/nc-gui/components/smartsheet/header/Menu.vue
  2. 2
      packages/nc-gui/components/smartsheet/toolbar/ColumnFilterMenu.vue
  3. 3
      packages/nc-gui/composables/useSmartsheetStore.ts
  4. 67
      packages/nc-gui/composables/useViewFilters.ts

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

@ -1,6 +1,6 @@
<script lang="ts" setup>
import type { ColumnReqType } from 'nocodb-sdk'
import { RelationTypes, UITypes, isLinksOrLTAR } from 'nocodb-sdk'
import { PlanLimitTypes, RelationTypes, UITypes, isLinksOrLTAR } from 'nocodb-sdk'
import { computed } from 'vue'
import {
ActiveViewInj,
@ -28,7 +28,7 @@ const virtual = toRef(props, 'virtual')
const isOpen = useVModel(props, 'isOpen', emit)
const { eventBus } = useSmartsheetStoreOrThrow()
const { eventBus, allFilters } = useSmartsheetStoreOrThrow()
const column = inject(ColumnInj)
@ -38,10 +38,12 @@ const meta = inject(MetaInj, ref())
const view = inject(ActiveViewInj, ref())
const { insertSort } = useViewSorts(view, () => reloadDataHook?.trigger())
const isLocked = inject(IsLockedInj)
const isPublic = inject(IsPublicInj, ref(false))
const { insertSort } = useViewSorts(view, () => reloadDataHook?.trigger())
const { $api, $e } = useNuxtApp()
const { t } = useI18n()
@ -304,8 +306,12 @@ const isFilterSupported = computed(
!!(meta.value?.columns || []).find((f) => f.id === column?.value?.id && ![UITypes.QrCode, UITypes.Barcode].includes(f.uidt)),
)
// TODO: calculate filter limit
const isFilterLimitExceeded = computed(() => false)
const { getPlanLimit } = useWorkspace()
const isFilterLimitExceeded = computed(
() =>
allFilters.value.filter((f) => !(f.is_group || f.status === 'delete')).length >= getPlanLimit(PlanLimitTypes.FILTER_LIMIT),
)
const isGroupedByThisField = computed(() => !!gridViewCols.value[column?.value?.id]?.group_by)
@ -392,9 +398,20 @@ const filterOrGroupByThisField = (event: SmartsheetStoreEvents) => {
<a-divider v-if="!column?.pk" class="!my-0" />
<template v-if="true">
<NcTooltip :disabled="isFilterSupported">
<template #title> This field type doesn't support filtering </template>
<NcMenuItem @click="filterOrGroupByThisField(SmartsheetStoreEvents.FILTER_ADD)" :disabled="!isFilterSupported">
<NcTooltip :disabled="isFilterSupported && !isFilterLimitExceeded">
<template #title>
{{
!isFilterSupported
? "This field type doesn't support filtering"
: isFilterLimitExceeded
? 'Filter by limit exceeded'
: ''
}}
</template>
<NcMenuItem
@click="filterOrGroupByThisField(SmartsheetStoreEvents.FILTER_ADD)"
:disabled="!isFilterSupported || isFilterLimitExceeded"
>
<div v-e="['a:field:add:filter']" class="nc-column-filter nc-header-menu-item">
<component :is="iconMap.filter" class="text-gray-700" />
<!-- Filter by this field -->
@ -403,16 +420,18 @@ const filterOrGroupByThisField = (event: SmartsheetStoreEvents) => {
</NcMenuItem>
</NcTooltip>
<NcTooltip :disabled="(isGroupBySupported && !isGroupByLimitExceeded) || isGroupedByThisField">
<NcTooltip
:disabled="(isGroupBySupported && !isGroupByLimitExceeded) || isGroupedByThisField || !(isEeUI && !isPublic)"
>
<template #title>{{
!isGroupBySupported
? "This field type doesn't support grouping"
: isGroupByLimitExceeded
? 'Group by limit exceeded'
: 'ds'
: ''
}}</template>
<NcMenuItem
:disabled="(!isGroupBySupported || isGroupByLimitExceeded) && !isGroupedByThisField"
:disabled="isEeUI && !isPublic && (!isGroupBySupported || isGroupByLimitExceeded) && !isGroupedByThisField"
@click="
filterOrGroupByThisField(
isGroupedByThisField ? SmartsheetStoreEvents.GROUP_BY_REMOVE : SmartsheetStoreEvents.GROUP_BY_ADD,

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

@ -42,7 +42,7 @@ watch(
() => activeView?.value?.id,
async (viewId) => {
if (viewId) {
await loadFilters()
await loadFilters(undefined, false, true)
filtersLength.value = nonDeletedFilters.value.length || 0
}
},

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

@ -58,6 +58,8 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
const sorts = ref<SortType[]>(unref(initialSorts) ?? [])
const nestedFilters = ref<FilterType[]>(unref(initialFilters) ?? [])
const allFilters = ref<Filter[]>([])
watch(
sorts,
() => {
@ -97,6 +99,7 @@ const [useProvideSmartsheetStore, useSmartsheetStore] = useInjectionState(
isSqlView,
eventBus,
sqlUi,
allFilters,
}
},
'smartsheet-store',

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

@ -43,7 +43,7 @@ export function useViewFilters(
const reloadHook = inject(ReloadViewDataHookInj)
const { nestedFilters } = useSmartsheetStoreOrThrow()
const { nestedFilters, allFilters } = useSmartsheetStoreOrThrow()
const { baseMeta } = storeToRefs(useBase())
@ -208,7 +208,35 @@ export function useViewFilters(
}
}
const loadFilters = async (hookId?: string, isWebhook = false) => {
const loadAllChildFilters = async (filters: Filter[]) => {
// Array to store promises of child filter loading
const promises = []
// Array to store all child filters
const allChildFilters: Filter[] = []
// Iterate over all filters
for (const filter of filters) {
// Check if the filter is a group
if (filter.id && filter.is_group) {
// Load children filters from the backend
const childFilterPromise = $api.dbTableFilter.childrenRead(filter.id).then((response) => {
const childFilters = response.list as Filter[]
allChildFilters.push(...childFilters)
return loadAllChildFilters(childFilters)
})
promises.push(childFilterPromise)
}
}
// Wait for all promises to resolve
await Promise.all(promises)
// Push all child filters into the allFilters array
allFilters.value.push(...allChildFilters)
}
const loadFilters = async (hookId?: string, isWebhook = false, loadAllFilters = false) => {
if (!view.value?.id) return
if (nestedMode.value) {
@ -228,6 +256,10 @@ export function useViewFilters(
filters.value = (await $api.dbTableFilter.childrenRead(parentId)).list as Filter[]
} else {
filters.value = (await $api.dbTableFilter.read(view.value!.id!)).list as Filter[]
if (loadAllFilters) {
allFilters.value = [...filters.value]
await loadAllChildFilters(allFilters.value)
}
}
}
} catch (e: any) {
@ -241,6 +273,11 @@ export function useViewFilters(
for (const [i, filter] of Object.entries(filters.value)) {
if (filter.status === 'delete') {
await $api.dbTableFilter.delete(filter.id as string)
if (filter.is_group) {
deleteFilterGroupFromAllFilters(filter)
} else {
allFilters.value = allFilters.value.filter((f) => f.id !== filter.id)
}
} else if (filter.status === 'update') {
await $api.dbTableFilter.update(filter.id as string, {
...filter,
@ -258,6 +295,8 @@ export function useViewFilters(
fk_parent_id: parentId,
})
}
allFilters.value.push(filters.value[+i])
}
}
@ -323,6 +362,8 @@ export function useViewFilters(
...filter,
fk_parent_id: parentId,
})
allFilters.value.push(filters.value[+i])
}
} catch (e: any) {
console.log(e)
@ -334,6 +375,21 @@ export function useViewFilters(
if (!isWebhook) reloadData?.()
}
function deleteFilterGroupFromAllFilters(filter: Filter) {
// Find all child filters of the specified parentId
const childFilters = allFilters.value.filter((f) => f.fk_parent_id === filter.id)
// Recursively delete child filter of child filter
childFilters.forEach((childFilter) => {
if (childFilter.is_group) {
deleteFilterGroupFromAllFilters(childFilter)
}
})
// Remove the parent object and its children from the array
allFilters.value = allFilters.value.filter((f) => f.id !== filter.id && f.fk_parent_id !== filter.id)
}
const deleteFilter = async (filter: Filter, i: number, undo = false) => {
if (!undo && !filter.is_group) {
addUndo({
@ -369,6 +425,7 @@ export function useViewFilters(
} else {
try {
await $api.dbTableFilter.delete(filter.id)
if (!isWebhook) reloadData?.()
filters.value.splice(i, 1)
} catch (e: any) {
@ -382,6 +439,12 @@ export function useViewFilters(
}
$e('a:filter:delete', { length: nonDeletedFilters.value.length })
}
if (filter.is_group) {
deleteFilterGroupFromAllFilters(filter)
} else {
allFilters.value = allFilters.value.filter((f) => f.id !== filter.id)
}
}
const saveOrUpdateDebounced = useDebounceFn(saveOrUpdate, 500)

Loading…
Cancel
Save