Skip to content

Commit

Permalink
Merge pull request #49177 from koko57/fix/49149-fix-lhn-and-copying-m…
Browse files Browse the repository at this point in the history
…essage-content

fix lhn and copying message content
  • Loading branch information
mountiny authored Sep 16, 2024
2 parents 2d5e876 + eab7d0e commit d860f2d
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 30 deletions.
31 changes: 5 additions & 26 deletions src/components/ReportActionItem/IssueCardMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import type {OnyxEntry} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import Button from '@components/Button';
import RenderHTML from '@components/RenderHTML';
import useEnvironment from '@hooks/useEnvironment';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {ReportAction} from '@src/types/onyx';
import type OriginalMessage from '@src/types/onyx/OriginalMessage';
import type {IssueNewCardOriginalMessage} from '@src/types/onyx/OriginalMessage';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

type IssueCardMessageProps = {
Expand All @@ -20,22 +20,14 @@ type IssueCardMessageProps = {
policyID: string | undefined;
};

type IssueNewCardOriginalMessage = OriginalMessage<
typeof CONST.REPORT.ACTIONS.TYPE.CARD_MISSING_ADDRESS | typeof CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED | typeof CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED_VIRTUAL
>;

function IssueCardMessage({action, policyID}: IssueCardMessageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const {environmentURL} = useEnvironment();
const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS);
const [session] = useOnyx(ONYXKEYS.SESSION);

const assigneeAccountID = (action?.originalMessage as IssueNewCardOriginalMessage)?.assigneeAccountID;

const assignee = `<mention-user accountID=${assigneeAccountID}></mention-user>`;
const link = `<a href='${environmentURL}/${ROUTES.SETTINGS_WALLET}'>${translate('cardPage.expensifyCard')}</a>`;

const missingDetails =
!privatePersonalDetails?.legalFirstName ||
!privatePersonalDetails?.legalLastName ||
Expand All @@ -46,25 +38,12 @@ function IssueCardMessage({action, policyID}: IssueCardMessageProps) {

const isAssigneeCurrentUser = !isEmptyObject(session) && session.accountID === assigneeAccountID;

const shouldShowDetailsButton = action?.actionName === CONST.REPORT.ACTIONS.TYPE.CARD_MISSING_ADDRESS && missingDetails && isAssigneeCurrentUser;

const getTranslation = () => {
switch (action?.actionName) {
case CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED:
return translate('workspace.expensifyCard.issuedCard', assignee);
case CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED_VIRTUAL:
return translate('workspace.expensifyCard.issuedCardVirtual', {assignee, link});
case CONST.REPORT.ACTIONS.TYPE.CARD_MISSING_ADDRESS:
return translate(`workspace.expensifyCard.${!isAssigneeCurrentUser || shouldShowDetailsButton ? 'issuedCardNoShippingDetails' : 'addedShippingDetails'}`, assignee);
default:
return '';
}
};
const shouldShowAddMissingDetailsButton = action?.actionName === CONST.REPORT.ACTIONS.TYPE.CARD_MISSING_ADDRESS && missingDetails && isAssigneeCurrentUser;

return (
<>
<RenderHTML html={`<muted-text>${getTranslation()}</muted-text>`} />
{shouldShowDetailsButton && (
<RenderHTML html={`<muted-text>${ReportActionsUtils.getCardIssuedMessage(action, true)}</muted-text>`} />
{shouldShowAddMissingDetailsButton && (
<Button
onPress={() => {
if (!policyID) {
Expand Down
58 changes: 55 additions & 3 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import type {ValueOf} from 'type-fest';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
import type {OnyxInputOrEntry} from '@src/types/onyx';
import type {JoinWorkspaceResolution, OriginalMessageChangeLog, OriginalMessageExportIntegration} from '@src/types/onyx/OriginalMessage';
import ROUTES from '@src/ROUTES';
import type {OnyxInputOrEntry, PrivatePersonalDetails} from '@src/types/onyx';
import type {IssueNewCardOriginalMessage, JoinWorkspaceResolution, OriginalMessageChangeLog, OriginalMessageExportIntegration} from '@src/types/onyx/OriginalMessage';
import type Report from '@src/types/onyx/Report';
import type ReportAction from '@src/types/onyx/ReportAction';
import type {Message, OldDotReportAction, OriginalMessage, ReportActions} from '@src/types/onyx/ReportAction';
Expand Down Expand Up @@ -82,6 +83,14 @@ Onyx.connect({
},
});

let privatePersonalDetails: PrivatePersonalDetails | undefined;
Onyx.connect({
key: ONYXKEYS.PRIVATE_PERSONAL_DETAILS,
callback: (personalDetails) => {
privatePersonalDetails = personalDetails;
},
});

let environmentURL: string;
Environment.getEnvironmentURL().then((url: string) => (environmentURL = url));

Expand Down Expand Up @@ -152,6 +161,7 @@ function isReportPreviewAction(reportAction: OnyxInputOrEntry<ReportAction>): re
function isSubmittedAction(reportAction: OnyxInputOrEntry<ReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.SUBMITTED> {
return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.SUBMITTED);
}

function isApprovedAction(reportAction: OnyxInputOrEntry<ReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.APPROVED> {
return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.APPROVED);
}
Expand Down Expand Up @@ -237,7 +247,10 @@ function getWhisperedTo(reportAction: OnyxInputOrEntry<ReportAction>): number[]
}

if (typeof originalMessage !== 'object') {
Log.info('Original message is not an object for reportAction: ', true, {reportActionID: reportAction?.reportActionID, actionName: reportAction?.actionName});
Log.info('Original message is not an object for reportAction: ', true, {
reportActionID: reportAction?.reportActionID,
actionName: reportAction?.actionName,
});
}

return [];
Expand Down Expand Up @@ -965,6 +978,7 @@ const iouRequestTypes = new Set<ValueOf<typeof CONST.IOU.REPORT_ACTION_TYPE>>([
CONST.IOU.REPORT_ACTION_TYPE.PAY,
CONST.IOU.REPORT_ACTION_TYPE.TRACK,
]);

/**
* Gets the reportID for the transaction thread associated with a report by iterating over the reportActions and identifying the IOU report actions.
* Returns a reportID if there is exactly one transaction thread for the report, and null otherwise.
Expand Down Expand Up @@ -1664,6 +1678,42 @@ function getRemovedFromApprovalChainMessage(reportAction: OnyxEntry<ReportAction
return Localize.translateLocal('workspaceActions.removedFromApprovalWorkflow', {submittersNames});
}

function isCardIssuedAction(reportAction: OnyxEntry<ReportAction>) {
return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED, CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED_VIRTUAL, CONST.REPORT.ACTIONS.TYPE.CARD_MISSING_ADDRESS);
}

function getCardIssuedMessage(reportAction: OnyxEntry<ReportAction>, shouldRenderHTML = false) {
const assigneeAccountID = (reportAction?.originalMessage as IssueNewCardOriginalMessage)?.assigneeAccountID;
const assigneeDetails = PersonalDetailsUtils.getPersonalDetailsByIDs([assigneeAccountID], currentUserAccountID ?? -1)[0];

const assignee = shouldRenderHTML ? `<mention-user accountID="${assigneeAccountID}"/>` : assigneeDetails?.firstName ?? assigneeDetails.login ?? '';
const link = shouldRenderHTML
? `<a href='${environmentURL}/${ROUTES.SETTINGS_WALLET}'>${Localize.translateLocal('cardPage.expensifyCard')}</a>`
: Localize.translateLocal('cardPage.expensifyCard');

const missingDetails =
!privatePersonalDetails?.legalFirstName ||
!privatePersonalDetails?.legalLastName ||
!privatePersonalDetails?.dob ||
!privatePersonalDetails?.phoneNumber ||
isEmptyObject(privatePersonalDetails?.addresses) ||
privatePersonalDetails.addresses.length === 0;

const isAssigneeCurrentUser = currentUserAccountID === assigneeAccountID;

const shouldShowAddMissingDetailsButton = reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CARD_MISSING_ADDRESS && missingDetails && isAssigneeCurrentUser;
switch (reportAction?.actionName) {
case CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED:
return Localize.translateLocal('workspace.expensifyCard.issuedCard', assignee);
case CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED_VIRTUAL:
return Localize.translateLocal('workspace.expensifyCard.issuedCardVirtual', {assignee, link});
case CONST.REPORT.ACTIONS.TYPE.CARD_MISSING_ADDRESS:
return Localize.translateLocal(`workspace.expensifyCard.${shouldShowAddMissingDetailsButton ? 'issuedCardNoShippingDetails' : 'addedShippingDetails'}`, assignee);
default:
return '';
}
}

export {
doesReportHaveVisibleActions,
extractLinksFromMessageHtml,
Expand Down Expand Up @@ -1766,6 +1816,8 @@ export {
getPolicyChangeLogChangeRoleMessage,
getPolicyChangeLogDeleteMemberMessage,
getRenamedAction,
isCardIssuedAction,
getCardIssuedMessage,
};

export type {LastVisibleMessage};
3 changes: 3 additions & 0 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3771,6 +3771,9 @@ function getReportName(
return report?.reportName ?? '';
}

if (ReportActionsUtils.isCardIssuedAction(parentReportAction)) {
return ReportActionsUtils.getCardIssuedMessage(parentReportAction);
}
return reportActionMessage;
}

Expand Down
2 changes: 2 additions & 0 deletions src/libs/SidebarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,8 @@ function getOptionData({
result.alternateText = ReportUtils.getWorkspaceNameUpdatedMessage(lastAction);
} else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.LEAVE_POLICY) {
result.alternateText = Localize.translateLocal('workspace.invite.leftWorkspace');
} else if (ReportActionsUtils.isCardIssuedAction(lastAction)) {
result.alternateText = ReportActionsUtils.getCardIssuedMessage(lastAction);
} else if (lastAction?.actionName !== CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW && lastActorDisplayName && lastMessageTextFromReport) {
result.alternateText = ReportUtils.formatReportLastMessageText(Parser.htmlToText(`${lastActorDisplayName}: ${lastMessageText}`));
} else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.ADD_TAG) {
Expand Down
2 changes: 2 additions & 0 deletions src/pages/home/report/ContextMenu/ContextMenuActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ const ContextMenuActions: ContextMenuAction[] = [
} else if (ReportActionsUtils.isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.INTEGRATION_SYNC_FAILED)) {
const {label, errorMessage} = ReportActionsUtils.getOriginalMessage(reportAction) ?? {label: '', errorMessage: ''};
setClipboardMessage(Localize.translateLocal('report.actions.type.integrationSyncFailed', label, errorMessage));
} else if (ReportActionsUtils.isCardIssuedAction(reportAction)) {
setClipboardMessage(ReportActionsUtils.getCardIssuedMessage(reportAction, true));
} else if (content) {
setClipboardMessage(
content.replace(/(<mention-user>)(.*?)(<\/mention-user>)/gi, (match, openTag: string, innerContent: string, closeTag: string): string => {
Expand Down
10 changes: 9 additions & 1 deletion src/types/onyx/OriginalMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,13 +523,20 @@ type OriginalMessageIntegrationSyncFailed = {
};

/**
* Original message for CARD_ISSUED, CARD_MISSING_ADDRESS, and CARD_ISSUED_VIRTUAL actions
* Model of CARD_ISSUED, CARD_MISSING_ADDRESS, and CARD_ISSUED_VIRTUAL actions
*/
type OriginalMessageExpensifyCard = {
/** The id of the user the card was assigned to */
assigneeAccountID: number;
};

/**
* Original message for CARD_ISSUED, CARD_MISSING_ADDRESS, and CARD_ISSUED_VIRTUAL actions
*/
type IssueNewCardOriginalMessage = OriginalMessage<
typeof CONST.REPORT.ACTIONS.TYPE.CARD_MISSING_ADDRESS | typeof CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED | typeof CONST.REPORT.ACTIONS.TYPE.CARD_ISSUED_VIRTUAL
>;

/** The map type of original message */
/* eslint-disable jsdoc/require-jsdoc */
type OriginalMessageMap = {
Expand Down Expand Up @@ -620,4 +627,5 @@ export type {
JoinWorkspaceResolution,
OriginalMessageModifiedExpense,
OriginalMessageExportIntegration,
IssueNewCardOriginalMessage,
};

0 comments on commit d860f2d

Please sign in to comment.