/* ======================================================================= File: static/js/dashboard.js Purpose: - Sidebar selectie - Start / Abort acties - UI status updates NOTE: - GEEN polling - state_updater.js is leidend ======================================================================= */ console.log("[DASHBOARD] loaded"); /* --------------------------------------------------------- Helpers --------------------------------------------------------- */ async function apiGet(url) { console.log("[DASHBOARD][API] GET", url); try { const r = await fetch(url, { cache: "no-store" }); if (!r.ok) { console.warn("[DASHBOARD][API] GET failed", url, r.status); return null; } return await r.json(); } catch (e) { console.error("[DASHBOARD][API] GET error", url, e); return null; } } function safeUpdateLogs(data) { if (typeof window.updateLogs === "function") { console.log("[DASHBOARD] updateLogs()"); window.updateLogs(data); } } /* --------------------------------------------------------- State --------------------------------------------------------- */ let ACTIVE_BOOK_IDX = null; /* --------------------------------------------------------- DOM READY --------------------------------------------------------- */ document.addEventListener("DOMContentLoaded", () => { console.log("[DASHBOARD] DOMContentLoaded"); bindSidebar(); bindBookCardButtons(); const first = document.querySelector(".book-list-item"); if (first) { console.log("[DASHBOARD] auto-select", first.dataset.bookIdx); selectBook(first.dataset.bookIdx); } }); /* --------------------------------------------------------- Sidebar --------------------------------------------------------- */ function bindSidebar() { console.log("[DASHBOARD] bindSidebar()"); document.querySelectorAll(".book-list-item").forEach((item) => { item.onclick = () => selectBook(item.dataset.bookIdx); }); } function selectBook(bookIdx) { if (!bookIdx || bookIdx === ACTIVE_BOOK_IDX) return; ACTIVE_BOOK_IDX = bookIdx; console.log("[DASHBOARD] selectBook", bookIdx); document.querySelectorAll(".book-list-item").forEach((el) => { el.classList.toggle("active", el.dataset.bookIdx === bookIdx); }); refreshBook(bookIdx); } /* --------------------------------------------------------- Book refresh (NO POLLING) --------------------------------------------------------- */ async function refreshBook(bookIdx) { console.log("[DASHBOARD] refreshBook", bookIdx); const logs = await apiGet(`/api/book/${bookIdx}/logs`); if (logs) safeUpdateLogs(logs); refreshBookCards(); } /* --------------------------------------------------------- Bookcard buttons --------------------------------------------------------- */ function bindBookCardButtons() { console.log("[DASHBOARD] bindBookCardButtons()"); document.querySelectorAll(".icon-start").forEach((btn) => { if (btn.dataset.bound) return; btn.dataset.bound = "1"; btn.onclick = (e) => { e.preventDefault(); const card = btn.closest(".book-card"); if (!card) return; startBook(card.dataset.bookIdx); }; }); document.querySelectorAll(".icon-abort").forEach((btn) => { if (btn.dataset.bound) return; btn.dataset.bound = "1"; btn.onclick = (e) => { e.preventDefault(); const card = btn.closest(".book-card"); if (!card) return; abortBook(card.dataset.bookIdx); }; }); } /* --------------------------------------------------------- START --------------------------------------------------------- */ function startBook(bookIdx) { console.log("[DASHBOARD] START", bookIdx); fetch("/start", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: `book_idx=${bookIdx}`, }).then(() => refreshBook(bookIdx)); } /* --------------------------------------------------------- ABORT --------------------------------------------------------- */ function abortBook(bookIdx) { if (!confirm(`Abort book ${bookIdx}?`)) return; console.log("[DASHBOARD] ABORT", bookIdx); fetch(`/abort/${bookIdx}`, { method: "POST" }).then(() => refreshBook(bookIdx) ); } /* --------------------------------------------------------- Bookcard UI refresh (non-progress) --------------------------------------------------------- */ async function refreshBookCards() { console.log("[DASHBOARD] refreshBookCards()"); const books = await apiGet("/api/books"); if (!books) return; document.querySelectorAll(".book-card").forEach((card) => { const idx = card.dataset.bookIdx; const info = books.find((b) => b.book_idx === idx); if (!info) return; console.log("[DASHBOARD] card status", idx, info.status); card.className = `book-card ${info.status}`; const abortBtn = card.querySelector(".icon-abort"); if (abortBtn) { abortBtn.disabled = ![ "processing", "downloading", "parsing", "audio", ].includes(info.status); } }); }