diff --git a/apps/remix/app/components/general/document/document-page-view-dropdown.tsx b/apps/remix/app/components/general/document/document-page-view-dropdown.tsx index 21f4ce481..bb2164f52 100644 --- a/apps/remix/app/components/general/document/document-page-view-dropdown.tsx +++ b/apps/remix/app/components/general/document/document-page-view-dropdown.tsx @@ -3,8 +3,8 @@ import { useState } from 'react'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; -import { DocumentStatus } from '@prisma/client'; import type { Document, Recipient, Team, User } from '@prisma/client'; +import { DocumentStatus } from '@prisma/client'; import { Copy, Download, @@ -15,8 +15,7 @@ import { Share, Trash2, } from 'lucide-react'; -import { Link } from 'react-router'; -import { useNavigate } from 'react-router'; +import { Link, useNavigate } from 'react-router'; import { downloadPDF } from '@documenso/lib/client-only/download-pdf'; import { useSession } from '@documenso/lib/client-only/providers/session'; @@ -99,6 +98,35 @@ export const DocumentPageViewDropdown = ({ document }: DocumentPageViewDropdownP } }; + const onDownloadOriginalClick = async () => { + try { + const documentWithData = await trpcClient.document.getDocumentById.query( + { + documentId: document.id, + }, + { + context: { + teamId: team?.id?.toString(), + }, + }, + ); + + const documentData = documentWithData?.documentData; + + if (!documentData) { + return; + } + + await downloadPDF({ documentData, fileName: document.title, version: 'original' }); + } catch (err) { + toast({ + title: _(msg`Something went wrong`), + description: _(msg`An error occurred while downloading your document.`), + variant: 'destructive', + }); + } + }; + const nonSignedRecipients = document.recipients.filter((item) => item.signingStatus !== 'SIGNED'); return ( @@ -128,6 +156,11 @@ export const DocumentPageViewDropdown = ({ document }: DocumentPageViewDropdownP )} + + + Download Original + + diff --git a/apps/remix/app/components/tables/documents-table-action-dropdown.tsx b/apps/remix/app/components/tables/documents-table-action-dropdown.tsx index ea0f11fc1..21e203a50 100644 --- a/apps/remix/app/components/tables/documents-table-action-dropdown.tsx +++ b/apps/remix/app/components/tables/documents-table-action-dropdown.tsx @@ -100,6 +100,32 @@ export const DocumentsTableActionDropdown = ({ row }: DocumentsTableActionDropdo } }; + const onDownloadOriginalClick = async () => { + try { + const document = !recipient + ? await trpcClient.document.getDocumentById.query({ + documentId: row.id, + }) + : await trpcClient.document.getDocumentByToken.query({ + token: recipient.token, + }); + + const documentData = document?.documentData; + + if (!documentData) { + return; + } + + await downloadPDF({ documentData, fileName: row.title, version: 'original' }); + } catch (err) { + toast({ + title: _(msg`Something went wrong`), + description: _(msg`An error occurred while downloading your document.`), + variant: 'destructive', + }); + } + }; + const nonSignedRecipients = row.recipients.filter((item) => item.signingStatus !== 'SIGNED'); return ( @@ -152,6 +178,11 @@ export const DocumentsTableActionDropdown = ({ row }: DocumentsTableActionDropdo Download + + + Download Original + + setDuplicateDialogOpen(true)}> Duplicate diff --git a/packages/lib/client-only/download-pdf.ts b/packages/lib/client-only/download-pdf.ts index 65c8ca4f6..f6db9b629 100644 --- a/packages/lib/client-only/download-pdf.ts +++ b/packages/lib/client-only/download-pdf.ts @@ -3,22 +3,38 @@ import type { DocumentData } from '@prisma/client'; import { getFile } from '../universal/upload/get-file'; import { downloadFile } from './download-file'; +type DocumentVersion = 'original' | 'signed'; + type DownloadPDFProps = { documentData: DocumentData; fileName?: string; + /** + * Specifies which version of the document to download. + * 'signed': Downloads the signed version (default). + * 'original': Downloads the original version. + */ + version?: DocumentVersion; }; -export const downloadPDF = async ({ documentData, fileName }: DownloadPDFProps) => { - const bytes = await getFile(documentData); +export const downloadPDF = async ({ + documentData, + fileName, + version = 'signed', +}: DownloadPDFProps) => { + const bytes = await getFile({ + type: documentData.type, + data: version === 'signed' ? documentData.data : documentData.initialData, + }); const blob = new Blob([bytes], { type: 'application/pdf', }); const baseTitle = (fileName ?? 'document').replace(/\.pdf$/, ''); + const suffix = version === 'signed' ? '_signed.pdf' : '.pdf'; downloadFile({ - filename: `${baseTitle}_signed.pdf`, + filename: `${baseTitle}${suffix}`, data: blob, }); }; diff --git a/packages/ui/styles/theme.css b/packages/ui/styles/theme.css index facb8be4c..f82f2b626 100644 --- a/packages/ui/styles/theme.css +++ b/packages/ui/styles/theme.css @@ -230,7 +230,7 @@ scrollbar-gutter: stable; } -.custom-scrollbar::-webkit-scrollbar-track { +/* .custom-scrollbar::-webkit-scrollbar-track { border-radius: 10px; } @@ -242,7 +242,7 @@ .custom-scrollbar::-webkit-scrollbar-thumb:hover { background: rgb(100 116 139 / 0.5); -} +} */ /* Custom Swagger Dark Theme */ .swagger-dark-theme .swagger-ui {