mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
feat(explorer): stabilize local graph interaction
This commit is contained in:
@@ -117,3 +117,6 @@ node_modules/
|
||||
|
||||
# Frontend build artifacts (generated by Vite — do not track in git)
|
||||
semantica/static/
|
||||
|
||||
# Local graph explorer test datasets
|
||||
demo_out/
|
||||
|
||||
@@ -173,6 +173,14 @@ export function GraphInspectorPanel({
|
||||
);
|
||||
}
|
||||
|
||||
if (!graph.hasNode(nodeId)) {
|
||||
return (
|
||||
<div style={{ padding: 24, color: "#8b949e", fontSize: 13, lineHeight: 1.6 }}>
|
||||
Selected grouped item is not directly inspectable. Activate Focused mode to resolve to a canonical node.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const attributes = graph.getNodeAttributes(nodeId) as {
|
||||
color?: string;
|
||||
content?: string;
|
||||
|
||||
@@ -823,9 +823,17 @@ export function GraphWorkspace() {
|
||||
};
|
||||
}, [debouncedTime, isLoading]);
|
||||
|
||||
const focusNode = useCallback((nodeId: string) => {
|
||||
const resolveNodeIdForFocusedMode = useCallback((nodeId: string): string | null => {
|
||||
if (!nodeId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (graph.hasNode(nodeId)) {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
const currentDisplayGraph = pluginRuntimeRef.current?.displayGraph ?? graph;
|
||||
if (viewMode === "grouped" && currentDisplayGraph.hasNode(nodeId)) {
|
||||
if (currentDisplayGraph.hasNode(nodeId)) {
|
||||
const displayAttrs = currentDisplayGraph.getNodeAttributes(nodeId) as NodeAttributes;
|
||||
const communityGroup = displayAttrs.properties?.__communityGroup as
|
||||
| {
|
||||
@@ -833,28 +841,44 @@ export function GraphWorkspace() {
|
||||
sampleNodeIds?: string[];
|
||||
}
|
||||
| undefined;
|
||||
|
||||
const anchorNodeId = communityGroup?.anchorNodeId || communityGroup?.sampleNodeIds?.[0] || "";
|
||||
if (anchorNodeId && graph.hasNode(anchorNodeId)) {
|
||||
setViewMode("focused");
|
||||
setSelectedNodeId(anchorNodeId);
|
||||
setSelectedEdgeId("");
|
||||
setPathResult(null);
|
||||
setSearchResults([]);
|
||||
setSearchError("");
|
||||
setIsLayoutRunning(false);
|
||||
return;
|
||||
return anchorNodeId;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}, []);
|
||||
|
||||
const activateFocusedMode = useCallback(() => {
|
||||
const canonicalNodeId = resolveNodeIdForFocusedMode(selectedNodeId);
|
||||
if (!canonicalNodeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (canonicalNodeId !== selectedNodeId) {
|
||||
setSelectedNodeId(canonicalNodeId);
|
||||
}
|
||||
setViewMode("focused");
|
||||
}, [resolveNodeIdForFocusedMode, selectedNodeId]);
|
||||
const canActivateFocusedMode = useMemo(
|
||||
() => Boolean(resolveNodeIdForFocusedMode(selectedNodeId)),
|
||||
[pluginRuntimeVersion, resolveNodeIdForFocusedMode, selectedNodeId],
|
||||
);
|
||||
|
||||
const focusNode = useCallback((nodeId: string) => {
|
||||
if (!nodeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSelectedNodeId(nodeId);
|
||||
setSelectedEdgeId("");
|
||||
setPathResult(null);
|
||||
setSearchResults([]);
|
||||
setSearchError("");
|
||||
if (nodeId) {
|
||||
setIsLayoutRunning(false);
|
||||
}
|
||||
}, [viewMode]);
|
||||
setIsLayoutRunning(false);
|
||||
}, []);
|
||||
|
||||
const handleEdgeSelect = useCallback((edgeId: string) => {
|
||||
setSelectedEdgeId(edgeId);
|
||||
@@ -1153,6 +1177,10 @@ export function GraphWorkspace() {
|
||||
focusNode(action.nodeId);
|
||||
return;
|
||||
case "setViewMode":
|
||||
if (action.viewMode === "focused") {
|
||||
activateFocusedMode();
|
||||
return;
|
||||
}
|
||||
setViewMode(action.viewMode);
|
||||
return;
|
||||
case "collapseNeighborhood":
|
||||
@@ -1205,7 +1233,7 @@ export function GraphWorkspace() {
|
||||
setActiveDockPanelId((previous) => (previous === action.panelId ? null : previous));
|
||||
return;
|
||||
}
|
||||
}, [focusNode, selectedNodeId, setEffectToggle]);
|
||||
}, [activateFocusedMode, focusNode, selectedNodeId, setEffectToggle]);
|
||||
|
||||
const diagnosticsSnapshot = useMemo<GraphDiagnosticsSnapshot | null>(() => {
|
||||
if (!GRAPH_THEME.effects.diagnostics.enabledInDev || !graphDiagnosticsState) {
|
||||
@@ -1401,8 +1429,8 @@ export function GraphWorkspace() {
|
||||
label: "Focused",
|
||||
title: "Inspect the selected node in a focused local graph",
|
||||
active: viewMode === "focused",
|
||||
disabled: !selectedNodeId,
|
||||
onClick: () => setViewMode("focused"),
|
||||
disabled: !canActivateFocusedMode,
|
||||
onClick: activateFocusedMode,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user