Fix hanging document mailbox imports

This commit is contained in:
2026-08-10 15:16:42 +02:00
parent 49cbc9314e
commit 5181ecc9f3
3 changed files with 100 additions and 26 deletions

View File

@@ -13,6 +13,13 @@ type ImportSource = {
hasPassword: boolean
lastSyncedAt?: string | null
lastError?: string | null
isSyncing: boolean
progress?: {
processed: number
total: number
imported: number
duplicates: number
} | null
}
const api = useNuxtApp().$api
@@ -23,6 +30,7 @@ const saving = ref(false)
const activeAction = ref<string | null>(null)
const editingId = ref<string | null>(null)
const showForm = ref(false)
let pollTimer: ReturnType<typeof setTimeout> | null = null
const emptyForm = () => ({
name: "",
@@ -38,23 +46,33 @@ const emptyForm = () => ({
})
const form = ref(emptyForm())
const load = async () => {
loading.value = true
const load = async (silent = false) => {
loading.value = sources.value.length === 0
try {
const result = await api<ImportSource[]>("/api/document-imports")
sources.value = Array.isArray(result) ? result : []
} catch (error: any) {
sources.value = []
toast.add({
title: "Importquellen konnten nicht geladen werden",
description: error?.data?.error || error?.message || "Bitte versuche es später erneut.",
color: "error",
})
if (!silent) {
toast.add({
title: "Importquellen konnten nicht geladen werden",
description: error?.data?.error || error?.message || "Bitte versuche es später erneut.",
color: "error",
})
}
} finally {
loading.value = false
}
}
const pollWhileSyncing = () => {
if (pollTimer || !sources.value.some(source => source.isSyncing)) return
pollTimer = setTimeout(async () => {
pollTimer = null
await load(true)
pollWhileSyncing()
}, 2000)
}
const create = () => {
editingId.value = null
form.value = emptyForm()
@@ -100,6 +118,13 @@ const runAction = async (id: string, action: "test" | "sync") => {
activeAction.value = `${id}:${action}`
try {
const result = await api(`/api/document-imports/${id}/${action}`, { method: "POST" })
if (action === "sync" && result.started) {
const source = sources.value.find(item => item.id === id)
if (source) source.isSyncing = true
toast.add({ title: "Import gestartet", description: "Die Nachrichten werden im Hintergrund verarbeitet.", color: "success" })
pollWhileSyncing()
return
}
toast.add({
title: action === "test" ? "Verbindung erfolgreich" : "Import abgeschlossen",
description: action === "test"
@@ -120,7 +145,13 @@ const runAction = async (id: string, action: "test" | "sync") => {
}
}
onMounted(load)
onMounted(async () => {
await load()
pollWhileSyncing()
})
onBeforeUnmount(() => {
if (pollTimer) clearTimeout(pollTimer)
})
</script>
<template>
@@ -160,6 +191,9 @@ onMounted(load)
<p v-if="source.lastSyncedAt" class="mt-1 text-xs text-dimmed">
Zuletzt synchronisiert: {{ new Date(source.lastSyncedAt).toLocaleString('de-DE') }}
</p>
<p v-if="source.isSyncing" class="mt-1 text-sm text-primary">
Import läuft<span v-if="source.progress">: {{ source.progress.processed }} von {{ source.progress.total }} Nachrichten verarbeitet</span>
</p>
<p v-if="source.lastError" class="mt-1 text-sm text-error">{{ source.lastError }}</p>
</div>
<div class="flex shrink-0 flex-wrap gap-2">
@@ -172,8 +206,8 @@ onMounted(load)
>Testen</UButton>
<UButton
icon="i-heroicons-arrow-path"
:loading="activeAction === `${source.id}:sync`"
:disabled="!source.enabled"
:loading="activeAction === `${source.id}:sync` || source.isSyncing"
:disabled="!source.enabled || source.isSyncing"
@click="runAction(source.id, 'sync')"
>Jetzt importieren</UButton>
<UButton color="neutral" variant="ghost" icon="i-heroicons-pencil-square" @click="edit(source)" />