PDF Generator for Exercise progress
This commit is contained in:
242
package-lock.json
generated
Normal file
242
package-lock.json
generated
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
{
|
||||||
|
"name": "eventmaster",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"jspdf": "^2.5.2",
|
||||||
|
"jspdf-autotable": "^3.8.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/runtime": {
|
||||||
|
"version": "7.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
|
||||||
|
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"regenerator-runtime": "^0.14.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/raf": {
|
||||||
|
"version": "3.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
|
||||||
|
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/atob": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||||
|
"license": "(MIT OR Apache-2.0)",
|
||||||
|
"bin": {
|
||||||
|
"atob": "bin/atob.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/base64-arraybuffer": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/btoa": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
|
||||||
|
"license": "(MIT OR Apache-2.0)",
|
||||||
|
"bin": {
|
||||||
|
"btoa": "bin/btoa.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/canvg": {
|
||||||
|
"version": "3.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz",
|
||||||
|
"integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"@types/raf": "^3.4.0",
|
||||||
|
"core-js": "^3.8.3",
|
||||||
|
"raf": "^3.4.1",
|
||||||
|
"regenerator-runtime": "^0.13.7",
|
||||||
|
"rgbcolor": "^1.0.1",
|
||||||
|
"stackblur-canvas": "^2.0.0",
|
||||||
|
"svg-pathdata": "^6.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/canvg/node_modules/regenerator-runtime": {
|
||||||
|
"version": "0.13.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||||
|
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/core-js": {
|
||||||
|
"version": "3.39.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz",
|
||||||
|
"integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/core-js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-line-break": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"utrie": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dompurify": {
|
||||||
|
"version": "2.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.7.tgz",
|
||||||
|
"integrity": "sha512-2q4bEI+coQM8f5ez7kt2xclg1XsecaV9ASJk/54vwlfRRNQfDqJz2pzQ8t0Ix/ToBpXlVjrRIx7pFC/o8itG2Q==",
|
||||||
|
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/fflate": {
|
||||||
|
"version": "0.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
|
||||||
|
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/html2canvas": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"css-line-break": "^2.1.0",
|
||||||
|
"text-segmentation": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jspdf": {
|
||||||
|
"version": "2.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz",
|
||||||
|
"integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.23.2",
|
||||||
|
"atob": "^2.1.2",
|
||||||
|
"btoa": "^1.2.1",
|
||||||
|
"fflate": "^0.8.1"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"canvg": "^3.0.6",
|
||||||
|
"core-js": "^3.6.0",
|
||||||
|
"dompurify": "^2.5.4",
|
||||||
|
"html2canvas": "^1.0.0-rc.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jspdf-autotable": {
|
||||||
|
"version": "3.8.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-3.8.4.tgz",
|
||||||
|
"integrity": "sha512-rSffGoBsJYX83iTRv8Ft7FhqfgEL2nLpGAIiqruEQQ3e4r0qdLFbPUB7N9HAle0I3XgpisvyW751VHCqKUVOgQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"jspdf": "^2.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/performance-now": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"node_modules/raf": {
|
||||||
|
"version": "3.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||||
|
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"performance-now": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/regenerator-runtime": {
|
||||||
|
"version": "0.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/rgbcolor": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
|
||||||
|
"license": "MIT OR SEE LICENSE IN FEEL-FREE.md",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.15"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/stackblur-canvas": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.1.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/svg-pathdata": {
|
||||||
|
"version": "6.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
|
||||||
|
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/text-segmentation": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"utrie": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/utrie": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"base64-arraybuffer": "^1.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
package.json
Normal file
6
package.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"jspdf": "^2.5.2",
|
||||||
|
"jspdf-autotable": "^3.8.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import { SeatGroupModel } from '@/data/models/locations/seatGroupModel';
|
|||||||
import { SeatModel } from '@/data/models/locations/seatModel';
|
import { SeatModel } from '@/data/models/locations/seatModel';
|
||||||
import { SeatRowModel } from '@/data/models/locations/seatRowModel';
|
import { SeatRowModel } from '@/data/models/locations/seatRowModel';
|
||||||
import { SelectedSeatModel } from '@/data/models/ordering/selectedSeatModel';
|
import { SelectedSeatModel } from '@/data/models/ordering/selectedSeatModel';
|
||||||
import { getSeatColor } from '@/helpers/colorScripts';
|
import { getSeatColor } from '@/scripts/colorScripts';
|
||||||
import { useBasketStore } from '@/stores/basket.store';
|
import { useBasketStore } from '@/stores/basket.store';
|
||||||
|
|
||||||
const basketStore = useBasketStore()
|
const basketStore = useBasketStore()
|
||||||
|
|||||||
@@ -1,14 +1,31 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import scoreCard from './scoreCard.vue';
|
import scoreCard from './scoreCard.vue';
|
||||||
import { useExerciseStore } from '@/stores/exercise.store';
|
import { useExerciseStore } from '@/stores/exercise.store';
|
||||||
|
import outlinedButton from '@/components/basics/outlinedButton.vue';
|
||||||
|
import { generateResultsPdf } from '@/scripts/pdfScripts';
|
||||||
|
import { usePreferencesStore } from '@/stores/preferences.store';
|
||||||
|
|
||||||
const exerciseStore = useExerciseStore()
|
const exerciseStore = useExerciseStore()
|
||||||
|
const preferencesStore = usePreferencesStore()
|
||||||
|
|
||||||
exerciseStore.getAllExercises()
|
exerciseStore.getAllExercises()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container max-width="1000">
|
<v-container max-width="1000">
|
||||||
|
<v-row>
|
||||||
|
<v-spacer />
|
||||||
|
|
||||||
|
<v-col cols="auto">
|
||||||
|
<outlined-button
|
||||||
|
prepend-icon="mdi-file-pdf-box"
|
||||||
|
@click="generateResultsPdf()"
|
||||||
|
:disabled="preferencesStore.studentName.length < 3 || preferencesStore.registrationNumber.length < 7"
|
||||||
|
>
|
||||||
|
PDF generieren
|
||||||
|
</outlined-button>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
<v-row v-if="exerciseStore.fetchInProgress" v-for="i in 3">
|
<v-row v-if="exerciseStore.fetchInProgress" v-for="i in 3">
|
||||||
<v-col>
|
<v-col>
|
||||||
<score-card :loading="true"
|
<score-card :loading="true"
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import cardView from '@/components/basics/cardView.vue';
|
import cardView from '@/components/basics/cardView.vue';
|
||||||
|
import { LanguageEnum } from '@/data/enums/languageEnum';
|
||||||
import { ExerciseGroupApiModel } from '@/data/models/exercises/exerciseGroupApiModel';
|
import { ExerciseGroupApiModel } from '@/data/models/exercises/exerciseGroupApiModel';
|
||||||
|
import { usePreferencesStore } from '@/stores/preferences.store';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
exerciseGroup: ExerciseGroupApiModel,
|
exerciseGroup: ExerciseGroupApiModel,
|
||||||
loading: Boolean
|
loading: Boolean
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const preferencesStore = usePreferencesStore()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -37,10 +41,10 @@ defineProps({
|
|||||||
</v-timeline>
|
</v-timeline>
|
||||||
</card-view>
|
</card-view>
|
||||||
|
|
||||||
<!-- todo: English -->
|
|
||||||
<card-view
|
<card-view
|
||||||
v-else
|
v-else
|
||||||
:title="$t('help.scoreBoard.exerciseGroupNr', [exerciseGroup.groupNr]) + exerciseGroup.nameDe"
|
:title="$t('help.scoreBoard.exerciseGroupNr', [exerciseGroup.groupNr]) +
|
||||||
|
(preferencesStore.language == LanguageEnum.GERMAN ? exerciseGroup.nameDe : exerciseGroup.nameEn)"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
>
|
>
|
||||||
<template #borderless>
|
<template #borderless>
|
||||||
@@ -69,14 +73,14 @@ defineProps({
|
|||||||
type="text"
|
type="text"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
>
|
>
|
||||||
<div class="text-center">
|
<div class="text-center pb-3">
|
||||||
<div class="text-h6">
|
<div class="text-h6">
|
||||||
{{ exercise.nameDe }}
|
{{ (preferencesStore.language == LanguageEnum.GERMAN ? exercise.nameDe : exercise.nameEn) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<!-- todo: English -->
|
{{ (preferencesStore.language == LanguageEnum.GERMAN ?
|
||||||
{{ exercise.descriptionDe }}
|
exercise.descriptionDe : exercise.descriptionEn) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</v-skeleton-loader>
|
</v-skeleton-loader>
|
||||||
|
|||||||
66
software/src/scripts/pdfScripts.ts
Normal file
66
software/src/scripts/pdfScripts.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { useExerciseStore } from "@/stores/exercise.store";
|
||||||
|
import { usePreferencesStore } from "@/stores/preferences.store";
|
||||||
|
import { jsPDF } from "jspdf"
|
||||||
|
import autoTable from "jspdf-autotable"
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
export function generateResultsPdf() {
|
||||||
|
const preferencesStore = usePreferencesStore()
|
||||||
|
const exerciseStore = useExerciseStore()
|
||||||
|
|
||||||
|
const doc = new jsPDF()
|
||||||
|
const pageHeight = doc.internal.pageSize.height || doc.internal.pageSize.getHeight();
|
||||||
|
const pageWidth = doc.internal.pageSize.width || doc.internal.pageSize.getWidth()
|
||||||
|
const midPage = doc.internal.pageSize.getWidth() / 2
|
||||||
|
|
||||||
|
const exerciseData = []
|
||||||
|
|
||||||
|
exerciseStore.exerciseGroups.forEach(group => {
|
||||||
|
group.exercises.forEach(exercise => {
|
||||||
|
exerciseData.push([
|
||||||
|
group.groupNr + "." + exercise.exerciseNr,
|
||||||
|
group.nameDe,
|
||||||
|
exercise.nameDe,
|
||||||
|
exercise.solved ? 'Ja' : 'Nein'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Title and image
|
||||||
|
doc.setFontSize(48)
|
||||||
|
doc.text("EventMaster", midPage, 25, { align: "center" })
|
||||||
|
doc.addImage("../../public/logo.png", "PNG", 65, 36, 80, 80)
|
||||||
|
|
||||||
|
// Data about student
|
||||||
|
doc.setFontSize(24)
|
||||||
|
doc.text([preferencesStore.studentName, preferencesStore.registrationNumber], midPage, 130, { align: "center" })
|
||||||
|
|
||||||
|
// Progress total
|
||||||
|
doc.setFontSize(28)
|
||||||
|
doc.text("Hat " + exerciseStore.exerciseGroups.reduce((counter, group) => {
|
||||||
|
for (let exercise of group.exercises) {
|
||||||
|
if (exercise.solved) {
|
||||||
|
counter++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter
|
||||||
|
}, 0) + " von 10 Aufgaben gelöst.", midPage, 160, { align: "center" })
|
||||||
|
|
||||||
|
|
||||||
|
// Progress table
|
||||||
|
doc.setFontSize(22)
|
||||||
|
autoTable(doc, {
|
||||||
|
startY: 170,
|
||||||
|
head: [[ "Aufgaben-Nr.", "Aufgabengruppe", "Aufgabe", "Abgeschlossen?"]],
|
||||||
|
body: exerciseData
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
doc.setFontSize(12)
|
||||||
|
doc.text(["Grundlagen der IT-Sicherheit", "Fachgebiet Usable Security and Privacy", "Institut für IT-Sicherheit", "Leibniz Universität Hannover"], midPage, pageHeight - 30, { align: "center" })
|
||||||
|
doc.text(moment().format("DD.MM.YYYY, HH:mm:ss"), midPage, pageHeight - 8, { align: "center" })
|
||||||
|
|
||||||
|
doc.save("eventmaster-exercise-result.pdf")
|
||||||
|
}
|
||||||
@@ -39,10 +39,10 @@ export const usePreferencesStore = defineStore('preferencesStore', {
|
|||||||
firstStartup: useLocalStorage<Boolean>("hackmycart/preferencesStore/firstStartup", true),
|
firstStartup: useLocalStorage<Boolean>("hackmycart/preferencesStore/firstStartup", true),
|
||||||
|
|
||||||
/** Full name of student */
|
/** Full name of student */
|
||||||
studentName: useLocalStorage<String>("hackmycart/preferencesStore/studentName", ""),
|
studentName: useLocalStorage<string>("hackmycart/preferencesStore/studentName", ""),
|
||||||
|
|
||||||
/** Matrikel number */
|
/** Matrikel number */
|
||||||
registrationNumber: useLocalStorage<String>("hackmycart/preferencesStore/registrationNumber", "")
|
registrationNumber: useLocalStorage<string>("hackmycart/preferencesStore/registrationNumber", "")
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|||||||
Reference in New Issue
Block a user