Compare commits
22
Commits
v0.4.2
...
405bb20601
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
405bb20601 | ||
|
|
ac572f1ea3 | ||
|
|
7fea1ca78f | ||
|
|
64fce5bd01 | ||
|
|
5ba26c4cbf | ||
|
|
b82a32ae3e | ||
|
|
0af9b81b38 | ||
|
|
955e11846b | ||
|
|
d1577cd08d | ||
|
|
6767c3b2d1 | ||
|
|
2b2195727b | ||
|
|
3ca2237953 | ||
|
|
8d6ea4dbf9 | ||
|
|
8b71608792 | ||
|
|
f1084b59a7 | ||
|
|
c8dc998ecd | ||
|
|
3df3d26708 | ||
|
|
922e762aa2 | ||
|
|
c3beb3e103 | ||
|
|
457ea26cf8 | ||
|
|
c2d2b66f2f | ||
|
|
289a0d8671 |
No files matched your search
@@ -113,6 +113,7 @@ steps:
|
||||
tags:
|
||||
- latest
|
||||
registry: registry.odit.services
|
||||
mtu: 1000
|
||||
- name: push merge to repo
|
||||
depends_on: ["clone"]
|
||||
image: appleboy/drone-git-push
|
||||
@@ -147,6 +148,7 @@ steps:
|
||||
tags:
|
||||
- '${DRONE_TAG}'
|
||||
registry: registry.odit.services
|
||||
mtu: 1000
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
@@ -2,8 +2,24 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
|
||||
|
||||
#### [v0.4.3](https://git.odit.services/lfk/document-server/compare/v0.4.3...v0.4.3)
|
||||
|
||||
#### [v0.4.3](https://git.odit.services/lfk/document-server/compare/v0.4.2...v0.4.3)
|
||||
|
||||
> 30 March 2021
|
||||
|
||||
- Merge pull request 'Release 0.4.3' (#40) from dev into main [`c8dc998`](https://git.odit.services/lfk/document-server/commit/c8dc998ecdccc7fc4348ecc0db552a3d7bc2eb52)
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`289a0d8`](https://git.odit.services/lfk/document-server/commit/289a0d8671575dda911c64f79d24726d3bbee071)
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`3df3d26`](https://git.odit.services/lfk/document-server/commit/3df3d26708aab12590cd9c1f697cfdea8017ace4)
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`457ea26`](https://git.odit.services/lfk/document-server/commit/457ea26cf8124009084415d12c7a0e31912a3eb1)
|
||||
- 🚀Bumped version to v0.4.3 [`c3beb3e`](https://git.odit.services/lfk/document-server/commit/c3beb3e1032492f9a8304c4b099a700ad0d1d2cf)
|
||||
- Pipeline mtu fix [`c2d2b66`](https://git.odit.services/lfk/document-server/commit/c2d2b66f2f6fbd30c2027fd3dab393db5219eb44)
|
||||
|
||||
#### [v0.4.2](https://git.odit.services/lfk/document-server/compare/v0.4.0...v0.4.2)
|
||||
|
||||
> 29 March 2021
|
||||
|
||||
- Merge pull request 'Release 0.4.2' (#39) from dev into main [`ce3053c`](https://git.odit.services/lfk/document-server/commit/ce3053c0ba5404ebd8d4cbd5386c454d8cd8c4d2)
|
||||
- 🚀Bumped version to v0.4.1 [`d17108f`](https://git.odit.services/lfk/document-server/commit/d17108f4b9f041727afcee5c171d5d8f9a3c677c)
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`0ade575`](https://git.odit.services/lfk/document-server/commit/0ade57536e372a62356fe2f329f6cfe04bcfc397)
|
||||
- Fixed faulty object mapping [`9584bfe`](https://git.odit.services/lfk/document-server/commit/9584bfed8ba5b8c856b55aa90969874d4d6751ff)
|
||||
@@ -11,6 +27,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`b8f0d1f`](https://git.odit.services/lfk/document-server/commit/b8f0d1fa60da4e3262623cecf4a78c8a9a322f8c)
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`073433f`](https://git.odit.services/lfk/document-server/commit/073433f308f2f8e7ada97dd0b3896fb541e85711)
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`a478081`](https://git.odit.services/lfk/document-server/commit/a47808172797e12800c46d17ccf4b458f4a506de)
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`6608456`](https://git.odit.services/lfk/document-server/commit/6608456c686e51d3aa16e630ba72c7c29e428b2a)
|
||||
- 🧾New changelog file version [CI SKIP] [skip ci] [`0839ff6`](https://git.odit.services/lfk/document-server/commit/0839ff63593cfb9e8339b2b2a86dbe7e2afb5dcb)
|
||||
- Now using our own images to build stuff 🚀 [`96886c7`](https://git.odit.services/lfk/document-server/commit/96886c74bc397e1ee793e83e0d01a6bbaa953da3)
|
||||
- 🚀Bumped version to v0.4.2 [`1cbe5a1`](https://git.odit.services/lfk/document-server/commit/1cbe5a1614c40fbf23f032be60039ddb1472ca94)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@odit/lfk-document-server",
|
||||
"version": "0.4.2",
|
||||
"version": "0.4.3",
|
||||
"description": "The document generation server for the LfK! runner system. This generates certificates, sponsoring aggreements and more",
|
||||
"main": "src/app.ts",
|
||||
"scripts": {
|
||||
|
||||
+29
-3
@@ -10,6 +10,7 @@ import { PDFDocument } from 'pdf-lib';
|
||||
import puppeteer from "puppeteer";
|
||||
import { awaitAsyncHandlebarHelpers, helpers } from './asyncHelpers';
|
||||
import { config } from './config';
|
||||
import { CertificateRunner } from './models/CertificateRunner';
|
||||
import { Runner } from './models/Runner';
|
||||
import { RunnerCard } from './models/RunnerCard';
|
||||
import { RunnerGroup } from './models/RunnerGroup';
|
||||
@@ -153,13 +154,37 @@ export class PdfCreator {
|
||||
await i18next.changeLanguage(locale);
|
||||
const template_source = fs.readFileSync(`${this.templateDir}/runner_card.html`, 'utf8');
|
||||
const template = Handlebars.compile(template_source);
|
||||
let result = template({ cards, cards_swapped, eventname: "LfK! 2069", codeformat: "qrcode" })
|
||||
let result = template({ cards, cards_swapped, eventname: config.eventname, codeformat: codeformat })
|
||||
result = await awaitAsyncHandlebarHelpers(result);
|
||||
fs.writeFileSync("lelelelele.tmp", result);
|
||||
const pdf = await this.renderPdf(result, { format: "A4", landscape: false });
|
||||
return pdf
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate sponsoring contract pdfs.
|
||||
* @param runner The runner you want to generate the contracts for.
|
||||
* @param locale The locale used for the contracts (default:en)
|
||||
*/
|
||||
public async generateRunnerCertficates(runners: CertificateRunner[], locale: string = "en"): Promise<Buffer> {
|
||||
if (runners.length > 50) {
|
||||
let pdf_promises = new Array<Promise<Buffer>>();
|
||||
let i, j;
|
||||
for (i = 0, j = runners.length; i < j; i += 50) {
|
||||
let chunk = runners.slice(i, i + 50);
|
||||
pdf_promises.push(this.generateRunnerCertficates(chunk, locale));
|
||||
}
|
||||
const pdfs = await Promise.all(pdf_promises);
|
||||
return await this.mergePdfs(pdfs);
|
||||
}
|
||||
await i18next.changeLanguage(locale);
|
||||
const template_source = fs.readFileSync(`${this.templateDir}/runner_certificate.html`, 'utf8');
|
||||
const template = Handlebars.compile(template_source);
|
||||
let result = template({ runners, eventname: config.eventname });
|
||||
result = await awaitAsyncHandlebarHelpers(result);
|
||||
const pdf = await this.renderPdf(result, { format: "A4", landscape: false, printBackground: true });
|
||||
return pdf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all images in html to base64.
|
||||
* Works with image files in the template directory or images from urls.
|
||||
@@ -167,6 +192,7 @@ export class PdfCreator {
|
||||
*/
|
||||
public async imgToBase64(html): Promise<string> {
|
||||
const $ = cheerio.load(html)
|
||||
|
||||
$('img').each(async (index, element) => {
|
||||
let imgsrc = $(element).attr("src");
|
||||
if (imgsrc.startsWith("data:image")) {
|
||||
@@ -192,7 +218,7 @@ export class PdfCreator {
|
||||
|
||||
image = `data:${img_type};base64,${image}`
|
||||
$(element).attr("src", image)
|
||||
})
|
||||
});
|
||||
|
||||
return $.html();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Authorized, Body, JsonController, Post, QueryParam, Res } from 'routing-controllers';
|
||||
import { OpenAPI } from 'routing-controllers-openapi';
|
||||
import { CertificateRunner } from '../models/CertificateRunner';
|
||||
import { Runner } from '../models/Runner';
|
||||
import { RunnerCard } from '../models/RunnerCard';
|
||||
import { PdfCreator } from '../PdfCreator';
|
||||
@@ -54,6 +55,25 @@ export class PdfController {
|
||||
return contracts;
|
||||
}
|
||||
|
||||
@Post('/certificates')
|
||||
@OpenAPI({ description: "Generate runner certificate pdfs from certificate runner objects.<br>You can choose your prefered locale by passing the 'locale' query-param.<br> If you provide more than 100 runenrs this could take a moment or two (we tested up to 1000 runners in about 70sec so far)." })
|
||||
async generateCertificates(@Body({ validate: true, options: { limit: "500mb" } }) runners: CertificateRunner[], @Res() res: any, @QueryParam("locale") locale: string, @QueryParam("download") download: boolean) {
|
||||
if (!this.initialized) {
|
||||
await this.pdf.init();
|
||||
this.initialized = true;
|
||||
}
|
||||
if (!Array.isArray(runners)) {
|
||||
runners = [runners];
|
||||
}
|
||||
runners = this.mapCertificatRunnersGroupNames(runners)
|
||||
const certificates = await this.pdf.generateRunnerCertficates(runners, locale);
|
||||
res.setHeader('content-type', 'application/pdf');
|
||||
if (download) {
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="certificates.pdf"')
|
||||
}
|
||||
return certificates;
|
||||
}
|
||||
|
||||
private mapRunnerGroupNames(runners: Runner[]): Runner[] {
|
||||
let response = new Array<Runner>();
|
||||
for (let runner of runners) {
|
||||
@@ -68,6 +88,20 @@ export class PdfController {
|
||||
return response;
|
||||
}
|
||||
|
||||
private mapCertificatRunnersGroupNames(runners: CertificateRunner[]): CertificateRunner[] {
|
||||
let response = new Array<CertificateRunner>();
|
||||
for (let runner of runners) {
|
||||
if (!runner.group.parentGroup) {
|
||||
runner.group.fullName = runner.group.name;
|
||||
}
|
||||
else {
|
||||
runner.group.fullName = `${runner.group.parentGroup.name}/${runner.group.name}`;
|
||||
}
|
||||
response.push(runner)
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private mapCardGroupNames(cards: RunnerCard[]): RunnerCard[] {
|
||||
let response = new Array<RunnerCard>();
|
||||
for (let card of cards) {
|
||||
|
||||
+27
-19
@@ -1,20 +1,28 @@
|
||||
{
|
||||
"address": "Adresse",
|
||||
"city": "Stadt",
|
||||
"date": "Datum",
|
||||
"firstname": "Vorname",
|
||||
"group": "Team/Klasse",
|
||||
"house_number": "Hausnummer",
|
||||
"id": "ID",
|
||||
"lastname": "Nachname",
|
||||
"location": "Ort",
|
||||
"please_use_blockletters": "Bitte in DRUCKBUCHSTABEN schreiben",
|
||||
"postalcode": "Postleitzahl",
|
||||
"signature": "Unterschrift",
|
||||
"sponsor": "Sponsor",
|
||||
"sponsoring_address_condition": "Muss ausgefüllt werden, wenn Sie eine Spendenquittung benötigen - Spendenquittungen können erst ab einem Gesamtbetrag von {{sponsoring_receipt_minimum_amount}}{{currency_symbol}} ausgestellt werden",
|
||||
"sponsoring_amount_per_distance": "mit einem Betrag von _____{{currency_symbol}} pro gelaufenem Kilometer zu unterstützen.",
|
||||
"sponsoring_subtitle": "Ich/Wir sind bereit anlässlich des {{eventname}}",
|
||||
"sponsoring_title": "Sponsoringerklärung",
|
||||
"street": "Straße"
|
||||
}
|
||||
"address": "Adresse",
|
||||
"city": "Stadt",
|
||||
"date": "Datum",
|
||||
"firstname": "Vorname",
|
||||
"group": "Team/Klasse",
|
||||
"house_number": "Hausnummer",
|
||||
"id": "ID",
|
||||
"lastname": "Nachname",
|
||||
"location": "Ort",
|
||||
"please_use_blockletters": "Bitte in DRUCKBUCHSTABEN schreiben",
|
||||
"postalcode": "Postleitzahl",
|
||||
"signature": "Unterschrift",
|
||||
"sponsor": "Sponsor",
|
||||
"sponsoring_address_condition": "Muss ausgefüllt werden, wenn Sie eine Spendenquittung benötigen - Spendenquittungen können erst ab einem Gesamtbetrag von {{sponsoring_receipt_minimum_amount}}{{currency_symbol}} ausgestellt werden",
|
||||
"sponsoring_amount_per_distance": "mit einem Betrag von _____{{currency_symbol}} pro gelaufenem Kilometer zu unterstützen.",
|
||||
"sponsoring_subtitle": "Ich/Wir sind bereit anlässlich des {{eventname}}",
|
||||
"sponsoring_title": "Sponsoringerklärung",
|
||||
"street": "Straße",
|
||||
"urkunde": "Urkunde",
|
||||
"hat-beim-eventname": "Hat beim {{../eventname}}",
|
||||
"fuer-den-guten-zweck-zurueckgelegt": "für den guten Zweck zurückgelegt",
|
||||
"sponsorings": "Sponsorings",
|
||||
"sponsor-in": "Sponsor:in",
|
||||
"betrag-km": "Betrag/KM",
|
||||
"gesamtbetrag": "Gesamtbetrag",
|
||||
"gesamt": "Gesamt"
|
||||
}
|
||||
+27
-18
@@ -1,19 +1,28 @@
|
||||
{
|
||||
"address": "Address",
|
||||
"city": "City",
|
||||
"date": "date",
|
||||
"firstname": "First name",
|
||||
"group": "Team/class",
|
||||
"house_number": "House number",
|
||||
"lastname": "Last name",
|
||||
"location": "Location",
|
||||
"please_use_blockletters": "Please write in BLOCK LETTERS.",
|
||||
"postalcode": "Postal code",
|
||||
"signature": "Signature",
|
||||
"sponsor": "sponsor",
|
||||
"sponsoring_address_condition": "You have to provide an address if you want a donation receipt - Donation receipts can't be issued for total donation amounts under {{sponsoring_receipt_minimum_amount}}{{currency_symbol}}",
|
||||
"sponsoring_amount_per_distance": "with the amount of _____{{currency_symbol}} per kilometer run.",
|
||||
"sponsoring_subtitle": "On the ocation of the {{eventname}} I/We want to support",
|
||||
"sponsoring_title": "Sponsoring contract",
|
||||
"street": "Street"
|
||||
}
|
||||
"address": "Address",
|
||||
"city": "City",
|
||||
"date": "date",
|
||||
"firstname": "First name",
|
||||
"group": "Team/class",
|
||||
"house_number": "House number",
|
||||
"lastname": "Last name",
|
||||
"location": "Location",
|
||||
"please_use_blockletters": "Please write in BLOCK LETTERS.",
|
||||
"postalcode": "Postal code",
|
||||
"signature": "Signature",
|
||||
"sponsor": "sponsor",
|
||||
"sponsoring_address_condition": "You have to provide an address if you want a donation receipt - Donation receipts can't be issued for total donation amounts under {{sponsoring_receipt_minimum_amount}}{{currency_symbol}}",
|
||||
"sponsoring_amount_per_distance": "with the amount of _____{{currency_symbol}} per kilometer run.",
|
||||
"sponsoring_subtitle": "On the ocation of the {{eventname}} I/We want to support",
|
||||
"sponsoring_title": "Sponsoring contract",
|
||||
"street": "Street",
|
||||
"urkunde": "Certifcate",
|
||||
"fuer-den-guten-zweck-zurueckgelegt": "for our good cuse at the {eventname}",
|
||||
"hat-beim-eventname": "Ran",
|
||||
"id": "ID",
|
||||
"sponsorings": "Donations",
|
||||
"sponsor-in": "Donor",
|
||||
"betrag-km": "Amount/KM",
|
||||
"gesamtbetrag": "Total",
|
||||
"gesamt": "Combined"
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
@@ -0,0 +1,98 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Sponsoring contract</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
|
||||
<style>
|
||||
.sheet {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
page-break-after: always;
|
||||
padding: 1.2cm 2cm 1.2cm 2cm;
|
||||
background-image: url("data:image/png;base64,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 truncated
|
||||
background-repeat: no-repeat;
|
||||
background-size: 11cm;
|
||||
background-position: 5cm 5cm;
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
background-blend-mode: lighten;
|
||||
/* border-style: solid; */
|
||||
}
|
||||
|
||||
body.A4 .sheet {
|
||||
width: 210mm;
|
||||
height: 296mm
|
||||
}
|
||||
|
||||
.certificate-footer {
|
||||
position: absolute;
|
||||
bottom: 0cm;
|
||||
}
|
||||
|
||||
td {
|
||||
border: 1px solid black;
|
||||
font-size: large;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="A4 landscape">
|
||||
{{#each runners}}
|
||||
<article class="sheet">
|
||||
<header class="content has-text-centered">
|
||||
<h1 style="font-size: 3cm; font-weight: bold;">{{__ "urkunde"}}</h1>
|
||||
</header>
|
||||
<main class="content has-text-centered" style="padding-top: 3cm;">
|
||||
<p style="width: 50%; font-size: 4vw; font-weight: bold; margin-bottom: 0; display: inline;">{{this.firstname}}
|
||||
{{this.middlename}} {{this.lastname}}
|
||||
</p>
|
||||
<p style="font-size: 1cm; margin-bottom: 0;">{{__ "hat-beim-eventname"}}</p>
|
||||
<p style="font-size: 2cm; font-weight: bold; margin-bottom: 0;">{{this.distance}}km</p>
|
||||
<p style="font-size: 1cm;">{{__ "fuer-den-guten-zweck-zurueckgelegt"}}</p>
|
||||
</main>
|
||||
<footer class="certificate-footer">
|
||||
<img src="./certificate_footer.png">
|
||||
</footer>
|
||||
</article>
|
||||
<article class="sheet">
|
||||
<header class="content has-text-centered">
|
||||
<h1 style="font-size: 2.5cm;">{{__ "sponsorings"}}</h1>
|
||||
</header>
|
||||
<main>
|
||||
<table style="border: solid; width: 17cm;">
|
||||
<thead>
|
||||
<td class=".td-head">{{__ "sponsor-in"}}</td>
|
||||
<td>{{__ "betrag-km"}}</td>
|
||||
<td>{{__ "gesamtbetrag"}}</td>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each this.distanceDonations}}
|
||||
<tr>
|
||||
<td>{{this.donor.firstname}} {{this.donor.middlename}} {{this.donor.lastname}}</td>
|
||||
<td>{{this.amountPerDistance}}</td>
|
||||
<td>{{this.amount}}]</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<td>{{__ "gesamt"}}</td>
|
||||
<td>0.5€</td>
|
||||
<td>1€</td>
|
||||
</tfoot>
|
||||
</table>
|
||||
</main>
|
||||
<footer class="certificate-footer">
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et
|
||||
dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
|
||||
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
</p>
|
||||
</footer>
|
||||
</article>
|
||||
{{/each}}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in new issue
Block a user