diff --git a/src/CONST.ts b/src/CONST.ts index 8c8d82aa43f1..14008f1ca3cc 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6295,6 +6295,7 @@ const CONST = { SORT_BY: 'sortBy', SORT_ORDER: 'sortOrder', POLICY_ID: 'policyID', + GROUP_BY: 'groupBy', }, SYNTAX_FILTER_KEYS: { DATE: 'date', @@ -6331,6 +6332,7 @@ const CONST = { SORT_BY: 'sort-by', SORT_ORDER: 'sort-order', POLICY_ID: 'workspace', + GROUP_BY: 'group-by', DATE: 'date', AMOUNT: 'amount', EXPENSE_TYPE: 'expense-type', diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 41fd4b830f12..192aebba60c6 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -39,8 +39,8 @@ const ROUTES = { SEARCH_ROOT: { route: 'search', - getRoute: ({query, name, groupBy}: {query: SearchQueryString; name?: string; groupBy?: string}) => { - return `search?q=${encodeURIComponent(query)}${groupBy ? `&groupBy=${groupBy}` : ''}${name ? `&name=${name}` : ''}` as const; + getRoute: ({query, name}: {query: SearchQueryString; name?: string}) => { + return `search?q=${encodeURIComponent(query)}${name ? `&name=${name}` : ''}` as const; }, }, SEARCH_SAVED_SEARCH_RENAME: { diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index ea8d923d9e8e..9407c59718bd 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -156,6 +156,7 @@ function SearchAutocompleteList( const [isInitialRender, setIsInitialRender] = useState(true); const typeAutocompleteList = Object.values(CONST.SEARCH.DATA_TYPES); + const groupByAutocompleteList = Object.values(CONST.SEARCH.GROUP_BY); const statusAutocompleteList = Object.values({...CONST.SEARCH.STATUS.EXPENSE, ...CONST.SEARCH.STATUS.INVOICE, ...CONST.SEARCH.STATUS.CHAT, ...CONST.SEARCH.STATUS.TRIP}); const expenseTypes = Object.values(CONST.SEARCH.TRANSACTION_TYPE); @@ -337,6 +338,12 @@ function SearchAutocompleteList( return filteredTypes.map((type) => ({filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TYPE, text: type})); } + case CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY: { + const filteredGroupBy = groupByAutocompleteList.filter( + (groupByValue) => groupByValue.toLowerCase().includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(groupByValue.toLowerCase()), + ); + return filteredGroupBy.map((groupByValue) => ({filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.GROUP_BY, text: groupByValue})); + } case CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS: { const filteredStatuses = statusAutocompleteList .filter((status) => status.includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(status)) @@ -405,6 +412,7 @@ function SearchAutocompleteList( workspaceCardFeeds, cardAutocompleteList, allCards, + groupByAutocompleteList, ]); const sortedRecentSearches = useMemo(() => { diff --git a/src/components/Search/SearchPageHeader/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader/SearchPageHeader.tsx index a3b814650a23..9aa1bbe3ce1b 100644 --- a/src/components/Search/SearchPageHeader/SearchPageHeader.tsx +++ b/src/components/Search/SearchPageHeader/SearchPageHeader.tsx @@ -46,12 +46,11 @@ type SearchPageHeaderProps = { searchRouterListVisible?: boolean; hideSearchRouterList?: () => void; onSearchRouterFocus?: () => void; - shouldGroupByReports?: boolean; }; type SearchHeaderOptionValue = DeepValueOf | undefined; -function SearchPageHeader({queryJSON, searchName, searchRouterListVisible, hideSearchRouterList, onSearchRouterFocus, shouldGroupByReports}: SearchPageHeaderProps) { +function SearchPageHeader({queryJSON, searchName, searchRouterListVisible, hideSearchRouterList, onSearchRouterFocus}: SearchPageHeaderProps) { const {translate} = useLocalize(); const theme = useTheme(); const styles = useThemeStyles(); @@ -432,7 +431,6 @@ function SearchPageHeader({queryJSON, searchName, searchRouterListVisible, hideS searchName={searchName} hideSearchRouterList={hideSearchRouterList} inputRightComponent={InputRightComponent} - shouldGroupByReports={shouldGroupByReports} /> void; searchName?: string; inputRightComponent: React.ReactNode; - shouldGroupByReports?: boolean; }; -function SearchPageHeaderInput({ - queryJSON, - searchRouterListVisible, - hideSearchRouterList, - onSearchRouterFocus, - searchName, - inputRightComponent, - shouldGroupByReports, -}: SearchPageHeaderInputProps) { +function SearchPageHeaderInput({queryJSON, searchRouterListVisible, hideSearchRouterList, onSearchRouterFocus, searchName, inputRightComponent}: SearchPageHeaderInputProps) { const {translate} = useLocalize(); const [showPopupButton, setShowPopupButton] = useState(true); const styles = useThemeStyles(); @@ -271,7 +262,6 @@ function SearchPageHeaderInput({ > diff --git a/src/components/Search/SearchPageHeader/SearchTypeMenuPopover.tsx b/src/components/Search/SearchPageHeader/SearchTypeMenuPopover.tsx index 812a109a8f59..ef1b90389978 100644 --- a/src/components/Search/SearchPageHeader/SearchTypeMenuPopover.tsx +++ b/src/components/Search/SearchPageHeader/SearchTypeMenuPopover.tsx @@ -39,16 +39,15 @@ type SavedSearchMenuItem = MenuItemWithLink & { type SearchTypeMenuNarrowProps = { queryJSON: SearchQueryJSON; searchName?: string; - shouldGroupByReports?: boolean; }; -function SearchTypeMenuPopover({queryJSON, searchName, shouldGroupByReports}: SearchTypeMenuNarrowProps) { +function SearchTypeMenuPopover({queryJSON, searchName}: SearchTypeMenuNarrowProps) { const theme = useTheme(); const styles = useThemeStyles(); const {singleExecution} = useSingleExecution(); const {windowHeight} = useWindowDimensions(); const {translate} = useLocalize(); - const {hash, policyID} = queryJSON; + const {hash, policyID, groupBy} = queryJSON; const {showDeleteModal, DeleteConfirmModal} = useDeleteSavedSearch(); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY); const [session] = useOnyx(ONYXKEYS.SESSION); @@ -59,6 +58,7 @@ function SearchTypeMenuPopover({queryJSON, searchName, shouldGroupByReports}: Se const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST); const allCards = useMemo(() => mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, userCardList), [userCardList, workspaceCardFeeds]); const {unmodifiedPaddings} = useStyledSafeAreaInsets(); + const shouldGroupByReports = groupBy === CONST.SEARCH.GROUP_BY.REPORTS; const cardFeedNamesWithType = useMemo(() => { return getCardFeedNamesWithType({workspaceCardFeeds, userCardList, translate}); }, [translate, workspaceCardFeeds, userCardList]); diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 02f5581c2d96..b14011d03df5 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -51,7 +51,6 @@ type SearchProps = { contentContainerStyle?: StyleProp; isSearchScreenFocused?: boolean; onContentSizeChange?: (w: number, h: number) => void; - shouldGroupByReports?: boolean; }; const transactionItemMobileHeight = 100; @@ -126,7 +125,7 @@ function prepareTransactionsList(item: TransactionListItemType, selectedTransact }; } -function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentContainerStyle, onContentSizeChange, shouldGroupByReports}: SearchProps) { +function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentContainerStyle, onContentSizeChange}: SearchProps) { const {isOffline} = useNetwork(); const {shouldUseNarrowLayout} = useResponsiveLayout(); const styles = useThemeStyles(); @@ -149,13 +148,14 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo const {selectionMode} = useMobileSelectionMode(); const [offset, setOffset] = useState(0); - const {type, status, sortBy, sortOrder, hash} = queryJSON; + const {type, status, sortBy, sortOrder, hash, groupBy} = queryJSON; const [currentSearchResults] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`); const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION); const previousTransactions = usePrevious(transactions); const [reportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS); const previousReportActions = usePrevious(reportActions); + const shouldGroupByReports = groupBy === CONST.SEARCH.GROUP_BY.REPORTS; useEffect(() => { if (!currentSearchResults?.search?.type) { @@ -266,7 +266,7 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo return []; } return getSections(type, status, searchResults.data, searchResults.search, shouldGroupByReports); - }, [searchResults, status, type, shouldGroupByReports]); + }, [searchResults, type, status, shouldGroupByReports]); useEffect(() => { /** We only want to display the skeleton for the status filters the first time we load them for a specific data type */ diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index 3dc408cc27c3..d5be6bb83cf4 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -58,6 +58,7 @@ type InvoiceSearchStatus = ValueOf; type TripSearchStatus = ValueOf; type ChatSearchStatus = ValueOf; type SearchStatus = ExpenseSearchStatus | InvoiceSearchStatus | TripSearchStatus | ChatSearchStatus | Array; +type SearchGroupBy = ValueOf; type SearchContext = { currentSearchHash: number; @@ -96,7 +97,8 @@ type SearchFilterKey = | ValueOf | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS - | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID; + | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID + | typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY; type UserFriendlyKey = ValueOf; @@ -112,6 +114,7 @@ type SearchQueryAST = { status: SearchStatus; sortBy: SearchColumnType; sortOrder: SortOrder; + groupBy?: SearchGroupBy; filters: ASTNode; policyID?: string; }; diff --git a/src/libs/SearchAutocompleteUtils.ts b/src/libs/SearchAutocompleteUtils.ts index 8d81ce7da593..613e425b0725 100644 --- a/src/libs/SearchAutocompleteUtils.ts +++ b/src/libs/SearchAutocompleteUtils.ts @@ -148,6 +148,7 @@ function filterOutRangesWithCorrectValue( const typeList = Object.values(CONST.SEARCH.DATA_TYPES) as string[]; const expenseTypeList = Object.values(CONST.SEARCH.TRANSACTION_TYPE) as string[]; const statusList = Object.values({...CONST.SEARCH.STATUS.EXPENSE, ...CONST.SEARCH.STATUS.INVOICE, ...CONST.SEARCH.STATUS.CHAT, ...CONST.SEARCH.STATUS.TRIP}) as string[]; + const groupByList = Object.values(CONST.SEARCH.GROUP_BY) as string[]; switch (range.key) { case CONST.SEARCH.SYNTAX_FILTER_KEYS.IN: @@ -172,6 +173,8 @@ function filterOutRangesWithCorrectValue( return categoryList.get().includes(range.value); case CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG: return tagList.get().includes(range.value); + case CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY: + return groupByList.includes(range.value); default: return false; } diff --git a/src/libs/SearchParser/autocompleteParser.js b/src/libs/SearchParser/autocompleteParser.js index fae0339d4ac9..5ee9b3942896 100644 --- a/src/libs/SearchParser/autocompleteParser.js +++ b/src/libs/SearchParser/autocompleteParser.js @@ -215,12 +215,14 @@ function peg$parse(input, options) { var peg$c29 = "paid"; var peg$c30 = "exported"; var peg$c31 = "posted"; - var peg$c32 = "feed"; - var peg$c33 = "!="; - var peg$c34 = ">="; - var peg$c35 = ">"; - var peg$c36 = "<="; - var peg$c37 = "<"; + var peg$c32 = "groupby"; + var peg$c33 = "group-by"; + var peg$c34 = "feed"; + var peg$c35 = "!="; + var peg$c36 = ">="; + var peg$c37 = ">"; + var peg$c38 = "<="; + var peg$c39 = "<"; var peg$r0 = /^[:=]/; var peg$r1 = /^[^ ,"\u201D\u201C\t\n\r\xA0]/; @@ -262,22 +264,24 @@ function peg$parse(input, options) { var peg$e30 = peg$literalExpectation("paid", true); var peg$e31 = peg$literalExpectation("exported", true); var peg$e32 = peg$literalExpectation("posted", true); - var peg$e33 = peg$literalExpectation("feed", true); - var peg$e34 = peg$otherExpectation("operator"); - var peg$e35 = peg$classExpectation([":", "="], false, false); - var peg$e36 = peg$literalExpectation("!=", false); - var peg$e37 = peg$literalExpectation(">=", false); - var peg$e38 = peg$literalExpectation(">", false); - var peg$e39 = peg$literalExpectation("<=", false); - var peg$e40 = peg$literalExpectation("<", false); - var peg$e41 = peg$otherExpectation("quote"); - var peg$e42 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e43 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e44 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e45 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e46 = peg$otherExpectation("word"); - var peg$e47 = peg$otherExpectation("whitespace"); - var peg$e48 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e33 = peg$literalExpectation("groupBy", true); + var peg$e34 = peg$literalExpectation("group-by", true); + var peg$e35 = peg$literalExpectation("feed", true); + var peg$e36 = peg$otherExpectation("operator"); + var peg$e37 = peg$classExpectation([":", "="], false, false); + var peg$e38 = peg$literalExpectation("!=", false); + var peg$e39 = peg$literalExpectation(">=", false); + var peg$e40 = peg$literalExpectation(">", false); + var peg$e41 = peg$literalExpectation("<=", false); + var peg$e42 = peg$literalExpectation("<", false); + var peg$e43 = peg$otherExpectation("quote"); + var peg$e44 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e45 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e46 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e47 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e48 = peg$otherExpectation("word"); + var peg$e49 = peg$otherExpectation("whitespace"); + var peg$e50 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); var peg$f0 = function(ranges) { return { autocomplete, ranges }; }; var peg$f1 = function(filters) { return filters.filter(Boolean).flat(); }; @@ -351,18 +355,19 @@ function peg$parse(input, options) { var peg$f27 = function() { return "paid"; }; var peg$f28 = function() { return "exported"; }; var peg$f29 = function() { return "posted"; }; - var peg$f30 = function() { return "feed"; }; - var peg$f31 = function() { return "eq"; }; - var peg$f32 = function() { return "neq"; }; - var peg$f33 = function() { return "gte"; }; - var peg$f34 = function() { return "gt"; }; - var peg$f35 = function() { return "lte"; }; - var peg$f36 = function() { return "lt"; }; - var peg$f37 = function(start, inner, end) { //handle no-breaking space + var peg$f30 = function() { return "groupBy"; }; + var peg$f31 = function() { return "feed"; }; + var peg$f32 = function() { return "eq"; }; + var peg$f33 = function() { return "neq"; }; + var peg$f34 = function() { return "gte"; }; + var peg$f35 = function() { return "gt"; }; + var peg$f36 = function() { return "lte"; }; + var peg$f37 = function() { return "lt"; }; + var peg$f38 = function(start, inner, end) { //handle no-breaking space return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f38 = function(chars) { return chars.join("").trim(); }; - var peg$f39 = function() { return "and"; }; + var peg$f39 = function(chars) { return chars.join("").trim(); }; + var peg$f40 = function() { return "and"; }; var peg$currPos = options.peg$currPos | 0; var peg$savedPos = peg$currPos; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -665,6 +670,9 @@ function peg$parse(input, options) { s1 = peg$parsecardID(); if (s1 === peg$FAILED) { s1 = peg$parsefeed(); + if (s1 === peg$FAILED) { + s1 = peg$parsegroupBy(); + } } } } @@ -1307,20 +1315,49 @@ function peg$parse(input, options) { return s0; } + function peg$parsegroupBy() { + var s0, s1; + + s0 = input.substr(peg$currPos, 7); + if (s0.toLowerCase() === peg$c32) { + peg$currPos += 7; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e33); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c33) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e34); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f30(); + } + s0 = s1; + } + + return s0; + } + function peg$parsefeed() { var s0, s1; s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c32) { + if (s1.toLowerCase() === peg$c34) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e33); } + if (peg$silentFails === 0) { peg$fail(peg$e35); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f30(); + s1 = peg$f31(); } s0 = s1; @@ -1337,81 +1374,81 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f31(); + s1 = peg$f32(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c33) { - s1 = peg$c33; + if (input.substr(peg$currPos, 2) === peg$c35) { + s1 = peg$c35; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f32(); + s1 = peg$f33(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c34) { - s1 = peg$c34; + if (input.substr(peg$currPos, 2) === peg$c36) { + s1 = peg$c36; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e37); } + if (peg$silentFails === 0) { peg$fail(peg$e39); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f33(); + s1 = peg$f34(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c35; + s1 = peg$c37; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f34(); + s1 = peg$f35(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c36) { - s1 = peg$c36; + if (input.substr(peg$currPos, 2) === peg$c38) { + s1 = peg$c38; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f35(); + s1 = peg$f36(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c37; + s1 = peg$c39; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f36(); + s1 = peg$f37(); } s0 = s1; } @@ -1422,7 +1459,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$e36); } } return s0; @@ -1439,7 +1476,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -1448,7 +1485,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } } s2 = input.charAt(peg$currPos); @@ -1456,7 +1493,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e43); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } if (s2 !== peg$FAILED) { s3 = []; @@ -1465,7 +1502,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e44); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -1474,7 +1511,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e44); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } } s4 = input.charAt(peg$currPos); @@ -1482,7 +1519,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e43); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } if (s4 !== peg$FAILED) { s5 = []; @@ -1491,7 +1528,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -1500,11 +1537,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } } peg$savedPos = s0; - s0 = peg$f37(s1, s3, s5); + s0 = peg$f38(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1516,7 +1553,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e41); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } return s0; @@ -1533,7 +1570,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -1543,7 +1580,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } } } else { @@ -1551,13 +1588,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f38(s1); + s1 = peg$f39(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e46); } + if (peg$silentFails === 0) { peg$fail(peg$e48); } } return s0; @@ -1569,7 +1606,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f39(); + s1 = peg$f40(); s0 = s1; return s0; @@ -1585,7 +1622,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e48); } + if (peg$silentFails === 0) { peg$fail(peg$e50); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1594,12 +1631,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e48); } + if (peg$silentFails === 0) { peg$fail(peg$e50); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e47); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } return s0; } diff --git a/src/libs/SearchParser/autocompleteParser.peggy b/src/libs/SearchParser/autocompleteParser.peggy index ddb472d2e2cc..8ed9e00c6869 100644 --- a/src/libs/SearchParser/autocompleteParser.peggy +++ b/src/libs/SearchParser/autocompleteParser.peggy @@ -67,6 +67,7 @@ autocompleteKey "key" / status / cardID / feed + / groupBy ) identifier diff --git a/src/libs/SearchParser/baseRules.peggy b/src/libs/SearchParser/baseRules.peggy index c6f9bdbebebd..d141746e7d19 100644 --- a/src/libs/SearchParser/baseRules.peggy +++ b/src/libs/SearchParser/baseRules.peggy @@ -46,6 +46,7 @@ approved = "approved"i { return "approved"; } paid = "paid"i { return "paid"; } exported = "exported"i { return "exported"; } posted = "posted"i { return "posted"; } +groupBy = "groupBy"i / "group-by"i { return "groupBy"; } feed = "feed"i { return "feed"; } operator "operator" diff --git a/src/libs/SearchParser/searchParser.js b/src/libs/SearchParser/searchParser.js index cedcd1af5991..446554bb4bc9 100644 --- a/src/libs/SearchParser/searchParser.js +++ b/src/libs/SearchParser/searchParser.js @@ -216,12 +216,14 @@ function peg$parse(input, options) { var peg$c29 = "paid"; var peg$c30 = "exported"; var peg$c31 = "posted"; - var peg$c32 = "feed"; - var peg$c33 = "!="; - var peg$c34 = ">="; - var peg$c35 = ">"; - var peg$c36 = "<="; - var peg$c37 = "<"; + var peg$c32 = "groupby"; + var peg$c33 = "group-by"; + var peg$c34 = "feed"; + var peg$c35 = "!="; + var peg$c36 = ">="; + var peg$c37 = ">"; + var peg$c38 = "<="; + var peg$c39 = "<"; var peg$r0 = /^[^ \t\r\n\xA0]/; var peg$r1 = /^[:=]/; @@ -266,22 +268,24 @@ function peg$parse(input, options) { var peg$e32 = peg$literalExpectation("paid", true); var peg$e33 = peg$literalExpectation("exported", true); var peg$e34 = peg$literalExpectation("posted", true); - var peg$e35 = peg$literalExpectation("feed", true); - var peg$e36 = peg$otherExpectation("operator"); - var peg$e37 = peg$classExpectation([":", "="], false, false); - var peg$e38 = peg$literalExpectation("!=", false); - var peg$e39 = peg$literalExpectation(">=", false); - var peg$e40 = peg$literalExpectation(">", false); - var peg$e41 = peg$literalExpectation("<=", false); - var peg$e42 = peg$literalExpectation("<", false); - var peg$e43 = peg$otherExpectation("quote"); - var peg$e44 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e45 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); - var peg$e46 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); - var peg$e47 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); - var peg$e48 = peg$otherExpectation("word"); - var peg$e49 = peg$otherExpectation("whitespace"); - var peg$e50 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); + var peg$e35 = peg$literalExpectation("groupBy", true); + var peg$e36 = peg$literalExpectation("group-by", true); + var peg$e37 = peg$literalExpectation("feed", true); + var peg$e38 = peg$otherExpectation("operator"); + var peg$e39 = peg$classExpectation([":", "="], false, false); + var peg$e40 = peg$literalExpectation("!=", false); + var peg$e41 = peg$literalExpectation(">=", false); + var peg$e42 = peg$literalExpectation(">", false); + var peg$e43 = peg$literalExpectation("<=", false); + var peg$e44 = peg$literalExpectation("<", false); + var peg$e45 = peg$otherExpectation("quote"); + var peg$e46 = peg$classExpectation([" ", ",", "\"", "\u201D", "\u201C", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e47 = peg$classExpectation(["\"", ["\u201C", "\u201D"]], false, false); + var peg$e48 = peg$classExpectation(["\"", "\u201D", "\u201C", "\r", "\n"], true, false); + var peg$e49 = peg$classExpectation([" ", ",", "\t", "\n", "\r", "\xA0"], true, false); + var peg$e50 = peg$otherExpectation("word"); + var peg$e51 = peg$otherExpectation("whitespace"); + var peg$e52 = peg$classExpectation([" ", "\t", "\r", "\n", "\xA0"], false, false); var peg$f0 = function(filters) { return applyDefaults(filters); }; var peg$f1 = function(head, tail) { @@ -368,18 +372,19 @@ function peg$parse(input, options) { var peg$f28 = function() { return "paid"; }; var peg$f29 = function() { return "exported"; }; var peg$f30 = function() { return "posted"; }; - var peg$f31 = function() { return "feed"; }; - var peg$f32 = function() { return "eq"; }; - var peg$f33 = function() { return "neq"; }; - var peg$f34 = function() { return "gte"; }; - var peg$f35 = function() { return "gt"; }; - var peg$f36 = function() { return "lte"; }; - var peg$f37 = function() { return "lt"; }; - var peg$f38 = function(start, inner, end) { //handle no-breaking space + var peg$f31 = function() { return "groupBy"; }; + var peg$f32 = function() { return "feed"; }; + var peg$f33 = function() { return "eq"; }; + var peg$f34 = function() { return "neq"; }; + var peg$f35 = function() { return "gte"; }; + var peg$f36 = function() { return "gt"; }; + var peg$f37 = function() { return "lte"; }; + var peg$f38 = function() { return "lt"; }; + var peg$f39 = function(start, inner, end) { //handle no-breaking space return [...start, '"', ...inner, '"', ...end].join(""); }; - var peg$f39 = function(chars) { return chars.join("").trim(); }; - var peg$f40 = function() { return "and"; }; + var peg$f40 = function(chars) { return chars.join("").trim(); }; + var peg$f41 = function() { return "and"; }; var peg$currPos = options.peg$currPos | 0; var peg$savedPos = peg$currPos; var peg$posDetailsCache = [{ line: 1, column: 1 }]; @@ -818,6 +823,9 @@ function peg$parse(input, options) { s1 = peg$parsesortOrder(); if (s1 === peg$FAILED) { s1 = peg$parsepolicyID(); + if (s1 === peg$FAILED) { + s1 = peg$parsegroupBy(); + } } } } @@ -1508,20 +1516,49 @@ function peg$parse(input, options) { return s0; } + function peg$parsegroupBy() { + var s0, s1; + + s0 = input.substr(peg$currPos, 7); + if (s0.toLowerCase() === peg$c32) { + peg$currPos += 7; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e35); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = input.substr(peg$currPos, 8); + if (s1.toLowerCase() === peg$c33) { + peg$currPos += 8; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e36); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f31(); + } + s0 = s1; + } + + return s0; + } + function peg$parsefeed() { var s0, s1; s0 = peg$currPos; s1 = input.substr(peg$currPos, 4); - if (s1.toLowerCase() === peg$c32) { + if (s1.toLowerCase() === peg$c34) { peg$currPos += 4; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e35); } + if (peg$silentFails === 0) { peg$fail(peg$e37); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f31(); + s1 = peg$f32(); } s0 = s1; @@ -1538,81 +1575,81 @@ 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$e39); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f32(); + s1 = peg$f33(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c33) { - s1 = peg$c33; + if (input.substr(peg$currPos, 2) === peg$c35) { + s1 = peg$c35; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e38); } + if (peg$silentFails === 0) { peg$fail(peg$e40); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f33(); + s1 = peg$f34(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c34) { - s1 = peg$c34; + if (input.substr(peg$currPos, 2) === peg$c36) { + s1 = peg$c36; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e39); } + if (peg$silentFails === 0) { peg$fail(peg$e41); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f34(); + s1 = peg$f35(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 62) { - s1 = peg$c35; + s1 = peg$c37; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e40); } + if (peg$silentFails === 0) { peg$fail(peg$e42); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f35(); + s1 = peg$f36(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c36) { - s1 = peg$c36; + if (input.substr(peg$currPos, 2) === peg$c38) { + s1 = peg$c38; peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e41); } + if (peg$silentFails === 0) { peg$fail(peg$e43); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f36(); + s1 = peg$f37(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 60) { - s1 = peg$c37; + s1 = peg$c39; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e42); } + if (peg$silentFails === 0) { peg$fail(peg$e44); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f37(); + s1 = peg$f38(); } s0 = s1; } @@ -1623,7 +1660,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e36); } + if (peg$silentFails === 0) { peg$fail(peg$e38); } } return s0; @@ -1640,7 +1677,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e44); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } while (s2 !== peg$FAILED) { s1.push(s2); @@ -1649,7 +1686,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e44); } + if (peg$silentFails === 0) { peg$fail(peg$e46); } } } s2 = input.charAt(peg$currPos); @@ -1657,7 +1694,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } if (s2 !== peg$FAILED) { s3 = []; @@ -1666,7 +1703,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e46); } + if (peg$silentFails === 0) { peg$fail(peg$e48); } } while (s4 !== peg$FAILED) { s3.push(s4); @@ -1675,7 +1712,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e46); } + if (peg$silentFails === 0) { peg$fail(peg$e48); } } } s4 = input.charAt(peg$currPos); @@ -1683,7 +1720,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e45); } + if (peg$silentFails === 0) { peg$fail(peg$e47); } } if (s4 !== peg$FAILED) { s5 = []; @@ -1692,7 +1729,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e47); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } } while (s6 !== peg$FAILED) { s5.push(s6); @@ -1701,11 +1738,11 @@ function peg$parse(input, options) { peg$currPos++; } else { s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e47); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } } } peg$savedPos = s0; - s0 = peg$f38(s1, s3, s5); + s0 = peg$f39(s1, s3, s5); } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1717,7 +1754,7 @@ function peg$parse(input, options) { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e43); } + if (peg$silentFails === 0) { peg$fail(peg$e45); } } return s0; @@ -1734,7 +1771,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e47); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { @@ -1744,7 +1781,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e47); } + if (peg$silentFails === 0) { peg$fail(peg$e49); } } } } else { @@ -1752,13 +1789,13 @@ function peg$parse(input, options) { } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$f39(s1); + s1 = peg$f40(s1); } s0 = s1; peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e48); } + if (peg$silentFails === 0) { peg$fail(peg$e50); } } return s0; @@ -1770,7 +1807,7 @@ function peg$parse(input, options) { s0 = peg$currPos; s1 = peg$parse_(); peg$savedPos = s0; - s1 = peg$f40(); + s1 = peg$f41(); s0 = s1; return s0; @@ -1786,7 +1823,7 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e50); } + if (peg$silentFails === 0) { peg$fail(peg$e52); } } while (s1 !== peg$FAILED) { s0.push(s1); @@ -1795,12 +1832,12 @@ function peg$parse(input, options) { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e50); } + if (peg$silentFails === 0) { peg$fail(peg$e52); } } } peg$silentFails--; s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$e49); } + if (peg$silentFails === 0) { peg$fail(peg$e51); } return s0; } diff --git a/src/libs/SearchParser/searchParser.peggy b/src/libs/SearchParser/searchParser.peggy index 987c31d38372..f8bf86d129e4 100644 --- a/src/libs/SearchParser/searchParser.peggy +++ b/src/libs/SearchParser/searchParser.peggy @@ -131,7 +131,7 @@ key "key" / feed ) -defaultKey "default key" = @(type / status / sortBy / sortOrder / policyID) +defaultKey "default key" = @(type / status / sortBy / sortOrder / policyID / groupBy) identifier = (","+)? parts:(quotedString / alphanumeric)|1.., ","+| empty:(","+)? { diff --git a/src/libs/SearchQueryUtils.ts b/src/libs/SearchQueryUtils.ts index b0a2e83bcfc9..a7a71d15eebc 100644 --- a/src/libs/SearchQueryUtils.ts +++ b/src/libs/SearchQueryUtils.ts @@ -66,6 +66,7 @@ const UserFriendlyKeyMap: Record | nul type: CONST.SEARCH.DATA_TYPES.EXPENSE, icon: Expensicons.Document, getRoute: (policyID?: string) => { - const query = buildCannedSearchQuery({policyID}); - return ROUTES.SEARCH_ROOT.getRoute({query, groupBy: 'reports'}); + const query = buildCannedSearchQuery({groupBy: CONST.SEARCH.GROUP_BY.REPORTS, policyID}); + return ROUTES.SEARCH_ROOT.getRoute({query}); }, }, { diff --git a/src/pages/Search/AdvancedSearchFilters.tsx b/src/pages/Search/AdvancedSearchFilters.tsx index 2ec71a04a965..fc7f0beadb82 100644 --- a/src/pages/Search/AdvancedSearchFilters.tsx +++ b/src/pages/Search/AdvancedSearchFilters.tsx @@ -293,7 +293,7 @@ function getFilterDisplayTitle(filters: Partial, filt return dateValue; } - const nonDateFilterKey = filterKey as Exclude; + const nonDateFilterKey = filterKey as Exclude; if (nonDateFilterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.AMOUNT) { const {lessThan, greaterThan} = filters; diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index b3f1a218b224..9f98fc32f339 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -19,7 +19,6 @@ import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {SearchFullscreenNavigatorParamList} from '@libs/Navigation/types'; import {buildCannedSearchQuery, buildSearchQueryJSON, getPolicyIDFromSearchQuery} from '@libs/SearchQueryUtils'; -import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import SearchPageNarrow from './SearchPageNarrow'; @@ -32,7 +31,7 @@ function SearchPage({route}: SearchPageProps) { const {shouldUseNarrowLayout} = useResponsiveLayout(); const styles = useThemeStyles(); - const {q, name, groupBy} = route.params; + const {q, name} = route.params; const {queryJSON, policyID} = useMemo(() => { const parsedQuery = buildSearchQueryJSON(q); @@ -44,8 +43,6 @@ function SearchPage({route}: SearchPageProps) { const handleOnBackButtonPress = () => Navigation.goBack(ROUTES.SEARCH_ROOT.getRoute({query: buildCannedSearchQuery()})); const {clearSelectedTransactions} = useSearchContext(); - const shouldGroupByReports = groupBy === CONST.SEARCH.GROUP_BY.REPORTS; - const isSearchNameModified = name === q; const searchName = isSearchNameModified ? undefined : name; @@ -54,7 +51,6 @@ function SearchPage({route}: SearchPageProps) { ); @@ -85,10 +81,7 @@ function SearchPage({route}: SearchPageProps) { breadcrumbLabel={translate('common.reports')} shouldDisplaySearch={false} /> - + ) : ( - + diff --git a/src/pages/Search/SearchPageNarrow.tsx b/src/pages/Search/SearchPageNarrow.tsx index 95333b79fd83..27cf500d76fa 100644 --- a/src/pages/Search/SearchPageNarrow.tsx +++ b/src/pages/Search/SearchPageNarrow.tsx @@ -34,10 +34,9 @@ type SearchPageNarrowProps = { queryJSON?: SearchQueryJSON; policyID?: string; searchName?: string; - shouldGroupByReports?: boolean; }; -function SearchPageNarrow({queryJSON, policyID, searchName, shouldGroupByReports}: SearchPageNarrowProps) { +function SearchPageNarrow({queryJSON, policyID, searchName}: SearchPageNarrowProps) { const {translate} = useLocalize(); const {shouldUseNarrowLayout} = useResponsiveLayout(); const {windowHeight} = useWindowDimensions(); @@ -151,7 +150,6 @@ function SearchPageNarrow({queryJSON, policyID, searchName, shouldGroupByReports topBarOffset.set(StyleUtils.searchHeaderDefaultOffset); setSearchRouterListVisible(true); }} - shouldGroupByReports={shouldGroupByReports} /> @@ -179,7 +177,6 @@ function SearchPageNarrow({queryJSON, policyID, searchName, shouldGroupByReports )} @@ -191,7 +188,6 @@ function SearchPageNarrow({queryJSON, policyID, searchName, shouldGroupByReports onSearchListScroll={scrollHandler} onContentSizeChange={onContentSizeChange} contentContainerStyle={!selectionMode?.isEnabled ? [styles.searchListContentContainerStyles] : undefined} - shouldGroupByReports={shouldGroupByReports} /> )} diff --git a/src/pages/Search/SearchTypeMenu.tsx b/src/pages/Search/SearchTypeMenu.tsx index 110ae4290195..4c5fb2522220 100644 --- a/src/pages/Search/SearchTypeMenu.tsx +++ b/src/pages/Search/SearchTypeMenu.tsx @@ -37,10 +37,9 @@ import SavedSearchItemThreeDotMenu from './SavedSearchItemThreeDotMenu'; type SearchTypeMenuProps = { queryJSON: SearchQueryJSON; - shouldGroupByReports?: boolean; }; -function SearchTypeMenu({queryJSON, shouldGroupByReports}: SearchTypeMenuProps) { +function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { const {type, hash} = queryJSON; const styles = useThemeStyles(); const {singleExecution} = useSingleExecution(); @@ -171,8 +170,8 @@ function SearchTypeMenu({queryJSON, shouldGroupByReports}: SearchTypeMenuProps) const isCannedQuery = isCannedSearchQuery(queryJSON); const activeItemIndex = isCannedQuery ? typeMenuItems.findIndex((item) => { - if (shouldGroupByReports) { - return item.translationPath === 'common.expenseReports'; + if (queryJSON.groupBy === CONST.SEARCH.GROUP_BY.REPORTS) { + return item.translationPath === 'common.expenseReports' && item.type === type; } return item.type === type; }) diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 7635c8e0fce5..06c524feb9da 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -1366,7 +1366,7 @@ describe('SearchUIUtils', () => { const expectedRoutes = [ ROUTES.SEARCH_ROOT.getRoute({query: 'type:expense status:all sortBy:date sortOrder:desc'}), - ROUTES.SEARCH_ROOT.getRoute({query: 'type:expense status:all sortBy:date sortOrder:desc', groupBy: 'reports'}), + ROUTES.SEARCH_ROOT.getRoute({query: 'type:expense status:all sortBy:date sortOrder:desc groupBy:reports'}), ROUTES.SEARCH_ROOT.getRoute({query: 'type:chat status:all sortBy:date sortOrder:desc'}), ROUTES.SEARCH_ROOT.getRoute({query: 'type:trip status:all sortBy:date sortOrder:desc'}), ];