fix: display newsletter progress in client

This commit is contained in:
Julian Krauser 2025-01-12 13:25:55 +01:00
parent 52a35be6c5
commit a8e2b05d8e
6 changed files with 72 additions and 40 deletions

View file

@ -113,10 +113,10 @@ export default defineComponent({
}, },
methods: { methods: {
...mapActions(useNotificationStore, ["revoke"]), ...mapActions(useNotificationStore, ["revoke"]),
close(id: number) { close(id: string) {
this.revoke(id); this.revoke(id);
}, },
hovering(id: number, value: boolean, timeout?: number) { hovering(id: string, value: boolean, timeout?: number) {
if (value) { if (value) {
clearTimeout(this.timeouts[id]); clearTimeout(this.timeouts[id]);
} else { } else {

View file

@ -9,8 +9,6 @@ export async function setNewsletterId(to: any, from: any, next: any) {
useNewsletterDatesStore().$reset(); useNewsletterDatesStore().$reset();
useNewsletterRecipientsStore().$reset(); useNewsletterRecipientsStore().$reset();
useNewsletterPrintoutStore().unsubscribePdfPrintingProgress();
useNewsletterPrintoutStore().unsubscribeMailSendingProgress();
useNewsletterPrintoutStore().$reset(); useNewsletterPrintoutStore().$reset();
next(); next();
@ -23,8 +21,6 @@ export async function resetNewsletterStores(to: any, from: any, next: any) {
useNewsletterDatesStore().$reset(); useNewsletterDatesStore().$reset();
useNewsletterRecipientsStore().$reset(); useNewsletterRecipientsStore().$reset();
useNewsletterPrintoutStore().unsubscribePdfPrintingProgress();
useNewsletterPrintoutStore().unsubscribeMailSendingProgress();
useNewsletterPrintoutStore().$reset(); useNewsletterPrintoutStore().$reset();
next(); next();

View file

@ -62,7 +62,7 @@ http.interceptors.response.use(
.then(() => { .then(() => {
return http(originalRequest); return http(originalRequest);
}) })
.catch(); .catch(() => {});
} }
const notificationStore = useNotificationStore(); const notificationStore = useNotificationStore();
@ -108,4 +108,25 @@ function newEventSource(path: string) {
}); });
} }
export { http, newEventSource, host }; async function* streamingFetch(path: string, abort?: AbortController) {
await refreshToken()
.then(() => {})
.catch(() => {});
const token = localStorage.getItem("accessToken");
const response = await fetch(url + "/api" + path, {
signal: abort?.signal,
headers: {
Authorization: `Bearer ${token}`,
},
});
const reader = response.body?.getReader();
while (true && reader) {
const { done, value } = await reader.read();
if (done) break;
yield new TextDecoder().decode(value);
}
}
export { http, newEventSource, streamingFetch, host };

View file

@ -1,8 +1,9 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { http, newEventSource } from "@/serverCom"; import { http, newEventSource, streamingFetch } from "@/serverCom";
import { useNewsletterStore } from "./newsletter"; import { useNewsletterStore } from "./newsletter";
import type { AxiosResponse } from "axios"; import type { AxiosResponse } from "axios";
import type { EventSourcePolyfill } from "event-source-polyfill"; import type { EventSourcePolyfill } from "event-source-polyfill";
import { useNotificationStore, type NotificationType } from "../../../notification";
export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", { export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", {
state: () => { state: () => {
@ -12,10 +13,10 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", {
printing: undefined as undefined | "loading" | "success" | "failed", printing: undefined as undefined | "loading" | "success" | "failed",
sending: undefined as undefined | "loading" | "success" | "failed", sending: undefined as undefined | "loading" | "success" | "failed",
sendingPreview: undefined as undefined | "loading" | "success" | "failed", sendingPreview: undefined as undefined | "loading" | "success" | "failed",
pdfProgessSource: undefined as undefined | EventSourcePolyfill,
mailProgessSource: undefined as undefined | EventSourcePolyfill,
pdfSourceMessages: [] as Array<Object>, pdfSourceMessages: [] as Array<Object>,
mailSourceMessages: [] as Array<Object>, mailSourceMessages: [] as Array<Object>,
pdfPrintingAbort: undefined as undefined | AbortController,
mailSendingAbort: undefined as undefined | AbortController,
}; };
}, },
actions: { actions: {
@ -63,6 +64,7 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", {
}); });
}, },
createNewsletterPrintout() { createNewsletterPrintout() {
this.subscribePdfPrintingProgress();
this.printing = "loading"; this.printing = "loading";
const newsletterId = useNewsletterStore().activeNewsletter; const newsletterId = useNewsletterStore().activeNewsletter;
if (newsletterId == null) return; if (newsletterId == null) return;
@ -78,10 +80,12 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", {
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {
this.printing = undefined; this.printing = undefined;
this.pdfPrintingAbort?.abort();
}, 1500); }, 1500);
}); });
}, },
createNewsletterSend() { createNewsletterSend() {
this.subscribeMailSendingProgress();
this.sending = "loading"; this.sending = "loading";
const newsletterId = useNewsletterStore().activeNewsletter; const newsletterId = useNewsletterStore().activeNewsletter;
if (newsletterId == null) return; if (newsletterId == null) return;
@ -96,32 +100,47 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", {
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {
this.sending = undefined; this.sending = undefined;
this.mailSendingAbort?.abort();
}, 1500); }, 1500);
}); });
}, },
subscribePdfPrintingProgress() { async subscribePdfPrintingProgress() {
// const newsletterId = useNewsletterStore().activeNewsletter; this.pdfSourceMessages = [];
// if (this.pdfProgessSource != undefined) return; const newsletterId = useNewsletterStore().activeNewsletter;
// this.pdfProgessSource = newEventSource(`/admin/newsletter/${newsletterId}/printoutprogress`); const notificationStore = useNotificationStore();
// this.pdfProgessSource.onmessage = (event) => { this.pdfPrintingAbort = new AbortController();
// console.log("pdf", event); for await (let chunk of streamingFetch(
// }; `/admin/newsletter/${newsletterId}/printoutprogress`,
this.pdfPrintingAbort
)) {
chunk.split("//").forEach((r) => {
if (r.trim() != "") {
let data = JSON.parse(r);
this.pdfSourceMessages.push(data);
let type: NotificationType = "info";
if (data.factor == "failed") type = "error";
notificationStore.push(`Druck: ${data.iteration}/${data.total}`, `${data.msg}`, type);
}
});
this.fetchNewsletterPrintout();
}
}, },
subscribeMailSendingProgress() { async subscribeMailSendingProgress() {
// const newsletterId = useNewsletterStore().activeNewsletter; this.mailSourceMessages = [];
// if (this.mailProgessSource != undefined) return; const newsletterId = useNewsletterStore().activeNewsletter;
// this.mailProgessSource = newEventSource(`/admin/newsletter/${newsletterId}/sendprogress`); const notificationStore = useNotificationStore();
// this.mailProgessSource.onmessage = (event) => { this.mailSendingAbort = new AbortController();
// console.log("mail", event); for await (let chunk of streamingFetch(`/admin/newsletter/${newsletterId}/sendprogress`, this.mailSendingAbort)) {
// }; chunk.split("//").forEach((r) => {
}, if (r.trim() != "") {
unsubscribePdfPrintingProgress() { let data = JSON.parse(r);
this.pdfProgessSource?.close(); this.mailSourceMessages.push(data);
this.pdfProgessSource = undefined; let type: NotificationType = "info";
}, if (data.factor == "failed") type = "error";
unsubscribeMailSendingProgress() { notificationStore.push(`Mailversand: ${data.iteration}/${data.total}`, `${data.msg}`, type);
this.mailProgessSource?.close(); }
this.mailProgessSource = undefined; });
}
}, },
}, },
}); });

