diff --git a/.env.example b/.env.example index f21560ca3..c482c128e 100644 --- a/.env.example +++ b/.env.example @@ -74,6 +74,8 @@ NEXT_PRIVATE_MAILCHANNELS_DKIM_DOMAIN= NEXT_PRIVATE_MAILCHANNELS_DKIM_SELECTOR= # OPTIONAL: The private key to use for DKIM signing. NEXT_PRIVATE_MAILCHANNELS_DKIM_PRIVATE_KEY= +# OPTIONAL: Displays the maximum document upload limit to the user in MBs +NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT=5 # [[STRIPE]] NEXT_PRIVATE_STRIPE_API_KEY= diff --git a/apps/web/src/app/(dashboard)/documents/upload-document.tsx b/apps/web/src/app/(dashboard)/documents/upload-document.tsx index 65b95f9ec..444bd1db0 100644 --- a/apps/web/src/app/(dashboard)/documents/upload-document.tsx +++ b/apps/web/src/app/(dashboard)/documents/upload-document.tsx @@ -10,6 +10,7 @@ import { useSession } from 'next-auth/react'; import { useLimits } from '@documenso/ee/server-only/limits/provider/client'; import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics'; +import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT } from '@documenso/lib/constants/app'; import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data'; import { putFile } from '@documenso/lib/universal/upload/put-file'; import { TRPCClientError } from '@documenso/trpc/client'; @@ -96,6 +97,15 @@ export const UploadDocument = ({ className }: UploadDocumentProps) => { } }; + const onFileDropRejected = () => { + toast({ + title: 'Your document failed to upload.', + description: `File cannot be larger than ${APP_DOCUMENT_UPLOAD_SIZE_LIMIT}MB`, + duration: 5000, + variant: 'destructive', + }); + }; + return (
{ disabled={remaining.documents === 0 || !session?.user.emailVerified} disabledMessage={disabledMessage} onDrop={onFileDrop} + onDropRejected={onFileDropRejected} />
diff --git a/packages/lib/constants/app.ts b/packages/lib/constants/app.ts index 827fcef0a..a19d2bb0d 100644 --- a/packages/lib/constants/app.ts +++ b/packages/lib/constants/app.ts @@ -6,3 +6,6 @@ export const APP_FOLDER = IS_APP_MARKETING ? 'marketing' : 'web'; export const APP_BASE_URL = IS_APP_WEB ? process.env.NEXT_PUBLIC_WEBAPP_URL : process.env.NEXT_PUBLIC_MARKETING_URL; + +export const APP_DOCUMENT_UPLOAD_SIZE_LIMIT = + Number(process.env.NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT) || 50; diff --git a/packages/ui/primitives/document-dropzone.tsx b/packages/ui/primitives/document-dropzone.tsx index 21337956d..6caf6d040 100644 --- a/packages/ui/primitives/document-dropzone.tsx +++ b/packages/ui/primitives/document-dropzone.tsx @@ -5,6 +5,7 @@ import { motion } from 'framer-motion'; import { Plus } from 'lucide-react'; import { useDropzone } from 'react-dropzone'; +import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT } from '@documenso/lib/constants/app'; import { megabytesToBytes } from '@documenso/lib/universal/unit-convertions'; import { cn } from '../lib/utils'; @@ -89,6 +90,7 @@ export type DocumentDropzoneProps = { disabled?: boolean; disabledMessage?: string; onDrop?: (_file: File) => void | Promise; + onDropRejected?: () => void | Promise; type?: 'document' | 'template'; [key: string]: unknown; }; @@ -96,6 +98,7 @@ export type DocumentDropzoneProps = { export const DocumentDropzone = ({ className, onDrop, + onDropRejected, disabled, disabledMessage = 'You cannot upload documents at this time.', type = 'document', @@ -112,7 +115,12 @@ export const DocumentDropzone = ({ void onDrop(acceptedFile); } }, - maxSize: megabytesToBytes(50), + onDropRejected: () => { + if (onDropRejected) { + void onDropRejected(); + } + }, + maxSize: megabytesToBytes(APP_DOCUMENT_UPLOAD_SIZE_LIMIT), }); return ( @@ -175,7 +183,7 @@ export const DocumentDropzone = ({

- {disabled ? disabledMessage : 'Drag & drop your document here.'} + {disabled ? disabledMessage : 'Drag & drop your PDF here.'}

diff --git a/turbo.json b/turbo.json index b78d7c9d0..b0a7a0fc6 100644 --- a/turbo.json +++ b/turbo.json @@ -45,6 +45,7 @@ "NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID", "NEXT_PUBLIC_STRIPE_FREE_PLAN_ID", "NEXT_PUBLIC_DISABLE_SIGNUP", + "NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT", "NEXT_PRIVATE_DATABASE_URL", "NEXT_PRIVATE_DIRECT_DATABASE_URL", "NEXT_PRIVATE_GOOGLE_CLIENT_ID",