Skip to content

Add feed syntax key #57454

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

Merged
merged 21 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e872958
Add feed syntax to SearchParser lib
JakubKorytko Feb 20, 2025
86e92a2
Create keyForFeed key for feed query
JakubKorytko Feb 20, 2025
501d1cf
Store only the feed in query if feed is selected
JakubKorytko Feb 20, 2025
159244f
Convert text to autocompleteID & vice-versa
JakubKorytko Feb 21, 2025
bcdfe7b
Remove 'cards_' part from feed syntax key
JakubKorytko Feb 21, 2025
4711093
Display proper feed name in AdvancedSearchFilters
JakubKorytko Feb 24, 2025
d897b00
Add logic for domain cards
JakubKorytko Feb 24, 2025
c72972b
Add loader for card filters page
JakubKorytko Feb 25, 2025
9221ae0
Improve domain cards logic
JakubKorytko Feb 25, 2025
1497b84
Add test for Card Feeds convertion
JakubKorytko Feb 25, 2025
fdb8366
Apply fixes regarding 2644855129 PR review comment
JakubKorytko Feb 28, 2025
e1bf580
Correct naming, types & domain cards logic
JakubKorytko Feb 28, 2025
007b51d
Merge branch 'main' into add-feed-syntax-key
JakubKorytko Mar 3, 2025
06d668b
Run prettier & fix FeedUtils members calls
JakubKorytko Mar 3, 2025
c9cc52d
Add value to createSavedSearchMenuItem useCallback arr dep
JakubKorytko Mar 3, 2025
2c9287b
Merge branch 'main' into add-feed-syntax-key
JakubKorytko Mar 5, 2025
c777e71
Suggestion when selected & missing feedName fix
JakubKorytko Mar 5, 2025
b8c047e
Run prettier
JakubKorytko Mar 5, 2025
df719be
Revert submodule Mobile-Expensify to commit bcf6a8
JakubKorytko Mar 6, 2025
11bd523
Fix workspace feed names in advanced filters
JakubKorytko Mar 6, 2025
e7fab49
Add fixes regarding 2663603239 review comment
JakubKorytko Mar 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6302,6 +6302,7 @@ const CONST = {
TAG: 'tag',
TAX_RATE: 'taxRate',
CARD_ID: 'cardID',
FEED: 'feed',
REPORT_ID: 'reportID',
KEYWORD: 'keyword',
IN: 'in',
Expand Down Expand Up @@ -6335,6 +6336,7 @@ const CONST = {
TAG: 'tag',
TAX_RATE: 'tax-rate',
CARD_ID: 'card',
FEED: 'feed',
REPORT_ID: 'reportid',
KEYWORD: 'keyword',
IN: 'in',
Expand Down
23 changes: 22 additions & 1 deletion src/components/Search/SearchAutocompleteList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import usePolicy from '@hooks/usePolicy';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import {searchInServer} from '@libs/actions/Report';
import {getCardFeedKey, getCardFeedNamesWithType} from '@libs/CardFeedUtils';
import {getCardDescription, isCard, isCardHiddenFromSearch, mergeCardListWithWorkspaceFeeds} from '@libs/CardUtils';
import {combineOrderingOfReportsAndPersonalDetails, getSearchOptions, getValidOptions} from '@libs/OptionsListUtils';
import type {Options, SearchOption} from '@libs/OptionsListUtils';
Expand Down Expand Up @@ -162,6 +163,10 @@ function SearchAutocompleteList(
const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST);
const allCards = useMemo(() => mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, userCardList), [userCardList, workspaceCardFeeds]);
const cardAutocompleteList = Object.values(allCards);
const cardFeedNamesWithType = useMemo(() => {
return getCardFeedNamesWithType({workspaceCardFeeds, userCardList, translate});
}, [translate, workspaceCardFeeds, userCardList]);
const feedAutoCompleteList = useMemo(() => Object.entries(cardFeedNamesWithType).map(([cardFeedKey, cardFeedName]) => ({cardFeedKey, cardFeedName})), [cardFeedNamesWithType]);

const participantsAutocompleteList = useMemo(() => {
if (!areOptionsInitialized) {
Expand Down Expand Up @@ -350,6 +355,20 @@ function SearchAutocompleteList(
text: expenseType,
}));
}
case CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED: {
const filteredFeeds = feedAutoCompleteList
.filter(
(feed) => feed.cardFeedName.name.toLowerCase().includes(autocompleteValue.toLowerCase()) && !alreadyAutocompletedKeys.includes(feed.cardFeedName.name.toLowerCase()),
)
.sort()
.slice(0, 10);
return filteredFeeds.map((feed) => ({
filterKey: CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS.FEED,
text: feed.cardFeedName.name,
autocompleteID: feed.cardFeedName.type === 'domain' ? feed.cardFeedKey : getCardFeedKey(workspaceCardFeeds, feed.cardFeedKey),
mapKey: CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED,
}));
}
case CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID: {
const filteredCards = cardAutocompleteList
.filter((card) => isCard(card) && !isCardHiddenFromSearch(card))
Expand Down Expand Up @@ -382,6 +401,8 @@ function SearchAutocompleteList(
typeAutocompleteList,
statusAutocompleteList,
expenseTypes,
feedAutoCompleteList,
workspaceCardFeeds,
cardAutocompleteList,
allCards,
]);
Expand All @@ -393,7 +414,7 @@ function SearchAutocompleteList(
const recentSearchesData = sortedRecentSearches?.slice(0, 5).map(({query, timestamp}) => {
const searchQueryJSON = buildSearchQueryJSON(query);
return {
text: searchQueryJSON ? buildUserReadableQueryString(searchQueryJSON, personalDetails, reports, taxRates, allCards) : query,
text: searchQueryJSON ? buildUserReadableQueryString(searchQueryJSON, personalDetails, reports, taxRates, allCards, cardFeedNamesWithType) : query,
singleIcon: Expensicons.History,
searchQuery: query,
keyForList: timestamp,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import type {SearchQueryJSON, SearchQueryString} from '@components/Search/types'
import {isSearchQueryItem} from '@components/SelectionList/Search/SearchQueryListItem';
import type {SearchQueryItem} from '@components/SelectionList/Search/SearchQueryListItem';
import type {SelectionListHandle} from '@components/SelectionList/types';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import {navigateToAndOpenReport} from '@libs/actions/Report';
import {clearAllFilters} from '@libs/actions/Search';
import {getCardFeedNamesWithType} from '@libs/CardFeedUtils';
import {mergeCardListWithWorkspaceFeeds} from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
import {getAllTaxRates} from '@libs/PolicyUtils';
Expand Down Expand Up @@ -56,6 +58,7 @@ function SearchPageHeaderInput({
inputRightComponent,
shouldGroupByReports,
}: SearchPageHeaderInputProps) {
const {translate} = useLocalize();
const [showPopupButton, setShowPopupButton] = useState(true);
const styles = useThemeStyles();
const {shouldUseNarrowLayout: displayNarrowHeader} = useResponsiveLayout();
Expand All @@ -65,10 +68,12 @@ function SearchPageHeaderInput({
const [userCardList] = useOnyx(ONYXKEYS.CARD_LIST);
const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST);
const allCards = useMemo(() => mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, userCardList), [userCardList, workspaceCardFeeds]);

const cardFeedNamesWithType = useMemo(() => {
return getCardFeedNamesWithType({workspaceCardFeeds, userCardList, translate});
}, [translate, workspaceCardFeeds, userCardList]);
const {inputQuery: originalInputQuery} = queryJSON;
const isDefaultQuery = isDefaultExpensesQuery(queryJSON);
const queryText = buildUserReadableQueryString(queryJSON, personalDetails, reports, taxRates, allCards);
const queryText = buildUserReadableQueryString(queryJSON, personalDetails, reports, taxRates, allCards, cardFeedNamesWithType);

// The actual input text that the user sees
const [textInputValue, setTextInputValue] = useState(isDefaultQuery ? '' : queryText);
Expand Down Expand Up @@ -107,9 +112,9 @@ function SearchPageHeaderInput({
}, [isDefaultQuery, queryText]);

useEffect(() => {
const substitutionsMap = buildSubstitutionsMap(originalInputQuery, personalDetails, reports, taxRates, allCards);
const substitutionsMap = buildSubstitutionsMap(originalInputQuery, personalDetails, reports, taxRates, allCards, cardFeedNamesWithType);
setAutocompleteSubstitutions(substitutionsMap);
}, [allCards, originalInputQuery, personalDetails, reports, taxRates]);
}, [cardFeedNamesWithType, allCards, originalInputQuery, personalDetails, reports, taxRates]);

useEffect(() => {
if (searchRouterListVisible) {
Expand Down Expand Up @@ -152,6 +157,7 @@ function SearchPageHeaderInput({
(queryString: SearchQueryString) => {
const queryWithSubstitutions = getQueryWithSubstitutions(queryString, autocompleteSubstitutions);
const updatedQuery = getQueryWithUpdatedValues(queryWithSubstitutions, queryJSON.policyID);

if (!updatedQuery) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import {clearAllFilters} from '@libs/actions/Search';
import {getCardFeedNamesWithType} from '@libs/CardFeedUtils';
import {mergeCardListWithWorkspaceFeeds} from '@libs/CardUtils';
import Navigation from '@libs/Navigation/Navigation';
import {getAllTaxRates} from '@libs/PolicyUtils';
Expand Down Expand Up @@ -58,6 +59,9 @@ 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 cardFeedNamesWithType = useMemo(() => {
return getCardFeedNamesWithType({workspaceCardFeeds, userCardList, translate});
}, [translate, workspaceCardFeeds, userCardList]);

const [isPopoverVisible, setIsPopoverVisible] = useState(false);
const buttonRef = useRef<HTMLDivElement>(null);
Expand All @@ -76,7 +80,7 @@ function SearchTypeMenuPopover({queryJSON, searchName, shouldGroupByReports}: Se

const typeMenuItems = useMemo(() => createTypeMenuItems(allPolicies, session?.email), [allPolicies, session?.email]);
const isCannedQuery = isCannedSearchQuery(queryJSON);
const title = searchName ?? (isCannedQuery ? undefined : buildUserReadableQueryString(queryJSON, personalDetails, reports, taxRates, allCards));
const title = searchName ?? (isCannedQuery ? undefined : buildUserReadableQueryString(queryJSON, personalDetails, reports, taxRates, allCards, cardFeedNamesWithType));
const activeItemIndex = isCannedQuery ? typeMenuItems.findIndex((item) => item.type === queryJSON.type) : -1;

const getOverflowMenu = useCallback(
Expand All @@ -89,7 +93,7 @@ function SearchTypeMenuPopover({queryJSON, searchName, shouldGroupByReports}: Se
let savedSearchTitle = item.name;
if (savedSearchTitle === item.query) {
const jsonQuery = buildSearchQueryJSON(item.query) ?? ({} as SearchQueryJSON);
savedSearchTitle = buildUserReadableQueryString(jsonQuery, personalDetails, reports, taxRates, allCards);
savedSearchTitle = buildUserReadableQueryString(jsonQuery, personalDetails, reports, taxRates, allCards, cardFeedNamesWithType);
}

const baseMenuItem: SavedSearchMenuItem = createBaseSavedSearchMenuItem(item, key, index, savedSearchTitle, hash);
Expand Down Expand Up @@ -120,7 +124,7 @@ function SearchTypeMenuPopover({queryJSON, searchName, shouldGroupByReports}: Se
shouldIconUseAutoWidthStyle: false,
};
},
[hash, getOverflowMenu, styles.textSupporting, personalDetails, reports, taxRates, allCards],
[hash, getOverflowMenu, styles.textSupporting, personalDetails, reports, taxRates, allCards, cardFeedNamesWithType],
);

const savedSearchItems = useMemo(() => {
Expand Down
8 changes: 5 additions & 3 deletions src/components/Search/SearchRouter/buildSubstitutionsMap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {OnyxCollection} from 'react-native-onyx';
import type {SearchAutocompleteQueryRange, SearchFilterKey} from '@components/Search/types';
import type {CardFeedNamesWithType} from '@libs/CardFeedUtils';
import {parse} from '@libs/SearchParser/autocompleteParser';
import {getFilterDisplayValue} from '@libs/SearchQueryUtils';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -30,6 +31,7 @@ function buildSubstitutionsMap(
reports: OnyxCollection<Report>,
allTaxRates: Record<string, string[]>,
cardList: CardList,
cardFeedNamesWithType: CardFeedNamesWithType,
): SubstitutionMap {
const parsedQuery = parse(query) as {ranges: SearchAutocompleteQueryRange[]};

Expand Down Expand Up @@ -60,9 +62,10 @@ function buildSubstitutionsMap(
filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.TO ||
filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.IN ||
filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.CARD_ID ||
filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG
filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.TAG ||
filterKey === CONST.SEARCH.SYNTAX_FILTER_KEYS.FEED
) {
const displayValue = getFilterDisplayValue(filterKey, filterValue, personalDetails, reports, cardList);
const displayValue = getFilterDisplayValue(filterKey, filterValue, personalDetails, reports, cardList, cardFeedNamesWithType);

// If displayValue === filterValue, then it means there is nothing to substitute, so we don't add any key to map
if (displayValue !== filterValue) {
Expand All @@ -74,7 +77,6 @@ function buildSubstitutionsMap(

return map;
}, {} as SubstitutionMap);

return substitutionsMap;
}

Expand Down
Loading
Loading