Skip to content

Commit 37f73fc

Browse files
authored
Merge pull request Expensify#63758 from Expensify/jsenyitko-reenable-export
Re-enable 'Export' Suggested Search
2 parents 5b556dd + c2657ae commit 37f73fc

12 files changed

Lines changed: 266 additions & 113 deletions

File tree

src/CONST/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6217,6 +6217,7 @@ const CONST = {
62176217
APPROVE: 'approve',
62186218
PAY: 'pay',
62196219
DONE: 'done',
6220+
EXPORT_TO_ACCOUNTING: 'exportToAccounting',
62206221
PAID: 'paid',
62216222
},
62226223
BULK_ACTION_TYPES: {
@@ -6421,6 +6422,18 @@ const CONST = {
64216422
ONYXKEYS.PERSONAL_DETAILS_LIST,
64226423
ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
64236424
],
6425+
SUGGESTED_SEARCH_KEYS: {
6426+
EXPENSES: 'expenses',
6427+
REPORTS: 'reports',
6428+
CHATS: 'chats',
6429+
SUBMIT: 'submit',
6430+
APPROVE: 'approve',
6431+
PAY: 'pay',
6432+
EXPORT: 'export',
6433+
UNAPPROVED: 'unapproved',
6434+
UNAPPROVED_CASH: 'unapprovedCash',
6435+
UNAPPROVED_COMPANY_CARDS: 'unapprovedCompanyCards',
6436+
},
64246437
},
64256438

64266439
EXPENSE: {

src/components/Search/index.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import useOnyx from '@hooks/useOnyx';
1414
import usePrevious from '@hooks/usePrevious';
1515
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1616
import useSearchHighlightAndScroll from '@hooks/useSearchHighlightAndScroll';
17+
import useSearchTypeMenuSections from '@hooks/useSearchTypeMenuSections';
1718
import useThemeStyles from '@hooks/useThemeStyles';
1819
import {turnOffMobileSelectionMode, turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
1920
import {openSearch, updateSearchResultsWithTransactionThreadReportID} from '@libs/actions/Search';
@@ -23,7 +24,7 @@ import Log from '@libs/Log';
2324
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
2425
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
2526
import Performance from '@libs/Performance';
26-
import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
27+
import {getIOUActionForTransactionID, isExportIntegrationAction, isIntegrationMessageAction} from '@libs/ReportActionsUtils';
2728
import {canEditFieldOfMoneyRequest, generateReportID} from '@libs/ReportUtils';
2829
import {buildSearchQueryString} from '@libs/SearchQueryUtils';
2930
import {
@@ -163,9 +164,24 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS
163164

164165
const {type, status, sortBy, sortOrder, hash, groupBy} = queryJSON;
165166

167+
const {currentSearch} = useSearchTypeMenuSections(hash);
166168
const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true});
167169
const previousTransactions = usePrevious(transactions);
168170
const [reportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS, {canBeMissing: true});
171+
// Create a selector for only the reportActions needed to determine if a report has been exported or not, grouped by report
172+
const [exportReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS, {
173+
canEvict: false,
174+
canBeMissing: true,
175+
selector: (allReportActions) => {
176+
return Object.fromEntries(
177+
Object.entries(allReportActions ?? {}).map(([reportID, reportActionsGroup]) => {
178+
const filteredReportActions = Object.values(reportActionsGroup ?? {}).filter((action) => isExportIntegrationAction(action) || isIntegrationMessageAction(action));
179+
return [reportID, filteredReportActions];
180+
}),
181+
);
182+
},
183+
});
184+
169185
const previousReportActions = usePrevious(reportActions);
170186
const reportActionsArray = useMemo(
171187
() =>
@@ -255,8 +271,9 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS
255271
if (searchResults === undefined || !isDataLoaded) {
256272
return [];
257273
}
258-
return getSections(type, status, searchResults.data, searchResults.search, groupBy);
259-
}, [searchResults, isDataLoaded, type, status, groupBy]);
274+
275+
return getSections(type, searchResults.data, searchResults.search, groupBy, exportReportActions, currentSearch?.key);
276+
}, [currentSearch?.key, exportReportActions, groupBy, isDataLoaded, searchResults, type]);
260277

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

src/components/SelectionList/Search/ActionCell.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const actionTranslationsMap: Record<SearchTransactionAction, TranslationPaths> =
1919
submit: 'common.submit',
2020
approve: 'iou.approve',
2121
pay: 'iou.pay',
22+
exportToAccounting: 'common.export',
2223
done: 'common.done',
2324
paid: 'iou.settledExpensify',
2425
};