View file

@ -1,7 +1,7 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
export interface Notification { export interface Notification {
id: number; id: string;
title: string; title: string;
text: string; text: string;
type: NotificationType; type: NotificationType;
@ -19,7 +19,7 @@ export const useNotificationStore = defineStore("notification", {
}, },
actions: { actions: {
push(title: string, text: string, type: NotificationType, timeout: number = 5000) { push(title: string, text: string, type: NotificationType, timeout: number = 5000) {
let id = Date.now(); let id = `${Date.now()}_${Math.random()}`;
this.notifications.push({ this.notifications.push({
id, id,
title, title,
@ -34,7 +34,7 @@ export const useNotificationStore = defineStore("notification", {
this.revoke(id); this.revoke(id);
}, timeout); }, timeout);
}, },
revoke(id: number) { revoke(id: string) {
this.notifications.splice( this.notifications.splice(
this.notifications.findIndex((n) => n.id === id), this.notifications.findIndex((n) => n.id === id),
1 1

View file

@ -89,8 +89,6 @@ export default defineComponent({
}, },
mounted() { mounted() {
this.fetchNewsletterPrintout(); this.fetchNewsletterPrintout();
this.subscribeMailSendingProgress();
this.subscribePdfPrintingProgress();
}, },
methods: { methods: {
...mapActions(useModalStore, ["openModal"]), ...mapActions(useModalStore, ["openModal"]),
@ -100,8 +98,6 @@ export default defineComponent({
"fetchNewsletterPrintoutById", "fetchNewsletterPrintoutById",
"createNewsletterMailPreview", "createNewsletterMailPreview",
"createNewsletterSend", "createNewsletterSend",
"subscribeMailSendingProgress",
"subscribePdfPrintingProgress",
]), ]),
openPdfShow(filename?: string) { openPdfShow(filename?: string) {
this.openModal( this.openModal(