const form = document.getElementById("command-form"); const nameInput = document.getElementById("name"); const commandInput = document.getElementById("command"); const list = document.getElementById("command-list"); const emptyNote = document.getElementById("empty-note"); const statusEl = document.getElementById("status"); const outputEl = document.getElementById("output"); function setStatus(message, kind) { statusEl.textContent = message; statusEl.className = "status" + (kind ? ` ${kind}` : ""); } function showOutput(text) { outputEl.hidden = !text; outputEl.textContent = text || ""; } function formatTerminal(command, output) { const lines = []; if (command) lines.push(`$ ${command}`); if (output) lines.push(output); return lines.join("\n"); } async function api(url, options) { const res = await fetch(url, options); const data = await res.json().catch(() => ({})); if (!res.ok) { const err = new Error(data.error || `Fehler ${res.status}`); err.data = data; throw err; } return data; } function renderCommands(commands) { list.replaceChildren(); emptyNote.hidden = commands.length > 0; for (const cmd of commands) { const li = document.createElement("li"); const info = document.createElement("div"); info.className = "info"; const name = document.createElement("span"); name.className = "name"; name.textContent = cmd.name; const code = document.createElement("code"); code.textContent = cmd.command; info.append(name, code); const actions = document.createElement("div"); actions.className = "actions"; const runBtn = document.createElement("button"); runBtn.type = "button"; runBtn.textContent = "Ausführen"; runBtn.addEventListener("click", () => runCommand(cmd, runBtn)); const delBtn = document.createElement("button"); delBtn.type = "button"; delBtn.className = "delete"; delBtn.textContent = "Löschen"; delBtn.addEventListener("click", () => deleteCommand(cmd, delBtn)); actions.append(runBtn, delBtn); li.append(info, actions); list.append(li); } } async function loadCommands() { try { renderCommands(await api("/api/commands")); } catch (err) { setStatus(`Befehle konnten nicht geladen werden: ${err.message}`, "error"); } } async function runCommand(cmd, button) { button.disabled = true; setStatus(`„${cmd.name}" wird gesendet …`); showOutput(""); try { const result = await api(`/api/commands/${cmd.id}/run`, { method: "POST" }); setStatus( result.ok ? `„${cmd.name}" wurde gesendet.` : `cec-client hat sich mit Exit-Code ${result.exitCode} beendet.`, result.ok ? "ok" : "error" ); showOutput(formatTerminal(result.command, result.output)); } catch (err) { setStatus(`Ausführen fehlgeschlagen: ${err.message}`, "error"); showOutput(formatTerminal(err.data?.command, err.data?.output)); } finally { button.disabled = false; } } async function deleteCommand(cmd, button) { button.disabled = true; try { await api(`/api/commands/${cmd.id}`, { method: "DELETE" }); setStatus(`„${cmd.name}" wurde gelöscht.`, "ok"); await loadCommands(); } catch (err) { setStatus(`Löschen fehlgeschlagen: ${err.message}`, "error"); button.disabled = false; } } form.addEventListener("submit", async (event) => { event.preventDefault(); const submitBtn = form.querySelector("button[type=submit]"); submitBtn.disabled = true; try { await api("/api/commands", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: nameInput.value.trim(), command: commandInput.value.trim(), }), }); setStatus(`„${nameInput.value.trim()}" wurde gespeichert.`, "ok"); form.reset(); nameInput.focus(); await loadCommands(); } catch (err) { setStatus(`Speichern fehlgeschlagen: ${err.message}`, "error"); } finally { submitBtn.disabled = false; } }); loadCommands();