2023-10-06 22:54:24 +00:00
|
|
|
import { z } from 'zod';
|
|
|
|
|
2024-05-10 19:45:19 +07:00
|
|
|
import {
|
|
|
|
ZDocumentAccessAuthTypesSchema,
|
|
|
|
ZDocumentActionAuthTypesSchema,
|
|
|
|
} from '@documenso/lib/types/document-auth';
|
2024-06-06 14:46:48 +10:00
|
|
|
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params';
|
2024-07-31 07:26:05 +02:00
|
|
|
import { isValidRedirectUrl } from '@documenso/lib/utils/is-valid-redirect-url';
|
2024-09-16 12:36:45 +00:00
|
|
|
import { DocumentSigningOrder, TemplateType } from '@documenso/prisma/client';
|
2024-05-10 19:45:19 +07:00
|
|
|
|
2024-06-02 15:49:09 +10:00
|
|
|
import { ZSignFieldWithTokenMutationSchema } from '../field-router/schema';
|
|
|
|
|
2023-10-06 22:54:24 +00:00
|
|
|
export const ZCreateTemplateMutationSchema = z.object({
|
2024-02-08 12:33:20 +11:00
|
|
|
title: z.string().min(1).trim(),
|
|
|
|
teamId: z.number().optional(),
|
2023-10-06 22:54:24 +00:00
|
|
|
templateDocumentDataId: z.string().min(1),
|
|
|
|
});
|
|
|
|
|
2024-06-02 15:49:09 +10:00
|
|
|
export const ZCreateDocumentFromDirectTemplateMutationSchema = z.object({
|
2024-07-05 03:03:22 +00:00
|
|
|
directRecipientName: z.string().optional(),
|
2024-06-02 15:49:09 +10:00
|
|
|
directRecipientEmail: z.string().email(),
|
|
|
|
directTemplateToken: z.string().min(1),
|
2024-08-09 11:06:17 +10:00
|
|
|
directTemplateExternalId: z.string().optional(),
|
2024-06-02 15:49:09 +10:00
|
|
|
signedFieldValues: z.array(ZSignFieldWithTokenMutationSchema),
|
|
|
|
templateUpdatedAt: z.date(),
|
|
|
|
});
|
|
|
|
|
2023-10-06 22:54:24 +00:00
|
|
|
export const ZCreateDocumentFromTemplateMutationSchema = z.object({
|
|
|
|
templateId: z.number(),
|
2024-02-26 10:31:24 +11:00
|
|
|
teamId: z.number().optional(),
|
2024-02-20 19:11:12 +00:00
|
|
|
recipients: z
|
|
|
|
.array(
|
|
|
|
z.object({
|
2024-05-07 15:04:12 +07:00
|
|
|
id: z.number(),
|
2024-02-20 19:11:12 +00:00
|
|
|
email: z.string().email(),
|
2024-05-07 15:04:12 +07:00
|
|
|
name: z.string().optional(),
|
2024-02-20 19:11:12 +00:00
|
|
|
}),
|
|
|
|
)
|
2024-05-07 15:04:12 +07:00
|
|
|
.refine((recipients) => {
|
|
|
|
const emails = recipients.map((signer) => signer.email);
|
|
|
|
return new Set(emails).size === emails.length;
|
|
|
|
}, 'Recipients must have unique emails'),
|
|
|
|
sendDocument: z.boolean().optional(),
|
2023-10-06 22:54:24 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
export const ZDuplicateTemplateMutationSchema = z.object({
|
|
|
|
templateId: z.number(),
|
2024-02-08 12:33:20 +11:00
|
|
|
teamId: z.number().optional(),
|
2023-10-06 22:54:24 +00:00
|
|
|
});
|
|
|
|
|
2024-06-02 15:49:09 +10:00
|
|
|
export const ZCreateTemplateDirectLinkMutationSchema = z.object({
|
|
|
|
templateId: z.number().min(1),
|
2024-07-22 20:52:17 +10:00
|
|
|
teamId: z.number().optional(),
|
2024-06-02 15:49:09 +10:00
|
|
|
directRecipientId: z.number().min(1).optional(),
|
|
|
|
});
|
|
|
|
|
|
|
|
export const ZDeleteTemplateDirectLinkMutationSchema = z.object({
|
|
|
|
templateId: z.number().min(1),
|
|
|
|
});
|
|
|
|
|
|
|
|
export const ZToggleTemplateDirectLinkMutationSchema = z.object({
|
|
|
|
templateId: z.number().min(1),
|
|
|
|
enabled: z.boolean(),
|
|
|
|
});
|
|
|
|
|
2023-10-06 22:54:24 +00:00
|
|
|
export const ZDeleteTemplateMutationSchema = z.object({
|
|
|
|
id: z.number().min(1),
|
feat: add more template API endpoints (#1198)
## Description
Update the API endpoint to support more actions for templates
## Changes Made
Add the following endpoints for templates:
- Get template
- Get templates
- Delete template
Get template(s) returns associated recipients and fields.
UI:
- Updated template delete button to have the destructive delete variant
## Testing Performed
Tested endpoints via /api/v1/openapi
Tested deleting templates via UI manually
## Test data
<details>
<summary>Delete template response</summary>
```json
{
"id": 32,
"type": "PRIVATE",
"title": "documenso-supporter-pledge.pdf",
"userId": 3,
"teamId": null,
"templateDocumentDataId": "clxva9b4h0001rrh7v0wdw97h",
"createdAt": "2024-06-26T03:35:45.065Z",
"updatedAt": "2024-06-26T03:35:45.065Z"
}
```
</details>
<details>
<summary>Get template response</summary>
```json
{
"id": 28,
"type": "PRIVATE",
"title": "blank_long.pdf",
"userId": 3,
"teamId": null,
"templateDocumentDataId": "clxu4vyty0003rrr52ue5ee4d",
"createdAt": "2024-06-25T08:17:38.418Z",
"updatedAt": "2024-06-26T03:36:33.890Z",
"templateMeta": {
"id": "clxvaacte0004rrh7s2k910nw",
"subject": "",
"message": "",
"timezone": "Australia/Melbourne",
"dateFormat": "yyyy-MM-dd hh:mm a",
"templateId": 28,
"redirectUrl": ""
},
"directLink": {
"token": "tBJHVFR75sC8m6hPfBTZd",
"enabled": true
},
"templateDocumentData": {
"id": "clxu4vyty0003rrr52ue5ee4d",
"type": "BYTES_64",
"data": "<PDF DATA>"
},
"Field": [
{
"id": 327,
"recipientId": 357,
"type": "SIGNATURE",
"page": 1,
"positionX": "55.8431952662722",
"positionY": "21.39588100686499",
"width": "29.58579881656805",
"height": "6.864988558352403"
},
{
"id": 328,
"recipientId": 357,
"type": "EMAIL",
"page": 1,
"positionX": "28.03254437869823",
"positionY": "72.99771167048056",
"width": "29.58579881656805",
"height": "6.864988558352403"
}
],
"Recipient": [
{
"id": 357,
"email": "direct.link@documenso.com",
"name": "Direct link recipient",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER"
},
{
"id": 359,
"email": "example@documenso.com",
"name": "Example User",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER"
}
]
}
```
</details>
<details>
<summary>Get templates response</summary>
```json
{
"templates": [
{
"id": 33,
"type": "PRIVATE",
"title": "documenso-supporter-pledge.pdf",
"userId": 3,
"teamId": null,
"templateDocumentDataId": "clxva9oaj0003rrh7hwdyg60o",
"createdAt": "2024-06-26T03:36:02.130Z",
"updatedAt": "2024-06-26T03:36:02.130Z",
"directLink": null,
"Field": [],
"Recipient": []
},
{
"id": 28,
"type": "PRIVATE",
"title": "blank_long.pdf",
"userId": 3,
"teamId": null,
"templateDocumentDataId": "clxu4vyty0003rrr52ue5ee4d",
"createdAt": "2024-06-25T08:17:38.418Z",
"updatedAt": "2024-06-26T03:36:33.890Z",
"directLink": {
"token": "tBJHVFR75sC8m6hPfBTZd",
"enabled": true
},
"Field": [
{
"id": 327,
"recipientId": 357,
"type": "SIGNATURE",
"page": 1,
"positionX": "55.8431952662722",
"positionY": "21.39588100686499",
"width": "29.58579881656805",
"height": "6.864988558352403"
},
{
"id": 328,
"recipientId": 357,
"type": "EMAIL",
"page": 1,
"positionX": "28.03254437869823",
"positionY": "72.99771167048056",
"width": "29.58579881656805",
"height": "6.864988558352403"
}
],
"Recipient": [
{
"id": 357,
"email": "direct.link@documenso.com",
"name": "Direct link recipient",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER"
},
{
"id": 359,
"email": "example@documenso.com",
"name": "Example User",
"authOptions": {
"accessAuth": null,
"actionAuth": null
},
"role": "SIGNER"
}
]
}
],
"totalPages": 2
}
```
</details>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added support for team-based template deletion in the dashboard.
- Enhanced API to manage templates, including fetching and deleting
templates by team ID.
- **Bug Fixes**
- Improved error handling for template operations, ensuring better
feedback when templates are not found.
- **Refactor**
- Updated various components and functions to include `teamId` for more
robust template management.
- **Documentation**
- Expanded schema definitions to detail new structures for template and
team interactions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2024-06-27 15:44:16 +10:00
|
|
|
teamId: z.number().optional(),
|
2023-10-06 22:54:24 +00:00
|
|
|
});
|
|
|
|
|
2024-06-06 14:46:48 +10:00
|
|
|
export const MAX_TEMPLATE_PUBLIC_TITLE_LENGTH = 50;
|
|
|
|
export const MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH = 256;
|
|
|
|
|
2024-05-10 19:45:19 +07:00
|
|
|
export const ZUpdateTemplateSettingsMutationSchema = z.object({
|
|
|
|
templateId: z.number(),
|
|
|
|
teamId: z.number().min(1).optional(),
|
|
|
|
data: z.object({
|
|
|
|
title: z.string().min(1).optional(),
|
2024-07-13 16:45:09 +10:00
|
|
|
externalId: z.string().nullish(),
|
2024-05-10 19:45:19 +07:00
|
|
|
globalAccessAuth: ZDocumentAccessAuthTypesSchema.nullable().optional(),
|
|
|
|
globalActionAuth: ZDocumentActionAuthTypesSchema.nullable().optional(),
|
2024-06-06 14:46:48 +10:00
|
|
|
publicTitle: z.string().trim().min(1).max(MAX_TEMPLATE_PUBLIC_TITLE_LENGTH).optional(),
|
|
|
|
publicDescription: z
|
2024-05-10 19:45:19 +07:00
|
|
|
.string()
|
2024-06-06 14:46:48 +10:00
|
|
|
.trim()
|
|
|
|
.min(1)
|
|
|
|
.max(MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH)
|
|
|
|
.optional(),
|
|
|
|
type: z.nativeEnum(TemplateType).optional(),
|
2024-05-10 19:45:19 +07:00
|
|
|
}),
|
2024-06-06 14:46:48 +10:00
|
|
|
meta: z
|
|
|
|
.object({
|
|
|
|
subject: z.string(),
|
|
|
|
message: z.string(),
|
|
|
|
timezone: z.string(),
|
|
|
|
dateFormat: z.string(),
|
|
|
|
redirectUrl: z
|
|
|
|
.string()
|
|
|
|
.optional()
|
2024-07-31 07:26:05 +02:00
|
|
|
.refine((value) => value === undefined || value === '' || isValidRedirectUrl(value), {
|
|
|
|
message:
|
|
|
|
'Please enter a valid URL, make sure you include http:// or https:// part of the url.',
|
2024-06-06 14:46:48 +10:00
|
|
|
}),
|
|
|
|
})
|
|
|
|
.optional(),
|
|
|
|
});
|
|
|
|
|
2024-09-16 12:36:45 +00:00
|
|
|
export const ZSetSigningOrderForTemplateMutationSchema = z.object({
|
|
|
|
templateId: z.number(),
|
|
|
|
teamId: z.number().optional(),
|
|
|
|
signingOrder: z.nativeEnum(DocumentSigningOrder),
|
|
|
|
});
|
|
|
|
|
2024-06-06 14:46:48 +10:00
|
|
|
export const ZFindTemplatesQuerySchema = ZBaseTableSearchParamsSchema.extend({
|
|
|
|
teamId: z.number().optional(),
|
|
|
|
type: z.nativeEnum(TemplateType).optional(),
|
2024-05-10 19:45:19 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
export const ZGetTemplateWithDetailsByIdQuerySchema = z.object({
|
|
|
|
id: z.number().min(1),
|
|
|
|
});
|
|
|
|
|
2024-07-05 03:20:27 +00:00
|
|
|
export const ZMoveTemplatesToTeamSchema = z.object({
|
|
|
|
templateId: z.number(),
|
|
|
|
teamId: z.number(),
|
|
|
|
});
|
|
|
|
|
2023-10-06 22:54:24 +00:00
|
|
|
export type TCreateTemplateMutationSchema = z.infer<typeof ZCreateTemplateMutationSchema>;
|
|
|
|
export type TCreateDocumentFromTemplateMutationSchema = z.infer<
|
|
|
|
typeof ZCreateDocumentFromTemplateMutationSchema
|
|
|
|
>;
|
|
|
|
export type TDuplicateTemplateMutationSchema = z.infer<typeof ZDuplicateTemplateMutationSchema>;
|
|
|
|
export type TDeleteTemplateMutationSchema = z.infer<typeof ZDeleteTemplateMutationSchema>;
|
2024-05-10 19:45:19 +07:00
|
|
|
export type TGetTemplateWithDetailsByIdQuerySchema = z.infer<
|
|
|
|
typeof ZGetTemplateWithDetailsByIdQuerySchema
|
|
|
|
>;
|
2024-07-05 03:20:27 +00:00
|
|
|
export type TMoveTemplatesToSchema = z.infer<typeof ZMoveTemplatesToTeamSchema>;
|