136 Commits

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

View File

@@ -2,22 +2,180 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. 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)
- Updated translation due to customer request [`517e8a0`](https://git.odit.services/lfk/document-server/commit/517e8a081970b9ce4f6f225a7f9b5b54cca1258e)
- 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] [`b78534e`](https://git.odit.services/lfk/document-server/commit/b78534e1b0165522ff0ee1dfd110d8ba78f183d8)
- 🧾New changelog file version [CI SKIP] [skip ci] [`5e92b9a`](https://git.odit.services/lfk/document-server/commit/5e92b9a48fcbb8ab6a179c53f180a7a6bd743ae7)
- 🧾New changelog file version [CI SKIP] [skip ci] [`dca2829`](https://git.odit.services/lfk/document-server/commit/dca2829323f3a19247455df99498633605d09603)
- 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] [`573b921`](https://git.odit.services/lfk/document-server/commit/573b9211972a55df0a38742cb6eb789d6fd3717b)
- Changed default kilometer formatting to min 2 decimals, max 3 [`3af4b52`](https://git.odit.services/lfk/document-server/commit/3af4b521d302e3aab558d20f1fccca57ea61fff3)
- Merge pull request 'Fixed decimal separator' (#47) from dev into main [`57a84c2`](https://git.odit.services/lfk/document-server/commit/57a84c256a978f583508bdf772499466a73b4a22)
- 🧾New changelog file version [CI SKIP] [skip ci] [`451b7fb`](https://git.odit.services/lfk/document-server/commit/451b7fbe0543991e8a203e38daa350a954ae0e11)
- 🚀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) #### [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) > 18 February 2021
- 🚀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) - 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) - 🚀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) - 📖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) - 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) - 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 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) - 🧾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) - 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) - 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] [`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] [`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) - 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 '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) - 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 # 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 WORKDIR /app
COPY package.json ./ COPY package.json ./
RUN npm i -g pnpm RUN npm i -g pnpm
@@ -8,7 +8,7 @@ COPY tsconfig.json ./
COPY src ./src COPY src ./src
RUN pnpm run build RUN pnpm run build
# final image # final image
FROM registry.odit.services/mirror/alpine:3.13.1 FROM registry.odit.services/hub/library/alpine:3.13.1
WORKDIR /app WORKDIR /app
RUN apk add --no-cache \ RUN apk add --no-cache \
chromium \ chromium \
@@ -19,7 +19,9 @@ RUN apk add --no-cache \
ca-certificates \ ca-certificates \
ttf-freefont \ ttf-freefont \
nodejs \ 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. # Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \ 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. | 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. | 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. | 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 ## Templates
> The document server uses html templates to generate various pdf documents. > The document server uses html templates to generate various pdf documents.

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
import { Authorized, Body, JsonController, Post, QueryParam, Res } from 'routing-controllers'; import { Authorized, Body, JsonController, Post, QueryParam, Res } from 'routing-controllers';
import { OpenAPI } from 'routing-controllers-openapi'; import { OpenAPI } from 'routing-controllers-openapi';
import { CertificateRunner } from '../models/CertificateRunner';
import { Runner } from '../models/Runner'; import { Runner } from '../models/Runner';
import { RunnerCard } from '../models/RunnerCard'; import { RunnerCard } from '../models/RunnerCard';
import { PdfCreator } from '../PdfCreator'; import { PdfCreator } from '../PdfCreator';
@@ -18,7 +19,7 @@ export class PdfController {
@Post('/contracts') @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)." }) @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) { if (!this.initialized) {
await this.pdf.init(); await this.pdf.init();
this.initialized = true; this.initialized = true;
@@ -29,12 +30,15 @@ export class PdfController {
runners = this.mapRunnerGroupNames(runners) runners = this.mapRunnerGroupNames(runners)
const contracts = await this.pdf.generateSponsoringContract(runners, locale, codeformat); const contracts = await this.pdf.generateSponsoringContract(runners, locale, codeformat);
res.setHeader('content-type', 'application/pdf'); res.setHeader('content-type', 'application/pdf');
if (download) {
res.setHeader('Content-Disposition', 'attachment; filename="contracts.pdf"')
}
return contracts; return contracts;
} }
@Post('/cards') @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." }) @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) { if (!this.initialized) {
await this.pdf.init(); await this.pdf.init();
this.initialized = true; this.initialized = true;
@@ -43,11 +47,33 @@ export class PdfController {
cards = [cards]; cards = [cards];
} }
cards = this.mapCardGroupNames(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'); res.setHeader('content-type', 'application/pdf');
if (download) {
res.setHeader('Content-Disposition', 'attachment; filename="cards.pdf"')
}
return contracts; 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[] { private mapRunnerGroupNames(runners: Runner[]): Runner[] {
let response = new Array<Runner>(); let response = new Array<Runner>();
for (let runner of runners) { for (let runner of runners) {
@@ -62,10 +88,52 @@ export class PdfController {
return response; 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[] { private mapCardGroupNames(cards: RunnerCard[]): RunnerCard[] {
let response = new Array<RunnerCard>(); let response = new Array<RunnerCard>();
for (let card of cards) { 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; card.runner.group.fullName = card.runner.group.name;
} }
else { else {

View File

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

View File

@@ -1,19 +1,29 @@
{ {
"address": "Address", "address": "Address",
"betrag-km": "Amount/ km",
"city": "City", "city": "City",
"date": "date", "date": "date",
"firstname": "First name", "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", "house_number": "House number",
"id": "ID",
"lastname": "Last name", "lastname": "Last name",
"location": "Location", "location": "Location",
"mit_unterstuetzung_von": "Supported by:",
"please_use_blockletters": "Please write in BLOCK LETTERS.", "please_use_blockletters": "Please write in BLOCK LETTERS.",
"postalcode": "Postal code", "postalcode": "Postal code",
"signature": "Signature", "signature": "Signature",
"sponsor": "sponsor", "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_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_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", "sponsoring_title": "Sponsoring contract",
"street": "Street" "sponsorings": "Donations",
"street": "Street",
"urkunde": "Certificate"
} }

View File

@@ -1,5 +1,5 @@
import { import {
IsArray IsArray, IsNumber, IsOptional
} from "class-validator"; } from "class-validator";
import { DistanceDonation } from './DistanceDonation'; import { DistanceDonation } from './DistanceDonation';
import { Runner } from './Runner'; import { Runner } from './Runner';
@@ -13,4 +13,13 @@ export class CertificateRunner extends Runner {
*/ */
@IsArray() @IsArray()
distanceDonations: DistanceDonation[]; 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}} {{#each cards}}
<div class="column is-half runnercard"> <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 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="text-align: center; margin-top: -1.5rem; font-size: small;">{{../card_subtitle}}</p>
<p style="font-size: small;">Mit unterstützung von:</p> <p style="font-size: small;">{{__ "mit_unterstuetzung_von"}}</p>
<div class="columns" style="height: 6rem; overflow: hidden;"> <div class="columns" style="height: 6rem; overflow: hidden;">
<div class="column is-two-thirds"> <div class="column is-half">
<!--SPONSOR LOGO HERE--> <!--SPONSOR LOGO HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;" <img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;"
src="{{--sponsor this.id}}" /> src="{{--sponsor this.id}}" />
</div> </div>
<div class="column is-one-third"> <div class="column is-half">
<!--BARCODE HERE--> <!--BARCODE HERE-->
<img style="vertical-align: revert; margin-top: auto; object-fit: cover; max-height: 2cm;" <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>
</div> </div>
<p>{{this.runner.lastname}}, {{this.runner.firstname}} {{this.runner.middlename}}</p> <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"> <div style="height: 2cm; padding: 0 0 2.25cm 0">
<img style="object-fit: cover; max-height: 2cm;" src="{{--sponsor this.id}}" /> <img style="object-fit: cover; max-height: 2cm;" src="{{--sponsor this.id}}" />
</div> </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> </div>
{{/each}} {{/each}}
</div> </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> <p style="font-size: x-small; display: block;">{{__ "group"}}</p>
</div> </div>
</div> </div>
<p>{{__ "sponsoring_amount_per_distance"}}</p> <p style="margin-top: -0.5rem">{{__ "sponsoring_amount_per_distance"}}</p>
<div class="columns"> <div class="columns" style="margin-top: -1rem;">
<div class="column is-6"> <div class="column is-6">
<span style="border-bottom: 1px solid; width: 100%; display: block;"></span> <span style="border-bottom: 1px solid; width: 100%; display: block;"></span>
<p style="font-size: x-small; display: block;">{{__ "lastname"}}</p> <p style="font-size: x-small; display: block;">{{__ "lastname"}}</p>
@@ -79,9 +79,9 @@
<p style="font-size: x-small; display: block;">{{__ "firstname"}}</p> <p style="font-size: x-small; display: block;">{{__ "firstname"}}</p>
</div> </div>
</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> <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"> <div class="column is-8">
<span style="border-bottom: 1px solid; width: 100%; display: block;"></span> <span style="border-bottom: 1px solid; width: 100%; display: block;"></span>
<p style="font-size: x-small; display: block;">{{__ "street"}}</p> <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> <p style="font-size: x-small; display: block;">{{__ "house_number"}}</p>
</div> </div>
</div> </div>
<div class="columns"> <div class="columns" style="margin-top: -1rem;">
<div class="column is-4"> <div class="column is-4">
<span style="border-bottom: 1px solid; width: 100%; display: block;"></span> <span style="border-bottom: 1px solid; width: 100%; display: block;"></span>
<p style="font-size: x-small; display: block;">{{__ "postalcode"}}</p> <p style="font-size: x-small; display: block;">{{__ "postalcode"}}</p>
@@ -101,8 +101,7 @@
<p style="font-size: x-small; display: block;">{{__ "city"}}</p> <p style="font-size: x-small; display: block;">{{__ "city"}}</p>
</div> </div>
</div> </div>
<br> <div class="columns" style="margin-top: -1rem;">
<div class="columns">
<div class="column is-7"> <div class="column is-7">
<span style="border-bottom: 1px solid; width: 100%; display: block;"></span> <span style="border-bottom: 1px solid; width: 100%; display: block;"></span>
<p style="font-size: x-small; display: block;">{{__ "location"}}, {{__ "date"}}</p> <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> <p style="font-size: x-small; display: block;">{{__ "signature"}}</p>
</div> </div>
</div> </div>
<p style="font-size: xx-small; overflow: hidden; height: 4rem; text-align: center;">{{../disclaimer}}</p>
</div> </div>
</div> </div>
{{/each}} {{/each}}

View File

@@ -1,10 +1,15 @@
import axios from "axios" import axios from "axios"
import faker from "faker" 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 { Runner } from '../models/Runner'
import { RunnerCard } from '../models/RunnerCard' import { RunnerCard } from '../models/RunnerCard'
import { RunnerGroup } from '../models/RunnerGroup' import { RunnerGroup } from '../models/RunnerGroup'
const baseurl = "http://localhost:4010" const baseurl = "http://localhost:4010"
const key = config.api_key;
axios.interceptors.request.use((config) => { axios.interceptors.request.use((config) => {
config.headers['request-startTime'] = process.hrtime() config.headers['request-startTime'] = process.hrtime()
@@ -46,6 +51,36 @@ function generateCards(amount: number): RunnerCard[] {
return cards; 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 { function idToEan13(id): string {
const multiply = [1, 3]; const multiply = [1, 3];
id = id.toString(); id = id.toString();
@@ -64,15 +99,20 @@ function idToEan13(id): string {
} }
async function postContracts(runners: Runner[]): Promise<Measurement> { 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'])) return new Measurement("contract", runners.length, parseInt(res.headers['request-duration']))
} }
async function postCards(cards: RunnerCard[]): Promise<Measurement> { 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'])) 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[]> { async function testContracts(sizes): Promise<Measurement[]> {
let measurements = new Array<Measurement>(); let measurements = new Array<Measurement>();
console.log("#### Testing contracts ####"); console.log("#### Testing contracts ####");
@@ -97,16 +137,30 @@ async function testCards(sizes): Promise<Measurement[]> {
return measurements; 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() { async function main() {
const sizes = [0, 1, 10, 50, 100, 200, 500, 1000] const sizes = [1, 10, 50, 100]
console.log("########### Speedtest ###########"); console.log("########### Speedtest ###########");
console.log(`Document server version (according to the api): ${(await axios.get("http://localhost:4010/version")).data.version}`); console.log(`Document server version (according to the api): ${(await axios.get("http://localhost:4010/version")).data.version}`);
console.log("####### Running tests #######"); console.log("####### Running tests #######");
const contractResults = await testContracts(sizes); const contractResults = await testContracts(sizes);
const cardResults = await testCards(sizes); const cardResults = await testCards(sizes);
const certificateResults = await testCertificates(sizes);
console.log("####### Results #######"); console.log("####### Results #######");
console.table(contractResults); console.table(contractResults);
console.table(cardResults); console.table(cardResults);
console.table(certificateResults);
} }
main(); main();