mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 08:13:56 +10:00
feat: edit recipients when creating document from template (#953)
https://github.com/documenso/documenso/assets/55143799/85a840e3-4fb4-4c02-ba63-b9626f4cea58
This commit is contained in:
@ -107,6 +107,8 @@ test('[TEMPLATES]: delete template', async ({ page }) => {
|
||||
await page.getByRole('menuitem', { name: 'Delete' }).click();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await expect(page.getByText('Template deleted').first()).toBeVisible();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
|
||||
await unseedTeam(team.url);
|
||||
@ -187,15 +189,18 @@ test('[TEMPLATES]: use template', async ({ page }) => {
|
||||
|
||||
// Use personal template.
|
||||
await page.getByRole('button', { name: 'Use Template' }).click();
|
||||
await page.getByRole('button', { name: 'Create Document' }).click();
|
||||
await page.waitForURL(/documents/);
|
||||
await page.getByRole('main').getByRole('link', { name: 'Documents' }).click();
|
||||
await page.waitForURL('/documents');
|
||||
await expect(page.getByRole('main')).toContainText('Showing 1 result');
|
||||
|
||||
await page.goto(`${WEBAPP_BASE_URL}/t/${team.url}/templates`);
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Use team template.
|
||||
await page.getByRole('button', { name: 'Use Template' }).click();
|
||||
await page.getByRole('button', { name: 'Create Document' }).click();
|
||||
await page.waitForURL(/\/t\/.+\/documents/);
|
||||
await page.getByRole('main').getByRole('link', { name: 'Documents' }).click();
|
||||
await page.waitForURL(`/t/${team.url}/documents`);
|
||||
|
||||
@ -1,14 +1,21 @@
|
||||
import { nanoid } from '@documenso/lib/universal/id';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import type { TCreateDocumentFromTemplateMutationSchema } from '@documenso/trpc/server/template-router/schema';
|
||||
import type { RecipientRole } from '@documenso/prisma/client';
|
||||
|
||||
export type CreateDocumentFromTemplateOptions = TCreateDocumentFromTemplateMutationSchema & {
|
||||
export type CreateDocumentFromTemplateOptions = {
|
||||
templateId: number;
|
||||
userId: number;
|
||||
recipients?: {
|
||||
name?: string;
|
||||
email: string;
|
||||
role?: RecipientRole;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const createDocumentFromTemplate = async ({
|
||||
templateId,
|
||||
userId,
|
||||
recipients,
|
||||
}: CreateDocumentFromTemplateOptions) => {
|
||||
const template = await prisma.template.findUnique({
|
||||
where: {
|
||||
@ -64,7 +71,11 @@ export const createDocumentFromTemplate = async ({
|
||||
},
|
||||
|
||||
include: {
|
||||
Recipient: true,
|
||||
Recipient: {
|
||||
orderBy: {
|
||||
id: 'asc',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -89,5 +100,34 @@ export const createDocumentFromTemplate = async ({
|
||||
}),
|
||||
});
|
||||
|
||||
if (recipients && recipients.length > 0) {
|
||||
document.Recipient = await Promise.all(
|
||||
recipients.map(async (recipient, index) => {
|
||||
const existingRecipient = document.Recipient.at(index);
|
||||
|
||||
return await prisma.recipient.upsert({
|
||||
where: {
|
||||
documentId_email: {
|
||||
documentId: document.id,
|
||||
email: existingRecipient?.email ?? recipient.email,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
name: recipient.name,
|
||||
email: recipient.email,
|
||||
role: recipient.role,
|
||||
},
|
||||
create: {
|
||||
documentId: document.id,
|
||||
email: recipient.email,
|
||||
name: recipient.name,
|
||||
role: recipient.role,
|
||||
token: nanoid(),
|
||||
},
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return document;
|
||||
};
|
||||
|
||||
@ -38,6 +38,7 @@ export const findTemplates = async ({
|
||||
include: {
|
||||
templateDocumentData: true,
|
||||
Field: true,
|
||||
Recipient: true,
|
||||
},
|
||||
skip: Math.max(page - 1, 0) * perPage,
|
||||
orderBy: {
|
||||
|
||||
@ -2,7 +2,7 @@ import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
import { prisma } from '..';
|
||||
import { DocumentDataType } from '../client';
|
||||
import { DocumentDataType, ReadStatus, RecipientRole, SendStatus, SigningStatus } from '../client';
|
||||
|
||||
const examplePdf = fs
|
||||
.readFileSync(path.join(__dirname, '../../../assets/example.pdf'))
|
||||
@ -28,9 +28,36 @@ export const seedTemplate = async (options: SeedTemplateOptions) => {
|
||||
return await prisma.template.create({
|
||||
data: {
|
||||
title,
|
||||
templateDocumentDataId: documentData.id,
|
||||
userId: userId,
|
||||
teamId,
|
||||
templateDocumentData: {
|
||||
connect: {
|
||||
id: documentData.id,
|
||||
},
|
||||
},
|
||||
User: {
|
||||
connect: {
|
||||
id: userId,
|
||||
},
|
||||
},
|
||||
Recipient: {
|
||||
create: {
|
||||
email: 'recipient.1@documenso.com',
|
||||
name: 'Recipient 1',
|
||||
token: Math.random().toString().slice(2, 7),
|
||||
sendStatus: SendStatus.NOT_SENT,
|
||||
signingStatus: SigningStatus.NOT_SIGNED,
|
||||
readStatus: ReadStatus.NOT_OPENED,
|
||||
role: RecipientRole.SIGNER,
|
||||
},
|
||||
},
|
||||
...(teamId
|
||||
? {
|
||||
team: {
|
||||
connect: {
|
||||
id: teamId,
|
||||
},
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -52,6 +52,7 @@ export const templateRouter = router({
|
||||
return await createDocumentFromTemplate({
|
||||
templateId,
|
||||
userId: ctx.user.id,
|
||||
recipients: input.recipients,
|
||||
});
|
||||
} catch (err) {
|
||||
throw new TRPCError({
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { RecipientRole } from '@documenso/prisma/client';
|
||||
|
||||
export const ZCreateTemplateMutationSchema = z.object({
|
||||
title: z.string().min(1).trim(),
|
||||
teamId: z.number().optional(),
|
||||
@ -8,6 +10,15 @@ export const ZCreateTemplateMutationSchema = z.object({
|
||||
|
||||
export const ZCreateDocumentFromTemplateMutationSchema = z.object({
|
||||
templateId: z.number(),
|
||||
recipients: z
|
||||
.array(
|
||||
z.object({
|
||||
email: z.string().email(),
|
||||
name: z.string(),
|
||||
role: z.nativeEnum(RecipientRole),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const ZDuplicateTemplateMutationSchema = z.object({
|
||||
|
||||
Reference in New Issue
Block a user