mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 17:21:41 +10:00
chore: finalize template settings
Signed-off-by: Adithya Krishna <aadithya794@gmail.com>
This commit is contained in:
@ -1,16 +1,17 @@
|
|||||||
/* eslint-disable unused-imports/no-unused-imports */
|
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/consistent-type-imports */
|
|
||||||
|
|
||||||
/* eslint-disable unused-imports/no-unused-vars */
|
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
import type {
|
||||||
import type { DocumentData, Field, Recipient, Template, User } from '@documenso/prisma/client';
|
DocumentData,
|
||||||
|
Field,
|
||||||
|
Recipient,
|
||||||
|
Template,
|
||||||
|
TemplateDocumentMeta,
|
||||||
|
User,
|
||||||
|
} from '@documenso/prisma/client';
|
||||||
import { trpc } from '@documenso/trpc/react';
|
import { trpc } from '@documenso/trpc/react';
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
||||||
@ -26,13 +27,9 @@ import type { TAddTemplateFieldsFormSchema } from '@documenso/ui/primitives/temp
|
|||||||
import { AddTemplatePlaceholderRecipientsFormPartial } from '@documenso/ui/primitives/template-flow/add-template-placeholder-recipients';
|
import { AddTemplatePlaceholderRecipientsFormPartial } from '@documenso/ui/primitives/template-flow/add-template-placeholder-recipients';
|
||||||
import type { TAddTemplatePlacholderRecipientsFormSchema } from '@documenso/ui/primitives/template-flow/add-template-placeholder-recipients.types';
|
import type { TAddTemplatePlacholderRecipientsFormSchema } from '@documenso/ui/primitives/template-flow/add-template-placeholder-recipients.types';
|
||||||
import { AddTemplateSettingsFormPartial } from '@documenso/ui/primitives/template-flow/add-template-settings';
|
import { AddTemplateSettingsFormPartial } from '@documenso/ui/primitives/template-flow/add-template-settings';
|
||||||
import { TTemplateSettingsFormSchema } from '@documenso/ui/primitives/template-flow/add-template-settings.types';
|
import type { TTemplateSettingsFormSchema } from '@documenso/ui/primitives/template-flow/add-template-settings.types';
|
||||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||||
|
|
||||||
/* eslint-disable unused-imports/no-unused-imports */
|
|
||||||
/* eslint-disable @typescript-eslint/consistent-type-imports */
|
|
||||||
/* eslint-disable unused-imports/no-unused-vars */
|
|
||||||
|
|
||||||
export type EditTemplateFormProps = {
|
export type EditTemplateFormProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
user: User;
|
user: User;
|
||||||
@ -40,6 +37,7 @@ export type EditTemplateFormProps = {
|
|||||||
recipients: Recipient[];
|
recipients: Recipient[];
|
||||||
fields: Field[];
|
fields: Field[];
|
||||||
documentData: DocumentData;
|
documentData: DocumentData;
|
||||||
|
documentMeta: TemplateDocumentMeta | null;
|
||||||
templateRootPath: string;
|
templateRootPath: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,16 +52,17 @@ export const EditTemplateForm = ({
|
|||||||
user: _user,
|
user: _user,
|
||||||
documentData,
|
documentData,
|
||||||
templateRootPath,
|
templateRootPath,
|
||||||
|
documentMeta,
|
||||||
}: EditTemplateFormProps) => {
|
}: EditTemplateFormProps) => {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const [step, setStep] = useState<EditTemplateStep>('signers');
|
const [step, setStep] = useState<EditTemplateStep>('settings');
|
||||||
|
|
||||||
const documentFlow: Record<EditTemplateStep, DocumentFlowStep> = {
|
const documentFlow: Record<EditTemplateStep, DocumentFlowStep> = {
|
||||||
settings: {
|
settings: {
|
||||||
title: 'General',
|
title: 'Settings',
|
||||||
description: 'Configure general settings for the document.',
|
description: 'Configure general settings for the template.',
|
||||||
stepIndex: 1,
|
stepIndex: 1,
|
||||||
},
|
},
|
||||||
signers: {
|
signers: {
|
||||||
@ -82,6 +81,8 @@ export const EditTemplateForm = ({
|
|||||||
|
|
||||||
const { mutateAsync: addTemplateFields } = trpc.field.addTemplateFields.useMutation();
|
const { mutateAsync: addTemplateFields } = trpc.field.addTemplateFields.useMutation();
|
||||||
const { mutateAsync: addTemplateSigners } = trpc.recipient.addTemplateSigners.useMutation();
|
const { mutateAsync: addTemplateSigners } = trpc.recipient.addTemplateSigners.useMutation();
|
||||||
|
const { mutateAsync: setSettingsForTemplate } =
|
||||||
|
trpc.template.setSettingsForTemplate.useMutation();
|
||||||
|
|
||||||
const onAddTemplatePlaceholderFormSubmit = async (
|
const onAddTemplatePlaceholderFormSubmit = async (
|
||||||
data: TAddTemplatePlacholderRecipientsFormSchema,
|
data: TAddTemplatePlacholderRecipientsFormSchema,
|
||||||
@ -105,32 +106,28 @@ export const EditTemplateForm = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onAddTemplateSettingsFormSubmit = async (data: TTemplateSettingsFormSchema) => {
|
const onAddTemplateSettingsFormSubmit = async (data: TTemplateSettingsFormSchema) => {
|
||||||
// try {
|
try {
|
||||||
// const { timezone, dateFormat, redirectUrl } = data.meta;
|
const { subject, message, timezone, dateFormat, redirectUrl } = data.meta;
|
||||||
// await setSettingsForDocument({
|
await setSettingsForTemplate({
|
||||||
// documentId: document.id,
|
templateId: template.id,
|
||||||
// data: {
|
meta: {
|
||||||
// title: data.title,
|
subject,
|
||||||
// globalAccessAuth: data.globalAccessAuth ?? null,
|
message,
|
||||||
// globalActionAuth: data.globalActionAuth ?? null,
|
timezone,
|
||||||
// },
|
dateFormat,
|
||||||
// meta: {
|
redirectUrl,
|
||||||
// timezone,
|
},
|
||||||
// dateFormat,
|
});
|
||||||
// redirectUrl,
|
router.refresh();
|
||||||
// },
|
setStep('signers');
|
||||||
// });
|
} catch (err) {
|
||||||
// // Router refresh is here to clear the router cache for when navigating to /documents.
|
console.error(err);
|
||||||
// router.refresh();
|
toast({
|
||||||
// setStep('signers');
|
title: 'Error',
|
||||||
// } catch (err) {
|
description: 'An error occurred while updating the template settings.',
|
||||||
// console.error(err);
|
variant: 'destructive',
|
||||||
// toast({
|
});
|
||||||
// title: 'Error',
|
}
|
||||||
// description: 'An error occurred while updating the document settings.',
|
|
||||||
// variant: 'destructive',
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAddFieldsFormSubmit = async (data: TAddTemplateFieldsFormSchema) => {
|
const onAddFieldsFormSubmit = async (data: TAddTemplateFieldsFormSchema) => {
|
||||||
@ -182,11 +179,12 @@ export const EditTemplateForm = ({
|
|||||||
setCurrentStep={(step) => setStep(EditTemplateSteps[step - 1])}
|
setCurrentStep={(step) => setStep(EditTemplateSteps[step - 1])}
|
||||||
>
|
>
|
||||||
<AddTemplateSettingsFormPartial
|
<AddTemplateSettingsFormPartial
|
||||||
|
template={template}
|
||||||
key={recipients.length}
|
key={recipients.length}
|
||||||
documentFlow={documentFlow.signers}
|
documentFlow={documentFlow.settings}
|
||||||
recipients={recipients}
|
recipients={recipients}
|
||||||
fields={fields}
|
|
||||||
onSubmit={onAddTemplateSettingsFormSubmit}
|
onSubmit={onAddTemplateSettingsFormSubmit}
|
||||||
|
documentMeta={documentMeta}
|
||||||
/>
|
/>
|
||||||
<AddTemplatePlaceholderRecipientsFormPartial
|
<AddTemplatePlaceholderRecipientsFormPartial
|
||||||
key={recipients.length}
|
key={recipients.length}
|
||||||
|
|||||||
@ -79,7 +79,7 @@ export const TemplatePageView = async ({ params, team }: TemplatePageViewProps)
|
|||||||
recipients={templateRecipients}
|
recipients={templateRecipients}
|
||||||
fields={templateFields}
|
fields={templateFields}
|
||||||
documentData={templateDocumentData}
|
documentData={templateDocumentData}
|
||||||
documemntMeta={templateDocumentMeta}
|
documentMeta={templateDocumentMeta}
|
||||||
templateRootPath={templateRootPath}
|
templateRootPath={templateRootPath}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -21,6 +21,14 @@ export const upsertTemplateDocumentMeta = async ({
|
|||||||
password,
|
password,
|
||||||
redirectUrl,
|
redirectUrl,
|
||||||
}: CreateTemplateDocumentMetaOptions) => {
|
}: CreateTemplateDocumentMetaOptions) => {
|
||||||
|
const templateDocumentMeta = await prisma.templateDocumentMeta.findFirstOrThrow({
|
||||||
|
where: {
|
||||||
|
templateId: templateId,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
template: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
return await prisma.$transaction(async (tx) => {
|
return await prisma.$transaction(async (tx) => {
|
||||||
const upsertedTemplateDocumentMeta = await tx.templateDocumentMeta.upsert({
|
const upsertedTemplateDocumentMeta = await tx.templateDocumentMeta.upsert({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { TRPCError } from '@trpc/server';
|
import { TRPCError } from '@trpc/server';
|
||||||
|
|
||||||
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
|
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
|
||||||
|
import { upsertTemplateDocumentMeta } from '@documenso/lib/server-only/template-document-meta/upsert-template-document-meta';
|
||||||
import { createDocumentFromTemplate } from '@documenso/lib/server-only/template/create-document-from-template';
|
import { createDocumentFromTemplate } from '@documenso/lib/server-only/template/create-document-from-template';
|
||||||
import { createTemplate } from '@documenso/lib/server-only/template/create-template';
|
import { createTemplate } from '@documenso/lib/server-only/template/create-template';
|
||||||
import { deleteTemplate } from '@documenso/lib/server-only/template/delete-template';
|
import { deleteTemplate } from '@documenso/lib/server-only/template/delete-template';
|
||||||
@ -12,6 +13,7 @@ import {
|
|||||||
ZCreateTemplateMutationSchema,
|
ZCreateTemplateMutationSchema,
|
||||||
ZDeleteTemplateMutationSchema,
|
ZDeleteTemplateMutationSchema,
|
||||||
ZDuplicateTemplateMutationSchema,
|
ZDuplicateTemplateMutationSchema,
|
||||||
|
ZSetSettingsForTemplateMutationSchema,
|
||||||
} from './schema';
|
} from './schema';
|
||||||
|
|
||||||
export const templateRouter = router({
|
export const templateRouter = router({
|
||||||
@ -104,4 +106,27 @@ export const templateRouter = router({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
setSettingsForTemplate: authenticatedProcedure
|
||||||
|
.input(ZSetSettingsForTemplateMutationSchema)
|
||||||
|
.mutation(async ({ input }) => {
|
||||||
|
try {
|
||||||
|
const { meta, templateId } = input;
|
||||||
|
|
||||||
|
return await upsertTemplateDocumentMeta({
|
||||||
|
templateId,
|
||||||
|
subject: meta.subject,
|
||||||
|
message: meta.message,
|
||||||
|
dateFormat: meta.dateFormat,
|
||||||
|
timezone: meta.timezone,
|
||||||
|
redirectUrl: meta.redirectUrl,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
|
||||||
|
throw new TRPCError({
|
||||||
|
code: 'BAD_REQUEST',
|
||||||
|
message: 'We were unable to set template settings. Please try again later.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { URL_REGEX } from '@documenso/lib/constants/url-regex';
|
||||||
import { RecipientRole } from '@documenso/prisma/client';
|
import { RecipientRole } from '@documenso/prisma/client';
|
||||||
|
|
||||||
export const ZCreateTemplateMutationSchema = z.object({
|
export const ZCreateTemplateMutationSchema = z.object({
|
||||||
@ -22,6 +23,22 @@ export const ZCreateDocumentFromTemplateMutationSchema = z.object({
|
|||||||
.optional(),
|
.optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const ZSetSettingsForTemplateMutationSchema = z.object({
|
||||||
|
templateId: z.number(),
|
||||||
|
meta: z.object({
|
||||||
|
subject: z.string().optional(),
|
||||||
|
message: z.string().optional(),
|
||||||
|
timezone: z.string().optional(),
|
||||||
|
dateFormat: z.string().optional(),
|
||||||
|
redirectUrl: z
|
||||||
|
.string()
|
||||||
|
.optional()
|
||||||
|
.refine((value) => value === undefined || value === '' || URL_REGEX.test(value), {
|
||||||
|
message: 'Please enter a valid URL',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
export const ZDuplicateTemplateMutationSchema = z.object({
|
export const ZDuplicateTemplateMutationSchema = z.object({
|
||||||
templateId: z.number(),
|
templateId: z.number(),
|
||||||
teamId: z.number().optional(),
|
teamId: z.number().optional(),
|
||||||
|
|||||||
@ -7,11 +7,9 @@ import { InfoIcon } from 'lucide-react';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
|
|
||||||
import { DATE_FORMATS, DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats';
|
import { DATE_FORMATS, DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats';
|
||||||
import { DOCUMENT_AUTH_TYPES } from '@documenso/lib/constants/document-auth';
|
|
||||||
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 { DocumentAccessAuth, DocumentActionAuth } from '@documenso/lib/types/document-auth';
|
import type { Template, TemplateDocumentMeta } from '@documenso/prisma/client';
|
||||||
import { DocumentStatus, type Field, type Recipient, SendStatus } from '@documenso/prisma/client';
|
import { type Recipient, SendStatus } from '@documenso/prisma/client';
|
||||||
import type { DocumentWithData } from '@documenso/prisma/types/document-with-data';
|
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionContent,
|
AccordionContent,
|
||||||
@ -32,47 +30,42 @@ import {
|
|||||||
DocumentFlowFormContainerActions,
|
DocumentFlowFormContainerActions,
|
||||||
DocumentFlowFormContainerContent,
|
DocumentFlowFormContainerContent,
|
||||||
DocumentFlowFormContainerFooter,
|
DocumentFlowFormContainerFooter,
|
||||||
DocumentFlowFormContainerHeader,
|
|
||||||
DocumentFlowFormContainerStep,
|
DocumentFlowFormContainerStep,
|
||||||
} from '../document-flow/document-flow-root';
|
} from '../document-flow/document-flow-root';
|
||||||
import { ShowFieldItem } from '../document-flow/show-field-item';
|
|
||||||
import type { DocumentFlowStep } from '../document-flow/types';
|
import type { DocumentFlowStep } from '../document-flow/types';
|
||||||
import { Input } from '../input';
|
import { Input } from '../input';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../select';
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../select';
|
||||||
import { useStep } from '../stepper';
|
import { useStep } from '../stepper';
|
||||||
|
import { Textarea } from '../textarea';
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip';
|
import { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip';
|
||||||
import type { TTemplateSettingsFormSchema } from './add-template-settings.types';
|
import type { TTemplateSettingsFormSchema } from './add-template-settings.types';
|
||||||
import { ZTemplateSettingsFormSchema } from './add-template-settings.types';
|
import { ZTemplateSettingsFormSchema } from './add-template-settings.types';
|
||||||
|
|
||||||
export type AddSettingsFormProps = {
|
export type AddSettingsFormProps = {
|
||||||
|
template: Template;
|
||||||
documentFlow: DocumentFlowStep;
|
documentFlow: DocumentFlowStep;
|
||||||
recipients: Recipient[];
|
recipients: Recipient[];
|
||||||
fields: Field[];
|
documentMeta: TemplateDocumentMeta | null;
|
||||||
isDocumentEnterprise: boolean;
|
|
||||||
isDocumentPdfLoaded: boolean;
|
|
||||||
document: DocumentWithData;
|
|
||||||
onSubmit: (_data: TTemplateSettingsFormSchema) => void;
|
onSubmit: (_data: TTemplateSettingsFormSchema) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AddTemplateSettingsFormPartial = ({
|
export const AddTemplateSettingsFormPartial = ({
|
||||||
documentFlow,
|
documentFlow,
|
||||||
recipients,
|
recipients,
|
||||||
fields,
|
documentMeta,
|
||||||
isDocumentEnterprise,
|
template,
|
||||||
isDocumentPdfLoaded,
|
|
||||||
document,
|
|
||||||
onSubmit,
|
onSubmit,
|
||||||
}: AddSettingsFormProps) => {
|
}: AddSettingsFormProps) => {
|
||||||
const form = useForm<TTemplateSettingsFormSchema>({
|
const form = useForm<TTemplateSettingsFormSchema>({
|
||||||
resolver: zodResolver(ZTemplateSettingsFormSchema),
|
resolver: zodResolver(ZTemplateSettingsFormSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
title: document.title,
|
title: template.title,
|
||||||
globalAccessAuth: documentAuthOption?.globalAccessAuth || undefined,
|
|
||||||
globalActionAuth: documentAuthOption?.globalActionAuth || undefined,
|
|
||||||
meta: {
|
meta: {
|
||||||
timezone: document.documentMeta?.timezone ?? DEFAULT_DOCUMENT_TIME_ZONE,
|
subject: documentMeta?.subject ?? '',
|
||||||
dateFormat: document.documentMeta?.dateFormat ?? DEFAULT_DOCUMENT_DATE_FORMAT,
|
message: documentMeta?.message ?? '',
|
||||||
redirectUrl: document.documentMeta?.redirectUrl ?? '',
|
timezone: documentMeta?.timezone ?? DEFAULT_DOCUMENT_TIME_ZONE,
|
||||||
|
dateFormat: documentMeta?.dateFormat ?? DEFAULT_DOCUMENT_DATE_FORMAT,
|
||||||
|
redirectUrl: documentMeta?.redirectUrl ?? '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -83,8 +76,6 @@ export const AddTemplateSettingsFormPartial = ({
|
|||||||
(recipient) => recipient.sendStatus === SendStatus.SENT,
|
(recipient) => recipient.sendStatus === SendStatus.SENT,
|
||||||
);
|
);
|
||||||
|
|
||||||
// We almost always want to set the timezone to the user's local timezone to avoid confusion
|
|
||||||
// when the document is signed.
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!form.formState.touchedFields.meta?.timezone && !documentHasBeenSent) {
|
if (!form.formState.touchedFields.meta?.timezone && !documentHasBeenSent) {
|
||||||
form.setValue('meta.timezone', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
form.setValue('meta.timezone', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
||||||
@ -93,17 +84,7 @@ export const AddTemplateSettingsFormPartial = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DocumentFlowFormContainerHeader
|
|
||||||
title={documentFlow.title}
|
|
||||||
description={documentFlow.description}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<DocumentFlowFormContainerContent>
|
<DocumentFlowFormContainerContent>
|
||||||
{isDocumentPdfLoaded &&
|
|
||||||
fields.map((field, index) => (
|
|
||||||
<ShowFieldItem key={index} field={field} recipients={recipients} />
|
|
||||||
))}
|
|
||||||
|
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<fieldset
|
<fieldset
|
||||||
className="flex h-full flex-col space-y-6"
|
className="flex h-full flex-col space-y-6"
|
||||||
@ -115,144 +96,14 @@ export const AddTemplateSettingsFormPartial = ({
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel required>Title</FormLabel>
|
<FormLabel required>Title</FormLabel>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input className="bg-background" {...field} disabled={field.disabled} />
|
||||||
className="bg-background"
|
|
||||||
{...field}
|
|
||||||
disabled={document.status !== DocumentStatus.DRAFT || field.disabled}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="globalAccessAuth"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel className="flex flex-row items-center">
|
|
||||||
Document access
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
|
||||||
</TooltipTrigger>
|
|
||||||
|
|
||||||
<TooltipContent className="text-foreground max-w-md space-y-2 p-4">
|
|
||||||
<h2>
|
|
||||||
<strong>Document access</strong>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>The authentication required for recipients to view the document.</p>
|
|
||||||
|
|
||||||
<ul className="ml-3.5 list-outside list-disc space-y-0.5 py-2">
|
|
||||||
<li>
|
|
||||||
<strong>Require account</strong> - The recipient must be signed in to
|
|
||||||
view the document
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>None</strong> - The document can be accessed directly by the URL
|
|
||||||
sent to the recipient
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<FormControl>
|
|
||||||
<Select {...field} onValueChange={field.onChange}>
|
|
||||||
<SelectTrigger className="bg-background text-muted-foreground">
|
|
||||||
<SelectValue data-testid="documentAccessSelectValue" placeholder="None" />
|
|
||||||
</SelectTrigger>
|
|
||||||
|
|
||||||
<SelectContent position="popper">
|
|
||||||
{Object.values(DocumentAccessAuth).map((authType) => (
|
|
||||||
<SelectItem key={authType} value={authType}>
|
|
||||||
{DOCUMENT_AUTH_TYPES[authType].value}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{/* Note: -1 is remapped in the Zod schema to the required value. */}
|
|
||||||
<SelectItem value={'-1'}>None</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{isDocumentEnterprise && (
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="globalActionAuth"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel className="flex flex-row items-center">
|
|
||||||
Recipient action authentication
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
|
||||||
</TooltipTrigger>
|
|
||||||
|
|
||||||
<TooltipContent className="text-foreground max-w-md space-y-2 p-4">
|
|
||||||
<h2>
|
|
||||||
<strong>Global recipient action authentication</strong>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The authentication required for recipients to sign the signature field.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This can be overriden by setting the authentication requirements
|
|
||||||
directly on each recipient in the next step.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul className="ml-3.5 list-outside list-disc space-y-0.5 py-2">
|
|
||||||
<li>
|
|
||||||
<strong>Require account</strong> - The recipient must be signed in
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Require passkey</strong> - The recipient must have an account
|
|
||||||
and passkey configured via their settings
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Require 2FA</strong> - The recipient must have an account and
|
|
||||||
2FA enabled via their settings
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>None</strong> - No authentication required
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</FormLabel>
|
|
||||||
|
|
||||||
<FormControl>
|
|
||||||
<Select {...field} onValueChange={field.onChange}>
|
|
||||||
<SelectTrigger className="bg-background text-muted-foreground">
|
|
||||||
<SelectValue data-testid="documentActionSelectValue" placeholder="None" />
|
|
||||||
</SelectTrigger>
|
|
||||||
|
|
||||||
<SelectContent position="popper">
|
|
||||||
{Object.values(DocumentActionAuth).map((authType) => (
|
|
||||||
<SelectItem key={authType} value={authType}>
|
|
||||||
{DOCUMENT_AUTH_TYPES[authType].value}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{/* Note: -1 is remapped in the Zod schema to the required value. */}
|
|
||||||
<SelectItem value={'-1'}>None</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Accordion type="multiple" className="mt-6">
|
<Accordion type="multiple" className="mt-6">
|
||||||
<AccordionItem value="advanced-options" className="border-none">
|
<AccordionItem value="advanced-options" className="border-none">
|
||||||
<AccordionTrigger className="text-foreground mb-2 rounded border px-3 py-2 text-left hover:bg-neutral-200/30 hover:no-underline">
|
<AccordionTrigger className="text-foreground mb-2 rounded border px-3 py-2 text-left hover:bg-neutral-200/30 hover:no-underline">
|
||||||
@ -293,6 +144,67 @@ export const AddTemplateSettingsFormPartial = ({
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="meta.subject"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel className="flex flex-row items-center">
|
||||||
|
Subject{' '}
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
|
</TooltipTrigger>
|
||||||
|
|
||||||
|
<TooltipContent className="text-muted-foreground max-w-xs">
|
||||||
|
Add email subject
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</FormLabel>
|
||||||
|
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
id="subject"
|
||||||
|
className="bg-background mt-2"
|
||||||
|
disabled={field.disabled}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="meta.message"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel className="flex flex-row items-center">
|
||||||
|
Message{' '}
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
|
</TooltipTrigger>
|
||||||
|
|
||||||
|
<TooltipContent className="text-muted-foreground max-w-xs">
|
||||||
|
Add message to send in the email
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</FormLabel>
|
||||||
|
|
||||||
|
<FormControl>
|
||||||
|
<Textarea
|
||||||
|
id="message"
|
||||||
|
className="bg-background mt-2 h-24 resize-none"
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="meta.timezone"
|
name="meta.timezone"
|
||||||
|
|||||||
@ -28,6 +28,8 @@ export const ZTemplateSettingsFormSchema = z.object({
|
|||||||
ZDocumentActionAuthTypesSchema.optional(),
|
ZDocumentActionAuthTypesSchema.optional(),
|
||||||
),
|
),
|
||||||
meta: z.object({
|
meta: z.object({
|
||||||
|
subject: z.string().optional(),
|
||||||
|
message: z.string().optional(),
|
||||||
timezone: z.string().optional().default(DEFAULT_DOCUMENT_TIME_ZONE),
|
timezone: z.string().optional().default(DEFAULT_DOCUMENT_TIME_ZONE),
|
||||||
dateFormat: z.string().optional().default(DEFAULT_DOCUMENT_DATE_FORMAT),
|
dateFormat: z.string().optional().default(DEFAULT_DOCUMENT_DATE_FORMAT),
|
||||||
redirectUrl: z
|
redirectUrl: z
|
||||||
|
|||||||
Reference in New Issue
Block a user