Skip to content
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

show recents in participants page based on action type #35431

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
adec852
show recents in participants page based on action type
rojiphil Jan 30, 2024
40b7aad
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Jan 31, 2024
5faec94
get transactions by action type
rojiphil Jan 31, 2024
69b5ff6
regression fixes
rojiphil Jan 31, 2024
64e6273
Fix for showing recent tasks
rojiphil Jan 31, 2024
7299643
prettier fix
rojiphil Jan 31, 2024
998f474
sort optimization
rojiphil Jan 31, 2024
8aa9601
use participant account ids for tasks
rojiphil Jan 31, 2024
c62108a
fix for max num of recents displayed
rojiphil Jan 31, 2024
d9cd091
reverting recent list by task action type
rojiphil Feb 1, 2024
5570493
fixes for recent list for money request action type
rojiphil Feb 1, 2024
9149a6a
fixes for recent list of task action type
rojiphil Feb 1, 2024
21e4eb6
Minor fix and added comments
rojiphil Feb 1, 2024
745ed17
prettier fix and check perf
rojiphil Feb 1, 2024
609acb2
Merge branch 'Expensify:main' into 34227-feature-show-recents-based-o…
rojiphil Feb 1, 2024
d9bcc73
fix for recent list of task action type
rojiphil Feb 1, 2024
3a8a5b8
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Feb 1, 2024
0a665e8
Merge branch 'Expensify:main' into 34227-feature-show-recents-based-o…
rojiphil Feb 2, 2024
54032a0
review feedback changes
rojiphil Feb 2, 2024
9919f20
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Feb 9, 2024
f34dd98
fix merge issues for IOUActionType
rojiphil Feb 9, 2024
3321875
use parent report of task in recent list
rojiphil Feb 12, 2024
a485edd
Merge branch 'Expensify:main' into 34227-feature-show-recents-based-o…
rojiphil Feb 19, 2024
2bfaf54
Merge branch 'Expensify:main' into 34227-feature-show-recents-based-o…
rojiphil Feb 20, 2024
bb40c9c
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil Feb 22, 2024
f319d1d
Merge branch 'Expensify:main' into 34227-feature-show-recents-based-o…
rojiphil Feb 22, 2024
591c6ef
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil Mar 1, 2024
16da324
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Mar 2, 2024
5a5d986
added timing logs
rojiphil Mar 5, 2024
2ff5217
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Mar 11, 2024
a9aa329
typecheck and prettier fix
rojiphil Mar 11, 2024
7f76198
removal of temporary code relating to timing logs
rojiphil Mar 11, 2024
b51298e
Update src/libs/TransactionUtils.ts
rojiphil Mar 11, 2024
ba95168
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil Mar 21, 2024
1b63dd8
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Apr 3, 2024
5180407
prettier fix
rojiphil Apr 3, 2024
0b3def2
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Apr 7, 2024
78374dc
task selector fix
rojiphil Apr 7, 2024
29d68b4
typecheck fix for recentReportOptions
rojiphil Apr 7, 2024
92bec33
fix for split request and prettier fix
rojiphil Apr 8, 2024
4fb7f58
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil Apr 11, 2024
4305481
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil Apr 12, 2024
faa9ed4
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil Apr 19, 2024
2ae00e8
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil Apr 22, 2024
e6c1b83
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Apr 24, 2024
04bffab
Resolving merge conflict
rojiphil Apr 24, 2024
9005bc0
Merge branch 'main' of https://github.com/Expensify/App into 34227-fe…
rojiphil Apr 29, 2024
e154b5b
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil May 1, 2024
5bcae4a
Merge branch 'main' into 34227-feature-show-recents-based-on-action-type
rojiphil May 8, 2024
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
108 changes: 87 additions & 21 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import lodashSet from 'lodash/set';
import lodashSortBy from 'lodash/sortBy';
import Onyx from 'react-native-onyx';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type {SelectedTagOption} from '@components/TagPicker';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
Expand Down Expand Up @@ -134,6 +135,8 @@ type Tax = {

type Hierarchy = Record<string, Category & {[key: string]: Hierarchy & Category}>;

type ActionType = ValueOf<typeof CONST.IOU.REQUEST_TYPE> | ValueOf<Pick<typeof CONST.REPORT.TYPE, 'TASK'>> | ValueOf<Pick<typeof CONST.IOU.TYPE, 'SPLIT'>> | undefined;

type GetOptionsConfig = {
reportActions?: ReportActions;
betas?: OnyxEntry<Beta[]>;
Expand Down Expand Up @@ -169,6 +172,7 @@ type GetOptionsConfig = {
policyReportFieldOptions?: string[];
recentlyUsedPolicyReportFieldOptions?: string[];
transactionViolations?: OnyxCollection<TransactionViolation[]>;
actionTypeForParticipants?: ActionType;
};

type GetUserToInviteConfig = {
Expand Down Expand Up @@ -1674,6 +1678,7 @@ function getOptions(
includePolicyReportFieldOptions = false,
policyReportFieldOptions = [],
recentlyUsedPolicyReportFieldOptions = [],
actionTypeForParticipants,
}: GetOptionsConfig,
): Options {
if (includeCategories) {
Expand Down Expand Up @@ -1732,6 +1737,7 @@ function getOptions(
};
}

const recentReportOptionsByAction: ReportUtils.OptionData[] = [];
const parsedPhoneNumber = PhoneNumber.parsePhoneNumber(LoginUtils.appendCountryCode(Str.removeSMSDomain(searchInputValue)));
const searchValue = parsedPhoneNumber.possible ? parsedPhoneNumber.number?.e164 ?? '' : searchInputValue.toLowerCase();
const topmostReportId = Navigation.getTopmostReportId() ?? '';
Expand Down Expand Up @@ -1771,6 +1777,14 @@ function getOptions(
});
orderedReportOptions.reverse();

const isTaskActionTypeForParticipants = actionTypeForParticipants === CONST.REPORT.TYPE.TASK;
const isMoneyRequestActionTypeForParticipants =
rojiphil marked this conversation as resolved.
Show resolved Hide resolved
!isTaskActionTypeForParticipants &&
(actionTypeForParticipants === CONST.IOU.REQUEST_TYPE.MANUAL ||
actionTypeForParticipants === CONST.IOU.REQUEST_TYPE.SCAN ||
actionTypeForParticipants === CONST.IOU.REQUEST_TYPE.DISTANCE ||
actionTypeForParticipants === CONST.IOU.TYPE.SPLIT);
const recentChatReportIDsForActionType: string[] = [];
const allReportOptions = orderedReportOptions.filter((option) => {
const report = option.item;

Expand Down Expand Up @@ -1813,6 +1827,14 @@ function getOptions(
return;
}

// Collect the parent report of the given task for consideration in recent list.
if (isTaskActionTypeForParticipants && isTaskReport && includeRecentReports) {
if (report.parentReportID && ReportUtils.isValidReportIDFromPath(report.parentReportID) && recentChatReportIDsForActionType.indexOf(report.parentReportID) === -1) {
recentChatReportIDsForActionType.push(report.parentReportID);
}
return;
}

if (isTaskReport && !includeTasks) {
return;
}
Expand Down Expand Up @@ -1841,7 +1863,7 @@ function getOptions(
allPersonalDetailsOptions = lodashOrderBy(allPersonalDetailsOptions, [(personalDetail) => personalDetail.text?.toLowerCase()], 'asc');
}

const optionsToExclude: Option[] = [{login: CONST.EMAIL.NOTIFICATIONS}];
let optionsToExclude: Option[] = [{login: CONST.EMAIL.NOTIFICATIONS}];

// If we're including selected options from the search results, we only want to exclude them if the search input is empty
// This is because on certain pages, we show the selected options at the top when the search input is empty
Expand All @@ -1854,22 +1876,33 @@ function getOptions(
optionsToExclude.push({login});
});

let recentReportOptions = [];
const optionsToExcludeByActions: Option[] = [];
optionsToExcludeByActions.push(...optionsToExclude);
let recentReportOptions: ReportUtils.OptionData[] = [];
let personalDetailsOptions: ReportUtils.OptionData[] = [];

if (includeRecentReports) {
// Collect the highest context (i.e. DM/Workspace chat) of the money request report for consideration in recent list.
if (isMoneyRequestActionTypeForParticipants) {
TransactionUtils.getTransactionsByActionType(actionTypeForParticipants).every((recentTransaction) => {
const iouReport = ReportUtils.getReport(recentTransaction?.reportID);
if (
iouReport?.parentReportID &&
ReportUtils.isValidReportIDFromPath(iouReport?.parentReportID) &&
recentChatReportIDsForActionType.indexOf(iouReport?.parentReportID) === -1
) {
recentChatReportIDsForActionType.push(iouReport?.parentReportID);
}
return true;
});
}

for (const reportOption of allReportOptions) {
/**
* By default, generated options does not have the chat preview line enabled.
* If showChatPreviewLine or forcePolicyNamePreview are true, let's generate and overwrite the alternate text.
*/
reportOption.alternateText = getAlternateText(reportOption, {showChatPreviewLine, forcePolicyNamePreview});

// Stop adding options to the recentReports array when we reach the maxRecentReportsToShow value
if (recentReportOptions.length > 0 && recentReportOptions.length === maxRecentReportsToShow) {
break;
}

// Skip notifications@expensify.com
if (reportOption.login === CONST.EMAIL.NOTIFICATIONS) {
continue;
Expand All @@ -1883,15 +1916,6 @@ function getOptions(
continue;
}

// If we're excluding threads, check the report to see if it has a single participant and if the participant is already selected
if (
!includeThreads &&
(!!reportOption.login || reportOption.reportID) &&
optionsToExclude.some((option) => option.login === reportOption.login || option.reportID === reportOption.reportID)
) {
continue;
}

// Finally check to see if this option is a match for the provided search string if we have one
const {searchText, participantsList, isChatRoom} = reportOption;
const participantNames = getParticipantNames(participantsList);
Expand All @@ -1908,14 +1932,54 @@ function getOptions(
}
}

// Check if this report option is to be displayed based on the action type
const isActionTypeOptionForParticipants =
(isMoneyRequestActionTypeForParticipants || isTaskActionTypeForParticipants) &&
recentChatReportIDsForActionType.some((reportID: string) => reportID === String(reportOption.reportID));
if (isActionTypeOptionForParticipants && optionsToExcludeByActions.some((option) => option.login === reportOption.login || option.reportID === reportOption.reportID)) {
continue;
}

reportOption.isSelected = isReportSelected(reportOption, selectedOptions);

recentReportOptions.push(reportOption);
// Stop adding to the recent report option list if we have reached the maxRecentReportsToShow value
if (recentReportOptionsByAction.length > 0 && recentReportOptionsByAction.length === maxRecentReportsToShow) {
break;
}

// Add this login to the exclude list so it won't appear when we process the personal details
if (reportOption.login) {
optionsToExclude.push({login: reportOption.login});
// Push the report option to be displayed based on action type
if (isActionTypeOptionForParticipants) {
recentReportOptionsByAction.push(reportOption);
if (reportOption.login) {
optionsToExcludeByActions.push({login: reportOption.login});
}
continue;
}

// If we're excluding threads, check the report to see if it has a single participant and if the participant is already selected
if (
!includeThreads &&
(!!reportOption.login || reportOption.reportID) &&
optionsToExclude.some((option) => option.login === reportOption.login || option.reportID === reportOption.reportID)
) {
continue;
}

// Keep adding to the recentReports array if there is no limit set or until maxRecentReportsToShow limit is reached
if (!maxRecentReportsToShow || recentReportOptions.length < maxRecentReportsToShow) {
recentReportOptions.push(reportOption);
// Add this login to the exclude list so it won't appear when we process the personal details
if (reportOption.login) {
optionsToExclude.push({login: reportOption.login});
}
}
}

// Let us reset the recent list and the options to exclude if we have found
// recent reports by action type for setting personal details and for search results.
if (recentReportOptionsByAction.length > 0) {
optionsToExclude = [...optionsToExcludeByActions];
recentReportOptions = [...recentReportOptionsByAction];
}
}

Expand Down Expand Up @@ -2082,6 +2146,7 @@ function getFilteredOptions(
recentlyUsedPolicyReportFieldOptions: string[] = [],
includePersonalDetails = true,
maxRecentReportsToShow = 5,
actionTypeForParticipants: ActionType = undefined,
) {
return getOptions(
{reports, personalDetails},
Expand Down Expand Up @@ -2109,6 +2174,7 @@ function getFilteredOptions(
includePolicyReportFieldOptions,
policyReportFieldOptions,
recentlyUsedPolicyReportFieldOptions,
actionTypeForParticipants,
},
);
}
Expand Down
31 changes: 30 additions & 1 deletion src/libs/TransactionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {ValueOf} from 'type-fest';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {RecentWaypoint, Report, TaxRate, TaxRates, TaxRatesWithDefault, Transaction, TransactionViolation} from '@src/types/onyx';
import type {Comment, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction';
import type {Comment, IOUActionType, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type {IOURequestType} from './actions/IOU';
import {isCorporateCard, isExpensifyCard} from './CardUtils';
Expand Down Expand Up @@ -55,6 +55,10 @@ function isScanRequest(transaction: OnyxEntry<Transaction>): boolean {
return Boolean(transaction?.receipt?.source);
}

function isSplitRequest(transaction: Transaction): boolean {
return Boolean(transaction?.comment?.source === CONST.IOU.TYPE.SPLIT);
}

function getRequestType(transaction: OnyxEntry<Transaction>): IOURequestType {
if (isDistanceRequest(transaction)) {
return CONST.IOU.REQUEST_TYPE.DISTANCE;
Expand All @@ -75,6 +79,28 @@ function isManualRequest(transaction: Transaction): boolean {
return getRequestType(transaction) === CONST.IOU.REQUEST_TYPE.MANUAL;
}

/**
* Returns the type of action for the given transaction
*/
function getTransactionActionType(transaction: Transaction): IOUActionType {
if (isSplitRequest(transaction)) {
return CONST.IOU.TYPE.SPLIT;
}
return getRequestType(transaction);
}

/**
* Returns a sorted array of transactions based on the type of action
*/
function getTransactionsByActionType(actionType?: IOUActionType): Array<OnyxEntry<Transaction>> {
return (
Object.values(allTransactions ?? {})
.filter((transaction): transaction is Transaction => transaction != null && actionType === getTransactionActionType(transaction))
// String based sorting of dates having format [YYYY-MM-DD HH:MM:SS.mmm]
.sort((transactionA, transactionB) => (transactionA?.created && transactionB?.created && transactionA?.created < transactionB?.created ? 1 : -1))
);
}

/**
* Optimistically generate a transaction.
*
Expand Down Expand Up @@ -680,6 +706,7 @@ export {
getRequestType,
isManualRequest,
isScanRequest,
isSplitRequest,
getAmount,
getTaxAmount,
getTaxCode,
Expand Down Expand Up @@ -723,6 +750,8 @@ export {
waypointHasValidAddress,
getRecentTransactions,
hasViolation,
getTransactionsByActionType,
getTransactionActionType,
hasNoticeTypeViolation,
isCustomUnitRateIDForP2P,
getRateID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({participants, onF

const offlineMessage = isOffline ? [`${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}`, {isTranslated: true}] : '';

const actionTypeForParticipants = iouType === CONST.IOU.TYPE.SPLIT ? CONST.IOU.TYPE.SPLIT : iouRequestType;
const isIOUSplit = iouType === CONST.IOU.TYPE.SPLIT;
const isCategorizeOrShareAction = [CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.ACTION.SHARE].includes(action);

Expand Down Expand Up @@ -129,6 +130,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({participants, onF
undefined,
!isCategorizeOrShareAction,
isCategorizeOrShareAction ? 0 : undefined,
actionTypeForParticipants,
);

const formatResults = OptionsListUtils.formatSectionsFromSearchTerm(debouncedSearchTerm, participants, chatOptions.recentReports, chatOptions.personalDetails, personalDetails, true);
Expand Down Expand Up @@ -172,6 +174,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({participants, onF
iouRequestType,
personalDetails,
translate,
actionTypeForParticipants,
didScreenTransitionEnd,
isCategorizeOrShareAction,
]);
Expand Down
12 changes: 11 additions & 1 deletion src/pages/tasks/TaskAssigneeSelectorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import type {Report, Task} from '@src/types/onyx';
import type {Report, Task, TaxRatesWithDefault} from '@src/types/onyx';

type TaskAssigneeSelectorModalOnyxProps = {
/** All reports shared with the user */
Expand Down Expand Up @@ -66,6 +66,16 @@ function useOptions() {
{},
[],
true,
false,
false,
{} as TaxRatesWithDefault,
false,
false,
[],
[],
true,
5,
CONST.REPORT.TYPE.TASK,
);

const headerMessage = OptionsListUtils.getHeaderMessage(
Expand Down
2 changes: 2 additions & 0 deletions src/types/onyx/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ type AdditionalTransactionChanges = {
type TransactionChanges = Partial<Transaction> & AdditionalTransactionChanges;

type TransactionCollectionDataSet = CollectionDataSet<typeof ONYXKEYS.COLLECTION.TRANSACTION>;
type IOUActionType = ValueOf<typeof CONST.IOU.REQUEST_TYPE> | ValueOf<Pick<typeof CONST.IOU.TYPE, 'SPLIT'>>;

export default Transaction;
export type {
Expand All @@ -276,6 +277,7 @@ export type {
TaxRate,
ReceiptSource,
TransactionCollectionDataSet,
IOUActionType,
SplitShare,
SplitShares,
};
Loading