1
+ // @ts -nocheck
2
+ import React from 'react' ;
3
+ import { BarStack } from '@visx/shape' ;
4
+ import { SeriesPoint } from '@visx/shape/lib/types' ;
5
+ import { Group } from '@visx/group' ;
6
+ import { Grid } from '@visx/grid' ;
7
+ import { AxisBottom , AxisLeft } from '@visx/axis' ;
8
+ import { scaleBand , scaleLinear , scaleOrdinal } from '@visx/scale' ;
9
+ import { useTooltip , useTooltipInPortal , defaultStyles } from '@visx/tooltip' ;
10
+ import { Text } from '@visx/text' ;
11
+ import { schemeSet3 } from 'd3-scale-chromatic' ;
12
+ import snapshots from './snapshots' ;
13
+ import { onHover , onHoverExit } from '../actions/actions' ;
14
+ import { useStoreContext } from '../store'
15
+
16
+ /* TYPESCRIPT */
17
+ interface data {
18
+ snapshotId ?: string ;
19
+ }
20
+
21
+ interface margin { top : number ; right : number ; bottom : number ; left : number } ;
22
+
23
+ interface snapshot {
24
+ snapshotId ?: string ;
25
+ children : [ ] ;
26
+ componentData : any ;
27
+ name : string ;
28
+ state : string ;
29
+ }
30
+
31
+ interface TooltipData {
32
+ bar : SeriesPoint < snapshot > ;
33
+ key : string ;
34
+ index : number ;
35
+ height : number ;
36
+ width : number ;
37
+ x : number ;
38
+ y : number ;
39
+ color : string ;
40
+ }
41
+
42
+ /* DEFAULTS */
43
+ const margin = { top : 60 , right : 30 , bottom : 0 , left : 50 } ;
44
+ const axisColor = '#62d6fb' ;
45
+ const background = '#242529' ;
46
+ const tooltipStyles = {
47
+ ...defaultStyles ,
48
+ minWidth : 60 ,
49
+ backgroundColor : 'rgba(0,0,0,0.9)' ,
50
+ color : 'white' ,
51
+ fontSize : '14px' ,
52
+ lineHeight : '18px' ,
53
+ fontFamily : 'Roboto'
54
+ } ;
55
+
56
+ const BarGraph = ( props ) => {
57
+ const [ { tabs, currentTab } , dispatch ] = useStoreContext ( ) ;
58
+ const { width, height, data } = props ;
59
+ console . log ( 'data: ' , data )
60
+ const {
61
+ tooltipOpen, tooltipLeft, tooltipTop, tooltipData, hideTooltip, showTooltip,
62
+ } = useTooltip < TooltipData > ( ) ;
63
+ let tooltipTimeout : number ;
64
+ const { containerRef, TooltipInPortal } = useTooltipInPortal ( ) ;
65
+
66
+ const keys = Object . keys ( data . componentData ) ;
67
+
68
+ // data accessor (used to generate scales) and formatter (add units for on hover box)
69
+ const getSnapshotId = ( d : snapshot ) => d . snapshotId ;
70
+ const formatSnapshotId = ( id ) => `Snapshot ID: ${ id } ` ;
71
+ const formatRenderTime = ( time ) => `${ time } ms ` ;
72
+
73
+ // create visualization SCALES with cleaned data
74
+ const snapshotIdScale = scaleBand < string > ( {
75
+ domain : data . barStack . map ( getSnapshotId ) ,
76
+ padding : 0.2 ,
77
+ } ) ;
78
+
79
+ const renderingScale = scaleLinear < number > ( {
80
+ domain : [ 0 , data . maxTotalRender ] ,
81
+ nice : true ,
82
+ } ) ;
83
+
84
+ const colorScale = scaleOrdinal < string > ( {
85
+ domain : keys ,
86
+ range : schemeSet3 ,
87
+ } ) ;
88
+
89
+ // setting max dimensions and scale ranges
90
+
91
+ const xMax = width - margin . left - margin . right ;
92
+ const yMax = height - margin . top - 150 ;
93
+ snapshotIdScale . rangeRound ( [ 0 , xMax ] ) ;
94
+ renderingScale . range ( [ yMax , 0 ] ) ;
95
+ console . log ( "renderingScale range: " , renderingScale . range ( [ yMax , 0 ] ) )
96
+ return (
97
+ < div >
98
+ < svg ref = { containerRef } width = { width } height = { height } >
99
+ { }
100
+ < rect
101
+ x = { 0 }
102
+ y = { 0 }
103
+ width = { width }
104
+ height = { height }
105
+ fill = { background }
106
+ rx = { 14 }
107
+ />
108
+ < Grid
109
+ top = { margin . top }
110
+ left = { margin . left }
111
+ xScale = { snapshotIdScale }
112
+ yScale = { renderingScale }
113
+ width = { xMax }
114
+ height = { yMax }
115
+ stroke = "black"
116
+ strokeOpacity = { 0.1 }
117
+ xOffset = { snapshotIdScale . bandwidth ( ) / 2 }
118
+ />
119
+ < Group top = { margin . top } left = { margin . left } >
120
+ < BarStack
121
+ data = { data . barStack }
122
+ keys = { keys }
123
+ x = { getSnapshotId }
124
+ xScale = { snapshotIdScale }
125
+ yScale = { renderingScale }
126
+ color = { colorScale }
127
+ >
128
+ { barStacks =>
129
+ barStacks . map ( barStack =>
130
+ barStack . bars . map ( ( ( bar , idx ) => {
131
+ // hides new components if components don't exist in previous snapshots
132
+ if ( Number . isNaN ( bar . bar [ 1 ] ) || bar . height < 0 ) {
133
+ bar . height = 0 ;
134
+ }
135
+ return (
136
+ < rect
137
+ key = { `bar-stack-${ barStack . index } -${ bar . index } ` }
138
+ x = { bar . x }
139
+ y = { bar . y }
140
+ height = { bar . height === 0 ? null : bar . height }
141
+ width = { bar . width }
142
+ fill = { bar . color }
143
+ /* TIP TOOL EVENT HANDLERS */
144
+ // Hides tool tip once cursor moves off the current rect
145
+ onMouseLeave = { ( ) => {
146
+ console . log ( 'bar: ' , bar )
147
+ dispatch ( onHoverExit ( data . componentData [ bar . key ] . rtid ) ,
148
+ tooltipTimeout = window . setTimeout ( ( ) => {
149
+ hideTooltip ( )
150
+ } , 300 ) )
151
+ } }
152
+ // Cursor position in window updates position of the tool tip
153
+ onMouseMove = { event => {
154
+ dispatch ( onHover ( data . componentData [ bar . key ] . rtid ) )
155
+ if ( tooltipTimeout ) clearTimeout ( tooltipTimeout ) ;
156
+ const top = event . clientY - margin . top - bar . height ;
157
+ const left = bar . x + bar . width / 2 ;
158
+ showTooltip ( {
159
+ tooltipData : bar ,
160
+ tooltipTop : top ,
161
+ tooltipLeft : left ,
162
+ } ) ;
163
+ } }
164
+ />
165
+ ) } ) ) )
166
+ }
167
+ </ BarStack >
168
+ </ Group >
169
+ < AxisLeft
170
+ top = { margin . top }
171
+ left = { margin . left }
172
+ scale = { renderingScale }
173
+ stroke = { axisColor }
174
+ tickStroke = { axisColor }
175
+ strokeWidth = { 2 }
176
+ tickLabelProps = { ( ) => ( {
177
+ fill : 'rgb(231, 231, 231)' ,
178
+ fontSize : 11 ,
179
+ verticalAnchor : 'middle' ,
180
+ textAnchor : 'end' ,
181
+ } ) }
182
+ />
183
+ < AxisBottom
184
+ top = { yMax + margin . top }
185
+ left = { margin . left }
186
+ scale = { snapshotIdScale }
187
+ stroke = { axisColor }
188
+ tickStroke = { axisColor }
189
+ strokeWidth = { 2 }
190
+ tickLabelProps = { ( ) => ( {
191
+ fill : 'rgb(231, 231, 231)' ,
192
+ fontSize : 11 ,
193
+ textAnchor : 'middle' ,
194
+ } ) }
195
+ />
196
+ < Text x = { - xMax / 2 } y = "15" transform = "rotate(-90)" fontSize = { 12 } fill = "#FFFFFF" > Rendering Time (ms) </ Text >
197
+ < Text x = { xMax / 2 } y = { yMax + 100 } fontSize = { 12 } fill = "#FFFFFF" > Snapshot Id </ Text >
198
+ </ svg >
199
+ { /* FOR HOVER OVER DISPLAY */ }
200
+ { tooltipOpen && tooltipData && (
201
+ < TooltipInPortal
202
+ key = { Math . random ( ) } // update tooltip bounds each render
203
+ top = { tooltipTop }
204
+ left = { tooltipLeft }
205
+ style = { tooltipStyles }
206
+ >
207
+ < div style = { { color : colorScale ( tooltipData . key ) } } >
208
+ { ' ' }
209
+ < strong > { tooltipData . key } </ strong >
210
+ { ' ' }
211
+ </ div >
212
+ < div > { data . componentData [ tooltipData . key ] . stateType } </ div >
213
+ < div >
214
+ { ' ' }
215
+ { formatRenderTime ( tooltipData . bar . data [ tooltipData . key ] ) }
216
+ { ' ' }
217
+ </ div >
218
+ < div >
219
+ { ' ' }
220
+ < small > { formatSnapshotId ( getSnapshotId ( tooltipData . bar . data ) ) } </ small >
221
+ </ div >
222
+ </ TooltipInPortal >
223
+ ) }
224
+ </ div >
225
+ ) } ;
226
+
227
+ export default BarGraph ;
0 commit comments