From 663919d9289652440a63ba8f45f9a041e86d8888 Mon Sep 17 00:00:00 2001 From: chihlasm Date: Sat, 28 Feb 2026 19:47:10 -0500 Subject: [PATCH] feat: add node picker dropdown to action node form for cross-references Co-Authored-By: Claude Opus 4.6 --- .../components/tree-editor/NodeFormAction.tsx | 70 ++++++++++++++++--- frontend/src/store/treeEditorStore.ts | 19 +++++ 2 files changed, 79 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/tree-editor/NodeFormAction.tsx b/frontend/src/components/tree-editor/NodeFormAction.tsx index 2cd5b837..71efaff3 100644 --- a/frontend/src/components/tree-editor/NodeFormAction.tsx +++ b/frontend/src/components/tree-editor/NodeFormAction.tsx @@ -1,6 +1,7 @@ import { useState } from 'react' import { DynamicArrayField } from './DynamicArrayField' -import { useTreeEditorStore } from '@/store/treeEditorStore' +import { useTreeEditorStore, collectAllNodesFlat } from '@/store/treeEditorStore' +import { Link2, X } from 'lucide-react' import { MarkdownContent } from '@/components/ui/MarkdownContent' import { InfoTip } from '@/components/common/InfoTip' import type { TreeStructure } from '@/types' @@ -158,16 +159,65 @@ export function NodeFormAction({ node, onUpdate }: NodeFormActionProps) { /> - {/* Next step hint */} - {hasNextNode ? ( -

- Next step is linked — click it on the canvas to edit. + {/* Link to existing node */} +

+ + {hasNextNode ? ( +
+ + Linked to: {(() => { + const treeStructure = useTreeEditorStore.getState().treeStructure + const allNodes = collectAllNodesFlat(treeStructure) + const target = allNodes.find(n => n.id === node.next_node_id) + return target ? target.label : node.next_node_id + })()} + + +
+ ) : ( + + )} +

+ {hasNextNode + ? 'This action will navigate to the linked node.' + : 'Select a node to navigate to after this action, or save to create a new placeholder.'}

- ) : ( -

- Save to create a placeholder for the next step. -

- )} +
) } diff --git a/frontend/src/store/treeEditorStore.ts b/frontend/src/store/treeEditorStore.ts index 11c84b70..271df0ba 100644 --- a/frontend/src/store/treeEditorStore.ts +++ b/frontend/src/store/treeEditorStore.ts @@ -123,6 +123,25 @@ export const findNodeInTree = ( return null } +/** Collect all nodes in the tree as a flat list with depth info. */ +export function collectAllNodesFlat( + root: TreeStructure | null +): Array<{ id: string; label: string; type: string; depth: number }> { + if (!root) return [] + const result: Array<{ id: string; label: string; type: string; depth: number }> = [] + + function walk(node: TreeStructure, depth: number) { + const label = node.type === 'decision' + ? (node.question || 'Untitled Decision') + : (node.title || `Untitled ${node.type}`) + result.push({ id: node.id, label, type: node.type, depth }) + node.children?.forEach(child => walk(child, depth + 1)) + } + + walk(root, 0) + return result +} + // Helper to find parent of a node const findParentNode = ( nodeId: string,