// news.js — News-Board (v6): Magazin-Layout + „Für dich: Upgrades". import { api, getHfToken } from "../core/api.js"; import { $, esc, ago, toast } from "../core/ui.js"; let UPS = []; const fitCls = l => l === "perfect" ? "ok" : l === "marginal" ? "warn" : "bad"; function mount() { $(".view[data-view='news']").innerHTML = `

News

Aktuelles aus der Local-LLM-Welt — aus kuratierten Quellen (HuggingFace, r/LocalLLaMA, Latent Space, Ahead of AI …).
Lade News…
`; $("#news-refresh").addEventListener("click", () => { load(); loadUpgrades(); }); load(); loadUpgrades(); } // ---- Upgrade-Vorschläge ---- function upRow(u, i) { return `
${esc(u.name)} ${esc(u.fit.text)}
Ersetzt dein „${esc(u.old)}". ${esc(u.why)}
`; } async function loadUpgrades() { const el = $("#upgrades"); if (!el) return; try { UPS = (await api("/api/cookbook/upgrades")).upgrades || []; if (!UPS.length) { el.innerHTML = ""; return; } el.innerHTML = `

Für dich: Upgrades

${UPS.length}
Neuere Modelle, die ein installiertes ersetzen können — mit Begründung.
${UPS.map(upRow).join("")}
`; el.querySelectorAll("[data-up]").forEach(b => b.addEventListener("click", () => installUpgrade(+b.getAttribute("data-up"), b))); } catch { el.innerHTML = ""; } } async function installUpgrade(i, btn) { const u = UPS[i]; if (!u) return; btn.disabled = true; btn.textContent = "Starte…"; try { await api("/api/cookbook/install-model", { method: "POST", body: JSON.stringify({ repo: u.repo, role: u.role, params_b: u.params_b, quant: u.quant, hf_token: getHfToken() }) }); toast(`„${u.name}" wird installiert — ersetzt „${u.old}". Siehe Aktivität.`); document.querySelector(".nav-item[data-view='activity']")?.click(); } catch (e) { toast("Fehler: " + e.message, true); btn.disabled = false; btn.textContent = "Installieren"; } } // ---- News (Magazin-Layout) ---- function newsCard(n, featured) { const date = n.ts ? ago(n.ts) : ""; const rel = n.relevant ? `für dich` : ""; return `
${esc(n.source)}${rel}${esc(date)}
${esc(n.title)}
`; } async function load() { const el = $("#news-list"); if (!el) return; el.innerHTML = `
Lade News… (erstes Laden kann kurz dauern)
`; try { const items = (await api("/api/news")).items || []; el.innerHTML = items.length ? `
${items.map((n, i) => newsCard(n, i === 0)).join("")}
` : `
Keine News geladen
Die Quellen sind gerade nicht erreichbar — später nochmal probieren.
`; } catch (e) { el.innerHTML = `
${esc(e.message)}
`; } } export default { id: "news", mount };