Skip to content

Commit 6286ab0

Browse files
authored
Merge pull request #57852 from software-mansion-labs/289Adam289/57674-move-groupBy-to-search-query
Make group-by part of query syntax
2 parents bdf6559 + f29223e commit 6286ab0

21 files changed

+279
-204
lines changed

src/CONST.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6361,6 +6361,7 @@ const CONST = {
63616361
SORT_BY: 'sortBy',
63626362
SORT_ORDER: 'sortOrder',
63636363
POLICY_ID: 'policyID',
6364+
GROUP_BY: 'groupBy',
63646365
},
63656366
SYNTAX_FILTER_KEYS: {
63666367
DATE: 'date',
@@ -6397,6 +6398,7 @@ const CONST = {
63976398
SORT_BY: 'sort-by',
63986399
SORT_ORDER: 'sort-order',
63996400
POLICY_ID: 'workspace',
6401+
GROUP_BY: 'group-by',
64006402
DATE: 'date',
64016403
AMOUNT: 'amount',
64026404
EXPENSE_TYPE: 'expense-type',

src/ROUTES.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ const ROUTES = {
3939

4040
SEARCH_ROOT: {
4141
route: 'search',
42-
getRoute: ({query, name, groupBy}: {query: SearchQueryString; name?: string; groupBy?: string}) => {
43-
return `search?q=${encodeURIComponent(query)}${groupBy ? `&groupBy=${groupBy}` : ''}${name ? `&name=${name}` : ''}` as const;
42+
getRoute: ({query, name}: {query: SearchQueryString; name?: string}) => {
43+
return `search?q=${encodeURIComponent(query)}${name ? `&name=${name}` : ''}` as const;
4444
},
4545
},
4646
SEARCH_SAVED_SEARCH_RENAME: {

src/components/Search/SearchAutocompleteList.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ function SearchAutocompleteList(
156156
const [isInitialRender, setIsInitialRender] = useState(true);
157157

158158
const typeAutocompleteList = Object.values(CONST.SEARCH.DATA_TYPES);
159+
const groupByAutocompleteList = Object.values(CONST.SEARCH.GROUP_BY);
159160
const statusAutocompleteList = Object.values({...CONST.SEARCH.STATUS.EXPENSE, ...CONST.SEARCH.STATUS.INVOICE, ...CONST.SEARCH.STATUS.CHAT, ...CONST.SEARCH.STATUS.TRIP});
160161
const expenseTypes = Object.values(CONST.SEARCH.TRANSACTION_TYPE);
161162

@@ -337,6 +338,12 @@ function SearchAutocompleteList(
337338

338339
return filteredTypes.map((type) => ({filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.TYPE, text: type}));
339340
}
341+
case CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY: {
342+
const filteredGroupBy = groupByAutocompleteList.filter(
343+
(groupByValue) => groupByValue.toLowerCase().includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(groupByValue.toLowerCase()),
344+
);
345+
return filteredGroupBy.map((groupByValue) => ({filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.GROUP_BY, text: groupByValue}));
346+
}
340347
case CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS: {
341348
const filteredStatuses = statusAutocompleteList
342349
.filter((status) => status.includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(status))
@@ -405,6 +412,7 @@ function SearchAutocompleteList(
405412
workspaceCardFeeds,
406413
cardAutocompleteList,
407414
allCards,
415+
groupByAutocompleteList,
408416
]);
409417

410418
const sortedRecentSearches = useMemo(() => {

src/components/Search/SearchPageHeader/SearchPageHeader.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,11 @@ type SearchPageHeaderProps = {
4646
searchRouterListVisible?: boolean;
4747
hideSearchRouterList?: () => void;
4848
onSearchRouterFocus?: () => void;
49-
shouldGroupByReports?: boolean;
5049
};
5150

5251
type SearchHeaderOptionValue = DeepValueOf<typeof CONST.SEARCH.BULK_ACTION_TYPES> | undefined;
5352

54-
function SearchPageHeader({queryJSON, searchName, searchRouterListVisible, hideSearchRouterList, onSearchRouterFocus, shouldGroupByReports}: SearchPageHeaderProps) {
53+
function SearchPageHeader({queryJSON, searchName, searchRouterListVisible, hideSearchRouterList, onSearchRouterFocus}: SearchPageHeaderProps) {
5554
const {translate} = useLocalize();
5655
const theme = useTheme();
5756
const styles = useThemeStyles();
@@ -433,7 +432,6 @@ function SearchPageHeader({queryJSON, searchName, searchRouterListVisible, hideS
433432
searchName={searchName}
434433
hideSearchRouterList={hideSearchRouterList}
435434
inputRightComponent={InputRightComponent}
436-
shouldGroupByReports={shouldGroupByReports}
437435
/>
438436
<ConfirmModal
439437
isVisible={isDeleteExpensesConfirmModalVisible}

src/components/Search/SearchPageHeader/SearchPageHeaderInput.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,9 @@ type SearchPageHeaderInputProps = {
4848
onSearchRouterFocus?: () => void;
4949
searchName?: string;
5050
inputRightComponent: React.ReactNode;
51-
shouldGroupByReports?: boolean;
5251
};
5352

54-
function SearchPageHeaderInput({
55-
queryJSON,
56-
searchRouterListVisible,
57-
hideSearchRouterList,
58-
onSearchRouterFocus,
59-
searchName,
60-
inputRightComponent,
61-
shouldGroupByReports,
62-
}: SearchPageHeaderInputProps) {
53+
function SearchPageHeaderInput({queryJSON, searchRouterListVisible, hideSearchRouterList, onSearchRouterFocus, searchName, inputRightComponent}: SearchPageHeaderInputProps) {
6354
const {translate} = useLocalize();
6455
const [showPopupButton, setShowPopupButton] = useState(true);
6556
const styles = useThemeStyles();
@@ -272,7 +263,6 @@ function SearchPageHeaderInput({
272263
>
273264
<SearchTypeMenuPopover
274265
queryJSON={queryJSON}
275-
shouldGroupByReports={shouldGroupByReports}
276266
searchName={searchName}
277267
/>
278268
</Animated.View>

src/components/Search/SearchPageHeader/SearchTypeMenuPopover.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,15 @@ type SavedSearchMenuItem = MenuItemWithLink & {
3939
type SearchTypeMenuNarrowProps = {
4040
queryJSON: SearchQueryJSON;
4141
searchName?: string;
42-
shouldGroupByReports?: boolean;
4342
};
4443

45-
function SearchTypeMenuPopover({queryJSON, searchName, shouldGroupByReports}: SearchTypeMenuNarrowProps) {
44+
function SearchTypeMenuPopover({queryJSON, searchName}: SearchTypeMenuNarrowProps) {
4645
const theme = useTheme();
4746
const styles = useThemeStyles();
4847
const {singleExecution} = useSingleExecution();
4948
const {windowHeight} = useWindowDimensions();
5049
const {translate} = useLocalize();
51-
const {hash, policyID} = queryJSON;
50+
const {hash, policyID, groupBy} = queryJSON;
5251
const {showDeleteModal, DeleteConfirmModal} = useDeleteSavedSearch();
5352
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
5453
const [session] = useOnyx(ONYXKEYS.SESSION);
@@ -59,6 +58,7 @@ function SearchTypeMenuPopover({queryJSON, searchName, shouldGroupByReports}: Se
5958
const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST);
6059
const allCards = useMemo(() => mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, userCardList), [userCardList, workspaceCardFeeds]);
6160
const {unmodifiedPaddings} = useStyledSafeAreaInsets();
61+
const shouldGroupByReports = groupBy === CONST.SEARCH.GROUP_BY.REPORTS;
6262
const cardFeedNamesWithType = useMemo(() => {
6363
return getCardFeedNamesWithType({workspaceCardFeeds, userCardList, translate});
6464
}, [translate, workspaceCardFeeds, userCardList]);

src/components/Search/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ type SearchProps = {
5252
contentContainerStyle?: StyleProp<ViewStyle>;
5353
isSearchScreenFocused?: boolean;
5454
onContentSizeChange?: (w: number, h: number) => void;
55-
shouldGroupByReports?: boolean;
5655
};
5756

5857
const transactionItemMobileHeight = 100;
@@ -127,7 +126,7 @@ function prepareTransactionsList(item: TransactionListItemType, selectedTransact
127126
};
128127
}
129128

130-
function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentContainerStyle, onContentSizeChange, shouldGroupByReports}: SearchProps) {
129+
function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentContainerStyle, onContentSizeChange}: SearchProps) {
131130
const {isOffline} = useNetwork();
132131
const {shouldUseNarrowLayout} = useResponsiveLayout();
133132
const styles = useThemeStyles();
@@ -150,13 +149,14 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
150149
const {selectionMode} = useMobileSelectionMode();
151150
const [offset, setOffset] = useState(0);
152151

153-
const {type, status, sortBy, sortOrder, hash} = queryJSON;
152+
const {type, status, sortBy, sortOrder, hash, groupBy} = queryJSON;
154153

155154
const [currentSearchResults] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`);
156155
const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION);
157156
const previousTransactions = usePrevious(transactions);
158157
const [reportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS);
159158
const previousReportActions = usePrevious(reportActions);
159+
const shouldGroupByReports = groupBy === CONST.SEARCH.GROUP_BY.REPORTS;
160160

161161
useEffect(() => {
162162
if (!currentSearchResults?.search?.type) {
@@ -267,7 +267,7 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
267267
return [];
268268
}
269269
return getSections(type, status, searchResults.data, searchResults.search, shouldGroupByReports);
270-
}, [searchResults, status, type, shouldGroupByReports]);
270+
}, [searchResults, type, status, shouldGroupByReports]);
271271

272272
useEffect(() => {
273273
/** We only want to display the skeleton for the status filters the first time we load them for a specific data type */

src/components/Search/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type InvoiceSearchStatus = ValueOf<typeof CONST.SEARCH.STATUS.INVOICE>;
5858
type TripSearchStatus = ValueOf<typeof CONST.SEARCH.STATUS.TRIP>;
5959
type ChatSearchStatus = ValueOf<typeof CONST.SEARCH.STATUS.CHAT>;
6060
type SearchStatus = ExpenseSearchStatus | InvoiceSearchStatus | TripSearchStatus | ChatSearchStatus | Array<ExpenseSearchStatus | InvoiceSearchStatus | TripSearchStatus | ChatSearchStatus>;
61+
type SearchGroupBy = ValueOf<typeof CONST.SEARCH.GROUP_BY>;
6162

6263
type SearchContext = {
6364
currentSearchHash: number;
@@ -96,7 +97,8 @@ type SearchFilterKey =
9697
| ValueOf<typeof CONST.SEARCH.SYNTAX_FILTER_KEYS>
9798
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE
9899
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS
99-
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID;
100+
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.POLICY_ID
101+
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY;
100102

101103
type UserFriendlyKey = ValueOf<typeof CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS>;
102104

@@ -112,6 +114,7 @@ type SearchQueryAST = {
112114
status: SearchStatus;
113115
sortBy: SearchColumnType;
114116
sortOrder: SortOrder;
117+
groupBy?: SearchGroupBy;
115118
filters: ASTNode;
116119
policyID?: string;
117120
};

src/libs/SearchAutocompleteUtils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ function filterOutRangesWithCorrectValue(
148148
const typeList = Object.values(CONST.SEARCH.DATA_TYPES) as string[];
149149
const expenseTypeList = Object.values(CONST.SEARCH.TRANSACTION_TYPE) as string[];
150150
const statusList = Object.values({...CONST.SEARCH.STATUS.EXPENSE, ...CONST.SEARCH.STATUS.INVOICE, ...CONST.SEARCH.STATUS.CHAT, ...CONST.SEARCH.STATUS.TRIP}) as string[];
151+
const groupByList = Object.values(CONST.SEARCH.GROUP_BY) as string[];
151152

152153
switch (range.key) {
153154
case CONST.SEARCH.SYNTAX_FILTER_KEYS.IN:
@@ -172,6 +173,8 @@ function filterOutRangesWithCorrectValue(
172173
return categoryList.get().includes(range.value);
173174
case CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG:
174175
return tagList.get().includes(range.value);
176+
case CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY:
177+
return groupByList.includes(range.value);
175178
default:
176179
return false;
177180
}

0 commit comments

Comments
 (0)