🗃️ 💄 insert text in custom font, typeSignature

This commit is contained in:
Timur Ercan
2023-02-20 18:14:52 +01:00
parent 0cda32d197
commit 9e4874bd27
6 changed files with 82 additions and 802 deletions

View File

@@ -15,6 +15,7 @@
"@documenso/ui": "*",
"@headlessui/react": "^1.7.4",
"@heroicons/react": "^2.0.13",
"@pdf-lib/fontkit": "^1.1.1",
"@tailwindcss/forms": "^0.5.3",
"@types/bcryptjs": "^2.4.2",
"@types/filesystem": "^0.0.32",
@@ -45,7 +46,6 @@
"sass": "^1.57.1",
"short-uuid": "^4.2.2",
"string-to-color": "^2.2.2",
"text2png": "^2.3.0",
"typescript": "4.8.4"
},
"devDependencies": {

View File

@@ -36,14 +36,19 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
if (!recipients.length) return res.status(200).end("");
let sentRequests = 0;
recipients.forEach(async (recipient) => {
await sendSigningRequest(recipient, document, user).catch((err) => {
console.log(err);
return res.status(502).end("Coud not send request for signing.");
});
sentRequests++;
if (sentRequests === recipients.length) {
return res.status(200).end();
}
});
return res.status(202).end();
// todo check if recipient has an account and show them in their inbox or something
}

View File

@@ -9,6 +9,7 @@ import { SigningStatus, DocumentStatus } from "@prisma/client";
import { getDocument } from "@documenso/lib/query";
import { Document as PrismaDocument } from "@prisma/client";
import { insertImageInPDF, insertTextInPDF } from "@documenso/pdf";
import { create } from "domain";
const text2png = require("text2png");
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
@@ -37,17 +38,23 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
if (!document) res.status(404).end(`No document found.`);
// todo insert if not exits
signatures.forEach(async (signature) => {
await prisma.signature.create({
data: {
if (!signature.signatureImage && !signature.typedSignature)
throw new Error("Cant't save invalid signature.");
await prisma.signature.upsert({
where: {
fieldId: signature.fieldId,
},
update: {},
create: {
recipientId: recipient.id,
fieldId: signature.fieldId,
signatureImageAsBase64: signature.signatureImage
? signature.signatureImage
: text2png(signature.typedSignature, {
color: "black",
lineSpacing: 10,
padding: 20,
}).toString("base64"),
: null,
typedSignature: signature.typedSignature
? signature.typedSignature
: null,
},
});
});
@@ -68,6 +75,7 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
},
});
console.log("unsignedRecipients.length.." + unsignedRecipients.length);
if (unsignedRecipients.length === 0) {
// todo if everybody signed insert images and create signature
const signedFields = await prisma.field.findMany({
@@ -77,18 +85,36 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
// todo rename .document to documentImageAsBase64 or sth. like that
let documentWithSignatureImages = document.document;
let signaturesInserted = 0;
signedFields.forEach(async (item) => {
if (!item.Signature) {
signedFields.forEach(async (signedField) => {
if (!signedField.Signature) {
documentWithSignatureImages = document.document;
throw new Error("Invalid Signature in Field");
}
documentWithSignatureImages = await insertImageInPDF(
documentWithSignatureImages,
item.Signature ? item.Signature?.signatureImageAsBase64 : "",
item.positionX,
item.positionY,
item.page
);
if (signedField.Signature.signatureImageAsBase64) {
documentWithSignatureImages = await insertImageInPDF(
documentWithSignatureImages,
signedField.Signature
? signedField.Signature?.signatureImageAsBase64
: "",
signedField.positionX,
signedField.positionY,
signedField.page
);
} else if (signedField.Signature.typedSignature) {
console.log("inserting text");
documentWithSignatureImages = await insertTextInPDF(
documentWithSignatureImages,
signedField.Signature.typedSignature,
signedField.positionX,
signedField.positionY,
signedField.page
);
} else {
documentWithSignatureImages = document.document;
throw new Error("Invalid signature could not be inserted.");
}
signaturesInserted++;
if (signaturesInserted == signedFields.length) {
await prisma.document.update({

795
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
import { PDFDocument, rgb, StandardFonts } from "pdf-lib";
import fontkit from "@pdf-lib/fontkit";
import * as fs from "fs";
export async function insertTextInPDF(
pdfAsBase64: string,
@@ -7,20 +9,25 @@ export async function insertTextInPDF(
positionY: number,
page: number = 0
): Promise<string> {
const fontBytes = fs.readFileSync("public/fonts/Qwigley-Regular.ttf");
const existingPdfBytes = pdfAsBase64;
const pdfDoc = await PDFDocument.load(existingPdfBytes);
const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
pdfDoc.registerFontkit(fontkit);
const customFont = await pdfDoc.embedFont(fontBytes);
const pages = pdfDoc.getPages();
const pdfPage = pages[page];
const lineHeightEsimate = 25;
const textSize = 50;
const textWidth = customFont.widthOfTextAtSize(text, textSize);
const textHeight = customFont.heightAtSize(textSize);
pdfPage.drawText(text, {
x: pdfPage.getWidth() - positionX,
y: pdfPage.getHeight() - positionY - lineHeightEsimate,
size: 25,
font: helveticaFont,
x: pdfPage.getWidth() - positionX - textWidth / 2, // todo adjust for exact field size
y: pdfPage.getHeight() - positionY - textHeight / 2, // todo adjust for exact field size
size: textSize,
font: customFont,
color: rgb(0, 0, 0),
});

View File

@@ -121,7 +121,8 @@ model Signature {
created DateTime @default(now())
recipientId Int
fieldId Int @unique
signatureImageAsBase64 String
signatureImageAsBase64 String?
typedSignature String?
Recipient Recipient @relation(fields: [recipientId], references: [id], onDelete: Restrict)
Field Field @relation(fields: [fieldId], references: [id], onDelete: Restrict)