From c1774d149b3190529f4fe967cb455f62563f64bf Mon Sep 17 00:00:00 2001 From: Alberto Date: Thu, 20 Feb 2025 14:55:56 +0100 Subject: [PATCH 01/42] labels --- src/CONST.ts | 3 ++- src/languages/en.ts | 2 ++ src/languages/es.ts | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index 55f0dafd85176..01f6db05c1bf3 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -3383,7 +3383,8 @@ const CONST = { SETTINGS: 'settings', LEAVE_ROOM: 'leaveRoom', PRIVATE_NOTES: 'privateNotes', - DOWNLOAD: 'download', + DOWNLOAD_CSV: 'downloadCSV', + DOWNLOAD_PDF: 'downloadPDF', EXPORT: 'export', DELETE: 'delete', MARK_AS_INCOMPLETE: 'markAsIncomplete', diff --git a/src/languages/en.ts b/src/languages/en.ts index 5ee0b939049ef..65c4f7da5df6a 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -502,6 +502,8 @@ const translations = { subrate: 'Subrate', perDiem: 'Per diem', validate: 'Validate', + downloadAsPDF: 'Download as PDF', + downloadAsCSV: 'Download as CSV', }, supportalNoAccess: { title: 'Not so fast', diff --git a/src/languages/es.ts b/src/languages/es.ts index 104dc52fd85b5..2674d36dc8a3f 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -493,6 +493,8 @@ const translations = { subrate: 'Subtasa', perDiem: 'Per diem', validate: 'Validar', + downloadAsPDF: 'Descargar como PDF', + downloadAsCSV: 'Descargar como CSV', }, supportalNoAccess: { title: 'No tan rápido', From 1cafa5571b706b41a7345f0b270d4d8fee263ab7 Mon Sep 17 00:00:00 2001 From: Alberto Date: Thu, 20 Feb 2025 14:57:08 +0100 Subject: [PATCH 02/42] Add new params --- src/libs/API/parameters/ExportReportPDFParams.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/libs/API/parameters/ExportReportPDFParams.ts diff --git a/src/libs/API/parameters/ExportReportPDFParams.ts b/src/libs/API/parameters/ExportReportPDFParams.ts new file mode 100644 index 0000000000000..460e6d225a71b --- /dev/null +++ b/src/libs/API/parameters/ExportReportPDFParams.ts @@ -0,0 +1,6 @@ +type ExportReportPDFParams = { + transactionIDList: string[]; + reportID: string; +}; + +export default ExportReportPDFParams; \ No newline at end of file From 9b5cd8c3f11784f1b0e5fa0b63e94283fdd1666d Mon Sep 17 00:00:00 2001 From: Alberto Date: Thu, 20 Feb 2025 14:58:46 +0100 Subject: [PATCH 03/42] new types and whatnot --- src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index dacad199d00fb..047b6cad68ce3 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -368,6 +368,7 @@ export type {default as BankAccountCreateCorpayParams} from './BankAccountCreate export type {default as JoinAccessiblePolicyParams} from './JoinAccessiblePolicyParams'; export type {default as ImportPerDiemRatesParams} from './ImportPerDiemRatesParams'; export type {default as ExportPerDiemCSVParams} from './ExportPerDiemCSVParams'; +export type {default as ExportReportPDFParams} from './ExportReportPDFParams'; export type {default as UpdateWorkspaceCustomUnitParams} from './UpdateWorkspaceCustomUnitParams'; export type {default as DismissProductTrainingParams} from './DismissProductTraining'; export type {default as OpenWorkspacePlanPageParams} from './OpenWorkspacePlanPage'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index f642e27117241..67bb1f80565a1 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -156,6 +156,7 @@ const WRITE_COMMANDS = { EXPORT_TAGS_CSV: 'ExportTagsCSV', EXPORT_PER_DIEM_CSV: 'ExportPerDiemCSV', EXPORT_REPORT_TO_CSV: 'ExportReportToCSV', + EXPORT_REPORT_TO_PDF: 'ExportReportToPDF', RENAME_WORKSPACE_CATEGORY: 'RenameWorkspaceCategory', CREATE_POLICY_TAG: 'CreatePolicyTag', RENAME_POLICY_TAG: 'RenamePolicyTag', @@ -602,6 +603,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.EXPORT_MEMBERS_CSV]: Parameters.ExportMembersSpreadsheetParams; [WRITE_COMMANDS.EXPORT_TAGS_CSV]: Parameters.ExportTagsSpreadsheetParams; [WRITE_COMMANDS.EXPORT_PER_DIEM_CSV]: Parameters.ExportPerDiemCSVParams; + [WRITE_COMMANDS.EXPORT_REPORT_TO_PDF]: Parameters.ExportReportPDFParams; [WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY]: Parameters.RenameWorkspaceCategoriesParams; [WRITE_COMMANDS.SET_WORKSPACE_REQUIRES_CATEGORY]: Parameters.SetWorkspaceRequiresCategoryParams; [WRITE_COMMANDS.DELETE_WORKSPACE_CATEGORIES]: Parameters.DeleteWorkspaceCategoriesParams; From c3cce3b1d53951125db8a29c584b5e4a3a2ec2e9 Mon Sep 17 00:00:00 2001 From: Alberto Date: Thu, 20 Feb 2025 15:04:40 +0100 Subject: [PATCH 04/42] Add button --- src/libs/actions/Report.ts | 21 +++++++++++++++ src/pages/ReportDetailsPage.tsx | 46 +++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index d9a5cf8f2bc61..bc103c1a2b8c0 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -49,6 +49,7 @@ import type { UpdateRoomDescriptionParams, } from '@libs/API/parameters'; import type ExportReportCSVParams from '@libs/API/parameters/ExportReportCSVParams'; +import type ExportReportPDFParams from '@libs/API/parameters/ExportReportPDFParams'; import type UpdateRoomVisibilityParams from '@libs/API/parameters/UpdateRoomVisibilityParams'; import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import * as ApiUtils from '@libs/ApiUtils'; @@ -4652,6 +4653,25 @@ function exportReportToCSV({reportID, transactionIDList}: ExportReportCSVParams, fileDownload(ApiUtils.getCommandURL({command: WRITE_COMMANDS.EXPORT_REPORT_TO_CSV}), 'Expensify.csv', '', false, formData, CONST.NETWORK.METHOD.POST, onDownloadFailed); } + +function exportReportToPDF({reportID, transactionIDList}: ExportReportPDFParams, onDownloadFailed: () => void) { + const finalParameters = enhanceParameters(WRITE_COMMANDS.EXPORT_REPORT_TO_PDF, { + reportID, + transactionIDList, + }); + + const formData = new FormData(); + Object.entries(finalParameters).forEach(([key, value]) => { + if (Array.isArray(value)) { + formData.append(key, value.join(',')); + } else { + formData.append(key, String(value)); + } + }); + + fileDownload(ApiUtils.getCommandURL({command: WRITE_COMMANDS.EXPORT_REPORT_TO_PDF}), 'Expensify.pdf', '', false, formData, CONST.NETWORK.METHOD.POST, onDownloadFailed); +} + function getConciergeReportID() { return conciergeChatReportID; } @@ -4690,6 +4710,7 @@ export { editReportComment, expandURLPreview, exportReportToCSV, + exportReportToPDF, exportToIntegration, flagComment, getConciergeReportID, diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 95ad130fcfaca..05d9c5d54db28 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -117,6 +117,7 @@ import { clearPolicyRoomNameErrors, clearReportFieldKeyErrors, exportReportToCSV, + exportReportToPDF, getReportPrivateNote, hasErrorInPrivateNotes, leaveGroupChat, @@ -531,22 +532,39 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta } if (isMoneyRequestReport) { - items.push({ - key: CONST.REPORT_DETAILS_MENU_ITEM.DOWNLOAD, - translationKey: 'common.download', - icon: Expensicons.Download, - isAnonymousAction: false, - action: () => { - if (isOffline) { - setOfflineModalVisible(true); - return; - } + items.push( + { + key: CONST.REPORT_DETAILS_MENU_ITEM.DOWNLOAD_CSV, + translationKey: 'common.downloadAsCSV', + icon: Expensicons.Table, + isAnonymousAction: false, + action: () => { + if (isOffline) { + setOfflineModalVisible(true); + return; + } - exportReportToCSV({reportID: report.reportID, transactionIDList}, () => { - setDownloadErrorModalVisible(true); - }); + exportReportToCSV({reportID: report.reportID, transactionIDList}, () => { + setDownloadErrorModalVisible(true); + }); + }, }, - }); + { + key: CONST.REPORT_DETAILS_MENU_ITEM.DOWNLOAD_PDF, + translationKey: 'common.downloadAsPDF', + icon: Expensicons.Document, + isAnonymousAction: false, + action: () => { + if (isOffline) { + setOfflineModalVisible(true); + } + + exportReportToPDF({reportID: report.reportID, transactionIDList}, () => { + setDownloadErrorModalVisible(true); + }); + }, + }, + ); } if (policy && connectedIntegration && isPolicyAdmin && !isSingleTransactionView && isExpenseReport) { From 04807e63f5a70044dcb5629d82e299533012d183 Mon Sep 17 00:00:00 2001 From: Alberto Date: Thu, 20 Feb 2025 17:00:02 +0100 Subject: [PATCH 05/42] typing changes --- src/ONYXKEYS.ts | 3 +++ src/libs/API/parameters/ExportReportPDFParams.ts | 1 - src/libs/actions/Report.ts | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index dce55b29b8760..f89216c00ec11 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -566,6 +566,8 @@ const ONYXKEYS = { /** Whether the bank account chosen for Expensify Card in on verification waitlist */ NVP_EXPENSIFY_ON_CARD_WAITLIST: 'nvp_expensify_onCardWaitlist_', + NVP_EXPENSIFY_REPORT_PDFFILENAME: 'nvp_expensify_report_PDFFilename_', + /** Stores the information about the state of issuing a new card */ ISSUE_NEW_EXPENSIFY_CARD: 'issueNewExpensifyCard_', }, @@ -903,6 +905,7 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.OLD_POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags; [ONYXKEYS.COLLECTION.SELECTED_TAB]: OnyxTypes.SelectedTabRequest; [ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string; + [ONYXKEYS.COLLECTION.NVP_EXPENSIFY_REPORT_PDFFILENAME]: string; [ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStep; [ONYXKEYS.COLLECTION.POLICY_JOIN_MEMBER]: OnyxTypes.PolicyJoinMember; [ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS]: OnyxTypes.PolicyConnectionSyncProgress; diff --git a/src/libs/API/parameters/ExportReportPDFParams.ts b/src/libs/API/parameters/ExportReportPDFParams.ts index 460e6d225a71b..0e677b26f7c38 100644 --- a/src/libs/API/parameters/ExportReportPDFParams.ts +++ b/src/libs/API/parameters/ExportReportPDFParams.ts @@ -1,5 +1,4 @@ type ExportReportPDFParams = { - transactionIDList: string[]; reportID: string; }; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index bc103c1a2b8c0..3a6fc4daf64c8 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -300,6 +300,15 @@ Onyx.connect({ }, }); +let allReportPDFFiles: OnyxCollection; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.NVP_EXPENSIFY_REPORT_PDFFILENAME, + waitForCollectionCallback: true, + callback: (value) => { + allReportPDFFiles = value; + }, +}); + const typingWatchTimers: Record = {}; let reportIDDeeplinkedFromOldDot: string | undefined; From 2be5e3e68d8084eef520cfa9fbc01d0f9a533290 Mon Sep 17 00:00:00 2001 From: Alberto Date: Fri, 21 Feb 2025 11:46:26 +0100 Subject: [PATCH 06/42] Add generating modal --- src/libs/actions/Report.ts | 18 ++-------------- src/pages/ReportDetailsPage.tsx | 38 +++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 3a6fc4daf64c8..eac13785d7d3e 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -4663,22 +4663,8 @@ function exportReportToCSV({reportID, transactionIDList}: ExportReportCSVParams, fileDownload(ApiUtils.getCommandURL({command: WRITE_COMMANDS.EXPORT_REPORT_TO_CSV}), 'Expensify.csv', '', false, formData, CONST.NETWORK.METHOD.POST, onDownloadFailed); } -function exportReportToPDF({reportID, transactionIDList}: ExportReportPDFParams, onDownloadFailed: () => void) { - const finalParameters = enhanceParameters(WRITE_COMMANDS.EXPORT_REPORT_TO_PDF, { - reportID, - transactionIDList, - }); - - const formData = new FormData(); - Object.entries(finalParameters).forEach(([key, value]) => { - if (Array.isArray(value)) { - formData.append(key, value.join(',')); - } else { - formData.append(key, String(value)); - } - }); - - fileDownload(ApiUtils.getCommandURL({command: WRITE_COMMANDS.EXPORT_REPORT_TO_PDF}), 'Expensify.pdf', '', false, formData, CONST.NETWORK.METHOD.POST, onDownloadFailed); +function exportReportToPDF({reportID}: ExportReportPDFParams, onDownloadFailed: () => void) { + console.log(allReportPDFFiles); } function getConciergeReportID() { diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 05d9c5d54db28..50df55485165e 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -1,6 +1,6 @@ import {Str} from 'expensify-common'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {View} from 'react-native'; +import {ActivityIndicator, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {useOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; @@ -139,6 +139,9 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; import type {WithReportOrNotFoundProps} from './home/report/withReportOrNotFound'; import withReportOrNotFound from './home/report/withReportOrNotFound'; +import Header from "@components/Header"; +import Button from "@components/Button"; +import Modal from "@components/Modal"; type ReportDetailsPageMenuItem = { key: DeepValueOf; @@ -195,6 +198,7 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); const [isUnapproveModalVisible, setIsUnapproveModalVisible] = useState(false); const [isConfirmModalVisible, setIsConfirmModalVisible] = useState(false); + const [isPDFModalVisible, setIsPDFModalVisible] = useState(false); const [offlineModalVisible, setOfflineModalVisible] = useState(false); const [downloadErrorModalVisible, setDownloadErrorModalVisible] = useState(false); const policy = useMemo(() => policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`], [policies, report?.policyID]); @@ -559,9 +563,7 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta setOfflineModalVisible(true); } - exportReportToPDF({reportID: report.reportID, transactionIDList}, () => { - setDownloadErrorModalVisible(true); - }); + setIsPDFModalVisible(true); }, }, ); @@ -1130,6 +1132,34 @@ function ReportDetailsPage({policies, report, route, reportMetadata}: ReportDeta isVisible={downloadErrorModalVisible} onClose={() => setDownloadErrorModalVisible(false)} /> + setIsPDFModalVisible(false)} + isVisible={isPDFModalVisible} + type={isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.CONFIRM} + > + + + +
+ + + {'Please wait while we generate the PDF'} + + + +