aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/dashboard
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/dashboard')
-rw-r--r--src/api/dashboard/dashboard.html41
1 files changed, 36 insertions, 5 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html
index ba2b893..5ba2b84 100644
--- a/src/api/dashboard/dashboard.html
+++ b/src/api/dashboard/dashboard.html
@@ -8,6 +8,9 @@
:root {
--bg: #fafaf9; --fg: #1c1917; --muted: #78716c; --line: #e7e5e4; --panel: #ffffff;
--ok: #15803d; --warn: #c2410c; --bad: #b91c1c; --intended: #a8a29e; --self: #1d4ed8;
+ /* How strong the grey under a console message is, pointed at or shown, and under
+ its nodes and link on the map. */
+ --pointed: .12; --shown: .22;
}
@media (prefers-color-scheme: dark) {
:root {
@@ -96,8 +99,8 @@
/* Of one exchange with the message pointed at or shown (`related`): a lighter grey, and
the bar. */
.console > div.related { background: rgba(127, 127, 127, .08); border-left-color: var(--self); }
- .console > div:hover { background: var(--hover, rgba(127, 127, 127, .12)); }
- .console > div.focused { background: rgba(127, 127, 127, .22); }
+ .console > div:hover { background: rgb(127 127 127 / var(--pointed)); }
+ .console > div.focused { background: rgb(127 127 127 / var(--shown)); }
/* The message takes the box's width and scrolls with it, not in a box of its own. */
#stats pre.message { margin: 4px 0 0; font-size: 12px; white-space: pre-wrap;
max-height: none; overflow: visible; }
@@ -800,6 +803,19 @@ function renderGraph() {
settle();
}
const children = [];
+ // Under everything: the nodes and the link of the message pointed at in the console,
+ // else of the one shown, in the grey its line has there, each in its own shape (the
+ // lines of a link as they bow, a node's circle). One group, so where they overlap
+ // the grey is no darker.
+ const message = pointedMessage || shownMessage;
+ const marks = drawing("marks", "g", { "pointer-events": "none",
+ style: "opacity: var(" + (pointedMessage ? "--pointed" : "--shown") + ")" });
+ const marked = [];
+ const markedKey = message ? pairKey(state.node.id, message.peer) : null;
+ const mark = (tag, attrs) => marked.push(svg(tag, attrs));
+ const markLine = (d, width) => mark("path", { d, fill: "none", stroke: "rgb(127 127 127)",
+ "stroke-width": width + 8, "stroke-linecap": "round" });
+ children.push(marks);
// Behind a link: a halo while it's hovered or in focus (`width`: of its lines).
const halo = (key, p, q, width) => {
if (key !== hovered && key !== focused) return;
@@ -825,6 +841,7 @@ function renderGraph() {
if (measured.has(key)) continue;
const p = positions.get(a), q = positions.get(b);
halo(key, p, q, 1);
+ if (key === markedKey) markLine("M " + p.x + " " + p.y + " L " + q.x + " " + q.y, 1);
children.push(drawing("intended " + key, "line", { x1: p.x, y1: p.y, x2: q.x, y2: q.y,
stroke: "var(--intended)", "stroke-dasharray": "4 4", "stroke-width": 1 }));
tooltip(hit(key, p, q, 1), name(a) + " – " + name(b) + ": intended (member list), not measured");
@@ -874,6 +891,7 @@ function renderGraph() {
} else if (line.used ? link.relayed : line.relayed) {
attrs["stroke-dasharray"] = "7 4";
}
+ if (key === markedKey) markLine(attrs.d, attrs["stroke-width"]);
const drawnLine = drawing("path " + key + " " + i, "path", attrs);
const description = name(a) + " – " + name(b) +
(line.transport ? " via " + line.transport : "") + (line.used ? " (in use)" : "") +
@@ -929,7 +947,11 @@ function renderGraph() {
}
// Dormant as this node sees it (`/peers`): a red outline.
const dormant = (state.peers.peers[id] || {}).status === "dormant";
- const circle = drawing("node " + id, "circle", { cx: p.x, cy: p.y, r: member.self ? 8 : 6,
+ const radius = member.self ? 8 : 6;
+ if (message && (id === state.node.id || id === message.peer)) {
+ mark("circle", { cx: p.x, cy: p.y, r: radius + 6, fill: "rgb(127 127 127)" });
+ }
+ const circle = drawing("node " + id, "circle", { cx: p.x, cy: p.y, r: radius,
fill: member.self ? "var(--self)" : reported ? "var(--fg)" : "var(--panel)",
stroke: member.self ? "var(--self)" : dormant ? "var(--bad)" : "var(--fg)",
"stroke-width": dormant ? 2.5 : 1.5 }, pressed);
@@ -948,6 +970,7 @@ function renderGraph() {
label(nameLabel, name(id));
children.push(circle, ...pin, nameLabel);
}
+ marks.replaceChildren(...marked);
show(document.getElementById("view"), children);
}
@@ -1758,6 +1781,14 @@ const WAYS = { sent: "→", received: "←", refused: "↛" };
// The exchange marked in the console (a message's `related`): the one of the message
// pointed at, else of the one shown; null: none.
let relatedMarked = null;
+// The message pointed at in the console, if any: its nodes and link are marked on the
+// map (`renderGraph`), else the shown one's.
+let pointedMessage = null;
+function pointAt(message) {
+ pointedMessage = message;
+ markRelated(message ? message.related : shownRelated());
+ if (state) renderGraph();
+}
function markRelated(key) {
relatedMarked = key || null;
for (const line of document.getElementById("console").children) {
@@ -1782,8 +1813,8 @@ function consoleLine(message) {
showMessage(shownMessage && shownMessage.seq === message.seq ? null : message);
});
// The messages of its exchange marked while pointed at; then the shown one's again.
- line.addEventListener("pointerenter", () => markRelated(message.related));
- line.addEventListener("pointerleave", () => markRelated(shownRelated()));
+ line.addEventListener("pointerenter", () => pointAt(message));
+ line.addEventListener("pointerleave", () => pointAt(null));
return line;
}
function showMessage(message) {