const form = document.getElementById("upload-form"); const titleInput = document.getElementById("title"); const audioInput = document.getElementById("audio"); const submitBtn = document.getElementById("submit-btn"); const uploadProgress = document.getElementById("upload-progress"); const uploadBar = uploadProgress.querySelector(".bar-fill"); const uploadMsg = document.getElementById("upload-msg"); const jobsBody = document.getElementById("jobs-body"); const macStatus = document.getElementById("mac-status"); async function checkMac() { try { const r = await fetch("/api/mac/health"); const j = await r.json(); if (r.ok && j.reachable) { macStatus.textContent = "Mac-Backend: online"; macStatus.classList.add("ok"); macStatus.classList.remove("err"); } else { macStatus.textContent = "Mac-Backend: nicht erreichbar"; macStatus.classList.add("err"); macStatus.classList.remove("ok"); } } catch { macStatus.textContent = "Mac-Backend: Fehler"; macStatus.classList.add("err"); } } function fmtDate(s) { const d = new Date(s); return d.toLocaleString("de-DE", { dateStyle: "short", timeStyle: "medium" }); } const DOWNLOADS = [ { kind: "docx", label: "DOCX", title: "Sitzungsprotokoll als Word-Dokument" }, { kind: "protocol", label: "Protokoll", title: "Strukturiertes Protokoll (JSON)" }, { kind: "summary", label: "Summary", title: "Zusammenfassung (JSON)" }, { kind: "transcript", label: "Transkript", title: "Rohes Transkript (JSON)" }, ]; function escapeHtml(s) { return String(s ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'", }[c])); } function row(job) { const tr = document.createElement("tr"); const title = job.title || job.original_name; const dlCell = document.createElement("td"); dlCell.className = "dl"; DOWNLOADS.forEach(({ kind, label, title: tip }) => { const a = document.createElement("a"); a.className = "btn-dl"; a.textContent = label; a.title = tip; a.href = `/api/jobs/${job.id}/download/${kind}`; if (!job.has[kind]) { a.classList.add("disabled"); a.removeAttribute("href"); a.title = `${tip} — noch nicht verfügbar`; } dlCell.appendChild(a); }); const statusCell = ` ${escapeHtml(job.status)} ${job.error ? `