review: address feedback — update navigation tree on cut/paste

When nodes with subgraphs are cut and pasted to a different graph,
reparent their tree entries so the sidebar tree and breadcrumbs
reflect the new hierarchy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Bot
2026-03-23 21:33:07 +00:00
parent 07571b64be
commit f7f2938bb1
2 changed files with 56 additions and 0 deletions

View File

@@ -62,6 +62,7 @@ export default function NodeContextMenu({
const graphsById = useGraphsStore((s) => (s as { graphsById: Map<string, GraphModel> }).graphsById);
const addTreeNode = useGraphLayersTreeStore(store => store.add);
const removeTreeNode = useGraphLayersTreeStore(store => store.remove);
const moveTreeNode = useGraphLayersTreeStore(store => store.move);
const setCut = useCutStore(store => store.setCut);
const clearCut = useCutStore(store => store.clearCut);
@@ -165,6 +166,22 @@ export default function NodeContextMenu({
}
}
// Update navigation tree: reparent tree nodes from source graph to target graph.
// A tree node belongs to the source graph when its tree parent matches sourceGraphId
// (or is a root node when sourceGraphId is 'main').
const treeState = useGraphLayersTreeStore.getState();
const effectiveSourceParent = cutState.sourceGraphId === 'main' ? undefined : cutState.sourceGraphId ?? undefined;
const newTreeParent = graphContextValue.graphId === 'main' ? undefined : graphContextValue.graphId;
for (const nodeId of cutState.cutNodeIds) {
if (treeState.nodesFlatById.has(nodeId)) {
const nodeTreeParent = treeState.parentIdByChildId.get(nodeId);
if (nodeTreeParent === effectiveSourceParent) {
moveTreeNode(nodeId, newTreeParent);
}
}
}
clearCut();
break;
}

View File

@@ -10,6 +10,7 @@ export interface TreeStore {
tree: TreeDataNode[];
add: (childNode: NodeContext, parentNodeId: string | undefined) => void;
remove: (nodeId: string) => void;
move: (nodeId: string, newParentId: string | undefined) => void;
reset: () => void;
}
@@ -90,6 +91,44 @@ export const useGraphLayersTreeStore = create<TreeStore>()((set) => ({
tree: createTree([...state.rootNodes], nodesFlatById)
}
}),
move: (nodeId, newParentId) => set((state) => {
const node = state.nodesFlatById.get(nodeId);
if (!node) return state;
const nodesFlatById = new Map(state.nodesFlatById);
const parentIdByChildId = new Map(state.parentIdByChildId);
let rootNodes = [...state.rootNodes];
// Remove from old parent
const oldParentId = state.parentIdByChildId.get(nodeId);
if (oldParentId !== undefined) {
const oldParent = nodesFlatById.get(oldParentId);
if (oldParent) {
oldParent.children = oldParent.children?.filter(n => n.key !== nodeId) ?? [];
}
parentIdByChildId.delete(nodeId);
} else {
rootNodes = rootNodes.filter(n => n.key !== nodeId);
}
// Add to new parent
if (newParentId !== undefined) {
const newParent = nodesFlatById.get(newParentId);
if (newParent) {
newParent.children = newParent.children ? [...newParent.children, node] : [node];
parentIdByChildId.set(nodeId, newParentId);
}
} else {
rootNodes = [...rootNodes, node];
}
return {
nodesFlatById,
parentIdByChildId,
rootNodes,
tree: createTree(rootNodes, nodesFlatById),
};
}),
reset: () => set({
nodesFlatById: new Map<React.Key, TreeDataNode>(),
parentIdByChildId: new Map<React.Key, string>(),