Skip to content

Commit 934dc89

Browse files
committed
refactor parseReportActionHtmlToText and getParentNavigationSubtitle to use conciergeReportID from useOnyx
1 parent 0a415ed commit 934dc89

9 files changed

Lines changed: 112 additions & 16 deletions

File tree

src/components/AvatarWithDisplayName.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ function AvatarWithDisplayName({
186186
const {localeCompare, formatPhoneNumber} = useLocalize();
187187
const [parentReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID}`, {canEvict: false});
188188
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST) ?? CONST.EMPTY_OBJECT;
189+
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
189190
const theme = useTheme();
190191
const styles = useThemeStyles();
191192
const StyleUtils = useStyleUtils();
@@ -199,7 +200,7 @@ function AvatarWithDisplayName({
199200
const title = getReportName(report, reportAttributes);
200201
const isParentReportArchived = useReportIsArchived(report?.parentReportID);
201202
const subtitle = getChatRoomSubtitle(report, true, isReportArchived);
202-
const parentNavigationSubtitleData = getParentNavigationSubtitle(report, isParentReportArchived, reportAttributes);
203+
const parentNavigationSubtitleData = getParentNavigationSubtitle(report, conciergeReportID, isParentReportArchived, reportAttributes);
203204
const isMoneyRequestOrReport = isMoneyRequestReport(report) || isMoneyRequest(report) || isTrackExpenseReport(report) || isInvoiceReport(report);
204205
const ownerPersonalDetails = getPersonalDetailsForAccountIDs(report?.ownerAccountID ? [report.ownerAccountID] : [], personalDetails);
205206
const displayNamesWithTooltips = getDisplayNamesWithTooltips(Object.values(ownerPersonalDetails), false, localeCompare, formatPhoneNumber);

src/components/SelectionListWithSections/Search/ExpenseReportListItemRow.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {SearchColumnType} from '@components/Search/types';
99
import type {ExpenseReportListItemType} from '@components/SelectionListWithSections/types';
1010
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
1111
import useLocalize from '@hooks/useLocalize';
12+
import useOnyx from '@hooks/useOnyx';
1213
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1314
import useStyleUtils from '@hooks/useStyleUtils';
1415
import useTheme from '@hooks/useTheme';
@@ -19,6 +20,7 @@ import {getParentNavigationSubtitle, getReportStatusTranslation} from '@libs/Rep
1920
import {isCorrectSearchUserName} from '@libs/SearchUIUtils';
2021
import variables from '@styles/variables';
2122
import CONST from '@src/CONST';
23+
import ONYXKEYS from '@src/ONYXKEYS';
2224
import type {ReportAction} from '@src/types/onyx';
2325
import ActionCell from './ActionCell';
2426
import DateCell from './DateCell';
@@ -67,6 +69,7 @@ function ExpenseReportListItemRow({
6769
const styles = useThemeStyles();
6870
const theme = useTheme();
6971
const {translate} = useLocalize();
72+
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
7073
const {isLargeScreenWidth, shouldUseNarrowLayout} = useResponsiveLayout();
7174
const expensifyIcons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
7275

@@ -232,7 +235,7 @@ function ExpenseReportListItemRow({
232235
const isInMobileSelectionMode = shouldUseNarrowLayout && !!canSelectMultiple;
233236

234237
// Compute accessible group label (user name, subtitle, report title, status, amount)
235-
const parentNavigationSubtitleData = getParentNavigationSubtitle(item);
238+
const parentNavigationSubtitleData = getParentNavigationSubtitle(item, conciergeReportID);
236239
const subtitleLabel = translate('threads.parentNavigationSummary', parentNavigationSubtitleData);
237240
const statusLabel = getReportStatusTranslation({stateNum: item.stateNum, statusNum: item.statusNum, translate});
238241
const amountLabel = convertToDisplayString(totalDisplaySpend, currency);

src/libs/ReportUtils.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5655,7 +5655,7 @@ function getAdminRoomInvitedParticipants(translate: LocalizedTranslate, parentRe
56555655
/**
56565656
* Parse html of reportAction into text
56575657
*/
5658-
function parseReportActionHtmlToText(reportAction: OnyxEntry<ReportAction>, reportID: string | undefined, childReportID?: string): string {
5658+
function parseReportActionHtmlToText(reportAction: OnyxEntry<ReportAction>, reportID: string | undefined, conciergeReportID: string | undefined, childReportID?: string): string {
56595659
if (!reportAction) {
56605660
return '';
56615661
}
@@ -5679,7 +5679,7 @@ function parseReportActionHtmlToText(reportAction: OnyxEntry<ReportAction>, repo
56795679
if (match[1] !== childReportID) {
56805680
// This will be fixed as follow up https://github.com/Expensify/App/pull/75357
56815681
// eslint-disable-next-line @typescript-eslint/no-use-before-define, @typescript-eslint/no-deprecated
5682-
reportIDToName[match[1]] = getReportName({report: getReportOrDraftReport(match[1])}) ?? '';
5682+
reportIDToName[match[1]] = getReportName({report: getReportOrDraftReport(match[1]), conciergeReportID}) ?? '';
56835683
}
56845684
}
56855685

@@ -5711,6 +5711,7 @@ function getReportActionMessage({
57115711
childReportID,
57125712
reports,
57135713
personalDetails,
5714+
conciergeReportID,
57145715
}: {
57155716
reportAction: OnyxEntry<ReportAction>;
57165717
translate: LocalizedTranslate;
@@ -5719,6 +5720,7 @@ function getReportActionMessage({
57195720
childReportID?: string;
57205721
reports?: Report[];
57215722
personalDetails?: Partial<PersonalDetailsList>;
5723+
conciergeReportID: string | undefined;
57225724
}) {
57235725
if (isEmptyObject(reportAction)) {
57245726
return '';
@@ -5764,7 +5766,7 @@ function getReportActionMessage({
57645766
return getReimbursementDeQueuedOrCanceledActionMessage(translate, reportAction, getReportOrDraftReport(reportID, reports));
57655767
}
57665768

5767-
return parseReportActionHtmlToText(reportAction, reportID, childReportID);
5769+
return parseReportActionHtmlToText(reportAction, reportID, conciergeReportID, childReportID);
57685770
}
57695771

57705772
/**
@@ -5858,6 +5860,7 @@ function getReportName(reportNameInformation: GetReportNameParams): string {
58585860
childReportID: report?.reportID,
58595861
reports,
58605862
personalDetails,
5863+
conciergeReportID,
58615864
}).replaceAll(/(\n+|\r\n|\n|\r)/gm, ' ');
58625865
if (isAttachment && reportActionMessage) {
58635866
// eslint-disable-next-line @typescript-eslint/no-deprecated
@@ -6126,7 +6129,12 @@ function getPendingChatMembers(accountIDs: number[], previousPendingChatMembers:
61266129
/**
61276130
* Gets the parent navigation subtitle for the report
61286131
*/
6129-
function getParentNavigationSubtitle(report: OnyxEntry<Report>, isParentReportArchived = false, reportAttributes?: ReportAttributesDerivedValue['reports']): ParentNavigationSummaryParams {
6132+
function getParentNavigationSubtitle(
6133+
report: OnyxEntry<Report>,
6134+
conciergeReportID: string | undefined,
6135+
isParentReportArchived = false,
6136+
reportAttributes?: ReportAttributesDerivedValue['reports'],
6137+
): ParentNavigationSummaryParams {
61306138
const parentReport = getParentReport(report);
61316139

61326140
if (isEmptyObject(parentReport)) {
@@ -6165,7 +6173,7 @@ function getParentNavigationSubtitle(report: OnyxEntry<Report>, isParentReportAr
61656173
return {
61666174
// This will be fixed as follow up https://github.com/Expensify/App/pull/75357
61676175
// eslint-disable-next-line @typescript-eslint/no-deprecated
6168-
reportName: getReportName({report: parentReport, reportAttributes}),
6176+
reportName: getReportName({report: parentReport, reportAttributes, conciergeReportID}),
61696177
workspaceName: getPolicyName({report: parentReport, returnEmptyIfNotFound: true}),
61706178
};
61716179
}

src/libs/actions/Task.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,7 @@ function getShareDestination(
10201020
reports: OnyxCollection<OnyxTypes.Report>,
10211021
personalDetails: OnyxEntry<OnyxTypes.PersonalDetailsList>,
10221022
localeCompare: LocaleContextProps['localeCompare'],
1023+
conciergeReportID: string | undefined,
10231024
): ShareDestination {
10241025
const report = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
10251026

@@ -1049,7 +1050,7 @@ function getShareDestination(
10491050
icons: ReportUtils.getIcons(report, LocalePhoneNumber.formatPhoneNumber, personalDetails, Expensicons.FallbackAvatar),
10501051
// Will be fixed in https://github.com/Expensify/App/issues/76852
10511052
// eslint-disable-next-line @typescript-eslint/no-deprecated
1052-
displayName: ReportUtils.getReportName({report}),
1053+
displayName: ReportUtils.getReportName({report, conciergeReportID}),
10531054
subtitle,
10541055
displayNamesWithTooltips,
10551056
shouldUseFullTitleToDisplay: ReportUtils.shouldUseFullTitleToDisplay(report),

src/pages/ReportDetailsPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
223223
const isReportArchived = useReportIsArchived(report?.reportID);
224224
const isArchivedRoom = useMemo(() => isArchivedNonExpenseReport(report, isReportArchived), [report, isReportArchived]);
225225
const shouldDisableRename = useMemo(() => shouldDisableRenameUtil(report, isReportArchived), [report, isReportArchived]);
226-
const parentNavigationSubtitleData = getParentNavigationSubtitle(report, isParentReportArchived);
226+
const parentNavigationSubtitleData = getParentNavigationSubtitle(report, conciergeReportID, isParentReportArchived);
227227
const base62ReportID = getBase62ReportID(Number(report.reportID));
228228
const ancestors = useAncestors(report);
229229
// eslint-disable-next-line react-hooks/exhaustive-deps -- policy is a dependency because `getChatRoomSubtitle` calls `getPolicyName` which in turn retrieves the value from the `policy` value stored in Onyx

src/pages/ShareCodePage.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
1515
import useEnvironment from '@hooks/useEnvironment';
1616
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
1717
import useLocalize from '@hooks/useLocalize';
18+
import useOnyx from '@hooks/useOnyx';
1819
import useReportAttributes from '@hooks/useReportAttributes';
1920
import useReportIsArchived from '@hooks/useReportIsArchived';
2021
import useStyleUtils from '@hooks/useStyleUtils';
@@ -38,6 +39,7 @@ import shouldAllowDownloadQRCode from '@libs/shouldAllowDownloadQRCode';
3839
import addTrailingForwardSlash from '@libs/UrlUtils';
3940
import {getAvatarURL} from '@libs/UserAvatarUtils';
4041
import CONST from '@src/CONST';
42+
import ONYXKEYS from '@src/ONYXKEYS';
4143
import ROUTES from '@src/ROUTES';
4244
import type {Policy, Report} from '@src/types/onyx';
4345

@@ -77,6 +79,7 @@ function ShareCodePage({report, policy, backTo}: ShareCodePageProps) {
7779
const qrCodeRef = useRef<QRShareWithDownloadHandle>(null);
7880

7981
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
82+
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
8083
const reportAttributes = useReportAttributes();
8184
const isParentReportArchived = useReportIsArchived(report?.parentReportID);
8285
const isReportArchived = useReportIsArchived(report?.reportID);
@@ -94,11 +97,11 @@ function ShareCodePage({report, policy, backTo}: ShareCodePageProps) {
9497
.join(' & ');
9598
}
9699

97-
return getParentNavigationSubtitle(report, isParentReportArchived).workspaceName ?? getChatRoomSubtitle(report, false, isReportArchived);
100+
return getParentNavigationSubtitle(report, conciergeReportID, isParentReportArchived).workspaceName ?? getChatRoomSubtitle(report, false, isReportArchived);
98101
}
99102

100103
return currentUserPersonalDetails.login;
101-
}, [report, currentUserPersonalDetails.login, isReport, isReportArchived, isParentReportArchived, formatPhoneNumber]);
104+
}, [report, currentUserPersonalDetails.login, isReport, isReportArchived, isParentReportArchived, formatPhoneNumber, conciergeReportID]);
102105

103106
const reportForTitle = useMemo(() => getReportForHeader(report), [report]);
104107

src/pages/inbox/HeaderView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
124124
const isReportArchived = isArchivedReport(reportNameValuePairs);
125125
const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {selector: reportsSelector});
126126
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
127+
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
127128

128129
const {translate, localeCompare, formatPhoneNumber} = useLocalize();
129130
const theme = useTheme();
@@ -160,7 +161,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
160161
: undefined;
161162
const statusColorForInvoiceReport = isParentInvoiceAndIsChatThread ? getReportStatusColorStyle(theme, reportHeaderData?.stateNum, reportHeaderData?.statusNum) : {};
162163
const isParentReportHeaderDataArchived = useReportIsArchived(reportHeaderData?.parentReportID);
163-
const parentNavigationSubtitleData = getParentNavigationSubtitle(parentNavigationReport, isParentReportHeaderDataArchived);
164+
const parentNavigationSubtitleData = getParentNavigationSubtitle(parentNavigationReport, conciergeReportID, isParentReportHeaderDataArchived);
164165
const reportDescription = Parser.htmlToText(getReportDescription(report));
165166
const policyName = getPolicyName({report, returnEmptyIfNotFound: true});
166167
const policyDescription = getPolicyDescriptionText(policy);
@@ -243,7 +244,6 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
243244
const isReportInRHP = route.name === SCREENS.RIGHT_MODAL.SEARCH_REPORT;
244245
const shouldDisplaySearchRouter = !isInSidePanel && (!isReportInRHP || isSmallScreenWidth);
245246
const [onboardingPurposeSelected] = useOnyx(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED);
246-
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
247247
const isChatUsedForOnboarding = isChatUsedForOnboardingReportUtils(report, onboarding, conciergeReportID, onboardingPurposeSelected);
248248
const shouldShowRegisterForWebinar =
249249
introSelected?.companySize === CONST.ONBOARDING_COMPANY_SIZE.MICRO && (isChatUsedForOnboarding || (isAdminRoom(report) && !isChatThread)) && !isInSidePanel;

src/pages/tasks/NewTaskPage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ function NewTaskPage({route}: NewTaskPageProps) {
3535
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
3636
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
3737
const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE);
38+
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
3839
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
3940
const styles = useThemeStyles();
4041
const {translate, formatPhoneNumber, localeCompare} = useLocalize();
@@ -45,7 +46,7 @@ function NewTaskPage({route}: NewTaskPageProps) {
4546
localeCompare,
4647
formatPhoneNumber,
4748
);
48-
const shareDestination = task?.shareDestination ? getShareDestination(task.shareDestination, reports, personalDetails, localeCompare) : undefined;
49+
const shareDestination = task?.shareDestination ? getShareDestination(task.shareDestination, reports, personalDetails, localeCompare, conciergeReportID) : undefined;
4950
const parentReport = task?.shareDestination ? reports?.[`${ONYXKEYS.COLLECTION.REPORT}${task.shareDestination}`] : undefined;
5051
const ancestors = useAncestors(parentReport);
5152
const taskKey = `${task?.assignee}|${task?.assigneeAccountID}|${task?.description}|${task?.parentReportID}|${task?.shareDestination}|${task?.title}`;

tests/unit/ReportUtilsTest.ts

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ import {
115115
isRootGroupChat,
116116
isSelfDMOrSelfDMThread,
117117
isWorkspaceMemberLeavingWorkspaceRoom,
118+
parseReportActionHtmlToText,
118119
parseReportRouteParams,
119120
prepareOnboardingOnyxData,
120121
pushTransactionViolationsOnyxData,
@@ -2820,16 +2821,94 @@ describe('ReportUtils', () => {
28202821
});
28212822

28222823
it('should return the correct parent navigation subtitle for the archived invoice report', () => {
2823-
const actual = getParentNavigationSubtitle(baseArchivedPolicyExpenseChat, true);
2824+
const actual = getParentNavigationSubtitle(baseArchivedPolicyExpenseChat, undefined, true);
28242825
const normalizedActual = {...actual, reportName: actual.reportName?.replaceAll('\u00A0', ' ')};
28252826
expect(normalizedActual).toEqual({reportName: 'A workspace & Ragnar Lothbrok (archived)'});
28262827
});
28272828

28282829
it('should return the correct parent navigation subtitle for the non archived invoice report', () => {
2829-
const actual = getParentNavigationSubtitle(baseArchivedPolicyExpenseChat, false);
2830+
const actual = getParentNavigationSubtitle(baseArchivedPolicyExpenseChat, undefined, false);
28302831
const normalizedActual = {...actual, reportName: actual.reportName?.replaceAll('\u00A0', ' ')};
28312832
expect(normalizedActual).toEqual({reportName: 'A workspace & Ragnar Lothbrok'});
28322833
});
2834+
2835+
it('should return empty object when report has no parent and is not expense or IOU', () => {
2836+
const chatReport: Report = {
2837+
reportID: '100',
2838+
lastReadTime: '2024-02-01 04:56:47.233',
2839+
reportName: 'Chat Report',
2840+
type: CONST.REPORT.TYPE.CHAT,
2841+
};
2842+
const actual = getParentNavigationSubtitle(chatReport, undefined);
2843+
expect(actual).toEqual({});
2844+
});
2845+
2846+
it('should pass conciergeReportID through to getReportName for parent report name resolution', () => {
2847+
const conciergeReportID = '999';
2848+
const conciergeParentReport: Report = {
2849+
reportID: conciergeReportID,
2850+
lastReadTime: '2024-02-01 04:56:47.233',
2851+
reportName: 'Concierge',
2852+
type: CONST.REPORT.TYPE.CHAT,
2853+
};
2854+
const childReport: Report = {
2855+
reportID: '1000',
2856+
lastReadTime: '2024-02-01 04:56:47.233',
2857+
parentReportID: conciergeReportID,
2858+
parentReportActionID: '1',
2859+
reportName: 'Child Thread',
2860+
type: CONST.REPORT.TYPE.CHAT,
2861+
};
2862+
2863+
const reportCollectionDataSet = toCollectionDataSet(ONYXKEYS.COLLECTION.REPORT, [conciergeParentReport, childReport], (report) => report.reportID);
2864+
return Onyx.multiSet({
2865+
...reportCollectionDataSet,
2866+
})
2867+
.then(waitForBatchedUpdates)
2868+
.then(() => {
2869+
const actual = getParentNavigationSubtitle(childReport, conciergeReportID);
2870+
expect(actual.reportName).toBe('Concierge');
2871+
});
2872+
});
2873+
2874+
it('should return reportName and workspaceName when parent report exists and conciergeReportID is undefined', () => {
2875+
const actual = getParentNavigationSubtitle(baseArchivedPolicyExpenseChat, undefined, false);
2876+
expect(actual).toHaveProperty('reportName');
2877+
});
2878+
});
2879+
2880+
describe('parseReportActionHtmlToText', () => {
2881+
it('should return empty string for undefined reportAction', () => {
2882+
const result = parseReportActionHtmlToText(undefined, '123', undefined);
2883+
expect(result).toBe('');
2884+
});
2885+
2886+
it('should return text from reportAction message when no html', () => {
2887+
const reportAction = {
2888+
...createRandomReportAction(1),
2889+
message: [{type: 'COMMENT', text: 'Hello world'}],
2890+
} as unknown as ReportAction;
2891+
const result = parseReportActionHtmlToText(reportAction, '123', undefined);
2892+
expect(result).toBe('Hello world');
2893+
});
2894+
2895+
it('should parse html to text with conciergeReportID', () => {
2896+
const reportAction = {
2897+
...createRandomReportAction(1),
2898+
message: [{type: 'COMMENT', html: '<p>Hello world</p>', text: 'Hello world'}],
2899+
} as unknown as ReportAction;
2900+
const result = parseReportActionHtmlToText(reportAction, '123', '999');
2901+
expect(result).toBe('Hello world');
2902+
});
2903+
2904+
it('should handle conciergeReportID being undefined', () => {
2905+
const reportAction = {
2906+
...createRandomReportAction(1),
2907+
message: [{type: 'COMMENT', html: '<p>Test message</p>', text: 'Test message'}],
2908+
} as unknown as ReportAction;
2909+
const result = parseReportActionHtmlToText(reportAction, '456', undefined);
2910+
expect(result).toBe('Test message');
2911+
});
28332912
});
28342913

28352914
describe('requiresAttentionFromCurrentUser', () => {

0 commit comments

Comments
 (0)