Compare commits
2
Commits
ae035c3fd4
...
93a81fd82c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93a81fd82c | ||
|
|
357888e310 |
+26
-9
@@ -1313,14 +1313,35 @@
|
|||||||
|
|
||||||
// ---- Main render -------------------------------------------------------
|
// ---- Main render -------------------------------------------------------
|
||||||
|
|
||||||
|
function iconArrowLeft() {
|
||||||
|
const s = el("span", { class: "icon" });
|
||||||
|
s.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>';
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function wsIndicator() {
|
||||||
|
state.wsDot = el("span", { class: "connection-status " + (state.wsOnline ? "online" : "offline") });
|
||||||
|
state.wsText = el("span", { class: "muted" }, state.wsOnline ? t("online") : t("offline"));
|
||||||
|
return el("span", { class: "ws-indicator" }, state.wsDot, state.wsText);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateWsIndicator() {
|
||||||
|
if (state.wsDot) {
|
||||||
|
state.wsDot.classList.toggle("online", state.wsOnline);
|
||||||
|
state.wsDot.classList.toggle("offline", !state.wsOnline);
|
||||||
|
}
|
||||||
|
if (state.wsText) state.wsText.textContent = state.wsOnline ? t("online") : t("offline");
|
||||||
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
clearNode(root);
|
clearNode(root);
|
||||||
const backBtn = el("button", { class: "ghost",
|
const backBtn = el("button", { class: "ghost btn-back",
|
||||||
onclick: () => { if (state.ws) { state.ws.close(); state.ws = null; } navigate("competitions"); } },
|
onclick: () => { if (state.ws) { state.ws.close(); state.ws = null; } navigate("competitions"); } },
|
||||||
"← " + t("back"));
|
iconArrowLeft(), t("back"));
|
||||||
root.appendChild(renderTopbar(user, { extra: backBtn }));
|
root.appendChild(renderTopbar(user, { extra: wsIndicator() }));
|
||||||
|
|
||||||
const container = el("div", { class: "container" });
|
const container = el("div", { class: "container" });
|
||||||
|
container.appendChild(backBtn);
|
||||||
container.appendChild(el("div", { class: "row", style: { justifyContent: "space-between", marginBottom: "0.5rem" } },
|
container.appendChild(el("div", { class: "row", style: { justifyContent: "space-between", marginBottom: "0.5rem" } },
|
||||||
el("h2", { style: { margin: 0 } },
|
el("h2", { style: { margin: 0 } },
|
||||||
state.competition.name,
|
state.competition.name,
|
||||||
@@ -1329,10 +1350,6 @@
|
|||||||
isClosed() ? " " : null,
|
isClosed() ? " " : null,
|
||||||
isClosed() ? el("span", { class: "badge warn" }, t("closed")) : null,
|
isClosed() ? el("span", { class: "badge warn" }, t("closed")) : null,
|
||||||
),
|
),
|
||||||
el("div", { class: "row" },
|
|
||||||
el("span", { class: "connection-status " + (state.wsOnline ? "online" : "offline") }),
|
|
||||||
el("span", { class: "muted" }, state.wsOnline ? t("online") : t("offline")),
|
|
||||||
),
|
|
||||||
));
|
));
|
||||||
|
|
||||||
const tabs = el("div", { class: "tabs" });
|
const tabs = el("div", { class: "tabs" });
|
||||||
@@ -1393,8 +1410,8 @@
|
|||||||
|
|
||||||
await loadAll();
|
await loadAll();
|
||||||
state.ws = openCompetitionWS(competitionId, {
|
state.ws = openCompetitionWS(competitionId, {
|
||||||
onopen: () => { state.wsOnline = true; const e = document.querySelector(".connection-status"); if (e) { e.classList.add("online"); e.classList.remove("offline"); } },
|
onopen: () => { state.wsOnline = true; updateWsIndicator(); },
|
||||||
onclose: () => { state.wsOnline = false; const e = document.querySelector(".connection-status"); if (e) { e.classList.remove("online"); e.classList.add("offline"); } },
|
onclose: () => { state.wsOnline = false; updateWsIndicator(); },
|
||||||
onmessage: handleWSMessage,
|
onmessage: handleWSMessage,
|
||||||
});
|
});
|
||||||
render();
|
render();
|
||||||
|
|||||||
+22
-1
@@ -387,11 +387,32 @@ tbody tr.transferred { background: #f3f6fb; }
|
|||||||
height: 8px;
|
height: 8px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #d1d5db;
|
background: #d1d5db;
|
||||||
margin-right: 0.5rem;
|
flex: none;
|
||||||
}
|
}
|
||||||
.connection-status.online { background: #10b981; }
|
.connection-status.online { background: #10b981; }
|
||||||
.connection-status.offline { background: #ef4444; }
|
.connection-status.offline { background: #ef4444; }
|
||||||
|
|
||||||
|
.ws-indicator {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
/* Optically drop the dot ~1px: an all-caps label (Online/Offline) has
|
||||||
|
unused descender space, so its glyphs sit above the flex centre line. */
|
||||||
|
.ws-indicator .connection-status { position: relative; top: 1px; }
|
||||||
|
|
||||||
|
.btn-back {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
padding-left: 0.3rem;
|
||||||
|
}
|
||||||
|
.icon { display: inline-flex; }
|
||||||
|
.icon svg { display: block; }
|
||||||
|
|
||||||
textarea { resize: vertical; min-height: 60px; }
|
textarea { resize: vertical; min-height: 60px; }
|
||||||
|
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
|
|||||||
Reference in New Issue
Block a user