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:
@@ -62,6 +62,7 @@ export default function NodeContextMenu({
|
|||||||
const graphsById = useGraphsStore((s) => (s as { graphsById: Map<string, GraphModel> }).graphsById);
|
const graphsById = useGraphsStore((s) => (s as { graphsById: Map<string, GraphModel> }).graphsById);
|
||||||
const addTreeNode = useGraphLayersTreeStore(store => store.add);
|
const addTreeNode = useGraphLayersTreeStore(store => store.add);
|
||||||
const removeTreeNode = useGraphLayersTreeStore(store => store.remove);
|
const removeTreeNode = useGraphLayersTreeStore(store => store.remove);
|
||||||
|
const moveTreeNode = useGraphLayersTreeStore(store => store.move);
|
||||||
const setCut = useCutStore(store => store.setCut);
|
const setCut = useCutStore(store => store.setCut);
|
||||||
const clearCut = useCutStore(store => store.clearCut);
|
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();
|
clearCut();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export interface TreeStore {
|
|||||||
tree: TreeDataNode[];
|
tree: TreeDataNode[];
|
||||||
add: (childNode: NodeContext, parentNodeId: string | undefined) => void;
|
add: (childNode: NodeContext, parentNodeId: string | undefined) => void;
|
||||||
remove: (nodeId: string) => void;
|
remove: (nodeId: string) => void;
|
||||||
|
move: (nodeId: string, newParentId: string | undefined) => void;
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +91,44 @@ export const useGraphLayersTreeStore = create<TreeStore>()((set) => ({
|
|||||||
tree: createTree([...state.rootNodes], nodesFlatById)
|
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({
|
reset: () => set({
|
||||||
nodesFlatById: new Map<React.Key, TreeDataNode>(),
|
nodesFlatById: new Map<React.Key, TreeDataNode>(),
|
||||||
parentIdByChildId: new Map<React.Key, string>(),
|
parentIdByChildId: new Map<React.Key, string>(),
|
||||||
|
|||||||
Reference in New Issue
Block a user