1+ 'use client' ;
2+
3+ import React , { useState , useCallback } from 'react' ;
4+ import { useParams , useRouter } from 'next/navigation' ;
5+ import { GraphVisualization } from '@/components/GraphVisualization' ;
6+ import { GraphTemplateDetail } from '@/components/GraphTemplateDetail' ;
7+ import { ThemeToggle } from '@/components/ThemeToggle' ;
8+ import { Button } from '@/components/ui/button' ;
9+ import { ArrowLeft } from 'lucide-react' ;
10+ import { clientApiService } from '@/services/clientApi' ;
11+ import { UpsertGraphTemplateResponse } from '@/types/state-manager' ;
12+
13+ export default function GraphPage ( ) {
14+ const router = useRouter ( ) ;
15+ const params = useParams ( ) ;
16+
17+ const namespace = params ?. namespace as string ;
18+ const runId = params ?. runId as string ;
19+
20+ // Graph template state
21+ const [ graphTemplate , setGraphTemplate ] = useState < UpsertGraphTemplateResponse | null > ( null ) ;
22+ const [ isLoadingTemplate , setIsLoadingTemplate ] = useState ( false ) ;
23+ const [ templateError , setTemplateError ] = useState < string | null > ( null ) ;
24+
25+ const handleBack = ( ) => {
26+ // Go back to the previous page or close the tab if opened from external link
27+ if ( window . history . length > 1 ) {
28+ router . back ( ) ;
29+ } else {
30+ window . close ( ) ;
31+ }
32+ } ;
33+
34+ const handleOpenGraphTemplate = useCallback ( async ( graphName : string ) => {
35+ if ( ! graphName || ! namespace ) return ;
36+
37+ try {
38+ setIsLoadingTemplate ( true ) ;
39+ setTemplateError ( null ) ;
40+ const template = await clientApiService . getGraphTemplate ( namespace , graphName ) ;
41+ // Add name and namespace to the template
42+ template . name = graphName ;
43+ template . namespace = namespace ;
44+ setGraphTemplate ( template ) ;
45+ } catch ( err ) {
46+ setTemplateError ( err instanceof Error ? err . message : 'Failed to load graph template' ) ;
47+ } finally {
48+ setIsLoadingTemplate ( false ) ;
49+ }
50+ } , [ namespace ] ) ;
51+
52+ const handleCloseGraphTemplate = ( ) => {
53+ setGraphTemplate ( null ) ;
54+ setTemplateError ( null ) ;
55+ } ;
56+
57+ if ( ! namespace || ! runId ) {
58+ return (
59+ < div className = "min-h-screen bg-background flex items-center justify-center" >
60+ < div className = "text-center" >
61+ < div className = "animate-spin rounded-full h-8 w-8 border-b-2 border-primary mx-auto mb-4" > </ div >
62+ < p className = "text-muted-foreground" > Loading...</ p >
63+ </ div >
64+ </ div >
65+ ) ;
66+ }
67+
68+ return (
69+ < div className = "min-h-screen bg-background" >
70+ { /* Header */ }
71+ < header className = "border-b border-border bg-card/50 backdrop-blur-sm sticky top-0 z-10" >
72+ < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8" >
73+ < div className = "flex items-center justify-between h-16" >
74+ < div className = "flex items-center space-x-4" >
75+ < Button
76+ onClick = { handleBack }
77+ variant = "ghost"
78+ size = "sm"
79+ className = "flex items-center space-x-2"
80+ >
81+ < ArrowLeft className = "w-4 h-4" />
82+ < span > Back</ span >
83+ </ Button >
84+ < div className = "h-6 w-px bg-border" />
85+ < div >
86+ < h1 className = "text-xl font-semibold text-foreground" >
87+ Graph Visualization
88+ </ h1 >
89+ < p className = "text-sm text-muted-foreground" >
90+ Namespace: { namespace } | Run: { runId }
91+ </ p >
92+ </ div >
93+ </ div >
94+ < ThemeToggle />
95+ </ div >
96+ </ div >
97+ </ header >
98+
99+ { /* Main Content */ }
100+ < main className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8" >
101+ < GraphVisualization
102+ namespace = { namespace }
103+ runId = { runId }
104+ onGraphTemplateRequest = { handleOpenGraphTemplate }
105+ />
106+ </ main >
107+
108+ { /* Graph Template Detail Modal - Inline at bottom */ }
109+ < div className = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-8" >
110+ { templateError && (
111+ < div className = "mb-4 p-4 bg-destructive/10 border border-destructive/20 rounded-lg" >
112+ < p className = "text-sm text-destructive" > { templateError } </ p >
113+ </ div >
114+ ) }
115+
116+ { isLoadingTemplate && (
117+ < div className = "mb-4 p-4 bg-muted rounded-lg" >
118+ < div className = "flex items-center" >
119+ < div className = "animate-spin rounded-full h-4 w-4 border-b-2 border-primary mr-2" > </ div >
120+ < p className = "text-sm text-muted-foreground" > Loading graph template...</ p >
121+ </ div >
122+ </ div >
123+ ) }
124+
125+ < GraphTemplateDetail
126+ graphTemplate = { graphTemplate }
127+ isOpen = { ! ! graphTemplate }
128+ onClose = { handleCloseGraphTemplate }
129+ />
130+ </ div >
131+ </ div >
132+ ) ;
133+ }
0 commit comments