Browse Source

fix: use custom cached debounce function to use individual debounce function for each filter

pull/8732/head
Pranav C 2 weeks ago
parent
commit
edc7c44d9f
  1. 45
      packages/nc-gui/composables/useDebounceFnCached.ts
  2. 33
      packages/nc-gui/composables/useViewFilters.ts

45
packages/nc-gui/composables/useDebounceFnCached.ts

@ -0,0 +1,45 @@
import type { DebounceFilterOptions, MaybeRefOrGetter } from '@vueuse/core'
type FunctionArgs = (...args: any[]) => any
// Cache to store debounced functions based on a unique key
const debounceCache = new Map<string | number, any>()
// Default function to generate a cache key
function defaultGetCacheKey(): string {
return 'default'
}
/**
* Creates a cached debounced version of the given function.
*
* @param fn - The function to debounce.
* @param ms - The debounce delay in milliseconds. Default is 500ms.
* @param getCacheKey - Function to generate a unique cache key based on the arguments.
* @param options - Additional options for debouncing.
*
* @returns A debounced version of the input function with caching.
*/
export function useCachedDebouncedFunction<T extends FunctionArgs>(
fn: T,
ms: MaybeRefOrGetter<number> = 500,
getCacheKey: (...args: Parameters<T>) => string | number = defaultGetCacheKey,
options: DebounceFilterOptions = {},
): (...args: Parameters<T>) => ReturnType<T> {
return function (...args: Parameters<T>): ReturnType<T> {
// Generate a unique key for the given arguments
const key = getCacheKey(args)
// If the debounced function for the given key is not in the cache, create and cache it
if (!debounceCache.has(key)) {
const debouncedFn = useDebounceFn(fn, ms, options)
debounceCache.set(key, debouncedFn)
}
// Retrieve the cached debounced function
const debouncedFn = debounceCache.get(key)
// Call and return the result of the debounced function
return debouncedFn!(...args)
}
}

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

@ -338,7 +338,9 @@ export function useViewFilters(
}
}
const saveOrUpdate = async (filter: Filter, i: number, force = false, undo = false, skipDataReload = false) => {
const saveOrUpdateDebounced = useCachedDebouncedFunction(saveOrUpdate, 500, (_filter: Filter, i: number) => i)
async function saveOrUpdate(filter: Filter, i: number, force = false, undo = false, skipDataReload = false) {
// if already in progress the debounced function which will call this function again with 500ms delay until it's not saving
if (savingStatus[i]) {
return saveOrUpdateDebounced(filter, i, force, undo, skipDataReload)
@ -386,7 +388,7 @@ export function useViewFilters(
filters.value = [...filters.value]
} else if (!autoApply?.value && !force) {
filter.status = filter.id ? 'update' : 'create'
} else if (filters.value[i]?.id && filter.status !== 'create') {
} else if (filters.value[i]?.id && filters.value[i]?.status !== 'create') {
await $api.dbTableFilter.update(filters.value[i].id!, {
...filter,
fk_parent_id: parentId.value,
@ -399,15 +401,23 @@ export function useViewFilters(
})
} else {
if (linkColId?.value) {
filters.value[i] = await $api.dbTableLinkFilter.create(linkColId.value, {
...filter,
fk_parent_id: parentId,
})
// set value with current value of filter since user can change value while saving
filters.value[i] = {
...((await $api.dbTableLinkFilter.create(linkColId.value, {
...filter,
fk_parent_id: parentId,
})) || {}),
value: (filters.value[i] || filter).value,
}
} else {
filters.value[i] = await $api.dbTableFilter.create(view.value.id!, {
...filter,
fk_parent_id: parentId.value,
})
// set value with current value of filter since user can change value while saving
filters.value[i] = {
...((await $api.dbTableFilter.create(view.value.id!, {
...filter,
fk_parent_id: parentId.value,
})) || {}),
value: (filters.value[i] || filter).value,
}
}
if (!isLink && !isWebhook) allFilters.value.push(filters.value[+i])
}
@ -496,9 +506,6 @@ export function useViewFilters(
if (!isLink && !isWebhook) allFilters.value = allFilters.value.filter((f) => f.id !== filter.id)
}
}
const saveOrUpdateDebounced = useDebounceFn(saveOrUpdate, 500)
const addFilter = async (undo = false, draftFilter: Partial<FilterType> = {}) => {
filters.value.push(draftFilter?.fk_column_id ? { ...placeholderFilter(), ...draftFilter } : placeholderFilter())
if (!undo) {

Loading…
Cancel
Save