Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7583,6 +7583,7 @@ const CONST = {
BULK_ACTION_TYPES: {
EDIT: 'edit',
EXPORT: 'export',
DOWNLOAD_PDF: 'downloadPDF',
APPROVE: 'approve',
CHANGE_APPROVER: 'changeApprover',
PAY: 'pay',
Expand Down
4 changes: 3 additions & 1 deletion src/components/ReportPDFDownloadModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ type ReportPDFDownloadModalProps = {
reportID: string | undefined;
isVisible: boolean;
onClose: () => void;
onModalHide?: () => void;
};

function ReportPDFDownloadModal({reportID, isVisible, onClose}: ReportPDFDownloadModalProps) {
function ReportPDFDownloadModal({reportID, isVisible, onClose, onModalHide}: ReportPDFDownloadModalProps) {
const shouldAutoDownloadPDF = useRef(false);

const [reportPDFFilename] = useOnyx(`${ONYXKEYS.COLLECTION.NVP_EXPENSIFY_REPORT_PDF_FILENAME}${reportID}`);
Expand Down Expand Up @@ -76,6 +77,7 @@ function ReportPDFDownloadModal({reportID, isVisible, onClose}: ReportPDFDownloa
return (
<Modal
onClose={onClose}
onModalHide={onModalHide}
isVisible={isVisible}
type={isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.CONFIRM}
innerContainerStyle={styles.pv0}
Expand Down
13 changes: 13 additions & 0 deletions src/components/Search/SearchBulkActionsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import HoldSubmitterEducationalModal from '@components/HoldSubmitterEducationalM
import KYCWall from '@components/KYCWall';
import {KYCWallContext} from '@components/KYCWall/KYCWallContext';
import {useLockedAccountActions, useLockedAccountState} from '@components/LockedAccountModalProvider';
import ReportPDFDownloadModal from '@components/ReportPDFDownloadModal';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
Expand Down Expand Up @@ -68,6 +69,10 @@ function SearchBulkActionsButton({queryJSON}: SearchBulkActionsButtonProps) {
emptyReportsCount,
handleOfflineModalClose,
handleDownloadErrorModalClose,
isPdfModalVisible,
setIsPdfModalVisible,
pdfReportID,
handlePdfModalHide,
dismissModalAndUpdateUseHold,
dismissRejectModalBasedOnAction,
isDuplicateOptionVisible,
Expand Down Expand Up @@ -255,6 +260,14 @@ function SearchBulkActionsButton({queryJSON}: SearchBulkActionsButtonProps) {
isVisible={isDownloadErrorModalVisible}
onClose={handleDownloadErrorModalClose}
/>
{!!pdfReportID && (
<ReportPDFDownloadModal
reportID={pdfReportID}
isVisible={isPdfModalVisible}
onClose={() => setIsPdfModalVisible(false)}
onModalHide={handlePdfModalHide}
/>
)}
{!!rejectModalAction && (
<HoldOrRejectEducationalModal
onClose={dismissRejectModalBasedOnAction}
Expand Down
4 changes: 4 additions & 0 deletions src/hooks/useExportActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ function useExportActions({reportID, policy, onPDFModalOpen}: UseExportActionsPa
icon: expensifyIcons.Download,
sentryLabel: CONST.SENTRY_LABEL.MORE_MENU.DOWNLOAD_PDF,
onSelected: () => {
if (isOffline) {
showOfflineModal();
return;
}
if (!moneyRequestReport?.reportID) {
return;
}
Expand Down
39 changes: 38 additions & 1 deletion src/hooks/useSearchBulkActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {useSearchActionsContext, useSearchStateContext} from '@components/Search
import type {BulkPaySelectionData, PaymentData, SearchQueryJSON} from '@components/Search/types';
import {unholdRequest} from '@libs/actions/IOU/Hold';
import {setupMergeTransactionDataAndNavigate} from '@libs/actions/MergeTransaction';
import {deleteAppReport, markAsManuallyExported, moveIOUReportToPolicy, moveIOUReportToPolicyAndInviteSubmitter} from '@libs/actions/Report';
import {deleteAppReport, exportReportToPDF, markAsManuallyExported, moveIOUReportToPolicy, moveIOUReportToPolicyAndInviteSubmitter} from '@libs/actions/Report';
import {
approveMoneyRequestOnSearch,
bulkDeleteReports,
Expand Down Expand Up @@ -254,6 +254,8 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {

const [isOfflineModalVisible, setIsOfflineModalVisible] = useState(false);
const [isDownloadErrorModalVisible, setIsDownloadErrorModalVisible] = useState(false);
const [isPdfModalVisible, setIsPdfModalVisible] = useState(false);
const [pdfReportID, setPdfReportID] = useState<string | undefined>(undefined);
const {showConfirmModal} = useConfirmModal();
const [isHoldEducationalModalVisible, setIsHoldEducationalModalVisible] = useState(false);
const [rejectModalAction, setRejectModalAction] = useState<ValueOf<
Expand All @@ -267,6 +269,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {

const isExpenseReportType = queryJSON?.type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
const expensifyIcons = useMemoizedLazyExpensifyIcons([
'Download',
'Export',
'Table',
'TablePencil',
Expand Down Expand Up @@ -1287,6 +1290,30 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {

options.push(exportButtonOption);

if (isExpenseReportSearch && selectedReportIDs.length === 1) {
const reportIDForPDF = selectedReportIDs.at(0);
options.push({
icon: expensifyIcons.Download,
text: translate('common.downloadAsPDF'),
value: CONST.SEARCH.BULK_ACTION_TYPES.DOWNLOAD_PDF,
shouldCloseModalOnSelect: true,
onSelected: async () => {
if (isOffline) {
setIsOfflineModalVisible(true);
return;
}
if (!reportIDForPDF) {
return;
}
// Using await prevent the double-download on the second PDF export
// by clearing Onyx filename before modal is visible
await exportReportToPDF({reportID: reportIDForPDF});
Comment thread
apeyada marked this conversation as resolved.
setPdfReportID(reportIDForPDF);
setIsPdfModalVisible(true);
},
});
}

const shouldShowHoldOption = !isOffline && selectedTransactionsKeys.every((id) => selectedTransactions[id].canHold);

if (shouldShowHoldOption) {
Expand Down Expand Up @@ -1561,6 +1588,11 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
setIsDownloadErrorModalVisible(false);
}, [setIsDownloadErrorModalVisible]);

const handlePdfModalHide = useCallback(() => {
setPdfReportID(undefined);
clearSelectedTransactions();
}, [clearSelectedTransactions]);

const dismissModalAndUpdateUseHold = useCallback(() => {
setIsHoldEducationalModalVisible(false);
setNameValuePair(ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION, true, false, !isOffline);
Expand Down Expand Up @@ -1596,6 +1628,10 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
emptyReportsCount,
handleOfflineModalClose,
handleDownloadErrorModalClose,
isPdfModalVisible,
setIsPdfModalVisible,
pdfReportID,
handlePdfModalHide,
dismissModalAndUpdateUseHold,
dismissRejectModalBasedOnAction,
isDuplicateOptionVisible,
Expand All @@ -1610,3 +1646,4 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {

export default useSearchBulkActions;
export {shouldShowBulkDuplicateOption};
export type {SearchHeaderOptionValue};
4 changes: 2 additions & 2 deletions src/libs/actions/Report/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6161,7 +6161,7 @@ function exportReportToCSV({reportID, transactionIDList}: ExportReportCSVParams,
fileDownload(translate, ApiUtils.getCommandURL({command: WRITE_COMMANDS.EXPORT_REPORT_TO_CSV}), 'Expensify.csv', '', false, formData, CONST.NETWORK.METHOD.POST, onDownloadFailed);
}

function exportReportToPDF({reportID}: ExportReportPDFParams) {
async function exportReportToPDF({reportID}: ExportReportPDFParams) {
const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.NVP_EXPENSIFY_REPORT_PDF_FILENAME>> = [
{
onyxMethod: Onyx.METHOD.SET,
Expand All @@ -6181,7 +6181,7 @@ function exportReportToPDF({reportID}: ExportReportPDFParams) {
reportID,
} satisfies ExportReportPDFParams;

API.write(WRITE_COMMANDS.EXPORT_REPORT_TO_PDF, params, {optimisticData, failureData});
return API.write(WRITE_COMMANDS.EXPORT_REPORT_TO_PDF, params, {optimisticData, failureData});
}

function downloadReportPDF(fileName: string, reportName: string, translate: LocalizedTranslate, currentUserLogin: string, encryptedAuthToken: string) {
Expand Down
Loading
Loading