diff --git a/src/CONST.ts b/src/CONST.ts
index d0695b1e285f..39b6902234b4 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -5395,11 +5395,6 @@ const CONST = {
DONE: 'done',
PAID: 'paid',
},
- CHAT_STATUS: {
- UNREAD: 'unread',
- PINNED: 'pinned',
- DRAFT: 'draft',
- },
BULK_ACTION_TYPES: {
EXPORT: 'export',
HOLD: 'hold',
@@ -5441,10 +5436,6 @@ const CONST = {
LINKS: 'links',
},
},
- CHAT_TYPES: {
- LINK: 'link',
- ATTACHMENT: 'attachment',
- },
TABLE_COLUMNS: {
RECEIPT: 'receipt',
DATE: 'date',
@@ -5492,8 +5483,6 @@ const CONST = {
REPORT_ID: 'reportID',
KEYWORD: 'keyword',
IN: 'in',
- HAS: 'has',
- IS: 'is',
},
},
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index a28c2ef4fc57..faa406136ec9 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -35,7 +35,7 @@ const ROUTES = {
SEARCH_CENTRAL_PANE: {
route: 'search',
- getRoute: ({query}: {query: SearchQueryString}) => `search?q=${query}` as const,
+ getRoute: ({query}: {query: SearchQueryString}) => `search?q=${encodeURIComponent(query)}` as const,
},
SEARCH_ADVANCED_FILTERS: 'search/filters',
SEARCH_ADVANCED_FILTERS_DATE: 'search/filters/date',
@@ -53,9 +53,6 @@ const ROUTES = {
SEARCH_ADVANCED_FILTERS_FROM: 'search/filters/from',
SEARCH_ADVANCED_FILTERS_TO: 'search/filters/to',
SEARCH_ADVANCED_FILTERS_IN: 'search/filters/in',
- SEARCH_ADVANCED_FILTERS_HAS: 'search/filters/has',
- SEARCH_ADVANCED_FILTERS_IS: 'search/filters/is',
-
SEARCH_REPORT: {
route: 'search/view/:reportID/:reportActionID?',
getRoute: (reportID: string, reportActionID?: string) => {
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 67ba5b84c9ec..27328c0c8951 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -47,8 +47,6 @@ const SCREENS = {
ADVANCED_FILTERS_FROM_RHP: 'Search_Advanced_Filters_From_RHP',
ADVANCED_FILTERS_TO_RHP: 'Search_Advanced_Filters_To_RHP',
ADVANCED_FILTERS_IN_RHP: 'Search_Advanced_Filters_In_RHP',
- ADVANCED_FILTERS_HAS_RHP: 'Search_Advanced_Filters_Has_RHP',
- ADVANCED_FILTERS_IS_RHP: 'Search_Advanced_Filters_Is_RHP',
TRANSACTION_HOLD_REASON_RHP: 'Search_Transaction_Hold_Reason_RHP',
BOTTOM_TAB: 'Search_Bottom_Tab',
},
diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx
index f336740a8558..5aa44fe914f2 100644
--- a/src/components/Search/SearchPageHeader.tsx
+++ b/src/components/Search/SearchPageHeader.tsx
@@ -298,6 +298,12 @@ function SearchPageHeader({queryJSON, hash, onSelectDeleteOption, setOfflineModa
return null;
}
+ const onPress = () => {
+ const values = SearchUtils.getFiltersFormValues(queryJSON);
+ SearchActions.updateAdvancedFilters(values);
+ Navigation.navigate(ROUTES.SEARCH_ADVANCED_FILTERS);
+ };
+
return (
Navigation.navigate(ROUTES.SEARCH_ADVANCED_FILTERS)}
+ onPress={onPress}
medium
/>
diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts
index b22c8e58e122..c1b5758763a7 100644
--- a/src/components/Search/types.ts
+++ b/src/components/Search/types.ts
@@ -50,7 +50,7 @@ type QueryFilter = {
value: string | number;
};
-type AdvancedFiltersKeys = ValueOf | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS;
+type AdvancedFiltersKeys = ValueOf;
type QueryFilters = {
[K in AdvancedFiltersKeys]?: QueryFilter[];
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 3d37787038ea..0fb15a8c834c 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -3918,12 +3918,9 @@ export default {
keyword: 'Keyword',
hasKeywords: 'Has keywords',
currency: 'Currency',
- has: 'Has',
link: 'Link',
- is: 'Is',
pinned: 'Pinned',
unread: 'Unread',
- draft: 'Draft',
amount: {
lessThan: (amount?: string) => `Less than ${amount ?? ''}`,
greaterThan: (amount?: string) => `Greater than ${amount ?? ''}`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index ff7650e9e02c..eddac07422b3 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -3969,12 +3969,9 @@ export default {
keyword: 'Palabra clave',
hasKeywords: 'Tiene palabras clave',
currency: 'Divisa',
- has: 'Tiene',
link: 'Enlace',
- is: 'Está',
pinned: 'Fijado',
unread: 'No leído',
- draft: 'Borrador',
amount: {
lessThan: (amount?: string) => `Menos de ${amount ?? ''}`,
greaterThan: (amount?: string) => `Más que ${amount ?? ''}`,
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 1b2390b17c39..76a9fad2749b 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -544,8 +544,6 @@ const SearchAdvancedFiltersModalStackNavigator = createModalStackNavigator require('@pages/Search/SearchAdvancedFiltersPage/SearchFiltersFromPage').default,
[SCREENS.SEARCH.ADVANCED_FILTERS_TO_RHP]: () => require('@pages/Search/SearchAdvancedFiltersPage/SearchFiltersToPage').default,
[SCREENS.SEARCH.ADVANCED_FILTERS_IN_RHP]: () => require('@pages/Search/SearchAdvancedFiltersPage/SearchFiltersInPage').default,
- [SCREENS.SEARCH.ADVANCED_FILTERS_HAS_RHP]: () => require('@pages/Search/SearchAdvancedFiltersPage/SearchFiltersHasPage').default,
- [SCREENS.SEARCH.ADVANCED_FILTERS_IS_RHP]: () => require('@pages/Search/SearchAdvancedFiltersPage/SearchFiltersIsPage').default,
});
const RestrictedActionModalStackNavigator = createModalStackNavigator({
diff --git a/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts b/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts
index ff3c60693cbc..ecdae4ed55b1 100755
--- a/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts
+++ b/src/libs/Navigation/linkingConfig/CENTRAL_PANE_TO_RHP_MAPPING.ts
@@ -61,7 +61,6 @@ const CENTRAL_PANE_TO_RHP_MAPPING: Partial> =
SCREENS.SEARCH.ADVANCED_FILTERS_TO_RHP,
SCREENS.SEARCH.ADVANCED_FILTERS_IN_RHP,
SCREENS.SEARCH.ADVANCED_FILTERS_CARD_RHP,
- SCREENS.SEARCH.ADVANCED_FILTERS_HAS_RHP,
],
[SCREENS.SETTINGS.SUBSCRIPTION.ROOT]: [
SCREENS.SETTINGS.SUBSCRIPTION.ADD_PAYMENT_CARD,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 65fb05f8d008..47bc5f421093 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -1082,8 +1082,6 @@ const config: LinkingOptions['config'] = {
[SCREENS.SEARCH.ADVANCED_FILTERS_FROM_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS_FROM,
[SCREENS.SEARCH.ADVANCED_FILTERS_TO_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS_TO,
[SCREENS.SEARCH.ADVANCED_FILTERS_IN_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS_IN,
- [SCREENS.SEARCH.ADVANCED_FILTERS_HAS_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS_HAS,
- [SCREENS.SEARCH.ADVANCED_FILTERS_IS_RHP]: ROUTES.SEARCH_ADVANCED_FILTERS_IS,
},
},
[SCREENS.RIGHT_MODAL.RESTRICTED_ACTION]: {
diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js
index 32fd834c1346..622c3f5f3c4a 100644
--- a/src/libs/SearchParser/searchParser.js
+++ b/src/libs/SearchParser/searchParser.js
@@ -200,14 +200,12 @@ function peg$parse(input, options) {
var peg$c17 = "cardID";
var peg$c18 = "from";
var peg$c19 = "expenseType";
- var peg$c20 = "has";
- var peg$c21 = "is";
- var peg$c22 = "type";
- var peg$c23 = "status";
- var peg$c24 = "sortBy";
- var peg$c25 = "sortOrder";
- var peg$c26 = "policyID";
- var peg$c27 = "\"";
+ var peg$c20 = "type";
+ var peg$c21 = "status";
+ var peg$c22 = "sortBy";
+ var peg$c23 = "sortOrder";
+ var peg$c24 = "policyID";
+ var peg$c25 = "\"";
var peg$r0 = /^[:=]/;
var peg$r1 = /^[^"\r\n]/;
@@ -237,21 +235,19 @@ function peg$parse(input, options) {
var peg$e20 = peg$literalExpectation("cardID", false);
var peg$e21 = peg$literalExpectation("from", false);
var peg$e22 = peg$literalExpectation("expenseType", false);
- var peg$e23 = peg$literalExpectation("has", false);
- var peg$e24 = peg$literalExpectation("is", false);
- var peg$e25 = peg$otherExpectation("default key");
- var peg$e26 = peg$literalExpectation("type", false);
- var peg$e27 = peg$literalExpectation("status", false);
- var peg$e28 = peg$literalExpectation("sortBy", false);
- var peg$e29 = peg$literalExpectation("sortOrder", false);
- var peg$e30 = peg$literalExpectation("policyID", false);
- var peg$e31 = peg$otherExpectation("quote");
- var peg$e32 = peg$literalExpectation("\"", false);
- var peg$e33 = peg$classExpectation(["\"", "\r", "\n"], true, false);
- var peg$e34 = peg$otherExpectation("word");
- var peg$e35 = peg$classExpectation([["A", "Z"], ["a", "z"], ["0", "9"], "_", "@", ".", "/", "#", "&", "+", "-", "\\", "'", ",", ";"], false, false);
- var peg$e36 = peg$otherExpectation("whitespace");
- var peg$e37 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false);
+ var peg$e23 = peg$otherExpectation("default key");
+ var peg$e24 = peg$literalExpectation("type", false);
+ var peg$e25 = peg$literalExpectation("status", false);
+ var peg$e26 = peg$literalExpectation("sortBy", false);
+ var peg$e27 = peg$literalExpectation("sortOrder", false);
+ var peg$e28 = peg$literalExpectation("policyID", false);
+ var peg$e29 = peg$otherExpectation("quote");
+ var peg$e30 = peg$literalExpectation("\"", false);
+ var peg$e31 = peg$classExpectation(["\"", "\r", "\n"], true, false);
+ var peg$e32 = peg$otherExpectation("word");
+ var peg$e33 = peg$classExpectation([["A", "Z"], ["a", "z"], ["0", "9"], "_", "@", ".", "/", "#", "&", "+", "-", "\\", "'", ",", ";"], false, false);
+ var peg$e34 = peg$otherExpectation("whitespace");
+ var peg$e35 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false);
var peg$f0 = function(filters) { return applyDefaults(filters); };
var peg$f1 = function(head, tail) {
@@ -853,30 +849,12 @@ function peg$parse(input, options) {
if (peg$silentFails === 0) { peg$fail(peg$e22); }
}
if (s1 === peg$FAILED) {
- if (input.substr(peg$currPos, 3) === peg$c20) {
- s1 = peg$c20;
- peg$currPos += 3;
+ if (input.substr(peg$currPos, 2) === peg$c11) {
+ s1 = peg$c11;
+ peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e23); }
- }
- if (s1 === peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c11) {
- s1 = peg$c11;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e14); }
- }
- if (s1 === peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c21) {
- s1 = peg$c21;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e24); }
- }
- }
+ if (peg$silentFails === 0) { peg$fail(peg$e14); }
}
}
}
@@ -913,44 +891,44 @@ function peg$parse(input, options) {
peg$silentFails++;
s0 = peg$currPos;
- if (input.substr(peg$currPos, 4) === peg$c22) {
- s1 = peg$c22;
+ if (input.substr(peg$currPos, 4) === peg$c20) {
+ s1 = peg$c20;
peg$currPos += 4;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e26); }
+ if (peg$silentFails === 0) { peg$fail(peg$e24); }
}
if (s1 === peg$FAILED) {
- if (input.substr(peg$currPos, 6) === peg$c23) {
- s1 = peg$c23;
+ if (input.substr(peg$currPos, 6) === peg$c21) {
+ s1 = peg$c21;
peg$currPos += 6;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e27); }
+ if (peg$silentFails === 0) { peg$fail(peg$e25); }
}
if (s1 === peg$FAILED) {
- if (input.substr(peg$currPos, 6) === peg$c24) {
- s1 = peg$c24;
+ if (input.substr(peg$currPos, 6) === peg$c22) {
+ s1 = peg$c22;
peg$currPos += 6;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e28); }
+ if (peg$silentFails === 0) { peg$fail(peg$e26); }
}
if (s1 === peg$FAILED) {
- if (input.substr(peg$currPos, 9) === peg$c25) {
- s1 = peg$c25;
+ if (input.substr(peg$currPos, 9) === peg$c23) {
+ s1 = peg$c23;
peg$currPos += 9;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e29); }
+ if (peg$silentFails === 0) { peg$fail(peg$e27); }
}
if (s1 === peg$FAILED) {
- if (input.substr(peg$currPos, 8) === peg$c26) {
- s1 = peg$c26;
+ if (input.substr(peg$currPos, 8) === peg$c24) {
+ s1 = peg$c24;
peg$currPos += 8;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e30); }
+ if (peg$silentFails === 0) { peg$fail(peg$e28); }
}
}
}
@@ -965,7 +943,7 @@ function peg$parse(input, options) {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e25); }
+ if (peg$silentFails === 0) { peg$fail(peg$e23); }
}
return s0;
@@ -1006,11 +984,11 @@ function peg$parse(input, options) {
peg$silentFails++;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
- s1 = peg$c27;
+ s1 = peg$c25;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e32); }
+ if (peg$silentFails === 0) { peg$fail(peg$e30); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1019,7 +997,7 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e33); }
+ if (peg$silentFails === 0) { peg$fail(peg$e31); }
}
while (s3 !== peg$FAILED) {
s2.push(s3);
@@ -1028,15 +1006,15 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e33); }
+ if (peg$silentFails === 0) { peg$fail(peg$e31); }
}
}
if (input.charCodeAt(peg$currPos) === 34) {
- s3 = peg$c27;
+ s3 = peg$c25;
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e32); }
+ if (peg$silentFails === 0) { peg$fail(peg$e30); }
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
@@ -1052,7 +1030,7 @@ function peg$parse(input, options) {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e31); }
+ if (peg$silentFails === 0) { peg$fail(peg$e29); }
}
return s0;
@@ -1069,7 +1047,7 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e35); }
+ if (peg$silentFails === 0) { peg$fail(peg$e33); }
}
if (s2 !== peg$FAILED) {
while (s2 !== peg$FAILED) {
@@ -1079,7 +1057,7 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e35); }
+ if (peg$silentFails === 0) { peg$fail(peg$e33); }
}
}
} else {
@@ -1093,7 +1071,7 @@ function peg$parse(input, options) {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e34); }
+ if (peg$silentFails === 0) { peg$fail(peg$e32); }
}
return s0;
@@ -1121,7 +1099,7 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e37); }
+ if (peg$silentFails === 0) { peg$fail(peg$e35); }
}
while (s1 !== peg$FAILED) {
s0.push(s1);
@@ -1130,12 +1108,12 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e37); }
+ if (peg$silentFails === 0) { peg$fail(peg$e35); }
}
}
peg$silentFails--;
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$e36); }
+ if (peg$silentFails === 0) { peg$fail(peg$e34); }
return s0;
}
diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy
index bea1e5cfd6ff..f9f681736c61 100644
--- a/src/libs/SearchParser/searchParser.peggy
+++ b/src/libs/SearchParser/searchParser.peggy
@@ -119,9 +119,7 @@ key "key"
/ "cardID"
/ "from"
/ "expenseType"
- / "has"
/ "in"
- / "is"
)
defaultKey "default key"
diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts
index 1b1fcaee8682..f488d90cfb89 100644
--- a/src/libs/SearchUtils.ts
+++ b/src/libs/SearchUtils.ts
@@ -22,7 +22,7 @@ import * as searchParser from './SearchParser/searchParser';
import * as TransactionUtils from './TransactionUtils';
import * as UserUtils from './UserUtils';
-type KeysOfFilterKeysObject = keyof typeof CONST.SEARCH.SYNTAX_FILTER_KEYS;
+type FilterKeys = keyof typeof CONST.SEARCH.SYNTAX_FILTER_KEYS;
const columnNamesToSortingProperty = {
[CONST.SEARCH.TABLE_COLUMNS.TO]: 'formattedTo' as const,
@@ -469,11 +469,11 @@ function buildAmountFilterQuery(filterValues: Partial
}
function sanitizeString(str: string) {
- const safeStr = str;
- if (safeStr.includes(' ') || safeStr.includes(',')) {
- return `"${safeStr}"`;
+ const regexp = /[<>,:= ]/g;
+ if (regexp.test(str)) {
+ return `"${str}"`;
}
- return safeStr;
+ return str;
}
function getExpenseTypeTranslationKey(expenseType: ValueOf): TranslationPaths {
@@ -488,46 +488,27 @@ function getExpenseTypeTranslationKey(expenseType: ValueOf): TranslationPaths {
- // eslint-disable-next-line default-case
- switch (has) {
- case CONST.SEARCH.CHAT_TYPES.LINK:
- return 'search.filters.link';
- case CONST.SEARCH.CHAT_TYPES.ATTACHMENT:
- return 'common.attachment';
- }
-}
-
-function getChatStatusTranslationKey(chatStatus: ValueOf): TranslationPaths {
- // eslint-disable-next-line default-case
- switch (chatStatus) {
- case CONST.SEARCH.CHAT_STATUS.PINNED:
- return 'search.filters.pinned';
- case CONST.SEARCH.CHAT_STATUS.UNREAD:
- return 'search.filters.unread';
- case CONST.SEARCH.CHAT_STATUS.DRAFT:
- return 'search.filters.draft';
- }
-}
-
/**
* Given object with chosen search filters builds correct query string from them
*/
function buildQueryStringFromFilters(filterValues: Partial) {
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 KeysOfFilterKeysObject[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === 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]}:${sanitizeString(filterValue as string)}`;
}
}
if (filterKey === FILTER_KEYS.KEYWORD && filterValue) {
- const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as KeysOfFilterKeysObject[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey);
- if (keyInCorrectForm) {
- return `${filterValue as string}`;
- }
+ const value = (filterValue as string).split(' ').map(sanitizeString).join(' ');
+ return `${value}`;
+ }
+ if (filterKey === FILTER_KEYS.TYPE && filterValue) {
+ return `${CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE}:${sanitizeString(filterValue as string)}`;
+ }
+ if (filterKey === FILTER_KEYS.STATUS && filterValue) {
+ return `${CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS}:${sanitizeString(filterValue as string)}`;
}
-
if (
(filterKey === FILTER_KEYS.CATEGORY ||
filterKey === FILTER_KEYS.CARD_ID ||
@@ -537,14 +518,12 @@ function buildQueryStringFromFilters(filterValues: Partial 0
) {
- const filterValueArray = filterValues[filterKey] ?? [];
- const keyInCorrectForm = (Object.keys(CONST.SEARCH.SYNTAX_FILTER_KEYS) as KeysOfFilterKeysObject[]).find((key) => CONST.SEARCH.SYNTAX_FILTER_KEYS[key] === filterKey);
+ 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(',')}`;
}
@@ -612,6 +591,57 @@ function getFilters(queryJSON: SearchQueryJSON) {
return filters;
}
+/**
+ * returns the values of the filters in a format that can be used in the SearchAdvancedFiltersForm as initial form values
+ */
+function getFiltersFormValues(queryJSON: SearchQueryJSON) {
+ const filters = getFilters(queryJSON);
+ const filterKeys = Object.keys(filters);
+ const filtersForm = {} as Partial;
+ for (const filterKey of filterKeys) {
+ if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.REPORT_ID || filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.MERCHANT || filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.DESCRIPTION) {
+ filtersForm[filterKey] = filters[filterKey]?.[0]?.value.toString();
+ }
+ if (
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.CATEGORY ||
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID ||
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE ||
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE ||
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG ||
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.CURRENCY ||
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM ||
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO ||
+ filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.IN
+ ) {
+ filtersForm[filterKey] = filters[filterKey]?.map((filter) => filter.value.toString());
+ }
+ if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.KEYWORD) {
+ filtersForm[filterKey] = filters[filterKey]
+ ?.map((filter) => filter.value.toString())
+ .map((filter) => {
+ if (filter.includes(' ')) {
+ return `"${filter}"`;
+ }
+ return filter;
+ })
+ .join(' ');
+ }
+ if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.DATE) {
+ filtersForm[FILTER_KEYS.DATE_BEFORE] = filters[filterKey]?.find((filter) => filter.operator === 'lt')?.value.toString();
+ filtersForm[FILTER_KEYS.DATE_AFTER] = filters[filterKey]?.find((filter) => filter.operator === 'gt')?.value.toString();
+ }
+ if (filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.AMOUNT) {
+ filtersForm[FILTER_KEYS.LESS_THAN] = filters[filterKey]?.find((filter) => filter.operator === 'lt')?.value.toString();
+ filtersForm[FILTER_KEYS.GREATER_THAN] = filters[filterKey]?.find((filter) => filter.operator === 'gt')?.value.toString();
+ }
+ }
+
+ filtersForm[FILTER_KEYS.TYPE] = queryJSON.type;
+ filtersForm[FILTER_KEYS.STATUS] = queryJSON.status;
+
+ return filtersForm;
+}
+
/**
* Given a SearchQueryJSON this function will try to find the value of policyID filter saved in query
* and return just the first policyID value from the filter.
@@ -680,6 +710,7 @@ export {
buildSearchQueryString,
getCurrentSearchParams,
getFilters,
+ getFiltersFormValues,
getPolicyIDFromSearchQuery,
getListItem,
getSearchHeaderTitle,
@@ -695,6 +726,4 @@ export {
buildCannedSearchQuery,
isCannedSearchQuery,
getExpenseTypeTranslationKey,
- getChatFiltersTranslationKey,
- getChatStatusTranslationKey,
};
diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts
index 020fc1bd2c30..2ca6f7ccf47f 100644
--- a/src/libs/actions/Search.ts
+++ b/src/libs/actions/Search.ts
@@ -1,5 +1,6 @@
import Onyx from 'react-native-onyx';
import type {OnyxUpdate} from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
import type {FormOnyxValues} from '@components/Form/types';
import type {SearchQueryJSON} from '@components/Search/types';
import * as API from '@libs/API';
@@ -10,6 +11,7 @@ import fileDownload from '@libs/fileDownload';
import enhanceParameters from '@libs/Network/enhanceParameters';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
+import FILTER_KEYS from '@src/types/form/SearchAdvancedFiltersForm';
import type {SearchTransaction} from '@src/types/onyx/SearchResults';
import * as Report from './Report';
@@ -128,10 +130,21 @@ function updateAdvancedFilters(values: Partial, null>> = {};
+ Object.values(FILTER_KEYS)
+ .filter((key) => key !== FILTER_KEYS.TYPE && key !== FILTER_KEYS.STATUS)
+ .forEach((key) => {
+ values[key] = null;
+ });
+
+ Onyx.merge(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, values);
+}
+
export {
search,
createTransactionThread,
@@ -140,5 +153,6 @@ export {
unholdMoneyRequestOnSearch,
exportSearchItemsToCSV,
updateAdvancedFilters,
+ clearAllFilters,
clearAdvancedFilters,
};
diff --git a/src/pages/Search/AdvancedSearchFilters.tsx b/src/pages/Search/AdvancedSearchFilters.tsx
index 7775825f33de..aa0f6ce85802 100644
--- a/src/pages/Search/AdvancedSearchFilters.tsx
+++ b/src/pages/Search/AdvancedSearchFilters.tsx
@@ -1,4 +1,3 @@
-import {Str} from 'expensify-common';
import React from 'react';
import {View} from 'react-native';
import type {ValueOf} from 'react-native-gesture-handler/lib/typescript/typeUtils';
@@ -98,28 +97,18 @@ const baseFilterConfig = {
description: 'common.to' as const,
route: ROUTES.SEARCH_ADVANCED_FILTERS_TO,
},
- has: {
- getTitle: getFilterHasDisplayTitle,
- description: 'search.filters.has' as const,
- route: ROUTES.SEARCH_ADVANCED_FILTERS_HAS,
- },
in: {
getTitle: getFilterInDisplayTitle,
description: 'common.in' as const,
route: ROUTES.SEARCH_ADVANCED_FILTERS_IN,
},
- is: {
- getTitle: getFilterIsDisplayTitle,
- description: 'search.filters.is' as const,
- route: ROUTES.SEARCH_ADVANCED_FILTERS_IS,
- },
};
const typeFiltersKeys: Record>> = {
[CONST.SEARCH.DATA_TYPES.EXPENSE]: ['date', 'currency', 'merchant', 'description', 'reportID', 'amount', 'category', 'keyword', 'taxRate', 'expenseType', 'tag', 'from', 'to', 'cardID'],
[CONST.SEARCH.DATA_TYPES.INVOICE]: ['date', 'currency', 'merchant', 'description', 'reportID', 'amount', 'category', 'keyword', 'taxRate', 'tag', 'from', 'to', 'cardID'],
[CONST.SEARCH.DATA_TYPES.TRIP]: ['date', 'currency', 'merchant', 'description', 'reportID', 'amount', 'category', 'keyword', 'taxRate', 'tag', 'from', 'to', 'cardID'],
- [CONST.SEARCH.DATA_TYPES.CHAT]: ['date', 'keyword', 'from', 'has', 'in', 'is'],
+ [CONST.SEARCH.DATA_TYPES.CHAT]: ['date', 'keyword', 'from', 'in'],
};
function getFilterCardDisplayTitle(filters: Partial, cards: CardList) {
@@ -175,6 +164,8 @@ function getFilterDisplayTitle(filters: Partial, fiel
if (greaterThan) {
return translate('search.filters.amount.greaterThan', convertToDisplayStringWithoutCurrency(Number(greaterThan)));
}
+ // Will never happen
+ return;
}
if (
@@ -189,11 +180,8 @@ function getFilterDisplayTitle(filters: Partial, fiel
return filters[fieldName];
}
- // Todo Once all Advanced filters are implemented this line can be cleaned up. See: https://github.com/Expensify/App/issues/45026
- // @ts-expect-error this property access is temporarily an error, because not every SYNTAX_FILTER_KEYS is handled by form.
- // When all filters are updated here: src/types/form/SearchAdvancedFiltersForm.ts this line comment + type cast can be removed.
- const filterValue = filters[fieldName] as string;
- return filterValue ? Str.recapitalize(filterValue) : undefined;
+ const filterValue = filters[fieldName];
+ return Array.isArray(filterValue) ? filterValue.join(', ') : filterValue;
}
function getFilterTaxRateDisplayTitle(filters: Partial, taxRates: Record) {
@@ -226,27 +214,6 @@ function getFilterExpenseDisplayTitle(filters: Partial, translate: LocaleContextProps['translate'], reports?: OnyxCollection) {
return filters.in ? filters.in.map((id) => ReportUtils.getReportName(reports?.[`${ONYXKEYS.COLLECTION.REPORT}${id}`])).join(', ') : undefined;
}
-
-function getFilterHasDisplayTitle(filters: Partial, translate: LocaleContextProps['translate']) {
- const filterValue = filters[CONST.SEARCH.SYNTAX_FILTER_KEYS.HAS];
- return filterValue
- ? Object.values(CONST.SEARCH.CHAT_TYPES)
- .filter((hasFilter) => filterValue.includes(hasFilter))
- .map((hasFilter) => translate(SearchUtils.getChatFiltersTranslationKey(hasFilter)))
- .join(', ')
- : undefined;
-}
-
-function getFilterIsDisplayTitle(filters: Partial, translate: LocaleContextProps['translate']) {
- const filterValue = filters[CONST.SEARCH.SYNTAX_FILTER_KEYS.IS];
- return filterValue
- ? Object.values(CONST.SEARCH.CHAT_STATUS)
- .filter((chatStatus) => filterValue.includes(chatStatus))
- .map((chatStatus) => translate(SearchUtils.getChatStatusTranslationKey(chatStatus)))
- .join(', ')
- : undefined;
-}
-
function AdvancedSearchFilters() {
const {translate} = useLocalize();
const styles = useThemeStyles();
@@ -262,7 +229,7 @@ function AdvancedSearchFilters() {
const onFormSubmit = () => {
const query = SearchUtils.buildQueryStringFromFilters(searchAdvancedFilters);
- SearchActions.clearAdvancedFilters();
+ SearchActions.clearAllFilters();
Navigation.dismissModal();
Navigation.navigate(
ROUTES.SEARCH_CENTRAL_PANE.getRoute({
@@ -293,7 +260,7 @@ function AdvancedSearchFilters() {
filterTitle = baseFilterConfig[key].getTitle(searchAdvancedFilters, cardList);
} else if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAX_RATE) {
filterTitle = baseFilterConfig[key].getTitle(searchAdvancedFilters, taxRates);
- } else if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE || key === CONST.SEARCH.SYNTAX_FILTER_KEYS.HAS || key === CONST.SEARCH.SYNTAX_FILTER_KEYS.IS) {
+ } else if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.EXPENSE_TYPE) {
filterTitle = baseFilterConfig[key].getTitle(searchAdvancedFilters, translate);
} else if (key === CONST.SEARCH.SYNTAX_FILTER_KEYS.FROM || key === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO) {
filterTitle = baseFilterConfig[key].getTitle(searchAdvancedFilters[key] ?? [], personalDetails);
diff --git a/src/pages/Search/SearchAdvancedFiltersPage.tsx b/src/pages/Search/SearchAdvancedFiltersPage.tsx
index 9c205de2433b..687e04c7341b 100644
--- a/src/pages/Search/SearchAdvancedFiltersPage.tsx
+++ b/src/pages/Search/SearchAdvancedFiltersPage.tsx
@@ -6,6 +6,7 @@ import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as SearchActions from '@userActions/Search';
+import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {SearchAdvancedFiltersForm} from '@src/types/form';
import AdvancedSearchFilters from './AdvancedSearchFilters';
@@ -17,7 +18,9 @@ function SearchAdvancedFiltersPage() {
const emptySearchFilters: SearchAdvancedFiltersForm = {} as SearchAdvancedFiltersForm;
const [searchAdvancedFilters = emptySearchFilters] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM);
- const shouldShowResetFilters = Object.values(searchAdvancedFilters).some((value) => (Array.isArray(value) ? value.length !== 0 : !!value));
+ const shouldShowResetFilters = Object.entries(searchAdvancedFilters)
+ .filter(([key]) => CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE !== key && CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS !== key)
+ .some(([, value]) => (Array.isArray(value) ? value.length !== 0 : !!value));
return (
[
- {
- name: translate('common.attachment'),
- value: CONST.SEARCH.CHAT_TYPES.ATTACHMENT,
- },
- {
- name: translate('search.filters.link'),
- value: CONST.SEARCH.CHAT_TYPES.LINK,
- },
- ],
- [translate],
- );
-
- const selectedOptions = useMemo(() => {
- return searchAdvancedFiltersForm?.has?.map((value) => filterItems.find((filterItem) => filterItem.value === value)).filter((item): item is FilterItem => item !== undefined) ?? [];
- }, [searchAdvancedFiltersForm, filterItems]);
-
- const updateHasFilter = useCallback((values: string[]) => SearchActions.updateAdvancedFilters({has: values}), []);
-
- return (
-
- {
- Navigation.goBack(ROUTES.SEARCH_ADVANCED_FILTERS);
- }}
- />
-
-
-
-
- );
-}
-
-SearchFiltersHasPage.displayName = 'SearchFiltersHasPage';
-
-export default SearchFiltersHasPage;
diff --git a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersIsPage.tsx b/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersIsPage.tsx
deleted file mode 100644
index d2431776eb44..000000000000
--- a/src/pages/Search/SearchAdvancedFiltersPage/SearchFiltersIsPage.tsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import React, {useCallback, useMemo} from 'react';
-import {View} from 'react-native';
-import {useOnyx} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import SearchMultipleSelectionPicker from '@components/Search/SearchMultipleSelectionPicker';
-import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
-import {getChatStatusTranslationKey} from '@libs/SearchUtils';
-import * as SearchActions from '@userActions/Search';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES from '@src/ROUTES';
-
-function SearchFiltersIsPage() {
- const styles = useThemeStyles();
- const {translate} = useLocalize();
-
- const [searchAdvancedFiltersForm] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM);
- const selectedChatStatuses = searchAdvancedFiltersForm?.is?.map((chatStatus) => {
- const chatStatusName = translate(getChatStatusTranslationKey(chatStatus as ValueOf));
- return {name: chatStatusName, value: chatStatus};
- });
- const allChatStatuses = Object.values(CONST.SEARCH.CHAT_STATUS);
-
- const chatStatusItems = useMemo(() => {
- return allChatStatuses.map((chatStatus) => {
- const chatStatusName = translate(getChatStatusTranslationKey(chatStatus));
- return {name: chatStatusName, value: chatStatus};
- });
- }, [allChatStatuses, translate]);
-
- const updateChatIsFilter = useCallback((values: string[]) => SearchActions.updateAdvancedFilters({is: values}), []);
-
- return (
-
- {
- Navigation.goBack(ROUTES.SEARCH_ADVANCED_FILTERS);
- }}
- />
-
-
-
-
- );
-}
-
-SearchFiltersIsPage.displayName = 'SearchFiltersIsPage';
-
-export default SearchFiltersIsPage;
diff --git a/src/pages/Search/SearchTypeMenu.tsx b/src/pages/Search/SearchTypeMenu.tsx
index a83fd364fa4a..84373b0d4964 100644
--- a/src/pages/Search/SearchTypeMenu.tsx
+++ b/src/pages/Search/SearchTypeMenu.tsx
@@ -6,6 +6,7 @@ import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSingleExecution from '@hooks/useSingleExecution';
import useThemeStyles from '@hooks/useThemeStyles';
+import * as SearchActions from '@libs/actions/Search';
import Navigation from '@libs/Navigation/Navigation';
import * as SearchUtils from '@libs/SearchUtils';
import variables from '@styles/variables';
@@ -72,6 +73,7 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) {
);
@@ -80,7 +82,10 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) {
return (
{typeMenuItems.map((item, index) => {
- const onPress = singleExecution(() => Navigation.navigate(item.route));
+ const onPress = singleExecution(() => {
+ SearchActions.clearAllFilters();
+ Navigation.navigate(item.route);
+ });
return (