Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6434,6 +6434,7 @@ const CONST = {
},
SORT_BY_COLUMNS: {
CATEGORY_GL_CODE: 'glcode',
TAG_GL_CODE: 'tagglcode',
},
GROUP_BY: {
FROM: 'from',
Expand Down Expand Up @@ -6480,6 +6481,7 @@ const CONST = {
ATTENDEES: {column: this.TABLE_COLUMNS.ATTENDEES, search: true, reportView: true},
TOTAL_PER_ATTENDEE: {column: this.TABLE_COLUMNS.TOTAL_PER_ATTENDEE, search: true, reportView: true},
TAG: {column: this.TABLE_COLUMNS.TAG, search: true, reportView: true},
TAG_GL_CODE: {column: this.TABLE_COLUMNS.TAG_GL_CODE, search: true, reportView: true},
EXCHANGE_RATE: {column: this.TABLE_COLUMNS.EXCHANGE_RATE, search: true, reportView: true},
ORIGINAL_AMOUNT: {column: this.TABLE_COLUMNS.ORIGINAL_AMOUNT, search: true, reportView: true},
REPORT_ID: {column: this.TABLE_COLUMNS.REPORT_ID, search: true, reportView: false},
Expand Down Expand Up @@ -6734,6 +6736,7 @@ const CONST = {
MCC: 'mcc',
TAX_CODE: 'taxCode',
CATEGORY_GL_CODE: 'categoryGLCode',
TAG_GL_CODE: 'tagGLCode',
WITHDRAWAL_ID: 'withdrawalID',
SUBMITTER_USER_ID: 'submitterUserID',
SUBMITTER_PAYROLL_ID: 'submitterPayrollID',
Expand Down Expand Up @@ -6954,6 +6957,7 @@ const CONST = {
[this.TABLE_COLUMNS.MCC]: 'mcc',
[this.TABLE_COLUMNS.TAX_CODE]: 'tax-code',
[this.TABLE_COLUMNS.CATEGORY_GL_CODE]: 'category-gl-code',
[this.TABLE_COLUMNS.TAG_GL_CODE]: 'tag-gl-code',
[this.TABLE_COLUMNS.WITHDRAWAL_ID]: 'withdrawal-id',
[this.TABLE_COLUMNS.AVATAR]: 'avatar',
[this.TABLE_COLUMNS.STATUS]: 'status',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {hasFlexColumn} from '@libs/SearchUIUtils';
import {getTransactionPendingAction, isTransactionPendingDelete} from '@libs/TransactionUtils';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import type {CardList, Policy, PolicyCategories, Report, TransactionViolations} from '@src/types/onyx';
import type {CardList, Policy, PolicyCategories, PolicyTagLists, Report, TransactionViolations} from '@src/types/onyx';
import type {TransactionWithOptionalHighlight} from './MoneyRequestReportTransactionList';

type MoneyRequestReportTransactionItemProps = {
Expand All @@ -40,6 +40,9 @@ type MoneyRequestReportTransactionItemProps = {
/** Categories for the policy to which the transaction belongs */
policyCategories?: PolicyCategories;

/** Tag lists for the policy to which the transaction belongs */
policyTagLists?: PolicyTagLists;

/** Whether the mobile selection mode is enabled */
isSelectionModeEnabled: boolean;

Expand Down Expand Up @@ -104,6 +107,7 @@ function MoneyRequestReportTransactionItemBody({
report,
policy,
policyCategories,
policyTagLists,
isSelectionModeEnabled,
toggleTransaction,
isSelected,
Expand Down Expand Up @@ -201,6 +205,7 @@ function MoneyRequestReportTransactionItemBody({
report={report}
policy={policy}
policyCategories={policyCategories}
policyTagLists={policyTagLists}
transactionThreadReportID={transactionThreadReportID}
isSelected={isSelected}
dateColumnSize={dateColumnSize}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ function MoneyRequestReportTransactionList({
const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector});
const [allTransactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report?.policyID}`);
const [policyTagLists] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`);

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

Expand Down Expand Up @@ -378,15 +379,15 @@ function MoneyRequestReportTransactionList({
}
}
return compareValues(
getTransactionSortValue(a, sortBy, report, policy, policyCategories),
getTransactionSortValue(b, sortBy, report, policy, policyCategories),
getTransactionSortValue(a, sortBy, report, policy, policyCategories, policyTagLists),
getTransactionSortValue(b, sortBy, report, policy, policyCategories, policyTagLists),
sortOrder,
sortBy,
localeCompare,
true,
);
});
}, [sortBy, sortOrder, transactions, localeCompare, report, policy, policyCategories, rbrTransactionIDs]);
}, [sortBy, sortOrder, transactions, localeCompare, report, policy, policyCategories, policyTagLists, rbrTransactionIDs]);

const resolvedTransactions = useMemo(() => resolveTransactionCardFields(sortedTransactions, cardList, translate), [sortedTransactions, cardList, translate]);

Expand All @@ -409,19 +410,8 @@ function MoneyRequestReportTransactionList({
shouldShowReimbursableColumn: hasNonReimbursableTransactions(transactions),
reportCurrency: report?.currency,
isPolicyTaxEnabled: isTaxEnabled,
policyCategories,
});
}, [
transactions,
currentUserDetails?.accountID,
isExpenseReportViewFromIOUReport,
shouldShowBillableColumn,
shouldShowCommentsColumn,
reportDetailsColumns,
report,
isTaxEnabled,
policyCategories,
]);
}, [transactions, currentUserDetails?.accountID, isExpenseReportViewFromIOUReport, shouldShowBillableColumn, shouldShowCommentsColumn, reportDetailsColumns, report, isTaxEnabled]);

