Compare commits

..

No commits in common. "3da0f4cd49be63f444c77f800976e9fa2572c0ce" and "52a35be6c5371c8dc890b4371bc24f64e2798ae5" have entirely different histories.

8 changed files with 49 additions and 213 deletions

View file

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

View file

@ -1,44 +0,0 @@
<template>
<div class="w-full md:max-w-md">
<div class="flex flex-col items-center">
<p class="text-xl font-medium">Newsletter Mail-Versand Logs</p>
</div>
<br />
<div class="h-96 overflow-y-scroll">
<p v-for="entry in mailSourceMessages">
{{ entry }}
</p>
</div>
<div class="flex flex-row justify-end">
<div class="flex flex-row gap-4 py-2">
<button primary-outline @click="closeModal">
abbrechen
</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { defineComponent } from "vue";
import { mapState, mapActions } from "pinia";
import { useModalStore } from "@/stores/modal";
import { useNewsletterPrintoutStore } from "@/stores/admin/club/newsletter/newsletterPrintout";
</script>
<script lang="ts">
export default defineComponent({
data() {
return {
};
},
computed:{
...mapState(useNewsletterPrintoutStore, ["mailSourceMessages"])
},
methods: {
...mapActions(useModalStore, ["closeModal"]),
},
});
</script>

View file

@ -1,50 +0,0 @@
<template>
<div class="w-full md:max-w-md">
<div class="flex flex-col items-center">
<p class="text-xl font-medium">Newsletter Druck-Prozess Logs</p>
</div>
<br />
<div class="flex flex-col gap-2 h-96 overflow-y-scroll">
<div
v-for="entry in pdfSourceMessages"
class="flex flex-row gap-2 border border-gray-200 rounded-md p-1 items-center"
>
<SuccessCheckmark v-if="entry.factor == 'success'" class="w-5 h-5" />
<InformationCircleIcon v-else-if="entry.factor == 'info'" class="w-5 h-5 min-h-5 min-w-5 text-gray-500" />
<FailureXMark v-else-if="entry.factor == 'failed'" class="w-5 h-5" />
<p>{{ entry.iteration }}/{{ entry.total }}: {{ entry.msg }}</p>
</div>
</div>
<div class="flex flex-row justify-end">
<div class="flex flex-row gap-4 py-2">
<button primary-outline @click="closeModal">abbrechen</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { defineComponent } from "vue";
import { mapState, mapActions } from "pinia";
import { useModalStore } from "@/stores/modal";
import { useNewsletterPrintoutStore } from "@/stores/admin/club/newsletter/newsletterPrintout";
import SuccessCheckmark from "@/components/SuccessCheckmark.vue";
import { InformationCircleIcon } from "@heroicons/vue/24/solid";
import FailureXMark from "@/components/FailureXMark.vue";
</script>
<script lang="ts">
export default defineComponent({
data() {
return {};
},
computed: {
...mapState(useNewsletterPrintoutStore, ["pdfSourceMessages"]),
},
methods: {
...mapActions(useModalStore, ["closeModal"]),
},
});
</script>

View file

