From 6faf27b544c533db31fd176eea6fa30c33429b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Mon, 16 Sep 2024 08:43:46 +0200 Subject: [PATCH 1/5] fix duplicate saved searches --- src/libs/SearchUtils.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 24872b5d90eb..eadfd7692139 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -522,6 +522,8 @@ function buildSearchQueryString(queryJSON?: SearchQueryJSON) { * Given object with chosen search filters builds correct query string from them */ function buildQueryStringFromFilterValues(filterValues: Partial) { + let expenseFilter = ''; + let statusFilter = ''; const filtersString = Object.entries(filterValues).map(([filterKey, filterValue]) => { if ((filterKey === FILTER_KEYS.MERCHANT || filterKey === FILTER_KEYS.DESCRIPTION || filterKey === FILTER_KEYS.REPORT_ID) && filterValue) { const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey); @@ -534,10 +536,10 @@ function buildQueryStringFromFilterValues(filterValues: Partial Date: Tue, 17 Sep 2024 15:20:49 +0200 Subject: [PATCH 2/5] update logic for buildQueryStringFromFilterValues() --- src/libs/SearchUtils.ts | 99 +++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index da94db605387..2626ea01494c 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -529,47 +529,59 @@ function buildSearchQueryString(queryJSON?: SearchQueryJSON) { * Given object with chosen search filters builds correct query string from them */ function buildQueryStringFromFilterValues(filterValues: Partial) { - let expenseFilter = ''; - let statusFilter = ''; - const filtersString = Object.entries(filterValues).map(([filterKey, filterValue]) => { - if ((filterKey === FILTER_KEYS.MERCHANT || filterKey === FILTER_KEYS.DESCRIPTION || filterKey === FILTER_KEYS.REPORT_ID) && filterValue) { - const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey); - if (keyInCorrectForm) { - return `${CONST.SEARCH.SYNTAX_FILTER_KEYS[keyInCorrectForm]}:${sanitizeString(filterValue as string)}`; + // We separe type and status filters from other filters to maintain hashes consistency for saved searches + const {type, status, ...otherFilters} = filterValues; + const filtersString: string[] = []; + + if (type) { + const sanitizedType = sanitizeString(type as string); + filtersString.push(`${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${sanitizedType}`); + } + + if (status) { + const sanitizedStatus = sanitizeString(status as string); + filtersString.push(`${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}:${sanitizedStatus}`); + } + + const mappedFilters = Object.entries(otherFilters) + .map(([filterKey, filterValue]) => { + if ((filterKey === FILTER_KEYS.MERCHANT || filterKey === FILTER_KEYS.DESCRIPTION || filterKey === FILTER_KEYS.REPORT_ID) && filterValue) { + const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey); + if (keyInCorrectForm) { + return `${CONST.SEARCH.SYNTAX_FILTER_KEYS[keyInCorrectForm]}:${sanitizeString(filterValue as string)}`; + } } - } - if (filterKey === FILTER_KEYS.KEYWORD && filterValue) { - const value = (filterValue as string).split(' ').map(sanitizeString).join(' '); - return `${value}`; - } - if (filterKey === FILTER_KEYS.TYPE && filterValue) { - expenseFilter = `${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${sanitizeString(filterValue as string)}`; - } - if (filterKey === FILTER_KEYS.STATUS && filterValue) { - statusFilter = `${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}:${sanitizeString(filterValue as string)}`; - } - if ( - (filterKey === FILTER_KEYS.CATEGORY || - filterKey === FILTER_KEYS.CARD_ID || - filterKey === FILTER_KEYS.TAX_RATE || - filterKey === FILTER_KEYS.EXPENSE_TYPE || - filterKey === FILTER_KEYS.TAG || - filterKey === FILTER_KEYS.CURRENCY || - filterKey === FILTER_KEYS.FROM || - filterKey === FILTER_KEYS.TO || - filterKey === FILTER_KEYS.IN) && - Array.isArray(filterValue) && - filterValue.length > 0 - ) { - const filterValueArray = [...new Set(filterValues[filterKey] ?? [])]; - const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey); - if (keyInCorrectForm) { - return `${CONST.SEARCH.SYNTAX_FILTER_KEYS[keyInCorrectForm]}:${filterValueArray.map(sanitizeString).join(',')}`; + + if (filterKey === FILTER_KEYS.KEYWORD && filterValue) { + const value = (filterValue as string).split(' ').map(sanitizeString).join(' '); + return `${value}`; } - } - return undefined; - }); + if ( + (filterKey === FILTER_KEYS.CATEGORY || + filterKey === FILTER_KEYS.CARD_ID || + filterKey === FILTER_KEYS.TAX_RATE || + filterKey === FILTER_KEYS.EXPENSE_TYPE || + filterKey === FILTER_KEYS.TAG || + filterKey === FILTER_KEYS.CURRENCY || + filterKey === FILTER_KEYS.FROM || + filterKey === FILTER_KEYS.TO || + filterKey === FILTER_KEYS.IN) && + Array.isArray(filterValue) && + filterValue.length > 0 + ) { + const filterValueArray = [...new Set(filterValue)]; + const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as FilterKeys[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey); + if (keyInCorrectForm) { + return `${CONST.SEARCH.SYNTAX_FILTER_KEYS[keyInCorrectForm]}:${filterValueArray.map(sanitizeString).join(',')}`; + } + } + + return undefined; + }) + .filter((filter): filter is string => Boolean(filter)); + + filtersString.push(...mappedFilters); const dateFilter = buildDateFilterQuery(filterValues); filtersString.push(dateFilter); @@ -577,16 +589,7 @@ function buildQueryStringFromFilterValues(filterValues: Partial Date: Tue, 17 Sep 2024 15:21:20 +0200 Subject: [PATCH 3/5] prevent saving search when hash is identical --- src/pages/Search/AdvancedSearchFilters.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pages/Search/AdvancedSearchFilters.tsx b/src/pages/Search/AdvancedSearchFilters.tsx index ad6416896447..8f08b128619a 100644 --- a/src/pages/Search/AdvancedSearchFilters.tsx +++ b/src/pages/Search/AdvancedSearchFilters.tsx @@ -222,6 +222,7 @@ function AdvancedSearchFilters() { const {singleExecution} = useSingleExecution(); const waitForNavigate = useWaitForNavigation(); const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); + const [savedSearches] = useOnyx(ONYXKEYS.SAVED_SEARCHES); const [searchAdvancedFilters = {} as SearchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM); const [cardList = {}] = useOnyx(ONYXKEYS.CARD_LIST); const taxRates = getAllTaxRates(); @@ -242,6 +243,13 @@ function AdvancedSearchFilters() { }; const onSaveSearch = () => { + const savedSearchKeys = Object.keys(savedSearches ?? {}); + if (savedSearches && savedSearchKeys.includes(String(queryJSON.hash))) { + // If the search is already saved, return early to prevent unnecessary API calls + Navigation.dismissModal(); + return; + } + SearchActions.saveSearch({ queryJSON, }); From 8abfc5c4f4e9c6e9aa0617bad99370370d90e00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 17 Sep 2024 15:23:50 +0200 Subject: [PATCH 4/5] fix lint --- src/libs/SearchUtils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 2626ea01494c..886f6388ad9f 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -534,12 +534,12 @@ function buildQueryStringFromFilterValues(filterValues: Partial Boolean(filter)); + .filter((filter): filter is string => !!filter); filtersString.push(...mappedFilters); From d823cca99de51e55c509699d6f841330fcca6a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Wed, 18 Sep 2024 08:29:40 +0200 Subject: [PATCH 5/5] fix typo --- src/libs/SearchUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts index 886f6388ad9f..9760ff80ca19 100644 --- a/src/libs/SearchUtils.ts +++ b/src/libs/SearchUtils.ts @@ -529,7 +529,7 @@ function buildSearchQueryString(queryJSON?: SearchQueryJSON) { * Given object with chosen search filters builds correct query string from them */ function buildQueryStringFromFilterValues(filterValues: Partial) { - // We separe type and status filters from other filters to maintain hashes consistency for saved searches + // We separate type and status filters from other filters to maintain hashes consistency for saved searches const {type, status, ...otherFilters} = filterValues; const filtersString: string[] = [];