mirror of
https://github.com/documenso/documenso.git
synced 2026-06-22 04:12:06 +10:00
fix: update link-only notification settings (#2821)
This commit is contained in:
+42
-10
@@ -9,7 +9,7 @@ import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants
|
|||||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
||||||
import { AppError } from '@documenso/lib/errors/app-error';
|
import { AppError } from '@documenso/lib/errors/app-error';
|
||||||
import { ZDocumentAccessAuthTypesSchema, ZDocumentActionAuthTypesSchema } from '@documenso/lib/types/document-auth';
|
import { ZDocumentAccessAuthTypesSchema, ZDocumentActionAuthTypesSchema } from '@documenso/lib/types/document-auth';
|
||||||
import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';
|
import { DocumentEmailEvents, ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';
|
||||||
import {
|
import {
|
||||||
type TDocumentMetaDateFormat,
|
type TDocumentMetaDateFormat,
|
||||||
ZDocumentMetaDateFormatSchema,
|
ZDocumentMetaDateFormatSchema,
|
||||||
@@ -39,6 +39,7 @@ import { ExpirationPeriodPicker } from '@documenso/ui/components/document/expira
|
|||||||
import { ReminderSettingsPicker } from '@documenso/ui/components/document/reminder-settings-picker';
|
import { ReminderSettingsPicker } from '@documenso/ui/components/document/reminder-settings-picker';
|
||||||
import { TemplateTypeSelect, TemplateTypeTooltip } from '@documenso/ui/components/template/template-type-select';
|
import { TemplateTypeSelect, TemplateTypeTooltip } from '@documenso/ui/components/template/template-type-select';
|
||||||
import { cn } from '@documenso/ui/lib/utils';
|
import { cn } from '@documenso/ui/lib/utils';
|
||||||
|
import { Alert, AlertDescription } from '@documenso/ui/primitives/alert';
|
||||||
import { Button } from '@documenso/ui/primitives/button';
|
import { Button } from '@documenso/ui/primitives/button';
|
||||||
import { CardDescription, CardHeader, CardTitle } from '@documenso/ui/primitives/card';
|
import { CardDescription, CardHeader, CardTitle } from '@documenso/ui/primitives/card';
|
||||||
import { Combobox } from '@documenso/ui/primitives/combobox';
|
import { Combobox } from '@documenso/ui/primitives/combobox';
|
||||||
@@ -114,7 +115,7 @@ export const ZAddSettingsFormSchema = z.object({
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
type EnvelopeEditorSettingsTabType = 'general' | 'reminders' | 'email' | 'security';
|
type EnvelopeEditorSettingsTabType = 'general' | 'reminders' | 'notifications' | 'security';
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
@@ -130,10 +131,10 @@ const tabs = [
|
|||||||
description: msg`Configure signing reminder settings for the document.`,
|
description: msg`Configure signing reminder settings for the document.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'email',
|
id: 'notifications',
|
||||||
title: msg`Email`,
|
title: msg`Notifications`,
|
||||||
icon: MailIcon,
|
icon: MailIcon,
|
||||||
description: msg`Configure email settings for the document.`,
|
description: msg`Configure notification settings for the document.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'security',
|
id: 'security',
|
||||||
@@ -143,6 +144,18 @@ const tabs = [
|
|||||||
},
|
},
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
// Recipient-facing notification events. These are suppressed at send time
|
||||||
|
// when distributionMethod is not EMAIL (see extractDerivedDocumentEmailSettings),
|
||||||
|
// so the UI mirrors that by disabling the matching checkboxes.
|
||||||
|
const RECIPIENT_EMAIL_EVENTS = [
|
||||||
|
DocumentEmailEvents.RecipientSigningRequest,
|
||||||
|
DocumentEmailEvents.RecipientRemoved,
|
||||||
|
DocumentEmailEvents.RecipientSigned,
|
||||||
|
DocumentEmailEvents.DocumentPending,
|
||||||
|
DocumentEmailEvents.DocumentCompleted,
|
||||||
|
DocumentEmailEvents.DocumentDeleted,
|
||||||
|
] as const;
|
||||||
|
|
||||||
type TAddSettingsFormSchema = z.infer<typeof ZAddSettingsFormSchema>;
|
type TAddSettingsFormSchema = z.infer<typeof ZAddSettingsFormSchema>;
|
||||||
|
|
||||||
type EnvelopeEditorSettingsDialogProps = {
|
type EnvelopeEditorSettingsDialogProps = {
|
||||||
@@ -205,6 +218,8 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
);
|
);
|
||||||
|
|
||||||
const emailSettings = form.watch('meta.emailSettings');
|
const emailSettings = form.watch('meta.emailSettings');
|
||||||
|
const distributionMethod = form.watch('meta.distributionMethod');
|
||||||
|
const isEmailDistribution = distributionMethod === DocumentDistributionMethod.EMAIL;
|
||||||
|
|
||||||
const { data: emailData, isLoading: isLoadingEmails } = trpc.enterprise.organisation.email.find.useQuery(
|
const { data: emailData, isLoading: isLoadingEmails } = trpc.enterprise.organisation.email.find.useQuery(
|
||||||
{
|
{
|
||||||
@@ -334,7 +349,7 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
|
|
||||||
<nav className="col-span-12 mb-8 flex flex-wrap items-center justify-start gap-x-2 gap-y-4 px-4 md:col-span-3 md:w-full md:flex-col md:items-start md:gap-y-2">
|
<nav className="col-span-12 mb-8 flex flex-wrap items-center justify-start gap-x-2 gap-y-4 px-4 md:col-span-3 md:w-full md:flex-col md:items-start md:gap-y-2">
|
||||||
{tabs.map((tab) => {
|
{tabs.map((tab) => {
|
||||||
if (tab.id === 'email' && !settings.allowConfigureDistribution) {
|
if (tab.id === 'notifications' && !settings.allowConfigureDistribution) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,7 +745,7 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
.with({ activeTab: 'email', settings: { allowConfigureDistribution: true } }, () => (
|
.with({ activeTab: 'notifications', settings: { allowConfigureDistribution: true } }, () => (
|
||||||
<>
|
<>
|
||||||
{settings.allowConfigureEmailSender && organisation.organisationClaim.flags.emailDomains && (
|
{settings.allowConfigureEmailSender && organisation.organisationClaim.flags.emailDomains && (
|
||||||
<FormField
|
<FormField
|
||||||
@@ -747,6 +762,7 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
{...field}
|
{...field}
|
||||||
value={field.value === null ? '-1' : field.value}
|
value={field.value === null ? '-1' : field.value}
|
||||||
onValueChange={(value) => field.onChange(value === '-1' ? null : value)}
|
onValueChange={(value) => field.onChange(value === '-1' ? null : value)}
|
||||||
|
disabled={!isEmailDistribution}
|
||||||
>
|
>
|
||||||
<SelectTrigger loading={isLoadingEmails} className="bg-background">
|
<SelectTrigger loading={isLoadingEmails} className="bg-background">
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
@@ -783,7 +799,7 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} disabled={!isEmailDistribution} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -804,7 +820,7 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} />
|
<Input {...field} disabled={!isEmailDistribution} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -832,7 +848,11 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Textarea className="h-16 resize-none bg-background" {...field} />
|
<Textarea
|
||||||
|
className="h-16 resize-none bg-background"
|
||||||
|
{...field}
|
||||||
|
disabled={!isEmailDistribution}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
@@ -843,7 +863,19 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
<DocumentEmailCheckboxes
|
<DocumentEmailCheckboxes
|
||||||
value={emailSettings}
|
value={emailSettings}
|
||||||
onChange={(value) => form.setValue('meta.emailSettings', value)}
|
onChange={(value) => form.setValue('meta.emailSettings', value)}
|
||||||
|
hiddenEvents={isEmailDistribution ? undefined : RECIPIENT_EMAIL_EVENTS}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{!isEmailDistribution && (
|
||||||
|
<Alert variant="warning">
|
||||||
|
<AlertDescription>
|
||||||
|
<Trans>
|
||||||
|
Email distribution needs to be enabled in the general settings tab to configure recipient
|
||||||
|
email related settings.
|
||||||
|
</Trans>
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
.with({ activeTab: 'security' }, () => (
|
.with({ activeTab: 'security' }, () => (
|
||||||
|
|||||||
@@ -115,6 +115,21 @@ const runSettingsFlow = async ({ root }: TEnvelopeEditorSurface, { externalId, i
|
|||||||
|
|
||||||
await root.locator('input[name="externalId"]').fill(externalId);
|
await root.locator('input[name="externalId"]').fill(externalId);
|
||||||
await root.locator('input[name="meta.redirectUrl"]').fill(TEST_SETTINGS_VALUES.redirectUrl);
|
await root.locator('input[name="meta.redirectUrl"]').fill(TEST_SETTINGS_VALUES.redirectUrl);
|
||||||
|
await root.getByRole('button', { name: 'Notifications' }).click();
|
||||||
|
// Fill email-content fields and toggle recipient-facing notification checkboxes
|
||||||
|
// while distributionMethod is still EMAIL. After it flips to NONE below, these
|
||||||
|
// controls are disabled because no email is sent to recipients.
|
||||||
|
await root.locator('input[name="meta.subject"]').fill(TEST_SETTINGS_VALUES.subject);
|
||||||
|
await root.locator('textarea[name="meta.message"]').fill(TEST_SETTINGS_VALUES.message);
|
||||||
|
await root.locator('input[name="meta.emailReplyTo"]').fill(TEST_SETTINGS_VALUES.replyTo);
|
||||||
|
await root.locator('#recipientSigned').click();
|
||||||
|
await root.locator('#recipientSigningRequest').click();
|
||||||
|
await root.locator('#recipientRemoved').click();
|
||||||
|
await root.locator('#documentPending').click();
|
||||||
|
await root.locator('#documentCompleted').click();
|
||||||
|
await root.locator('#documentDeleted').click();
|
||||||
|
|
||||||
|
await root.getByRole('button', { name: 'General' }).click();
|
||||||
|
|
||||||
await root.locator('[data-testid="documentDistributionMethodSelectValue"]').click();
|
await root.locator('[data-testid="documentDistributionMethodSelectValue"]').click();
|
||||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.distributionMethod }).click();
|
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.distributionMethod }).click();
|
||||||
@@ -190,19 +205,35 @@ const runSettingsFlow = async ({ root }: TEnvelopeEditorSurface, { externalId, i
|
|||||||
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderRepeatUnit }).click();
|
await root.getByRole('option', { name: TEST_SETTINGS_VALUES.reminderRepeatUnit }).click();
|
||||||
await clickSettingsDialogHeader(root);
|
await clickSettingsDialogHeader(root);
|
||||||
|
|
||||||
await root.getByRole('button', { name: 'Email' }).click();
|
await root.getByRole('button', { name: 'Notifications' }).click();
|
||||||
await root.locator('#recipientSigned').click();
|
|
||||||
await root.locator('#recipientSigningRequest').click();
|
// Distribution is NONE: email-content fields stay rendered but disabled,
|
||||||
await root.locator('#recipientRemoved').click();
|
// recipient-facing checkboxes are hidden entirely and replaced by an alert,
|
||||||
await root.locator('#documentPending').click();
|
// owner-facing checkboxes stay editable so we toggle them here.
|
||||||
await root.locator('#documentCompleted').click();
|
await expect(root.locator('input[name="meta.subject"]')).toBeDisabled();
|
||||||
await root.locator('#documentDeleted').click();
|
await expect(root.locator('textarea[name="meta.message"]')).toBeDisabled();
|
||||||
|
await expect(root.locator('input[name="meta.emailReplyTo"]')).toBeDisabled();
|
||||||
|
await expect(root.locator('#recipientSigned')).toHaveCount(0);
|
||||||
|
await expect(root.locator('#recipientSigningRequest')).toHaveCount(0);
|
||||||
|
await expect(root.locator('#recipientRemoved')).toHaveCount(0);
|
||||||
|
await expect(root.locator('#documentPending')).toHaveCount(0);
|
||||||
|
await expect(root.locator('#documentCompleted')).toHaveCount(0);
|
||||||
|
await expect(root.locator('#documentDeleted')).toHaveCount(0);
|
||||||
|
await expect(root.getByText(/Email distribution needs to be enabled/)).toBeVisible();
|
||||||
|
|
||||||
|
// Email Sender select only renders when the org has the emailDomains feature
|
||||||
|
// flag plus allowConfigureEmailSender, so the assertion is conditional.
|
||||||
|
const emailSenderSelect = getComboboxByLabel(root, 'Email Sender');
|
||||||
|
const hasEmailSenderSelect = (await emailSenderSelect.count()) > 0;
|
||||||
|
|
||||||
|
if (hasEmailSenderSelect) {
|
||||||
|
await expect(emailSenderSelect).toBeDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
await expect(root.locator('#ownerDocumentCompleted')).toBeEnabled();
|
||||||
await root.locator('#ownerDocumentCompleted').click();
|
await root.locator('#ownerDocumentCompleted').click();
|
||||||
await root.locator('#ownerRecipientExpired').click();
|
await root.locator('#ownerRecipientExpired').click();
|
||||||
await root.locator('#ownerDocumentCreated').click();
|
await root.locator('#ownerDocumentCreated').click();
|
||||||
await root.locator('input[name="meta.emailReplyTo"]').fill(TEST_SETTINGS_VALUES.replyTo);
|
|
||||||
await root.locator('input[name="meta.subject"]').fill(TEST_SETTINGS_VALUES.subject);
|
|
||||||
await root.locator('textarea[name="meta.message"]').fill(TEST_SETTINGS_VALUES.message);
|
|
||||||
|
|
||||||
await root.getByRole('button', { name: 'Security' }).click();
|
await root.getByRole('button', { name: 'Security' }).click();
|
||||||
await selectMultiSelectOption(root, 'documentAccessSelectValue', TEST_SETTINGS_VALUES.accessAuth);
|
await selectMultiSelectOption(root, 'documentAccessSelectValue', TEST_SETTINGS_VALUES.accessAuth);
|
||||||
@@ -264,13 +295,17 @@ const runSettingsFlow = async ({ root }: TEnvelopeEditorSurface, { externalId, i
|
|||||||
TEST_SETTINGS_VALUES.reminderRepeatUnit,
|
TEST_SETTINGS_VALUES.reminderRepeatUnit,
|
||||||
);
|
);
|
||||||
|
|
||||||
await root.getByRole('button', { name: 'Email' }).click();
|
await root.getByRole('button', { name: 'Notifications' }).click();
|
||||||
await expect(root.locator('#recipientSigned')).toHaveAttribute('aria-checked', 'false');
|
// Distribution persisted as NONE: recipient-facing checkboxes are hidden, owner-facing
|
||||||
await expect(root.locator('#recipientSigningRequest')).toHaveAttribute('aria-checked', 'false');
|
// checkboxes remain visible and persist their stored values. Email-content fields are
|
||||||
await expect(root.locator('#recipientRemoved')).toHaveAttribute('aria-checked', 'false');
|
// still rendered (disabled) and persist their stored values.
|
||||||
await expect(root.locator('#documentPending')).toHaveAttribute('aria-checked', 'false');
|
await expect(root.locator('#recipientSigned')).toHaveCount(0);
|
||||||
await expect(root.locator('#documentCompleted')).toHaveAttribute('aria-checked', 'false');
|
await expect(root.locator('#recipientSigningRequest')).toHaveCount(0);
|
||||||
await expect(root.locator('#documentDeleted')).toHaveAttribute('aria-checked', 'false');
|
await expect(root.locator('#recipientRemoved')).toHaveCount(0);
|
||||||
|
await expect(root.locator('#documentPending')).toHaveCount(0);
|
||||||
|
await expect(root.locator('#documentCompleted')).toHaveCount(0);
|
||||||
|
await expect(root.locator('#documentDeleted')).toHaveCount(0);
|
||||||
|
await expect(root.getByText(/Email distribution needs to be enabled/)).toBeVisible();
|
||||||
await expect(root.locator('#ownerDocumentCompleted')).toHaveAttribute('aria-checked', 'false');
|
await expect(root.locator('#ownerDocumentCompleted')).toHaveAttribute('aria-checked', 'false');
|
||||||
await expect(root.locator('#ownerRecipientExpired')).toHaveAttribute('aria-checked', 'false');
|
await expect(root.locator('#ownerRecipientExpired')).toHaveAttribute('aria-checked', 'false');
|
||||||
await expect(root.locator('#ownerDocumentCreated')).toHaveAttribute('aria-checked', 'false');
|
await expect(root.locator('#ownerDocumentCreated')).toHaveAttribute('aria-checked', 'false');
|
||||||
|
|||||||
@@ -13,334 +13,361 @@ type DocumentEmailCheckboxesProps = {
|
|||||||
value: Value;
|
value: Value;
|
||||||
onChange: (value: Value) => void;
|
onChange: (value: Value) => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
hiddenEvents?: readonly DocumentEmailEvents[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DocumentEmailCheckboxes = ({ value, onChange, className }: DocumentEmailCheckboxesProps) => {
|
export const DocumentEmailCheckboxes = ({ value, onChange, className, hiddenEvents }: DocumentEmailCheckboxesProps) => {
|
||||||
|
const isHidden = (event: DocumentEmailEvents) => hiddenEvents?.includes(event) ?? false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn('space-y-3', className)}>
|
<div className={cn('space-y-3', className)}>
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.RecipientSigned) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.RecipientSigned}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.RecipientSigned}
|
||||||
checked={value.recipientSigned}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) => onChange({ ...value, [DocumentEmailEvents.RecipientSigned]: Boolean(checked) })}
|
checked={value.recipientSigned}
|
||||||
/>
|
onCheckedChange={(checked) =>
|
||||||
|
onChange({ ...value, [DocumentEmailEvents.RecipientSigned]: Boolean(checked) })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.RecipientSigned}
|
htmlFor={DocumentEmailEvents.RecipientSigned}
|
||||||
>
|
>
|
||||||
<Trans>Email the owner when a recipient signs</Trans>
|
<Trans>Email the owner when a recipient signs</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Recipient signed email</Trans>
|
<Trans>Recipient signed email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>This email is sent to the document owner when a recipient has signed the document.</Trans>
|
<Trans>This email is sent to the document owner when a recipient has signed the document.</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.RecipientSigningRequest) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.RecipientSigningRequest}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.RecipientSigningRequest}
|
||||||
checked={value.recipientSigningRequest}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) =>
|
checked={value.recipientSigningRequest}
|
||||||
onChange({ ...value, [DocumentEmailEvents.RecipientSigningRequest]: Boolean(checked) })
|
onCheckedChange={(checked) =>
|
||||||
}
|
onChange({ ...value, [DocumentEmailEvents.RecipientSigningRequest]: Boolean(checked) })
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.RecipientSigningRequest}
|
htmlFor={DocumentEmailEvents.RecipientSigningRequest}
|
||||||
>
|
>
|
||||||
<Trans>Email recipients with a signing request</Trans>
|
<Trans>Email recipients with a signing request</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Recipient signing request email</Trans>
|
<Trans>Recipient signing request email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>This email is sent to the recipient requesting them to sign the document.</Trans>
|
<Trans>This email is sent to the recipient requesting them to sign the document.</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.RecipientRemoved) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.RecipientRemoved}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.RecipientRemoved}
|
||||||
checked={value.recipientRemoved}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) =>
|
checked={value.recipientRemoved}
|
||||||
onChange({ ...value, [DocumentEmailEvents.RecipientRemoved]: Boolean(checked) })
|
onCheckedChange={(checked) =>
|
||||||
}
|
onChange({ ...value, [DocumentEmailEvents.RecipientRemoved]: Boolean(checked) })
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.RecipientRemoved}
|
htmlFor={DocumentEmailEvents.RecipientRemoved}
|
||||||
>
|
>
|
||||||
<Trans>Email recipients when they're removed from a pending document</Trans>
|
<Trans>Email recipients when they're removed from a pending document</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Recipient removed email</Trans>
|
<Trans>Recipient removed email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>This email is sent to the recipient if they are removed from a pending document.</Trans>
|
<Trans>This email is sent to the recipient if they are removed from a pending document.</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.DocumentPending) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.DocumentPending}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.DocumentPending}
|
||||||
checked={value.documentPending}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) => onChange({ ...value, [DocumentEmailEvents.DocumentPending]: Boolean(checked) })}
|
checked={value.documentPending}
|
||||||
/>
|
onCheckedChange={(checked) =>
|
||||||
|
onChange({ ...value, [DocumentEmailEvents.DocumentPending]: Boolean(checked) })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.DocumentPending}
|
htmlFor={DocumentEmailEvents.DocumentPending}
|
||||||
>
|
>
|
||||||
<Trans>Email the signer if the document is still pending</Trans>
|
<Trans>Email the signer if the document is still pending</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Document pending email</Trans>
|
<Trans>Document pending email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>
|
<Trans>
|
||||||
This email will be sent to the recipient who has just signed the document, if there are still other
|
This email will be sent to the recipient who has just signed the document, if there are still other
|
||||||
recipients who have not signed yet.
|
recipients who have not signed yet.
|
||||||
</Trans>
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.DocumentCompleted) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.DocumentCompleted}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.DocumentCompleted}
|
||||||
checked={value.documentCompleted}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) =>
|
checked={value.documentCompleted}
|
||||||
onChange({ ...value, [DocumentEmailEvents.DocumentCompleted]: Boolean(checked) })
|
onCheckedChange={(checked) =>
|
||||||
}
|
onChange({ ...value, [DocumentEmailEvents.DocumentCompleted]: Boolean(checked) })
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.DocumentCompleted}
|
htmlFor={DocumentEmailEvents.DocumentCompleted}
|
||||||
>
|
>
|
||||||
<Trans>Email recipients when the document is completed</Trans>
|
<Trans>Email recipients when the document is completed</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Document completed email</Trans>
|
<Trans>Document completed email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>This will be sent to all recipients once the document has been fully completed.</Trans>
|
<Trans>This will be sent to all recipients once the document has been fully completed.</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.DocumentDeleted) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.DocumentDeleted}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.DocumentDeleted}
|
||||||
checked={value.documentDeleted}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) => onChange({ ...value, [DocumentEmailEvents.DocumentDeleted]: Boolean(checked) })}
|
checked={value.documentDeleted}
|
||||||
/>
|
onCheckedChange={(checked) =>
|
||||||
|
onChange({ ...value, [DocumentEmailEvents.DocumentDeleted]: Boolean(checked) })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.DocumentDeleted}
|
htmlFor={DocumentEmailEvents.DocumentDeleted}
|
||||||
>
|
>
|
||||||
<Trans>Email recipients when a pending document is deleted</Trans>
|
<Trans>Email recipients when a pending document is deleted</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Document deleted email</Trans>
|
<Trans>Document deleted email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>This will be sent to all recipients if a pending document has been deleted.</Trans>
|
<Trans>This will be sent to all recipients if a pending document has been deleted.</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.OwnerDocumentCompleted) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.OwnerDocumentCompleted}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.OwnerDocumentCompleted}
|
||||||
checked={value.ownerDocumentCompleted}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) =>
|
checked={value.ownerDocumentCompleted}
|
||||||
onChange({ ...value, [DocumentEmailEvents.OwnerDocumentCompleted]: Boolean(checked) })
|
onCheckedChange={(checked) =>
|
||||||
}
|
onChange({ ...value, [DocumentEmailEvents.OwnerDocumentCompleted]: Boolean(checked) })
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.OwnerDocumentCompleted}
|
htmlFor={DocumentEmailEvents.OwnerDocumentCompleted}
|
||||||
>
|
>
|
||||||
<Trans>Email the owner when the document is completed</Trans>
|
<Trans>Email the owner when the document is completed</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Document completed email</Trans>
|
<Trans>Document completed email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>This will be sent to the document owner once the document has been fully completed.</Trans>
|
<Trans>This will be sent to the document owner once the document has been fully completed.</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.OwnerDocumentCreated) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.OwnerDocumentCreated}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.OwnerDocumentCreated}
|
||||||
checked={value.ownerDocumentCreated}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) =>
|
checked={value.ownerDocumentCreated}
|
||||||
onChange({ ...value, [DocumentEmailEvents.OwnerDocumentCreated]: Boolean(checked) })
|
onCheckedChange={(checked) =>
|
||||||
}
|
onChange({ ...value, [DocumentEmailEvents.OwnerDocumentCreated]: Boolean(checked) })
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.OwnerDocumentCreated}
|
htmlFor={DocumentEmailEvents.OwnerDocumentCreated}
|
||||||
>
|
>
|
||||||
<Trans>Email the owner when a document is created from a direct template</Trans>
|
<Trans>Email the owner when a document is created from a direct template</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Document created from direct template email</Trans>
|
<Trans>Document created from direct template email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>
|
<Trans>
|
||||||
This email is sent to the document owner when a recipient creates a document via a direct template
|
This email is sent to the document owner when a recipient creates a document via a direct template
|
||||||
link.
|
link.
|
||||||
</Trans>
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
{!isHidden(DocumentEmailEvents.OwnerRecipientExpired) && (
|
||||||
<Checkbox
|
<div className="flex flex-row items-center">
|
||||||
id={DocumentEmailEvents.OwnerRecipientExpired}
|
<Checkbox
|
||||||
className="h-5 w-5"
|
id={DocumentEmailEvents.OwnerRecipientExpired}
|
||||||
checked={value.ownerRecipientExpired}
|
className="h-5 w-5"
|
||||||
onCheckedChange={(checked) =>
|
checked={value.ownerRecipientExpired}
|
||||||
onChange({ ...value, [DocumentEmailEvents.OwnerRecipientExpired]: Boolean(checked) })
|
onCheckedChange={(checked) =>
|
||||||
}
|
onChange({ ...value, [DocumentEmailEvents.OwnerRecipientExpired]: Boolean(checked) })
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
className="ml-2 flex flex-row items-center text-muted-foreground text-sm"
|
||||||
htmlFor={DocumentEmailEvents.OwnerRecipientExpired}
|
htmlFor={DocumentEmailEvents.OwnerRecipientExpired}
|
||||||
>
|
>
|
||||||
<Trans>Send recipient expired email to the owner</Trans>
|
<Trans>Send recipient expired email to the owner</Trans>
|
||||||
|
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger>
|
<TooltipTrigger>
|
||||||
<InfoIcon className="mx-2 h-4 w-4" />
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
|
|
||||||
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
<h2>
|
<h2>
|
||||||
<strong>
|
<strong>
|
||||||
<Trans>Recipient expired email</Trans>
|
<Trans>Recipient expired email</Trans>
|
||||||
</strong>
|
</strong>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<Trans>This will be sent to the document owner when a recipient's signing window has expired.</Trans>
|
<Trans>This will be sent to the document owner when a recipient's signing window has expired.</Trans>
|
||||||
</p>
|
</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user