Button
This commit is contained in:
@@ -29,6 +29,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
|
||||
this._installingRepoId = null;
|
||||
this._updatingRepoId = null;
|
||||
this._uninstallingRepoId = null;
|
||||
this._restartRequired = false;
|
||||
this._lastActionMsg = null;
|
||||
}
|
||||
@@ -141,6 +142,36 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
async _uninstallRepo(repoId) {
|
||||
if (!repoId) return;
|
||||
if (this._installingRepoId || this._updatingRepoId || this._uninstallingRepoId) return;
|
||||
|
||||
const r = this._repoById(repoId);
|
||||
const name = this._safeText(r?.name) || repoId;
|
||||
|
||||
const ok = window.confirm(`Uninstall "${name}"?\n\nThis will delete the integration folder(s) from /config/custom_components. A restart will be required.`);
|
||||
if (!ok) return;
|
||||
|
||||
this._uninstallingRepoId = repoId;
|
||||
this._lastActionMsg = null;
|
||||
this.requestUpdate();
|
||||
|
||||
try {
|
||||
const resp = await this._hass.callApi("post", `bcs/uninstall?repo_id=${encodeURIComponent(repoId)}`, {});
|
||||
if (resp && resp.ok) {
|
||||
this._restartRequired = !!resp.restart_required;
|
||||
this._lastActionMsg = "Uninstalled. Restart required.";
|
||||
} else {
|
||||
this._lastActionMsg = (resp && resp.message) ? String(resp.message) : "Uninstall failed.";
|
||||
}
|
||||
} catch (e) {
|
||||
this._lastActionMsg = e && e.message ? e.message : "Uninstall failed.";
|
||||
} finally {
|
||||
this._uninstallingRepoId = null;
|
||||
await this._load();
|
||||
}
|
||||
}
|
||||
|
||||
async _restartHA() {
|
||||
if (!this._hass) return;
|
||||
try {
|
||||
@@ -436,15 +467,15 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
|
||||
<div class="mobilebar">
|
||||
<div class="left">
|
||||
<div class="iconbtn" id="menuBtn" title="Menu">☰</div>
|
||||
<div class="iconbtn" id="backBtn" title="Back">←</div>
|
||||
<div class="iconbtn" id="menuBtn" title="Menu">鈽<EFBFBD></div>
|
||||
<div class="iconbtn" id="backBtn" title="Back">鈫<EFBFBD></div>
|
||||
<div>
|
||||
<div style="font-weight:700;">Bahmcloud Store</div>
|
||||
<div class="muted small" id="subtitle">Store</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="iconbtn" id="refreshBtn" title="Refresh">⟳</div>
|
||||
<div class="iconbtn" id="refreshBtn" title="Refresh">鉄<EFBFBD></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -506,7 +537,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
: "";
|
||||
|
||||
if (this._loading) {
|
||||
content.innerHTML = `${err}<div class="card">Loading…</div>`;
|
||||
content.innerHTML = `${err}<div class="card">Loading鈥<EFBFBD></div>`;
|
||||
fabs.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
@@ -608,7 +639,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
if (updateAvailable) badges.push("Update");
|
||||
|
||||
const badgeHtml = badges.length
|
||||
? `<div class="badge">${this._esc(badges.join(" · "))}</div>`
|
||||
? `<div class="badge">${this._esc(badges.join(" 路 "))}</div>`
|
||||
: `<div class="badge">${this._esc(this._safeText(r?.provider || "repo"))}</div>`;
|
||||
|
||||
return `
|
||||
@@ -628,7 +659,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
|
||||
return `
|
||||
<div class="filters">
|
||||
<input id="q" placeholder="Search…" value="${this._esc(this._search)}" />
|
||||
<input id="q" placeholder="Search鈥<EFBFBD>" value="${this._esc(this._search)}" />
|
||||
<select id="cat">
|
||||
<option value="all">All categories</option>
|
||||
${categories.map((c) => `<option value="${this._esc(c)}" ${this._category === c ? "selected" : ""}>${this._esc(c)}</option>`).join("")}
|
||||
@@ -640,7 +671,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="muted small">Version: ${this._esc(this._data.version || "-")} · Repositories: ${repos.length}</div>
|
||||
<div class="muted small">Version: ${this._esc(this._data.version || "-")} 路 Repositories: ${repos.length}</div>
|
||||
|
||||
<div class="grid" style="margin-top:12px;">
|
||||
${cards || `<div class="card">No repositories found.</div>`}
|
||||
@@ -713,7 +744,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
].filter(Boolean);
|
||||
|
||||
const readmeBlock = this._readmeLoading
|
||||
? `<div class="card">Loading README…</div>`
|
||||
? `<div class="card">Loading README鈥<EFBFBD></div>`
|
||||
: this._readmeText
|
||||
? `
|
||||
<div class="card">
|
||||
@@ -748,12 +779,14 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
|
||||
const busyInstall = this._installingRepoId === repoId;
|
||||
const busyUpdate = this._updatingRepoId === repoId;
|
||||
const busy = busyInstall || busyUpdate;
|
||||
const busyUninstall = this._uninstallingRepoId === repoId;
|
||||
const busy = busyInstall || busyUpdate || busyUninstall;
|
||||
|
||||
const updateAvailable = installed && !!latestVersion && (!installedVersion || latestVersion !== installedVersion);
|
||||
|
||||
const installBtn = `<button class="primary" id="btnInstall" ${installed || busy ? "disabled" : ""}>${busyInstall ? "Installing…" : installed ? "Installed" : "Install"}</button>`;
|
||||
const updateBtn = `<button class="primary" id="btnUpdate" ${!updateAvailable || busy ? "disabled" : ""}>${busyUpdate ? "Updating…" : updateAvailable ? "Update" : "Up to date"}</button>`;
|
||||
const installBtn = `<button class="primary" id="btnInstall" ${installed || busy ? "disabled" : ""}>${busyInstall ? "Installing鈥<EFBFBD>" : installed ? "Installed" : "Install"}</button>`;
|
||||
const updateBtn = `<button class="primary" id="btnUpdate" ${!updateAvailable || busy ? "disabled" : ""}>${busyUpdate ? "Updating鈥<EFBFBD>" : updateAvailable ? "Update" : "Up to date"}</button>`;
|
||||
const uninstallBtn = `<button id="btnUninstall" ${!installed || busy ? "disabled" : ""}>${busyUninstall ? "Uninstalling鈥<67>" : "Uninstall"}</button>`;
|
||||
|
||||
const restartHint = this._restartRequired
|
||||
? `
|
||||
@@ -777,7 +810,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
<div>
|
||||
<div><strong style="font-size:16px;">${this._esc(name)}</strong></div>
|
||||
<div class="muted">${this._esc(desc)}</div>
|
||||
<div class="muted small" style="margin-top:8px;">${this._esc(infoBits.join(" · "))}</div>
|
||||
<div class="muted small" style="margin-top:8px;">${this._esc(infoBits.join(" 路 "))}</div>
|
||||
<div class="muted small" style="margin-top:8px;">
|
||||
<a href="${this._esc(url)}" target="_blank" rel="noreferrer">Open repository</a>
|
||||
</div>
|
||||
@@ -805,6 +838,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
<div class="row" style="margin-top:14px; gap:10px; flex-wrap:wrap;">
|
||||
${installBtn}
|
||||
${updateBtn}
|
||||
${uninstallBtn}
|
||||
</div>
|
||||
|
||||
${restartHint}
|
||||
@@ -820,6 +854,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
// Always wire action buttons (even if README is already loaded)
|
||||
const btnInstall = root.getElementById("btnInstall");
|
||||
const btnUpdate = root.getElementById("btnUpdate");
|
||||
const btnUninstall = root.getElementById("btnUninstall");
|
||||
const btnRestart = root.getElementById("btnRestart");
|
||||
|
||||
if (btnInstall) {
|
||||
@@ -836,6 +871,13 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
});
|
||||
}
|
||||
|
||||
if (btnUninstall) {
|
||||
btnUninstall.addEventListener("click", () => {
|
||||
if (btnUninstall.disabled) return;
|
||||
if (this._detailRepoId) this._uninstallRepo(this._detailRepoId);
|
||||
});
|
||||
}
|
||||
|
||||
if (btnRestart) {
|
||||
btnRestart.addEventListener("click", () => this._restartHA());
|
||||
}
|
||||
@@ -848,7 +890,7 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
mount.innerHTML = this._readmeHtml;
|
||||
this._postprocessRenderedMarkdown(mount);
|
||||
} else {
|
||||
mount.innerHTML = `<div class="muted">Rendered HTML not available. Use “Show raw Markdown”.</div>`;
|
||||
mount.innerHTML = `<div class="muted">Rendered HTML not available. Use 鈥淪how raw Markdown鈥<EFBFBD>.</div>`;
|
||||
}
|
||||
} else {
|
||||
mount.innerHTML = "";
|
||||
@@ -883,10 +925,10 @@ class BahmcloudStorePanel extends HTMLElement {
|
||||
|
||||
return `
|
||||
<div class="fabs">
|
||||
<button class="fabbtn primary" id="fabOpen" title="Open repository">↗</button>
|
||||
<button class="fabbtn" id="fabReload" title="Reload README">⟳</button>
|
||||
<button class="fabbtn" id="fabInstall" title="${installDisabled ? (installed ? "Already installed" : "Installing…") : "Install"}" ${installDisabled ? "disabled" : ""}>+</button>
|
||||
<button class="fabbtn" id="fabUpdate" title="${updateDisabled ? (!installed ? "Not installed" : "No update available") : "Update"}" ${updateDisabled ? "disabled" : ""}>↑</button>
|
||||
<button class="fabbtn primary" id="fabOpen" title="Open repository">鈫<EFBFBD></button>
|
||||
<button class="fabbtn" id="fabReload" title="Reload README">鉄<EFBFBD></button>
|
||||
<button class="fabbtn" id="fabInstall" title="${installDisabled ? (installed ? "Already installed" : "Installing鈥<EFBFBD>") : "Install"}" ${installDisabled ? "disabled" : ""}>锛<EFBFBD></button>
|
||||
<button class="fabbtn" id="fabUpdate" title="${updateDisabled ? (!installed ? "Not installed" : "No update available") : "Update"}" ${updateDisabled ? "disabled" : ""}>鈫<EFBFBD></button>
|
||||
<button class="fabbtn" id="fabInfo" title="About">i</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user