diff --git a/.vscode/settings.json b/.vscode/settings.json index 97d5d1948..82aa3c1a3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "typescript.tsdk": "node_modules/typescript/lib", "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "eslint.validate": ["typescript", "typescriptreact", "javascript", "javascriptreact"], "javascript.preferences.importModuleSpecifier": "non-relative", diff --git a/apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx b/apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx index 51f3f7c58..9910ef111 100644 --- a/apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx +++ b/apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx @@ -6,12 +6,13 @@ import { Download, Edit, Pencil } from 'lucide-react'; import { useSession } from 'next-auth/react'; import { match } from 'ts-pattern'; -import { downloadFile } from '@documenso/lib/client-only/download-pdf'; +import { downloadPDF } from '@documenso/lib/client-only/download-pdf'; import type { Document, Recipient, User } from '@documenso/prisma/client'; import { DocumentStatus, SigningStatus } from '@documenso/prisma/client'; import type { DocumentWithData } from '@documenso/prisma/types/document-with-data'; import { trpc as trpcClient } from '@documenso/trpc/client'; import { Button } from '@documenso/ui/primitives/button'; +import { useToast } from '@documenso/ui/primitives/use-toast'; export type DataTableActionButtonProps = { row: Document & { @@ -22,6 +23,7 @@ export type DataTableActionButtonProps = { export const DataTableActionButton = ({ row }: DataTableActionButtonProps) => { const { data: session } = useSession(); + const { toast } = useToast(); if (!session) { return null; @@ -37,25 +39,33 @@ export const DataTableActionButton = ({ row }: DataTableActionButtonProps) => { const isSigned = recipient?.signingStatus === SigningStatus.SIGNED; const onDownloadClick = async () => { - let document: DocumentWithData | null = null; + try { + let document: DocumentWithData | null = null; - if (!recipient) { - document = await trpcClient.document.getDocumentById.query({ - id: row.id, - }); - } else { - document = await trpcClient.document.getDocumentByToken.query({ - token: recipient.token, + if (!recipient) { + document = await trpcClient.document.getDocumentById.query({ + id: row.id, + }); + } else { + document = await trpcClient.document.getDocumentByToken.query({ + token: recipient.token, + }); + } + + const documentData = document?.documentData; + + if (!documentData) { + throw Error('No document available'); + } + + await downloadPDF({ documentData, fileName: row.title }); + } catch (err) { + toast({ + title: 'Something went wrong', + description: 'An error occurred while downloading your document.', + variant: 'destructive', }); } - - const documentData = document?.documentData; - - if (!documentData) { - return; - } - - await downloadFile({ documentData, fileName: row.title }); }; return match({ diff --git a/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx b/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx index e9a713d62..c95a49ff6 100644 --- a/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx +++ b/apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx @@ -17,7 +17,7 @@ import { } from 'lucide-react'; import { useSession } from 'next-auth/react'; -import { downloadFile } from '@documenso/lib/client-only/download-pdf'; +import { downloadPDF } from '@documenso/lib/client-only/download-pdf'; import type { Document, Recipient, User } from '@documenso/prisma/client'; import { DocumentStatus } from '@documenso/prisma/client'; import type { DocumentWithData } from '@documenso/prisma/types/document-with-data'; @@ -63,25 +63,33 @@ export const DataTableActionDropdown = ({ row }: DataTableActionDropdownProps) = const isDocumentDeletable = isOwner; const onDownloadClick = async () => { - let document: DocumentWithData | null = null; + try { + let document: DocumentWithData | null = null; - if (!recipient) { - document = await trpcClient.document.getDocumentById.query({ - id: row.id, - }); - } else { - document = await trpcClient.document.getDocumentByToken.query({ - token: recipient.token, + if (!recipient) { + document = await trpcClient.document.getDocumentById.query({ + id: row.id, + }); + } else { + document = await trpcClient.document.getDocumentByToken.query({ + token: recipient.token, + }); + } + + const documentData = document?.documentData; + + if (!documentData) { + return; + } + + await downloadPDF({ documentData, fileName: row.title }); + } catch (err) { + toast({ + title: 'Something went wrong', + description: 'An error occurred while downloading your document.', + variant: 'destructive', }); } - - const documentData = document?.documentData; - - if (!documentData) { - return; - } - - await downloadFile({ documentData, fileName: row.title }); }; const nonSignedRecipients = row.Recipient.filter((item) => item.signingStatus !== 'SIGNED'); diff --git a/packages/lib/client-only/download-pdf.ts b/packages/lib/client-only/download-pdf.ts index af304f983..e095002ee 100644 --- a/packages/lib/client-only/download-pdf.ts +++ b/packages/lib/client-only/download-pdf.ts @@ -1,5 +1,4 @@ import type { DocumentData } from '@documenso/prisma/client'; -import { toast } from '@documenso/ui/primitives/use-toast'; import { getFile } from '../universal/upload/get-file'; @@ -8,30 +7,20 @@ type DownloadPDFProps = { fileName?: string; }; -export const downloadFile = async ({ documentData, fileName }: DownloadPDFProps) => { - try { - const bytes = await getFile(documentData); +export const downloadPDF = async ({ documentData, fileName }: DownloadPDFProps) => { + const bytes = await getFile(documentData); - const blob = new Blob([bytes], { - type: 'application/pdf', - }); + const blob = new Blob([bytes], { + type: 'application/pdf', + }); - const link = window.document.createElement('a'); - const baseTitle = fileName?.includes('.pdf') ? fileName.split('.pdf')[0] : fileName; + const link = window.document.createElement('a'); + const baseTitle = fileName?.includes('.pdf') ? fileName.split('.pdf')[0] : fileName; - link.href = window.URL.createObjectURL(blob); - link.download = baseTitle ? `${baseTitle}_signed.pdf` : 'document.pdf'; + link.href = window.URL.createObjectURL(blob); + link.download = baseTitle ? `${baseTitle}_signed.pdf` : 'document.pdf'; - link.click(); + link.click(); - window.URL.revokeObjectURL(link.href); - } catch (err) { - console.error(err); - - toast({ - title: 'Something went wrong', - description: 'An error occurred while downloading your document.', - variant: 'destructive', - }); - } + window.URL.revokeObjectURL(link.href); }; diff --git a/packages/ui/components/document/document-download-button.tsx b/packages/ui/components/document/document-download-button.tsx index 9471611ff..ee41cc691 100644 --- a/packages/ui/components/document/document-download-button.tsx +++ b/packages/ui/components/document/document-download-button.tsx @@ -3,9 +3,10 @@ import type { HTMLAttributes } from 'react'; import { useState } from 'react'; +import { useToast } from '@/primitives/use-toast'; import { Download } from 'lucide-react'; -import { downloadFile } from '@documenso/lib/client-only/download-pdf'; +import { downloadPDF } from '@documenso/lib/client-only/download-pdf'; import type { DocumentData } from '@documenso/prisma/client'; import { Button } from '../../primitives/button'; @@ -24,17 +25,29 @@ export const DocumentDownloadButton = ({ ...props }: DownloadButtonProps) => { const [isLoading, setIsLoading] = useState(false); + const { toast } = useToast(); const onDownloadClick = async () => { - setIsLoading(true); + try { + setIsLoading(true); - if (!documentData) { - return; - } + if (!documentData) { + setIsLoading(false); + return; + } - await downloadFile({ documentData, fileName }).then(() => { + await downloadPDF({ documentData, fileName }).then(() => { + setIsLoading(false); + }); + } catch (err) { setIsLoading(false); - }); + + toast({ + title: 'Something went wrong', + description: 'An error occurred while downloading your document.', + variant: 'destructive', + }); + } }; return ( diff --git a/packages/ui/primitives/use-toast.ts b/packages/ui/primitives/use-toast.ts index 27f96aa29..093ec8bb5 100644 --- a/packages/ui/primitives/use-toast.ts +++ b/packages/ui/primitives/use-toast.ts @@ -1,8 +1,7 @@ // Inspired by react-hot-toast library import * as React from 'react'; -import type { ToastActionElement } from './toast'; -import { type ToastProps } from './toast'; +import type { ToastActionElement, ToastProps } from './toast'; const TOAST_LIMIT = 1; const TOAST_REMOVE_DELAY = 1000000;