From 16a9b9c43614a68bf12b552dd6546f8f191ed8dd Mon Sep 17 00:00:00 2001 From: claude-dev Date: Sat, 25 Jul 2026 21:37:14 +0000 Subject: [PATCH] refactor(dashboard): Kachel Artikel-Uebersetzung entfernt Die Kachel wird nicht mehr gebraucht, die Uebersetzungs-Einstellungen im Monitor bleiben unveraendert (global TRANSLATOR_ENABLED=false, Override pro Organisation weiterhin wirksam). - Markup der Karte translationCard aus dashboard.html entfernt. - Zugehoerigen JS-Block aus app.js entfernt (setupTranslation, renderTranslation, loadTranslationStatus, pollTranslation, startTranslation, cancelTranslation, formatDuration) samt der drei Aufrufstellen beim Start und beim Wechsel auf den Dashboard-Tab. Die API-Endpoints unter /api/translation und translation_agent.py bleiben bestehen, sie haben jetzt nur keine Oberflaeche mehr. Co-Authored-By: Claude Opus 5 (1M context) --- src/static/dashboard.html | 26 ------- src/static/js/app.js | 148 -------------------------------------- 2 files changed, 174 deletions(-) diff --git a/src/static/dashboard.html b/src/static/dashboard.html index cd74936..c399afe 100644 --- a/src/static/dashboard.html +++ b/src/static/dashboard.html @@ -76,32 +76,6 @@ - - -
-
-

Artikel-Übersetzung

-
-
-

- Die automatische Übersetzung im Monitor ist deaktiviert. Hier lassen sich - fremdsprachige Artikel ohne deutsche Fassung manuell übersetzen. -

-

Status wird geladen…

