139 lines
4.0 KiB
JavaScript
139 lines
4.0 KiB
JavaScript
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();
|