From 3cb9573124d2ba74e209fa99406b4227102ea271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Tejero=20Cantero?= Date: Thu, 16 Jul 2026 19:37:34 +0200 Subject: [PATCH] :lipstick: Polish graph console session panel and edge labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Loaded-session fieldset: graph size gains a resident-memory estimate (fit to graph_sizes.md: ~1.1 MiB floor + ~5.4 KiB/node) with per-table counts on hover, replacing the load-time Projection stats; loaded-at compacts to local HH:MM with the full instant on hover. Edge rel labels drop to 7 px and lose the dashed stroke — the text label alone carries rel identity. Signed-off-by: Álvaro Tejero Cantero --- .../app/templates/graph-console.tmpl | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/backend/resources/app/templates/graph-console.tmpl b/backend/resources/app/templates/graph-console.tmpl index 6cc4b66add..605c6965de 100644 --- a/backend/resources/app/templates/graph-console.tmpl +++ b/backend/resources/app/templates/graph-console.tmpl @@ -61,7 +61,7 @@ Graph Console Graph revision: {% if session.graph-revn %}{{session.graph-revn}}{% else %}{{session.revn}}{% endif %}
Graph size:
Schema: {{session.schema-version}}
- Loaded at: {{session.loaded-at}} + Loaded at: {{session.loaded-at}}

Feed: connecting… @@ -70,14 +70,6 @@ Graph Console

- {% if session.projection.stats %} -

- Projection: - documents={{session.projection.stats.documents}}, - pages={{session.projection.stats.pages}}, - shapes={{session.projection.stats.shapes}} -

- {% endif %} @@ -379,10 +371,11 @@ Graph Console // is the unlabeled default (the background tree structure). // `sym` may be a full rel name: no compact glyph reads as "derived from // a template" (∈ wrongly connotes membership), so IsInstanceOf spells - // itself out; the legend falls back to the dash-arrow for long syms. + // itself out; the legend falls back to an arrow for long syms. No + // dashed edges — the label alone carries rel identity. const EDGE_STYLES = { "IsChildOf": { stroke: "#b3b0a8" }, - "IsInstanceOf": { stroke: "#8b98a9", lineDash: [4, 3], sym: "IsInstanceOf" } + "IsInstanceOf": { stroke: "#8b98a9", sym: "IsInstanceOf" } }; const FALLBACK_EDGE_STYLE = { stroke: "#b3b0a8" }; // --- graph diff: add/remove marks with step fade -------------------- @@ -841,7 +834,7 @@ Graph Console return m ? Math.max(diffFade(m), 0.15) : 1; }, labelText: function (d) { return edgeStyle(d.data.rel).sym || ""; }, - labelFontSize: 9, + labelFontSize: 7, labelFill: "#52514e", labelBackground: true, labelBackgroundFill: "#ffffff", @@ -1017,11 +1010,22 @@ Graph Console }) .then(function (data) { // Session-fieldset size line stays live even through skipped - // repaints (unlike the status line under the canvas). + // repaints (unlike the status line under the canvas). The MiB + // figure is a resident-size estimate fitted to the measurements + // in graph_sizes.md: ≈1.1 MiB session floor + ≈5.4 KiB per node + // (full-schema projection); hover shows per-table counts. const sizeEl = document.getElementById("graph-size"); if (sizeEl) { + const mib = 1.1 + data.nodes.length * 5.4 / 1024; sizeEl.textContent = data.nodes.length + " nodes, " - + data.edges.length + " edges"; + + data.edges.length + " edges (≈" + mib.toFixed(1) + " MiB)"; + const counts = {}; + data.nodes.forEach(function (n) { + counts[n.table] = (counts[n.table] || 0) + 1; + }); + sizeEl.title = Object.keys(counts).sort().map(function (t) { + return t + "=" + counts[t]; + }).join(", ") + " — MiB ≈ 1.1 + 5.4 KiB × nodes (measured fit)"; } // Skip the repaint when the display projection is unchanged: a // change burst that only touches non-projected attrs (e.g. moving @@ -1529,6 +1533,17 @@ Graph Console }); } + // Compact the loaded-at timestamp to local HH:MM; full instant on hover. + const loadedAtEl = document.getElementById("graph-loaded-at"); + if (loadedAtEl) { + const d = new Date(loadedAtEl.textContent.trim()); + if (!isNaN(d.getTime())) { + loadedAtEl.title = loadedAtEl.textContent.trim(); + loadedAtEl.textContent = String(d.getHours()).padStart(2, "0") + + ":" + String(d.getMinutes()).padStart(2, "0"); + } + } + connect(); refreshSyncStatus(); refetchGraph();