mirror of
https://github.com/documenso/documenso.git
synced 2026-06-22 04:12:06 +10:00
feat: add option to disable Document created from template (#2609)
This commit is contained in:
@@ -219,7 +219,8 @@ export const EmailPreferencesForm = ({
|
|||||||
|
|
||||||
<FormDescription>
|
<FormDescription>
|
||||||
<Trans>
|
<Trans>
|
||||||
Controls the default email settings when new documents or templates are created
|
Controls the default email settings when new documents or templates are created.
|
||||||
|
Updating these settings will not affect existing documents or templates.
|
||||||
</Trans>
|
</Trans>
|
||||||
</FormDescription>
|
</FormDescription>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ test.describe('API V2 Envelopes', () => {
|
|||||||
documentDeleted: false,
|
documentDeleted: false,
|
||||||
ownerRecipientExpired: true,
|
ownerRecipientExpired: true,
|
||||||
ownerDocumentCompleted: true,
|
ownerDocumentCompleted: true,
|
||||||
|
ownerDocumentCreated: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
attachments: [
|
attachments: [
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ const DB_EXPECTED_VALUES = {
|
|||||||
documentDeleted: false,
|
documentDeleted: false,
|
||||||
ownerDocumentCompleted: false,
|
ownerDocumentCompleted: false,
|
||||||
ownerRecipientExpired: false,
|
ownerRecipientExpired: false,
|
||||||
|
ownerDocumentCreated: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -138,6 +139,7 @@ const runSettingsFlow = async (
|
|||||||
await root.locator('#documentDeleted').click();
|
await root.locator('#documentDeleted').click();
|
||||||
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('input[name="meta.emailReplyTo"]').fill(TEST_SETTINGS_VALUES.replyTo);
|
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('input[name="meta.subject"]').fill(TEST_SETTINGS_VALUES.subject);
|
||||||
await root.locator('textarea[name="meta.message"]').fill(TEST_SETTINGS_VALUES.message);
|
await root.locator('textarea[name="meta.message"]').fill(TEST_SETTINGS_VALUES.message);
|
||||||
@@ -207,6 +209,7 @@ const runSettingsFlow = async (
|
|||||||
await expect(root.locator('#documentDeleted')).toHaveAttribute('aria-checked', 'false');
|
await expect(root.locator('#documentDeleted')).toHaveAttribute('aria-checked', 'false');
|
||||||
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('input[name="meta.emailReplyTo"]')).toHaveValue(
|
await expect(root.locator('input[name="meta.emailReplyTo"]')).toHaveValue(
|
||||||
TEST_SETTINGS_VALUES.replyTo,
|
TEST_SETTINGS_VALUES.replyTo,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
|
|||||||
documentDeleted: false, // unchecked
|
documentDeleted: false, // unchecked
|
||||||
ownerRecipientExpired: true,
|
ownerRecipientExpired: true,
|
||||||
ownerDocumentCompleted: true,
|
ownerDocumentCompleted: true,
|
||||||
|
ownerDocumentCreated: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Edit the team email settings
|
// Edit the team email settings
|
||||||
@@ -271,6 +272,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
|
|||||||
documentDeleted: true,
|
documentDeleted: true,
|
||||||
ownerRecipientExpired: true,
|
ownerRecipientExpired: true,
|
||||||
ownerDocumentCompleted: false,
|
ownerDocumentCompleted: false,
|
||||||
|
ownerDocumentCreated: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify that a document can be created successfully with the team email settings
|
// Verify that a document can be created successfully with the team email settings
|
||||||
@@ -292,6 +294,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
|
|||||||
documentDeleted: true,
|
documentDeleted: true,
|
||||||
ownerRecipientExpired: true,
|
ownerRecipientExpired: true,
|
||||||
ownerDocumentCompleted: false,
|
ownerDocumentCompleted: false,
|
||||||
|
ownerDocumentCreated: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test inheritance by setting team back to inherit from organisation
|
// Test inheritance by setting team back to inherit from organisation
|
||||||
@@ -318,6 +321,7 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
|
|||||||
documentDeleted: false,
|
documentDeleted: false,
|
||||||
ownerRecipientExpired: true,
|
ownerRecipientExpired: true,
|
||||||
ownerDocumentCompleted: true,
|
ownerDocumentCompleted: true,
|
||||||
|
ownerDocumentCreated: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify that a document can be created successfully with the email settings
|
// Verify that a document can be created successfully with the email settings
|
||||||
@@ -339,5 +343,6 @@ test('[ORGANISATIONS]: manage email preferences', async ({ page }) => {
|
|||||||
documentDeleted: false,
|
documentDeleted: false,
|
||||||
ownerRecipientExpired: true,
|
ownerRecipientExpired: true,
|
||||||
ownerDocumentCompleted: true,
|
ownerDocumentCompleted: true,
|
||||||
|
ownerDocumentCreated: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { jobs } from '../../jobs/client';
|
|||||||
import { DOCUMENT_AUDIT_LOG_TYPE, RECIPIENT_DIFF_TYPE } from '../../types/document-audit-logs';
|
import { DOCUMENT_AUDIT_LOG_TYPE, RECIPIENT_DIFF_TYPE } from '../../types/document-audit-logs';
|
||||||
import type { TRecipientActionAuthTypes } from '../../types/document-auth';
|
import type { TRecipientActionAuthTypes } from '../../types/document-auth';
|
||||||
import { DocumentAccessAuth, ZRecipientAuthOptionsSchema } from '../../types/document-auth';
|
import { DocumentAccessAuth, ZRecipientAuthOptionsSchema } from '../../types/document-auth';
|
||||||
|
import { extractDerivedDocumentEmailSettings } from '../../types/document-email';
|
||||||
import { ZFieldMetaSchema } from '../../types/field-meta';
|
import { ZFieldMetaSchema } from '../../types/field-meta';
|
||||||
import {
|
import {
|
||||||
ZWebhookDocumentSchema,
|
ZWebhookDocumentSchema,
|
||||||
@@ -743,14 +744,17 @@ export const createDocumentFromDirectTemplate = async ({
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send email to template owner via background job.
|
const emailSettings = extractDerivedDocumentEmailSettings(documentMeta);
|
||||||
await jobs.triggerJob({
|
|
||||||
name: 'send.document.created.from.direct.template.email',
|
if (emailSettings.ownerDocumentCreated) {
|
||||||
payload: {
|
await jobs.triggerJob({
|
||||||
envelopeId: createdEnvelope.id,
|
name: 'send.document.created.from.direct.template.email',
|
||||||
recipientId,
|
payload: {
|
||||||
},
|
envelopeId: createdEnvelope.id,
|
||||||
});
|
recipientId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// This handles sending emails and sealing the document if required.
|
// This handles sending emails and sealing the document if required.
|
||||||
|
|||||||
@@ -440,6 +440,7 @@ export const generateSampleWebhookPayload = (
|
|||||||
documentCompleted: true,
|
documentCompleted: true,
|
||||||
ownerDocumentCompleted: true,
|
ownerDocumentCompleted: true,
|
||||||
ownerRecipientExpired: true,
|
ownerRecipientExpired: true,
|
||||||
|
ownerDocumentCreated: true,
|
||||||
recipientSigningRequest: true,
|
recipientSigningRequest: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export enum DocumentEmailEvents {
|
|||||||
DocumentDeleted = 'documentDeleted',
|
DocumentDeleted = 'documentDeleted',
|
||||||
OwnerDocumentCompleted = 'ownerDocumentCompleted',
|
OwnerDocumentCompleted = 'ownerDocumentCompleted',
|
||||||
OwnerRecipientExpired = 'ownerRecipientExpired',
|
OwnerRecipientExpired = 'ownerRecipientExpired',
|
||||||
|
OwnerDocumentCreated = 'ownerDocumentCreated',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ZDocumentEmailSettingsSchema = z
|
export const ZDocumentEmailSettingsSchema = z
|
||||||
@@ -59,6 +60,12 @@ export const ZDocumentEmailSettingsSchema = z
|
|||||||
"Whether to send an email to the document owner when a recipient's signing window has expired.",
|
"Whether to send an email to the document owner when a recipient's signing window has expired.",
|
||||||
)
|
)
|
||||||
.default(true),
|
.default(true),
|
||||||
|
ownerDocumentCreated: z
|
||||||
|
.boolean()
|
||||||
|
.describe(
|
||||||
|
'Whether to send an email to the document owner when a document is created from a direct template.',
|
||||||
|
)
|
||||||
|
.default(true),
|
||||||
})
|
})
|
||||||
.strip()
|
.strip()
|
||||||
.catch(() => ({ ...DEFAULT_DOCUMENT_EMAIL_SETTINGS }));
|
.catch(() => ({ ...DEFAULT_DOCUMENT_EMAIL_SETTINGS }));
|
||||||
@@ -86,6 +93,7 @@ export const extractDerivedDocumentEmailSettings = (
|
|||||||
documentDeleted: false,
|
documentDeleted: false,
|
||||||
ownerDocumentCompleted: emailSettings.ownerDocumentCompleted,
|
ownerDocumentCompleted: emailSettings.ownerDocumentCompleted,
|
||||||
ownerRecipientExpired: emailSettings.ownerRecipientExpired,
|
ownerRecipientExpired: emailSettings.ownerRecipientExpired,
|
||||||
|
ownerDocumentCreated: emailSettings.ownerDocumentCreated,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,4 +106,5 @@ export const DEFAULT_DOCUMENT_EMAIL_SETTINGS: TDocumentEmailSettings = {
|
|||||||
documentDeleted: true,
|
documentDeleted: true,
|
||||||
ownerDocumentCompleted: true,
|
ownerDocumentCompleted: true,
|
||||||
ownerRecipientExpired: true,
|
ownerRecipientExpired: true,
|
||||||
|
ownerDocumentCreated: true,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -291,6 +291,45 @@ export const DocumentEmailCheckboxes = ({
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-row items-center">
|
||||||
|
<Checkbox
|
||||||
|
id={DocumentEmailEvents.OwnerDocumentCreated}
|
||||||
|
className="h-5 w-5"
|
||||||
|
checked={value.ownerDocumentCreated}
|
||||||
|
onCheckedChange={(checked) =>
|
||||||
|
onChange({ ...value, [DocumentEmailEvents.OwnerDocumentCreated]: Boolean(checked) })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<label
|
||||||
|
className="ml-2 flex flex-row items-center text-sm text-muted-foreground"
|
||||||
|
htmlFor={DocumentEmailEvents.OwnerDocumentCreated}
|
||||||
|
>
|
||||||
|
<Trans>Email the owner when a document is created from a direct template</Trans>
|
||||||
|
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<InfoIcon className="mx-2 h-4 w-4" />
|
||||||
|
</TooltipTrigger>
|
||||||
|
|
||||||
|
<TooltipContent className="max-w-md space-y-2 p-4 text-foreground">
|
||||||
|
<h2>
|
||||||
|
<strong>
|
||||||
|
<Trans>Document created from direct template email</Trans>
|
||||||
|
</strong>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<Trans>
|
||||||
|
This email is sent to the document owner when a recipient creates a document via a
|
||||||
|
direct template link.
|
||||||
|
</Trans>
|
||||||
|
</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={DocumentEmailEvents.OwnerRecipientExpired}
|
id={DocumentEmailEvents.OwnerRecipientExpired}
|
||||||
|
|||||||
Reference in New Issue
Block a user