Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
d7faef1
add columns button
JS00001 Dec 15, 2025
763542a
add faux translations
JS00001 Dec 15, 2025
a39ee54
create columns page
JS00001 Dec 15, 2025
9cfa9bb
add route for rhp
JS00001 Dec 15, 2025
1a8f900
navigate on click
JS00001 Dec 15, 2025
4c84d05
finish column RHP
JS00001 Dec 15, 2025
6ad72b0
add columns as search advanced filter
JS00001 Dec 15, 2025
6a1c1aa
add translation for col names
JS00001 Dec 15, 2025
582f325
add initial selected item
JS00001 Dec 15, 2025
e9b9080
remove jump to top behavior
JS00001 Dec 15, 2025
fa938b4
add new selection list
JS00001 Dec 15, 2025
201a4ba
more logic for cols
JS00001 Dec 15, 2025
3b61518
cleanup search page
JS00001 Dec 15, 2025
1dc9ea6
set the advanced filter form
JS00001 Dec 15, 2025
6d453ed
save to query
JS00001 Dec 15, 2025
95b2406
add highlight via syntax
JS00001 Dec 15, 2025
9bc6c59
parser updates
JS00001 Dec 15, 2025
96f5cb8
add all columns by default
JS00001 Dec 15, 2025
2a36968
add errors
JS00001 Dec 15, 2025
2b80f8c
update custom column types
JS00001 Dec 15, 2025
29c0d61
new parsers
JS00001 Dec 15, 2025
2880362
update more to use query json
JS00001 Dec 15, 2025
69e8e9c
parser updates
JS00001 Dec 15, 2025
a499268
add defaults and reset columns
JS00001 Dec 15, 2025
24c69e7
reset columns functionality
JS00001 Dec 15, 2025
9cad167
add logic for filtering out columns
JS00001 Dec 15, 2025
27d0c8f
add visiible columns
JS00001 Dec 15, 2025
d0f39dd
update to expense report, not expense
JS00001 Dec 15, 2025
04dd680
update search ui logic for expens e reports
JS00001 Dec 15, 2025
b7ea9ae
add visibility logic to reports
JS00001 Dec 15, 2025
9fb1bc8
fix visibility not working for avatars
JS00001 Dec 15, 2025
4135929
fix reset filters showing up incorrectly
JS00001 Dec 15, 2025
673290e
Merge branch 'main' of github.com:Expensify/App into jsenyitko-custom…
JS00001 Dec 15, 2025
830162a
add spanish translations, revert changes to search selection picker
JS00001 Dec 15, 2025
e8e2bc6
all other translations
JS00001 Dec 15, 2025
396325c
compress svg and search columns page comment updates
JS00001 Dec 15, 2025
4ffe323
fix react checks and misspelled words
JS00001 Dec 15, 2025
1aa1059
update canned search query logic
JS00001 Dec 15, 2025
733be87
hash the columns as well
JS00001 Dec 15, 2025
ae4c645
Merge branch 'main' of github.com:Expensify/App into jsenyitko-custom…
JS00001 Dec 15, 2025
b8cade9
fix hash crash
JS00001 Dec 15, 2025
e172776
add disabled logic
JS00001 Dec 15, 2025
8c4e9e7
rename consts for search to re-use table columns
JS00001 Dec 15, 2025
badd8b2
use new consts everywhere
JS00001 Dec 15, 2025
b2e2ce8
Merge branch 'main' of github.com:Expensify/App into jsenyitko-custom…
JS00001 Dec 15, 2025
ff3c20b
add tests for search ui utils
JS00001 Dec 15, 2025
1db948b
fix tests
JS00001 Dec 15, 2025
be8487d
fix style issues with date
JS00001 Dec 15, 2025
9ef5284
fix react key errors
JS00001 Dec 15, 2025
95f6e76
fix hashing method
JS00001 Dec 15, 2025
00445e5
only show for reports
JS00001 Dec 15, 2025
958d410
update reportName to title
JS00001 Dec 15, 2025
cd41d5b
remove dead code
JS00001 Dec 15, 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
1 change: 1 addition & 0 deletions assets/images/columns.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6699,6 +6699,21 @@ const CONST = {
CARD: 'card',
WITHDRAWAL_ID: 'withdrawal-id',
},
get CUSTOM_COLUMNS() {
return {
DATE: this.TABLE_COLUMNS.DATE,
STATUS: this.TABLE_COLUMNS.STATUS,
TITLE: this.TABLE_COLUMNS.TITLE,
FROM: this.TABLE_COLUMNS.FROM,
TO: this.TABLE_COLUMNS.TO,
ACTION: this.TABLE_COLUMNS.ACTION,
};
},
get DEFAULT_COLUMNS() {
return {
EXPENSE_REPORT: [this.TABLE_COLUMNS.DATE, this.TABLE_COLUMNS.STATUS, this.TABLE_COLUMNS.TITLE, this.TABLE_COLUMNS.FROM, this.TABLE_COLUMNS.TO, this.TABLE_COLUMNS.ACTION],
};
},
BOOLEAN: {
YES: 'yes',
NO: 'no',
Expand Down Expand Up @@ -6781,6 +6796,7 @@ const CONST = {
SORT_BY: 'sortBy',
SORT_ORDER: 'sortOrder',
GROUP_BY: 'groupBy',
COLUMNS: 'columns',
},
SYNTAX_FILTER_KEYS: {
TYPE: 'type',
Expand Down Expand Up @@ -6889,6 +6905,7 @@ const CONST = {
ATTENDEE: 'attendee',
IS: 'is',
REPORT_FIELD: 'report-field',
COLUMNS: 'columns',
},
get SEARCH_USER_FRIENDLY_VALUES_MAP() {
return {
Expand Down
1 change: 1 addition & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const ROUTES = {
route: 'search/saved-search/rename',
getRoute: ({name, jsonQuery}: {name: string; jsonQuery: SearchQueryString}) => `search/saved-search/rename?name=${name}&q=${jsonQuery}` as const,
},
SEARCH_COLUMNS: 'search/columns',
SEARCH_ADVANCED_FILTERS: {
route: 'search/filters/:filterKey?',
getRoute: (filterKey?: SearchFilterKey | UserFriendlyKey) => {
Expand Down
2 changes: 2 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const SCREENS = {
MONEY_REQUEST_REPORT_HOLD_TRANSACTIONS: 'Search_Money_Request_Report_Hold_Transactions',
MONEY_REQUEST_REPORT_REJECT_TRANSACTIONS: 'Search_Money_Request_Report_Reject_Transactions',
REPORT_RHP: 'Search_Report_RHP',
COLUMNS_RHP: 'Search_Columns_RHP',
REPORT_VERIFY_ACCOUNT: 'Search_Report_Verify_Account',
ADVANCED_FILTERS_RHP: 'Search_Advanced_Filters_RHP',
ADVANCED_FILTERS_TYPE_RHP: 'Search_Advanced_Filters_Type_RHP',
Expand Down Expand Up @@ -253,6 +254,7 @@ const SCREENS = {
EXPENSE_REPORT: 'ExpenseReport',
SEARCH_MONEY_REQUEST_REPORT: 'SearchMoneyRequestReport',

SEARCH_COLUMNS: 'SearchColumns',
SEARCH_ADVANCED_FILTERS: 'SearchAdvancedFilters',
SEARCH_SAVED_SEARCH: 'SearchSavedSearch',
SETTINGS_CATEGORIES: 'SettingsCategories',
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import Close from '@assets/images/close.svg';
import ClosedSign from '@assets/images/closed-sign.svg';
import Coins from '@assets/images/coins.svg';
import Collapse from '@assets/images/collapse.svg';
import Columns from '@assets/images/columns.svg';
import CommentBubbles from '@assets/images/comment-bubbles.svg';
import Concierge from '@assets/images/concierge.svg';
import Connect from '@assets/images/connect.svg';
Expand Down Expand Up @@ -216,6 +217,7 @@ export {
ConciergeAvatar,
Connect,
ConnectionComplete,
Columns,
Copy,
CreditCard,
CreditCardHourglass,
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/chunks/expensify-icons.chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import Close from '@assets/images/close.svg';
import ClosedSign from '@assets/images/closed-sign.svg';
import Coins from '@assets/images/coins.svg';
import Collapse from '@assets/images/collapse.svg';
import Columns from '@assets/images/columns.svg';
import CommentBubbles from '@assets/images/comment-bubbles.svg';
import Concierge from '@assets/images/concierge.svg';
import Connect from '@assets/images/connect.svg';
Expand Down Expand Up @@ -266,6 +267,7 @@ const Expensicons = {
Clock,
ClosedSign,
Collapse,
Columns,
CommentBubbles,
Concierge,
ConciergeAvatar,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import type {TupleToUnion} from 'type-fest';
import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
import Checkbox from '@components/Checkbox';
import * as Expensicons from '@components/Icon/Expensicons';

Check warning on line 8 in src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'@components/Icon/Expensicons' import is restricted from being used by a pattern. Direct imports from Icon/Expensicons are deprecated. Please use lazy loading hooks instead. Use `useMemoizedLazyExpensifyIcons` from @hooks/useLazyAsset. See docs/LAZY_ICONS_AND_ILLUSTRATIONS.md for details

Check warning on line 8 in src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'@components/Icon/Expensicons' import is restricted from being used. Direct imports from @components/Icon/Expensicons are deprecated. Please use lazy loading hooks instead. Use `useMemoizedLazyExpensifyIcons` from @hooks/useLazyAsset. See docs/LAZY_ICONS_AND_ILLUSTRATIONS.md for details
import MenuItem from '@components/MenuItem';
import Modal from '@components/Modal';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
Expand Down Expand Up @@ -65,6 +65,7 @@
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
import type * as OnyxTypes from '@src/types/onyx';
import type {PendingAction} from '@src/types/onyx/OnyxCommon';
import MoneyRequestReportGroupHeader from './MoneyRequestReportGroupHeader';
Expand Down Expand Up @@ -183,6 +184,8 @@
const shouldShowAddExpenseButton = canAddTransaction(report, isReportArchived) && isCurrentUserSubmitter(report);
const [lastDistanceExpenseType] = useOnyx(ONYXKEYS.NVP_LAST_DISTANCE_EXPENSE_TYPE, {canBeMissing: true});
const [reportLayoutGroupBy] = useOnyx(ONYXKEYS.NVP_REPORT_LAYOUT_GROUP_BY, {canBeMissing: true});
const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {canBeMissing: true, selector: columnsSelector});

const shouldShowGroupedTransactions = isExpenseReport(report) && !isIOUReport(report);

const addExpenseDropdownOptions = useMemo(
Expand Down Expand Up @@ -265,9 +268,9 @@
}, [newTransactions, sortBy, sortOrder, transactions, localeCompare, report]);

const columnsToShow = useMemo(() => {
const columns = getColumnsToShow(currentUserDetails?.accountID, transactions, true);
const columns = getColumnsToShow(currentUserDetails?.accountID, transactions, visibleColumns, true);
return (Object.keys(columns) as SearchColumnType[]).filter((column) => columns[column]);
}, [transactions, currentUserDetails?.accountID]);
}, [transactions, currentUserDetails?.accountID, visibleColumns]);

const currentGroupBy = getReportLayoutGroupBy(reportLayoutGroupBy);

Expand Down
61 changes: 47 additions & 14 deletions src/components/Search/SearchPageHeader/SearchFiltersBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function SearchFiltersBar({

const {isOffline} = useNetwork();
const personalDetails = usePersonalDetails();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {shouldUseNarrowLayout, isLargeScreenWidth} = useResponsiveLayout();
const {selectedTransactions, selectAllMatchingItems, areAllMatchingItemsSelected, showSelectAllMatchingItems, shouldShowFiltersBarLoading} = useSearchContext();

const [email] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: true, selector: emailSelector});
Expand All @@ -113,7 +113,7 @@ function SearchFiltersBar({
const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER, {canBeMissing: true});
const {isAccountLocked, showLockedAccountModal} = useContext(LockedAccountContext);
const [searchResultsErrors] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, {canBeMissing: true, selector: searchResultsErrorSelector});
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Filter'] as const);
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Filter', 'Columns'] as const);

const taxRates = getAllTaxRates(allPolicies);

Expand Down Expand Up @@ -324,6 +324,10 @@ function SearchFiltersBar({
Navigation.navigate(ROUTES.SEARCH_ADVANCED_FILTERS.getRoute());
}, [filterFormValues]);

const openSearchColumns = () => {
Navigation.navigate(ROUTES.SEARCH_COLUMNS);
};

const isFormInitializedRef = useRef(false);

useEffect(() => {
Expand Down Expand Up @@ -777,26 +781,55 @@ function SearchFiltersBar({
[],
);

const shouldShowColumnsButton = isLargeScreenWidth && queryJSON.type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;

const filterButtonText = useMemo(
() => translate('search.filtersHeader') + (hiddenSelectedFilters.length > 0 ? ` (${hiddenSelectedFilters.length})` : ''),
[translate, hiddenSelectedFilters.length],
);

const renderListFooter = useCallback(
() => (
<Button
link
small
shouldUseDefaultHover={false}
text={filterButtonText}
iconFill={theme.link}
iconHoverFill={theme.linkHover}
icon={expensifyIcons.Filter}
textStyles={[styles.textMicroBold]}
onPress={openAdvancedFilters}
/>
<View style={[styles.flexRow, styles.gap2]}>
<Button
link
small
shouldUseDefaultHover={false}
text={filterButtonText}
iconFill={theme.link}
iconHoverFill={theme.linkHover}
icon={expensifyIcons.Filter}
textStyles={[styles.textMicroBold]}
onPress={openAdvancedFilters}
/>
{shouldShowColumnsButton && (
<Button
link
small
shouldUseDefaultHover={false}
text={translate('search.columns')}
iconFill={theme.link}
iconHoverFill={theme.linkHover}
icon={expensifyIcons.Columns}
textStyles={[styles.textMicroBold]}
onPress={openSearchColumns}
/>
)}
</View>
),
[filterButtonText, theme.link, theme.linkHover, styles.textMicroBold, openAdvancedFilters, expensifyIcons],
[
styles.flexRow,
styles.gap2,
styles.textMicroBold,
filterButtonText,
theme.link,
theme.linkHover,
expensifyIcons.Filter,
expensifyIcons.Columns,
openAdvancedFilters,
shouldShowColumnsButton,
translate,
Comment thread
JS00001 marked this conversation as resolved.
],
);

if (hasErrors) {
Expand Down
7 changes: 5 additions & 2 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
import {isActionLoadingSetSelector} from '@src/selectors/ReportMetaData';
import type {OutstandingReportsByPolicyIDDerivedValue, Transaction} from '@src/types/onyx';
import type SearchResults from '@src/types/onyx/SearchResults';
Expand Down Expand Up @@ -283,6 +284,8 @@ function Search({
const [violations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true});
const {accountID, email} = useCurrentUserPersonalDetails();
const [isActionLoadingSet = new Set<string>()] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}`, {canBeMissing: true, selector: isActionLoadingSetSelector});
const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {canBeMissing: true, selector: columnsSelector});

const isExpenseReportType = type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;

// Filter violations based on user visibility
Expand Down Expand Up @@ -824,10 +827,10 @@ function Search({
if (!searchResults?.data) {
return [];
}
const columns = getColumnsToShow(accountID, searchResults?.data, false, searchResults?.search?.type);
const columns = getColumnsToShow(accountID, searchResults?.data, visibleColumns, false, searchResults?.search?.type);

return (Object.keys(columns) as SearchColumnType[]).filter((col) => columns[col]);
}, [accountID, searchResults?.data, searchResults?.search?.type]);
}, [accountID, searchResults?.data, searchResults?.search?.type, visibleColumns]);

const opacity = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
Expand Down
6 changes: 5 additions & 1 deletion src/components/Search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ type TableColumnSize = ValueOf<typeof CONST.SEARCH.TABLE_COLUMN_SIZES>;
type SearchDatePreset = ValueOf<typeof CONST.SEARCH.DATE_PRESETS>;
type SearchWithdrawalType = ValueOf<typeof CONST.SEARCH.WITHDRAWAL_TYPE>;
type SearchAction = ValueOf<typeof CONST.SEARCH.ACTION_FILTERS>;
type SearchCustomColumnIds = ValueOf<typeof CONST.SEARCH.CUSTOM_COLUMNS>;

type SearchContextData = {
currentSearchHash: number;
Expand Down Expand Up @@ -196,7 +197,8 @@ type SearchFilterKey =
| ValueOf<typeof CONST.SEARCH.SYNTAX_FILTER_KEYS>
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.TYPE
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.STATUS
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY;
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.GROUP_BY
| typeof CONST.SEARCH.SYNTAX_ROOT_KEYS.COLUMNS;

type UserFriendlyKey = ValueOf<typeof CONST.SEARCH.SEARCH_USER_FRIENDLY_KEYS>;
type UserFriendlyValue = ValueOf<typeof CONST.SEARCH.SEARCH_USER_FRIENDLY_VALUES_MAP>;
Expand All @@ -222,6 +224,7 @@ type SearchQueryAST = {
status: SearchStatus;
sortBy: SearchColumnType;
sortOrder: SortOrder;
columns?: SearchCustomColumnIds[];
groupBy?: SearchGroupBy;
filters: ASTNode;
policyID?: string[];
Expand Down Expand Up @@ -310,4 +313,5 @@ export type {
SelectedReports,
SearchTextFilterKeys,
BankAccountMenuItem,
SearchCustomColumnIds,
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
isLoading,
isFocused,
showTooltip,
columns,
canSelectMultiple,
onSelectRow,
onFocus,
Expand Down Expand Up @@ -159,6 +160,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
<View style={[styles.flex1]}>
<ExpenseReportListItemRow
item={reportItem}
columns={columns}
policy={snapshotPolicy}
isActionLoading={isActionLoading ?? isLoading}
showTooltip={showTooltip}
Expand Down
Loading
Loading