55 lines
1.7 KiB
JavaScript
55 lines
1.7 KiB
JavaScript
(() => {
|
|
const list = document.querySelector(".status-list");
|
|
if (!list) return;
|
|
|
|
const esc = (value) => String(value ?? "").replace(/[&<>"']/g, (ch) => ({
|
|
"&": "&",
|
|
"<": "<",
|
|
">": ">",
|
|
"\"": """,
|
|
"'": "'",
|
|
}[ch]));
|
|
|
|
const players = (value) => {
|
|
const n = Number(value || 0);
|
|
return `${n.toLocaleString()} ${n === 1 ? "Player" : "Players"}`;
|
|
};
|
|
|
|
const render = (data) => {
|
|
const servers = Array.isArray(data?.servers) ? data.servers : [];
|
|
if (!servers.length) return;
|
|
|
|
list.classList.add("status-list--regions");
|
|
list.innerHTML = servers.map((server) => `
|
|
<div class="status-region" role="group" aria-label="${esc(server.label)} player counts">
|
|
<div class="status-row status-parent status-server" role="listitem">
|
|
<span>${esc(server.label)}</span><span>${players(server.players)}</span>
|
|
</div>
|
|
${(server.ships || []).map((ship) => `
|
|
<div class="status-row status-parent status-ship" role="listitem">
|
|
<span>${esc(ship.label)}</span><span></span>
|
|
</div>
|
|
${(ship.rows || []).map((row) => `
|
|
<div class="status-row status-child" role="listitem">
|
|
<span>${esc(row.label)}</span><span>${players(row.players)}</span>
|
|
</div>
|
|
`).join("")}
|
|
`).join("")}
|
|
</div>
|
|
`).join("");
|
|
};
|
|
|
|
const loadStatus = (url) => fetch(url, { cache: "no-store" })
|
|
.then((res) => {
|
|
if (!res.ok) {
|
|
throw new Error(`status ${res.status}`);
|
|
}
|
|
return res.json();
|
|
});
|
|
|
|
loadStatus(`/server-status.json?ts=${Date.now()}`)
|
|
.catch(() => loadStatus("/api/server-status"))
|
|
.then((data) => data && render(data))
|
|
.catch(() => {});
|
|
})();
|