const {windowWidth, windowHeight} = useWindowDimensions();
const minTableWidth = getTableMinWidth(columnsToShow);
Expand Down Expand Up @@ -710,6 +700,7 @@ function MoneyRequestReportTransactionList({
report={report}
policy={policy}
policyCategories={policyCategories}
policyTagLists={policyTagLists}
isSelectionModeEnabled={isMobileSelectionModeEnabled}
toggleTransaction={toggleTransaction}
isSelected={isTransactionSelected(transaction.transactionID)}
Expand Down
3 changes: 1 addition & 2 deletions src/components/Search/FilterDropdowns/SortByPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,11 @@ function SortByPopup({searchResults, queryJSON, groupBy, onSort, onSortOrderPres
const {clearSelectedTransactions} = useSearchSelectionActions();

const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
const [policyCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CATEGORIES);

const searchDataType = shouldUseLiveData ? CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT : searchResults?.search?.type;
const currentColumns = !searchResults?.data
? []
: getColumnsToShow({currentAccountID: accountID, data: searchResults.data, visibleColumns, type: searchDataType, groupBy: groupBy?.value, policyCategories});
: getColumnsToShow({currentAccountID: accountID, data: searchResults.data, visibleColumns, type: searchDataType, groupBy: groupBy?.value});
const sortableColumns = getSortByOptions(currentColumns, translate);
const sortOrder = queryJSON.sortOrder;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION);
const [policyCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CATEGORIES);
const [policyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS);
const {policyForMovingExpensesID} = usePolicyForMovingExpenses();

const transactionsSnapshotMetadata = transactionsSnapshot?.search;
Expand Down Expand Up @@ -123,18 +124,20 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
data: transactionsSnapshot?.data,
visibleColumns,
type: transactionsSnapshot?.search.type,
policyCategories,
fallbackPolicyID: policyForMovingExpensesID,
});
}
}

const getPolicyCategoriesForTransaction = (transaction: TransactionListItemType) => {
const transactionPolicyID =
[transaction.policyID, transaction.policy?.id, transaction.report?.policyID].find(Boolean) ??
(transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID ? policyForMovingExpensesID : undefined);
return policyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${getNonEmptyStringOnyxID(transactionPolicyID)}`];
};
const getTransactionPolicyID = (transaction: TransactionListItemType) =>
[transaction.policyID, transaction.policy?.id, transaction.report?.policyID].find(Boolean) ??
(transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID ? policyForMovingExpensesID : undefined);

const getPolicyCategoriesForTransaction = (transaction: TransactionListItemType) =>
policyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${getNonEmptyStringOnyxID(getTransactionPolicyID(transaction))}`];

