mirror of
https://github.com/documenso/documenso.git
synced 2026-07-26 01:45:08 +10:00
feat: upload template via API (#1842)
Allow users to upload templates via both v1 and v2 APIs. Similar to uploading documents.
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
import { initContract } from '@ts-rest/core';
|
import { initContract } from '@ts-rest/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ZCreateTemplateV2RequestSchema,
|
||||||
|
ZCreateTemplateV2ResponseSchema,
|
||||||
|
} from '@documenso/trpc/server/template-router/schema';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ZAuthorizationHeadersSchema,
|
ZAuthorizationHeadersSchema,
|
||||||
ZCreateDocumentFromTemplateMutationResponseSchema,
|
ZCreateDocumentFromTemplateMutationResponseSchema,
|
||||||
@@ -87,6 +92,18 @@ export const ApiContractV1 = c.router(
|
|||||||
summary: 'Upload a new document and get a presigned URL',
|
summary: 'Upload a new document and get a presigned URL',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
createTemplate: {
|
||||||
|
method: 'POST',
|
||||||
|
path: '/api/v1/templates',
|
||||||
|
body: ZCreateTemplateV2RequestSchema,
|
||||||
|
responses: {
|
||||||
|
200: ZCreateTemplateV2ResponseSchema,
|
||||||
|
401: ZUnsuccessfulResponseSchema,
|
||||||
|
404: ZUnsuccessfulResponseSchema,
|
||||||
|
},
|
||||||
|
summary: 'Create a new template and get a presigned URL',
|
||||||
|
},
|
||||||
|
|
||||||
deleteTemplate: {
|
deleteTemplate: {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
path: '/api/v1/templates/:id',
|
path: '/api/v1/templates/:id',
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { setDocumentRecipients } from '@documenso/lib/server-only/recipient/set-
|
|||||||
import { updateDocumentRecipients } from '@documenso/lib/server-only/recipient/update-document-recipients';
|
import { updateDocumentRecipients } from '@documenso/lib/server-only/recipient/update-document-recipients';
|
||||||
import { createDocumentFromTemplate } from '@documenso/lib/server-only/template/create-document-from-template';
|
import { createDocumentFromTemplate } from '@documenso/lib/server-only/template/create-document-from-template';
|
||||||
import { createDocumentFromTemplateLegacy } from '@documenso/lib/server-only/template/create-document-from-template-legacy';
|
import { createDocumentFromTemplateLegacy } from '@documenso/lib/server-only/template/create-document-from-template-legacy';
|
||||||
|
import { createTemplate } from '@documenso/lib/server-only/template/create-template';
|
||||||
import { deleteTemplate } from '@documenso/lib/server-only/template/delete-template';
|
import { deleteTemplate } from '@documenso/lib/server-only/template/delete-template';
|
||||||
import { findTemplates } from '@documenso/lib/server-only/template/find-templates';
|
import { findTemplates } from '@documenso/lib/server-only/template/find-templates';
|
||||||
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
|
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
|
||||||
@@ -400,6 +401,109 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
createTemplate: authenticatedMiddleware(async (args, user, team) => {
|
||||||
|
const { body } = args;
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
folderId,
|
||||||
|
externalId,
|
||||||
|
visibility,
|
||||||
|
globalAccessAuth,
|
||||||
|
globalActionAuth,
|
||||||
|
publicTitle,
|
||||||
|
publicDescription,
|
||||||
|
type,
|
||||||
|
meta,
|
||||||
|
} = body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (process.env.NEXT_PUBLIC_UPLOAD_TRANSPORT !== 's3') {
|
||||||
|
return {
|
||||||
|
status: 500,
|
||||||
|
body: {
|
||||||
|
message: 'Create template is not available without S3 transport.',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateFormat = meta?.dateFormat
|
||||||
|
? DATE_FORMATS.find((format) => format.value === meta?.dateFormat)
|
||||||
|
: DATE_FORMATS.find((format) => format.value === DEFAULT_DOCUMENT_DATE_FORMAT);
|
||||||
|
|
||||||
|
if (meta?.dateFormat && !dateFormat) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Invalid date format. Please provide a valid date format',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const timezone = meta?.timezone
|
||||||
|
? TIME_ZONES.find((tz) => tz === meta?.timezone)
|
||||||
|
: DEFAULT_DOCUMENT_TIME_ZONE;
|
||||||
|
|
||||||
|
const isTimeZoneValid = meta?.timezone ? TIME_ZONES.includes(String(timezone)) : true;
|
||||||
|
|
||||||
|
if (!isTimeZoneValid) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Invalid timezone. Please provide a valid timezone',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileName = title?.endsWith('.pdf') ? title : `${title}.pdf`;
|
||||||
|
|
||||||
|
const { url, key } = await getPresignPostUrl(fileName, 'application/pdf');
|
||||||
|
|
||||||
|
const templateDocumentData = await createDocumentData({
|
||||||
|
data: key,
|
||||||
|
type: DocumentDataType.S3_PATH,
|
||||||
|
});
|
||||||
|
|
||||||
|
const createdTemplate = await createTemplate({
|
||||||
|
userId: user.id,
|
||||||
|
teamId: team.id,
|
||||||
|
templateDocumentDataId: templateDocumentData.id,
|
||||||
|
data: {
|
||||||
|
title,
|
||||||
|
folderId,
|
||||||
|
externalId,
|
||||||
|
visibility,
|
||||||
|
globalAccessAuth,
|
||||||
|
globalActionAuth,
|
||||||
|
publicTitle,
|
||||||
|
publicDescription,
|
||||||
|
type,
|
||||||
|
},
|
||||||
|
meta,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fullTemplate = await getTemplateById({
|
||||||
|
id: createdTemplate.id,
|
||||||
|
userId: user.id,
|
||||||
|
teamId: team.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: {
|
||||||
|
uploadUrl: url,
|
||||||
|
template: fullTemplate,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'An error has occured while creating the template',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
deleteTemplate: authenticatedMiddleware(async (args, user, team, { logger }) => {
|
deleteTemplate: authenticatedMiddleware(async (args, user, team, { logger }) => {
|
||||||
const { id: templateId } = args.params;
|
const { id: templateId } = args.params;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,31 @@
|
|||||||
|
import type { DocumentVisibility, Template, TemplateMeta } from '@prisma/client';
|
||||||
import type { z } from 'zod';
|
import type { z } from 'zod';
|
||||||
|
|
||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
import { TemplateSchema } from '@documenso/prisma/generated/zod/modelSchema//TemplateSchema';
|
import { TemplateSchema } from '@documenso/prisma/generated/zod/modelSchema//TemplateSchema';
|
||||||
import type { TCreateTemplateMutationSchema } from '@documenso/trpc/server/template-router/schema';
|
|
||||||
|
|
||||||
import { AppError, AppErrorCode } from '../../errors/app-error';
|
import { AppError, AppErrorCode } from '../../errors/app-error';
|
||||||
|
import type { TDocumentAccessAuthTypes, TDocumentActionAuthTypes } from '../../types/document-auth';
|
||||||
|
import { createDocumentAuthOptions } from '../../utils/document-auth';
|
||||||
import { buildTeamWhereQuery } from '../../utils/teams';
|
import { buildTeamWhereQuery } from '../../utils/teams';
|
||||||
import { getTeamSettings } from '../team/get-team-settings';
|
import { getTeamSettings } from '../team/get-team-settings';
|
||||||
|
|
||||||
export type CreateTemplateOptions = TCreateTemplateMutationSchema & {
|
export type CreateTemplateOptions = {
|
||||||
userId: number;
|
userId: number;
|
||||||
teamId: number;
|
teamId: number;
|
||||||
|
templateDocumentDataId: string;
|
||||||
|
data: {
|
||||||
|
title: string;
|
||||||
|
folderId?: string;
|
||||||
|
externalId?: string | null;
|
||||||
|
visibility?: DocumentVisibility;
|
||||||
|
globalAccessAuth?: TDocumentAccessAuthTypes[];
|
||||||
|
globalActionAuth?: TDocumentActionAuthTypes[];
|
||||||
|
publicTitle?: string;
|
||||||
|
publicDescription?: string;
|
||||||
|
type?: Template['type'];
|
||||||
|
};
|
||||||
|
meta?: Partial<Omit<TemplateMeta, 'id' | 'templateId'>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ZCreateTemplateResponseSchema = TemplateSchema;
|
export const ZCreateTemplateResponseSchema = TemplateSchema;
|
||||||
@@ -18,12 +33,14 @@ export const ZCreateTemplateResponseSchema = TemplateSchema;
|
|||||||
export type TCreateTemplateResponse = z.infer<typeof ZCreateTemplateResponseSchema>;
|
export type TCreateTemplateResponse = z.infer<typeof ZCreateTemplateResponseSchema>;
|
||||||
|
|
||||||
export const createTemplate = async ({
|
export const createTemplate = async ({
|
||||||
title,
|
|
||||||
userId,
|
userId,
|
||||||
teamId,
|
teamId,
|
||||||
templateDocumentDataId,
|
templateDocumentDataId,
|
||||||
folderId,
|
data,
|
||||||
|
meta = {},
|
||||||
}: CreateTemplateOptions) => {
|
}: CreateTemplateOptions) => {
|
||||||
|
const { title, folderId } = data;
|
||||||
|
|
||||||
const team = await prisma.team.findFirst({
|
const team = await prisma.team.findFirst({
|
||||||
where: buildTeamWhereQuery({ teamId, userId }),
|
where: buildTeamWhereQuery({ teamId, userId }),
|
||||||
});
|
});
|
||||||
@@ -55,16 +72,27 @@ export const createTemplate = async ({
|
|||||||
return await prisma.template.create({
|
return await prisma.template.create({
|
||||||
data: {
|
data: {
|
||||||
title,
|
title,
|
||||||
|
teamId,
|
||||||
userId,
|
userId,
|
||||||
templateDocumentDataId,
|
templateDocumentDataId,
|
||||||
teamId,
|
folderId,
|
||||||
folderId: folderId,
|
externalId: data.externalId,
|
||||||
|
visibility: data.visibility ?? settings.documentVisibility,
|
||||||
|
authOptions: createDocumentAuthOptions({
|
||||||
|
globalAccessAuth: data.globalAccessAuth || [],
|
||||||
|
globalActionAuth: data.globalActionAuth || [],
|
||||||
|
}),
|
||||||
|
publicTitle: data.publicTitle,
|
||||||
|
publicDescription: data.publicDescription,
|
||||||
|
type: data.type,
|
||||||
templateMeta: {
|
templateMeta: {
|
||||||
create: {
|
create: {
|
||||||
language: settings.documentLanguage,
|
...meta,
|
||||||
typedSignatureEnabled: settings.typedSignatureEnabled,
|
language: meta?.language ?? settings.documentLanguage,
|
||||||
uploadSignatureEnabled: settings.uploadSignatureEnabled,
|
typedSignatureEnabled: meta?.typedSignatureEnabled ?? settings.typedSignatureEnabled,
|
||||||
drawSignatureEnabled: settings.drawSignatureEnabled,
|
uploadSignatureEnabled: meta?.uploadSignatureEnabled ?? settings.uploadSignatureEnabled,
|
||||||
|
drawSignatureEnabled: meta?.drawSignatureEnabled ?? settings.drawSignatureEnabled,
|
||||||
|
emailSettings: meta?.emailSettings || undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -207,7 +207,9 @@ export const seedTeamTemplateWithMeta = async (team: Team) => {
|
|||||||
const ownerUser = organisation.owner;
|
const ownerUser = organisation.owner;
|
||||||
|
|
||||||
const template = await createTemplate({
|
const template = await createTemplate({
|
||||||
title: `[TEST] Template ${nanoid(8)} - Draft`,
|
data: {
|
||||||
|
title: `[TEST] Template ${nanoid(8)} - Draft`,
|
||||||
|
},
|
||||||
userId: ownerUser.id,
|
userId: ownerUser.id,
|
||||||
teamId: team.id,
|
teamId: team.id,
|
||||||
templateDocumentDataId: documentData.id,
|
templateDocumentDataId: documentData.id,
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ export const documentRouter = router({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
document: createdDocument,
|
document: createdDocument,
|
||||||
folder: createdDocument.folder,
|
folder: createdDocument.folder, // Todo: Remove this prior to api-v2 release.
|
||||||
uploadUrl: url,
|
uploadUrl: url,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ export const createEmbeddingTemplateRoute = procedure
|
|||||||
// First create the template
|
// First create the template
|
||||||
const template = await createTemplate({
|
const template = await createTemplate({
|
||||||
userId: apiToken.userId,
|
userId: apiToken.userId,
|
||||||
title,
|
data: {
|
||||||
|
title,
|
||||||
|
},
|
||||||
templateDocumentDataId: documentDataId,
|
templateDocumentDataId: documentDataId,
|
||||||
teamId: apiToken.teamId ?? undefined,
|
teamId: apiToken.teamId ?? undefined,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import type { Document } from '@prisma/client';
|
import type { Document } from '@prisma/client';
|
||||||
|
import { DocumentDataType } from '@prisma/client';
|
||||||
import { TRPCError } from '@trpc/server';
|
import { TRPCError } from '@trpc/server';
|
||||||
|
|
||||||
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
|
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
|
||||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||||
import { jobs } from '@documenso/lib/jobs/client';
|
import { jobs } from '@documenso/lib/jobs/client';
|
||||||
|
import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data';
|
||||||
import { getDocumentWithDetailsById } from '@documenso/lib/server-only/document/get-document-with-details-by-id';
|
import { getDocumentWithDetailsById } from '@documenso/lib/server-only/document/get-document-with-details-by-id';
|
||||||
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
|
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
|
||||||
import {
|
import {
|
||||||
@@ -23,6 +25,7 @@ import { findTemplates } from '@documenso/lib/server-only/template/find-template
|
|||||||
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
|
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
|
||||||
import { toggleTemplateDirectLink } from '@documenso/lib/server-only/template/toggle-template-direct-link';
|
import { toggleTemplateDirectLink } from '@documenso/lib/server-only/template/toggle-template-direct-link';
|
||||||
import { updateTemplate } from '@documenso/lib/server-only/template/update-template';
|
import { updateTemplate } from '@documenso/lib/server-only/template/update-template';
|
||||||
|
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
|
||||||
|
|
||||||
import { ZGenericSuccessResponse, ZSuccessResponseSchema } from '../document-router/schema';
|
import { ZGenericSuccessResponse, ZSuccessResponseSchema } from '../document-router/schema';
|
||||||
import { authenticatedProcedure, maybeAuthenticatedProcedure, router } from '../trpc';
|
import { authenticatedProcedure, maybeAuthenticatedProcedure, router } from '../trpc';
|
||||||
@@ -34,6 +37,8 @@ import {
|
|||||||
ZCreateTemplateDirectLinkRequestSchema,
|
ZCreateTemplateDirectLinkRequestSchema,
|
||||||
ZCreateTemplateDirectLinkResponseSchema,
|
ZCreateTemplateDirectLinkResponseSchema,
|
||||||
ZCreateTemplateMutationSchema,
|
ZCreateTemplateMutationSchema,
|
||||||
|
ZCreateTemplateV2RequestSchema,
|
||||||
|
ZCreateTemplateV2ResponseSchema,
|
||||||
ZDeleteTemplateDirectLinkRequestSchema,
|
ZDeleteTemplateDirectLinkRequestSchema,
|
||||||
ZDeleteTemplateMutationSchema,
|
ZDeleteTemplateMutationSchema,
|
||||||
ZDuplicateTemplateMutationSchema,
|
ZDuplicateTemplateMutationSchema,
|
||||||
@@ -141,12 +146,88 @@ export const templateRouter = router({
|
|||||||
return await createTemplate({
|
return await createTemplate({
|
||||||
userId: ctx.user.id,
|
userId: ctx.user.id,
|
||||||
teamId,
|
teamId,
|
||||||
title,
|
|
||||||
templateDocumentDataId,
|
templateDocumentDataId,
|
||||||
folderId,
|
data: {
|
||||||
|
title,
|
||||||
|
folderId,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporariy endpoint for V2 Beta until we allow passthrough documents on create.
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
createTemplateTemporary: authenticatedProcedure
|
||||||
|
.meta({
|
||||||
|
openapi: {
|
||||||
|
method: 'POST',
|
||||||
|
path: '/template/create/beta',
|
||||||
|
summary: 'Create template',
|
||||||
|
description:
|
||||||
|
'You will need to upload the PDF to the provided URL returned. Note: Once V2 API is released, this will be removed since we will allow direct uploads, instead of using an upload URL.',
|
||||||
|
tags: ['Template'],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.input(ZCreateTemplateV2RequestSchema)
|
||||||
|
.output(ZCreateTemplateV2ResponseSchema)
|
||||||
|
.mutation(async ({ input, ctx }) => {
|
||||||
|
const { teamId, user } = ctx;
|
||||||
|
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
folderId,
|
||||||
|
externalId,
|
||||||
|
visibility,
|
||||||
|
globalAccessAuth,
|
||||||
|
globalActionAuth,
|
||||||
|
publicTitle,
|
||||||
|
publicDescription,
|
||||||
|
type,
|
||||||
|
meta,
|
||||||
|
} = input;
|
||||||
|
|
||||||
|
const fileName = title.endsWith('.pdf') ? title : `${title}.pdf`;
|
||||||
|
|
||||||
|
const { url, key } = await getPresignPostUrl(fileName, 'application/pdf');
|
||||||
|
|
||||||
|
const templateDocumentData = await createDocumentData({
|
||||||
|
data: key,
|
||||||
|
type: DocumentDataType.S3_PATH,
|
||||||
|
});
|
||||||
|
|
||||||
|
const createdTemplate = await createTemplate({
|
||||||
|
userId: user.id,
|
||||||
|
teamId,
|
||||||
|
templateDocumentDataId: templateDocumentData.id,
|
||||||
|
data: {
|
||||||
|
title,
|
||||||
|
folderId,
|
||||||
|
externalId,
|
||||||
|
visibility,
|
||||||
|
globalAccessAuth,
|
||||||
|
globalActionAuth,
|
||||||
|
publicTitle,
|
||||||
|
publicDescription,
|
||||||
|
type,
|
||||||
|
},
|
||||||
|
meta,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fullTemplate = await getTemplateById({
|
||||||
|
id: createdTemplate.id,
|
||||||
|
userId: user.id,
|
||||||
|
teamId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
template: fullTemplate,
|
||||||
|
uploadUrl: url,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,6 +30,50 @@ import {
|
|||||||
} from '../document-router/schema';
|
} from '../document-router/schema';
|
||||||
import { ZSignFieldWithTokenMutationSchema } from '../field-router/schema';
|
import { ZSignFieldWithTokenMutationSchema } from '../field-router/schema';
|
||||||
|
|
||||||
|
export const MAX_TEMPLATE_PUBLIC_TITLE_LENGTH = 50;
|
||||||
|
export const MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH = 256;
|
||||||
|
|
||||||
|
export const ZTemplateTitleSchema = z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1)
|
||||||
|
.max(255)
|
||||||
|
.describe('The title of the document.');
|
||||||
|
|
||||||
|
export const ZTemplatePublicTitleSchema = z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1)
|
||||||
|
.max(MAX_TEMPLATE_PUBLIC_TITLE_LENGTH)
|
||||||
|
.describe(
|
||||||
|
'The title of the template that will be displayed to the public. Only applicable for public templates.',
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ZTemplatePublicDescriptionSchema = z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1)
|
||||||
|
.max(MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH)
|
||||||
|
.describe(
|
||||||
|
'The description of the template that will be displayed to the public. Only applicable for public templates.',
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ZTemplateMetaUpsertSchema = z.object({
|
||||||
|
subject: ZDocumentMetaSubjectSchema.optional(),
|
||||||
|
message: ZDocumentMetaMessageSchema.optional(),
|
||||||
|
timezone: ZDocumentMetaTimezoneSchema.optional(),
|
||||||
|
dateFormat: ZDocumentMetaDateFormatSchema.optional(),
|
||||||
|
distributionMethod: ZDocumentMetaDistributionMethodSchema.optional(),
|
||||||
|
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
||||||
|
redirectUrl: ZDocumentMetaRedirectUrlSchema.optional(),
|
||||||
|
language: ZDocumentMetaLanguageSchema.optional(),
|
||||||
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
|
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
||||||
|
allowDictateNextSigner: z.boolean().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
export const ZCreateTemplateMutationSchema = z.object({
|
export const ZCreateTemplateMutationSchema = z.object({
|
||||||
title: z.string().min(1).trim(),
|
title: z.string().min(1).trim(),
|
||||||
templateDocumentDataId: z.string().min(1),
|
templateDocumentDataId: z.string().min(1),
|
||||||
@@ -123,57 +167,46 @@ export const ZDeleteTemplateMutationSchema = z.object({
|
|||||||
templateId: z.number(),
|
templateId: z.number(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const MAX_TEMPLATE_PUBLIC_TITLE_LENGTH = 50;
|
/**
|
||||||
export const MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH = 256;
|
* Note: This is the same between V1 and V2. Be careful when updating this schema and think of the consequences.
|
||||||
|
*/
|
||||||
|
export const ZCreateTemplateV2RequestSchema = z.object({
|
||||||
|
title: ZTemplateTitleSchema,
|
||||||
|
folderId: z.string().optional(),
|
||||||
|
externalId: z.string().nullish(),
|
||||||
|
visibility: z.nativeEnum(DocumentVisibility).optional(),
|
||||||
|
globalAccessAuth: z.array(ZDocumentAccessAuthTypesSchema).optional().default([]),
|
||||||
|
globalActionAuth: z.array(ZDocumentActionAuthTypesSchema).optional().default([]),
|
||||||
|
publicTitle: ZTemplatePublicTitleSchema.optional(),
|
||||||
|
publicDescription: ZTemplatePublicDescriptionSchema.optional(),
|
||||||
|
type: z.nativeEnum(TemplateType).optional(),
|
||||||
|
meta: ZTemplateMetaUpsertSchema.optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: This is the same between V1 and V2. Be careful when updating this schema and think of the consequences.
|
||||||
|
*/
|
||||||
|
export const ZCreateTemplateV2ResponseSchema = z.object({
|
||||||
|
template: ZTemplateSchema,
|
||||||
|
uploadUrl: z.string().min(1),
|
||||||
|
});
|
||||||
|
|
||||||
export const ZUpdateTemplateRequestSchema = z.object({
|
export const ZUpdateTemplateRequestSchema = z.object({
|
||||||
templateId: z.number(),
|
templateId: z.number(),
|
||||||
data: z
|
data: z
|
||||||
.object({
|
.object({
|
||||||
title: z.string().min(1).optional(),
|
title: ZTemplateTitleSchema.optional(),
|
||||||
externalId: z.string().nullish(),
|
externalId: z.string().nullish(),
|
||||||
visibility: z.nativeEnum(DocumentVisibility).optional(),
|
visibility: z.nativeEnum(DocumentVisibility).optional(),
|
||||||
globalAccessAuth: z.array(ZDocumentAccessAuthTypesSchema).optional().default([]),
|
globalAccessAuth: z.array(ZDocumentAccessAuthTypesSchema).optional().default([]),
|
||||||
globalActionAuth: z.array(ZDocumentActionAuthTypesSchema).optional().default([]),
|
globalActionAuth: z.array(ZDocumentActionAuthTypesSchema).optional().default([]),
|
||||||
publicTitle: z
|
publicTitle: ZTemplatePublicTitleSchema.optional(),
|
||||||
.string()
|
publicDescription: ZTemplatePublicDescriptionSchema.optional(),
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.max(MAX_TEMPLATE_PUBLIC_TITLE_LENGTH)
|
|
||||||
.describe(
|
|
||||||
'The title of the template that will be displayed to the public. Only applicable for public templates.',
|
|
||||||
)
|
|
||||||
.optional(),
|
|
||||||
publicDescription: z
|
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.max(MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH)
|
|
||||||
.describe(
|
|
||||||
'The description of the template that will be displayed to the public. Only applicable for public templates.',
|
|
||||||
)
|
|
||||||
.optional(),
|
|
||||||
type: z.nativeEnum(TemplateType).optional(),
|
type: z.nativeEnum(TemplateType).optional(),
|
||||||
useLegacyFieldInsertion: z.boolean().optional(),
|
useLegacyFieldInsertion: z.boolean().optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
meta: z
|
meta: ZTemplateMetaUpsertSchema.optional(),
|
||||||
.object({
|
|
||||||
subject: ZDocumentMetaSubjectSchema.optional(),
|
|
||||||
message: ZDocumentMetaMessageSchema.optional(),
|
|
||||||
timezone: ZDocumentMetaTimezoneSchema.optional(),
|
|
||||||
dateFormat: ZDocumentMetaDateFormatSchema.optional(),
|
|
||||||
distributionMethod: ZDocumentMetaDistributionMethodSchema.optional(),
|
|
||||||
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
|
||||||
redirectUrl: ZDocumentMetaRedirectUrlSchema.optional(),
|
|
||||||
language: ZDocumentMetaLanguageSchema.optional(),
|
|
||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
|
||||||
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
|
||||||
allowDictateNextSigner: z.boolean().optional(),
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ZUpdateTemplateResponseSchema = ZTemplateLiteSchema;
|
export const ZUpdateTemplateResponseSchema = ZTemplateLiteSchema;
|
||||||
|
|||||||
@@ -206,8 +206,8 @@ export const AddSubjectFormPartial = ({
|
|||||||
|
|
||||||
<p className="mt-2">
|
<p className="mt-2">
|
||||||
<Trans>
|
<Trans>
|
||||||
We will generate signing links for you, which you can send to the
|
We will generate signing links for you, which you can send to the recipients
|
||||||
recipients through your method of choice.
|
through your method of choice.
|
||||||
</Trans>
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user