From f6d90df9016a77a69ebbcbb3944ed227edaa345d Mon Sep 17 00:00:00 2001 From: pankajydv07 Date: Fri, 26 Sep 2025 18:56:18 +0530 Subject: [PATCH] fix: ReactFlow controls not working in dashboard graph visualizations --- .../app/graph/[namespace]/[runId]/page.tsx | 13 +++-- .../src/components/GraphTemplateDetail.tsx | 19 +++++-- .../src/components/GraphVisualization.tsx | 54 +++++++++++++++++-- 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/dashboard/src/app/graph/[namespace]/[runId]/page.tsx b/dashboard/src/app/graph/[namespace]/[runId]/page.tsx index 200869f4..59fe66b8 100644 --- a/dashboard/src/app/graph/[namespace]/[runId]/page.tsx +++ b/dashboard/src/app/graph/[namespace]/[runId]/page.tsx @@ -2,6 +2,7 @@ import React, { useState, useCallback } from 'react'; import { useParams, useRouter } from 'next/navigation'; +import { ReactFlowProvider } from 'reactflow'; import { GraphVisualization } from '@/components/GraphVisualization'; import { GraphTemplateDetail } from '@/components/GraphTemplateDetail'; import { ThemeToggle } from '@/components/ThemeToggle'; @@ -103,11 +104,13 @@ export default function GraphPage() { {/* Main Content */}
- + + +
{/* Graph Template Detail Modal - Inline at bottom */} diff --git a/dashboard/src/components/GraphTemplateDetail.tsx b/dashboard/src/components/GraphTemplateDetail.tsx index 4ae40d38..0273a3d1 100644 --- a/dashboard/src/components/GraphTemplateDetail.tsx +++ b/dashboard/src/components/GraphTemplateDetail.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useMemo } from 'react'; +import React, { useMemo, useState, useCallback } from 'react'; import { UpsertGraphTemplateResponse, NodeTemplate } from '@/types/state-manager'; import { X, GitBranch, Settings, Database, Workflow, Clock } from 'lucide-react'; import ReactFlow, { @@ -257,6 +257,9 @@ const GraphVisualizer: React.FC<{ nodes: NodeTemplate[] }> = ({ nodes }) => { ); } + const [isInteractive, setIsInteractive] = useState(true); + const handleInteractiveChange = useCallback((val: boolean) => setIsInteractive(val), []); + return ( @@ -279,12 +282,20 @@ const GraphVisualizer: React.FC<{ nodes: NodeTemplate[] }> = ({ nodes }) => { minZoom={0.1} maxZoom={2} defaultViewport={{ x: 0, y: 0, zoom: 1.5 }} - elementsSelectable={true} + elementsSelectable={isInteractive} nodesConnectable={false} - nodesDraggable={false} + nodesDraggable={isInteractive} + zoomOnScroll={isInteractive} + panOnScroll={isInteractive} + panOnDrag={isInteractive} + zoomOnPinch={isInteractive} + zoomOnDoubleClick={isInteractive} className="bg-background" > - + diff --git a/dashboard/src/components/GraphVisualization.tsx b/dashboard/src/components/GraphVisualization.tsx index 7536bfcc..f94934e7 100644 --- a/dashboard/src/components/GraphVisualization.tsx +++ b/dashboard/src/components/GraphVisualization.tsx @@ -12,7 +12,9 @@ import ReactFlow, { MarkerType, NodeTypes, ConnectionLineType, - Handle + Handle, + useReactFlow, + Panel } from 'reactflow'; import 'reactflow/dist/style.css'; import { clientApiService } from '@/services/clientApi'; @@ -29,7 +31,8 @@ import { XCircle, Loader2, Network, - BarChart3 + BarChart3, + Maximize2 } from 'lucide-react'; import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; @@ -124,6 +127,7 @@ export const GraphVisualization: React.FC = ({ runId, onGraphTemplateRequest }) => { + const { fitView } = useReactFlow(); const [graphData, setGraphData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); @@ -131,6 +135,14 @@ export const GraphVisualization: React.FC = ({ const [selectedNodeDetails, setSelectedNodeDetails] = useState(null); const [isLoadingNodeDetails, setIsLoadingNodeDetails] = useState(false); const [nodeDetailsError, setNodeDetailsError] = useState(null); + const [isInteractive, setIsInteractive] = useState(true); + + const handleFitView = useCallback(() => { + fitView({ + duration: 800, // Animation duration in ms + padding: 0.2 // 20% padding around the graph + }); + }, [fitView]); const loadGraphStructure = useCallback(async () => { setIsLoading(true); @@ -525,12 +537,44 @@ export const GraphVisualization: React.FC = ({ defaultViewport={{ x: 0, y: 0, zoom: 0.7 }} proOptions={{ hideAttribution: true }} connectionLineType={ConnectionLineType.Straight} - elementsSelectable={true} + elementsSelectable={isInteractive} nodesConnectable={false} - nodesDraggable={false} + nodesDraggable={isInteractive} + zoomOnScroll={isInteractive} + panOnScroll={isInteractive} + panOnDrag={isInteractive} + zoomOnPinch={isInteractive} + zoomOnDoubleClick={isInteractive} > - + + + + +