mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 17:21:41 +10:00
fix: update dropzone to create envelopes
This commit is contained in:
@ -1,10 +1,15 @@
|
|||||||
import { type ReactNode, useState } from 'react';
|
import { type ReactNode, useState } from 'react';
|
||||||
|
|
||||||
import { msg } from '@lingui/core/macro';
|
import { useLingui } from '@lingui/react/macro';
|
||||||
import { useLingui } from '@lingui/react';
|
|
||||||
import { Trans } from '@lingui/react/macro';
|
import { Trans } from '@lingui/react/macro';
|
||||||
|
import { EnvelopeType } from '@prisma/client';
|
||||||
import { Loader } from 'lucide-react';
|
import { Loader } from 'lucide-react';
|
||||||
import { ErrorCode, type FileRejection, useDropzone } from 'react-dropzone';
|
import {
|
||||||
|
ErrorCode as DropzoneErrorCode,
|
||||||
|
ErrorCode,
|
||||||
|
type FileRejection,
|
||||||
|
useDropzone,
|
||||||
|
} from 'react-dropzone';
|
||||||
import { Link, useNavigate, useParams } from 'react-router';
|
import { Link, useNavigate, useParams } from 'react-router';
|
||||||
import { match } from 'ts-pattern';
|
import { match } from 'ts-pattern';
|
||||||
|
|
||||||
@ -16,21 +21,26 @@ import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT, IS_BILLING_ENABLED } from '@documenso/l
|
|||||||
import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants/time-zones';
|
import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants/time-zones';
|
||||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||||
import { megabytesToBytes } from '@documenso/lib/universal/unit-convertions';
|
import { megabytesToBytes } from '@documenso/lib/universal/unit-convertions';
|
||||||
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
|
import { formatDocumentsPath, formatTemplatesPath } from '@documenso/lib/utils/teams';
|
||||||
import { trpc } from '@documenso/trpc/react';
|
import { trpc } from '@documenso/trpc/react';
|
||||||
import type { TCreateDocumentPayloadSchema } from '@documenso/trpc/server/document-router/create-document.types';
|
import type { TCreateEnvelopePayload } from '@documenso/trpc/server/envelope-router/create-envelope.types';
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||||
|
|
||||||
import { useCurrentTeam } from '~/providers/team';
|
import { useCurrentTeam } from '~/providers/team';
|
||||||
|
|
||||||
export interface DocumentDropZoneWrapperProps {
|
export interface EnvelopeDropZoneWrapperProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
|
type: EnvelopeType;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZoneWrapperProps) => {
|
export const EnvelopeDropZoneWrapper = ({
|
||||||
const { _ } = useLingui();
|
children,
|
||||||
|
type,
|
||||||
|
className,
|
||||||
|
}: EnvelopeDropZoneWrapperProps) => {
|
||||||
|
const { t } = useLingui();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { user } = useSession();
|
const { user } = useSession();
|
||||||
const { folderId } = useParams();
|
const { folderId } = useParams();
|
||||||
@ -47,13 +57,13 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon
|
|||||||
TIME_ZONES.find((timezone) => timezone === Intl.DateTimeFormat().resolvedOptions().timeZone) ??
|
TIME_ZONES.find((timezone) => timezone === Intl.DateTimeFormat().resolvedOptions().timeZone) ??
|
||||||
DEFAULT_DOCUMENT_TIME_ZONE;
|
DEFAULT_DOCUMENT_TIME_ZONE;
|
||||||
|
|
||||||
const { quota, remaining, refreshLimits } = useLimits();
|
const { quota, remaining, refreshLimits, maximumEnvelopeItemCount } = useLimits();
|
||||||
|
|
||||||
const { mutateAsync: createDocument } = trpc.document.create.useMutation();
|
const { mutateAsync: createEnvelope } = trpc.envelope.create.useMutation();
|
||||||
|
|
||||||
const isUploadDisabled = remaining.documents === 0 || !user.emailVerified;
|
const isUploadDisabled = remaining.documents === 0 || !user.emailVerified;
|
||||||
|
|
||||||
const onFileDrop = async (file: File) => {
|
const onFileDrop = async (files: File[]) => {
|
||||||
if (isUploadDisabled && IS_BILLING_ENABLED()) {
|
if (isUploadDisabled && IS_BILLING_ENABLED()) {
|
||||||
await navigate(`/o/${organisation.url}/settings/billing`);
|
await navigate(`/o/${organisation.url}/settings/billing`);
|
||||||
return;
|
return;
|
||||||
@ -63,51 +73,67 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
title: file.name,
|
folderId,
|
||||||
|
type,
|
||||||
|
title: files[0].name,
|
||||||
|
meta: {
|
||||||
timezone: userTimezone,
|
timezone: userTimezone,
|
||||||
folderId: folderId ?? undefined,
|
},
|
||||||
} satisfies TCreateDocumentPayloadSchema;
|
} satisfies TCreateEnvelopePayload;
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
formData.append('payload', JSON.stringify(payload));
|
formData.append('payload', JSON.stringify(payload));
|
||||||
formData.append('file', file);
|
|
||||||
|
|
||||||
const { envelopeId: id } = await createDocument(formData);
|
for (const file of files) {
|
||||||
|
formData.append('files', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id } = await createEnvelope(formData);
|
||||||
|
|
||||||
void refreshLimits();
|
void refreshLimits();
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: _(msg`Document uploaded`),
|
title: type === EnvelopeType.DOCUMENT ? t`Document uploaded` : t`Template uploaded`,
|
||||||
description: _(msg`Your document has been uploaded successfully.`),
|
description:
|
||||||
|
type === EnvelopeType.DOCUMENT
|
||||||
|
? t`Your document has been uploaded successfully.`
|
||||||
|
: t`Your template has been uploaded successfully.`,
|
||||||
duration: 5000,
|
duration: 5000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (type === EnvelopeType.DOCUMENT) {
|
||||||
analytics.capture('App: Document Uploaded', {
|
analytics.capture('App: Document Uploaded', {
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
documentId: id,
|
documentId: id,
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await navigate(`${formatDocumentsPath(team.url)}/${id}/edit`);
|
const pathPrefix =
|
||||||
|
type === EnvelopeType.DOCUMENT
|
||||||
|
? formatDocumentsPath(team.url)
|
||||||
|
: formatTemplatesPath(team.url);
|
||||||
|
|
||||||
|
await navigate(`${pathPrefix}/${id}/edit`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const error = AppError.parseError(err);
|
const error = AppError.parseError(err);
|
||||||
|
|
||||||
const errorMessage = match(error.code)
|
const errorMessage = match(error.code)
|
||||||
.with('INVALID_DOCUMENT_FILE', () => msg`You cannot upload encrypted PDFs`)
|
.with('INVALID_DOCUMENT_FILE', () => t`You cannot upload encrypted PDFs`)
|
||||||
.with(
|
.with(
|
||||||
AppErrorCode.LIMIT_EXCEEDED,
|
AppErrorCode.LIMIT_EXCEEDED,
|
||||||
() => msg`You have reached your document limit for this month. Please upgrade your plan.`,
|
() => t`You have reached your document limit for this month. Please upgrade your plan.`,
|
||||||
)
|
)
|
||||||
.with(
|
.with(
|
||||||
'ENVELOPE_ITEM_LIMIT_EXCEEDED',
|
'ENVELOPE_ITEM_LIMIT_EXCEEDED',
|
||||||
() => msg`You have reached the limit of the number of files per envelope`,
|
() => t`You have reached the limit of the number of files per envelope`,
|
||||||
)
|
)
|
||||||
.otherwise(() => msg`An error occurred while uploading your document.`);
|
.otherwise(() => t`An error occurred during upload.`);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: _(msg`Error`),
|
title: t`Error`,
|
||||||
description: _(errorMessage),
|
description: errorMessage,
|
||||||
variant: 'destructive',
|
variant: 'destructive',
|
||||||
duration: 7500,
|
duration: 7500,
|
||||||
});
|
});
|
||||||
@ -121,6 +147,20 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxItemsReached = fileRejections.some((fileRejection) =>
|
||||||
|
fileRejection.errors.some((error) => error.code === DropzoneErrorCode.TooManyFiles),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (maxItemsReached) {
|
||||||
|
toast({
|
||||||
|
title: t`You cannot upload more than ${maximumEnvelopeItemCount} items per envelope.`,
|
||||||
|
duration: 5000,
|
||||||
|
variant: 'destructive',
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Since users can only upload only one file (no multi-upload), we only handle the first file rejection
|
// Since users can only upload only one file (no multi-upload), we only handle the first file rejection
|
||||||
const { file, errors } = fileRejections[0];
|
const { file, errors } = fileRejections[0];
|
||||||
|
|
||||||
@ -155,7 +195,7 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon
|
|||||||
);
|
);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: _(msg`Upload failed`),
|
title: t`Upload failed`,
|
||||||
description,
|
description,
|
||||||
duration: 5000,
|
duration: 5000,
|
||||||
variant: 'destructive',
|
variant: 'destructive',
|
||||||
@ -165,17 +205,11 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon
|
|||||||
accept: {
|
accept: {
|
||||||
'application/pdf': ['.pdf'],
|
'application/pdf': ['.pdf'],
|
||||||
},
|
},
|
||||||
//disabled: isUploadDisabled,
|
multiple: true,
|
||||||
multiple: false,
|
|
||||||
maxSize: megabytesToBytes(APP_DOCUMENT_UPLOAD_SIZE_LIMIT),
|
maxSize: megabytesToBytes(APP_DOCUMENT_UPLOAD_SIZE_LIMIT),
|
||||||
onDrop: ([acceptedFile]) => {
|
maxFiles: maximumEnvelopeItemCount,
|
||||||
if (acceptedFile) {
|
onDrop: (files) => void onFileDrop(files),
|
||||||
void onFileDrop(acceptedFile);
|
onDropRejected: onFileDropRejected,
|
||||||
}
|
|
||||||
},
|
|
||||||
onDropRejected: (fileRejections) => {
|
|
||||||
onFileDropRejected(fileRejections);
|
|
||||||
},
|
|
||||||
noClick: true,
|
noClick: true,
|
||||||
noDragEventsBubbling: true,
|
noDragEventsBubbling: true,
|
||||||
});
|
});
|
||||||
@ -189,7 +223,11 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon
|
|||||||
<div className="bg-muted/60 fixed left-0 top-0 z-[9999] h-full w-full backdrop-blur-[4px]">
|
<div className="bg-muted/60 fixed left-0 top-0 z-[9999] h-full w-full backdrop-blur-[4px]">
|
||||||
<div className="pointer-events-none flex h-full w-full flex-col items-center justify-center">
|
<div className="pointer-events-none flex h-full w-full flex-col items-center justify-center">
|
||||||
<h2 className="text-foreground text-2xl font-semibold">
|
<h2 className="text-foreground text-2xl font-semibold">
|
||||||
|
{type === EnvelopeType.DOCUMENT ? (
|
||||||
<Trans>Upload Document</Trans>
|
<Trans>Upload Document</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans>Upload Template</Trans>
|
||||||
|
)}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p className="text-muted-foreground text-md mt-4">
|
<p className="text-muted-foreground text-md mt-4">
|
||||||
@ -224,7 +262,7 @@ export const DocumentDropZoneWrapper = ({ children, className }: DocumentDropZon
|
|||||||
<div className="pointer-events-none flex h-1/2 w-full flex-col items-center justify-center">
|
<div className="pointer-events-none flex h-1/2 w-full flex-col items-center justify-center">
|
||||||
<Loader className="text-primary h-12 w-12 animate-spin" />
|
<Loader className="text-primary h-12 w-12 animate-spin" />
|
||||||
<p className="text-foreground mt-8 font-medium">
|
<p className="text-foreground mt-8 font-medium">
|
||||||
<Trans>Uploading document...</Trans>
|
<Trans>Uploading</Trans>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -20,7 +20,7 @@ import { DocumentUploadButtonLegacy } from '~/components/general/document/docume
|
|||||||
import { FolderCard, FolderCardEmpty } from '~/components/general/folder/folder-card';
|
import { FolderCard, FolderCardEmpty } from '~/components/general/folder/folder-card';
|
||||||
import { useCurrentTeam } from '~/providers/team';
|
import { useCurrentTeam } from '~/providers/team';
|
||||||
|
|
||||||
import { EnvelopeUploadButton } from '../document/envelope-upload-button';
|
import { EnvelopeUploadButton } from '../envelope/envelope-upload-button';
|
||||||
|
|
||||||
export type FolderGridProps = {
|
export type FolderGridProps = {
|
||||||
type: FolderType;
|
type: FolderType;
|
||||||
|
|||||||
@ -1,171 +0,0 @@
|
|||||||
import { type ReactNode, useState } from 'react';
|
|
||||||
|
|
||||||
import { msg } from '@lingui/core/macro';
|
|
||||||
import { useLingui } from '@lingui/react';
|
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
import { Loader } from 'lucide-react';
|
|
||||||
import { ErrorCode, type FileRejection, useDropzone } from 'react-dropzone';
|
|
||||||
import { useNavigate, useParams } from 'react-router';
|
|
||||||
import { match } from 'ts-pattern';
|
|
||||||
|
|
||||||
import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT } from '@documenso/lib/constants/app';
|
|
||||||
import { megabytesToBytes } from '@documenso/lib/universal/unit-convertions';
|
|
||||||
import { formatTemplatesPath } from '@documenso/lib/utils/teams';
|
|
||||||
import { trpc } from '@documenso/trpc/react';
|
|
||||||
import type { TCreateTemplatePayloadSchema } from '@documenso/trpc/server/template-router/schema';
|
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
|
||||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
|
||||||
|
|
||||||
import { useCurrentTeam } from '~/providers/team';
|
|
||||||
|
|
||||||
export interface TemplateDropZoneWrapperProps {
|
|
||||||
children: ReactNode;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TemplateDropZoneWrapper = ({ children, className }: TemplateDropZoneWrapperProps) => {
|
|
||||||
const { _ } = useLingui();
|
|
||||||
const { toast } = useToast();
|
|
||||||
const { folderId } = useParams();
|
|
||||||
|
|
||||||
const team = useCurrentTeam();
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
const { mutateAsync: createTemplate } = trpc.template.createTemplate.useMutation();
|
|
||||||
|
|
||||||
const onFileDrop = async (file: File) => {
|
|
||||||
try {
|
|
||||||
setIsLoading(true);
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
title: file.name,
|
|
||||||
folderId: folderId ?? undefined,
|
|
||||||
} satisfies TCreateTemplatePayloadSchema;
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
formData.append('payload', JSON.stringify(payload));
|
|
||||||
formData.append('file', file);
|
|
||||||
|
|
||||||
const { envelopeId: id } = await createTemplate(formData);
|
|
||||||
|
|
||||||
toast({
|
|
||||||
title: _(msg`Template uploaded`),
|
|
||||||
description: _(
|
|
||||||
msg`Your template has been uploaded successfully. You will be redirected to the template page.`,
|
|
||||||
),
|
|
||||||
duration: 5000,
|
|
||||||
});
|
|
||||||
|
|
||||||
await navigate(`${formatTemplatesPath(team.url)}/${id}/edit`);
|
|
||||||
} catch {
|
|
||||||
toast({
|
|
||||||
title: _(msg`Something went wrong`),
|
|
||||||
description: _(msg`Please try again later.`),
|
|
||||||
variant: 'destructive',
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onFileDropRejected = (fileRejections: FileRejection[]) => {
|
|
||||||
if (!fileRejections.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since users can only upload only one file (no multi-upload), we only handle the first file rejection
|
|
||||||
const { file, errors } = fileRejections[0];
|
|
||||||
|
|
||||||
if (!errors.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorNodes = errors.map((error, index) => (
|
|
||||||
<span key={index} className="block">
|
|
||||||
{match(error.code)
|
|
||||||
.with(ErrorCode.FileTooLarge, () => (
|
|
||||||
<Trans>File is larger than {APP_DOCUMENT_UPLOAD_SIZE_LIMIT}MB</Trans>
|
|
||||||
))
|
|
||||||
.with(ErrorCode.FileInvalidType, () => <Trans>Only PDF files are allowed</Trans>)
|
|
||||||
.with(ErrorCode.FileTooSmall, () => <Trans>File is too small</Trans>)
|
|
||||||
.with(ErrorCode.TooManyFiles, () => (
|
|
||||||
<Trans>Only one file can be uploaded at a time</Trans>
|
|
||||||
))
|
|
||||||
.otherwise(() => (
|
|
||||||
<Trans>Unknown error</Trans>
|
|
||||||
))}
|
|
||||||
</span>
|
|
||||||
));
|
|
||||||
|
|
||||||
const description = (
|
|
||||||
<>
|
|
||||||
<span className="font-medium">
|
|
||||||
<Trans>{file.name} couldn't be uploaded:</Trans>
|
|
||||||
</span>
|
|
||||||
{errorNodes}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
toast({
|
|
||||||
title: _(msg`Upload failed`),
|
|
||||||
description,
|
|
||||||
duration: 5000,
|
|
||||||
variant: 'destructive',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
|
||||||
accept: {
|
|
||||||
'application/pdf': ['.pdf'],
|
|
||||||
},
|
|
||||||
//disabled: isUploadDisabled,
|
|
||||||
multiple: false,
|
|
||||||
maxSize: megabytesToBytes(APP_DOCUMENT_UPLOAD_SIZE_LIMIT),
|
|
||||||
onDrop: ([acceptedFile]) => {
|
|
||||||
if (acceptedFile) {
|
|
||||||
void onFileDrop(acceptedFile);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDropRejected: (fileRejections) => {
|
|
||||||
onFileDropRejected(fileRejections);
|
|
||||||
},
|
|
||||||
noClick: true,
|
|
||||||
noDragEventsBubbling: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div {...getRootProps()} className={cn('relative min-h-screen', className)}>
|
|
||||||
<input {...getInputProps()} />
|
|
||||||
{children}
|
|
||||||
|
|
||||||
{isDragActive && (
|
|
||||||
<div className="bg-muted/60 fixed left-0 top-0 z-[9999] h-full w-full backdrop-blur-[4px]">
|
|
||||||
<div className="pointer-events-none flex h-full w-full flex-col items-center justify-center">
|
|
||||||
<h2 className="text-foreground text-2xl font-semibold">
|
|
||||||
<Trans>Upload Template</Trans>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p className="text-muted-foreground text-md mt-4">
|
|
||||||
<Trans>Drag and drop your PDF file here</Trans>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{isLoading && (
|
|
||||||
<div className="bg-muted/30 absolute inset-0 z-50 backdrop-blur-[2px]">
|
|
||||||
<div className="pointer-events-none flex h-1/2 w-full flex-col items-center justify-center">
|
|
||||||
<Loader className="text-primary h-12 w-12 animate-spin" />
|
|
||||||
<p className="text-foreground mt-8 font-medium">
|
|
||||||
<Trans>Uploading template...</Trans>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { Trans } from '@lingui/react/macro';
|
import { Trans } from '@lingui/react/macro';
|
||||||
|
import { EnvelopeType } from '@prisma/client';
|
||||||
import { FolderType, OrganisationType } from '@prisma/client';
|
import { FolderType, OrganisationType } from '@prisma/client';
|
||||||
import { useParams, useSearchParams } from 'react-router';
|
import { useParams, useSearchParams } from 'react-router';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
@ -18,9 +19,9 @@ import { Avatar, AvatarFallback, AvatarImage } from '@documenso/ui/primitives/av
|
|||||||
import { Tabs, TabsList, TabsTrigger } from '@documenso/ui/primitives/tabs';
|
import { Tabs, TabsList, TabsTrigger } from '@documenso/ui/primitives/tabs';
|
||||||
|
|
||||||
import { DocumentMoveToFolderDialog } from '~/components/dialogs/document-move-to-folder-dialog';
|
import { DocumentMoveToFolderDialog } from '~/components/dialogs/document-move-to-folder-dialog';
|
||||||
import { DocumentDropZoneWrapper } from '~/components/general/document/document-drop-zone-wrapper';
|
|
||||||
import { DocumentSearch } from '~/components/general/document/document-search';
|
import { DocumentSearch } from '~/components/general/document/document-search';
|
||||||
import { DocumentStatus } from '~/components/general/document/document-status';
|
import { DocumentStatus } from '~/components/general/document/document-status';
|
||||||
|
import { EnvelopeDropZoneWrapper } from '~/components/general/envelope/envelope-drop-zone-wrapper';
|
||||||
import { FolderGrid } from '~/components/general/folder/folder-grid';
|
import { FolderGrid } from '~/components/general/folder/folder-grid';
|
||||||
import { PeriodSelector } from '~/components/general/period-selector';
|
import { PeriodSelector } from '~/components/general/period-selector';
|
||||||
import { DocumentsTable } from '~/components/tables/documents-table';
|
import { DocumentsTable } from '~/components/tables/documents-table';
|
||||||
@ -108,9 +109,8 @@ export default function DocumentsPage() {
|
|||||||
}
|
}
|
||||||
}, [data?.stats]);
|
}, [data?.stats]);
|
||||||
|
|
||||||
// Todo: Envelopes - Change the dropzone wrapper to create to V2 documents after we're ready.
|
|
||||||
return (
|
return (
|
||||||
<DocumentDropZoneWrapper>
|
<EnvelopeDropZoneWrapper type={EnvelopeType.DOCUMENT}>
|
||||||
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
|
<div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
|
||||||
<FolderGrid type={FolderType.DOCUMENT} parentId={folderId ?? null} />
|
<FolderGrid type={FolderType.DOCUMENT} parentId={folderId ?? null} />
|
||||||
|
|
||||||
@ -210,6 +210,6 @@ export default function DocumentsPage() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</DocumentDropZoneWrapper>
|
</EnvelopeDropZoneWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { Trans } from '@lingui/react/macro';
|
import { Trans } from '@lingui/react/macro';
|
||||||
|
import { EnvelopeType } from '@prisma/client';
|
||||||
import { Bird } from 'lucide-react';
|
import { Bird } from 'lucide-react';
|
||||||
import { useParams, useSearchParams } from 'react-router';
|
import { useParams, useSearchParams } from 'react-router';
|
||||||
|
|
||||||
@ -8,8 +9,8 @@ import { formatDocumentsPath, formatTemplatesPath } from '@documenso/lib/utils/t
|
|||||||
import { trpc } from '@documenso/trpc/react';
|
import { trpc } from '@documenso/trpc/react';
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from '@documenso/ui/primitives/avatar';
|
import { Avatar, AvatarFallback, AvatarImage } from '@documenso/ui/primitives/avatar';
|
||||||
|
|
||||||
|
import { EnvelopeDropZoneWrapper } from '~/components/general/envelope/envelope-drop-zone-wrapper';
|
||||||
import { FolderGrid } from '~/components/general/folder/folder-grid';
|
import { FolderGrid } from '~/components/general/folder/folder-grid';
|
||||||
import { TemplateDropZoneWrapper } from '~/components/general/template/template-drop-zone-wrapper';
|
|
||||||
import { TemplatesTable } from '~/components/tables/templates-table';
|
import { TemplatesTable } from '~/components/tables/templates-table';
|
||||||
import { useCurrentTeam } from '~/providers/team';
|
import { useCurrentTeam } from '~/providers/team';
|
||||||
import { appMetaTags } from '~/utils/meta';
|
import { appMetaTags } from '~/utils/meta';
|
||||||
@ -37,7 +38,7 @@ export default function TemplatesPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TemplateDropZoneWrapper>
|
<EnvelopeDropZoneWrapper type={EnvelopeType.TEMPLATE}>
|
||||||
<div className="mx-auto max-w-screen-xl px-4 md:px-8">
|
<div className="mx-auto max-w-screen-xl px-4 md:px-8">
|
||||||
<FolderGrid type={FolderType.TEMPLATE} parentId={folderId ?? null} />
|
<FolderGrid type={FolderType.TEMPLATE} parentId={folderId ?? null} />
|
||||||
|
|
||||||
@ -85,6 +86,6 @@ export default function TemplatesPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TemplateDropZoneWrapper>
|
</EnvelopeDropZoneWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user