const getPolicyTagListsForTransaction = (transaction: TransactionListItemType) =>
policyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${getNonEmptyStringOnyxID(getTransactionPolicyID(transaction))}`];

// Currently only the transaction report groups have transactions where the empty view makes sense
const shouldDisplayShowMoreButton = isExpenseReportType ? transactions.length > transactionsVisibleLimit : !!transactionsSnapshotMetadata?.hasMoreResults && !isOffline;
Expand Down Expand Up @@ -341,6 +344,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
report={transaction.report}
policy={transaction.policy}
policyCategories={getPolicyCategoriesForTransaction(transaction)}
policyTagLists={getPolicyTagListsForTransaction(transaction)}
transactionItem={transaction}
violations={getTransactionViolations(
transaction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function TransactionListItemWide<TItem extends ListItem>({
transactionPreviewData,
exportedReportActions,
policyCategories,
policyTagLists,
nonPersonalAndWorkspaceCards,
isAttendeesEnabledForMovingPolicy,
currentSearchHash,
Expand Down Expand Up @@ -173,6 +174,7 @@ function TransactionListItemWide<TItem extends ListItem>({
report={transactionItem.report}
policy={transactionItem.policy}
policyCategories={policyCategories}
policyTagLists={policyTagLists}
shouldShowTooltip={showTooltip}
onButtonPress={handleActionButtonPress}
onCheckboxPress={() => onCheckboxPress?.(item)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ function TransactionListItem<TItem extends ListItem>({

// Fetch policy categories directly from Onyx since they are not included in the search snapshot
const [policyCategories] = originalUseOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${getNonEmptyStringOnyxID(policyID)}`);
// Fetch policy tags directly from Onyx (not in the snapshot) so the Tag GL code cell can resolve.
const [policyTagLists] = originalUseOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${getNonEmptyStringOnyxID(policyID)}`);

const [parentReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(transactionItem.reportID)}`);
const [transactionThreadReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionItem?.reportAction?.childReportID}`);
Expand Down Expand Up @@ -222,6 +224,7 @@ function TransactionListItem<TItem extends ListItem>({
transactionPreviewData,
exportedReportActions,
policyCategories,
policyTagLists,
nonPersonalAndWorkspaceCards,
isAttendeesEnabledForMovingPolicy,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {ListItemFocusEventHandler} from '@components/SelectionList/ListItem
import type {ListItem} from '@components/SelectionList/types';
import type {TransactionPreviewData} from '@libs/actions/Search';
import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
import type {CardList, PolicyCategories, ReportAction, TransactionViolation} from '@src/types/onyx';
import type {CardList, PolicyCategories, PolicyTagLists, ReportAction, TransactionViolation} from '@src/types/onyx';

type TransactionListItemSharedProps<TItem extends ListItem> = {
item: TItem;
Expand All @@ -26,6 +26,7 @@ type TransactionListItemSharedProps<TItem extends ListItem> = {
transactionPreviewData: TransactionPreviewData;
exportedReportActions: ReportAction[];
policyCategories?: PolicyCategories;
policyTagLists?: PolicyTagLists;
nonPersonalAndWorkspaceCards?: CardList;
isAttendeesEnabledForMovingPolicy?: boolean;
};
Expand Down
3 changes: 3 additions & 0 deletions src/components/Search/SearchList/ListItem/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
LastPaymentMethod,
PersonalDetails,
Policy,
PolicyTagLists,
Report,
ReportAction,
SearchResults,
Expand Down Expand Up @@ -446,6 +447,8 @@ type TransactionListItemProps<TItem extends ListItem> = ListItemProps<TItem> &
columns?: SearchColumnType[];
/** Non-personal and workspace cards for company card display */
nonPersonalAndWorkspaceCards?: CardList;
/** All policies' tag lists, drilled from the list level so each row can resolve its policy's tags without an Onyx subscription per row */
policyTags?: OnyxCollection<PolicyTagLists>;
/** Callback to undelete a transaction */
onUndelete?: (transaction: Transaction) => void;
};
Expand Down
9 changes: 8 additions & 1 deletion src/components/Search/SearchList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, {useCallback, useImperativeHandle, useMemo, useRef, useState} from
import type {ForwardedRef} from 'react';
import {View} from 'react-native';
import type {NativeSyntheticEvent, StyleProp, ViewStyle} from 'react-native';
import type {OnyxCollection} from 'react-native-onyx';
import AnimatedExitRow from '@components/Search/primitives/AnimatedExitRow';
import HorizontalTableScroll from '@components/Search/primitives/HorizontalTableScroll';
import SelectionTopBar from '@components/Search/primitives/SelectionTopBar';
Expand All @@ -29,7 +30,7 @@ import type {TransactionPreviewData} from '@userActions/Search';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
import type {CardList, Transaction} from '@src/types/onyx';
import type {CardList, PolicyTagLists, Transaction} from '@src/types/onyx';
import BaseSearchList from './BaseSearchList';
import type ChatListItem from './ListItem/ChatListItem';
import type ExpenseReportListItem from './ListItem/ExpenseReportListItem';
Expand Down Expand Up @@ -106,6 +107,9 @@ type SearchListProps = Pick<FlashListProps<SearchListItem>, 'onScroll' | 'conten
/** Non-personal and workspace cards (same drill path as former custom card names for rows) */
nonPersonalAndWorkspaceCards?: CardList;

/** All policies' tag lists, drilled from the list level so each row can resolve its policy's tags without an Onyx subscription per row */
policyTags?: OnyxCollection<PolicyTagLists>;

/** Whether all transactions have been loaded from snapshots in group-by views */
hasLoadedAllTransactions?: boolean;

Expand Down Expand Up @@ -194,6 +198,7 @@ function SearchList({
newTransactions = [],
nonPersonalAndWorkspaceCards,
hasLoadedAllTransactions,
policyTags,
isActionColumnWide,
isAttendeesEnabledForMovingPolicy,
ref,
Expand Down Expand Up @@ -543,6 +548,7 @@ function SearchList({
userBillingGracePeriodEnds={userBillingGracePeriodEnds}
ownerBillingGracePeriodEnd={ownerBillingGracePeriodEnd}
nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
policyTags={policyTags}
onFocus={onFocus}
newTransactionID={newTransactionID}
onUndelete={handleUndelete}
Expand Down Expand Up @@ -571,6 +577,7 @@ function SearchList({
userBillingGracePeriodEnds,
ownerBillingGracePeriodEnd,
nonPersonalAndWorkspaceCards,
policyTags,
ListFooterComponent,
handleUndelete,
firstVisibleIndex,
Expand Down
5 changes: 5 additions & 0 deletions src/components/Search/SearchTableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ const getExpenseHeaders = (groupBy?: SearchGroupBy): SearchColumnConfig[] => [
translationKey: 'common.tag',
canEdit: true,
},
{
columnName: CONST.SEARCH.TABLE_COLUMNS.TAG_GL_CODE,
translationKey: 'common.tagGLCode',
sortColumnName: CONST.SEARCH.SORT_BY_COLUMNS.TAG_GL_CODE,
},
{
columnName: CONST.SEARCH.TABLE_COLUMNS.REIMBURSABLE,
translationKey: 'common.reimbursable',
Expand Down
20 changes: 17 additions & 3 deletions src/components/Search/SortableHeaderText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,33 @@ type SearchTableHeaderColumnProps = WithSentryLabel & {
sortOrder: SortOrder;
isSortable?: boolean;
containerStyle?: StyleProp<ViewStyle>;

/** Styles for the inner content row. Put padding/borders here, not on the container, so flex columns stay aligned. */
innerContainerStyle?: StyleProp<ViewStyle>;
textStyle?: StyleProp<TextStyle>;
onPress: (order: SortOrder) => void;
};

export default function SortableHeaderText({text, icon, sortOrder, isActive, textStyle, containerStyle, isSortable = true, onPress, sentryLabel}: SearchTableHeaderColumnProps) {
export default function SortableHeaderText({
text,
icon,
sortOrder,
isActive,
textStyle,
containerStyle,
innerContainerStyle,
isSortable = true,
onPress,
sentryLabel,
}: SearchTableHeaderColumnProps) {
const icons = useMemoizedLazyExpensifyIcons(['ArrowDownLong', 'ArrowUpLong']);
const styles = useThemeStyles();
const theme = useTheme();

if (!isSortable) {
return (
<View style={containerStyle}>
<View style={[styles.flexRow, styles.alignItemsCenter, styles.gap1]}>
<View style={[styles.flexRow, styles.alignItemsCenter, styles.gap1, innerContainerStyle]}>
{!!icon && (
<Icon
src={icon}
Expand Down Expand Up @@ -69,7 +83,7 @@ export default function SortableHeaderText({text, icon, sortOrder, isActive, tex
disabled={!isSortable}
sentryLabel={sentryLabel}
>
<View style={[styles.flexRow, styles.alignItemsCenter, styles.gap1]}>
<View style={[styles.flexRow, styles.alignItemsCenter, styles.gap1, innerContainerStyle]}>
{!!icon && (
<Icon
src={icon}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Search/SortableTableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ function SortableTableHeader({
sortOrder={sortOrder ?? CONST.SEARCH.SORT_ORDER.ASC}
isActive={isActive}
sentryLabel={CONST.SENTRY_LABEL.SEARCH.SORTABLE_HEADER}
innerContainerStyle={canEdit && styles.editableCellHeader}
containerStyle={[
canEdit && styles.editableCellHeader,
StyleUtils.getReportTableColumnStyles(columnName, {
isDateColumnWide: dateColumnSize === CONST.SEARCH.TABLE_COLUMN_SIZES.WIDE,
isSubmittedColumnWide: submittedColumnSize === CONST.SEARCH.TABLE_COLUMN_SIZES.WIDE,
Expand Down
Loading
Loading