PDF Generator for Exercise progress
This commit is contained in:
@@ -4,7 +4,7 @@ import { SeatGroupModel } from '@/data/models/locations/seatGroupModel';
|
||||
import { SeatModel } from '@/data/models/locations/seatModel';
|
||||
import { SeatRowModel } from '@/data/models/locations/seatRowModel';
|
||||
import { SelectedSeatModel } from '@/data/models/ordering/selectedSeatModel';
|
||||
import { getSeatColor } from '@/helpers/colorScripts';
|
||||
import { getSeatColor } from '@/scripts/colorScripts';
|
||||
import { useBasketStore } from '@/stores/basket.store';
|
||||
|
||||
const basketStore = useBasketStore()
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import scoreCard from './scoreCard.vue';
|
||||
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 preferencesStore = usePreferencesStore()
|
||||
|
||||
exerciseStore.getAllExercises()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<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-col>
|
||||
<score-card :loading="true"
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import cardView from '@/components/basics/cardView.vue';
|
||||
import { LanguageEnum } from '@/data/enums/languageEnum';
|
||||
import { ExerciseGroupApiModel } from '@/data/models/exercises/exerciseGroupApiModel';
|
||||
import { usePreferencesStore } from '@/stores/preferences.store';
|
||||
|
||||
defineProps({
|
||||
exerciseGroup: ExerciseGroupApiModel,
|
||||
loading: Boolean
|
||||
})
|
||||
|
||||
const preferencesStore = usePreferencesStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -37,10 +41,10 @@ defineProps({
|
||||
</v-timeline>
|
||||
</card-view>
|
||||
|
||||
<!-- todo: English -->
|
||||
<card-view
|
||||
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"
|
||||
>
|
||||
<template #borderless>
|
||||
@@ -69,14 +73,14 @@ defineProps({
|
||||
type="text"
|
||||
:loading="loading"
|
||||
>
|
||||
<div class="text-center">
|
||||
<div class="text-center pb-3">
|
||||
<div class="text-h6">
|
||||
{{ exercise.nameDe }}
|
||||
{{ (preferencesStore.language == LanguageEnum.GERMAN ? exercise.nameDe : exercise.nameEn) }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<!-- todo: English -->
|
||||
{{ exercise.descriptionDe }}
|
||||
{{ (preferencesStore.language == LanguageEnum.GERMAN ?
|
||||
exercise.descriptionDe : exercise.descriptionEn) }}
|
||||
</div>
|
||||
</div>
|
||||
</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),
|
||||
|
||||
/** Full name of student */
|
||||
studentName: useLocalStorage<String>("hackmycart/preferencesStore/studentName", ""),
|
||||
studentName: useLocalStorage<string>("hackmycart/preferencesStore/studentName", ""),
|
||||
|
||||
/** Matrikel number */
|
||||
registrationNumber: useLocalStorage<String>("hackmycart/preferencesStore/registrationNumber", "")
|
||||
registrationNumber: useLocalStorage<string>("hackmycart/preferencesStore/registrationNumber", "")
|
||||
}),
|
||||
|
||||
actions: {
|
||||
|
||||
Reference in New Issue
Block a user