From 7ad0af4ac8f76c4770fcd4b55af352e97fcff892 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:27:00 +0200 Subject: [PATCH 01/14] feat: add offline pattern B for manual report exports --- src/languages/en.ts | 8 +- src/languages/types.ts | 2 +- .../API/parameters/MarkAsExportedParams.ts | 1 + src/libs/API/parameters/ReportExportParams.ts | 1 + src/libs/ReportActionsUtils.ts | 2 +- src/libs/ReportUtils.ts | 72 ++++++++++++++++ src/libs/actions/Report.ts | 83 ++++++++++++++++++- 7 files changed, 162 insertions(+), 7 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index aef5372f76b1..053956043215 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3059,7 +3059,13 @@ export default { changeType: ({oldType, newType}: ChangeTypeParams) => `changed type from ${oldType} to ${newType}`, delegateSubmit: ({delegateUser, originalManager}: DelegateSubmitParams) => `sent this report to ${delegateUser} since ${originalManager} is on vacation`, exportedToCSV: `exported this report to CSV`, - exportedToIntegration: ({label}: ExportedToIntegrationParams) => `exported this report to ${label}`, + exportedToIntegration: ({label, markedManually}: ExportedToIntegrationParams) => { + if (markedManually) { + // TODO: Verify translation - it was taken from the backend response, and it is needed here for the optimistic response + return `You marked this report as manually exported to`; + } + return `exported this report to ${label}`; + }, forwarded: ({amount, currency}: ForwardedParams) => `approved ${currency}${amount}`, integrationsMessage: ({errorMessage, label}: IntegrationsMessageParams) => `failed to export this report to ${label}. ${errorMessage}`, managerAttachReceipt: `added a receipt`, diff --git a/src/languages/types.ts b/src/languages/types.ts index eb90f2d9e0b2..f6ff01894368 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -306,7 +306,7 @@ type ChangeTypeParams = {oldType: string; newType: string}; type DelegateSubmitParams = {delegateUser: string; originalManager: string}; -type ExportedToIntegrationParams = {label: string}; +type ExportedToIntegrationParams = {label: string; markedManually: boolean}; type ForwardedParams = {amount: string; currency: string}; diff --git a/src/libs/API/parameters/MarkAsExportedParams.ts b/src/libs/API/parameters/MarkAsExportedParams.ts index 03348e856b15..09f5c4cf2e61 100644 --- a/src/libs/API/parameters/MarkAsExportedParams.ts +++ b/src/libs/API/parameters/MarkAsExportedParams.ts @@ -1,6 +1,7 @@ type MarkAsExportedParams = { reportIDList: string; markedManually: true; + optimisticReportActionID: string; }; export default MarkAsExportedParams; diff --git a/src/libs/API/parameters/ReportExportParams.ts b/src/libs/API/parameters/ReportExportParams.ts index dc87ce2170c4..ff626059a036 100644 --- a/src/libs/API/parameters/ReportExportParams.ts +++ b/src/libs/API/parameters/ReportExportParams.ts @@ -5,6 +5,7 @@ type ReportExportParams = { reportIDList: string; connectionName: ValueOf; type: 'MANUAL'; + optimisticReportActionID: string; }; export default ReportExportParams; diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 63a56633edc6..a1dbb446ecd9 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -1258,7 +1258,7 @@ function getMessageOfOldDotReportAction(oldDotAction: PartialReportAction | OldD case CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_CSV: return Localize.translateLocal('report.actions.type.exportedToCSV'); case CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION: - return Localize.translateLocal('report.actions.type.exportedToIntegration', {label: originalMessage.label}); + return Localize.translateLocal('report.actions.type.exportedToIntegration', {label: originalMessage.label, markedManually: originalMessage.markedManually}); case CONST.REPORT.ACTIONS.TYPE.INTEGRATIONS_MESSAGE: { const {errorMessage, label} = originalMessage; return Localize.translateLocal('report.actions.type.integrationsMessage', {errorMessage, label}); diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 3fd4749bbd88..69fb101a841e 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -276,6 +276,23 @@ type OptimisticChatReport = Pick< isOptimisticReport: true; }; +type OptimisticExportAction = Pick< + ReportAction, + | 'reportActionID' + | 'actionName' + | 'actorAccountID' + | 'avatar' + | 'created' + | 'lastModified' + | 'message' + | 'originalMessage' + | 'person' + | 'shouldShow' + | 'pendingAction' + | 'errors' + | 'automatic' +>; + type OptimisticTaskReportAction = Pick< ReportAction, | 'reportActionID' @@ -5109,6 +5126,60 @@ function buildOptimisticTaskReport( }; } +// function buildOptimisticCreatedReportAction(emailCreatingAction: string, created = DateUtils.getDBTime()): OptimisticCreatedReportAction { +// return { +// reportActionID: NumberUtils.rand64(), +// actionName: CONST.REPORT.ACTIONS.TYPE.CREATED, +// pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, +// actorAccountID: currentUserAccountID, +// message: [ +// { +// type: CONST.REPORT.MESSAGE.TYPE.TEXT, +// style: 'strong', +// text: emailCreatingAction, +// }, +// { +// type: CONST.REPORT.MESSAGE.TYPE.TEXT, +// style: 'normal', +// text: ' created this report', +// }, +// ], +// person: [ +// { +// type: CONST.REPORT.MESSAGE.TYPE.TEXT, +// style: 'strong', +// text: getCurrentUserDisplayNameOrEmail(), +// }, +// ], +// automatic: false, +// avatar: getCurrentUserAvatar(), +// created, +// shouldShow: true, +// }; +// } + +// Manual export +function buildOptimisticExportIntegrationAction(label = '', markedManually = false): OptimisticExportAction { + return { + reportActionID: NumberUtils.rand64(), + actionName: CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + actorAccountID: currentUserAccountID, + message: [], + person: [], + automatic: false, + avatar: getCurrentUserAvatar(), + created: DateUtils.getDBTime(), + shouldShow: true, + originalMessage: { + automaticAction: false, + label, + lastModified: DateUtils.getDBTime(), + markedManually, + }, + }; +} + /** * A helper method to create transaction thread * @@ -7341,6 +7412,7 @@ export { changeMoneyRequestHoldStatus, createDraftWorkspaceAndNavigateToConfirmationScreen, isChatUsedForOnboarding, + buildOptimisticExportIntegrationAction, getChatUsedForOnboarding, findPolicyExpenseChatByPolicyID, getIntegrationIcon, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index f63639673083..f318bd2c1dce 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3735,22 +3735,97 @@ function setGroupDraft(newGroupDraft: Partial) { } function exportToIntegration(reportID: string, connectionName: ConnectionName) { - API.write(WRITE_COMMANDS.REPORT_EXPORT, { + const action = ReportUtils.buildOptimisticExportIntegrationAction(connectionName); + const optimisticReportActionID = action.reportActionID; + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: action, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: null, + }, + }, + ]; + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: { + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + ]; + + const params = { // TODO: Update it when backend is ready // eslint-disable-next-line @typescript-eslint/naming-convention 'reportIDList[]': reportID, connectionName, type: 'MANUAL', - }); + optimisticReportActionID, + }; + + API.write(WRITE_COMMANDS.REPORT_EXPORT, params, {optimisticData, successData, failureData}); } function markAsManuallyExported(reportID: string) { - API.write(WRITE_COMMANDS.MARK_AS_EXPORTED, { + const action = ReportUtils.buildOptimisticExportIntegrationAction(undefined, true); + const optimisticReportActionID = action.reportActionID; + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: action, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: null, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: { + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + ]; + + const params = { // TODO: Update it when backend is ready // eslint-disable-next-line @typescript-eslint/naming-convention 'reportIDList[]': reportID, markedManually: true, - }); + optimisticReportActionID, + }; + + API.write(WRITE_COMMANDS.MARK_AS_EXPORTED, params, {optimisticData, successData, failureData}); } /** Save the preferred export method for a policy */ From 533097ae4c5123725a3f156388850d14a5b02198 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 4 Jul 2024 10:26:25 +0200 Subject: [PATCH 02/14] cleanup --- src/libs/ReportUtils.ts | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a792c485f46f..71056ebf1bd4 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -5152,38 +5152,6 @@ function buildOptimisticTaskReport( }; } -// function buildOptimisticCreatedReportAction(emailCreatingAction: string, created = DateUtils.getDBTime()): OptimisticCreatedReportAction { -// return { -// reportActionID: NumberUtils.rand64(), -// actionName: CONST.REPORT.ACTIONS.TYPE.CREATED, -// pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, -// actorAccountID: currentUserAccountID, -// message: [ -// { -// type: CONST.REPORT.MESSAGE.TYPE.TEXT, -// style: 'strong', -// text: emailCreatingAction, -// }, -// { -// type: CONST.REPORT.MESSAGE.TYPE.TEXT, -// style: 'normal', -// text: ' created this report', -// }, -// ], -// person: [ -// { -// type: CONST.REPORT.MESSAGE.TYPE.TEXT, -// style: 'strong', -// text: getCurrentUserDisplayNameOrEmail(), -// }, -// ], -// automatic: false, -// avatar: getCurrentUserAvatar(), -// created, -// shouldShow: true, -// }; -// } - // Manual export function buildOptimisticExportIntegrationAction(label = '', markedManually = false): OptimisticExportAction { return { From 1425235363fbdbf93bdd21e9760b076ac0b25a4e Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 4 Jul 2024 15:02:05 +0200 Subject: [PATCH 03/14] fix: rbr --- src/components/ReportActionItem/ReportPreview.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 53b8ecd9a47e..2161067e06c3 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -154,7 +154,7 @@ function ReportPreview({ const hasReceipts = transactionsWithReceipts.length > 0; const isScanning = hasReceipts && areAllRequestsBeingSmartScanned; const hasErrors = - hasMissingSmartscanFields || + (hasMissingSmartscanFields && !iouSettled) || // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing (canUseViolations && (ReportUtils.hasViolations(iouReportID, transactionViolations) || ReportUtils.hasWarningTypeViolations(iouReportID, transactionViolations))) || ReportUtils.hasActionsWithErrors(iouReportID); @@ -283,7 +283,7 @@ function ReportPreview({ const shouldShowSettlementButton = (shouldShowPayButton || shouldShowApproveButton) && !showRTERViolationMessage; const shouldPromptUserToAddBankAccount = ReportUtils.hasMissingPaymentMethod(userWallet, iouReportID); - const shouldShowRBR = !iouSettled && hasErrors; + const shouldShowRBR = hasErrors; /* Show subtitle if at least one of the expenses is not being smart scanned, and either: From 652ce3684fbabac2b99dce791c5a37763a471403 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Fri, 5 Jul 2024 11:49:59 +0200 Subject: [PATCH 04/14] feat: add in progress status --- src/languages/en.ts | 1 + src/languages/types.ts | 2 +- src/libs/ReportActionsUtils.ts | 6 +++++- src/libs/ReportUtils.ts | 24 +++++++----------------- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 85bcae07530c..966a25a9623c 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3235,6 +3235,7 @@ export default { } return `exported this report to ${label}`; }, + exportInProgress: ({label}: ExportedToIntegrationParams) => `started exporting this report to ${label}...`, forwarded: ({amount, currency}: ForwardedParams) => `approved ${currency}${amount}`, integrationsMessage: (errorMessage: string, label: string) => `failed to export this report to ${label} ("${errorMessage}").`, managerAttachReceipt: `added a receipt`, diff --git a/src/languages/types.ts b/src/languages/types.ts index caf44a73bd3b..397c35651e82 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -308,7 +308,7 @@ type ChangeTypeParams = {oldType: string; newType: string}; type DelegateSubmitParams = {delegateUser: string; originalManager: string}; -type ExportedToIntegrationParams = {label: string; markedManually: boolean}; +type ExportedToIntegrationParams = {label: string; markedManually?: boolean; inProgress?: boolean; lastModified?: string}; type ForwardedParams = {amount: string; currency: string}; diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index b7e13c929056..bac669f63ec9 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -1257,8 +1257,12 @@ function getMessageOfOldDotReportAction(oldDotAction: PartialReportAction | OldD } case CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_CSV: return Localize.translateLocal('report.actions.type.exportedToCSV'); - case CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION: + case CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION: { + if (originalMessage.inProgress) { + return Localize.translateLocal('report.actions.type.exportInProgress', {label: originalMessage.label}); + } return Localize.translateLocal('report.actions.type.exportedToIntegration', {label: originalMessage.label, markedManually: originalMessage.markedManually}); + } case CONST.REPORT.ACTIONS.TYPE.INTEGRATIONS_MESSAGE: { const {result, label} = originalMessage; const errorMessage = result?.messages?.join(', ') ?? ''; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 11ca6edf239e..a9d583a9b6cd 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -39,6 +39,7 @@ import type { UserWallet, } from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; +import {OriginalMessageExportedToIntegration} from '@src/types/onyx/OldDotAction'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; import type {OriginalMessageChangeLog, PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type {Status} from '@src/types/onyx/PersonalDetails'; @@ -276,22 +277,11 @@ type OptimisticChatReport = Pick< isOptimisticReport: true; }; -type OptimisticExportAction = Pick< - ReportAction, - | 'reportActionID' - | 'actionName' - | 'actorAccountID' - | 'avatar' - | 'created' - | 'lastModified' - | 'message' - | 'originalMessage' - | 'person' - | 'shouldShow' - | 'pendingAction' - | 'errors' - | 'automatic' ->; +type OptimisticExportAction = OriginalMessageExportedToIntegration & + Pick< + ReportAction, + 'reportActionID' | 'actorAccountID' | 'avatar' | 'created' | 'lastModified' | 'message' | 'person' | 'shouldShow' | 'pendingAction' | 'errors' | 'automatic' + >; type OptimisticTaskReportAction = Pick< ReportAction, @@ -5196,10 +5186,10 @@ function buildOptimisticExportIntegrationAction(label = '', markedManually = fal created: DateUtils.getDBTime(), shouldShow: true, originalMessage: { - automaticAction: false, label, lastModified: DateUtils.getDBTime(), markedManually, + inProgress: true, }, }; } From 42b923c67c185e427c4fb21bcc687820dc335fbf Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Fri, 5 Jul 2024 12:35:24 +0200 Subject: [PATCH 05/14] fix lang --- src/languages/en.ts | 2 +- src/libs/ReportUtils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index b63b093ead9d..846a9af5b734 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3351,7 +3351,7 @@ export default { } return `exported this report to ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}`; }, - exportInProgress: ({label}: ExportedToIntegrationParams) => `started exporting this report to ${label}...`, + exportInProgress: ({label}: ExportedToIntegrationParams) => `started exporting this report to ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}...`, forwarded: ({amount, currency}: ForwardedParams) => `approved ${currency}${amount}`, integrationsMessage: (errorMessage: string, label: string) => `failed to export this report to ${label} ("${errorMessage}").`, managerAttachReceipt: `added a receipt`, diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e050799e0c0f..e15d3abfbb0d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -5126,7 +5126,7 @@ function buildOptimisticTaskReport( } // Manual export -function buildOptimisticExportIntegrationAction(label = '', markedManually = false): OptimisticExportAction { +function buildOptimisticExportIntegrationAction(label: ConnectionName, markedManually = false): OptimisticExportAction { return { reportActionID: NumberUtils.rand64(), actionName: CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION, From 98c74431ddad2176730073c8a047f7b1f12d651f Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:19:01 +0200 Subject: [PATCH 06/14] fixes --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index fb7fda9db7f1..1069cba9b73a 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -5123,7 +5123,7 @@ function buildOptimisticTaskReport( } // Manual export -function buildOptimisticExportIntegrationAction(label: ConnectionName, markedManually = false): OptimisticExportAction { +function buildOptimisticExportIntegrationAction(label?: ConnectionName, markedManually = false): OptimisticExportAction { return { reportActionID: NumberUtils.rand64(), actionName: CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION, From 972f91075f0d02e43097f8b070e0e6439ca9df6e Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 16 Jul 2024 10:39:21 +0200 Subject: [PATCH 07/14] cleanup --- .../ExportWithDropdownMenu.tsx | 4 ++-- src/languages/en.ts | 6 +++--- src/libs/ReportActionsUtils.ts | 2 +- src/libs/ReportUtils.ts | 9 +++++++-- src/libs/actions/Report.ts | 18 ++++++++---------- .../home/report/ReportDetailsExportPage.tsx | 2 +- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/components/ReportActionItem/ExportWithDropdownMenu.tsx b/src/components/ReportActionItem/ExportWithDropdownMenu.tsx index a13c0a266689..87ddb3b42bf0 100644 --- a/src/components/ReportActionItem/ExportWithDropdownMenu.tsx +++ b/src/components/ReportActionItem/ExportWithDropdownMenu.tsx @@ -74,7 +74,7 @@ function ExportWithDropdownMenu({policy, report, connectionName}: ExportWithDrop if (modalStatus === CONST.REPORT.EXPORT_OPTIONS.EXPORT_TO_INTEGRATION) { ReportActions.exportToIntegration(reportID, connectionName); } else if (modalStatus === CONST.REPORT.EXPORT_OPTIONS.MARK_AS_EXPORTED) { - ReportActions.markAsManuallyExported(reportID); + ReportActions.markAsManuallyExported(reportID, connectionName); } }, [connectionName, modalStatus, reportID]); @@ -106,7 +106,7 @@ function ExportWithDropdownMenu({policy, report, connectionName}: ExportWithDrop if (value === CONST.REPORT.EXPORT_OPTIONS.EXPORT_TO_INTEGRATION) { ReportActions.exportToIntegration(reportID, connectionName); } else if (value === CONST.REPORT.EXPORT_OPTIONS.MARK_AS_EXPORTED) { - ReportActions.markAsManuallyExported(reportID); + ReportActions.markAsManuallyExported(reportID, connectionName); } }} onOptionSelected={({value}) => savePreferredExportMethod(value)} diff --git a/src/languages/en.ts b/src/languages/en.ts index d8cb0862485b..77d9c1a13b92 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3608,11 +3608,11 @@ export default { delegateSubmit: ({delegateUser, originalManager}: DelegateSubmitParams) => `sent this report to ${delegateUser} since ${originalManager} is on vacation`, exportedToCSV: `exported this report to CSV`, exportedToIntegration: ({label, markedManually}: ExportedToIntegrationParams) => { + const friendlyLabel = CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label; if (markedManually) { - // TODO: Verify translation - it was taken from the backend response, and it is needed here for the optimistic response - return `You marked this report as manually exported to`; + return `You marked this report as manually exported to ${friendlyLabel}`; } - return `exported this report to ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}`; + return `exported this report to ${friendlyLabel}`; }, exportInProgress: ({label}: ExportedToIntegrationParams) => `started exporting this report to ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}...`, forwarded: ({amount, currency}: ForwardedParams) => `approved ${currency}${amount}`, diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 1c2ef82154b6..00ed22886700 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -1221,7 +1221,7 @@ function getMessageOfOldDotReportAction(oldDotAction: PartialReportAction | OldD case CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_CSV: return Localize.translateLocal('report.actions.type.exportedToCSV'); case CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION: { - if (originalMessage.inProgress) { + if (originalMessage.inProgress && !originalMessage.markedManually) { return Localize.translateLocal('report.actions.type.exportInProgress', {label: originalMessage.label}); } return Localize.translateLocal('report.actions.type.exportedToIntegration', {label: originalMessage.label, markedManually: originalMessage.markedManually}); diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index aaf81bd97e06..a26d440f14d9 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -40,7 +40,7 @@ import type { UserWallet, } from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; -import {OriginalMessageExportedToIntegration} from '@src/types/onyx/OldDotAction'; +import type {OriginalMessageExportedToIntegration} from '@src/types/onyx/OldDotAction'; import type Onboarding from '@src/types/onyx/Onboarding'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; import type {OriginalMessageChangeLog, PaymentMethodType} from '@src/types/onyx/OriginalMessage'; @@ -5138,7 +5138,12 @@ function buildOptimisticTaskReport( }; } -// Manual export +/** + * Builds an optimistic EXPORTED_TO_INTEGRATION report action + * + * @param label - The connectionName of the integration + * @param markedManually - Whether the integration was marked as manually exported + */ function buildOptimisticExportIntegrationAction(label: ConnectionName, markedManually = false): OptimisticExportAction { return { reportActionID: NumberUtils.rand64(), diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 29b5866ff5ba..56d982694614 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -24,6 +24,7 @@ import type { InviteToGroupChatParams, InviteToRoomParams, LeaveRoomParams, + MarkAsExportedParams, MarkAsUnreadParams, OpenReportParams, OpenRoomMembersPageParams, @@ -31,6 +32,7 @@ import type { RemoveEmojiReactionParams, RemoveFromGroupChatParams, RemoveFromRoomParams, + ReportExportParams, ResolveActionableMentionWhisperParams, ResolveActionableReportMentionWhisperParams, SearchForReportsParams, @@ -3814,19 +3816,17 @@ function exportToIntegration(reportID: string, connectionName: ConnectionName) { ]; const params = { - // TODO: Update it when backend is ready - // eslint-disable-next-line @typescript-eslint/naming-convention - 'reportIDList[]': reportID, + reportIDList: reportID, connectionName, type: 'MANUAL', optimisticReportActionID, - }; + } satisfies ReportExportParams; API.write(WRITE_COMMANDS.REPORT_EXPORT, params, {optimisticData, successData, failureData}); } -function markAsManuallyExported(reportID: string) { - const action = ReportUtils.buildOptimisticExportIntegrationAction(undefined, true); +function markAsManuallyExported(reportID: string, connectionName: ConnectionName) { + const action = ReportUtils.buildOptimisticExportIntegrationAction(connectionName, true); const optimisticReportActionID = action.reportActionID; const optimisticData: OnyxUpdate[] = [ @@ -3862,12 +3862,10 @@ function markAsManuallyExported(reportID: string) { ]; const params = { - // TODO: Update it when backend is ready - // eslint-disable-next-line @typescript-eslint/naming-convention - 'reportIDList[]': reportID, + reportIDList: reportID, markedManually: true, optimisticReportActionID, - }; + } satisfies MarkAsExportedParams; API.write(WRITE_COMMANDS.MARK_AS_EXPORTED, params, {optimisticData, successData, failureData}); } diff --git a/src/pages/home/report/ReportDetailsExportPage.tsx b/src/pages/home/report/ReportDetailsExportPage.tsx index 99b7305cc7a9..6f16786682af 100644 --- a/src/pages/home/report/ReportDetailsExportPage.tsx +++ b/src/pages/home/report/ReportDetailsExportPage.tsx @@ -45,7 +45,7 @@ function ReportDetailsExportPage({route}: ReportDetailsExportPageProps) { if (type === CONST.REPORT.EXPORT_OPTIONS.EXPORT_TO_INTEGRATION) { ReportActions.exportToIntegration(reportID, connectionName); } else if (type === CONST.REPORT.EXPORT_OPTIONS.MARK_AS_EXPORTED) { - ReportActions.markAsManuallyExported(reportID); + ReportActions.markAsManuallyExported(reportID, connectionName); } setModalStatus(null); Navigation.dismissModal(); From 37a7735259a2e3bbe3e434585bab41f123b64467 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:04:49 +0200 Subject: [PATCH 08/14] add DeepL translations --- src/languages/en.ts | 5 ++--- src/languages/es.ts | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 77d9c1a13b92..84440f748cd3 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3608,11 +3608,10 @@ export default { delegateSubmit: ({delegateUser, originalManager}: DelegateSubmitParams) => `sent this report to ${delegateUser} since ${originalManager} is on vacation`, exportedToCSV: `exported this report to CSV`, exportedToIntegration: ({label, markedManually}: ExportedToIntegrationParams) => { - const friendlyLabel = CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label; if (markedManually) { - return `You marked this report as manually exported to ${friendlyLabel}`; + return `You marked this report as manually exported to ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}`; } - return `exported this report to ${friendlyLabel}`; + return `exported this report to ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}`; }, exportInProgress: ({label}: ExportedToIntegrationParams) => `started exporting this report to ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}...`, forwarded: ({amount, currency}: ForwardedParams) => `approved ${currency}${amount}`, diff --git a/src/languages/es.ts b/src/languages/es.ts index 055dcf043ef4..9dd1832592d5 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3662,7 +3662,13 @@ export default { changeType: ({oldType, newType}: ChangeTypeParams) => `cambió type de ${oldType} a ${newType}`, delegateSubmit: ({delegateUser, originalManager}: DelegateSubmitParams) => `envié este informe a ${delegateUser} ya que ${originalManager} está de vacaciones`, exportedToCSV: `exportó este informe a CSV`, - exportedToIntegration: ({label}: ExportedToIntegrationParams) => `exportó este informe a ${label}`, + exportedToIntegration: ({label, markedManually}: ExportedToIntegrationParams) => { + if (markedManually) { + return `Ha marcado este informe como exportado manualmente a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}`; + } + return `exportó este informe a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}`; + }, + exportInProgress: ({label}: ExportedToIntegrationParams) => `comenzado a exportar este informe a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[label] ?? label}...`, forwarded: ({amount, currency}: ForwardedParams) => `aprobado ${currency}${amount}`, integrationsMessage: (errorMessage: string, label: string) => `no se pudo exportar este informe a ${label} ("${errorMessage}").`, managerAttachReceipt: `agregó un recibo`, From fdcd82718f81c1c2e495c462d4671a389ca617f0 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Wed, 17 Jul 2024 08:38:36 +0200 Subject: [PATCH 09/14] fix: displaying friendly name --- src/libs/ReportUtils.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 289a772d13e5..9c2f8bb9795d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -5146,10 +5146,11 @@ function buildOptimisticTaskReport( /** * Builds an optimistic EXPORTED_TO_INTEGRATION report action * - * @param label - The connectionName of the integration + * @param integration - The connectionName of the integration * @param markedManually - Whether the integration was marked as manually exported */ -function buildOptimisticExportIntegrationAction(label: ConnectionName, markedManually = false): OptimisticExportAction { +function buildOptimisticExportIntegrationAction(integration: ConnectionName, markedManually = false): OptimisticExportAction { + const label = CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration]; return { reportActionID: NumberUtils.rand64(), actionName: CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION, From a029907af45b66fbb41d2709e90cfc482768f77e Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Fri, 19 Jul 2024 15:24:43 +0200 Subject: [PATCH 10/14] address review --- src/libs/API/parameters/MarkAsExportedParams.ts | 1 + src/libs/actions/Report.ts | 17 ++++++----------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/libs/API/parameters/MarkAsExportedParams.ts b/src/libs/API/parameters/MarkAsExportedParams.ts index 09f5c4cf2e61..50d771279bd5 100644 --- a/src/libs/API/parameters/MarkAsExportedParams.ts +++ b/src/libs/API/parameters/MarkAsExportedParams.ts @@ -2,6 +2,7 @@ type MarkAsExportedParams = { reportIDList: string; markedManually: true; optimisticReportActionID: string; + customLabel: string; }; export default MarkAsExportedParams; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 76944ac7698e..5cf2550f304c 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3800,15 +3800,6 @@ function exportToIntegration(reportID: string, connectionName: ConnectionName) { }, ]; - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: { - [optimisticReportActionID]: null, - }, - }, - ]; const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -3828,11 +3819,12 @@ function exportToIntegration(reportID: string, connectionName: ConnectionName) { optimisticReportActionID, } satisfies ReportExportParams; - API.write(WRITE_COMMANDS.REPORT_EXPORT, params, {optimisticData, successData, failureData}); + API.write(WRITE_COMMANDS.REPORT_EXPORT, params, {optimisticData, failureData}); } function markAsManuallyExported(reportID: string, connectionName: ConnectionName) { const action = ReportUtils.buildOptimisticExportIntegrationAction(connectionName, true); + const label = CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]; const optimisticReportActionID = action.reportActionID; const optimisticData: OnyxUpdate[] = [ @@ -3850,7 +3842,9 @@ function markAsManuallyExported(reportID: string, connectionName: ConnectionName onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, value: { - [optimisticReportActionID]: null, + [optimisticReportActionID]: { + pendingAction: null, + }, }, }, ]; @@ -3871,6 +3865,7 @@ function markAsManuallyExported(reportID: string, connectionName: ConnectionName reportIDList: reportID, markedManually: true, optimisticReportActionID, + customLabel: label, } satisfies MarkAsExportedParams; API.write(WRITE_COMMANDS.MARK_AS_EXPORTED, params, {optimisticData, successData, failureData}); From 9af61d1c241e509cd30253186c6fea79844c3ccd Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Fri, 19 Jul 2024 15:26:03 +0200 Subject: [PATCH 11/14] address review --- src/libs/ReportUtils.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 9e8ea0bdde87..2ad6b44ea9b8 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -284,7 +284,7 @@ type OptimisticChatReport = Pick< isOptimisticReport: true; }; -type OptimisticExportAction = OriginalMessageExportedToIntegration & +type OptimisticExportIntegrationAction = OriginalMessageExportedToIntegration & Pick< ReportAction, 'reportActionID' | 'actorAccountID' | 'avatar' | 'created' | 'lastModified' | 'message' | 'person' | 'shouldShow' | 'pendingAction' | 'errors' | 'automatic' @@ -5149,7 +5149,7 @@ function buildOptimisticTaskReport( * @param integration - The connectionName of the integration * @param markedManually - Whether the integration was marked as manually exported */ -function buildOptimisticExportIntegrationAction(integration: ConnectionName, markedManually = false): OptimisticExportAction { +function buildOptimisticExportIntegrationAction(integration: ConnectionName, markedManually = false): OptimisticExportIntegrationAction { const label = CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration]; return { reportActionID: NumberUtils.rand64(), @@ -5157,7 +5157,13 @@ function buildOptimisticExportIntegrationAction(integration: ConnectionName, mar pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, actorAccountID: currentUserAccountID, message: [], - person: [], + person: [ + { + type: CONST.REPORT.MESSAGE.TYPE.TEXT, + style: 'strong', + text: getCurrentUserDisplayNameOrEmail(), + }, + ], automatic: false, avatar: getCurrentUserAvatar(), created: DateUtils.getDBTime(), From d024caf029613dc644e6b4d6df5e196f81a146a8 Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 25 Jul 2024 11:50:58 +0200 Subject: [PATCH 12/14] adjust API calls parameters --- src/libs/API/parameters/MarkAsExportedParams.ts | 14 ++++++++++---- src/libs/API/parameters/ReportExportParams.ts | 8 +++++++- src/libs/actions/Report.ts | 12 ++++++++---- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/libs/API/parameters/MarkAsExportedParams.ts b/src/libs/API/parameters/MarkAsExportedParams.ts index 50d771279bd5..4e2ed2625de3 100644 --- a/src/libs/API/parameters/MarkAsExportedParams.ts +++ b/src/libs/API/parameters/MarkAsExportedParams.ts @@ -1,8 +1,14 @@ type MarkAsExportedParams = { - reportIDList: string; - markedManually: true; - optimisticReportActionID: string; - customLabel: string; + markedManually: boolean; + /** + * Stringified JSON object with type of following structure: + * { + * reportID: number; + * label: string; + * optimisticReportActionID: string; + * }> + */ + data: string; }; export default MarkAsExportedParams; diff --git a/src/libs/API/parameters/ReportExportParams.ts b/src/libs/API/parameters/ReportExportParams.ts index ff626059a036..c6a4b7b58ee8 100644 --- a/src/libs/API/parameters/ReportExportParams.ts +++ b/src/libs/API/parameters/ReportExportParams.ts @@ -5,7 +5,13 @@ type ReportExportParams = { reportIDList: string; connectionName: ValueOf; type: 'MANUAL'; - optimisticReportActionID: string; + /** + * Stringified JSON object with type of following structure: + * { + * [reportID]: optimisticReportActionID; + * }> + */ + optimisticReportActions: string; }; export default ReportExportParams; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index f311f7ca05ae..d4a58c82b496 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3866,7 +3866,9 @@ function exportToIntegration(reportID: string, connectionName: ConnectionName) { reportIDList: reportID, connectionName, type: 'MANUAL', - optimisticReportActionID, + optimisticReportActions: JSON.stringify({ + [reportID]: optimisticReportActionID, + }), } satisfies ReportExportParams; API.write(WRITE_COMMANDS.REPORT_EXPORT, params, {optimisticData, failureData}); @@ -3912,10 +3914,12 @@ function markAsManuallyExported(reportID: string, connectionName: ConnectionName ]; const params = { - reportIDList: reportID, markedManually: true, - optimisticReportActionID, - customLabel: label, + data: JSON.stringify({ + reportID, + label, + optimisticReportActionID, + }), } satisfies MarkAsExportedParams; API.write(WRITE_COMMANDS.MARK_AS_EXPORTED, params, {optimisticData, successData, failureData}); From dd8d4bdc3a46067a050a5c00ddac9640557fb6bf Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 25 Jul 2024 11:54:25 +0200 Subject: [PATCH 13/14] fix params --- src/libs/API/parameters/MarkAsExportedParams.ts | 2 +- src/libs/actions/Report.ts | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libs/API/parameters/MarkAsExportedParams.ts b/src/libs/API/parameters/MarkAsExportedParams.ts index 4e2ed2625de3..ed457afb42e3 100644 --- a/src/libs/API/parameters/MarkAsExportedParams.ts +++ b/src/libs/API/parameters/MarkAsExportedParams.ts @@ -2,7 +2,7 @@ type MarkAsExportedParams = { markedManually: boolean; /** * Stringified JSON object with type of following structure: - * { + * Array<{ * reportID: number; * label: string; * optimisticReportActionID: string; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index d4a58c82b496..9cb92ebd7c8a 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3915,11 +3915,13 @@ function markAsManuallyExported(reportID: string, connectionName: ConnectionName const params = { markedManually: true, - data: JSON.stringify({ - reportID, - label, - optimisticReportActionID, - }), + data: JSON.stringify([ + { + reportID, + label, + optimisticReportActionID, + }, + ]), } satisfies MarkAsExportedParams; API.write(WRITE_COMMANDS.MARK_AS_EXPORTED, params, {optimisticData, successData, failureData}); From 805ae17c8449395d7d7319c02f5b624862aea600 Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 25 Jul 2024 12:55:10 +0200 Subject: [PATCH 14/14] fix wrong export integration button conditions --- src/components/ReportActionItem/ReportPreview.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 04648fa26d5e..68f5bca3d764 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -425,7 +425,7 @@ function ReportPreview({ )} - {shouldShowSettlementButton && !shouldShowExportIntegrationButton && ( + {shouldShowSettlementButton && ( )} - {shouldShowExportIntegrationButton && ( + {shouldShowExportIntegrationButton && !shouldShowSettlementButton && (