fix: reverse meta relation and tidy code

This commit is contained in:
Mythie
2023-09-22 12:27:54 +00:00
parent e330e90688
commit f4c7799537
13 changed files with 165 additions and 105 deletions

View File

@ -1,9 +1,8 @@
'use server';
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-session';
import { createDocumentMeta } from '@documenso/lib/server-only/document-meta/create-document-meta';
import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta';
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
import { updateDocument } from '@documenso/lib/server-only/document/update-document';
import { TAddSubjectFormSchema } from '@documenso/ui/primitives/document-flow/add-subject.types';
export type CompleteDocumentActionInput = TAddSubjectFormSchema & {
@ -15,30 +14,15 @@ export const completeDocument = async ({ documentId, email }: CompleteDocumentAc
const { id: userId } = await getRequiredServerComponentSession();
if (!email.message && !email.subject) {
return await sendDocument({
userId,
if (email.message || email.subject) {
await upsertDocumentMeta({
documentId,
subject: email.subject,
message: email.message,
});
}
const createDocumentMetaResponse = await createDocumentMeta({
emailBody: email.message,
emailSubject: email.subject,
});
await updateDocument({
documentId,
data: {
DocumentMeta: {
connect: {
id: createDocumentMetaResponse.id,
},
},
},
});
await sendDocument({
return await sendDocument({
userId,
documentId,
});

View File

@ -1,4 +1,4 @@
import { Button, Img, Section, Tailwind, Text } from '@react-email/components';
import { Button, Column, Img, Row, Section, Tailwind, Text } from '@react-email/components';
import * as config from '@documenso/tailwind-config';
@ -29,11 +29,23 @@ export const TemplateDocumentCompleted = ({
},
}}
>
<Section className="flex-row items-center justify-center">
<div className="flex items-center justify-center p-4">
<Img className="h-42" src={getAssetUrl('/static/document.png')} alt="Documenso" />
</div>
<Section>
<Row className="table-fixed">
<Column />
<Column>
<Img
className="h-42 mx-auto"
src={getAssetUrl('/static/document.png')}
alt="Documenso"
/>
</Column>
<Column />
</Row>
</Section>
<Section>
<Text className="mb-4 flex items-center justify-center text-center text-base font-semibold text-[#7AC455]">
<Img src={getAssetUrl('/static/completed.png')} className="-mb-0.5 mr-2 inline h-7 w-7" />
Completed

View File

@ -1,4 +1,4 @@
import { Button, Img, Section, Tailwind, Text } from '@react-email/components';
import { Button, Column, Img, Row, Section, Tailwind, Text } from '@react-email/components';
import * as config from '@documenso/tailwind-config';
@ -30,13 +30,26 @@ export const TemplateDocumentInvite = ({
},
}}
>
<Section className="mt-4 flex-row items-center justify-center">
<div className="flex items-center justify-center p-4">
<Img className="h-42" src={getAssetUrl('/static/document.png')} alt="Documenso" />
</div>
<Section className="mt-4">
<Row className="table-fixed">
<Column />
<Column>
<Img
className="h-42 mx-auto"
src={getAssetUrl('/static/document.png')}
alt="Documenso"
/>
</Column>
<Column />
</Row>
</Section>
<Section>
<Text className="text-primary mx-auto mb-0 max-w-[80%] text-center text-lg font-semibold">
{inviterName} has invited you to sign "{documentName}"
{inviterName} has invited you to sign
<br />"{documentName}"
</Text>
<Text className="my-1 text-center text-base text-slate-400">

View File

@ -1,4 +1,4 @@
import { Img, Section, Tailwind, Text } from '@react-email/components';
import { Column, Img, Row, Section, Tailwind, Text } from '@react-email/components';
import * as config from '@documenso/tailwind-config';
@ -25,11 +25,23 @@ export const TemplateDocumentPending = ({
},
}}
>
<Section className="flex-row items-center justify-center">
<div className="flex items-center justify-center p-4">
<Img className="h-42" src={getAssetUrl('/static/document.png')} alt="Documenso" />
</div>
<Section>
<Row className="table-fixed">
<Column />
<Column>
<Img
className="h-42 mx-auto"
src={getAssetUrl('/static/document.png')}
alt="Documenso"
/>
</Column>
<Column />
</Row>
</Section>
<Section>
<Text className="mb-4 flex items-center justify-center text-center text-base font-semibold text-blue-500">
<Img src={getAssetUrl('/static/clock.png')} className="-mb-0.5 mr-2 inline h-7 w-7" />
Waiting for others

View File

@ -1,33 +0,0 @@
'use server';
import { prisma } from '@documenso/prisma';
export type CreateDocumentMetaOptions = {
emailSubject: string;
emailBody: string;
};
export const createDocumentMeta = async ({
emailBody,
emailSubject,
}: CreateDocumentMetaOptions) => {
const emailData = {
customEmailBody: emailBody,
customEmailSubject: emailSubject,
};
const existingDocumentMeta = await prisma.documentMeta.findFirst({
where: emailData,
});
if (existingDocumentMeta) {
return await prisma.documentMeta.update({
where: { id: existingDocumentMeta.id },
data: emailData,
});
} else {
return await prisma.documentMeta.create({
data: emailData,
});
}
};

View File

@ -0,0 +1,30 @@
'use server';
import { prisma } from '@documenso/prisma';
export type CreateDocumentMetaOptions = {
documentId: number;
subject: string;
message: string;
};
export const upsertDocumentMeta = async ({
subject,
message,
documentId,
}: CreateDocumentMetaOptions) => {
return await prisma.documentMeta.upsert({
where: {
documentId,
},
create: {
subject,
message,
documentId,
},
update: {
subject,
message,
},
});
};

View File

@ -13,6 +13,7 @@ export const getDocumentById = async ({ id, userId }: GetDocumentByIdOptions) =>
},
include: {
documentData: true,
documentMeta: true,
},
});
};

