11"use client"
22
3- import { useEffect , useMemo , useState } from "react"
4- import { Bar , BarChart , CartesianGrid , XAxis , YAxis } from "recharts"
53import { Card , CardContent , CardHeader , CardTitle } from "@/components/ui/card"
6- import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from "@/components/ui/select"
74import { ChartContainer , ChartTooltip , ChartTooltipContent } from "@/components/ui/chart"
5+ import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from "@/components/ui/select"
6+ import { Skeleton } from "@/components/ui/skeleton"
7+ import { Loader2Icon } from "lucide-react"
8+ import { useEffect , useMemo , useState } from "react"
9+ import { Bar , BarChart , CartesianGrid , XAxis , YAxis } from "recharts"
810
9- const sampleData = [
10- {
11- metadata : { name : "gpu-queue" } ,
12- status : {
13- allocated : {
14- memory : "8Gi" ,
15- cpu : "4000m" ,
16- pods : "10" ,
17- "nvidia.com/gpu" : "2" ,
18- } ,
19- } ,
20- spec : {
21- capability : {
22- memory : "16Gi" ,
23- cpu : "8000m" ,
24- pods : "20" ,
25- "nvidia.com/gpu" : "4" ,
26- } ,
27- } ,
28- } ,
29- {
30- metadata : { name : "cpu-intensive" } ,
31- status : {
32- allocated : {
33- memory : "12Gi" ,
34- cpu : "6000m" ,
35- pods : "15" ,
36- "nvidia.com/gpu" : "0" ,
37- } ,
38- } ,
39- spec : {
40- capability : {
41- memory : "32Gi" ,
42- cpu : "16000m" ,
43- pods : "50" ,
44- "nvidia.com/gpu" : "0" ,
45- } ,
46- } ,
47- } ,
48- {
49- metadata : { name : "memory-heavy" } ,
50- status : {
51- allocated : {
52- memory : "24Gi" ,
53- cpu : "2000m" ,
54- pods : "8" ,
55- "nvidia.com/gpu" : "1" ,
56- } ,
57- } ,
58- spec : {
59- capability : {
60- memory : "64Gi" ,
61- cpu : "8000m" ,
62- pods : "30" ,
63- "nvidia.com/gpu" : "2" ,
64- } ,
65- } ,
66- } ,
67- {
68- metadata : { name : "general-purpose" } ,
69- status : {
70- allocated : {
71- memory : "4Gi" ,
72- cpu : "2000m" ,
73- pods : "12" ,
74- "nvidia.com/gpu" : "0" ,
75- } ,
76- } ,
77- spec : {
78- capability : {
79- memory : "16Gi" ,
80- cpu : "8000m" ,
81- pods : "40" ,
82- "nvidia.com/gpu" : "0" ,
83- } ,
84- } ,
85- } ,
86- {
87- metadata : { name : "ml-training" } ,
88- status : {
89- allocated : {
90- memory : "32Gi" ,
91- cpu : "8000m" ,
92- pods : "5" ,
93- "nvidia.com/gpu" : "8" ,
94- } ,
95- } ,
96- spec : {
97- capability : {
98- memory : "128Gi" ,
99- cpu : "32000m" ,
100- pods : "20" ,
101- "nvidia.com/gpu" : "16" ,
102- } ,
103- } ,
104- } ,
105- ]
11+ interface QueueMetrics {
12+ name : string
13+ weight : number
14+ reclaimable : boolean
15+ inqueue : number
16+ pending : number
17+ running : number
18+ unknown : number
19+ }
10620
10721interface QueueResourcesBarChartProps {
108- data ?: typeof sampleData
22+ data ?: QueueMetrics [ ]
23+ isLoading ?: boolean
10924}
11025
111- const QueueResourcesBarChart = ( { data = sampleData } : QueueResourcesBarChartProps ) => {
26+ const BarChartSkeleton = ( ) => (
27+ < Card className = "h-full flex flex-col" >
28+ < CardHeader className = "flex flex-row items-center justify-between space-y-0 pb-4" >
29+ < Skeleton className = "h-6 w-32" />
30+ < Skeleton className = "h-10 w-[180px]" />
31+ </ CardHeader >
32+ < CardContent className = "flex items-center justify-center h-[300px]" >
33+ < div className = "flex flex-col items-center space-y-2" >
34+ < Loader2Icon className = "h-8 w-8 animate-spin text-muted-foreground" />
35+ < p className = "text-muted-foreground" > Loading queue data...</ p >
36+ </ div >
37+ </ CardContent >
38+ </ Card >
39+ ) ;
40+
41+ const QueueResourcesBarChart = ( { data = [ ] , isLoading = false } : QueueResourcesBarChartProps ) => {
11242 const [ selectedResource , setSelectedResource ] = useState ( "" )
11343
44+ // Transform API data to match the expected format
45+ const transformedData = useMemo ( ( ) => {
46+ return data . map ( queue => ( {
47+ metadata : { name : queue . name } ,
48+ status : {
49+ allocated : {
50+ inqueue : queue . inqueue ,
51+ pending : queue . pending ,
52+ running : queue . running ,
53+ unknown : queue . unknown ,
54+ } ,
55+ } ,
56+ spec : {
57+ capability : {
58+ inqueue : queue . inqueue + queue . pending + queue . running + queue . unknown ,
59+ pending : queue . pending + queue . running + queue . unknown ,
60+ running : queue . running + queue . unknown ,
61+ unknown : queue . unknown ,
62+ } ,
63+ } ,
64+ } ) ) ;
65+ } , [ data ] ) ;
66+
11467 // Get resource type options dynamically
11568 const resourceOptions = useMemo ( ( ) => {
116- if ( ! data || data . length === 0 ) return [ ]
69+ if ( ! transformedData || transformedData . length === 0 ) return [ ]
11770
11871 const resourceTypes = new Set < string > ( )
11972
120- data . forEach ( ( queue ) => {
73+ transformedData . forEach ( ( queue ) => {
12174 const allocated = queue . status ?. allocated || { }
12275 Object . keys ( allocated ) . forEach ( ( resource ) => resourceTypes . add ( resource ) )
12376 } )
@@ -126,7 +79,7 @@ const QueueResourcesBarChart = ({ data = sampleData }: QueueResourcesBarChartPro
12679 value : resource ,
12780 label : `${ resource . charAt ( 0 ) . toUpperCase ( ) + resource . slice ( 1 ) } Resources` . replace ( "Nvidia.com/gpu" , "GPU" ) ,
12881 } ) )
129- } , [ data ] )
82+ } , [ transformedData ] )
13083
13184 useEffect ( ( ) => {
13285 if ( resourceOptions . length > 0 && ! selectedResource ) {
@@ -152,29 +105,19 @@ const QueueResourcesBarChart = ({ data = sampleData }: QueueResourcesBarChartPro
152105 return cpuStr . toString ( ) . includes ( "m" ) ? value / 1000 : value // m is converted to the number of cores
153106 }
154107
155- const processData = ( data : typeof sampleData ) => {
108+ const processData = ( data : typeof transformedData ) => {
156109 return data . reduce (
157110 ( acc , queue ) => {
158111 const name = queue . metadata . name
159112 const allocated = queue . status ?. allocated || { }
160113 const capability = queue . spec ?. capability || { }
161114
162- const allocatedMemory = convertMemoryToGi ( allocated . memory || "0" )
163- const capabilityMemory = convertMemoryToGi ( capability . memory || "0" )
164-
165- const allocatedCPU = convertCPUToCores ( allocated . cpu || "0" )
166- const capabilityCPU = convertCPUToCores ( capability . cpu || "0" )
167-
168115 acc [ name ] = {
169116 allocated : {
170117 ...allocated ,
171- memory : allocatedMemory ,
172- cpu : allocatedCPU ,
173118 } ,
174119 capability : {
175120 ...capability ,
176- memory : capabilityMemory ,
177- cpu : capabilityCPU ,
178121 } ,
179122 }
180123 return acc
@@ -183,7 +126,7 @@ const QueueResourcesBarChart = ({ data = sampleData }: QueueResourcesBarChartPro
183126 )
184127 }
185128
186- const processedData = useMemo ( ( ) => processData ( data ) , [ data ] )
129+ const processedData = useMemo ( ( ) => processData ( transformedData ) , [ transformedData ] )
187130
188131 const chartData = useMemo ( ( ) => {
189132 return Object . keys ( processedData ) . map ( ( queueName ) => ( {
@@ -203,6 +146,14 @@ const QueueResourcesBarChart = ({ data = sampleData }: QueueResourcesBarChartPro
203146 return "Pod Count"
204147 case "nvidia.com/gpu" :
205148 return "GPU Count"
149+ case "inqueue" :
150+ return "In Queue Count"
151+ case "pending" :
152+ return "Pending Count"
153+ case "running" :
154+ return "Running Count"
155+ case "unknown" :
156+ return "Unknown Count"
206157 default :
207158 return "Amount"
208159 }
@@ -219,6 +170,29 @@ const QueueResourcesBarChart = ({ data = sampleData }: QueueResourcesBarChartPro
219170 } ,
220171 }
221172
173+ if ( isLoading ) {
174+ return < BarChartSkeleton /> ;
175+ }
176+
177+ if ( transformedData . length === 0 ) {
178+ return (
179+ < Card className = "h-full flex flex-col" >
180+ < CardHeader className = "flex flex-row items-center justify-between space-y-0 pb-4" >
181+ < CardTitle > Queue Resources</ CardTitle >
182+ </ CardHeader >
183+ < CardContent className = "flex items-center justify-center h-[300px]" >
184+ < div className = "flex flex-col items-center space-y-2" >
185+ < div className = "w-16 h-16 rounded-full bg-muted flex items-center justify-center" >
186+ < span className = "text-2xl" > 📈</ span >
187+ </ div >
188+ < p className = "text-muted-foreground" > No queue data available</ p >
189+ < p className = "text-sm text-muted-foreground" > Create a queue to see resource information</ p >
190+ </ div >
191+ </ CardContent >
192+ </ Card >
193+ ) ;
194+ }
195+
222196 return (
223197 < Card className = "h-full flex flex-col" >
224198 < CardHeader className = "flex flex-row items-center justify-between space-y-0 pb-4" >
0 commit comments