// jobs.js (Aktivität) — System-Metriken & Hintergrund-Jobs import { $, esc, icon } from "../core/ui.js"; const tracked = new Set(); let JOBS = []; let SYS = null; export function track(id) { tracked.add(id); renderJobs(); } function statusBadge(state) { if (state === "done") return 'fertig'; if (state === "failed") return 'fehler'; return 'lädt…'; } function dotClass(state) { if (state === "done") return "on"; if (state === "failed") return ""; return "load"; } function kpi(cls, title, ic, value, sub) { return `
${title}${icon(ic)}
${value}
${sub}
`; } function kvRow(k, v, cls = "") { return `
${k}${v}
`; } // Chart-Daten (letzte 60 Sekunden, je 3s Polling = 20 Punkte) const hist = { cpu: [], ram: [], gpu: [] }; const MAX_HIST = 20; function renderSys() { if (!SYS) return; const sysV = `${SYS.cpu.percent.toFixed(0)}% CPU`; const sysS = `${SYS.ram.percent.toFixed(0)}% RAM, ${SYS.gpu_temp ? SYS.gpu_temp.toFixed(0)+'°C' : SYS.cpu.temp ? SYS.cpu.temp.toFixed(0)+'°C' : '–'}`; // History aktualisieren hist.cpu.push(SYS.cpu.percent); hist.ram.push(SYS.ram.percent); let gpuP = 0; if (SYS.gpu && SYS.gpu.vram.total) { gpuP = ((SYS.gpu.vram.used + SYS.gpu.gtt.used) / (SYS.gpu.vram.total + SYS.gpu.gtt.total)) * 100; } hist.gpu.push(gpuP); if (hist.cpu.length > MAX_HIST) hist.cpu.shift(); if (hist.ram.length > MAX_HIST) hist.ram.shift(); if (hist.gpu.length > MAX_HIST) hist.gpu.shift(); // Mini-Sparklines generieren const makeBars = (arr, color) => { return '
' + arr.map(v => `
`).join("") + '
'; }; $("#act-kpis").innerHTML = kpi("blue", "CPU Last", "gauge", sysV, sysS) + kpi("purple", "RAM", "monitor", `${SYS.ram.percent.toFixed(0)}%`, "Arbeitsspeicher") + kpi("green", "GPU VRAM", "layers", `${gpuP.toFixed(0)}%`, "Grafikspeicher"); const gb = b => (b / 1024 / 1024 / 1024).toFixed(1); const ramStr = `${gb(SYS.ram.used)} GB / ${gb(SYS.ram.total)} GB`; const gpuStr = (SYS.gpu && SYS.gpu.vram.total) ? `${gb(SYS.gpu.vram.used + SYS.gpu.gtt.used)} GB / ${gb(SYS.gpu.vram.total + SYS.gpu.gtt.total)} GB` : "–"; const diskStr = `${SYS.disk.percent.toFixed(0)}% belegt`; $("#act-sys").innerHTML = `

System-Metriken (Bosgame)

${kvRow("Arbeitsspeicher (RAM)", ramStr)} ${kvRow("Grafikspeicher (VRAM+GTT)", gpuStr)} ${kvRow("Speicherplatz (Disk)", diskStr)} ${kvRow("Temperatur (GPU / CPU)", `${SYS.gpu_temp?.toFixed(1) || '–'}°C / ${SYS.cpu.temp?.toFixed(1) || '–'}°C`)}
CPU Historie
${makeBars(hist.cpu, "act")}
RAM Historie
${makeBars(hist.ram, "purple")}
VRAM Historie
${makeBars(hist.gpu, "on")}
`; } function mount() { $("#v-activity").innerHTML = `

Hintergrund-Aktivitäten

Keine laufenden Jobs.
Downloads, Updates & Co. erscheinen hier mit Live-Log.
`; // Klicks auf Job-Kopf -> auf/zuklappen $("#v-activity").addEventListener("click", e => { const h = e.target.closest(".job-h"); if (!h) return; const id = h.getAttribute("data-id"); tracked.has(id) ? tracked.delete(id) : tracked.add(id); renderJobs(); }); if (SYS) renderSys(); } function renderJobs() { const c = $("#jobs"); if (!c) return; $("#jobs-empty").style.display = JOBS.length ? "none" : "flex"; const failed = JOBS.filter(j => j.state === "failed").length; $("#job-count").textContent = JOBS.length ? (failed ? failed + " Fehler" : JOBS.length + " gesamt") : ""; c.innerHTML = JOBS.map(j => { const open = tracked.has(j.id); const log = open ? `
${esc((j.log || []).join("\\n"))}
` : ""; return `
${esc(j.label)}${statusBadge(j.state)}
${log}
`; }).join(""); } function onJobs(jobs) { JOBS = jobs || []; renderJobs(); } function onSystem(sys) { SYS = sys; const c = $("#act-sys"); if (c) renderSys(); } export default { id: "jobs", mount, onJobs, onSystem };