View File

@ -26,11 +26,11 @@ export const sendDocument = async ({ documentId, userId }: SendDocumentOptions)
},
include: {
Recipient: true,
DocumentMeta: true,
documentMeta: true,
},
});
const customEmail = document?.DocumentMeta;
const customEmail = document?.documentMeta;
if (!document) {
throw new Error('Document not found');
@ -67,10 +67,7 @@ export const sendDocument = async ({ documentId, userId }: SendDocumentOptions)
inviterEmail: user.email,
assetBaseUrl,
signDocumentLink,
customBody: renderCustomEmailTemplate(
customEmail?.customEmailBody || '',
customEmailTemplate,
),
customBody: renderCustomEmailTemplate(customEmail?.message || '', customEmailTemplate),
});
await mailer.sendMail({
@ -82,8 +79,8 @@ export const sendDocument = async ({ documentId, userId }: SendDocumentOptions)
name: process.env.NEXT_PRIVATE_SMTP_FROM_NAME || 'Documenso',
address: process.env.NEXT_PRIVATE_SMTP_FROM_ADDRESS || 'noreply@documenso.com',
},
subject: customEmail?.customEmailSubject
? renderCustomEmailTemplate(customEmail.customEmailSubject, customEmailTemplate)
subject: customEmail?.subject
? renderCustomEmailTemplate(customEmail.subject, customEmailTemplate)
: 'Please sign this document',
html: render(template),
text: render(template, { plainText: true }),

View File

@ -2,19 +2,11 @@ export const renderCustomEmailTemplate = <T extends Record<string, string>>(
template: string,
variables: T,
): string => {
let t = template;
Object.entries(variables).forEach((entry) => {
const [key, value] = entry;
const placeholder = `{${key}}`;
const re = new RegExp(placeholder, 'g');
if (Object.prototype.hasOwnProperty.call(variables, key)) {
t = t.replace(re, String(value));
return template.replace(/\{(\S+)\}/g, (_, key) => {
if (key in variables) {
return variables[key];
}
});
return t;
return key;
});
};

View File

@ -0,0 +1,52 @@
/*
Warnings:
- You are about to drop the column `documentMetaId` on the `Document` table. All the data in the column will be lost.
- You are about to drop the column `customEmailBody` on the `DocumentMeta` table. All the data in the column will be lost.
- You are about to drop the column `customEmailSubject` on the `DocumentMeta` table. All the data in the column will be lost.
- A unique constraint covering the columns `[documentId]` on the table `DocumentMeta` will be added. If there are existing duplicate values, this will fail.
- Added the required column `documentId` to the `DocumentMeta` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "Document" DROP CONSTRAINT "Document_documentMetaId_fkey";
-- DropIndex
DROP INDEX "Document_documentMetaId_key";
-- AlterTable
ALTER TABLE "DocumentMeta"
ADD COLUMN "documentId" INTEGER,
ADD COLUMN "message" TEXT,
ADD COLUMN "subject" TEXT;
-- Migrate data
UPDATE "DocumentMeta" SET "documentId" = (
SELECT "id" FROM "Document" WHERE "Document"."documentMetaId" = "DocumentMeta"."id"
);
-- Migrate data
UPDATE "DocumentMeta" SET "message" = "customEmailBody";
-- Migrate data
UPDATE "DocumentMeta" SET "subject" = "customEmailSubject";
-- Prune data
DELETE FROM "DocumentMeta" WHERE "documentId" IS NULL;
-- AlterTable
ALTER TABLE "Document" DROP COLUMN "documentMetaId";
-- AlterTable
ALTER TABLE "DocumentMeta"
DROP COLUMN "customEmailBody",
DROP COLUMN "customEmailSubject";
-- AlterColumn
ALTER TABLE "DocumentMeta" ALTER COLUMN "documentId" SET NOT NULL;
-- CreateIndex
CREATE UNIQUE INDEX "DocumentMeta_documentId_key" ON "DocumentMeta"("documentId");
-- AddForeignKey
ALTER TABLE "DocumentMeta" ADD CONSTRAINT "DocumentMeta_documentId_fkey" FOREIGN KEY ("documentId") REFERENCES "Document"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -110,14 +110,11 @@ model Document {
Field Field[]
documentDataId String
documentData DocumentData @relation(fields: [documentDataId], references: [id], onDelete: Cascade)
documentMeta DocumentMeta?
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
documentMetaId String?
DocumentMeta DocumentMeta? @relation(fields: [documentMetaId], references: [id], onDelete: Cascade)
@@unique([documentDataId])
@@unique([documentMetaId])
}
enum DocumentDataType {
@ -135,10 +132,11 @@ model DocumentData {
}
model DocumentMeta {
id String @id @default(cuid())
customEmailSubject String?
customEmailBody String?
Document Document?
id String @id @default(cuid())
subject String?
message String?
documentId Int @unique
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
}
enum ReadStatus {

View File

@ -1,5 +1,6 @@
import { Document, DocumentData } from '@documenso/prisma/client';
import { Document, DocumentData, DocumentMeta } from '@documenso/prisma/client';
export type DocumentWithData = Document & {
documentData?: DocumentData | null;
documentMeta?: DocumentMeta | null;
};

View File

@ -2,7 +2,8 @@
import { useForm } from 'react-hook-form';
import { Document, DocumentStatus, Field, Recipient } from '@documenso/prisma/client';
import { DocumentStatus, Field, Recipient } from '@documenso/prisma/client';
import { DocumentWithData } from '@documenso/prisma/types/document-with-data';
import { FormErrorMessage } from '@documenso/ui/primitives/form/form-error-message';
import { Input } from '@documenso/ui/primitives/input';
import { Label } from '@documenso/ui/primitives/label';
@ -21,7 +22,7 @@ export type AddSubjectFormProps = {
documentFlow: DocumentFlowStep;
recipients: Recipient[];
fields: Field[];
document: Document;
document: DocumentWithData;
numberOfSteps: number;
onSubmit: (_data: TAddSubjectFormSchema) => void;
};
@ -41,8 +42,8 @@ export const AddSubjectFormPartial = ({
} = useForm<TAddSubjectFormSchema>({
defaultValues: {
email: {
subject: '',
message: '',
subject: document.documentMeta?.subject ?? '',
message: document.documentMeta?.message ?? '',
},
},
});