22import SelectTheme from '@/app/styles/select' ;
33import { formatGraphLabel , timeOptions } from '@/app/utils/graph' ;
44import { TimeAggregateType } from '@/grpc_generated/route' ;
5+ import { useTheme } from '@/lib/AppTheme' ;
6+ import { Icon } from '@/lib/Icon' ;
57import { Label } from '@/lib/Label' ;
6- import { BarChart } from '@tremor/react' ;
7- import { useEffect , useState } from 'react' ;
8+ import {
9+ BarElement ,
10+ CategoryScale ,
11+ Chart as ChartJS ,
12+ ChartOptions ,
13+ Legend ,
14+ LinearScale ,
15+ Title ,
16+ Tooltip ,
17+ } from 'chart.js' ;
18+ import { useState } from 'react' ;
19+ import { Bar } from 'react-chartjs-2' ;
820import ReactSelect from 'react-select' ;
21+ import { BarLoader } from 'react-spinners' ;
22+ import useSWR from 'swr' ;
23+
24+ const CdcSyncingLoader = ( ) => {
25+ return (
26+ < div
27+ style = { {
28+ display : 'flex' ,
29+ rowGap : '1rem' ,
30+ flexDirection : 'column' ,
31+ alignItems : 'center' ,
32+ } }
33+ >
34+ Loading sync data...
35+ < BarLoader />
36+ </ div >
37+ ) ;
38+ } ;
39+
40+ const CdcSyncHistoryError = ( ) => {
41+ return (
42+ < div style = { { display : 'flex' , alignItems : 'center' , columnGap : '0.5rem' } } >
43+ < Icon name = 'error' /> Failed to load sync history
44+ </ div >
45+ ) ;
46+ } ;
947
1048type CdcGraphProps = { mirrorName : string } ;
1149
1250export default function CdcGraph ( { mirrorName } : CdcGraphProps ) {
1351 const [ aggregateType , setAggregateType ] = useState < TimeAggregateType > (
1452 TimeAggregateType . TIME_AGGREGATE_TYPE_ONE_HOUR
1553 ) ;
16- const [ graphValues , setGraphValues ] = useState <
17- { name : string ; 'Rows synced at a point in time' : number } [ ]
18- > ( [ ] ) ;
1954
20- useEffect ( ( ) => {
21- const fetchData = async ( ) => {
22- const req : any = {
23- flowJobName : mirrorName ,
24- aggregateType,
25- } ;
55+ ChartJS . register (
56+ BarElement ,
57+ CategoryScale ,
58+ LinearScale ,
59+ Title ,
60+ Tooltip ,
61+ Legend
62+ ) ;
63+ const theme = useTheme ( ) ;
64+ const isDarkMode = theme . theme === 'dark' ;
65+ const chartOptions : ChartOptions < 'bar' > = {
66+ maintainAspectRatio : false ,
67+ scales : {
68+ x : {
69+ grid : { display : false } ,
70+ } ,
71+ y : {
72+ grid : {
73+ color : isDarkMode ? '#333333' : '#e5e7eb' ,
74+ } ,
75+ } ,
76+ } ,
77+ } ;
78+ const fetcher = async ( [ mirrorName , aggregateType ] : [
79+ string ,
80+ TimeAggregateType ,
81+ ] ) => {
82+ const req = {
83+ flowJobName : mirrorName ,
84+ aggregateType,
85+ } ;
86+ const res = await fetch ( '/api/v1/mirrors/cdc/graph' , {
87+ method : 'POST' ,
88+ cache : 'no-store' ,
89+ body : JSON . stringify ( req ) ,
90+ } ) ;
91+ const data : { data : { time : number ; rows : number } [ ] } = await res . json ( ) ;
2692
27- const res = await fetch ( '/api/v1/mirrors/cdc/graph' , {
28- method : 'POST' ,
29- cache : 'no-store' ,
30- body : JSON . stringify ( req ) ,
31- } ) ;
32- const data : { data : { time : number ; rows : number } [ ] } = await res . json ( ) ;
33- setGraphValues (
34- data . data . map ( ( { time, rows } ) => ( {
35- name : formatGraphLabel ( new Date ( time ) , aggregateType ) ,
36- 'Rows synced at a point in time' : Number ( rows ) ,
37- } ) )
38- ) ;
93+ const chartData = {
94+ labels : data . data . map ( ( { time } ) =>
95+ formatGraphLabel ( new Date ( time ) , aggregateType )
96+ ) ,
97+ datasets : [
98+ {
99+ label : 'Rows synced at a point in time' ,
100+ data : data . data . map ( ( { rows } ) => rows ) ,
101+ backgroundColor : 'rgba(75, 192, 192, 0.2)' ,
102+ borderColor : 'rgba(75, 192, 192, 1)' ,
103+ borderWidth : 1 ,
104+ } ,
105+ ] ,
39106 } ;
107+ return chartData ;
108+ } ;
40109
41- fetchData ( ) ;
42- } , [ mirrorName , aggregateType ] ) ;
110+ const { data, isLoading, error } = useSWR (
111+ [ mirrorName , aggregateType ] ,
112+ fetcher
113+ ) ;
43114
44115 return (
45116 < div >
@@ -56,12 +127,21 @@ export default function CdcGraph({ mirrorName }: CdcGraphProps) {
56127 < div style = { { height : '3rem' } } >
57128 < Label variant = 'headline' > Sync history</ Label >
58129 </ div >
59- < BarChart
60- className = 'mt-3'
61- data = { graphValues }
62- index = 'name'
63- categories = { [ 'Rows synced at a point in time' ] }
64- />
130+ < div
131+ style = { {
132+ height : '320px' ,
133+ alignItems : 'center' ,
134+ justifyContent : 'center' ,
135+ display : 'flex' ,
136+ width : '100%' ,
137+ } }
138+ >
139+ { isLoading && < CdcSyncingLoader /> }
140+ { error && < CdcSyncHistoryError /> }
141+ { data && ! isLoading && ! error && (
142+ < Bar data = { data } options = { chartOptions } />
143+ ) }
144+ </ div >
65145 </ div >
66146 ) ;
67147}
0 commit comments