@@ -3,12 +3,14 @@ import {
33 Background ,
44 BackgroundVariant ,
55 Edge ,
6- Node , Panel ,
6+ Node ,
77 ReactFlow ,
88 ReactFlowProvider ,
99 useEdgesState ,
1010 useNodesState ,
11- useUpdateNodeInternals
11+ useReactFlow ,
12+ useUpdateNodeInternals ,
13+ ViewportPortal
1214} from "@xyflow/react" ;
1315import React from "react" ;
1416import '@xyflow/react/dist/style.css' ;
@@ -17,16 +19,16 @@ import {DFlowNodeDefaultCard} from "../d-flow-node/DFlowNodeDefaultCard";
1719import { DFlowNodeGroupCard } from "../d-flow-node/DFlowNodeGroupCard" ;
1820import { DFlowNodeTriggerCard } from "../d-flow-node/DFlowNodeTriggerCard" ;
1921import { DFlowEdge } from "./DFlowEdge" ;
20- import { DFlowPanelSize } from "../d-flow-panel" ;
22+ import { DFlowPanelControl , DFlowPanelLayout , DFlowPanelSize } from "../d-flow-panel" ;
2123import { DFlowValidation } from "../d-flow-validation" ;
2224import { Flow , type Namespace , type NamespaceProject } from "@code0-tech/sagittarius-graphql-types" ;
2325import { useFlowNodes } from "./DFlow.nodes.hook" ;
2426import { useFlowEdges } from "./DFlow.edges.hook" ;
25- import { DFlowPanelControl } from "../d-flow-panel" ;
26- import { DFlowPanelLayout } from "../d-flow-panel" ;
2727import { DFlowPanelUpdate } from "../d-flow-panel/DFlowPanelUpdate" ;
28- import { Button } from "../button/Button" ;
29- import { ButtonGroup } from "../button-group/ButtonGroup" ;
28+ import { Text } from "../text/Text" ;
29+ import { LineWobble } from 'ldrs/react'
30+ import 'ldrs/react/LineWobble.css'
31+ import { Spacing } from "../spacing/Spacing" ;
3032
3133/**
3234 * Dynamically layouts a tree of nodes and their parameter nodes for a flow-based editor.
@@ -612,8 +614,8 @@ export const DFlow: React.FC<DFlowProps> = (props) => {
612614}
613615
614616const InternalDFlow : React . FC < DFlowProps > = ( props ) => {
617+ const { flowId, namespaceId, projectId, ...rest } = props
615618
616- const { flowId, namespaceId, projectId} = props
617619 const nodeTypes = React . useMemo ( ( ) => ( {
618620 default : DFlowNodeDefaultCard ,
619621 group : DFlowNodeGroupCard ,
@@ -626,10 +628,16 @@ const InternalDFlow: React.FC<DFlowProps> = (props) => {
626628
627629 const initialNodes = useFlowNodes ( flowId , namespaceId , projectId )
628630 const initialEdges = useFlowEdges ( flowId , namespaceId , projectId )
631+
629632 const [ nodes , setNodes ] = useNodesState < Node > ( [ ] )
630633 const [ edges , setEdges , edgeChangeEvent ] = useEdgesState < Edge > ( [ ] )
634+ const [ showTree , setShowTree ] = React . useState < boolean > ( false )
635+
631636 const updateNodeInternals = useUpdateNodeInternals ( )
632637
638+ const { fitView} = useReactFlow ( )
639+ const didFitViewRef = React . useRef ( false )
640+
633641 const revalidateHandles = React . useCallback ( ( ids : string [ ] ) => {
634642 requestAnimationFrame ( ( ) => {
635643 ids . forEach ( id => updateNodeInternals ( id ) )
@@ -688,26 +696,110 @@ const InternalDFlow: React.FC<DFlowProps> = (props) => {
688696
689697 } , [ initialNodes , initialEdges , revalidateHandles ] )
690698
699+ React . useEffect ( ( ) => {
700+ if ( didFitViewRef . current ) return
701+ if ( nodes . length <= 0 ) return
702+
703+ didFitViewRef . current = true
704+
705+ requestAnimationFrame ( ( ) => {
706+ requestAnimationFrame ( ( ) => {
707+ setTimeout ( async ( ) => {
708+ await fitView ( {
709+ padding : "64px" ,
710+ maxZoom : 1
711+ } )
712+ setShowTree ( true )
713+ } , 1000 )
714+ } )
715+ } )
716+ } , [ nodes , didFitViewRef ] )
717+
691718 return (
692719 < ReactFlow
693720 onlyRenderVisibleElements
694721 panOnScroll = { false }
695722 nodeTypes = { nodeTypes }
696723 edgeTypes = { edgeTypes }
697- onInit = { ( rf ) => rf . fitView ( ) }
698724 onNodesChange = { nodeChangeEvent }
699725 onEdgesChange = { edgeChangeEvent }
700- { ...mergeCode0Props ( "flow" , props ) }
726+ { ...mergeCode0Props ( "flow" , rest ) }
727+ data-tree-visibility = { showTree }
701728 proOptions = { { hideAttribution : true } }
702729 nodes = { nodes }
703730 edges = { edges }
731+ panOnDrag = { showTree }
732+ zoomOnScroll = { showTree }
733+ zoomOnPinch = { showTree }
734+ zoomOnDoubleClick = { showTree }
704735 >
705- < Background variant = { BackgroundVariant . Dots } color = "rgba(255,255,255, .05)" gap = { 8 } size = { 2 } />
706- < DFlowPanelSize />
707- < DFlowPanelLayout />
708- < DFlowValidation flowId = { "gid://sagittarius/Flow/1" } />
709- < DFlowPanelControl flowId = { flowId } />
710- < DFlowPanelUpdate flowId = { flowId } />
736+
737+ { ! showTree ? (
738+ < ViewportPortal >
739+ < div style = { {
740+ left : "50%" ,
741+ top : "50%" ,
742+ transform : "translate(-50%, -50%)" ,
743+ position : 'absolute' ,
744+ display : "flex" ,
745+ alignItems : "center" ,
746+ justifyContent : "center" ,
747+ flexDirection : "column"
748+ } } >
749+ < LineWobble
750+ size = "200"
751+ stroke = "5"
752+ bgOpacity = "0.5"
753+ speed = "2"
754+ color = "rgba(255, 255, 255, 0.15)"
755+ />
756+ < Spacing spacing = { "xl" } />
757+ < LoadingFlowText />
758+ < Spacing spacing = { "xs" } />
759+ < Text hierarchy = { "tertiary" } style = { {
760+ margin : "0 20%" ,
761+ textAlign : "center"
762+ } } >
763+ We are running requests to prepare your flow. This may take a few moments.
764+ </ Text >
765+ </ div >
766+ </ ViewportPortal >
767+ ) : null }
768+ { showTree ? (
769+ < >
770+ < Background variant = { BackgroundVariant . Dots } color = "rgba(255,255,255, .05)" gap = { 8 } size = { 2 } />
771+ < DFlowPanelSize />
772+ < DFlowPanelLayout />
773+ < DFlowValidation flowId = { "gid://sagittarius/Flow/1" } />
774+ < DFlowPanelControl flowId = { flowId } />
775+ < DFlowPanelUpdate flowId = { flowId } />
776+ </ >
777+ ) : null }
711778 </ ReactFlow >
712779 )
780+ }
781+
782+ const LoadingFlowText : React . FC = ( ) => {
783+
784+ const [ index , setIndex ] = React . useState ( 0 )
785+
786+ const loadingTexts = [
787+ "Preparing flow data" ,
788+ "Loading node and edge definitions" ,
789+ "Calculating perfect layout"
790+ ]
791+
792+ React . useEffect ( ( ) => {
793+ const id = setInterval ( ( ) => {
794+ setIndex ( i => ( i + 1 ) % loadingTexts . length )
795+ } , 2000 )
796+
797+ return ( ) => clearInterval ( id )
798+ } , [ ] )
799+
800+ return (
801+ < Text size = "md" >
802+ { loadingTexts [ index ] }
803+ </ Text >
804+ )
713805}
0 commit comments