feat: hide signature ui when theres no signature field (#1676)

This commit is contained in:
Ephraim Duncan
2025-03-06 01:34:11 +00:00
committed by GitHub
parent a41ac632d0
commit ae6cc24317
5 changed files with 186 additions and 143 deletions

View File

@ -311,7 +311,11 @@ export const SigningForm = ({
<> <>
<form onSubmit={handleSubmit(onFormSubmit)}> <form onSubmit={handleSubmit(onFormSubmit)}>
<p className="text-muted-foreground mt-2 text-sm"> <p className="text-muted-foreground mt-2 text-sm">
{recipient.role === RecipientRole.APPROVER && !hasSignatureField ? (
<Trans>Please review the document before approving.</Trans>
) : (
<Trans>Please review the document before signing.</Trans> <Trans>Please review the document before signing.</Trans>
)}
</p> </p>
<hr className="border-border mb-8 mt-4" /> <hr className="border-border mb-8 mt-4" />
@ -335,6 +339,7 @@ export const SigningForm = ({
/> />
</div> </div>
{hasSignatureField && (
<div> <div>
<Label htmlFor="Signature"> <Label htmlFor="Signature">
<Trans>Signature</Trans> <Trans>Signature</Trans>
@ -359,7 +364,7 @@ export const SigningForm = ({
</CardContent> </CardContent>
</Card> </Card>
{hasSignatureField && !signatureValid && ( {!signatureValid && (
<div className="text-destructive mt-2 text-sm"> <div className="text-destructive mt-2 text-sm">
<Trans> <Trans>
Signature is too small. Please provide a more complete signature. Signature is too small. Please provide a more complete signature.
@ -367,6 +372,7 @@ export const SigningForm = ({
</div> </div>
)} )}
</div> </div>
)}
</div> </div>
<div className="flex flex-col gap-4 md:flex-row"> <div className="flex flex-col gap-4 md:flex-row">

View File

@ -1,6 +1,7 @@
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { Trans } from '@lingui/macro'; import { Trans } from '@lingui/macro';
import { match } from 'ts-pattern';
import { fieldsContainUnsignedRequiredField } from '@documenso/lib/utils/advanced-fields-helpers'; import { fieldsContainUnsignedRequiredField } from '@documenso/lib/utils/advanced-fields-helpers';
import type { Field } from '@documenso/prisma/client'; import type { Field } from '@documenso/prisma/client';
@ -58,21 +59,33 @@ export const SignDialog = ({
loading={isSubmitting} loading={isSubmitting}
disabled={disabled} disabled={disabled}
> >
{isComplete ? <Trans>Complete</Trans> : <Trans>Next field</Trans>} {match({ isComplete, role })
.with({ isComplete: false }, () => <Trans>Next field</Trans>)
.with({ isComplete: true, role: RecipientRole.APPROVER }, () => <Trans>Approve</Trans>)
.with({ isComplete: true, role: RecipientRole.VIEWER }, () => (
<Trans>Mark as viewed</Trans>
))
.with({ isComplete: true }, () => <Trans>Complete</Trans>)
.exhaustive()}
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent> <DialogContent>
<DialogTitle> <DialogTitle>
<div className="text-foreground text-xl font-semibold"> <div className="text-foreground text-xl font-semibold">
{role === RecipientRole.VIEWER && <Trans>Complete Viewing</Trans>} {match(role)
{role === RecipientRole.SIGNER && <Trans>Complete Signing</Trans>} .with(RecipientRole.VIEWER, () => <Trans>Complete Viewing</Trans>)
{role === RecipientRole.APPROVER && <Trans>Complete Approval</Trans>} .with(RecipientRole.SIGNER, () => <Trans>Complete Signing</Trans>)
.with(RecipientRole.APPROVER, () => <Trans>Complete Approval</Trans>)
.with(RecipientRole.CC, () => <Trans>Complete Viewing</Trans>)
.with(RecipientRole.ASSISTANT, () => <Trans>Complete Assisting</Trans>)
.exhaustive()}
</div> </div>
</DialogTitle> </DialogTitle>
<div className="text-muted-foreground max-w-[50ch]"> <div className="text-muted-foreground max-w-[50ch]">
{role === RecipientRole.VIEWER && ( {match(role)
.with(RecipientRole.VIEWER, () => (
<span> <span>
<Trans> <Trans>
<span className="inline-flex flex-wrap"> <span className="inline-flex flex-wrap">
@ -85,8 +98,8 @@ export const SignDialog = ({
<br /> Are you sure? <br /> Are you sure?
</Trans> </Trans>
</span> </span>
)} ))
{role === RecipientRole.SIGNER && ( .with(RecipientRole.SIGNER, () => (
<span> <span>
<Trans> <Trans>
<span className="inline-flex flex-wrap"> <span className="inline-flex flex-wrap">
@ -99,8 +112,8 @@ export const SignDialog = ({
<br /> Are you sure? <br /> Are you sure?
</Trans> </Trans>
</span> </span>
)} ))
{role === RecipientRole.APPROVER && ( .with(RecipientRole.APPROVER, () => (
<span> <span>
<Trans> <Trans>
<span className="inline-flex flex-wrap"> <span className="inline-flex flex-wrap">
@ -113,7 +126,21 @@ export const SignDialog = ({
<br /> Are you sure? <br /> Are you sure?
</Trans> </Trans>
</span> </span>
)} ))
.otherwise(() => (
<span>
<Trans>
<span className="inline-flex flex-wrap">
You are about to complete viewing "
<span className="inline-block max-w-[11rem] truncate align-baseline">
{documentTitle}
</span>
".
</span>
<br /> Are you sure?
</Trans>
</span>
))}
</div> </div>
<SigningDisclosure className="mt-4" /> <SigningDisclosure className="mt-4" />
@ -138,9 +165,13 @@ export const SignDialog = ({
loading={isSubmitting} loading={isSubmitting}
onClick={onSignatureComplete} onClick={onSignatureComplete}
> >
{role === RecipientRole.VIEWER && <Trans>Mark as Viewed</Trans>} {match(role)
{role === RecipientRole.SIGNER && <Trans>Sign</Trans>} .with(RecipientRole.VIEWER, () => <Trans>Mark as Viewed</Trans>)
{role === RecipientRole.APPROVER && <Trans>Approve</Trans>} .with(RecipientRole.SIGNER, () => <Trans>Sign</Trans>)
.with(RecipientRole.APPROVER, () => <Trans>Approve</Trans>)
.with(RecipientRole.CC, () => <Trans>Mark as Viewed</Trans>)
.with(RecipientRole.ASSISTANT, () => <Trans>Complete</Trans>)
.exhaustive()}
</Button> </Button>
</div> </div>
</DialogFooter> </DialogFooter>

View File

@ -432,6 +432,7 @@ export const EmbedDirectTemplateClientPage = ({
/> />
</div> </div>
{hasSignatureField && (
<div> <div>
<Label htmlFor="Signature"> <Label htmlFor="Signature">
<Trans>Signature</Trans> <Trans>Signature</Trans>
@ -466,6 +467,7 @@ export const EmbedDirectTemplateClientPage = ({
</div> </div>
)} )}
</div> </div>
)}
</div> </div>
</div> </div>

View File

@ -436,6 +436,7 @@ export const EmbedSignDocumentClientPage = ({
/> />
</div> </div>
{hasSignatureField && (
<div> <div>
<Label htmlFor="Signature"> <Label htmlFor="Signature">
<Trans>Signature</Trans> <Trans>Signature</Trans>
@ -470,6 +471,7 @@ export const EmbedSignDocumentClientPage = ({
</div> </div>
)} )}
</div> </div>
)}
</> </>
)} )}
</div> </div>

View File

@ -384,7 +384,9 @@ test('[DOCUMENT_FLOW]: should be able to approve a document', async ({ page }) =
await expect(page.locator(`#field-${field.id}`)).toHaveAttribute('data-inserted', 'true'); await expect(page.locator(`#field-${field.id}`)).toHaveAttribute('data-inserted', 'true');
} }
await page.getByRole('button', { name: 'Complete' }).click(); await page
.getByRole('button', { name: role === RecipientRole.SIGNER ? 'Complete' : 'Approve' })
.click();
await page await page
.getByRole('button', { name: role === RecipientRole.SIGNER ? 'Sign' : 'Approve' }) .getByRole('button', { name: role === RecipientRole.SIGNER ? 'Sign' : 'Approve' })
.click(); .click();
@ -454,7 +456,7 @@ test('[DOCUMENT_FLOW]: should be able to create, send with redirect url, sign a
const { status } = await getDocumentByToken(token); const { status } = await getDocumentByToken(token);
expect(status).toBe(DocumentStatus.PENDING); expect(status).toBe(DocumentStatus.PENDING);
await page.getByRole('button', { name: 'Complete' }).click(); await page.getByRole('button', { name: 'Approve' }).click();
await expect(page.getByRole('dialog').getByText('Complete Approval').first()).toBeVisible(); await expect(page.getByRole('dialog').getByText('Complete Approval').first()).toBeVisible();
await page.getByRole('button', { name: 'Approve' }).click(); await page.getByRole('button', { name: 'Approve' }).click();