mirror of
https://github.com/penpot/penpot.git
synced 2026-09-08 21:19:49 +00:00
💄 Graph console QoL round
"Show result in graph view" moves into an actions bar above the results table; results scroll inside a 45vh container (client and server render paths); the Loaded-session fieldset gains a live "Graph size" line that stays fresh through skipped repaints; IsInstanceOf mid-edge label becomes the spelled-out rel name (∈ read as membership, not derivation) with the legend falling back to the dash-arrow for long syms. Signed-off-by: Álvaro Tejero Cantero <alvorithm@teje.ro>
This commit is contained in:
parent
6b10ed065a
commit
e08ac33700
@ -59,6 +59,7 @@ Graph Console
|
|||||||
target="_blank">{{session.name}}</a></b> ({{session.file-id}})<br />
|
target="_blank">{{session.name}}</a></b> ({{session.file-id}})<br />
|
||||||
Loaded at revision: <b>{{session.revn}}</b><br />
|
Loaded at revision: <b>{{session.revn}}</b><br />
|
||||||
Graph revision: <b id="graph-sync-revn">{% if session.graph-revn %}{{session.graph-revn}}{% else %}{{session.revn}}{% endif %}</b><br />
|
Graph revision: <b id="graph-sync-revn">{% if session.graph-revn %}{{session.graph-revn}}{% else %}{{session.revn}}{% endif %}</b><br />
|
||||||
|
Graph size: <b id="graph-size">…</b><br />
|
||||||
Schema: <b>{{session.schema-version}}</b><br />
|
Schema: <b>{{session.schema-version}}</b><br />
|
||||||
Loaded at: <b>{{session.loaded-at}}</b>
|
Loaded at: <b>{{session.loaded-at}}</b>
|
||||||
</p>
|
</p>
|
||||||
@ -125,6 +126,7 @@ Graph Console
|
|||||||
{% if query-result %}
|
{% if query-result %}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Results ({{query-result.row-count}} rows{% if query-result.truncated? %}, truncated{% endif %})</legend>
|
<legend>Results ({{query-result.row-count}} rows{% if query-result.truncated? %}, truncated{% endif %})</legend>
|
||||||
|
<div style="max-height: 45vh; overflow: auto;">
|
||||||
<table border="1" cellpadding="4" cellspacing="0" style="border-collapse: collapse; width: 100%;">
|
<table border="1" cellpadding="4" cellspacing="0" style="border-collapse: collapse; width: 100%;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -143,6 +145,7 @@ Graph Console
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -374,9 +377,12 @@ Graph Console
|
|||||||
// rel label rendered mid-edge (abacus viewer EDGE_SYM convention) —
|
// rel label rendered mid-edge (abacus viewer EDGE_SYM convention) —
|
||||||
// dash variants alone cannot carry the growing rel roster. IsChildOf
|
// dash variants alone cannot carry the growing rel roster. IsChildOf
|
||||||
// is the unlabeled default (the background tree structure).
|
// 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.
|
||||||
const EDGE_STYLES = {
|
const EDGE_STYLES = {
|
||||||
"IsChildOf": { stroke: "#b3b0a8" },
|
"IsChildOf": { stroke: "#b3b0a8" },
|
||||||
"IsInstanceOf": { stroke: "#8b98a9", lineDash: [4, 3], sym: "∈" }
|
"IsInstanceOf": { stroke: "#8b98a9", lineDash: [4, 3], sym: "IsInstanceOf" }
|
||||||
};
|
};
|
||||||
const FALLBACK_EDGE_STYLE = { stroke: "#b3b0a8" };
|
const FALLBACK_EDGE_STYLE = { stroke: "#b3b0a8" };
|
||||||
// --- graph diff: add/remove marks with step fade --------------------
|
// --- graph diff: add/remove marks with step fade --------------------
|
||||||
@ -918,9 +924,10 @@ Graph Console
|
|||||||
});
|
});
|
||||||
Object.keys(rels).sort().forEach(function (rel) {
|
Object.keys(rels).sort().forEach(function (rel) {
|
||||||
const s = edgeStyle(rel);
|
const s = edgeStyle(rel);
|
||||||
|
const glyph = (s.sym && s.sym.length <= 2) ? s.sym : (s.lineDash ? "⇢" : "→");
|
||||||
items.push('<span style="margin-right: 1em; white-space: nowrap;">'
|
items.push('<span style="margin-right: 1em; white-space: nowrap;">'
|
||||||
+ '<span style="color: ' + s.stroke + '; font-size: 14px;">'
|
+ '<span style="color: ' + s.stroke + '; font-size: 14px;">'
|
||||||
+ escapeHtml(s.sym || (s.lineDash ? "⇢" : "→")) + '</span> '
|
+ escapeHtml(glyph) + '</span> '
|
||||||
+ escapeHtml(rel) + "</span>");
|
+ escapeHtml(rel) + "</span>");
|
||||||
});
|
});
|
||||||
if (anyLiveMarks()) {
|
if (anyLiveMarks()) {
|
||||||
@ -1009,6 +1016,13 @@ Graph Console
|
|||||||
return resp.json();
|
return resp.json();
|
||||||
})
|
})
|
||||||
.then(function (data) {
|
.then(function (data) {
|
||||||
|
// Session-fieldset size line stays live even through skipped
|
||||||
|
// repaints (unlike the status line under the canvas).
|
||||||
|
const sizeEl = document.getElementById("graph-size");
|
||||||
|
if (sizeEl) {
|
||||||
|
sizeEl.textContent = data.nodes.length + " nodes, "
|
||||||
|
+ data.edges.length + " edges";
|
||||||
|
}
|
||||||
// Skip the repaint when the display projection is unchanged: a
|
// Skip the repaint when the display projection is unchanged: a
|
||||||
// change burst that only touches non-projected attrs (e.g. moving
|
// change burst that only touches non-projected attrs (e.g. moving
|
||||||
// shapes around) bumps revn but not the picture.
|
// shapes around) bumps revn but not the picture.
|
||||||
@ -1304,10 +1318,15 @@ Graph Console
|
|||||||
}
|
}
|
||||||
|
|
||||||
const truncated = result["truncated?"] ? ", truncated" : "";
|
const truncated = result["truncated?"] ? ", truncated" : "";
|
||||||
|
// Actions bar sits above the table so a long result cannot push the
|
||||||
|
// "Show result in graph view" button out of sight; the table itself
|
||||||
|
// scrolls inside a capped container.
|
||||||
let html =
|
let html =
|
||||||
"<fieldset><legend>Results ("
|
"<fieldset><legend>Results ("
|
||||||
+ escapeHtml(String(result["row-count"]))
|
+ escapeHtml(String(result["row-count"]))
|
||||||
+ " rows" + truncated + ")</legend>"
|
+ " rows" + truncated + ")</legend>"
|
||||||
|
+ "<div id=\"graph-result-actions\" style=\"margin-bottom: 4px;\"></div>"
|
||||||
|
+ "<div style=\"max-height: 45vh; overflow: auto;\">"
|
||||||
+ "<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\""
|
+ "<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\""
|
||||||
+ " style=\"border-collapse: collapse; width: 100%;\">"
|
+ " style=\"border-collapse: collapse; width: 100%;\">"
|
||||||
+ "<thead><tr>";
|
+ "<thead><tr>";
|
||||||
@ -1332,7 +1351,7 @@ Graph Console
|
|||||||
html += "</tr>";
|
html += "</tr>";
|
||||||
});
|
});
|
||||||
|
|
||||||
html += "</tbody></table></fieldset>";
|
html += "</tbody></table></div></fieldset>";
|
||||||
output.innerHTML = html;
|
output.innerHTML = html;
|
||||||
|
|
||||||
// Offer to view the result as an induced subgraph: any UUID appearing
|
// Offer to view the result as an induced subgraph: any UUID appearing
|
||||||
@ -1350,7 +1369,7 @@ Graph Console
|
|||||||
btn.type = "button";
|
btn.type = "button";
|
||||||
btn.textContent = "Show result in graph view (" + ids.size + " ids)";
|
btn.textContent = "Show result in graph view (" + ids.size + " ids)";
|
||||||
btn.addEventListener("click", function () { applyQueryFilter(ids); });
|
btn.addEventListener("click", function () { applyQueryFilter(ids); });
|
||||||
output.appendChild(btn);
|
document.getElementById("graph-result-actions").appendChild(btn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user