render protocol by template

This commit is contained in:
Julian Krauser 2024-10-18 15:23:51 +02:00
parent da219eb5f4
commit 58213923e5
8 changed files with 950 additions and 3 deletions

1
.gitignore vendored
View file

@ -130,3 +130,4 @@ dist
.yarn/install-state.gz
.pnp.*
export

804
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -32,6 +32,7 @@
"mysql": "^2.18.1",
"node-schedule": "^2.1.1",
"nodemailer": "^6.9.14",
"pdf-creator-node": "^2.3.5",
"qrcode": "^1.5.4",
"reflect-metadata": "^0.2.2",
"socket.io": "^4.7.5",

View file

@ -22,6 +22,7 @@ import { SynchronizeProtocolDecisionCommand } from "../../command/protocolDecisi
import { SynchronizeProtocolVotingCommand } from "../../command/protocolVotingCommand";
import { ProtocolVotingViewModel } from "../../viewmodel/admin/protocolVoting.models";
import ProtocolVotingCommandHandler from "../../command/protocolVotingCommandHandler";
import { PdfExport } from "../../helpers/pdfExport";
/**
* @description get all protocols
@ -289,3 +290,47 @@ export async function synchronizeProtocolPrecenseById(req: Request, res: Respons
res.sendStatus(204);
}
/**
* @description render protocol to file by id
* @param req {Request} Express req object
* @param res {Response} Express res object
* @returns {Promise<*>}
*/
export async function printPdf(req: Request, res: Response): Promise<any> {
let protocolId = parseInt(req.params.protocolId);
let protocol = await ProtocolService.getById(protocolId);
let agenda = await ProtocolAgendaService.getAll(protocolId);
let decisions = await ProtocolDecisionService.getAll(protocolId);
let presence = await ProtocolPresenceService.getAll(protocolId);
let votings = await ProtocolVotingService.getAll(protocolId);
await PdfExport.renderFile({
template: "protocol.template.html",
title: protocol.title,
data: {
title: protocol.title,
summary: protocol.summary,
date: new Date(protocol.date).toLocaleDateString("de-DE", {
weekday: "long",
day: "2-digit",
month: "2-digit",
year: "numeric",
}),
start: new Date(protocol.starttime).toLocaleTimeString("de-DE", {
minute: "2-digit",
hour: "2-digit",
}),
end: new Date(protocol.endtime).toLocaleTimeString("de-DE", {
minute: "2-digit",
hour: "2-digit",
}),
agenda,
decisions,
presence: presence.map((p) => p.member),
votings,
},
});
res.sendStatus(204);
}

34
src/helpers/pdfExport.ts Normal file
View file

@ -0,0 +1,34 @@
import { readFileSync } from "fs";
import pdf, { Options } from "pdf-creator-node";
var options = (title: string = "pdf-export Mitgliederverwaltung"): Options => ({
format: "A4",
orientation: "portrait",
border: "10mm",
header: {
height: "10mm",
contents: `<h1 style="text-align: center;">${title}</h1>`,
},
footer: {
height: "5mm",
contents: {
default: '<span style="color: #444;">{{page}}</span>/<span>{{pages}}</span>',
},
},
});
export abstract class PdfExport {
static getTemplate(template: string) {
return readFileSync(process.cwd() + "/src/templates/" + template, "utf8");
}
static async renderFile({ template, title, data }: { template: string; title: string; data: any }) {
let document = {
html: this.getTemplate(template),
data,
path: process.cwd() + `/export/${title}.pdf`,
};
await pdf.create(document, options(title));
}
}

View file

@ -10,6 +10,7 @@ import {
getProtocolDecisonsById,
getProtocolPrecenseById,
getProtocolVotingsById,
printPdf,
synchronizeProtocolAgendaById,
synchronizeProtocolById,
synchronizeProtocolDecisonsById,
@ -59,6 +60,10 @@ router.post("/:protocolId/voting", async (req: Request, res: Response) => {
await createProtocolVotingsById(req, res);
});
router.post("/:protocolId/render", async (req: Request, res: Response) => {
await printPdf(req, res);
});
router.patch("/:id/synchronize", async (req: Request, res: Response) => {
await synchronizeProtocolById(req, res);
});

View file

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Protokoll</title>
</head>
<body>
<h1>{{title}}</h1>
<p>Am {{date}} von {{start}} Uhr bis {{end}} Uhr</p>
<p>{{sumary}}</p>
<h2>Anwesenheit</h2>
<ul>
{{#each presence}}
<li>{{this.firstname}} {{this.lastname}}</li>
{{/each}}
</ul>
<h2>Agenda</h2>
<ul>
{{#each agenda}}
<li>{{this}}</li>
{{/each}}
</ul>
<h2>Entscheidungen</h2>
<ul>
{{#each decisions}}
<li>{{this}}</li>
{{/each}}
</ul>
<h2>Abstimmungen</h2>
<ul>
{{#each votings}}
<li>{{this}}</li>
{{/each}}
</ul>
</body>
</html>

27
src/types/pdf-creator-node.d.ts vendored Normal file
View file

@ -0,0 +1,27 @@
// types/pdf-creator-node.d.ts
declare module "pdf-creator-node" {
interface Document {
html: string;
data: any;
path: string;
type?: string;
}
interface Options {
format: string;
orientation: string;
border: string;
header?: {
height: string;
contents: string;
};
footer?: {
height: string;
contents: string | { [key: string]: string | number };
};
}
function create(document: Document, options: Options): Promise<any>;
export { create, Document, Options };
}