Revert "Submit GUI commands without page navigation"
This reverts commit 0da5377ff2.
This commit is contained in:
@@ -129,174 +129,6 @@ function refreshSnapshot(button) {
|
||||
}, SNAPSHOT_REFRESH_DELAY_MS);
|
||||
}
|
||||
|
||||
function actionContainerById(actionId) {
|
||||
for (const container of document.querySelectorAll("[data-action-id]")) {
|
||||
if (container.dataset.actionId === actionId) {
|
||||
return container;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function actionStatusForForm(form) {
|
||||
return form.closest(".action-control, .global-action")?.querySelector("[data-action-status]");
|
||||
}
|
||||
|
||||
function showActionMessage(form, message, type = "success") {
|
||||
const status = actionStatusForForm(form);
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
status.textContent = message || "";
|
||||
status.classList.toggle("is-visible", Boolean(message));
|
||||
status.classList.toggle("is-success", type === "success");
|
||||
status.classList.toggle("is-error", type === "error");
|
||||
}
|
||||
|
||||
function setCommandBusy(button, busy) {
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
if (busy) {
|
||||
button.disabled = true;
|
||||
button.classList.add("is-working");
|
||||
button.setAttribute("aria-busy", "true");
|
||||
return;
|
||||
}
|
||||
if (button.dataset.timerLocked !== "true") {
|
||||
button.disabled = false;
|
||||
}
|
||||
button.classList.remove("is-working");
|
||||
button.removeAttribute("aria-busy");
|
||||
}
|
||||
|
||||
function updateStateChip(container, action) {
|
||||
const chip = container.querySelector("[data-state-chip]");
|
||||
if (!chip || !action.state) {
|
||||
return;
|
||||
}
|
||||
const state = String(action.state).toLowerCase();
|
||||
for (const className of Array.from(chip.classList)) {
|
||||
if (className.startsWith("chip-state-")) {
|
||||
chip.classList.remove(className);
|
||||
}
|
||||
}
|
||||
chip.classList.add(`chip-state-${state}`);
|
||||
chip.textContent = action.state_label || chip.dataset[`label${state.charAt(0).toUpperCase()}${state.slice(1)}`] || action.state;
|
||||
}
|
||||
|
||||
function updateTimer(container, action) {
|
||||
const timer = container.querySelector("[data-timer]");
|
||||
if (!timer) {
|
||||
return;
|
||||
}
|
||||
if (action.auto_off_at) {
|
||||
timer.dataset.autoOffAt = String(action.auto_off_at);
|
||||
timer.classList.remove("timer-idle", "timer-expired");
|
||||
updateTimers();
|
||||
return;
|
||||
}
|
||||
delete timer.dataset.autoOffAt;
|
||||
timer.classList.add("timer-idle");
|
||||
timer.classList.remove("timer-expired");
|
||||
timer.textContent = timer.dataset.idleLabel || "";
|
||||
}
|
||||
|
||||
function updateOnButtonLock(container, action) {
|
||||
const button = container.querySelector(".cmd-on");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
if (action.auto_off_at) {
|
||||
const label = button.dataset.disabledLabel || "Already active until automatic turn-off";
|
||||
button.dataset.timerLocked = "true";
|
||||
button.disabled = true;
|
||||
button.title = label;
|
||||
button.setAttribute("aria-label", label);
|
||||
return;
|
||||
}
|
||||
delete button.dataset.timerLocked;
|
||||
if (!button.classList.contains("is-working")) {
|
||||
button.disabled = false;
|
||||
}
|
||||
button.removeAttribute("title");
|
||||
button.removeAttribute("aria-label");
|
||||
}
|
||||
|
||||
function applyActionState(action) {
|
||||
if (!action?.id) {
|
||||
return;
|
||||
}
|
||||
const container = actionContainerById(action.id);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
updateStateChip(container, action);
|
||||
updateTimer(container, action);
|
||||
updateOnButtonLock(container, action);
|
||||
}
|
||||
|
||||
function applyActionPayload(payload) {
|
||||
if (Array.isArray(payload.actions)) {
|
||||
payload.actions.forEach(applyActionState);
|
||||
return;
|
||||
}
|
||||
applyActionState(payload.action);
|
||||
}
|
||||
|
||||
function refreshSnapshotForCommand(form) {
|
||||
const button = form.closest(".camera-card")?.querySelector(".snapshot-refresh");
|
||||
if (!button || button.classList.contains("is-refreshing")) {
|
||||
return;
|
||||
}
|
||||
refreshSnapshot(button);
|
||||
}
|
||||
|
||||
async function responseJson(response) {
|
||||
const text = await response.text();
|
||||
if (!text) {
|
||||
return {};
|
||||
}
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (_error) {
|
||||
return { ok: false, message: text };
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCommandSubmit(form, event) {
|
||||
event.preventDefault();
|
||||
if (form.dataset.requiresAck === "true") {
|
||||
const message = form.dataset.ackMessage || "Confirm this action";
|
||||
if (!window.confirm(message)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const button = form.querySelector(".cmd");
|
||||
if (button?.classList.contains("is-working")) {
|
||||
return;
|
||||
}
|
||||
showActionMessage(form, form.dataset.workingLabel || "Sending command...", "success");
|
||||
setCommandBusy(button, true);
|
||||
try {
|
||||
const response = await fetch(form.action, {
|
||||
method: "POST",
|
||||
headers: { Accept: "application/json" },
|
||||
});
|
||||
const payload = await responseJson(response);
|
||||
if (!response.ok || payload.ok === false) {
|
||||
throw new Error(payload.message || form.dataset.failedLabel || "Command failed.");
|
||||
}
|
||||
applyActionPayload(payload);
|
||||
showActionMessage(form, payload.message || form.dataset.successLabel || "Command sent.", "success");
|
||||
refreshSnapshotForCommand(form);
|
||||
} catch (error) {
|
||||
showActionMessage(form, error.message || form.dataset.failedLabel || "Command failed.", "error");
|
||||
} finally {
|
||||
setCommandBusy(button, false);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", (event) => {
|
||||
const button = event.target.closest(".snapshot-refresh");
|
||||
if (!(button instanceof HTMLButtonElement)) {
|
||||
@@ -314,10 +146,13 @@ document.addEventListener("submit", (event) => {
|
||||
handleRefreshSubmit(form, event);
|
||||
return;
|
||||
}
|
||||
if (form.classList.contains("command-form")) {
|
||||
handleCommandSubmit(form, event);
|
||||
if (form.dataset.requiresAck !== "true") {
|
||||
return;
|
||||
}
|
||||
const message = form.dataset.ackMessage || "Confirm this action";
|
||||
if (!window.confirm(message)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
updateTimers();
|
||||
|
||||
Reference in New Issue
Block a user