diff --git a/custom_components/bahmcloud_store/panel/app.js b/custom_components/bahmcloud_store/panel/app.js index 4dc341c..9054b81 100644 --- a/custom_components/bahmcloud_store/panel/app.js +++ b/custom_components/bahmcloud_store/panel/app.js @@ -1,29 +1,86 @@ -async function load() { +async function apiGet() { const r = await fetch("/api/bahmcloud_store", { credentials: "same-origin" }); - const data = await r.json(); + return await r.json(); +} +async function apiPost(payload) { + const r = await fetch("/api/bahmcloud_store", { + method: "POST", + headers: { "Content-Type": "application/json" }, + credentials: "same-origin", + body: JSON.stringify(payload), + }); + return await r.json(); +} + +function el(tag, attrs = {}, children = []) { + const n = document.createElement(tag); + for (const [k, v] of Object.entries(attrs)) { + if (k === "class") n.className = v; + else if (k === "onclick") n.onclick = v; + else n.setAttribute(k, v); + } + for (const c of children) { + n.appendChild(typeof c === "string" ? document.createTextNode(c) : c); + } + return n; +} + +function card(pkg) { + const installedBadge = el("span", { class: "badge" }, [pkg.installed ? "Installed" : "Not installed"]); + + const title = el("div", {}, [ + el("strong", {}, [pkg.name]), + el("div", { class: "muted" }, [pkg.repo]), + ]); + + const ver = el("div", { class: "muted" }, [ + `Installed: ${pkg.installed_version || "-"} | Latest: ${pkg.latest_version || "-"}` + ]); + + const btnInstall = el("button", { + onclick: async () => { + btnInstall.disabled = true; + btnInstall.textContent = "Working..."; + await apiPost({ op: "install", package_id: pkg.id }); + await load(); + } + }, [pkg.installed ? "Reinstall" : "Install"]); + + const btnUpdate = el("button", { + onclick: async () => { + btnUpdate.disabled = true; + btnUpdate.textContent = "Working..."; + await apiPost({ op: "update", package_id: pkg.id }); + await load(); + } + }, ["Update"]); + + // Update-Button nur wenn installiert + btnUpdate.disabled = !pkg.installed; + + const actions = el("div", { class: "actions" }, [btnInstall, btnUpdate]); + + return el("div", { class: "card" }, [ + el("div", { class: "row" }, [title, installedBadge]), + ver, + actions + ]); +} + +async function load() { + const status = document.getElementById("status"); const list = document.getElementById("list"); + + status.textContent = "Loading..."; list.innerHTML = ""; - data.packages.forEach(p => { - const div = document.createElement("div"); - div.className = "card"; - div.innerHTML = ` -
-
- ${p.name} -
${p.repo}
-
-
${p.installed ? "Installed" : "Not installed"}
-
-
- Installed: ${p.installed_version || "-"} | - Latest: ${p.latest_version || "-"} - ${p.release_url ? `| Release` : ""} -
- `; - list.appendChild(div); - }); + const data = await apiGet(); + status.textContent = `Store: ${data.store_url}`; + + for (const pkg of data.packages) { + list.appendChild(card(pkg)); + } } document.getElementById("refresh").onclick = load;