Lumi/plugins/throne_wishlist/public/debug-modal.js
2026-06-10 18:57:38 +02:00

132 lines
4.3 KiB
JavaScript

(() => {
const modal = document.querySelector("[data-debug-modal]");
const openButton = document.querySelector("[data-debug-open]");
const closeButton = modal?.querySelector("[data-debug-close]");
const status = modal?.querySelector("[data-debug-status]");
const page = modal?.querySelector("[data-debug-page]");
const slider = modal?.querySelector("[data-debug-slider]");
const previous = modal?.querySelector("[data-debug-prev]");
const next = modal?.querySelector("[data-debug-next]");
const summary = modal?.querySelector("[data-debug-summary]");
const json = modal?.querySelector("[data-debug-json]");
const items = [];
let current = -1;
let sessionId = null;
let source = null;
const render = () => {
const total = items.length;
if (!total) {
current = -1;
page.textContent = "0 / 0";
slider.min = "1";
slider.max = "1";
slider.value = "1";
slider.disabled = true;
previous.disabled = true;
next.disabled = true;
summary.textContent = "No payloads received during this session.";
json.textContent = "{}";
return;
}
current = Math.max(0, Math.min(current, total - 1));
const item = items[current];
page.textContent = `${current + 1} / ${total}`;
slider.min = "1";
slider.max = String(total);
slider.value = String(current + 1);
slider.disabled = false;
previous.disabled = current === 0;
next.disabled = current === total - 1;
summary.innerHTML = "";
[
`Endpoint: ${item.endpointIdentifier}`,
`Event: ${item.eventType || "unknown"}`,
`Event ID: ${item.eventId || "none"}`,
`Authenticity: ${item.authentic ? "valid" : item.authenticityStatus}`
].forEach((text) => {
const line = document.createElement("div");
line.textContent = text;
summary.appendChild(line);
});
json.textContent = JSON.stringify(item.payload || {
raw_body_preview: item.rawBodyPreview
}, null, 2);
};
const stop = async () => {
source?.close();
source = null;
if (sessionId) {
navigator.sendBeacon?.(`/plugins/throne_wishlist/debug/stop/${sessionId}`);
sessionId = null;
}
};
const close = async () => {
await stop();
modal.classList.remove("is-open");
modal.setAttribute("aria-hidden", "true");
};
const open = async () => {
items.length = 0;
current = -1;
render();
modal.classList.add("is-open");
modal.setAttribute("aria-hidden", "false");
status.textContent = "Starting debug session…";
try {
const response = await fetch("/plugins/throne_wishlist/debug/start", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" }
});
if (!response.ok) throw new Error("Unable to start debug session.");
const data = await response.json();
sessionId = data.sessionId;
source = new EventSource(`/plugins/throne_wishlist/debug/stream/${sessionId}`);
source.addEventListener("ready", () => {
status.textContent = "Listening for new Throne payloads.";
});
source.addEventListener("payload", (event) => {
items.push(JSON.parse(event.data));
current = items.length - 1;
status.textContent = "Payload received.";
render();
});
source.addEventListener("close", (event) => {
const data = JSON.parse(event.data || "{}");
status.textContent = `Debug session ended: ${data.reason || "closed"}.`;
source?.close();
});
source.onerror = () => {
status.textContent = "Debug stream disconnected.";
};
} catch (error) {
status.textContent = error.message;
}
};
openButton?.addEventListener("click", open);
closeButton?.addEventListener("click", close);
modal?.addEventListener("click", (event) => {
if (event.target === modal) close();
});
previous?.addEventListener("click", () => {
current -= 1;
render();
});
next?.addEventListener("click", () => {
current += 1;
render();
});
slider?.addEventListener("input", () => {
current = Number(slider.value) - 1;
render();
});
window.addEventListener("keydown", (event) => {
if (event.key === "Escape" && modal?.classList.contains("is-open")) close();
});
window.addEventListener("beforeunload", stop);
})();