- - - -
- - -
-
-
diff --git a/src/static/js/app.js b/src/static/js/app.js index d4a06eb..b9ecdac 100644 --- a/src/static/js/app.js +++ b/src/static/js/app.js @@ -130,11 +130,9 @@ document.addEventListener("DOMContentLoaded", () => { setupNavTabs(); setupOrgDetailTabs(); setupForms(); - setupTranslation(); loadDashboard(); loadTariffInfo(); loadDashboardTokenStats(); - loadTranslationStatus(); loadOrgs(); }); @@ -154,7 +152,6 @@ function setupNavTabs() { document.querySelectorAll(".app-content > .section").forEach(s => s.classList.remove("active")); document.getElementById(`sec-${section}`).classList.add("active"); - if (section === "dashboard") loadTranslationStatus(); if (section === "audit" && typeof loadAudit === "function") loadAudit(); }); }); @@ -918,151 +915,6 @@ function formatDate(iso) { } -// ===== Artikel-Übersetzung ===== -let translationPollTimer = null; - -function setupTranslation() { - const runBtn = document.getElementById("translationRunBtn"); - const cancelBtn = document.getElementById("translationCancelBtn"); - if (runBtn) runBtn.addEventListener("click", startTranslation); - if (cancelBtn) cancelBtn.addEventListener("click", cancelTranslation); -} - -function formatDuration(seconds) { - seconds = Math.max(0, Math.round(seconds || 0)); - if (seconds < 60) return seconds + " Sek."; - const min = Math.round(seconds / 60); - if (min < 60) return min + " Min."; - const h = Math.floor(min / 60), m = min % 60; - return h + " Std. " + (m ? m + " Min." : "").trim(); -} - -function renderTranslation(st) { - const info = document.getElementById("translationInfo"); - const wrap = document.getElementById("translationProgressWrap"); - const bar = document.getElementById("translationProgressBar"); - const ptext = document.getElementById("translationProgressText"); - const runBtn = document.getElementById("translationRunBtn"); - const cancelBtn = document.getElementById("translationCancelBtn"); - if (!info || !runBtn) return; - - if (st.running) { - runBtn.style.display = "none"; - cancelBtn.style.display = ""; - wrap.style.display = ""; - const pct = st.total > 0 ? Math.round((st.done / st.total) * 100) : 0; - bar.style.width = pct + "%"; - ptext.textContent = `${st.done} / ${st.total} verarbeitet, ${st.translated} übersetzt (${pct}%)`; - info.textContent = "Übersetzung läuft…"; - return; - } - - runBtn.style.display = ""; - cancelBtn.style.display = "none"; - wrap.style.display = "none"; - - let resultLine = ""; - if (st.finished_at && (st.total > 0 || st.error)) { - if (st.error) { - resultLine = `Letzter Lauf mit Fehler beendet: ${st.error}. `; - } else if (st.cancelled) { - resultLine = `Letzter Lauf abgebrochen, ${st.translated} von ${st.total} Artikeln übersetzt. `; - } else { - resultLine = `Letzter Lauf abgeschlossen, ${st.translated} Artikel übersetzt. `; - } - } - - if (st.pending > 0) { - const est = st.estimate || {}; - info.textContent = resultLine + - `${st.pending} Artikel ohne deutsche Übersetzung. ` + - `Geschätzt: ${formatDuration(est.seconds)}, ca. $${est.cost_usd}.`; - runBtn.disabled = false; - } else { - info.textContent = resultLine + "Alle Artikel sind übersetzt."; - runBtn.disabled = true; - } -} - -async function loadTranslationStatus() { - try { - const st = await API.get("/api/translation/status"); - renderTranslation(st); - if (st.running && !translationPollTimer) { - translationPollTimer = setInterval(pollTranslation, 3000); - } - } catch (e) { - const info = document.getElementById("translationInfo"); - if (info) info.textContent = "Status nicht abrufbar: " + (e.message || e); - } -} - -async function pollTranslation() { - try { - const st = await API.get("/api/translation/status"); - renderTranslation(st); - if (!st.running) { - clearInterval(translationPollTimer); - translationPollTimer = null; - if (st.error) { - showToast("Übersetzung mit Fehler beendet", "error"); - } else if (st.cancelled) { - showToast(`Übersetzung abgebrochen, ${st.translated} übersetzt`, "info"); - } else { - showToast(`Übersetzung fertig: ${st.translated} Artikel`, "success"); - } - } - } catch (e) { - console.warn("Translation-Poll fehlgeschlagen:", e); - } -} - -async function startTranslation() { - let st; - try { - st = await API.get("/api/translation/status"); - } catch (e) { - showToast(e.message || "Status nicht abrufbar", "error"); - return; - } - if (st.running) { showToast("Es läuft bereits eine Übersetzung", "info"); return; } - if (!st.pending) { showToast("Es gibt nichts zu übersetzen", "info"); return; } - - const est = st.estimate || {}; - const ok = await showConfirm( - "Übersetzung starten", - `${st.pending} Artikel werden ins Deutsche übersetzt. ` + - `Geschätzte Dauer: ${formatDuration(est.seconds)}, geschätzte Kosten: ca. $${est.cost_usd}. ` + - `Der Lauf kann jederzeit abgebrochen werden.` - ); - if (!ok) return; - - try { - const res = await API.post("/api/translation/run", {}); - if (res && res.status === "started") { - showToast(`Übersetzung gestartet (${res.pending} Artikel)`, "success"); - await loadTranslationStatus(); - if (!translationPollTimer) { - translationPollTimer = setInterval(pollTranslation, 3000); - } - } else { - showToast("Es gibt nichts zu übersetzen", "info"); - loadTranslationStatus(); - } - } catch (e) { - showToast(e.message || "Start fehlgeschlagen", "error"); - } -} - -async function cancelTranslation() { - try { - await API.post("/api/translation/cancel", {}); - showToast("Übersetzung wird abgebrochen…", "info"); - } catch (e) { - showToast(e.message || "Abbruch fehlgeschlagen", "error"); - } -} - // ===== Token-Nutzung ===== async function loadOrgTokenUsage(orgId) { try {