-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ability to bulk select cards from the same bank in the Card filter #53389
Changes from 48 commits
951f85b
4113519
e0d5bf8
9336e8f
defc543
98b3512
a5545b7
6ebe579
a1ae60e
d9f0e8a
42ecedc
93e23ca
00f3ad8
cfb2417
6f8efac
bd92551
5d93a9d
ab009cc
e9cb9da
cec56f7
9068aa8
313bb46
0f274f9
a48f976
5f21294
b4e5aab
e18af2a
fc3f071
947d918
6ad3f86
d340930
719a972
306f6c6
415ef30
00dc930
a49beaf
4954b15
2a8fe1d
79a5c3d
7a8d927
137ffe8
a3001be
b22f596
69400ad
ded2e05
22dd304
185b375
e7c543b
91b84ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,11 +17,12 @@ | |
import useResponsiveLayout from '@hooks/useResponsiveLayout'; | ||
import useTheme from '@hooks/useTheme'; | ||
import useThemeStyles from '@hooks/useThemeStyles'; | ||
import * as SearchActions from '@libs/actions/Search'; | ||
Check failure on line 20 in src/components/Search/SearchPageHeader.tsx
|
||
import * as CardUtils from '@libs/CardUtils'; | ||
Check failure on line 21 in src/components/Search/SearchPageHeader.tsx
|
||
import Navigation from '@libs/Navigation/Navigation'; | ||
import {getAllTaxRates} from '@libs/PolicyUtils'; | ||
import * as PolicyUtils from '@libs/PolicyUtils'; | ||
Check failure on line 24 in src/components/Search/SearchPageHeader.tsx
|
||
import * as SearchQueryUtils from '@libs/SearchQueryUtils'; | ||
Check failure on line 25 in src/components/Search/SearchPageHeader.tsx
|
||
import SearchSelectedNarrow from '@pages/Search/SearchSelectedNarrow'; | ||
import variables from '@styles/variables'; | ||
import CONST from '@src/CONST'; | ||
|
@@ -50,7 +51,9 @@ | |
const personalDetails = usePersonalDetails(); | ||
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); | ||
const taxRates = getAllTaxRates(); | ||
const [cardList = {}] = useOnyx(ONYXKEYS.CARD_LIST); | ||
const [userCardList = {}] = useOnyx(ONYXKEYS.CARD_LIST); | ||
const [workspaceCardFeeds = {}] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST); | ||
const allCards = useMemo(() => CardUtils.mergeCardListWithWorkspaceFeeds(workspaceCardFeeds, userCardList), [userCardList, workspaceCardFeeds]); | ||
const [currencyList = {}] = useOnyx(ONYXKEYS.CURRENCY_LIST); | ||
const [policyCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CATEGORIES); | ||
const [policyTagsLists] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS); | ||
|
@@ -200,7 +203,13 @@ | |
|
||
const reportIDList = selectedReports?.filter((report) => !!report).map((report) => report.reportID) ?? []; | ||
SearchActions.exportSearchItemsToCSV( | ||
{query: status, jsonQuery: JSON.stringify(queryJSON), reportIDList, transactionIDList: selectedTransactionsKeys, policyIDs: [activeWorkspaceID ?? '']}, | ||
{ | ||
query: status, | ||
jsonQuery: JSON.stringify(queryJSON), | ||
reportIDList, | ||
transactionIDList: selectedTransactionsKeys, | ||
policyIDs: activeWorkspaceID ? [activeWorkspaceID] : [''], | ||
}, | ||
() => { | ||
setIsDownloadErrorModalVisible(true); | ||
}, | ||
|
@@ -284,20 +293,20 @@ | |
|
||
return options; | ||
}, [ | ||
queryJSON, | ||
status, | ||
selectedTransactionsKeys, | ||
selectedTransactions, | ||
isOffline, | ||
selectedReports, | ||
translate, | ||
hash, | ||
lastPaymentMethods, | ||
status, | ||
queryJSON, | ||
activeWorkspaceID, | ||
theme.icon, | ||
styles.colorMuted, | ||
styles.fontWeightNormal, | ||
isOffline, | ||
activeWorkspaceID, | ||
selectedReports, | ||
styles.textWrap, | ||
lastPaymentMethods, | ||
]); | ||
|
||
if (shouldUseNarrowLayout) { | ||
|
@@ -346,7 +355,7 @@ | |
|
||
const onFiltersButtonPress = () => { | ||
hideProductTrainingTooltip(); | ||
const filterFormValues = SearchQueryUtils.buildFilterFormValuesFromQuery(queryJSON, policyCategories, policyTagsLists, currencyList, personalDetails, cardList, reports, taxRates); | ||
const filterFormValues = SearchQueryUtils.buildFilterFormValuesFromQuery(queryJSON, policyCategories, policyTagsLists, currencyList, personalDetails, allCards, reports, taxRates); | ||
SearchActions.updateAdvancedFilters(filterFormValues); | ||
|
||
Navigation.navigate(ROUTES.SEARCH_ADVANCED_FILTERS); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,14 +14,15 @@ | |
import Text from '@components/Text'; | ||
import useLocalize from '@hooks/useLocalize'; | ||
import useThemeStyles from '@hooks/useThemeStyles'; | ||
import * as SearchActions from '@libs/actions/Search'; | ||
Check failure on line 17 in src/components/Search/SearchPageHeaderInput.tsx
|
||
import * as CardUtils from '@libs/CardUtils'; | ||
Check failure on line 18 in src/components/Search/SearchPageHeaderInput.tsx
|
||
import Navigation from '@libs/Navigation/Navigation'; | ||
import {getAllTaxRates} from '@libs/PolicyUtils'; | ||
import type {OptionData} from '@libs/ReportUtils'; | ||
import * as SearchAutocompleteUtils from '@libs/SearchAutocompleteUtils'; | ||
Check failure on line 22 in src/components/Search/SearchPageHeaderInput.tsx
|
||
import * as SearchQueryUtils from '@libs/SearchQueryUtils'; | ||
Check failure on line 23 in src/components/Search/SearchPageHeaderInput.tsx
|
||
import variables from '@styles/variables'; | ||
import * as ReportUserActions from '@userActions/Report'; | ||
Check failure on line 25 in src/components/Search/SearchPageHeaderInput.tsx
|
||
import CONST from '@src/CONST'; | ||
import type {TranslationPaths} from '@src/languages/types'; | ||
import ONYXKEYS from '@src/ONYXKEYS'; | ||
|
@@ -71,10 +72,13 @@ | |
const personalDetails = usePersonalDetails(); | ||
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); | ||
const taxRates = useMemo(() => getAllTaxRates(), []); | ||
const [userCardList = {}] = useOnyx(ONYXKEYS.CARD_LIST); | ||
const [workspaceCardFeeds = {}] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST); | ||
const allCards = useMemo(() => CardUtils.mergeCardListWithWorkspaceFeeds(workspaceCardFeeds, userCardList), [userCardList, workspaceCardFeeds]); | ||
|
||
const {type, inputQuery: originalInputQuery} = queryJSON; | ||
const isCannedQuery = SearchQueryUtils.isCannedSearchQuery(queryJSON); | ||
const queryText = SearchQueryUtils.buildUserReadableQueryString(queryJSON, personalDetails, reports, taxRates); | ||
const queryText = SearchQueryUtils.buildUserReadableQueryString(queryJSON, personalDetails, reports, taxRates, allCards); | ||
const headerText = isCannedQuery ? translate(getHeaderContent(type).titleText) : ''; | ||
|
||
// The actual input text that the user sees | ||
|
@@ -107,9 +111,9 @@ | |
}, [queryText]); | ||
|
||
useEffect(() => { | ||
const substitutionsMap = buildSubstitutionsMap(originalInputQuery, personalDetails, reports, taxRates); | ||
const substitutionsMap = buildSubstitutionsMap(originalInputQuery, personalDetails, reports, taxRates, allCards); | ||
setAutocompleteSubstitutions(substitutionsMap); | ||
}, [originalInputQuery, personalDetails, reports, taxRates]); | ||
}, [allCards, originalInputQuery, personalDetails, reports, taxRates]); | ||
|
||
const onSearchQueryChange = useCallback( | ||
(userQuery: string) => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ | |
import usePolicy from '@hooks/usePolicy'; | ||
import useResponsiveLayout from '@hooks/useResponsiveLayout'; | ||
import useThemeStyles from '@hooks/useThemeStyles'; | ||
import * as CardUtils from '@libs/CardUtils'; | ||
Check failure on line 20 in src/components/Search/SearchRouter/SearchRouterList.tsx
|
||
import * as OptionsListUtils from '@libs/OptionsListUtils'; | ||
import type {SearchOption} from '@libs/OptionsListUtils'; | ||
import Performance from '@libs/Performance'; | ||
|
@@ -148,8 +148,11 @@ | |
const statusAutocompleteList = Object.values({...CONST.SEARCH.STATUS.TRIP, ...CONST.SEARCH.STATUS.INVOICE, ...CONST.SEARCH.STATUS.CHAT, ...CONST.SEARCH.STATUS.TRIP}); | ||
const expenseTypes = Object.values(CONST.SEARCH.TRANSACTION_TYPE); | ||
|
||
const [cardList = {}] = useOnyx(ONYXKEYS.CARD_LIST); | ||
const cardAutocompleteList = Object.values(cardList); | ||
const [userCardList = {}] = useOnyx(ONYXKEYS.CARD_LIST); | ||
const [workspaceCardFeeds = {}] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST); | ||
const allCards = useMemo(() => CardUtils.mergeCardListWithWorkspaceFeeds(workspaceCardFeeds, userCardList), [userCardList, workspaceCardFeeds]); | ||
const cardAutocompleteList = Object.values(allCards); | ||
|
||
const participantsAutocompleteList = useMemo(() => { | ||
if (!areOptionsInitialized) { | ||
return []; | ||
|
@@ -335,6 +338,7 @@ | |
} | ||
case CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID: { | ||
const filteredCards = cardAutocompleteList | ||
.filter((card) => CardUtils.isCard(card) && CardUtils.isCardIssued(card)) | ||
.filter( | ||
(card) => | ||
card.bank.toLowerCase().includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(CardUtils.getCardDescription(card.cardID).toLowerCase()), | ||
|
@@ -344,7 +348,7 @@ | |
|
||
return filteredCards.map((card) => ({ | ||
filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.CARD_ID, | ||
text: CardUtils.getCardDescription(card.cardID), | ||
text: CardUtils.getCardDescription(card.cardID, allCards), | ||
autocompleteID: card.cardID.toString(), | ||
mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID, | ||
})); | ||
|
@@ -368,6 +372,7 @@ | |
statusAutocompleteList, | ||
expenseTypes, | ||
cardAutocompleteList, | ||
allCards, | ||
]); | ||
|
||
const sortedRecentSearches = useMemo(() => { | ||
|
@@ -377,7 +382,7 @@ | |
const recentSearchesData = sortedRecentSearches?.slice(0, 5).map(({query, timestamp}) => { | ||
const searchQueryJSON = SearchQueryUtils.buildSearchQueryJSON(query); | ||
return { | ||
text: searchQueryJSON ? SearchQueryUtils.buildUserReadableQueryString(searchQueryJSON, personalDetails, reports, taxRates) : query, | ||
text: searchQueryJSON ? SearchQueryUtils.buildUserReadableQueryString(searchQueryJSON, personalDetails, reports, taxRates, allCards) : query, | ||
singleIcon: Expensicons.History, | ||
searchQuery: query, | ||
keyForList: timestamp, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Console error:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see such error, also everything that could cause "update max depth exceeded" seems wrapped in useMemo, so I don't see a case when this error pops up. Do you have some specific steps of reproduction for this error?
