mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 09:12:02 +10:00
chore: merge main
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@documenso/marketing",
|
||||
"version": "1.7.2-rc.0",
|
||||
"version": "1.7.2-rc.1",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@documenso/web",
|
||||
"version": "1.7.2-rc.0",
|
||||
"version": "1.7.2-rc.1",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
||||
@ -114,6 +114,24 @@ export const EditDocumentForm = ({
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: updateTypedSignature } =
|
||||
trpc.document.updateTypedSignatureSettings.useMutation({
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
onSuccess: (newData) => {
|
||||
utils.document.getDocumentWithDetailsById.setData(
|
||||
{
|
||||
id: initialDocument.id,
|
||||
teamId: team?.id,
|
||||
},
|
||||
(oldData) => ({
|
||||
...(oldData || initialDocument),
|
||||
...newData,
|
||||
id: Number(newData.id),
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: addSigners } = trpc.recipient.addSigners.useMutation({
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
onSuccess: (newRecipients) => {
|
||||
@ -273,6 +291,11 @@ export const EditDocumentForm = ({
|
||||
fields: data.fields,
|
||||
});
|
||||
|
||||
await updateTypedSignature({
|
||||
documentId: document.id,
|
||||
typedSignatureEnabled: data.typedSignatureEnabled,
|
||||
});
|
||||
|
||||
// Clear all field data from localStorage
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
@ -413,6 +436,7 @@ export const EditDocumentForm = ({
|
||||
fields={fields}
|
||||
onSubmit={onAddFieldsFormSubmit}
|
||||
isDocumentPdfLoaded={isDocumentPdfLoaded}
|
||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||
teamId={team?.id}
|
||||
/>
|
||||
|
||||
|
||||
@ -144,6 +144,7 @@ export const TemplatesDataTable = ({
|
||||
<div className="flex items-center gap-x-4">
|
||||
<UseTemplateDialog
|
||||
templateId={row.original.id}
|
||||
templateSigningOrder={row.original.templateMeta?.signingOrder}
|
||||
recipients={row.original.Recipient}
|
||||
documentRootPath={documentRootPath}
|
||||
/>
|
||||
|
||||
@ -434,12 +434,14 @@ export const TemplateDirectLinkDialog = ({
|
||||
<Button
|
||||
type="button"
|
||||
loading={isTogglingTemplateAccess}
|
||||
onClick={async () =>
|
||||
toggleTemplateDirectLink({
|
||||
onClick={async () => {
|
||||
await toggleTemplateDirectLink({
|
||||
templateId: template.id,
|
||||
enabled: isEnabled,
|
||||
})
|
||||
}
|
||||
}).catch((e) => null);
|
||||
|
||||
onOpenChange(false);
|
||||
}}
|
||||
>
|
||||
<Trans>Save</Trans>
|
||||
</Button>
|
||||
|
||||
@ -15,7 +15,9 @@ import {
|
||||
} from '@documenso/lib/constants/template';
|
||||
import { AppError } from '@documenso/lib/errors/app-error';
|
||||
import type { Recipient } from '@documenso/prisma/client';
|
||||
import { DocumentSigningOrder } from '@documenso/prisma/client';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Checkbox } from '@documenso/ui/primitives/checkbox';
|
||||
import {
|
||||
@ -51,6 +53,7 @@ const ZAddRecipientsForNewDocumentSchema = z
|
||||
id: z.number(),
|
||||
email: z.string().email(),
|
||||
name: z.string(),
|
||||
signingOrder: z.number().optional(),
|
||||
}),
|
||||
),
|
||||
})
|
||||
@ -86,6 +89,7 @@ type TAddRecipientsForNewDocumentSchema = z.infer<typeof ZAddRecipientsForNewDoc
|
||||
|
||||
export type UseTemplateDialogProps = {
|
||||
templateId: number;
|
||||
templateSigningOrder?: DocumentSigningOrder | null;
|
||||
recipients: Recipient[];
|
||||
documentRootPath: string;
|
||||
};
|
||||
@ -94,6 +98,7 @@ export function UseTemplateDialog({
|
||||
recipients,
|
||||
documentRootPath,
|
||||
templateId,
|
||||
templateSigningOrder,
|
||||
}: UseTemplateDialogProps) {
|
||||
const router = useRouter();
|
||||
|
||||
@ -108,21 +113,24 @@ export function UseTemplateDialog({
|
||||
resolver: zodResolver(ZAddRecipientsForNewDocumentSchema),
|
||||
defaultValues: {
|
||||
sendDocument: false,
|
||||
recipients: recipients.map((recipient) => {
|
||||
const isRecipientEmailPlaceholder = recipient.email.match(
|
||||
TEMPLATE_RECIPIENT_EMAIL_PLACEHOLDER_REGEX,
|
||||
);
|
||||
recipients: recipients
|
||||
.sort((a, b) => (a.signingOrder || 0) - (b.signingOrder || 0))
|
||||
.map((recipient) => {
|
||||
const isRecipientEmailPlaceholder = recipient.email.match(
|
||||
TEMPLATE_RECIPIENT_EMAIL_PLACEHOLDER_REGEX,
|
||||
);
|
||||
|
||||
const isRecipientNamePlaceholder = recipient.name.match(
|
||||
TEMPLATE_RECIPIENT_NAME_PLACEHOLDER_REGEX,
|
||||
);
|
||||
const isRecipientNamePlaceholder = recipient.name.match(
|
||||
TEMPLATE_RECIPIENT_NAME_PLACEHOLDER_REGEX,
|
||||
);
|
||||
|
||||
return {
|
||||
id: recipient.id,
|
||||
name: !isRecipientNamePlaceholder ? recipient.name : '',
|
||||
email: !isRecipientEmailPlaceholder ? recipient.email : '',
|
||||
};
|
||||
}),
|
||||
return {
|
||||
id: recipient.id,
|
||||
name: !isRecipientNamePlaceholder ? recipient.name : '',
|
||||
email: !isRecipientEmailPlaceholder ? recipient.email : '',
|
||||
signingOrder: recipient.signingOrder ?? undefined,
|
||||
};
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
@ -203,6 +211,33 @@ export function UseTemplateDialog({
|
||||
<div className="custom-scrollbar -m-1 max-h-[60vh] space-y-4 overflow-y-auto p-1">
|
||||
{formRecipients.map((recipient, index) => (
|
||||
<div className="flex w-full flex-row space-x-4" key={recipient.id}>
|
||||
{templateSigningOrder === DocumentSigningOrder.SEQUENTIAL && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`recipients.${index}.signingOrder`}
|
||||
render={({ field }) => (
|
||||
<FormItem
|
||||
className={cn('w-20', {
|
||||
'mt-8': index === 0,
|
||||
})}
|
||||
>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
disabled
|
||||
className="items-center justify-center"
|
||||
value={
|
||||
field.value?.toString() ||
|
||||
recipients[index]?.signingOrder?.toString()
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={`recipients.${index}.email`}
|
||||
|
||||
@ -9,9 +9,10 @@ import { useSession } from 'next-auth/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
|
||||
import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics';
|
||||
import type { DocumentAndSender } from '@documenso/lib/server-only/document/get-document-by-token';
|
||||
import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth';
|
||||
import { sortFieldsByPosition, validateFieldsInserted } from '@documenso/lib/utils/fields';
|
||||
import { type Document, type Field, type Recipient, RecipientRole } from '@documenso/prisma/client';
|
||||
import { type Field, type Recipient, RecipientRole } from '@documenso/prisma/client';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { FieldToolTip } from '@documenso/ui/components/field/field-tooltip';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
@ -25,7 +26,7 @@ import { useRequiredSigningContext } from './provider';
|
||||
import { SignDialog } from './sign-dialog';
|
||||
|
||||
export type SigningFormProps = {
|
||||
document: Document;
|
||||
document: DocumentAndSender;
|
||||
recipient: Recipient;
|
||||
fields: Field[];
|
||||
redirectUrl?: string | null;
|
||||
@ -196,6 +197,7 @@ export const SigningForm = ({
|
||||
onChange={(value) => {
|
||||
setSignature(value);
|
||||
}}
|
||||
allowTypedSignature={document.documentMeta?.typedSignatureEnabled}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@ -31,12 +31,12 @@ import { useRequiredSigningContext } from './provider';
|
||||
import { SigningFieldContainer } from './signing-field-container';
|
||||
|
||||
type SignatureFieldState = 'empty' | 'signed-image' | 'signed-text';
|
||||
|
||||
export type SignatureFieldProps = {
|
||||
field: FieldWithSignature;
|
||||
recipient: Recipient;
|
||||
onSignField?: (value: TSignFieldWithTokenMutationSchema) => Promise<void> | void;
|
||||
onUnsignField?: (value: TRemovedSignedFieldWithTokenMutationSchema) => Promise<void> | void;
|
||||
typedSignatureEnabled?: boolean;
|
||||
};
|
||||
|
||||
export const SignatureField = ({
|
||||
@ -44,6 +44,7 @@ export const SignatureField = ({
|
||||
recipient,
|
||||
onSignField,
|
||||
onUnsignField,
|
||||
typedSignatureEnabled,
|
||||
}: SignatureFieldProps) => {
|
||||
const router = useRouter();
|
||||
|
||||
@ -92,14 +93,12 @@ export const SignatureField = ({
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* When the user clicks the sign button in the dialog where they enter their signature.
|
||||
*/
|
||||
const onDialogSignClick = () => {
|
||||
setShowSignatureModal(false);
|
||||
setProvidedSignature(localSignature);
|
||||
|
||||
if (!localSignature) {
|
||||
return;
|
||||
}
|
||||
@ -109,7 +108,6 @@ export const SignatureField = ({
|
||||
actionTarget: field.type,
|
||||
});
|
||||
};
|
||||
|
||||
const onSign = async (authOptions?: TRecipientActionAuth, signature?: string) => {
|
||||
try {
|
||||
const value = signature || providedSignature;
|
||||
@ -231,11 +229,11 @@ export const SignatureField = ({
|
||||
id="signature"
|
||||
className="border-border mt-2 h-44 w-full rounded-md border"
|
||||
onChange={(value) => setLocalSignature(value)}
|
||||
allowTypedSignature={typedSignatureEnabled}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<SigningDisclosure />
|
||||
|
||||
<DialogFooter>
|
||||
<div className="flex w-full flex-1 flex-nowrap gap-4">
|
||||
<Button
|
||||
@ -249,7 +247,6 @@ export const SignatureField = ({
|
||||
>
|
||||
<Trans>Cancel</Trans>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
className="flex-1"
|
||||
|
||||
@ -112,7 +112,12 @@ export const SigningPageView = ({
|
||||
{fields.map((field) =>
|
||||
match(field.type)
|
||||
.with(FieldType.SIGNATURE, () => (
|
||||
<SignatureField key={field.id} field={field} recipient={recipient} />
|
||||
<SignatureField
|
||||
key={field.id}
|
||||
field={field}
|
||||
recipient={recipient}
|
||||
typedSignatureEnabled={documentMeta?.typedSignatureEnabled}
|
||||
/>
|
||||
))
|
||||
.with(FieldType.INITIALS, () => (
|
||||
<InitialsField key={field.id} field={field} recipient={recipient} />
|
||||
|
||||
Reference in New Issue
Block a user