diff --git a/frontend/src/api/service/GeneratePdfService.ts b/frontend/src/api/service/GeneratePdfService.ts index 2ee6cc5b..72a3b730 100644 --- a/frontend/src/api/service/GeneratePdfService.ts +++ b/frontend/src/api/service/GeneratePdfService.ts @@ -29,6 +29,15 @@ export default class GeneratePdfService { data ); } + static postPdfCustomFetchTemplateGesamtauswertung( + data: FormData + ): Promise { + return FetchService.postForPdf( + data, + `${this.ENDPOINT}/auswertung`, + "Beim Generieren der PDF ist ein Fehler aufgetreten." + ); + } private static postPdfCustomFetchTemplate( type: string, diff --git a/frontend/src/components/messstelle/charts/SpeedDial.vue b/frontend/src/components/messstelle/charts/SpeedDial.vue index 4b4239de..c396e1b2 100644 --- a/frontend/src/components/messstelle/charts/SpeedDial.vue +++ b/frontend/src/components/messstelle/charts/SpeedDial.vue @@ -39,6 +39,7 @@ @click="$emit('generateCsv')" /> (); +const props = withDefaults(defineProps(), { + openPdfReportDialog: true, +}); defineEmits<{ (e: "generatePdf"): void; diff --git a/frontend/src/components/messstelle/gesamtauswertung/stepper/TagesTypStepContent.vue b/frontend/src/components/messstelle/gesamtauswertung/stepper/TagesTypStepContent.vue index c7f13823..3264c7b8 100644 --- a/frontend/src/components/messstelle/gesamtauswertung/stepper/TagesTypStepContent.vue +++ b/frontend/src/components/messstelle/gesamtauswertung/stepper/TagesTypStepContent.vue @@ -15,7 +15,7 @@ import type MessstelleAuswertungOptionsDTO from "@/types/messstelle/auswertung/M import { computed } from "vue"; -import { tagesTypText } from "@/types/enum/TagesTyp"; +import TagesTyp, { tagesTypText } from "@/types/enum/TagesTyp"; const auswertungOptions = defineModel({ required: true, @@ -24,10 +24,12 @@ const auswertungOptions = defineModel({ const selectableTagesTypen = computed(() => { const tagestypen: Array = []; tagesTypText.forEach((value, key) => { - tagestypen.push({ - title: value, - value: key, - }); + if (key !== TagesTyp.UNSPECIFIED) { + tagestypen.push({ + title: value, + value: key, + }); + } }); return tagestypen; }); diff --git a/frontend/src/util/MessstelleUtils.ts b/frontend/src/util/MessstelleUtils.ts index 9d06c191..a984bf29 100644 --- a/frontend/src/util/MessstelleUtils.ts +++ b/frontend/src/util/MessstelleUtils.ts @@ -36,10 +36,43 @@ export function useMessstelleUtils() { ); } + function getSelectedVerkehrsartAsText(fahrzeugOptions: FahrzeugOptions) { + let selectedVerkehrsartAsText = "unbekannt"; + if (fahrzeugOptions.busse) { + selectedVerkehrsartAsText = "Bus"; + } else if (fahrzeugOptions.fussverkehr) { + selectedVerkehrsartAsText = "Fuß"; + } else if (fahrzeugOptions.gueterverkehr) { + selectedVerkehrsartAsText = "GV"; + } else if (fahrzeugOptions.kraftraeder) { + selectedVerkehrsartAsText = "Krad"; + } else if (fahrzeugOptions.lastzuege) { + selectedVerkehrsartAsText = "Lz"; + } else if (fahrzeugOptions.gueterverkehrsanteilProzent) { + selectedVerkehrsartAsText = "GV_Anteil"; + } else if (fahrzeugOptions.kraftfahrzeugverkehr) { + selectedVerkehrsartAsText = "Kfz"; + } else if (fahrzeugOptions.lastkraftwagen) { + selectedVerkehrsartAsText = "Lkw"; + } else if (fahrzeugOptions.lieferwagen) { + selectedVerkehrsartAsText = "Lfw"; + } else if (fahrzeugOptions.personenkraftwagen) { + selectedVerkehrsartAsText = "Pkw"; + } else if (fahrzeugOptions.radverkehr) { + selectedVerkehrsartAsText = "Rad"; + } else if (fahrzeugOptions.schwerverkehr) { + selectedVerkehrsartAsText = "SV"; + } else if (fahrzeugOptions.schwerverkehrsanteilProzent) { + selectedVerkehrsartAsText = "SV_Anteil"; + } + return selectedVerkehrsartAsText; + } + return { alleRichtungen, isZeitauswahlSpitzenstunde, hasSelectedFahrzeugkategorie, hasSelectedVerkehrsarten, + getSelectedVerkehrsartAsText, }; } diff --git a/frontend/src/util/ReportTools.ts b/frontend/src/util/ReportTools.ts index 2fc8592f..d664c675 100644 --- a/frontend/src/util/ReportTools.ts +++ b/frontend/src/util/ReportTools.ts @@ -177,6 +177,21 @@ export function useReportTools() { ); } + function addGesamtauswertungToPdfReport( + type: string, + caption: string, + base64: string | undefined + ): void { + if (base64) { + addImageToReport(base64, caption); + snackbarStore.showSuccess(`${type} wurde dem PDF Report hinzugefügt.`); + } else { + snackbarStore.showError( + `${type} konnte dem PDF Report nicht hinzugefügt.` + ); + } + } + function getFileName( erhebungsstelle: Erhebungsstelle, type: string, @@ -210,7 +225,14 @@ export function useReportTools() { base64: string ): void { const filename = getFileName(erhebungsstelle, type, zeitraum); + downloadImage(filename, base64); + } + + function saveGesamtauswertungAsImage(filename: string, base64: string): void { + downloadImage(filename, base64); + } + function downloadImage(filename: string, base64: string): void { if (base64) { const link = document.createElement("a"); link.setAttribute("href", base64); @@ -223,7 +245,9 @@ export function useReportTools() { return { addChartToPdfReport, addDatatableToPdfReport, + addGesamtauswertungToPdfReport, saveGraphAsImage, + saveGesamtauswertungAsImage, getFileName, }; } diff --git a/frontend/src/views/AuswertungView.vue b/frontend/src/views/AuswertungView.vue index eb935589..dcad4bb5 100644 --- a/frontend/src/views/AuswertungView.vue +++ b/frontend/src/views/AuswertungView.vue @@ -17,7 +17,7 @@ + @@ -58,19 +68,32 @@ import { cloneDeep, isNil, toArray, valuesIn } from "lodash"; import { computed, ref } from "vue"; import { useDisplay } from "vuetify"; +import GeneratePdfService from "@/api/service/GeneratePdfService"; import MessstelleAuswertungService from "@/api/service/MessstelleAuswertungService"; import BannerMesstelleTabs from "@/components/messstelle/charts/BannerMesstelleTabs.vue"; +import SpeedDial from "@/components/messstelle/charts/SpeedDial.vue"; import AuswertungStepper from "@/components/messstelle/gesamtauswertung/stepper/AuswertungStepper.vue"; import StepLineCard from "@/components/zaehlstelle/charts/StepLineCard.vue"; +import { useSnackbarStore } from "@/store/SnackbarStore"; +import { useUserStore } from "@/store/UserStore"; import DefaultObjectCreator from "@/util/DefaultObjectCreator"; import { useDownloadUtils } from "@/util/DownloadUtils"; +import { useMessstelleUtils } from "@/util/MessstelleUtils"; +import { useReportTools } from "@/util/ReportTools"; const NUMBER_OF_MAX_XAXIS_ELEMENTS_TO_SHOW = 96; const minWidth = 600; +const reportTools = useReportTools(); const display = useDisplay(); const downloadUtils = useDownloadUtils(); +const snackbarStore = useSnackbarStore(); +const messstelleUtils = useMessstelleUtils(); + +const loadingFile = ref(false); +const auswertungLoaded = ref(false); +const steplineCard = ref | null>(); const zaehldatenMessstellen = ref( DefaultObjectCreator.createDefaultLadeZaehldatenSteplineDTO() @@ -111,6 +134,10 @@ const showDiagram = computed(() => { ); }); +const showSpeeddial = computed(() => { + return showDiagram.value && isEverythingValid.value && auswertungLoaded.value; +}); + const isNumberOfXaxisElementsShowable = computed(() => { const numerOfChosenXaxisElements = toArray(auswertungsOptions.value.zeitraum).length * @@ -146,7 +173,7 @@ const stepperHeightVh = computed(() => { }); const isEverythingValid = computed(() => { - return !( + return ( auswertungsOptions.value.zeitraum.length > 0 && auswertungsOptions.value.tagesTyp.length > 0 && auswertungsOptions.value.jahre.length > 0 && @@ -179,8 +206,8 @@ function resetAuswertungsOptions() { } function auswertungStarten() { - MessstelleAuswertungService.generate(auswertungsOptions.value).then( - (result: AuswertungMessstelleWithFileDTO) => { + MessstelleAuswertungService.generate(auswertungsOptions.value) + .then((result: AuswertungMessstelleWithFileDTO) => { zaehldatenMessstellen.value = isNil(result.zaehldatenMessstellen) ? cloneDeep( DefaultObjectCreator.createDefaultLadeZaehldatenSteplineDTO() @@ -188,7 +215,89 @@ function auswertungStarten() { : cloneDeep(result.zaehldatenMessstellen); const filename = `Gesamtauswertung_${new Date().toISOString().split("T")[0]}.xlsx`; downloadUtils.downloadXlsx(result.spreadsheetBase64Encoded, filename); - } + auswertungLoaded.value = true; + }) + .catch((error) => { + snackbarStore.showApiError(error); + auswertungLoaded.value = false; + }); +} + +/** + * Base 64 String der Ganglinie + */ +function getGanglinieBase64(): string | undefined { + return steplineCard?.value?.steplineForPdf?.chart?.getDataURL({ + pixelRatio: 2, + backgroundColor: "#fff", + excludeComponents: ["toolbox"], + }); +} + +function createPdf() { + const formData = new FormData(); + formData.append( + "options", + new Blob([JSON.stringify(auswertungsOptions.value)], { + type: "application/json", + }) + ); + formData.append( + "chartAsBase64Png", + new Blob([getGanglinieBase64() ?? ""], { + type: "image/png", + }) + ); + formData.append( + "auswertung", + new Blob([JSON.stringify(zaehldatenMessstellen.value)], { + type: "application/json", + }) ); + formData.append("department", useUserStore().getDepartment); + + GeneratePdfService.postPdfCustomFetchTemplateGesamtauswertung(formData) + .then((blob) => { + downloadUtils.downloadFile(blob, getFilename(".pdf")); + }) + .catch((error) => useSnackbarStore().showApiError(error)); +} + +/** + * Speichert das aktuell offene Diagramm als Png bzw SVG (Kreuzung-Belastungsplan) + */ +function saveGraphAsImage(): void { + loadingFile.value = true; + const encodedUri = getGanglinieBase64(); + if (encodedUri) { + reportTools.saveGesamtauswertungAsImage(getFilename(".png"), encodedUri); + } + loadingFile.value = false; +} + +/** + * Fügt dem PDF Report das aktuell angezeigte Chart hinzu. + */ +function addChartToPdfReport(): void { + let caption = getFilename(""); + caption = caption.replaceAll("_", " "); + reportTools.addGesamtauswertungToPdfReport( + "Die Auswertung", + caption, + getGanglinieBase64() + ); +} + +function getFilename(ending: string) { + let filename = `Gesamtauswertung_${new Date().toISOString().split("T")[0]}`; + if (auswertungsOptions.value.messstelleAuswertungIds.length === 1) { + const firstMessstelle = + auswertungsOptions.value.messstelleAuswertungIds.at(0); + filename = `Zeitreihe_zur_Messstelle_${firstMessstelle ? firstMessstelle.mstId : "unbekannt"}`; + } + if (auswertungsOptions.value.messstelleAuswertungIds.length > 1) { + filename = `Zeitreihe_zur_Messung_${messstelleUtils.getSelectedVerkehrsartAsText(auswertungsOptions.value.fahrzeuge)}`; + } + return `${filename}${ending}`; }