@ -9,6 +9,8 @@ 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();
@ -21,6 +23,8 @@ 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,25 +108,4 @@ function newEventSource(path: string) {
}); });
} }
async function* streamingFetch(path: string, abort?: AbortController) { export { http, newEventSource, host };
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,9 +1,8 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { http, newEventSource, streamingFetch } from "@/serverCom"; import { http, newEventSource } 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: () => {
@ -13,10 +12,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",
pdfSourceMessages: [] as Array<{ kind: string; factor: string; [key: string]: string }>, pdfProgessSource: undefined as undefined | EventSourcePolyfill,
mailSourceMessages: [] as Array<{ kind: string; factor: string; [key: string]: string }>, mailProgessSource: undefined as undefined | EventSourcePolyfill,
pdfPrintingAbort: undefined as undefined | AbortController, pdfSourceMessages: [] as Array<Object>,
mailSendingAbort: undefined as undefined | AbortController, mailSourceMessages: [] as Array<Object>,
}; };
}, },
actions: { actions: {
@ -64,7 +63,6 @@ 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;
@ -80,12 +78,10 @@ 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;
@ -100,55 +96,32 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", {
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {
this.sending = undefined; this.sending = undefined;
this.mailSendingAbort?.abort();
}, 1500); }, 1500);
}); });
}, },
async subscribePdfPrintingProgress() { subscribePdfPrintingProgress() {
this.pdfSourceMessages = []; // const newsletterId = useNewsletterStore().activeNewsletter;
const newsletterId = useNewsletterStore().activeNewsletter; // if (this.pdfProgessSource != undefined) return;
const notificationStore = useNotificationStore(); // this.pdfProgessSource = newEventSource(`/admin/newsletter/${newsletterId}/printoutprogress`);
this.pdfPrintingAbort = new AbortController(); // this.pdfProgessSource.onmessage = (event) => {
for await (let chunk of streamingFetch( // console.log("pdf", event);
`/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";
let timeout = undefined;
if (data.factor == "failed") {
type = "error";
timeout = 0;
}
notificationStore.push(`Druck: ${data.iteration}/${data.total}`, `${data.msg}`, type, timeout);
}
});
this.fetchNewsletterPrintout();
}
}, },
async subscribeMailSendingProgress() { subscribeMailSendingProgress() {
this.mailSourceMessages = []; // const newsletterId = useNewsletterStore().activeNewsletter;
const newsletterId = useNewsletterStore().activeNewsletter; // if (this.mailProgessSource != undefined) return;
const notificationStore = useNotificationStore(); // this.mailProgessSource = newEventSource(`/admin/newsletter/${newsletterId}/sendprogress`);
this.mailSendingAbort = new AbortController(); // this.mailProgessSource.onmessage = (event) => {
for await (let chunk of streamingFetch(`/admin/newsletter/${newsletterId}/sendprogress`, this.mailSendingAbort)) { // console.log("mail", event);
chunk.split("//").forEach((r) => { // };
if (r.trim() != "") { },
let data = JSON.parse(r); unsubscribePdfPrintingProgress() {
this.mailSourceMessages.push(data); this.pdfProgessSource?.close();
let type: NotificationType = "info"; this.pdfProgessSource = undefined;
let timeout = undefined; },
if (data.factor == "failed") { unsubscribeMailSendingProgress() {
type = "error"; this.mailProgessSource?.close();
timeout = 0; this.mailProgessSource = undefined;
}
notificationStore.push(`Mailversand: ${data.iteration}/${data.total}`, `${data.msg}`, type, timeout);
}
});
}
}, },
}, },
}); });

View file

@ -1,7 +1,7 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
export interface Notification { export interface Notification {
id: string; id: number;
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()}_${Math.random()}`; let id = Date.now();
this.notifications.push({ this.notifications.push({
id, id,
title, title,
@ -27,16 +27,14 @@ export const useNotificationStore = defineStore("notification", {
type, type,
indicator: false, indicator: false,
}); });
if (timeout != 0) { setTimeout(() => {
setTimeout(() => { this.notifications[this.notifications.findIndex((n) => n.id === id)].indicator = true;
this.notifications[this.notifications.findIndex((n) => n.id === id)].indicator = true; }, 100);
}, 100); this.timeouts[id] = setTimeout(() => {
this.timeouts[id] = setTimeout(() => { this.revoke(id);
this.revoke(id); }, timeout);
}, timeout);
}
}, },
revoke(id: string) { revoke(id: number) {
this.notifications.splice( this.notifications.splice(
this.notifications.findIndex((n) => n.id === id), this.notifications.findIndex((n) => n.id === id),
1 1

View file

@ -61,12 +61,6 @@
<SuccessCheckmark v-else-if="sendingPreview == 'success'" /> <SuccessCheckmark v-else-if="sendingPreview == 'success'" />
<FailureXMark v-else-if="sendingPreview == 'failed'" /> <FailureXMark v-else-if="sendingPreview == 'failed'" />
</button> </button>
<button v-if="pdfSourceMessages.length != 0" primary-outline class="!w-fit" @click="openPdfLogs">
Druck Logs
</button>
<button v-if="mailSourceMessages.length != 0" primary-outline class="!w-fit" @click="openMailLogs">
Versand Logs
</button>
</div> </div>
</div> </div>
</template> </template>
@ -90,19 +84,13 @@ export default defineComponent({
newsletterId: String, newsletterId: String,
}, },
computed: { computed: {
...mapState(useNewsletterPrintoutStore, [ ...mapState(useNewsletterPrintoutStore, ["printout", "loading", "printing", "sending", "sendingPreview"]),
"printout",
"loading",
"printing",
"sending",
"sendingPreview",
"mailSourceMessages",
"pdfSourceMessages",
]),
...mapState(useAbilityStore, ["can"]), ...mapState(useAbilityStore, ["can"]),
}, },
mounted() { mounted() {
this.fetchNewsletterPrintout(); this.fetchNewsletterPrintout();
this.subscribeMailSendingProgress();
this.subscribePdfPrintingProgress();
}, },
methods: { methods: {
...mapActions(useModalStore, ["openModal"]), ...mapActions(useModalStore, ["openModal"]),
@ -112,6 +100,8 @@ export default defineComponent({
"fetchNewsletterPrintoutById", "fetchNewsletterPrintoutById",
"createNewsletterMailPreview", "createNewsletterMailPreview",
"createNewsletterSend", "createNewsletterSend",
"subscribeMailSendingProgress",
"subscribePdfPrintingProgress",
]), ]),
openPdfShow(filename?: string) { openPdfShow(filename?: string) {
this.openModal( this.openModal(
@ -132,20 +122,6 @@ export default defineComponent({
}) })
.catch(() => {}); .catch(() => {});
}, },
openPdfLogs() {
this.openModal(
markRaw(
defineAsyncComponent(() => import("@/components/admin/club/newsletter/NewsletterPrintingProgressModal.vue"))
)
);
},
openMailLogs() {
this.openModal(
markRaw(
defineAsyncComponent(() => import("@/components/admin/club/newsletter/NewsletterMailProgressModal.vue"))
)
);
},
}, },
}); });
</script> </script>