From edc7c44d9f25cd347c175269f7d9bdb6f341c802 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Thu, 13 Jun 2024 21:26:32 +0000 Subject: [PATCH] fix: use custom cached debounce function to use individual debounce function for each filter --- .../nc-gui/composables/useDebounceFnCached.ts | 45 +++++++++++++++++++ packages/nc-gui/composables/useViewFilters.ts | 33 ++++++++------ 2 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 packages/nc-gui/composables/useDebounceFnCached.ts diff --git a/packages/nc-gui/composables/useDebounceFnCached.ts b/packages/nc-gui/composables/useDebounceFnCached.ts new file mode 100644 index 0000000000..31b101fa23 --- /dev/null +++ b/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() + +// 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( + fn: T, + ms: MaybeRefOrGetter = 500, + getCacheKey: (...args: Parameters) => string | number = defaultGetCacheKey, + options: DebounceFilterOptions = {}, +): (...args: Parameters) => ReturnType { + return function (...args: Parameters): ReturnType { + // 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) + } +} diff --git a/packages/nc-gui/composables/useViewFilters.ts b/packages/nc-gui/composables/useViewFilters.ts index dca8d9b391..681bb12bad 100644 --- a/packages/nc-gui/composables/useViewFilters.ts +++ b/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 = {}) => { filters.value.push(draftFilter?.fk_column_id ? { ...placeholderFilter(), ...draftFilter } : placeholderFilter()) if (!undo) {