Files
logwisp/internal/sink/http/web/view.js
T

68 lines
2.3 KiB
JavaScript

import { logout } from "./scram.js";
const base = new URL("..", location.href);
// The server writes its status path here, relative to the mount
const statusPath = document.querySelector('meta[name="logwisp-status"]').content;
const MAX_LINES = 5000;
const log = document.getElementById("log");
const state = document.getElementById("state");
let source = null;
function append(line) {
const atBottom = log.scrollTop + log.clientHeight >= log.scrollHeight - 4;
const row = document.createElement("div");
row.textContent = line;
log.append(row);
while (log.childElementCount > MAX_LINES) log.firstElementChild.remove();
if (atBottom) log.scrollTop = log.scrollHeight;
}
// The status answer names the stream path; its 401 is the only way to tell an
// expired session apart, since EventSource hides the status of a failure.
async function connect() {
let res;
try {
res = await fetch(new URL("./" + statusPath, base), { credentials: "same-origin", cache: "no-store", redirect: "error" });
} catch {
return retry("server unreachable");
}
if (res.status === 401) {
location.replace(new URL("login?next=view", location.href).href);
return;
}
const path = res.ok ? (await res.json().catch(() => ({})))?.endpoints?.stream : null;
if (typeof path !== "string" || !path.startsWith("/")) {
return retry(`status unavailable (${res.status})`);
}
// Stream paths are absolute in logwisp; the proxy may mount it under a prefix
source = new EventSource(new URL("./" + path.replace(/^\/+/, ""), base));
source.addEventListener("connected", () => { state.textContent = "live"; });
source.addEventListener("disconnect", () => {
source.close();
retry("server shut down");
});
source.onmessage = (event) => event.data.split("\n").forEach(append);
source.onerror = () => {
if (source.readyState === EventSource.CLOSED) retry("disconnected");
else state.textContent = "reconnecting…";
};
}
function retry(reason) {
state.textContent = `${reason}, retrying…`;
setTimeout(connect, 5000);
}
document.getElementById("logout").addEventListener("click", async () => {
source?.close();
try {
await logout(base);
} catch (err) {
state.textContent = err.message;
return;
}
location.replace(new URL("login", location.href).href);
});
connect();