diff options
| author | tv <tv@krebsco.de> | 2026-11-02 16:51:53 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-02 16:53:23 +0100 |
| commit | 3da7da39a1a0751afac234065a4c492a5f8bf6ae (patch) | |
| tree | 6b1ae542f962a554ea8eb626c6965b3b7b168c4f /src | |
| parent | 857b7766985cb4d60ba3b5797d3a8cb43f6a53bb (diff) | |
dashboard: messages tint related nodes and edges
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 41 |
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) { |
