From 594f3ec16aef83aac55cf1d954c18e29f1866ce2 Mon Sep 17 00:00:00 2001 From: Mythie Date: Fri, 20 Oct 2023 13:42:10 +1100 Subject: [PATCH] fix: move getFile to client side --- .../app/(marketing)/singleplayer/client.tsx | 11 +- .../documents/[id]/edit-document.tsx | 8 +- .../app/(dashboard)/documents/[id]/page.tsx | 9 +- .../src/app/(signing)/sign/[token]/page.tsx | 7 +- .../components/document/document-dialog.tsx | 10 +- packages/ui/primitives/pdf-viewer.tsx | 147 +++++++++++------- 6 files changed, 119 insertions(+), 73 deletions(-) diff --git a/apps/marketing/src/app/(marketing)/singleplayer/client.tsx b/apps/marketing/src/app/(marketing)/singleplayer/client.tsx index 4780200c0..747b77a15 100644 --- a/apps/marketing/src/app/(marketing)/singleplayer/client.tsx +++ b/apps/marketing/src/app/(marketing)/singleplayer/client.tsx @@ -8,7 +8,7 @@ import { useRouter } from 'next/navigation'; import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics'; import { base64 } from '@documenso/lib/universal/base64'; import { putFile } from '@documenso/lib/universal/upload/put-file'; -import { Field, Prisma, Recipient } from '@documenso/prisma/client'; +import { DocumentDataType, Field, Prisma, Recipient } from '@documenso/prisma/client'; import { Card, CardContent } from '@documenso/ui/primitives/card'; import { DocumentDropzone } from '@documenso/ui/primitives/document-dropzone'; import { AddFieldsFormPartial } from '@documenso/ui/primitives/document-flow/add-fields'; @@ -199,7 +199,14 @@ export const SinglePlayerClient = () => { {uploadedFile ? ( - + ) : ( diff --git a/apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx b/apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx index 7c30dc411..7684c9b64 100644 --- a/apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx +++ b/apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx @@ -4,7 +4,7 @@ import { useState } from 'react'; import { useRouter } from 'next/navigation'; -import { Field, Recipient, User } from '@documenso/prisma/client'; +import { DocumentData, Field, Recipient, User } from '@documenso/prisma/client'; import { DocumentWithData } from '@documenso/prisma/types/document-with-data'; import { cn } from '@documenso/ui/lib/utils'; import { Card, CardContent } from '@documenso/ui/primitives/card'; @@ -32,7 +32,7 @@ export type EditDocumentFormProps = { document: DocumentWithData; recipients: Recipient[]; fields: Field[]; - dataUrl: string; + documentData: DocumentData; }; type EditDocumentStep = 'signers' | 'fields' | 'subject'; @@ -43,7 +43,7 @@ export const EditDocumentForm = ({ recipients, fields, user: _user, - dataUrl, + documentData, }: EditDocumentFormProps) => { const { toast } = useToast(); const router = useRouter(); @@ -153,7 +153,7 @@ export const EditDocumentForm = ({ gradient > - + diff --git a/apps/web/src/app/(dashboard)/documents/[id]/page.tsx b/apps/web/src/app/(dashboard)/documents/[id]/page.tsx index d44ac2800..85e30012c 100644 --- a/apps/web/src/app/(dashboard)/documents/[id]/page.tsx +++ b/apps/web/src/app/(dashboard)/documents/[id]/page.tsx @@ -7,7 +7,6 @@ import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get- import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id'; import { getFieldsForDocument } from '@documenso/lib/server-only/field/get-fields-for-document'; import { getRecipientsForDocument } from '@documenso/lib/server-only/recipient/get-recipients-for-document'; -import { getFile } from '@documenso/lib/universal/upload/get-file'; import { DocumentStatus as InternalDocumentStatus } from '@documenso/prisma/client'; import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; @@ -43,10 +42,6 @@ export default async function DocumentPage({ params }: DocumentPageProps) { const { documentData } = document; - const documentDataUrl = await getFile(documentData) - .then((buffer) => Buffer.from(buffer).toString('base64')) - .then((data) => `data:application/pdf;base64,${data}`); - const [recipients, fields] = await Promise.all([ await getRecipientsForDocument({ documentId, @@ -90,13 +85,13 @@ export default async function DocumentPage({ params }: DocumentPageProps) { user={user} recipients={recipients} fields={fields} - dataUrl={documentDataUrl} + documentData={documentData} /> )} {document.status === InternalDocumentStatus.COMPLETED && (
- +
)} diff --git a/apps/web/src/app/(signing)/sign/[token]/page.tsx b/apps/web/src/app/(signing)/sign/[token]/page.tsx index 40a650afd..3841a2da6 100644 --- a/apps/web/src/app/(signing)/sign/[token]/page.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/page.tsx @@ -8,7 +8,6 @@ import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document import { viewedDocument } from '@documenso/lib/server-only/document/viewed-document'; import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-for-token'; import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token'; -import { getFile } from '@documenso/lib/universal/upload/get-file'; import { DocumentStatus, FieldType, SigningStatus } from '@documenso/prisma/client'; import { Card, CardContent } from '@documenso/ui/primitives/card'; import { ElementVisible } from '@documenso/ui/primitives/element-visible'; @@ -47,10 +46,6 @@ export default async function SigningPage({ params: { token } }: SigningPageProp const { documentData } = document; - const documentDataUrl = await getFile(documentData) - .then((buffer) => Buffer.from(buffer).toString('base64')) - .then((data) => `data:application/pdf;base64,${data}`); - const { user } = await getServerComponentSession(); if ( @@ -79,7 +74,7 @@ export default async function SigningPage({ params: { token } }: SigningPageProp gradient > - + diff --git a/packages/ui/components/document/document-dialog.tsx b/packages/ui/components/document/document-dialog.tsx index b76d54eeb..e90147806 100644 --- a/packages/ui/components/document/document-dialog.tsx +++ b/packages/ui/components/document/document-dialog.tsx @@ -5,8 +5,9 @@ import { useState } from 'react'; import * as DialogPrimitive from '@radix-ui/react-dialog'; import { X } from 'lucide-react'; -import { cn } from '@documenso/ui/lib/utils'; +import { DocumentDataType } from '@documenso/prisma/client'; +import { cn } from '../../lib/utils'; import { Dialog, DialogOverlay, DialogPortal } from '../../primitives/dialog'; import { LazyPDFViewerNoLoader } from '../../primitives/lazy-pdf-viewer'; @@ -40,7 +41,12 @@ export default function DocumentDialog({ document, ...props }: DocumentDialogPro > e.stopPropagation()} onDocumentLoad={onDocumentLoad} /> diff --git a/packages/ui/primitives/pdf-viewer.tsx b/packages/ui/primitives/pdf-viewer.tsx index 008e81f82..fb7b0d51a 100644 --- a/packages/ui/primitives/pdf-viewer.tsx +++ b/packages/ui/primitives/pdf-viewer.tsx @@ -9,8 +9,12 @@ import 'react-pdf/dist/esm/Page/AnnotationLayer.css'; import 'react-pdf/dist/esm/Page/TextLayer.css'; import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer'; +import { getFile } from '@documenso/lib/universal/upload/get-file'; +import { DocumentData } from '@documenso/prisma/client'; import { cn } from '@documenso/ui/lib/utils'; +import { useToast } from './use-toast'; + export type LoadedPDFDocument = PDFDocumentProxy; /** @@ -28,9 +32,17 @@ export type OnPDFViewerPageClick = (_event: { pageY: number; }) => void | Promise; +const PDFLoader = () => ( + <> + + +

Loading document...

+ +); + export type PDFViewerProps = { className?: string; - document: string; + documentData: DocumentData; onDocumentLoad?: (_doc: LoadedPDFDocument) => void; onPageClick?: OnPDFViewerPageClick; [key: string]: unknown; @@ -38,13 +50,18 @@ export type PDFViewerProps = { export const PDFViewer = ({ className, - document, + documentData, onDocumentLoad, onPageClick, ...props }: PDFViewerProps) => { + const { toast } = useToast(); + const $el = useRef(null); + const [isDocumentBytesLoading, setIsDocumentBytesLoading] = useState(false); + const [documentBytes, setDocumentBytes] = useState(null); + const [width, setWidth] = useState(0); const [numPages, setNumPages] = useState(0); const [pdfError, setPdfError] = useState(false); @@ -110,63 +127,89 @@ export const PDFViewer = ({ } }, []); + useEffect(() => { + const fetchDocumentBytes = async () => { + try { + setIsDocumentBytesLoading(true); + + const bytes = await getFile(documentData); + + setDocumentBytes(bytes); + + setIsDocumentBytesLoading(false); + } catch (err) { + console.error(err); + + toast({ + title: 'Error', + description: 'An error occurred while loading the document.', + variant: 'destructive', + }); + } + }; + + void fetchDocumentBytes(); + }, [documentData, toast]); + return (
- onDocumentLoaded(d)} - // Uploading a invalid document causes an error which doesn't appear to be handled by the `error` prop. - // Therefore we add some additional custom error handling. - onSourceError={() => { - setPdfError(true); - }} - externalLinkTarget="_blank" - loading={ -
- {pdfError ? ( + {isDocumentBytesLoading ? ( +
+ +
+ ) : ( + onDocumentLoaded(d)} + // Uploading a invalid document causes an error which doesn't appear to be handled by the `error` prop. + // Therefore we add some additional custom error handling. + onSourceError={() => { + setPdfError(true); + }} + externalLinkTarget="_blank" + loading={ +
+ {pdfError ? ( +
+

Something went wrong while loading the document.

+

Please try again or contact our support.

+
+ ) : ( + + )} +
+ } + error={ +

Something went wrong while loading the document.

Please try again or contact our support.

- ) : ( - <> - - -

Loading document...

- - )} -
- } - error={ -
-
-

Something went wrong while loading the document.

-

Please try again or contact our support.

-
- } - > - {Array(numPages) - .fill(null) - .map((_, i) => ( -
- ''} - onClick={(e) => onDocumentPageClick(e, i + 1)} - /> -
- ))} -
+ } + > + {Array(numPages) + .fill(null) + .map((_, i) => ( +
+ ''} + onClick={(e) => onDocumentPageClick(e, i + 1)} + /> +
+ ))} + + )}
); };