Compare commits

...

131 Commits
v0.3.2 ... main

Author SHA1 Message Date
Nicolai Ort 57a84c256a Merge pull request 'Fixed decimal separator' (#47) from dev into main
continuous-integration/drone/push Build is passing Details
Reviewed-on: #47
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-07-19 16:15:35 +00:00
Nicolai Ort b78534e1b0 🧾New changelog file version [CI SKIP] [skip ci] 2021-07-19 16:14:59 +00:00
Nicolai Ort 9b85b54da5 Merge branch 'dev' of git.odit.services:lfk/document-server into dev
continuous-integration/drone/push Build is passing Details
2021-07-19 18:14:03 +02:00
Nicolai Ort 4b5a86282d 🚀Bumped version to v0.5.4 2021-07-19 18:13:53 +02:00
Nicolai Ort c9cb03ea95
Fixed decimal separator in docker 2021-07-19 18:13:37 +02:00
Philipp Dormann c7f57548f3 🧾New changelog file version [CI SKIP] [skip ci] 2021-07-19 15:53:52 +00:00
Philipp Dormann 8d00307170 Merge pull request 'Hotfixes' (#46) from dev into main
continuous-integration/drone/push Build is passing Details
Reviewed-on: #46
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-07-19 15:53:40 +00:00
Nicolai Ort 5e92b9a48f 🧾New changelog file version [CI SKIP] [skip ci] 2021-07-19 15:50:28 +00:00
Nicolai Ort 01e1323555 🚀Bumped version to v0.5.3
continuous-integration/drone/push Build is passing Details
2021-07-19 17:49:35 +02:00
Nicolai Ort f8465721cd 🧾New changelog file version [CI SKIP] [skip ci] 2021-07-19 15:41:59 +00:00
Nicolai Ort 4cea7cb32f Merge branch 'dev' of git.odit.services:lfk/document-server into dev
continuous-integration/drone/push Build is passing Details
2021-07-19 17:41:13 +02:00
Nicolai Ort 72303b1105
Fix for runner donation array 2021-07-19 17:39:52 +02:00
Nicolai Ort 451b7fbe05 🧾New changelog file version [CI SKIP] [skip ci] 2021-07-19 15:23:19 +00:00
Nicolai Ort 2a3322612d
Fixed Locale comma format
continuous-integration/drone/push Build is passing Details
2021-07-19 17:22:03 +02:00
Philipp Dormann 4b4d66ae78 🧾New changelog file version [CI SKIP] [skip ci] 2021-07-04 11:42:27 +00:00
Philipp Dormann c935950eb0 Merge pull request 'v0.5.2: hotfix TypeError in Runner Certificate generation' (#45) from dev into main
continuous-integration/drone/push Build is passing Details
Reviewed-on: #45
2021-07-04 11:41:55 +00:00
Philipp Dormann 573b921197 🧾New changelog file version [CI SKIP] [skip ci] 2021-07-04 11:40:08 +00:00
Philipp Dormann 274c13e358
🚀Bumped version to v0.5.2
continuous-integration/drone/push Build is passing Details
2021-07-04 13:39:06 +02:00
Philipp Dormann ff0421da2f 🧾New changelog file version [CI SKIP] [skip ci] 2021-07-04 11:34:41 +00:00
Philipp Dormann 915baa6efa Merge branch 'bugfix/44-runner-certificates-result-in-a-status-500' into dev
continuous-integration/drone/push Build is passing Details
close #44
2021-07-04 13:33:50 +02:00
Philipp Dormann bac004d74e wrap distanceDonations.reduce in array length check
ref #44
2021-07-04 13:32:53 +02:00
Nicolai Ort b7b7f6a0ae 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-22 16:16:50 +00:00
Nicolai Ort 11efdebacf Merge pull request 'Release 0.5.1' (#43) from dev into main
continuous-integration/drone/push Build is passing Details
Reviewed-on: #43
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-04-22 16:16:12 +00:00
Nicolai Ort 0f2d6f58d6 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-22 16:14:54 +00:00
Nicolai Ort df8bd1133b Merge branch 'dev' of git.odit.services:lfk/document-server into dev
continuous-integration/drone/push Build is passing Details
2021-04-22 18:14:02 +02:00
Nicolai Ort 22fb3edd78 🚀Bumped version to v0.5.1 2021-04-22 18:13:50 +02:00
Nicolai Ort ded610f114 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-22 16:13:22 +00:00
Nicolai Ort a4c8dade23 Updated docker-compose example🐳
continuous-integration/drone/push Build is passing Details
2021-04-22 18:12:38 +02:00
Nicolai Ort b6fc069042 Emoji+Chinese fixes🌍 2021-04-22 18:10:32 +02:00
Nicolai Ort 60cc343adf 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-22 15:55:26 +00:00
Nicolai Ort 010f2046ad Added new config options to reamde
continuous-integration/drone/push Build is passing Details
2021-04-22 17:54:43 +02:00
Nicolai Ort c18cb7f135 Merge branch 'dev' of git.odit.services:lfk/document-server into dev 2021-04-22 17:50:46 +02:00
Philipp Dormann 2e7c3e8a5b 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-22 15:50:43 +00:00
Nicolai Ort ac9be793bd You can now configure the card's code format distinct from the others 2021-04-22 17:50:42 +02:00
Philipp Dormann c18fc4ec93 Merge branch 'dev' of https://git.odit.services/lfk/document-server into dev
continuous-integration/drone/push Build is passing Details
2021-04-22 17:49:40 +02:00
Philipp Dormann 981bae4786 more typo fixes 2021-04-22 17:49:31 +02:00
Philipp Dormann 754d0ca58c 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-22 15:47:59 +00:00
Philipp Dormann fa26ed6012 typo fixes
continuous-integration/drone/push Build is passing Details
2021-04-22 17:47:19 +02:00
Nicolai Ort cc4a2b4ab4 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-22 15:44:08 +00:00
Nicolai Ort e97e209746 Now laoding card subtitle from env
continuous-integration/drone/push Build is passing Details
2021-04-22 17:41:36 +02:00
Nicolai Ort 8f30d8933f Fixed typo in translation 2021-04-22 17:35:02 +02:00
Nicolai Ort f78037c0f1 Fixed barcode generation for runenrcard pdfs🐞 2021-04-22 17:32:36 +02:00
Nicolai Ort 3c02e13997 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-16 19:10:33 +00:00
Nicolai Ort d8f3a6ed06 Dependenc bump 🔝
continuous-integration/drone/push Build is passing Details
2021-04-16 21:09:03 +02:00
Nicolai Ort 2ee4c06055 🧾New changelog file version [CI SKIP] [skip ci] 2021-04-11 17:49:45 +00:00
Nicolai Ort 76418f65e1 Quick callstack fix🛠
continuous-integration/drone/push Build is passing Details
2021-04-11 19:49:05 +02:00
Nicolai Ort a57e0909b9 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-31 18:16:18 +00:00
Nicolai Ort a81db03ba3 Merge pull request 'Release 0.5.0' (#42) from dev into main
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details
Reviewed-on: #42
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-03-31 18:15:32 +00:00
Nicolai Ort 7ae4750307 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-31 17:20:16 +00:00
Nicolai Ort f623c0a7cd 🚀Bumped version to v0.5.0
continuous-integration/drone/push Build is passing Details
2021-03-31 19:15:06 +02:00
Nicolai Ort 3fc612488d 📖New license file version [CI SKIP] [skip ci] 2021-03-31 17:11:04 +00:00
Nicolai Ort f220e70743 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-31 17:10:05 +00:00
Nicolai Ort d3f7d1a6c9 Merge pull request 'Generate runner certificates feature/36-runner_certificates' (#41) from feature/36-runner_certificates into dev
continuous-integration/drone/push Build is passing Details
Reviewed-on: #41
2021-03-31 17:09:24 +00:00
Nicolai Ort 82159bed53 Pinned dev dependencies
ref #36
2021-03-31 17:19:48 +02:00
Nicolai Ort 479e28c46c Pinned depencencies (and bumped some)
ref #36
2021-03-31 17:18:43 +02:00
Nicolai Ort e75f15142e disabled testing for now
ref #36
2021-03-31 17:15:57 +02:00
Nicolai Ort cec893032d disabled testing for now
ref #36
2021-03-31 17:15:29 +02:00
Nicolai Ort 2278e4ad06 Sorted translations 🌍
ref #36
2021-03-31 17:14:20 +02:00
Nicolai Ort 5a98688d60 Documented new env var
ref #36
2021-03-31 17:13:54 +02:00
Nicolai Ort 63c7beb8b9 Made footer text configureable
ref #36
2021-03-31 17:12:41 +02:00
Nicolai Ort 2a4cfdb2f8 Fixed background opacity
ref #36
2021-03-31 17:08:57 +02:00
Nicolai Ort a580841973 Addest first coupple of test improvements
ref #36
2021-03-31 16:43:59 +02:00
Nicolai Ort 6b23dea477 Now calculateing total donations (perdistance)
ref #36
2021-03-31 16:31:44 +02:00
Nicolai Ort e0add846bb Now formatting currency ans distance
ref #36
2021-03-31 16:24:05 +02:00
Nicolai Ort 1d12de7045 Fixed typo
ref #36
2021-03-31 16:17:48 +02:00
Nicolai Ort b43aeec0cf Added missing interpolations
ref #36
2021-03-31 16:16:37 +02:00
Nicolai Ort 405bb20601 Merge branch 'feature/36-runner_certificates' of git.odit.services:lfk/document-server into feature/36-runner_certificates 2021-03-31 16:15:51 +02:00
Nicolai Ort ac572f1ea3 Added translations
ref #36
2021-03-31 16:15:49 +02:00
Nicolai Ort 7fea1ca78f Added translations
ref #46
2021-03-31 16:15:42 +02:00
Nicolai Ort 64fce5bd01 Now with embedded background
ref #36
2021-03-31 16:09:15 +02:00
Nicolai Ort 5ba26c4cbf Removed temporary background-image fix
ref #36
2021-03-31 16:05:13 +02:00
Nicolai Ort b82a32ae3e Fixed page size+background image
ref #36
2021-03-31 15:42:52 +02:00
Nicolai Ort 0af9b81b38 Added new basic certificate endpoint
ref #36
2021-03-31 15:22:16 +02:00
Nicolai Ort 955e11846b Added function for generateing runner certificates
ref #36
2021-03-31 15:18:36 +02:00
Nicolai Ort d1577cd08d Merge branch 'feature/36-runner_certificates' of git.odit.services:lfk/document-server into feature/36-runner_certificates 2021-03-31 15:13:14 +02:00
Nicolai Ort 6767c3b2d1 Added template strings
ref #36
2021-03-31 15:13:12 +02:00
Nicolai Ort 2b2195727b Added template strings
ref #46
2021-03-31 15:13:08 +02:00
Nicolai Ort 3ca2237953 Added backside table
ref #36
2021-03-31 15:09:14 +02:00
Nicolai Ort 8d6ea4dbf9 Fixed bg image opacity overlay
ref #36
2021-03-31 15:00:12 +02:00
Nicolai Ort 8b71608792 Added front certificate design
ref #36
2021-03-31 14:51:41 +02:00
Nicolai Ort f1084b59a7 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-30 16:08:57 +00:00
Nicolai Ort c8dc998ecd Merge pull request 'Release 0.4.3' (#40) from dev into main
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
Reviewed-on: #40
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-03-30 16:07:37 +00:00
Nicolai Ort 3df3d26708 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-30 16:07:01 +00:00
Nicolai Ort 922e762aa2 Merge branch 'dev' of git.odit.services:lfk/document-server into dev
continuous-integration/drone/push Build is passing Details
2021-03-30 18:06:02 +02:00
Nicolai Ort c3beb3e103 🚀Bumped version to v0.4.3 2021-03-30 18:05:48 +02:00
Nicolai Ort 457ea26cf8 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-30 16:05:37 +00:00
Nicolai Ort c2d2b66f2f Pipeline mtu fix
continuous-integration/drone/push Build was killed Details
2021-03-30 18:04:54 +02:00
Nicolai Ort 289a0d8671 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-29 16:48:57 +00:00
Nicolai Ort ce3053c0ba Merge pull request 'Release 0.4.2' (#39) from dev into main
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build was killed Details
Reviewed-on: #39
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-03-29 16:46:31 +00:00
Nicolai Ort 6608456c68 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-29 16:44:43 +00:00
Nicolai Ort 1cbe5a1614 🚀Bumped version to v0.4.2
continuous-integration/drone/push Build is failing Details
2021-03-29 18:43:29 +02:00
Nicolai Ort 9584bfed8b Fixed faulty object mapping 2021-03-29 18:42:50 +02:00
Nicolai Ort 0839ff6359 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-20 17:13:45 +00:00
Nicolai Ort 4739193709 Merge branch 'dev' of git.odit.services:lfk/document-server into dev
continuous-integration/drone/push Build is passing Details
2021-03-20 18:12:54 +01:00
Nicolai Ort 0ade57536e 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-20 17:13:17 +00:00
Nicolai Ort d17108f4b9 🚀Bumped version to v0.4.1 2021-03-20 18:12:50 +01:00
Nicolai Ort 3c42ca3042 Emergency bugfixes 🐞
continuous-integration/drone/push Build is failing Details
2021-03-20 18:12:34 +01:00
Nicolai Ort 073433f308 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-15 14:31:35 +00:00
Nicolai Ort 8bac1fadd6 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-14 20:20:59 +00:00
Nicolai Ort a478081727 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-14 20:14:03 +00:00
Nicolai Ort b1978e796f Merge branch 'dev' of git.odit.services:lfk/document-server into dev
continuous-integration/drone/push Build is passing Details
2021-03-14 21:13:19 +01:00
Nicolai Ort c51ec74d30 Let's try the mtu fix
´
2021-03-14 21:13:14 +01:00
Nicolai Ort b8f0d1fa60 🧾New changelog file version [CI SKIP] [skip ci] 2021-03-14 20:05:37 +00:00
Nicolai Ort 96886c74bc Now using our own images to build stuff 🚀
continuous-integration/drone/push Build was killed Details
2021-03-14 21:04:51 +01:00
Nicolai Ort 8d3cc34395 Merge pull request 'Alpha Release 0.4.0' (#38) from dev into main
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/tag Build is failing Details
Reviewed-on: #38
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-03-14 15:51:53 +00:00
Nicolai Ort 85519bc2e4 🚀Bumped version to v0.4.0
continuous-integration/drone/push Build is failing Details
2021-03-14 16:33:17 +01:00
Nicolai Ort ed02306738 Merge pull request 'Configureable contracts amount feature/35-contracts_per_runner' (#37) from feature/35-contracts_per_runner into dev
continuous-integration/drone/push Build is failing Details
Reviewed-on: #37
2021-03-14 15:31:26 +00:00
Nicolai Ort 31a59500fa Documented the new config var
ref #35
2021-03-13 14:03:14 +01:00
Nicolai Ort d01b4a0b99 Added config for amount of contracts per runner
ref #35
2021-03-13 14:01:30 +01:00
Nicolai Ort d9919404b5 Added logic for generateing multiple contracts per runner
ref #35
2021-03-13 13:59:34 +01:00
Nicolai Ort b180e04045 Updated ci with new kubernetes secrets 🚀🚀🚀
continuous-integration/drone/push Build is failing Details
ref odit/org#12
2021-03-12 18:58:09 +01:00
Nicolai Ort 7f28525ec2 Merge branch 'feature/33-disclaimer' into dev
continuous-integration/drone/push Build is failing Details
2021-03-10 20:15:39 +01:00
Nicolai Ort 677bd86133 Changed ci pipeline type to kubernetes
ref odit/org#12 (comment)
2021-03-10 20:11:16 +01:00
Nicolai Ort b612562d34 🧾New changelog file version [CI SKIP] [skip ci] 2021-02-20 15:19:11 +00:00
Nicolai Ort e9d3574599 Merge pull request 'Configurable sponsoring disclaimer feature/33-disclaimer' (#34) from feature/33-disclaimer into dev
continuous-integration/drone/push Build is passing Details
Reviewed-on: #34
2021-02-20 15:18:55 +00:00
Nicolai Ort 9dd62cefa9 Added reamde entry for the new env var
ref #33
2021-02-20 16:05:58 +01:00
Nicolai Ort 0797c678c8 Merge branch 'feature/33-disclaimer' of git.odit.services:lfk/document-server into feature/33-disclaimer 2021-02-20 16:04:02 +01:00
Nicolai Ort 5e4d6f44da MAde disclaimer configurable via env
ref #33
2021-02-20 16:04:00 +01:00
Nicolai Ort 885765ac71 MAde disclaimer configurable via env 2021-02-20 16:03:54 +01:00
Nicolai Ort 03ed6d5bc1 Updated styleing
ref #33
2021-02-20 16:03:15 +01:00
Nicolai Ort 4e1e124d0d Added disclaimer to template
ref #33
2021-02-20 15:58:11 +01:00
Nicolai Ort 19fbf50f6f 🧾New changelog file version [CI SKIP] [skip ci] 2021-02-19 19:10:02 +00:00
Nicolai Ort 21b5e048ed Merge pull request 'Alpha Release 0.3.3 - Download options' (#32) from dev into main
continuous-integration/drone/tag Build is passing Details
continuous-integration/drone/push Build is passing Details
Reviewed-on: #32
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
2021-02-19 19:09:25 +00:00
Nicolai Ort c012b4943d 🧾New changelog file version [CI SKIP] [skip ci] 2021-02-19 19:08:18 +00:00
Nicolai Ort 7c23dba493 Merge branch 'dev' of git.odit.services:lfk/document-server into dev
continuous-integration/drone/push Build is passing Details
2021-02-19 20:07:59 +01:00
Nicolai Ort ba566bcc33 🚀Bumped version to v0.3.3 2021-02-19 20:04:44 +01:00
Nicolai Ort a386c5bef8 🧾New changelog file version [CI SKIP] [skip ci] 2021-02-19 19:04:35 +00:00
Nicolai Ort 1ca5d3ea07 Added download option to cards
continuous-integration/drone/push Build is passing Details
2021-02-19 20:04:15 +01:00
Nicolai Ort fd8b7e56da 🧾New changelog file version [CI SKIP] [skip ci] 2021-02-19 18:35:54 +00:00
Nicolai Ort 55877de2aa Added download header
continuous-integration/drone/push Build is passing Details
2021-02-19 19:35:06 +01:00
Nicolai Ort d1a29c1cbb 🧾New changelog file version [CI SKIP] [skip ci] 2021-02-18 15:22:54 +00:00
19 changed files with 888 additions and 393 deletions

View File

@ -1,6 +1,27 @@
---
kind: secret
name: docker_username
get:
path: odit-registry-builder
name: username
---
kind: secret
name: docker_password
get:
path: odit-registry-builder
name: password
---
kind: secret
name: git_ssh
get:
path: odit-git-bot
name: sshkey
---
kind: pipeline
type: docker
type: kubernetes
name: build:dev
clone:
disable: true
@ -16,13 +37,14 @@ steps:
depends_on: [clone]
settings:
username:
from_secret: DOCKER_REGISTRY_USER
from_secret: docker_username
password:
from_secret: DOCKER_REGISTRY_PASSWORD
from_secret: docker_password
repo: registry.odit.services/lfk/document-server
tags:
- dev
registry: registry.odit.services
mtu: 1000
- name: run changelog export
depends_on: ["clone"]
image: node:latest
@ -38,7 +60,7 @@ steps:
author_email: bot@odit.services
remote: git@git.odit.services:lfk/document-server.git
ssh_key:
from_secret: GITLAB_SSHKEY
from_secret: git_ssh
- name: run full license export
depends_on: ["clone"]
image: node:14.15.1-alpine3.12
@ -56,7 +78,7 @@ steps:
remote: git@git.odit.services:lfk/document-server.git
skip_verify: true
ssh_key:
from_secret: GITLAB_SSHKEY
from_secret: git_ssh
trigger:
branch:
@ -66,7 +88,7 @@ trigger:
---
kind: pipeline
type: docker
type: kubernetes
name: build:latest
clone:
disable: true
@ -84,13 +106,14 @@ steps:
image: plugins/docker
settings:
username:
from_secret: DOCKER_REGISTRY_USER
from_secret: docker_username
password:
from_secret: DOCKER_REGISTRY_PASSWORD
from_secret: docker_password
repo: registry.odit.services/lfk/document-server
tags:
- latest
registry: registry.odit.services
mtu: 1000
- name: push merge to repo
depends_on: ["clone"]
image: appleboy/drone-git-push
@ -99,7 +122,7 @@ steps:
commit: false
remote: git@git.odit.services:lfk/document-server.git
ssh_key:
from_secret: GITLAB_SSHKEY
from_secret: git_ssh
trigger:
branch:
@ -109,7 +132,7 @@ trigger:
---
kind: pipeline
type: docker
type: kubernetes
name: build:tags
steps:
@ -118,13 +141,14 @@ steps:
depends_on: [clone]
settings:
username:
from_secret: DOCKER_REGISTRY_USER
from_secret: docker_username
password:
from_secret: DOCKER_REGISTRY_PASSWORD
from_secret: docker_password
repo: registry.odit.services/lfk/document-server
tags:
- '${DRONE_TAG}'
registry: registry.odit.services
mtu: 1000
trigger:
event:
- tag

View File

@ -2,22 +2,175 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v0.5.4](https://git.odit.services/lfk/document-server/compare/v0.5.1...v0.5.4)
- Merge branch 'bugfix/44-runner-certificates-result-in-a-status-500' into dev [`#44`](https://git.odit.services/lfk/document-server/issues/44)
- Fixed Locale comma format [`2a33226`](https://git.odit.services/lfk/document-server/commit/2a3322612d473bd9002cf8d6f9807f9dc7d687da)
- wrap distanceDonations.reduce in array length check [`bac004d`](https://git.odit.services/lfk/document-server/commit/bac004d74eb954d1753d4efcdb927822b89fa757)
- 🧾New changelog file version [CI SKIP] [skip ci] [`ff0421d`](https://git.odit.services/lfk/document-server/commit/ff0421da2f16a8f79f9987dabea7bdcb4ef88c05)
- 🧾New changelog file version [CI SKIP] [skip ci] [`5e92b9a`](https://git.odit.services/lfk/document-server/commit/5e92b9a48fcbb8ab6a179c53f180a7a6bd743ae7)
- Fixed decimal separator in docker [`c9cb03e`](https://git.odit.services/lfk/document-server/commit/c9cb03ea95acccd6cdc8b86c747c787938840d07)
- 🧾New changelog file version [CI SKIP] [skip ci] [`f846572`](https://git.odit.services/lfk/document-server/commit/f8465721cddfb55d51eb30d29d74ef63d825b5ac)
- Fix for runner donation array [`72303b1`](https://git.odit.services/lfk/document-server/commit/72303b11052276ad15373887f9e04183841f56f4)
- 🧾New changelog file version [CI SKIP] [skip ci] [`451b7fb`](https://git.odit.services/lfk/document-server/commit/451b7fbe0543991e8a203e38daa350a954ae0e11)
- 🧾New changelog file version [CI SKIP] [skip ci] [`573b921`](https://git.odit.services/lfk/document-server/commit/573b9211972a55df0a38742cb6eb789d6fd3717b)
- 🚀Bumped version to v0.5.4 [`4b5a862`](https://git.odit.services/lfk/document-server/commit/4b5a86282d0618a0c5b00fc796efe77db2103356)
- 🧾New changelog file version [CI SKIP] [skip ci] [`c7f5754`](https://git.odit.services/lfk/document-server/commit/c7f57548f316e1bb6635bd56bd269d80ac1e220f)
- Merge pull request 'Hotfixes' (#46) from dev into main [`8d00307`](https://git.odit.services/lfk/document-server/commit/8d003071704b5a6d7b0d70aff2f9cb05c3660b78)
- 🚀Bumped version to v0.5.3 [`01e1323`](https://git.odit.services/lfk/document-server/commit/01e1323555fe67f6f0ce3c18163e475035bd1cdd)
- 🧾New changelog file version [CI SKIP] [skip ci] [`4b4d66a`](https://git.odit.services/lfk/document-server/commit/4b4d66ae784150f7e1cc491a3fc5d84c93273aee)
- Merge pull request 'v0.5.2: hotfix TypeError in Runner Certificate generation' (#45) from dev into main [`c935950`](https://git.odit.services/lfk/document-server/commit/c935950eb052bce71185fc74c750ec77f081e7df)
- 🚀Bumped version to v0.5.2 [`274c13e`](https://git.odit.services/lfk/document-server/commit/274c13e358f16207fe8bb5cdc1b9ede0582ecb46)
- 🧾New changelog file version [CI SKIP] [skip ci] [`b7b7f6a`](https://git.odit.services/lfk/document-server/commit/b7b7f6a0ae304d24f90a3de3931f53cf08770060)
#### [v0.5.1](https://git.odit.services/lfk/document-server/compare/v0.5.0...v0.5.1)
> 22 April 2021
- Merge pull request 'Release 0.5.1' (#43) from dev into main [`11efdeb`](https://git.odit.services/lfk/document-server/commit/11efdebacf076ecfe0e10cdcda37ac07464901ce)
- Quick callstack fix🛠 [`76418f6`](https://git.odit.services/lfk/document-server/commit/76418f65e1e111e83838f0d42c541ae6a8063a09)
- Fixed barcode generation for runenrcard pdfs🐞 [`f78037c`](https://git.odit.services/lfk/document-server/commit/f78037c0f15162d5b98986edf20d263961f43e69)
- Updated docker-compose example🐳 [`a4c8dad`](https://git.odit.services/lfk/document-server/commit/a4c8dade23e448d4d4caefe304a6cd9195c873a4)
- Now laoding card subtitle from env [`e97e209`](https://git.odit.services/lfk/document-server/commit/e97e2097463f4c88947e865a38ea1e5aa2be1f5d)
- typo fixes [`fa26ed6`](https://git.odit.services/lfk/document-server/commit/fa26ed6012ded759d3702587dba67c2090324801)
- 🧾New changelog file version [CI SKIP] [skip ci] [`2ee4c06`](https://git.odit.services/lfk/document-server/commit/2ee4c060557a44db1974a015412288f7942ebe72)
- more typo fixes [`981bae4`](https://git.odit.services/lfk/document-server/commit/981bae4786a2fa12a1355122e8c5a1e95e29cf32)
- You can now configure the card's code format distinct from the others [`ac9be79`](https://git.odit.services/lfk/document-server/commit/ac9be793bd598771174f5313ef8288240306ba5c)
- 🧾New changelog file version [CI SKIP] [skip ci] [`0f2d6f5`](https://git.odit.services/lfk/document-server/commit/0f2d6f58d6a8a8888263778cf1a14c73b28e774e)
- 🚀Bumped version to v0.5.1 [`22fb3ed`](https://git.odit.services/lfk/document-server/commit/22fb3edd7836ba4ca35e6b208ab6f6620da60f4a)
- Emoji+Chinese fixes🌍 [`b6fc069`](https://git.odit.services/lfk/document-server/commit/b6fc069042dc9c5d7ec97f2660568e8e105780b9)
- 🧾New changelog file version [CI SKIP] [skip ci] [`cc4a2b4`](https://git.odit.services/lfk/document-server/commit/cc4a2b4ab4c2cb9976797f93e8348607fb88ea7d)
- Dependenc bump 🔝 [`d8f3a6e`](https://git.odit.services/lfk/document-server/commit/d8f3a6ed063a9cdf6189e85ae01a5516b4295892)
- 🧾New changelog file version [CI SKIP] [skip ci] [`a57e090`](https://git.odit.services/lfk/document-server/commit/a57e0909b919a1c720c9994b6baa8910b78dc569)
- 🧾New changelog file version [CI SKIP] [skip ci] [`ded610f`](https://git.odit.services/lfk/document-server/commit/ded610f11464a27429b8184a32554e99aed63f72)
- 🧾New changelog file version [CI SKIP] [skip ci] [`60cc343`](https://git.odit.services/lfk/document-server/commit/60cc343adf71ed3b849d1d93af3d60cbc2820fed)
- Added new config options to reamde [`010f204`](https://git.odit.services/lfk/document-server/commit/010f2046ad326898c75b6546e4d70a6f78346d8b)
- 🧾New changelog file version [CI SKIP] [skip ci] [`2e7c3e8`](https://git.odit.services/lfk/document-server/commit/2e7c3e8a5b7f6a0461254b33c6f412929719c966)
- 🧾New changelog file version [CI SKIP] [skip ci] [`754d0ca`](https://git.odit.services/lfk/document-server/commit/754d0ca58ccf8f77570ff6218f2dec61cfb4f808)
- Fixed typo in translation [`8f30d89`](https://git.odit.services/lfk/document-server/commit/8f30d8933f105b4bf112c81222a72ca1931145d7)
- 🧾New changelog file version [CI SKIP] [skip ci] [`3c02e13`](https://git.odit.services/lfk/document-server/commit/3c02e13997b1626fb0e6496da4c58eac2cc6fcf8)
#### [v0.5.0](https://git.odit.services/lfk/document-server/compare/v0.4.3...v0.5.0)
> 31 March 2021
- Merge pull request 'Release 0.5.0' (#42) from dev into main [`a81db03`](https://git.odit.services/lfk/document-server/commit/a81db03ba3b274c44be4b4c0c318083bdeb07987)
- Added translations [`ac572f1`](https://git.odit.services/lfk/document-server/commit/ac572f1ea31cb66985e04cb5d56cc67f521e990d)
- Added translations [`7fea1ca`](https://git.odit.services/lfk/document-server/commit/7fea1ca78ff6fdbb38dee0edd9918eaeb1264d18)
- Sorted translations 🌍 [`2278e4a`](https://git.odit.services/lfk/document-server/commit/2278e4ad06947b540323856ea1e71022562ea719)
- Added front certificate design [`8b71608`](https://git.odit.services/lfk/document-server/commit/8b71608792f00084df1e71956e503f102cea290d)
- 📖New license file version [CI SKIP] [skip ci] [`3fc6124`](https://git.odit.services/lfk/document-server/commit/3fc612488d1f231d83d6a5823a13dc4817e6a588)
- Addest first coupple of test improvements [`a580841`](https://git.odit.services/lfk/document-server/commit/a5808419738563fec3a7d8d35f4ce20d76c017fb)
- Pinned depencencies (and bumped some) [`479e28c`](https://git.odit.services/lfk/document-server/commit/479e28c46c6b3b8ba1622bcf5712695a94c2ae89)
- Added new basic certificate endpoint [`0af9b81`](https://git.odit.services/lfk/document-server/commit/0af9b81b38e1c28261c012375af2c91808e65621)
- Added function for generateing runner certificates [`955e118`](https://git.odit.services/lfk/document-server/commit/955e11846b5385c1a0b6f0b54b9951f0768ff414)
- 🧾New changelog file version [CI SKIP] [skip ci] [`f220e70`](https://git.odit.services/lfk/document-server/commit/f220e70743534c1fc66ff6f50e3693182d35990a)
- Now formatting currency ans distance [`e0add84`](https://git.odit.services/lfk/document-server/commit/e0add846bb37b435da9807bdc76c70793002896e)
- Fixed bg image opacity overlay [`8d6ea4d`](https://git.odit.services/lfk/document-server/commit/8d6ea4dbf9763994f0f44c4ad9b32a7b1d16f11a)
- Pinned dev dependencies [`82159be`](https://git.odit.services/lfk/document-server/commit/82159bed536bbafd20746927f5a7f61f76959637)
- Now calculateing total donations (perdistance) [`6b23dea`](https://git.odit.services/lfk/document-server/commit/6b23dea47745e98371a65a4f577f2e20cfdfe597)
- Added backside table [`3ca2237`](https://git.odit.services/lfk/document-server/commit/3ca22379535bba72d05e0b3fafe22d3a4b2f549d)
- Added template strings [`6767c3b`](https://git.odit.services/lfk/document-server/commit/6767c3b2d1e991e2f4f74b8d423a72e240ffcb8c)
- Added template strings [`2b21957`](https://git.odit.services/lfk/document-server/commit/2b2195727b15b8666edf0d925f2e68a98030153d)
- Fixed background opacity [`2a4cfdb`](https://git.odit.services/lfk/document-server/commit/2a4cfdb2f88ad3ac1ebc925199a440756e9e9d3a)
- Now with embedded background [`64fce5b`](https://git.odit.services/lfk/document-server/commit/64fce5bd019a00bf34c1ebd133c1904bb577b67b)
- 🧾New changelog file version [CI SKIP] [skip ci] [`7ae4750`](https://git.odit.services/lfk/document-server/commit/7ae47503076f6721d1cfd82fbf8218b9febfa580)
- 🚀Bumped version to v0.5.0 [`f623c0a`](https://git.odit.services/lfk/document-server/commit/f623c0a7cd06f707ac488456c9e8a051d3ceae46)
- Merge pull request 'Generate runner certificates feature/36-runner_certificates' (#41) from feature/36-runner_certificates into dev [`d3f7d1a`](https://git.odit.services/lfk/document-server/commit/d3f7d1a6c9858d7fdf09c696622962e6f8471e78)
- disabled testing for now [`cec8930`](https://git.odit.services/lfk/document-server/commit/cec893032dea9f312e37841232a9434e19b79003)
- Added missing interpolations [`b43aeec`](https://git.odit.services/lfk/document-server/commit/b43aeec0cf40a9c37a10072062ab5d93102f6c81)
- Made footer text configureable [`63c7beb`](https://git.odit.services/lfk/document-server/commit/63c7beb8b9cdc564186c5b86a4f305c8575f5b9f)
- 🧾New changelog file version [CI SKIP] [skip ci] [`f1084b5`](https://git.odit.services/lfk/document-server/commit/f1084b59a74dcc5981fd314721c36726706f386c)
- disabled testing for now [`e75f151`](https://git.odit.services/lfk/document-server/commit/e75f15142e293349a071a7cdcc53cc10780304f6)
- Removed temporary background-image fix [`5ba26c4`](https://git.odit.services/lfk/document-server/commit/5ba26c4cbfae7d3f31d3709aaeb372c14de78fa9)
- Fixed page size+background image [`b82a32a`](https://git.odit.services/lfk/document-server/commit/b82a32ae3ee3256402be5dde0ada903f2c19a8cc)
- Fixed typo [`1d12de7`](https://git.odit.services/lfk/document-server/commit/1d12de7045b5e8324dc0ddc421944e70ffc2ec73)
- Documented new env var [`5a98688`](https://git.odit.services/lfk/document-server/commit/5a98688d60eed34644391ecde638949fe5a46c65)
#### [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)
- 🧾New changelog file version [CI SKIP] [skip ci] [`8bac1fa`](https://git.odit.services/lfk/document-server/commit/8bac1fadd6b4257e5062a1b1673e122c5b535046)
- 🧾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)
- Emergency bugfixes 🐞 [`3c42ca3`](https://git.odit.services/lfk/document-server/commit/3c42ca30427174c21e0db6426d8f0d91a1ebc501)
- Let's try the mtu fix [`c51ec74`](https://git.odit.services/lfk/document-server/commit/c51ec74d30334b156668de4719c77f2e9c6d023f)
#### [v0.4.0](https://git.odit.services/lfk/document-server/compare/v0.3.3...v0.4.0)
> 14 March 2021
- Merge pull request 'Alpha Release 0.4.0' (#38) from dev into main [`8d3cc34`](https://git.odit.services/lfk/document-server/commit/8d3cc34395922a271da1032310da6ec6f7a164f7)
- Updated ci with new kubernetes secrets 🚀🚀🚀 [`b180e04`](https://git.odit.services/lfk/document-server/commit/b180e0404537404d0564453fde5976f4de672a8b)
- Updated styleing [`03ed6d5`](https://git.odit.services/lfk/document-server/commit/03ed6d5bc18c5b26edd7b1d698c9de936e008f32)
- 🧾New changelog file version [CI SKIP] [skip ci] [`b612562`](https://git.odit.services/lfk/document-server/commit/b612562d347f5fafcf4ce94a4508b7c0bb9370c6)
- 🚀Bumped version to v0.4.0 [`85519bc`](https://git.odit.services/lfk/document-server/commit/85519bc2e4e8906732dc5f99e417014a14bad7d0)
- Merge pull request 'Configureable contracts amount feature/35-contracts_per_runner' (#37) from feature/35-contracts_per_runner into dev [`ed02306`](https://git.odit.services/lfk/document-server/commit/ed023067386551dc92d60ba63dff8bc4cc44ce00)
- Added disclaimer to template [`4e1e124`](https://git.odit.services/lfk/document-server/commit/4e1e124d0dc08f96aeb05dd1c975064fe785b80f)
- Changed ci pipeline type to kubernetes [`677bd86`](https://git.odit.services/lfk/document-server/commit/677bd861335302269baec96a59916475bbdd405f)
- Added config for amount of contracts per runner [`d01b4a0`](https://git.odit.services/lfk/document-server/commit/d01b4a0b99f3c1aa088b02d766d21bfb6b9e3a29)
- Added logic for generateing multiple contracts per runner [`d991940`](https://git.odit.services/lfk/document-server/commit/d9919404b5b90151318d20258a273ca6c7640393)
- MAde disclaimer configurable via env [`5e4d6f4`](https://git.odit.services/lfk/document-server/commit/5e4d6f44dab581483135594432bd8c8d65ba74ef)
- MAde disclaimer configurable via env [`885765a`](https://git.odit.services/lfk/document-server/commit/885765ac71b6a65c869ee841c383667f4947dcde)
- Documented the new config var [`31a5950`](https://git.odit.services/lfk/document-server/commit/31a59500fa77f1ad7c54fa297d00c8707ae6db9c)
- Merge pull request 'Configurable sponsoring disclaimer feature/33-disclaimer' (#34) from feature/33-disclaimer into dev [`e9d3574`](https://git.odit.services/lfk/document-server/commit/e9d35745997a9e948509ea67b59f5a7658f9d652)
- 🧾New changelog file version [CI SKIP] [skip ci] [`19fbf50`](https://git.odit.services/lfk/document-server/commit/19fbf50f6f6057c5321a999b6551d05db32b5fd8)
- Added reamde entry for the new env var [`9dd62ce`](https://git.odit.services/lfk/document-server/commit/9dd62cefa94bf3f0bf8e77fd25e7ca1ec4b30e2b)
#### [v0.3.3](https://git.odit.services/lfk/document-server/compare/v0.3.2...v0.3.3)
> 19 February 2021
- Merge pull request 'Alpha Release 0.3.3 - Download options' (#32) from dev into main [`21b5e04`](https://git.odit.services/lfk/document-server/commit/21b5e048ed5ed72f88304e5c737639c54cc71483)
- 🧾New changelog file version [CI SKIP] [skip ci] [`d1a29c1`](https://git.odit.services/lfk/document-server/commit/d1a29c1cbb8845a1adf8a414d158ebcabd48dc04)
- 🧾New changelog file version [CI SKIP] [skip ci] [`fd8b7e5`](https://git.odit.services/lfk/document-server/commit/fd8b7e56da4a1601141f63627e3990660c521ea6)
- Added download option to cards [`1ca5d3e`](https://git.odit.services/lfk/document-server/commit/1ca5d3ea078ef51818657e2b3c9f114c67bff86d)
- Added download header [`55877de`](https://git.odit.services/lfk/document-server/commit/55877de2aa46583f30d033467037e0454d1236be)
- 🧾New changelog file version [CI SKIP] [skip ci] [`c012b49`](https://git.odit.services/lfk/document-server/commit/c012b4943d96ee3a9442c65389c4dcea08642109)
- 🚀Bumped version to v0.3.3 [`ba566bc`](https://git.odit.services/lfk/document-server/commit/ba566bcc33ed920324cd9977b3f293a2c629f92c)
- 🧾New changelog file version [CI SKIP] [skip ci] [`a386c5b`](https://git.odit.services/lfk/document-server/commit/a386c5bef88da29e4447399d4edca0234b674ed5)
#### [v0.3.2](https://git.odit.services/lfk/document-server/compare/v0.3.0...v0.3.2)
- 🧾New changelog file version [CI SKIP] [skip ci] [`cc6a53b`](https://git.odit.services/lfk/document-server/commit/cc6a53b25895594874acca370a1439d37bb280de)
- 🚀Bumped version to v0.3.2 [`a9019e4`](https://git.odit.services/lfk/document-server/commit/a9019e4c67e7620b65650d60b0ebd57bc11a854e)
- Merge pull request 'Now using full group names feature/18-group_names' (#30) from feature/18-group_names into dev [`e0db6f6`](https://git.odit.services/lfk/document-server/commit/e0db6f6a78d0026a8485a57c88af1e9407bd68a4)
> 18 February 2021
- Merge pull request 'Alpha Release 0.3.2' (#31) from dev into main [`e6f7dd2`](https://git.odit.services/lfk/document-server/commit/e6f7dd2be8d729f5fc7fbb458cc859b113f5aa86)
- 🚀Bumped version to v0.3.1 [`dcde424`](https://git.odit.services/lfk/document-server/commit/dcde424b77dcc9753859f94f7bcbe24fe3523c27)
- 📖New license file version [CI SKIP] [skip ci] [`92c5240`](https://git.odit.services/lfk/document-server/commit/92c52401b398f6a2f247c10879e17f6dc105aa8e)
- Now manually parsing runnergroup full names [`c290908`](https://git.odit.services/lfk/document-server/commit/c2909082a2dbb38041ae0fc695bd0fa1451b39ff)
- Implemented basic auth [`bdeadd2`](https://git.odit.services/lfk/document-server/commit/bdeadd274bc0f9c8cbab35a8a5605bef4c22ba6c)
- 📖New license file version [CI SKIP] [skip ci] [`9d7d044`](https://git.odit.services/lfk/document-server/commit/9d7d0443848522e5bdfdb6a80c836bea4bc200a1)
- 🧾New changelog file version [CI SKIP] [skip ci] [`cc6a53b`](https://git.odit.services/lfk/document-server/commit/cc6a53b25895594874acca370a1439d37bb280de)
- 🧾New changelog file version [CI SKIP] [skip ci] [`e306cdb`](https://git.odit.services/lfk/document-server/commit/e306cdb2c8e58fc1aef79b95cba5d4cc96ac7658)
- Added auth to openapi spec [`729f2d7`](https://git.odit.services/lfk/document-server/commit/729f2d7240b54ffe2d4db36cce29de0afdfc9417)
- Pinned routing controllers version as temp workaround for routing controllers openapi being broken again [`7ca7266`](https://git.odit.services/lfk/document-server/commit/7ca7266ea46965251c9df637a2556f2a1706e7e6)
- 🧾New changelog file version [CI SKIP] [skip ci] [`adf11ab`](https://git.odit.services/lfk/document-server/commit/adf11ab1c356b6964230541331836abd363170b0)
- 🧾New changelog file version [CI SKIP] [skip ci] [`b7c6c6e`](https://git.odit.services/lfk/document-server/commit/b7c6c6e15708e471f5c3d0ca4cf11b1c08c88c9c)
- 🧾New changelog file version [CI SKIP] [skip ci] [`95099c5`](https://git.odit.services/lfk/document-server/commit/95099c5fbd7e6cb07c68151a998eebb0f00556f3)
- 🧾New changelog file version [CI SKIP] [skip ci] [`49590b8`](https://git.odit.services/lfk/document-server/commit/49590b897ed5ee5c9386d34408ac6868f43cc27c)
- 🚀Bumped version to v0.3.2 [`a9019e4`](https://git.odit.services/lfk/document-server/commit/a9019e4c67e7620b65650d60b0ebd57bc11a854e)
- Merge pull request 'Now using full group names feature/18-group_names' (#30) from feature/18-group_names into dev [`e0db6f6`](https://git.odit.services/lfk/document-server/commit/e0db6f6a78d0026a8485a57c88af1e9407bd68a4)
- 🧾New changelog file version [CI SKIP] [skip ci] [`adf11ab`](https://git.odit.services/lfk/document-server/commit/adf11ab1c356b6964230541331836abd363170b0)
- Updated templates with full group name [`0fcfb30`](https://git.odit.services/lfk/document-server/commit/0fcfb30d5c13266ca4faf7697308dfb7a0f91b4f)
- Merge pull request 'Alpha Release 0.3.1 - API Keys' (#29) from dev into main [`db91661`](https://git.odit.services/lfk/document-server/commit/db916615564813e8d21e3672581e4f3a4d748b89)
- Merge pull request 'API Key based auth feature/26-api_auth' (#27) from feature/26-api_auth into dev [`2d031da`](https://git.odit.services/lfk/document-server/commit/2d031dae035866a4aa247398ea68ff338ab58cbd)

View File

@ -1,5 +1,5 @@
# Typescript Build
FROM registry.odit.services/mirror/node:14.15.1-alpine3.12
FROM registry.odit.services/hub/library/node:14.15.1-alpine3.12
WORKDIR /app
COPY package.json ./
RUN npm i -g pnpm
@ -8,7 +8,7 @@ COPY tsconfig.json ./
COPY src ./src
RUN pnpm run build
# final image
FROM registry.odit.services/mirror/alpine:3.13.1
FROM registry.odit.services/hub/library/alpine:3.13.1
WORKDIR /app
RUN apk add --no-cache \
chromium \
@ -19,7 +19,9 @@ RUN apk add --no-cache \
ca-certificates \
ttf-freefont \
nodejs \
yarn
yarn \
font-noto-emoji \
&& apk add wqy-zenhei --update-cache --repository https://nl.alpinelinux.org/alpine/edge/testing
# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \

View File

@ -36,6 +36,12 @@ The basic generation mechanism makes the templates and routes interchangeable (i
| SPONSORING_RECEIPT_MINIMUM_AMOUNT | String | "10" | The mimimum total donation amount a sponsor has to donate to be able to receive a donation receipt - used to generate pdf text.
| SPONOR_LOGOS | Array<String> | Empty png | The sponsor images you want to loop through. You can provide them via http url, local file or base64-encoded image.
| API_KEY | String(min length: 64) | Random generated string | The api key you want to use for auth (query-param `key`), has to be at least 64 chars long.
| DISCLAIMER_TEXT | String | N/A | A disclaimer that will get displayed on the bottom of each sponsoring contract. R/N You can only provide the disclaimer for one language.
| DONATIONS_FOOTER_TEXT | String | N/A | A text that will get displayed on the bottom of each runner certificate's second page. R/N You can only provide the text for one language.
| CONTRACTS_PER_RUNNER | Number | 1 | The amount of contracts that get created per runner (per request).
| CODEFORMAT | String | code39 | The barcode format for everything except.
| CODEFORMAT_CARDS | String | code39 | The barcode format for runnercards (overwrites CODEFORMAT).
| CARD_SUBTITLE | String | Empty | A subtitle that get's displayed on the cards under the eventname.
## Templates
> The document server uses html templates to generate various pdf documents.

View File

@ -1,9 +1,18 @@
version: "3"
services:
document_server:
build: .
ports:
- 4010:4010
environment:
APP_PORT: 4010
NODE_ENV: production
version: "3"
services:
document_server:
build: .
ports:
- 4010:4010
environment:
APP_PORT: 4010
NODE_ENV: production
EVENT_NAME: "Testen für Kaya!"
CURRENCY_SYMBOL: "€"
API_KEY: NqZSYTy5AFQ7MppbLW5moqpTk7u7YrNUHKYhKYuThnnya2WpCOIU694hIZT1FzYe
CONTRACTS_PER_RUNNER: 2
SPONSORING_RECEIPT_MINIMUM_AMOUNT: 42
DISCLAIMER_TEXT: "Hier könnte ihre Werbung stehen"
CODEFORMAT: "code39"
CODEFORMAT_CARDS: "ean13"
CARD_SUBTITLE: "Hier könnte mehr Werbung stehen"

View File

@ -1,6 +1,6 @@
# @odit/class-validator-jsonschema
**Author**: Aleksi Pekkala <aleksipekkala@gmail.com>
**Repo**: git@github.com:epiphone/class-validator-jsonschema.git
**Repo**: git@github.com:epiphone/class-validator-jsonschema
**License**: MIT
**Description**: Convert class-validator-decorated classes into JSON schema
## License Text
@ -29,7 +29,7 @@ SOFTWARE.
# async-helpers
**Author**: Brian Woodward (https://github.com/doowb)
**Repo**: doowb/async-helpers
**Repo**: https://github.com/doowb/async-helpers
**License**: MIT
**Description**: Use async helpers in templates with engines that typically only handle sync helpers. Handlebars and Lodash have been tested.
## License Text
@ -58,7 +58,7 @@ THE SOFTWARE.
# axios
**Author**: Matt Zabriskie
**Repo**: https://github.com/axios/axios.git
**Repo**: https://github.com/axios/axios
**License**: MIT
**Description**: Promise based HTTP client for the browser and node.js
## License Text
@ -85,7 +85,7 @@ THE SOFTWARE.
# bwip-js
**Author**: Mark Warren <mwarren@metafloor.com>
**Repo**: https://github.com/metafloor/bwip-js.git
**Repo**: https://github.com/metafloor/bwip-js
**License**: MIT
**Description**: JavaScript barcode generator supporting over 100 types and standards.
## License Text
@ -117,7 +117,7 @@ THE SOFTWARE.
# cheerio
**Author**: Matt Mueller <mattmuelle@gmail.com> (mat.io)
**Repo**: git://github.com/cheeriojs/cheerio.git
**Repo**: https://github.comcheeriojs/cheerio
**License**: MIT
**Description**: Tiny, fast, and elegant implementation of core jQuery designed specifically for the server
## License Text
@ -144,8 +144,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# class-transformer
**Author**: [object Object]
**Repo**: https://github.com/typestack/class-transformer.git
**Author**: Umed Khudoiberdiev
**Repo**: https://github.com/typestack/class-transformer
**License**: MIT
**Description**: Proper decorator-based transformation / serialization / deserialization of plain javascript objects to class constructors
## License Text
@ -173,7 +173,7 @@ THE SOFTWARE.
# class-validator
**Author**: TypeStack contributors
**Repo**: https://github.com/typestack/class-validator.git
**Repo**: https://github.com/typestack/class-validator
**License**: MIT
**Description**: Decorator-based property validation for classes.
## License Text
@ -201,7 +201,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# consola
**Author**: undefined
**Author**: ?
**Repo**: nuxt/consola
**License**: MIT
**Description**: Elegant Console Logger for Node.js and Browser
@ -239,8 +239,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# dotenv
**Author**: undefined
**Repo**: git://github.com/motdotla/dotenv.git
**Author**: ?
**Repo**: https://github.commotdotla/dotenv
**License**: BSD-2-Clause
**Description**: Loads environment variables from .env file
## License Text
@ -303,7 +303,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# handlebars
**Author**: Yehuda Katz
**Repo**: https://github.com/wycats/handlebars.js.git
**Repo**: https://github.com/wycats/handlebars.js
**License**: MIT
**Description**: Handlebars provides the power necessary to let you build semantic templates effectively with no frustration
## License Text
@ -330,7 +330,7 @@ THE SOFTWARE.
# i18next
**Author**: Jan Mühlemann <jan.muehlemann@gmail.com> (https://github.com/jamuhl)
**Repo**: https://github.com/i18next/i18next.git
**Repo**: https://github.com/i18next/i18next
**License**: MIT
**Description**: i18next internationalization framework
## License Text
@ -358,15 +358,15 @@ SOFTWARE.
# i18next-fs-backend
**Author**: undefined
**Repo**: git@github.com:i18next/i18next-fs-backend.git
**Author**: ?
**Repo**: git@github.com:i18next/i18next-fs-backend
**License**: undefined
**Description**: i18next-fs-backend is a backend layer for i18next using in Node.js and for Deno to load translations from the filesystem.
## License Text
# mime-types
**Author**: undefined
**Author**: ?
**Repo**: jshttp/mime-types
**License**: MIT
**Description**: The ultimate javascript content-type utility.
@ -398,7 +398,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# pdf-lib
**Author**: Andrew Dillon <andrew.dillon.j@gmail.com>
**Repo**: git+https://github.com/Hopding/pdf-lib.git
**Repo**: git+https://github.com/Hopding/pdf-lib
**License**: MIT
**Description**: Create and modify PDF files with JavaScript
## License Text
@ -427,7 +427,7 @@ SOFTWARE.
# puppeteer
**Author**: The Chromium Authors
**Repo**: github:puppeteer/puppeteer
**Repo**: https://github.com/puppeteer/puppeteer
**License**: Apache-2.0
**Description**: A high-level API to control headless Chrome over the DevTools Protocol
## License Text
@ -636,8 +636,8 @@ SOFTWARE.
# reflect-metadata
**Author**: [object Object]
**Repo**: https://github.com/rbuckton/reflect-metadata.git
**Author**: Ron Buckton
**Repo**: https://github.com/rbuckton/reflect-metadata
**License**: Apache-2.0
**Description**: Polyfill for Metadata Reflection API
## License Text
@ -698,8 +698,8 @@ If the Work includes a "NOTICE" text file as part of its distribution, then any
END OF TERMS AND CONDITIONS
# routing-controllers
**Author**: [object Object]
**Repo**: https://github.com/typestack/routing-controllers.git
**Author**: Umed Khudoiberdiev
**Repo**: https://github.com/typestack/routing-controllers
**License**: MIT
**Description**: Create structured, declarative and beautifully organized class-based controllers with heavy decorators usage for Express / Koa using TypeScript.
## License Text
@ -762,8 +762,8 @@ OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# @types/express
**Author**: undefined
**Repo**: https://github.com/DefinitelyTyped/DefinitelyTyped.git
**Author**: ?
**Repo**: https://github.com/DefinitelyTyped/DefinitelyTyped
**License**: MIT
**Description**: TypeScript definitions for Express
## License Text
@ -791,8 +791,8 @@ OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# @types/node
**Author**: undefined
**Repo**: https://github.com/DefinitelyTyped/DefinitelyTyped.git
**Author**: ?
**Repo**: https://github.com/DefinitelyTyped/DefinitelyTyped
**License**: MIT
**Description**: TypeScript definitions for Node.js
## License Text
@ -820,8 +820,8 @@ OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# @types/puppeteer
**Author**: undefined
**Repo**: https://github.com/DefinitelyTyped/DefinitelyTyped.git
**Author**: ?
**Repo**: https://github.com/DefinitelyTyped/DefinitelyTyped
**License**: MIT
**Description**: TypeScript definitions for puppeteer
## License Text
@ -849,8 +849,8 @@ OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# cp-cli
**Author**: undefined
**Repo**: git+https://github.com/screendriver/cp-cli.git
**Author**: ?
**Repo**: https://github.com/screendriver/cp-cli
**License**: MIT
**Description**: A 'cp' CLI util for Node.js
## License Text
@ -878,16 +878,16 @@ SOFTWARE.
# faker
**Author**: undefined
**Repo**: http://github.com/Marak/Faker.js.git
**Author**: ?
**Repo**: http://github.com/Marak/Faker.js
**License**: MIT
**Description**: Generate massive amounts of fake contextual data
## License Text
# nodemon
**Author**: [object Object]
**Repo**: https://github.com/remy/nodemon.git
**Author**: Remy Sharp
**Repo**: https://github.com/remy/nodemon
**License**: MIT
**Description**: Simple monitor script for use during development of a node.js app.
## License Text
@ -915,8 +915,8 @@ SOFTWARE.
# release-it
**Author**: [object Object]
**Repo**: https://github.com/release-it/release-it.git
**Author**: Lars Kappert
**Repo**: https://github.com/release-it/release-it
**License**: MIT
**Description**: Generic CLI tool to automate versioning and package publishing related tasks.
## License Text
@ -945,7 +945,7 @@ SOFTWARE.
# rimraf
**Author**: Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)
**Repo**: git://github.com/isaacs/rimraf.git
**Repo**: git://github.com/isaacs/rimraf
**License**: ISC
**Description**: A deep deletion module for node (like `rm -rf`)
## License Text
@ -968,15 +968,15 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# start-server-and-test
**Author**: Gleb Bahmutov <gleb.bahmutov@gmail.com>
**Repo**: https://github.com/bahmutov/start-server-and-test.git
**Repo**: https://github.com/bahmutov/start-server-and-test
**License**: MIT
**Description**: Starts server, waits for URL, then runs test command; when the tests end, shuts down server
## License Text
# ts-node
**Author**: [object Object]
**Repo**: git://github.com/TypeStrong/ts-node.git
**Author**: Blake Embrey
**Repo**: https://github.comTypeStrong/ts-node
**License**: MIT
**Description**: TypeScript execution environment and REPL for node.js, with source map support
## License Text
@ -1005,7 +1005,7 @@ THE SOFTWARE.
# typescript
**Author**: Microsoft Corp.
**Repo**: https://github.com/Microsoft/TypeScript.git
**Repo**: https://github.com/Microsoft/TypeScript
**License**: Apache-2.0
**Description**: TypeScript is a language for application scale JavaScript development
## License Text

View File

@ -1,6 +1,6 @@
{
"name": "@odit/lfk-document-server",
"version": "0.3.2",
"version": "0.5.4",
"description": "The document generation server for the LfK! runner system. This generates certificates, sponsoring aggreements and more",
"main": "src/app.ts",
"scripts": {
@ -8,9 +8,7 @@
"build": "rimraf ./dist && tsc && cp-cli ./src/templates ./dist/templates && cp-cli ./src/locales ./dist/locales",
"licenses:export": "license-exporter --markdown",
"release": "release-it --only-version",
"translations:sort": "node sort_translations.js",
"test:speed": "start-server-and-test dev http://localhost:4010/docs/openapi.json test:speed:run",
"test:speed:run": "ts-node src/tests/speedtest.ts"
"translations:sort": "node sort_translations.js"
},
"repository": {
"type": "git",
@ -41,40 +39,40 @@
],
"license": "CC-BY-NC-SA-4.0",
"dependencies": {
"@odit/class-validator-jsonschema": "^2.1.1",
"async-helpers": "^0.3.17",
"axios": "^0.21.1",
"bwip-js": "^2.0.12",
"cheerio": "^1.0.0-rc.5",
"@odit/class-validator-jsonschema": "2.1.1",
"async-helpers": "0.3.17",
"axios": "0.21.1",
"bwip-js": "2.1.1",
"cheerio": "1.0.0-rc.5",
"class-transformer": "0.3.1",
"class-validator": "^0.13.1",
"consola": "^2.15.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"handlebars": "^4.7.6",
"i18next": "^19.8.7",
"i18next-fs-backend": "^1.0.8",
"mime-types": "^2.1.28",
"pdf-lib": "^1.16.0",
"puppeteer": "^7.0.1",
"reflect-metadata": "^0.1.13",
"class-validator": "0.13.1",
"consola": "2.15.3",
"cors": "2.8.5",
"dotenv": "8.2.0",
"express": "4.17.1",
"handlebars": "4.7.7",
"i18next": "20.1.0",
"i18next-fs-backend": "1.1.1",
"mime-types": "2.1.30",
"pdf-lib": "1.16.0",
"puppeteer": "8.0.0",
"reflect-metadata": "0.1.13",
"routing-controllers": "0.9.0-alpha.6",
"routing-controllers-openapi": "2.2.0"
},
"devDependencies": {
"@odit/license-exporter": "^0.0.10",
"@types/express": "^4.17.11",
"@types/node": "^14.14.22",
"@types/puppeteer": "^5.4.3",
"cp-cli": "^2.0.0",
"faker": "^5.3.1",
"nodemon": "^2.0.7",
"@odit/license-exporter": "0.0.11",
"@types/express": "4.17.11",
"@types/node": "14.14.22",
"@types/puppeteer": "5.4.3",
"cp-cli": "2.0.0",
"faker": "5.3.1",
"nodemon": "2.0.7",
"release-it": "^14.2.2",
"rimraf": "^3.0.2",
"start-server-and-test": "^1.12.0",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
"rimraf": "3.0.2",
"start-server-and-test": "1.12.0",
"ts-node": "9.1.1",
"typescript": "4.1.3"
},
"release-it": {
"git": {

View File

@ -1,265 +1,308 @@
import axios from 'axios';
import cheerio from "cheerio";
import fs from "fs";
import Handlebars from 'handlebars';
import i18next from "i18next";
import Backend from 'i18next-fs-backend';
import mime from "mime-types";
import path from 'path';
import { PDFDocument } from 'pdf-lib';
import puppeteer from "puppeteer";
import { awaitAsyncHandlebarHelpers, helpers } from './asyncHelpers';
import { config } from './config';
import { Runner } from './models/Runner';
import { RunnerCard } from './models/RunnerCard';
import { RunnerGroup } from './models/RunnerGroup';
/**
* This class is responsible for all things pdf creation.
* This uses the html templates from src/templates.
*/
export class PdfCreator {
private templateDir = path.join(__dirname, '/templates');
private browser;
private static interpolations = { eventname: config.eventname, sponsoring_receipt_minimum_amount: config.sponsoring_receipt_minimum_amount, currency_symbol: config.currency_symbol }
/**
* Main constructor.
* Initializes i18n(ext), Handlebars and puppeteer.
*/
constructor() {
this.init();
}
/**
* Main constructor.
* Initializes i18n(ext), Handlebars and puppeteer.
*/
public async init() {
const minimal_args = [
'--autoplay-policy=user-gesture-required',
'--disable-background-networking',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-breakpad',
'--disable-client-side-phishing-detection',
'--disable-component-update',
'--disable-default-apps',
'--disable-dev-shm-usage',
'--disable-domain-reliability',
'--disable-extensions',
'--disable-features=AudioServiceOutOfProcess',
'--disable-hang-monitor',
'--disable-ipc-flooding-protection',
'--disable-notifications',
'--disable-offer-store-unmasked-wallet-cards',
'--disable-popup-blocking',
'--disable-print-preview',
'--disable-prompt-on-repost',
'--disable-renderer-backgrounding',
'--disable-speech-api',
'--disable-sync',
'--hide-scrollbars',
'--ignore-gpu-blacklist',
'--metrics-recording-only',
'--mute-audio',
'--no-default-browser-check',
'--no-first-run',
'--no-pings',
'--no-zygote',
'--password-store=basic',
'--use-gl=swiftshader',
'--no-sandbox'
];
await i18next
.use(Backend)
.init({
fallbackLng: 'en',
lng: 'en',
backend: {
loadPath: path.join(__dirname, '/locales/{{lng}}.json')
}
});
await Handlebars.registerHelper(helpers);
await Handlebars.registerHelper('__',
function (str) {
return i18next.t(str, PdfCreator.interpolations).toString();
}
);
await Handlebars.registerHelper('--sponsor',
function (str) {
const index = (parseInt(str) % config.sponor_logos.length);
if (isNaN(index)) {
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg=="
}
return config.sponor_logos[index];
}
);
this.browser = await puppeteer.launch({ headless: true, args: minimal_args });
}
/**
* 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 generateSponsoringContract(runners: Runner[], locale: string = "en", codeformat: string = config.codeformat): Promise<Buffer> {
if (runners.length == 1 && Object.keys(runners[0]).length == 0) {
runners[0] = this.generateEmptyRunner();
}
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.generateSponsoringContract(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}/sponsoring_contract.html`, 'utf8');
const template = Handlebars.compile(template_source);
let result = template({ runners, codeformat });
result = await awaitAsyncHandlebarHelpers(result);
const pdf = await this.renderPdf(result, { format: "A5", landscape: true });
return pdf
}
/**
* Generate runner card pdfs.
* @param cards The runner cars you want to generate the cards for.
* @param locale The locale used for the cards (default:en)
*/
public async generateRunnerCards(cards: RunnerCard[], locale: string = "en", codeformat: string = config.codeformat): Promise<Buffer> {
if (cards.length > 10) {
let pdf_promises = new Array<Promise<Buffer>>();
let i, j;
for (i = 0, j = cards.length; i < j; i += 10) {
let chunk = cards.slice(i, i + 10);
pdf_promises.push(this.generateRunnerCards(chunk, locale));
}
const pdfs = await Promise.all(pdf_promises);
return await this.mergePdfs(pdfs);
}
const cards_swapped = this.swapArrayPairs(cards);
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" })
result = await awaitAsyncHandlebarHelpers(result);
fs.writeFileSync("lelelelele.tmp", result);
const pdf = await this.renderPdf(result, { format: "A4", landscape: false });
return pdf
}
/**
* Converts all images in html to base64.
* Works with image files in the template directory or images from urls.
* @param html The html string whoms images shall get replaced.
*/
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")) {
return;
}
const img_type = mime.lookup(imgsrc);
if (!(img_type.includes("image"))) {
throw new Error("File is not image mime type");
}
let image;
if (imgsrc.startsWith("http")) {
image = (await axios.get(imgsrc)).data;
image = Buffer.from(image).toString('base64');
}
else {
if (imgsrc.startsWith("./")) {
imgsrc = imgsrc.replace("./", "");
}
image = fs.readFileSync(`${this.templateDir}/${imgsrc}`, { encoding: "base64" });
}
image = `data:${img_type};base64,${image}`
$(element).attr("src", image)
})
return $.html();
}
/**
* This method manages the creation of pdfs via puppeteer.
* @param html The HTML that should get rendered.
* @param options Puppeteer PDF option (eg: {format: "A4"})
*/
public async renderPdf(html: string, options): Promise<any> {
html = await this.imgToBase64(html);
let page = await this.browser.newPage();
await page.setContent(html);
const pdf = await page.pdf(options);
await page.close();
return pdf;
}
/**
* Merges multiple pdfs into one.
* @param pdfs The pdfs you want to merge as an buffer array.
* @returns The merged pdf as a buffer.
*/
private async mergePdfs(pdfs: Buffer[]): Promise<Buffer> {
const mergedPdf = await PDFDocument.create();
for (const pdfBuffer of pdfs) {
const pdf = await PDFDocument.load(pdfBuffer);
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
copiedPages.forEach((page) => {
mergedPdf.addPage(page);
});
}
return <Buffer>(await mergedPdf.save());
}
/**
* Generates a new dummy runner with halfspaces for all strings.
* Can be used to generate empty sponsoring contracts.
* @returns A new runner object that apears to be empty.
*/
private generateEmptyRunner(): Runner {
let group = new RunnerGroup();
group.id = 0;
group.name = "";
let runner = new Runner();
runner.id = 0;
runner.firstname = "";
runner.lastname = "";
runner.group = group;
return runner;
}
/**
* Swaps pairs (0/1, 2/3, ...) of elements in an array recursively.
* If the last element has no partner it inserts an empty element at the end and swaps the two
* This is needed to generate pdfs with front- and backside that get printet on one paper.
* @param array The array which's pairs shall get switched.
* @returns Array with swapped pairs,
*/
private swapArrayPairs(array): Array<any> {
if (array.length == 1) {
return [null, array[0]];
}
if (array.length == 0) {
return null;
}
const rest = this.swapArrayPairs(array.slice(2))
if (!rest) {
return [array[1], array[0]]
}
return [array[1], array[0]].concat(rest);
}
import axios from 'axios';
import cheerio from "cheerio";
import fs from "fs";
import Handlebars from 'handlebars';
import i18next from "i18next";
import Backend from 'i18next-fs-backend';
import mime from "mime-types";
import path from 'path';
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';
/**
* This class is responsible for all things pdf creation.
* This uses the html templates from src/templates.
*/
export class PdfCreator {
private templateDir = path.join(__dirname, '/templates');
private browser;
private static interpolations = { eventname: config.eventname, sponsoring_receipt_minimum_amount: config.sponsoring_receipt_minimum_amount, currency_symbol: config.currency_symbol }
private static contractsPerRunner = config.contracts_per_runner;
/**
* Main constructor.
* Initializes i18n(ext), Handlebars and puppeteer.
*/
constructor() {
this.init();
}
/**
* Main constructor.
* Initializes i18n(ext), Handlebars and puppeteer.
*/
public async init() {
const minimal_args = [
'--autoplay-policy=user-gesture-required',
'--disable-background-networking',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-breakpad',
'--disable-client-side-phishing-detection',
'--disable-component-update',
'--disable-default-apps',
'--disable-dev-shm-usage',
'--disable-domain-reliability',
'--disable-extensions',
'--disable-features=AudioServiceOutOfProcess',
'--disable-hang-monitor',
'--disable-ipc-flooding-protection',
'--disable-notifications',
'--disable-offer-store-unmasked-wallet-cards',
'--disable-popup-blocking',
'--disable-print-preview',
'--disable-prompt-on-repost',
'--disable-renderer-backgrounding',
'--disable-speech-api',
'--disable-sync',
'--hide-scrollbars',
'--ignore-gpu-blacklist',
'--metrics-recording-only',
'--mute-audio',
'--no-default-browser-check',
'--no-first-run',
'--no-pings',
'--no-zygote',
'--password-store=basic',
'--use-gl=swiftshader',
'--no-sandbox'
];
await i18next
.use(Backend)
.init({
fallbackLng: 'en',
lng: 'en',
backend: {
loadPath: path.join(__dirname, '/locales/{{lng}}.json')
}
});
await Handlebars.registerHelper(helpers);
await Handlebars.registerHelper('__',
function (str) {
return i18next.t(str, PdfCreator.interpolations).toString();
}
);
await Handlebars.registerHelper('--sponsor',
function (str) {
const index = (parseInt(str) % config.sponor_logos.length);
if (isNaN(index)) {
return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg=="
}
return config.sponor_logos[index];
}
);
await Handlebars.registerHelper('--format_kilometers',
function (str) {
let meters = parseInt(str);
return ((meters / 1000).toLocaleString("en-EN", { minimumFractionDigits: 1, maximumFractionDigits: 3 }).replace(".", ","));
}
);
await Handlebars.registerHelper('--format_currency',
function (str) {
let meters = parseInt(str);
return ((meters / 100).toLocaleString("en-EN", { minimumFractionDigits: 2, maximumFractionDigits: 2 }).replace(".", ","));
}
);
this.browser = await puppeteer.launch({ headless: true, args: minimal_args });
}
/**
* 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 generateSponsoringContract(runners: Runner[], locale: string = "en", codeformat: string = config.codeformat): Promise<Buffer> {
if (runners.length == 1 && Object.keys(runners[0]).length == 0) {
runners[0] = this.generateEmptyRunner();
}
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.generateSponsoringContract(chunk, locale));
}
const pdfs = await Promise.all(pdf_promises);
return await this.mergePdfs(pdfs);
}
for (var i = 1; i < PdfCreator.contractsPerRunner; i++) {
runners = runners.reduce(function (res, current, index, array) {
return res.concat([current, current]);
}, []);
}
await i18next.changeLanguage(locale);
const template_source = fs.readFileSync(`${this.templateDir}/sponsoring_contract.html`, 'utf8');
const template = Handlebars.compile(template_source);
let result = template({ runners, codeformat, disclaimer: config.disclaimer_text });
result = await awaitAsyncHandlebarHelpers(result);
const pdf = await this.renderPdf(result, { format: "A5", landscape: true });
return pdf
}
/**
* Generate runner card pdfs.
* @param cards The runner cars you want to generate the cards for.
* @param locale The locale used for the cards (default:en)
*/
public async generateRunnerCards(cards: RunnerCard[], locale: string = "en", codeformat: string = config.codeformat_cards): Promise<Buffer> {
if (cards.length > 10) {
let pdf_promises = new Array<Promise<Buffer>>();
let i, j;
for (i = 0, j = cards.length; i < j; i += 10) {
let chunk = cards.slice(i, i + 10);
pdf_promises.push(this.generateRunnerCards(chunk, locale, codeformat));
}
const pdfs = await Promise.all(pdf_promises);
return await this.mergePdfs(pdfs);
}
const cards_swapped = this.swapArrayPairs(cards);
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: config.eventname, codeformat: codeformat, card_subtitle: config.card_subtitle })
result = await awaitAsyncHandlebarHelpers(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<Buffer>();
let i, j;
for (i = 0, j = runners.length; i < j; i += 50) {
let chunk = runners.slice(i, i + 50);
pdf_promises.push(await this.generateRunnerCertficates(chunk, locale));
}
return await this.mergePdfs(pdf_promises);
}
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, currency_symbol: config.currency_symbol, donations_footer_text: config.donations_footer_text });
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.
* @param html The html string whoms images shall get replaced.
*/
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")) {
return;
}
const img_type = mime.lookup(imgsrc);
if (!(img_type.includes("image"))) {
throw new Error("File is not image mime type");
}
let image;
if (imgsrc.startsWith("http")) {
image = (await axios.get(imgsrc)).data;
image = Buffer.from(image).toString('base64');
}
else {
if (imgsrc.startsWith("./")) {
imgsrc = imgsrc.replace("./", "");
}
image = fs.readFileSync(`${this.templateDir}/${imgsrc}`, { encoding: "base64" });
}
image = `data:${img_type};base64,${image}`
$(element).attr("src", image)
});
return $.html();
}
/**
* This method manages the creation of pdfs via puppeteer.
* @param html The HTML that should get rendered.
* @param options Puppeteer PDF option (eg: {format: "A4"})
*/
public async renderPdf(html: string, options): Promise<any> {
html = await this.imgToBase64(html);
let page = await this.browser.newPage();
await page.setContent(html);
const pdf = await page.pdf(options);
await page.close();
return pdf;
}
/**
* Merges multiple pdfs into one.
* @param pdfs The pdfs you want to merge as an buffer array.
* @returns The merged pdf as a buffer.
*/
private async mergePdfs(pdfs: Buffer[]): Promise<Buffer> {
const mergedPdf = await PDFDocument.create();
for (const pdfBuffer of pdfs) {
const pdf = await PDFDocument.load(pdfBuffer);
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
copiedPages.forEach((page) => {
mergedPdf.addPage(page);
});
}
return <Buffer>(await mergedPdf.save());
}
/**
* Generates a new dummy runner with halfspaces for all strings.
* Can be used to generate empty sponsoring contracts.
* @returns A new runner object that apears to be empty.
*/
private generateEmptyRunner(): Runner {
let group = new RunnerGroup();
group.id = 0;
group.name = "";
let runner = new Runner();
runner.id = 0;
runner.firstname = "";
runner.lastname = "";
runner.group = group;
return runner;
}
/**
* Swaps pairs (0/1, 2/3, ...) of elements in an array recursively.
* If the last element has no partner it inserts an empty element at the end and swaps the two
* This is needed to generate pdfs with front- and backside that get printet on one paper.
* @param array The array which's pairs shall get switched.
* @returns Array with swapped pairs,
*/
private swapArrayPairs(array): Array<any> {
if (array.length == 1) {
return [null, array[0]];
}
if (array.length == 0) {
return null;
}
const rest = this.swapArrayPairs(array.slice(2))
if (!rest) {
return [array[1], array[0]]
}
return [array[1], array[0]].concat(rest);
}
}

View File

@ -9,14 +9,22 @@ export const config = {
eventname: process.env.EVENT_NAME || "Please set the event name",
currency_symbol: process.env.CURRENCY_SYMBOL || "€",
sponsoring_receipt_minimum_amount: process.env.SPONSORING_RECEIPT_MINIMUM_AMOUNT || "10",
codeformat: process.env.CODEFORMAT || "qrcode",
codeformat: process.env.CODEFORMAT || "code39",
codeformat_cards: process.env.CODEFORMAT_CARDS || process.env.CODEFORMAT || "code39",
sponor_logos: getSponsorLogos(),
api_key: getApiKey(),
disclaimer_text: process.env.DISCLAIMER_TEXT || "",
donations_footer_text: process.env.DONATIONS_FOOTER_TEXT || "",
contracts_per_runner: parseInt(process.env.CONTRACTS_PER_RUNNER) || 1,
card_subtitle: process.env.CARD_SUBTITLE || ""
}
let errors = 0
if (typeof config.internal_port !== "number") {
errors++
}
if (typeof config.contracts_per_runner !== "number") {
errors++
}
if (typeof config.development !== "boolean") {
errors++
}

View File

@ -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';
@ -18,7 +19,7 @@ export class PdfController {
@Post('/contracts')
@OpenAPI({ description: "Generate Sponsoring contract pdfs from 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 generateContracts(@Body({ validate: true, options: { limit: "500mb" } }) runners: Runner[], @Res() res: any, @QueryParam("locale") locale: string, @QueryParam("codeformat") codeformat: string) {
async generateContracts(@Body({ validate: true, options: { limit: "500mb" } }) runners: Runner[], @Res() res: any, @QueryParam("locale") locale: string, @QueryParam("codeformat") codeformat: string, @QueryParam("download") download: boolean) {
if (!this.initialized) {
await this.pdf.init();
this.initialized = true;
@ -29,12 +30,15 @@ export class PdfController {
runners = this.mapRunnerGroupNames(runners)
const contracts = await this.pdf.generateSponsoringContract(runners, locale, codeformat);
res.setHeader('content-type', 'application/pdf');
if (download) {
res.setHeader('Content-Disposition', 'attachment; filename="contracts.pdf"')
}
return contracts;
}
@Post('/cards')
@OpenAPI({ description: "Generate runner card pdfs from runner card objects.<br>You can choose your prefered locale by passing the 'locale' query-param." })
async generateCards(@Body({ validate: true, options: { limit: "500mb" } }) cards: RunnerCard | RunnerCard[], @Res() res: any, @QueryParam("locale") locale: string) {
async generateCards(@Body({ validate: true, options: { limit: "500mb" } }) cards: RunnerCard | RunnerCard[], @Res() res: any, @QueryParam("locale") locale: string, @QueryParam("codeformat") codeformat: string, @QueryParam("download") download: boolean) {
if (!this.initialized) {
await this.pdf.init();
this.initialized = true;
@ -43,11 +47,33 @@ export class PdfController {
cards = [cards];
}
cards = this.mapCardGroupNames(cards);
const contracts = await this.pdf.generateRunnerCards(cards, locale);
const contracts = await this.pdf.generateRunnerCards(cards, locale, codeformat);
res.setHeader('content-type', 'application/pdf');
if (download) {
res.setHeader('Content-Disposition', 'attachment; filename="cards.pdf"')
}
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) {
@ -62,10 +88,52 @@ 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}`;
}
runner.donationPerDistanceTotal = 0;
if (!Array.isArray(runner.distanceDonations)){
runner.distanceDonations = [].concat(runner.distanceDonations)
}
if (runner.distanceDonations.length > 0) {
runner.donationPerDistanceTotal += runner.distanceDonations.reduce(function (sum, current) {
return sum + current.amountPerDistance;
}, 0);
}
runner.donationTotal = 0;
if (runner.distanceDonations.length > 0) {
runner.donationTotal += runner.distanceDonations.reduce(function (sum, current) {
return sum + current.amount;
}, 0);
}
response.push(runner)
}
return response;
}
private mapCardGroupNames(cards: RunnerCard[]): RunnerCard[] {
let response = new Array<RunnerCard>();
for (let card of cards) {
if (!card.runner.group.parentGroup) {
if (!card.runner) {
card.runner = {
id: 0,
firstname: "Blank",
lastname: "Blank",
distance: 0,
group: {
id: 0,
name: "Blank",
fullName: "Blank"
}
}
}
else if (!card.runner.group.parentGroup) {
card.runner.group.fullName = card.runner.group.name;
}
else {

View File

@ -1,20 +1,29 @@
{
"address": "Adresse",
"betrag-km": "Betrag/ km",
"city": "Stadt",
"date": "Datum",
"firstname": "Vorname",
"group": "Team/Klasse",
"fuer-den-guten-zweck-zurueckgelegt": "für den guten Zweck zurückgelegt",
"gesamt": "Gesamt",
"gesamtbetrag": "Gesamtbetrag",
"group": "Team/ Klasse",
"hat-beim-eventname": "Hat beim {{eventname}}",
"house_number": "Hausnummer",
"id": "ID",
"lastname": "Nachname",
"location": "Ort",
"mit_unterstuetzung_von": "Mit Unterstützung von:",
"please_use_blockletters": "Bitte in DRUCKBUCHSTABEN schreiben",
"postalcode": "Postleitzahl",
"signature": "Unterschrift",
"sponsor": "Sponsor",
"sponsor-in": "Sponsor:in",
"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_subtitle": "Ich bin/ Wir sind bereit anlässlich des {{eventname}}",
"sponsoring_title": "Sponsoringerklärung",
"street": "Straße"
"sponsorings": "Sponsorings",
"street": "Straße",
"urkunde": "Urkunde"
}

View File

@ -1,19 +1,29 @@
{
"address": "Address",
"betrag-km": "Amount/ km",
"city": "City",
"date": "date",
"firstname": "First name",
"group": "Team/class",
"fuer-den-guten-zweck-zurueckgelegt": "for our good cause at the {{eventname}}",
"gesamt": "Combined",
"gesamtbetrag": "Total",
"group": "Team/ class",
"hat-beim-eventname": "Ran",
"house_number": "House number",
"id": "ID",
"lastname": "Last name",
"location": "Location",
"mit_unterstuetzung_von": "Supported by:",
"please_use_blockletters": "Please write in BLOCK LETTERS.",
"postalcode": "Postal code",
"signature": "Signature",
"sponsor": "sponsor",
"sponsor-in": "Donor",
"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_subtitle": "On the occasion of the {{eventname}} I/We want to support",
"sponsoring_title": "Sponsoring contract",
"street": "Street"
"sponsorings": "Donations",
"street": "Street",
"urkunde": "Certificate"
}

View File

@ -1,5 +1,5 @@
import {
IsArray
IsArray, IsNumber, IsOptional
} from "class-validator";
import { DistanceDonation } from './DistanceDonation';
import { Runner } from './Runner';
@ -13,4 +13,13 @@ export class CertificateRunner extends Runner {
*/
@IsArray()
distanceDonations: DistanceDonation[];
@IsNumber()
@IsOptional()
donationPerDistanceTotal?: number = 0;
@IsNumber()
@IsOptional()
donationTotal?: number = 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -33,18 +33,18 @@
{{#each cards}}
<div class="column is-half runnercard">
<p class="title is-5" style="text-align: center; padding-bottom: 0; margin-top: -0.75rem;">{{../eventname}}</p>
<p style="text-align: center; margin-top: -1.5rem; font-size: small;">lauf-fuer-kaya.de - am 01.01.2021</p>
<p style="font-size: small;">Mit unterstützung von:</p>
<p style="text-align: center; margin-top: -1.5rem; font-size: small;">{{../card_subtitle}}</p>
<p style="font-size: small;">{{__ "mit_unterstuetzung_von"}}</p>
<div class="columns" style="height: 6rem; overflow: hidden;">
<div class="column is-two-thirds">
<div class="column is-half">
<!--SPONSOR LOGO HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--sponsor this.id}}" />
</div>
<div class="column is-one-third">
<div class="column is-half">
<!--BARCODE HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--bc this.id ../codeformat}}" />
src="{{--bc this.code ../codeformat}}" />
</div>
</div>
<p>{{this.runner.lastname}}, {{this.runner.firstname}} {{this.runner.middlename}}</p>
@ -61,7 +61,7 @@
<div style="height: 2cm; padding: 0 0 2.25cm 0">
<img style="object-fit: cover; max-height: 2cm;" src="{{--sponsor this.id}}" />
</div>
<img style="object-fit: cover; max-height: 2.5cm; position: relative;" src="{{--bc this.id ../codeformat}}" />
<img style="object-fit: cover; max-height: 2.5cm; position: relative;" src="{{--bc this.code ../codeformat}}" />
</div>
{{/each}}
</div>

File diff suppressed because one or more lines are too long

View File

@ -68,8 +68,8 @@
<p style="font-size: x-small; display: block;">{{__ "group"}}</p>
</div>
</div>
<p>{{__ "sponsoring_amount_per_distance"}}</p>
<div class="columns">
<p style="margin-top: -0.5rem">{{__ "sponsoring_amount_per_distance"}}</p>
<div class="columns" style="margin-top: -1rem;">
<div class="column is-6">
<span style="border-bottom: 1px solid; width: 100%; display: block;"></span>
<p style="font-size: x-small; display: block;">{{__ "lastname"}}</p>
@ -79,9 +79,9 @@
<p style="font-size: x-small; display: block;">{{__ "firstname"}}</p>
</div>
</div>
<p style="font-size: medium;">{{__ "address"}} ({{__ "sponsor"}})</p>
<p style="font-size: medium; margin-top: -0.5rem;">{{__ "address"}} ({{__ "sponsor"}})</p>
<p style="font-size: x-small;">({{__ "sponsoring_address_condition"}})</p>
<div class="columns">
<div class="columns" style="margin-top: -1rem;">
<div class="column is-8">
<span style="border-bottom: 1px solid; width: 100%; display: block;"></span>
<p style="font-size: x-small; display: block;">{{__ "street"}}</p>
@ -91,7 +91,7 @@
<p style="font-size: x-small; display: block;">{{__ "house_number"}}</p>
</div>
</div>
<div class="columns">
<div class="columns" style="margin-top: -1rem;">
<div class="column is-4">
<span style="border-bottom: 1px solid; width: 100%; display: block;"></span>
<p style="font-size: x-small; display: block;">{{__ "postalcode"}}</p>
@ -101,8 +101,7 @@
<p style="font-size: x-small; display: block;">{{__ "city"}}</p>
</div>
</div>
<br>
<div class="columns">
<div class="columns" style="margin-top: -1rem;">
<div class="column is-7">
<span style="border-bottom: 1px solid; width: 100%; display: block;"></span>
<p style="font-size: x-small; display: block;">{{__ "location"}}, {{__ "date"}}</p>
@ -112,6 +111,7 @@
<p style="font-size: x-small; display: block;">{{__ "signature"}}</p>
</div>
</div>
<p style="font-size: xx-small; overflow: hidden; height: 4rem; text-align: center;">{{../disclaimer}}</p>
</div>
</div>
{{/each}}

View File

@ -1,10 +1,15 @@
import axios from "axios"
import faker from "faker"
import { config } from '../config'
import { CertificateRunner } from '../models/CertificateRunner'
import { DistanceDonation } from '../models/DistanceDonation'
import { Donor } from '../models/Donor'
import { Runner } from '../models/Runner'
import { RunnerCard } from '../models/RunnerCard'
import { RunnerGroup } from '../models/RunnerGroup'
const baseurl = "http://localhost:4010"
const key = config.api_key;
axios.interceptors.request.use((config) => {
config.headers['request-startTime'] = process.hrtime()
@ -46,6 +51,36 @@ function generateCards(amount: number): RunnerCard[] {
return cards;
}
function generateCertificateRunners(amount: number): CertificateRunner[] {
let runners: CertificateRunner[] = new Array<CertificateRunner>();
let group = new RunnerGroup();
let runner = new CertificateRunner();
let donor = new Donor();
let donation = new DistanceDonation();
for (var i = 0; i < amount; i++) {
group.name = faker.company.bsBuzz();
group.id = Math.floor(Math.random() * (9999999 - 1) + 1);
donor.firstname = faker.name.firstName();
donor.lastname = faker.name.lastName();
donor.id = Math.floor(Math.random() * (9999999 - 1) + 1);
runner.firstname = faker.name.firstName();
runner.lastname = faker.name.lastName();
runner.id = Math.floor(Math.random() * (9999999 - 1) + 1);
runner.distance = Math.floor(Math.random() * (9999999 - 1) + 1);
donation.id = Math.floor(Math.random() * (9999999 - 1) + 1);
donation.donor = donor;
donation.runner = runner;
donation.amountPerDistance = Math.floor(Math.random() * (10000 - 1) + 1);
runner.distanceDonations = [donation, donation]
runners.push(runner);
}
return runners;
}
function idToEan13(id): string {
const multiply = [1, 3];
id = id.toString();
@ -64,15 +99,20 @@ function idToEan13(id): string {
}
async function postContracts(runners: Runner[]): Promise<Measurement> {
const res = await axios.post(`${baseurl}/contracts`, runners);
const res = await axios.post(`${baseurl}/contracts?key=${key}`, runners);
return new Measurement("contract", runners.length, parseInt(res.headers['request-duration']))
}
async function postCards(cards: RunnerCard[]): Promise<Measurement> {
const res = await axios.post(`${baseurl}/cards`, cards);
const res = await axios.post(`${baseurl}/cards?key=${key}`, cards);
return new Measurement("card", cards.length, parseInt(res.headers['request-duration']))
}
async function postCertificates(runners: CertificateRunner[]): Promise<Measurement> {
const res = await axios.post(`${baseurl}/certificates?key=${key}`, runners);
return new Measurement("certificate", runners.length, parseInt(res.headers['request-duration']))
}
async function testContracts(sizes): Promise<Measurement[]> {
let measurements = new Array<Measurement>();
console.log("#### Testing contracts ####");
@ -97,16 +137,30 @@ async function testCards(sizes): Promise<Measurement[]> {
return measurements;
}
async function testCertificates(sizes): Promise<Measurement[]> {
let measurements = new Array<Measurement>();
console.log("#### Testing Certificates ####");
for (let size of sizes) {
const m = await postCertificates(generateCertificateRunners(size));
console.log(m.toString());
measurements.push(m);
}
return measurements;
}
async function main() {
const sizes = [0, 1, 10, 50, 100, 200, 500, 1000]
const sizes = [1, 10, 50, 100]
console.log("########### Speedtest ###########");
console.log(`Document server version (according to the api): ${(await axios.get("http://localhost:4010/version")).data.version}`);
console.log("####### Running tests #######");
const contractResults = await testContracts(sizes);
const cardResults = await testCards(sizes);
const certificateResults = await testCertificates(sizes);
console.log("####### Results #######");
console.table(contractResults);
console.table(cardResults);
console.table(certificateResults);
}
main();