diff options
| author | tv <tv@krebsco.de> | 2026-10-30 19:46:41 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-30 19:46:41 +0100 |
| commit | 8e3ca379b90e4797006cc9c54b26185e2c998815 (patch) | |
| tree | d80a06a40b0a17335268aab7685493693713569d /src/api/dashboard | |
| parent | 8de181ace16647b4fa2181b41a2f8f4fd03d68de (diff) | |
dashboard: neaten up tree indentation
Diffstat (limited to 'src/api/dashboard')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index 0b15450..7feb8c3 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -79,7 +79,7 @@ border: 2px solid var(--self); opacity: .5; } .scroll { overflow: auto; min-height: 0; } #figures-box .scroll, #document-box .scroll { flex: 1; } - .tree pre { margin: 2px 0 4px 1em; white-space: pre-wrap; word-break: break-all; + .tree pre { margin: 2px 0 4px 1.1em; white-space: pre-wrap; word-break: break-all; max-height: 20em; overflow: auto; } .note { color: var(--muted); font-style: italic; } table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; } @@ -91,10 +91,15 @@ #peers tr.focused td { background: var(--line); } .id { font-family: ui-monospace, monospace; font-size: 12px; } .active { color: var(--ok); } .dormant { color: var(--bad); } .unknown { color: var(--muted); } - details { margin-left: 1em; } - summary { cursor: pointer; } .tree { font-family: ui-monospace, monospace; font-size: 12px; } - .tree > details { margin-left: 0; } + /* Every entry indented alike: a branch's triangle sits in the indentation, left of + where the text of every entry begins. */ + .tree details, .tree .leaf { position: relative; padding-left: 1.1em; } + .tree summary { cursor: pointer; list-style: none; } + .tree summary::-webkit-details-marker { display: none; } + .tree summary::before { content: "▸"; position: absolute; left: .1em; color: var(--muted); } + .tree details[open] > summary::before { content: "▾"; } + .tree details > .note { padding-left: 1.1em; } .key { color: var(--muted); } </style> </head> @@ -250,7 +255,7 @@ function tree(key, value, path) { for (const [k, v] of entries) details.append(tree(k, v, path + "." + k)); return details; } - return el("div", {}, el("span", { class: "key" }, key + ": "), + return el("div", { class: "leaf" }, el("span", { class: "key" }, key + ": "), JSON.stringify(aged(key, value))); } function renderStats() { @@ -262,7 +267,7 @@ function renderStats() { what.textContent = name(a) + " – " + name(b); what.title = focused; const listed = (x, y) => (state.graph.intended[x] || []).includes(y); - shown = [el("div", {}, el("span", { class: "key" }, "intended: "), + shown = [el("div", { class: "leaf" }, el("span", { class: "key" }, "intended: "), listed(a, b) || listed(b, a) ? "yes (member list)" : "no")]; // Each end's view of it, as it reported it. for (const [x, y, path] of [[a, b, "from"], [b, a, "to"]]) { @@ -271,7 +276,7 @@ function renderStats() { if (link) { shown.push(tree(name(x) + " reports", { secsAgo: report.secsAgo, ...link }, path)); } else { - shown.push(el("div", { class: "key" }, name(x) + (report + shown.push(el("div", { class: "key leaf" }, name(x) + (report ? " reports no link to " + name(y) + "." : " reports no links."))); } } @@ -289,7 +294,7 @@ function renderStats() { const report = state.graph.measured[focused]; shown = []; if (peer) shown.push(tree("peer", peer, "peer")); - else shown.push(el("div", { class: "key" }, "Not a peer of this node.")); + else shown.push(el("div", { class: "key leaf" }, "Not a peer of this node.")); if (report) shown.push(tree("links", report, "links")); } title.replaceChildren(focused === null ? "Figures: " : "Peer: ", what); @@ -567,7 +572,8 @@ async function readStore(path, shallow) { // branch's entries are kept across reads, so what's open inside stays open. function documentEntry(key, summary, path) { if ("value" in summary) { - return el("div", {}, el("span", { class: "key" }, key + ": "), JSON.stringify(summary.value)); + return el("div", { class: "leaf" }, el("span", { class: "key" }, key + ": "), + JSON.stringify(summary.value)); } const details = el("details", {}); const described = document.createTextNode(describe(summary)); |
