mirror of
https://github.com/documenso/documenso.git
synced 2025-11-18 10:42:01 +10:00
feat: add signature configurations (#1710)
Add ability to enable or disable allowed signature types: - Drawn - Typed - Uploaded **Tabbed style signature dialog**  **Document settings**  **Team preferences**  ## Changes Made - Add multiselect to select allowed signatures in document and templates settings tab - Add multiselect to select allowed signatures in teams preferences - Removed "Enable typed signatures" from document/template edit page - Refactored signature pad to use tabs instead of an all in one signature pad ## Testing Performed Added E2E tests to check settings are applied correctly for documents and templates
This commit is contained in:
@ -54,10 +54,9 @@ import { Popover, PopoverContent, PopoverTrigger } from '@documenso/ui/primitive
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { getSignerColorStyles, useSignerColors } from '../../lib/signer-colors';
|
||||
import { Checkbox } from '../checkbox';
|
||||
import type { FieldFormType } from '../document-flow/add-fields';
|
||||
import { FieldAdvancedSettings } from '../document-flow/field-item-advanced-settings';
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel } from '../form/form';
|
||||
import { Form } from '../form/form';
|
||||
import { useStep } from '../stepper';
|
||||
import type { TAddTemplateFieldsFormSchema } from './add-template-fields.types';
|
||||
|
||||
@ -74,7 +73,6 @@ export type AddTemplateFieldsFormProps = {
|
||||
fields: Field[];
|
||||
onSubmit: (_data: TAddTemplateFieldsFormSchema) => void;
|
||||
teamId?: number;
|
||||
typedSignatureEnabled?: boolean;
|
||||
};
|
||||
|
||||
export const AddTemplateFieldsFormPartial = ({
|
||||
@ -84,7 +82,6 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
fields,
|
||||
onSubmit,
|
||||
teamId,
|
||||
typedSignatureEnabled,
|
||||
}: AddTemplateFieldsFormProps) => {
|
||||
const { _ } = useLingui();
|
||||
const { toast } = useToast();
|
||||
@ -119,7 +116,6 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
recipients.find((recipient) => recipient.id === field.recipientId)?.token ?? '',
|
||||
fieldMeta: field.fieldMeta ? ZFieldMetaSchema.parse(field.fieldMeta) : undefined,
|
||||
})),
|
||||
typedSignatureEnabled: typedSignatureEnabled ?? false,
|
||||
},
|
||||
});
|
||||
|
||||
@ -483,12 +479,6 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
form.setValue('fields', updatedFields);
|
||||
};
|
||||
|
||||
const isTypedSignatureEnabled = form.watch('typedSignatureEnabled');
|
||||
|
||||
const handleTypedSignatureChange = (value: boolean) => {
|
||||
form.setValue('typedSignatureEnabled', value, { shouldDirty: true });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{showAdvancedSettings && currentField ? (
|
||||
@ -662,31 +652,6 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
)}
|
||||
|
||||
<Form {...form}>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="typedSignatureEnabled"
|
||||
render={({ field: { value, ...field } }) => (
|
||||
<FormItem className="mb-6 flex flex-row items-center space-x-2 space-y-0">
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
{...field}
|
||||
id="typedSignatureEnabled"
|
||||
checked={value}
|
||||
onCheckedChange={(checked) => field.onChange(checked)}
|
||||
disabled={form.formState.isSubmitting}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormLabel
|
||||
htmlFor="typedSignatureEnabled"
|
||||
className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
>
|
||||
<Trans>Enable Typed Signatures</Trans>
|
||||
</FormLabel>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="-mx-2 flex-1 overflow-y-auto px-2">
|
||||
<fieldset className="my-2 grid grid-cols-3 gap-4">
|
||||
<button
|
||||
|
||||
@ -20,7 +20,6 @@ export const ZAddTemplateFieldsFormSchema = z.object({
|
||||
fieldMeta: ZFieldMetaSchema,
|
||||
}),
|
||||
),
|
||||
typedSignatureEnabled: z.boolean(),
|
||||
});
|
||||
|
||||
export type TAddTemplateFieldsFormSchema = z.infer<typeof ZAddTemplateFieldsFormSchema>;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { DocumentVisibility, TeamMemberRole } from '@prisma/client';
|
||||
import { DocumentDistributionMethod, type Field, type Recipient } from '@prisma/client';
|
||||
@ -10,12 +10,16 @@ import { useForm } from 'react-hook-form';
|
||||
import { match } from 'ts-pattern';
|
||||
|
||||
import { DATE_FORMATS, DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats';
|
||||
import { DOCUMENT_DISTRIBUTION_METHODS } from '@documenso/lib/constants/document';
|
||||
import {
|
||||
DOCUMENT_DISTRIBUTION_METHODS,
|
||||
DOCUMENT_SIGNATURE_TYPES,
|
||||
} from '@documenso/lib/constants/document';
|
||||
import { SUPPORTED_LANGUAGES } from '@documenso/lib/constants/i18n';
|
||||
import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants/time-zones';
|
||||
import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';
|
||||
import type { TTemplate } from '@documenso/lib/types/template';
|
||||
import { extractDocumentAuthMethods } from '@documenso/lib/utils/document-auth';
|
||||
import { extractTeamSignatureSettings } from '@documenso/lib/utils/teams';
|
||||
import type { TDocumentMetaDateFormat } from '@documenso/trpc/server/document-router/schema';
|
||||
import {
|
||||
DocumentGlobalAuthAccessSelect,
|
||||
@ -46,6 +50,7 @@ import {
|
||||
} from '@documenso/ui/primitives/form/form';
|
||||
|
||||
import { DocumentEmailCheckboxes } from '../../components/document/document-email-checkboxes';
|
||||
import { DocumentSignatureSettingsTooltip } from '../../components/document/document-signature-settings-tooltip';
|
||||
import { Combobox } from '../combobox';
|
||||
import {
|
||||
DocumentFlowFormContainerActions,
|
||||
@ -57,6 +62,7 @@ import {
|
||||
import { ShowFieldItem } from '../document-flow/show-field-item';
|
||||
import type { DocumentFlowStep } from '../document-flow/types';
|
||||
import { Input } from '../input';
|
||||
import { MultiSelectCombobox } from '../multi-select-combobox';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../select';
|
||||
import { useStep } from '../stepper';
|
||||
import { Textarea } from '../textarea';
|
||||
@ -85,7 +91,7 @@ export const AddTemplateSettingsFormPartial = ({
|
||||
currentTeamMemberRole,
|
||||
onSubmit,
|
||||
}: AddTemplateSettingsFormProps) => {
|
||||
const { _ } = useLingui();
|
||||
const { t, i18n } = useLingui();
|
||||
|
||||
const { documentAuthOption } = extractDocumentAuthMethods({
|
||||
documentAuth: template.authOptions,
|
||||
@ -111,6 +117,7 @@ export const AddTemplateSettingsFormPartial = ({
|
||||
redirectUrl: template.templateMeta?.redirectUrl ?? '',
|
||||
language: template.templateMeta?.language ?? 'en',
|
||||
emailSettings: ZDocumentEmailSettingsSchema.parse(template?.templateMeta?.emailSettings),
|
||||
signatureTypes: extractTeamSignatureSettings(template?.templateMeta),
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -314,7 +321,7 @@ export const AddTemplateSettingsFormPartial = ({
|
||||
{Object.values(DOCUMENT_DISTRIBUTION_METHODS).map(
|
||||
({ value, description }) => (
|
||||
<SelectItem key={value} value={value}>
|
||||
{_(description)}
|
||||
{i18n._(description)}
|
||||
</SelectItem>
|
||||
),
|
||||
)}
|
||||
@ -325,6 +332,34 @@ export const AddTemplateSettingsFormPartial = ({
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="meta.signatureTypes"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="flex flex-row items-center">
|
||||
<Trans>Allowed Signature Types</Trans>
|
||||
<DocumentSignatureSettingsTooltip />
|
||||
</FormLabel>
|
||||
|
||||
<FormControl>
|
||||
<MultiSelectCombobox
|
||||
options={Object.values(DOCUMENT_SIGNATURE_TYPES).map((option) => ({
|
||||
label: t(option.label),
|
||||
value: option.value,
|
||||
}))}
|
||||
selectedValues={field.value}
|
||||
onChange={field.onChange}
|
||||
className="bg-background w-full"
|
||||
emptySelectionPlaceholder="Select signature types"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{isEnterprise && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { DocumentDistributionMethod } from '@prisma/client';
|
||||
import { DocumentVisibility } from '@prisma/client';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats';
|
||||
import { DocumentSignatureType } from '@documenso/lib/constants/document';
|
||||
import { SUPPORTED_LANGUAGE_CODES } from '@documenso/lib/constants/i18n';
|
||||
import { DEFAULT_DOCUMENT_TIME_ZONE } from '@documenso/lib/constants/time-zones';
|
||||
import {
|
||||
@ -49,6 +51,9 @@ export const ZAddTemplateSettingsFormSchema = z.object({
|
||||
.optional()
|
||||
.default('en'),
|
||||
emailSettings: ZDocumentEmailSettingsSchema,
|
||||
signatureTypes: z.array(z.nativeEnum(DocumentSignatureType)).min(1, {
|
||||
message: msg`At least one signature type must be enabled`.id,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user