src/hooks/useSearchTypeMenu.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Navigation from '@libs/Navigation/Navigation';
1111
import {getAllTaxRates} from '@libs/PolicyUtils';
1212
import {buildSearchQueryJSON, buildUserReadableQueryString} from '@libs/SearchQueryUtils';
1313
import type {SavedSearchMenuItem} from '@libs/SearchUIUtils';
14-
import {createBaseSavedSearchMenuItem, createTypeMenuSections, getOverflowMenu as getOverflowMenuUtil} from '@libs/SearchUIUtils';
14+
import {createBaseSavedSearchMenuItem, getOverflowMenu as getOverflowMenuUtil} from '@libs/SearchUIUtils';
1515
import variables from '@styles/variables';
1616
import * as Expensicons from '@src/components/Icon/Expensicons';
1717
import CONST from '@src/CONST';
@@ -22,21 +22,23 @@ import {getEmptyObject} from '@src/types/utils/EmptyObject';
2222
import useDeleteSavedSearch from './useDeleteSavedSearch';
2323
import useLocalize from './useLocalize';
2424
import useOnyx from './useOnyx';
25+
import useSearchTypeMenuSections from './useSearchTypeMenuSections';
2526
import useSingleExecution from './useSingleExecution';
2627
import useTheme from './useTheme';
2728
import useThemeStyles from './useThemeStyles';
2829
import useWindowDimensions from './useWindowDimensions';
2930

3031
export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) {
32+
const {hash} = queryJSON;
33+
3134
const theme = useTheme();
3235
const styles = useThemeStyles();
3336
const {singleExecution} = useSingleExecution();
3437
const {windowHeight} = useWindowDimensions();
3538
const {translate} = useLocalize();
36-
const {hash} = queryJSON;
39+
const {typeMenuSections} = useSearchTypeMenuSections(hash);
3740
const {showDeleteModal, DeleteConfirmModal} = useDeleteSavedSearch();
3841
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
39-
const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false});
4042
const personalDetails = usePersonalDetails();
4143
const [reports = getEmptyObject<NonNullable<OnyxCollection<Report>>>()] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: true});
4244
const taxRates = getAllTaxRates();
@@ -47,14 +49,11 @@ export default function useSearchTypeMenu(queryJSON: SearchQueryJSON) {
4749
const [isPopoverVisible, setIsPopoverVisible] = useState(false);
4850
const [processedMenuItems, setProcessedMenuItems] = useState<PopoverMenuItem[]>([]);
4951

50-
const [allCards, hasCardFeed] = useMemo(() => {
51-
const mergedCards = mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, userCardList);
52-
return [mergedCards, Object.keys(mergedCards).length > 0];
52+
const allCards = useMemo(() => {
53+
return mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, userCardList);
5354
}, [userCardList, workspaceCardFeeds]);
5455
const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER, {canBeMissing: true});
5556

56-
const typeMenuSections = useMemo(() => createTypeMenuSections(session, hasCardFeed, allPolicies), [session, hasCardFeed, allPolicies]);
57-
5857
// this is a performance fix, rendering popover menu takes a lot of time and we don't need this component initially, that's why we postpone rendering it until everything else is rendered
5958
const [delayPopoverMenuFirstRender, setDelayPopoverMenuFirstRender] = useState(true);
6059
useEffect(() => {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import {useMemo} from 'react';
2+
import {mergeCardListWithWorkspaceFeeds} from '@libs/CardUtils';
3+
import {buildSearchQueryJSON} from '@libs/SearchQueryUtils';
4+
import {createTypeMenuSections} from '@libs/SearchUIUtils';
5+
import CONST from '@src/CONST';
6+
import ONYXKEYS from '@src/ONYXKEYS';
7+
import useOnyx from './useOnyx';
8+
9+
/**
10+
* Get a list of all search groupings, along with their search items. Also returns the
11+
* currently focused search, based on the hash
12+
*/
13+
const useSearchTypeMenuSections = (hash = 0) => {
14+
const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false});
15+
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
16+
const [userCardList] = useOnyx(ONYXKEYS.CARD_LIST, {canBeMissing: true});
17+
const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST, {canBeMissing: true});
18+
19+
const hasCardFeed = useMemo(() => {
20+
return Object.keys(mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, userCardList)).length > 0;
21+
}, [userCardList, workspaceCardFeeds]);
22+
23+
const typeMenuSections = useMemo(() => createTypeMenuSections(session, hasCardFeed, allPolicies), [allPolicies, hasCardFeed, session]);
24+
25+
const currentSearch = useMemo(() => {
26+
const flatMenuItems = typeMenuSections.map((section) => section.menuItems).flat();
27+
return flatMenuItems.find((menuItem) => {
28+
const menuHash = buildSearchQueryJSON(menuItem.getSearchQuery())?.hash;
29+
return menuHash === hash;
30+
});
31+
}, [hash, typeMenuSections]);
32+
33+
return {typeMenuSections, currentSearch};
34+
};
35+
36+
export default useSearchTypeMenuSections;

src/libs/ReportPrimaryActionUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,4 +397,4 @@ function getTransactionThreadPrimaryAction(
397397
return '';
398398
}
399399

400-
export {getReportPrimaryAction, getTransactionThreadPrimaryAction, isAddExpenseAction, isPrimaryPayAction, getAllExpensesToHoldIfApplicable};
400+
export {getReportPrimaryAction, getTransactionThreadPrimaryAction, isAddExpenseAction, isPrimaryPayAction, isExportAction, getAllExpensesToHoldIfApplicable};

0 commit comments

Comments
 (0)