Adapt the coordination graph to flavor and indexed depends_on.
Omit flavor=residual by default, draw hub depends_on first, and keep citation waits_on as a tagged fallback. Explorer checkbox and CLI --include-residuals match State Hub include_residuals. Assistant: grok Assistant-Session: 01a09dc1-b21e-77e1-919e-fcad2f82b267
This commit is contained in:
parent
0b0abedbe8
commit
725e440b1e
8 changed files with 410 additions and 39 deletions
|
|
@ -405,6 +405,10 @@ def graph_explorer_page() -> str:
|
|||
<span class="field-label">Mode <button type="button" class="help-tip" aria-label="Mode help" data-help-title="Mode" data-help="Modes are predefined map views. Some modes use the selected item as context; changing modes changes which graph entities are visible, but keeps the layout controls separate.">?</button></span>
|
||||
<select id="mode-select" aria-label="Graph mode"></select>
|
||||
</div>
|
||||
<label id="include-residuals-wrap" class="field" style="display:none;align-self:end">
|
||||
<span class="field-label">Residuals <button type="button" class="help-tip" aria-label="Residuals help" data-help-title="Include residuals" data-help="Default coordination view omits flavor=residual workplans. Enable this to show them. Unspecified flavor stays visible. Titles containing the word residual are not treated as residual.">?</button></span>
|
||||
<input type="checkbox" id="include-residuals" aria-label="Include residual workplans">
|
||||
</label>
|
||||
<div class="field">
|
||||
<span class="field-label">Layout <button type="button" class="help-tip" aria-label="Layout help" data-help-title="Layout" data-help="Layout redraws the map arrangement. Cose uses relationship strength and repo affinity; circle, grid, concentric, and breadthfirst are simpler alternate arrangements.">?</button></span>
|
||||
<select id="layout-select" aria-label="Graph layout">
|
||||
|
|
@ -563,9 +567,13 @@ def graph_explorer_page() -> str:
|
|||
<script>
|
||||
(() => {
|
||||
const manifestUrl = "/exports/graph-explorer/manifest";
|
||||
const graphMode = new URLSearchParams(window.location.search).get("mode");
|
||||
const pageParams = new URLSearchParams(window.location.search);
|
||||
const graphMode = pageParams.get("mode");
|
||||
const includeResidualsParam = ["1", "true", "yes"].includes(
|
||||
(pageParams.get("include_residuals") || "").toLowerCase()
|
||||
);
|
||||
const graphUrl = graphMode === "coordination"
|
||||
? "/exports/graph-explorer?mode=coordination"
|
||||
? `/exports/graph-explorer?mode=coordination${includeResidualsParam ? "&include_residuals=true" : ""}`
|
||||
: "/exports/graph-explorer";
|
||||
const canvas = document.getElementById("graph-canvas");
|
||||
const zoneOverlay = document.getElementById("zone-overlay");
|
||||
|
|
@ -2779,6 +2787,8 @@ def graph_explorer_page() -> str:
|
|||
'<span class="pill"><span style="display:inline-block;width:12px;height:12px;border:2px dashed #b45309;border-radius:50%"></span>Unresolved</span>',
|
||||
'<span class="pill"><span style="display:inline-block;width:12px;height:12px;border:2px dashed #be123c;border-radius:3px"></span>Registered only</span>',
|
||||
'<span class="pill"><span style="display:inline-block;width:18px;border-top:2px dotted #98a2b3"></span>Weak edge</span>',
|
||||
'<span class="pill"><span style="display:inline-block;width:18px;border-top:3px solid #1d4ed8"></span>depends_on (indexed)</span>',
|
||||
'<span class="pill"><span style="display:inline-block;width:18px;border-top:2px dashed #b45309"></span>waits_on (citation)</span>',
|
||||
];
|
||||
legend.innerHTML = [...nodeTypes, ...statusItems].join("");
|
||||
};
|
||||
|
|
@ -2794,6 +2804,10 @@ def graph_explorer_page() -> str:
|
|||
option.textContent = mode.label;
|
||||
modeSelect.appendChild(option);
|
||||
});
|
||||
if (graphMode === "coordination" && optionExists(modeSelect, "coordination")) {
|
||||
modeSelect.value = "coordination";
|
||||
activeMode = "coordination";
|
||||
}
|
||||
profilePersistence = manifest.profile_persistence || "none";
|
||||
layerColors = Object.fromEntries((manifest.layers || []).map((layer) => [layer.id, layer.color]));
|
||||
nodeTypeLabels = Object.fromEntries((manifest.layers || []).map((layer) => [layer.id, layer.label]));
|
||||
|
|
@ -2807,6 +2821,20 @@ def graph_explorer_page() -> str:
|
|||
renderChecklist(edgeTypeFilter, allEdgeTypes, {}, "edge-type");
|
||||
syncFilterSummaries();
|
||||
renderLegend(manifest.layers || []);
|
||||
const residualsWrap = document.getElementById("include-residuals-wrap");
|
||||
const residualsToggle = document.getElementById("include-residuals");
|
||||
if (residualsWrap && residualsToggle) {
|
||||
const coordinationActive = graphMode === "coordination";
|
||||
residualsWrap.style.display = coordinationActive ? "" : "none";
|
||||
residualsToggle.checked = includeResidualsParam;
|
||||
residualsToggle.addEventListener("change", () => {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("mode", "coordination");
|
||||
if (residualsToggle.checked) url.searchParams.set("include_residuals", "true");
|
||||
else url.searchParams.delete("include_residuals");
|
||||
window.location.search = url.search;
|
||||
});
|
||||
}
|
||||
profiles = loadProfiles();
|
||||
renderProfiles();
|
||||
const elements = (payload.elements || []).map((element) => ({
|
||||
|
|
@ -2873,6 +2901,13 @@ def graph_explorer_page() -> str:
|
|||
}},
|
||||
{selector: "edge[strength = 'strong']", style: {"line-color": "#344054", "target-arrow-color": "#344054"}},
|
||||
{selector: "edge[strength = 'weak']", style: {"line-style": "dotted"}},
|
||||
{selector: "edge[edgeType = 'depends_on']", style: {"line-color": "#1d4ed8", "target-arrow-color": "#1d4ed8", "width": 3}},
|
||||
{selector: "edge[edgeType = 'waits_on']", style: {"line-color": "#b45309", "target-arrow-color": "#b45309", "line-style": "dashed", "width": 2}},
|
||||
{selector: "node[flavor = 'planning']", style: {"background-color": "#6366f1"}},
|
||||
{selector: "node[flavor = 'implementation']", style: {"background-color": "#1d4ed8"}},
|
||||
{selector: "node[flavor = 'refactoring']", style: {"background-color": "#b45309"}},
|
||||
{selector: "node[flavor = 'extension']", style: {"background-color": "#0f766e"}},
|
||||
{selector: "node[flavor = 'residual']", style: {"background-color": "#64748b"}},
|
||||
{selector: "edge[zoneCollapse = true]", style: {"line-style": "dashed", "line-color": "#0f766e", "target-arrow-color": "#0f766e"}},
|
||||
{selector: "node.rule-highlight", style: {
|
||||
"border-color": "#2563eb",
|
||||
|
|
@ -2957,6 +2992,19 @@ def graph_explorer_page() -> str:
|
|||
nodeTypeFilter.addEventListener("change", handleFilterChange);
|
||||
edgeTypeFilter.addEventListener("change", handleFilterChange);
|
||||
modeSelect.addEventListener("input", () => {
|
||||
if (modeSelect.value === "coordination" && graphMode !== "coordination") {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("mode", "coordination");
|
||||
window.location.search = url.search;
|
||||
return;
|
||||
}
|
||||
if (graphMode === "coordination" && modeSelect.value !== "coordination") {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.delete("mode");
|
||||
url.searchParams.delete("include_residuals");
|
||||
window.location.search = url.search;
|
||||
return;
|
||||
}
|
||||
activeMode = modeSelect.value || "full";
|
||||
focusSet = null;
|
||||
currentProfileId = "";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue