Skip to content

Commit ead881c

Browse files
authored
Add subgraph navigation with double-click and auto-fit view (#1019)
## Description Added support for subgraph node navigation by implementing double-click functionality on subgraph nodes. When a user double-clicks on a subgraph node, they will be navigated to that subgraph. Additionally, modified the TaskConfiguration component to handle subgraph nodes differently by: 1. Adding an `isSubgraphNode` prop to TaskConfiguration 2. Setting "details" as the default tab for subgraph nodes instead of "io" 3. Adding a visual cursor pointer indicator for subgraph nodes Also implemented automatic view fitting when navigating between subgraphs, which ensures the graph is properly centered and zoomed after navigation. ## Type of Change - [x] New feature - [x] Improvement ## Checklist - [x] I have tested this does not break current pipelines / runs functionality - [x] I have tested the changes on staging ## Test Instructions 1. Create a pipeline with a subgraph node 2. Run the pipeline 3. Double-click on the subgraph node to navigate to the subgraph 4. Verify that the subgraph node shows the details tab by default 5. Confirm the cursor changes to a pointer when hovering over subgraph nodes 6. Navigate between subgraphs and verify the view automatically fits to show all nodes
1 parent 16b2ef7 commit ead881c

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

src/components/shared/ReactFlow/FlowCanvas/FlowCanvas.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -763,17 +763,22 @@ const FlowCanvas = ({
763763
initialCanvasLoaded.current = true;
764764
}, [componentSpec, currentSubgraphPath, preserveIOSelectionOnSpecChange]);
765765

766+
useEffect(() => {
767+
reactFlowInstance?.fitView({
768+
maxZoom: 1,
769+
duration: 300,
770+
});
771+
}, [currentSubgraphPath, reactFlowInstance]);
772+
766773
// Reset when loading a new component file
767774
useEffect(() => {
768775
resetPrevSpec();
769776
}, [componentSpec?.name, resetPrevSpec]);
770777

771778
const fitView = useCallback(() => {
772-
if (reactFlowInstance) {
773-
reactFlowInstance.fitView({
774-
maxZoom: 1,
775-
});
776-
}
779+
reactFlowInstance?.fitView({
780+
maxZoom: 1,
781+
});
777782
}, [reactFlowInstance]);
778783

779784
useScheduleExecutionOnceWhenConditionMet(

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNodeCard/TaskNodeCard.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ const TaskNodeCard = () => {
163163
setExpandedOutputs((prev) => !prev);
164164
}, []);
165165

166+
const handleDoubleClick = useCallback(() => {
167+
if (isSubgraphNode && taskId && isSubgraphNavigationEnabled) {
168+
navigateToSubgraph(taskId);
169+
}
170+
}, [isSubgraphNode, taskId, navigateToSubgraph, isSubgraphNavigationEnabled]);
171+
166172
useEffect(() => {
167173
if (nodeRef.current) {
168174
setScrollHeight(nodeRef.current.scrollHeight);
@@ -201,13 +207,15 @@ const TaskNodeCard = () => {
201207
"rounded-2xl border-gray-200 border-2 break-words p-0 drop-shadow-none gap-2",
202208
selected ? "border-gray-500" : "hover:border-slate-200",
203209
(highlighted || highlightedState) && "border-orange-500!",
210+
isSubgraphNode && "cursor-pointer",
204211
)}
205212
style={{
206213
width: dimensions.w + "px",
207214
height: condensed || !dimensions.h ? "auto" : dimensions.h + "px",
208215
transition: "height 0.2s",
209216
}}
210217
ref={nodeRef}
218+
onDoubleClick={handleDoubleClick}
211219
>
212220
<CardHeader className="border-b border-slate-200 px-2 py-2.5 flex flex-row justify-between items-start">
213221
<BlockStack>

src/routes/PipelineRun/PipelineRun.test.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ vi.mock("@/providers/BackendProvider", () => ({
4949
}));
5050

5151
vi.mock("@/services/executionService", () => ({
52+
useFetchExecutionInfo: vi.fn(),
53+
useFetchPipelineRun: () => ({
54+
data: null,
55+
isLoading: false,
56+
error: null,
57+
isFetching: false,
58+
refetch: () => {},
59+
enabled: false,
60+
}),
5261
countTaskStatuses: vi.fn(),
5362
getRunStatus: vi.fn(),
5463
STATUS: {

0 commit comments

Comments
 (0)