1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- /* eslint-disable max-len */
3
- /* eslint-disable @typescript-eslint/ban-types */
4
- /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
5
- /* eslint-disable eqeqeq */
6
- /* eslint-disable react/prop-types */
7
- /* eslint-disable no-mixed-operators */
8
- /* eslint-disable prefer-template */
9
- /* eslint-disable no-return-assign */
10
- /* eslint-disable prefer-arrow-callback */
11
- /* eslint-disable func-names */
12
- /* eslint-disable no-underscore-dangle */
13
- /* eslint-disable no-param-reassign */
14
- /* eslint-disable no-use-before-define */
15
- /* eslint-disable react/no-string-refs */
16
-
17
1
import React , { Component } from 'react' ;
18
2
import * as d3 from 'd3' ;
19
3
20
4
/**
21
5
* @var colors: Colors array for the diffrerent node branches, each color is for a different branch
22
6
*/
23
- const colors = [ '#95B6B7' , '#475485' , '#519331' , '#AA5039' , '#8B2F5F' , '#C5B738' , '#858DFF' , '#FF8D02' , '#FFCD51' , '#ACDAE6' , '#FC997E' , '#CF93AD' , '#AA3939' , '#AA6C39' , '#226666' , '#2C4870' ] ;
7
+ const colors = [
8
+ '#95B6B7' ,
9
+ '#475485' ,
10
+ '#519331' ,
11
+ '#AA5039' ,
12
+ '#8B2F5F' ,
13
+ '#C5B738' ,
14
+ '#858DFF' ,
15
+ '#FF8D02' ,
16
+ '#FFCD51' ,
17
+ '#ACDAE6' ,
18
+ '#FC997E' ,
19
+ '#CF93AD' ,
20
+ '#AA3939' ,
21
+ '#AA6C39' ,
22
+ '#226666' ,
23
+ '#2C4870' ,
24
+ ] ;
24
25
25
- const filter = ( data :any [ ] ) => {
26
+ const filterHooks = ( data : any [ ] ) => {
26
27
if ( data [ 0 ] . children && data [ 0 ] . state === 'stateless' ) {
27
- return filter ( data [ 0 ] . children ) ;
28
+ return filterHooks ( data [ 0 ] . children ) ;
28
29
}
29
30
return JSON . stringify ( data [ 0 ] . state ) ;
30
31
} ;
31
32
33
+ //const filterRecoil = (data: any[]) => {};
34
+
32
35
interface ChartProps {
33
36
hierarchy : Record < string , unknown > ;
34
37
}
@@ -38,15 +41,18 @@ class Chart extends Component {
38
41
/**
39
42
* @method maked3Tree :Creates a new D3 Tree
40
43
*/
41
- constructor ( props :ChartProps ) {
44
+ constructor ( props : ChartProps ) {
42
45
super ( props ) ;
46
+ // what React.createRef() is doing.
43
47
this . chartRef = React . createRef ( ) ;
44
48
this . maked3Tree = this . maked3Tree . bind ( this ) ;
45
49
this . removed3Tree = this . removed3Tree . bind ( this ) ;
50
+ this . isRecoil = false ;
46
51
}
47
52
48
53
componentDidMount ( ) {
49
54
const { hierarchy } = this . props ;
55
+ console . log ( 'HIERARCHYYYYY' , hierarchy ) ;
50
56
root = JSON . parse ( JSON . stringify ( hierarchy ) ) ;
51
57
this . maked3Tree ( ) ;
52
58
}
@@ -78,12 +84,14 @@ class Chart extends Component {
78
84
// };
79
85
const width = 600 ; // - margin.right - margin.left;
80
86
const height = 600 ; // 700 - margin.top - margin.bottom;
81
- const chartContainer = d3 . select ( this . chartRef . current )
82
- . append ( 'svg' ) // chartContainer is now pointing to svg
87
+ const svgContainer = d3
88
+ . select ( this . chartRef . current )
89
+ . append ( 'svg' ) // svgContainer is now pointing to svg
83
90
. attr ( 'width' , width )
84
91
. attr ( 'height' , height ) ;
85
92
86
- const g = chartContainer . append ( 'g' )
93
+ const g = svgContainer
94
+ . append ( 'g' )
87
95
// this is changing where the graph is located physically
88
96
. attr ( 'transform' , `translate(${ width / 2 + 4 } , ${ height / 2 + 2 } )` ) ;
89
97
@@ -96,12 +104,15 @@ class Chart extends Component {
96
104
// (our object titled dataset), which must be an object representing the root node
97
105
const hierarchy = d3 . hierarchy ( root ) ;
98
106
99
- const tree = d3 . tree ( )
107
+ const tree = d3
108
+ . tree ( )
100
109
// this assigns width of tree to be 2pi
101
110
// .size([2 * Math.PI, radius / 1.3])
102
111
. nodeSize ( [ width / 10 , height / 10 ] )
103
112
// .separation(function (a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
104
- . separation ( function ( a :{ parent :object } , b :{ parent :object } ) { return ( a . parent == b . parent ? 2 : 2 ) ; } ) ;
113
+ . separation ( function ( a : { parent : object } , b : { parent : object } ) {
114
+ return a . parent == b . parent ? 2 : 2 ;
115
+ } ) ;
105
116
106
117
const d3root = tree ( hierarchy ) ;
107
118
@@ -114,16 +125,30 @@ class Chart extends Component {
114
125
. enter ( )
115
126
. append ( 'path' )
116
127
. attr ( 'class' , 'link' )
117
- . attr ( 'd' , d3 . linkRadial ( )
118
- . angle ( ( d :{ x :number } ) => d . x )
119
- . radius ( ( d :{ y :number } ) => d . y ) ) ;
128
+ . attr (
129
+ 'd' ,
130
+ d3
131
+ . linkRadial ( )
132
+ . angle ( ( d : { x : number } ) => d . x )
133
+ . radius ( ( d : { y : number } ) => d . y )
134
+ ) ;
120
135
121
- const node = g . selectAll ( '.node' )
136
+ const node = g
137
+ . selectAll ( '.node' )
122
138
// root.descendants gets an array of of all nodes
123
139
. data ( d3root . descendants ( ) )
124
140
. enter ( )
125
141
. append ( 'g' )
126
- . style ( 'fill' , function ( d :{ data :{ branch :number } } ) {
142
+ . style ( 'fill' , function ( d ) {
143
+ let loadTime =
144
+ d . data . stateSnapshot . children [ 0 ] . componentData . actualDuration ;
145
+
146
+ if ( loadTime !== undefined ) {
147
+ if ( loadTime > 16 ) {
148
+ return '#ff0000' ;
149
+ }
150
+ }
151
+
127
152
if ( d . data . branch < colors . length ) {
128
153
return colors [ d . data . branch ] ;
129
154
}
@@ -134,96 +159,134 @@ class Chart extends Component {
134
159
return colors [ indexColors ] ;
135
160
} )
136
161
. attr ( 'class' , 'node--internal' )
137
- // })
138
- // assigning class to the node based on whether node has children or not
139
- // .attr('class', function (d) {
140
- // return 'node' + (d.children ? ' node--internal' : ' node--leaf');
141
- // })
142
- . attr ( 'transform' , function ( d :{ x :number , y :number } ) {
162
+ . attr ( 'transform' , function ( d : { x : number ; y : number } ) {
143
163
return 'translate(' + reinfeldTidierAlgo ( d . x , d . y ) + ')' ;
144
164
} ) ;
145
165
146
- node . append ( 'circle' )
166
+ node
167
+ . append ( 'circle' )
147
168
. attr ( 'r' , 15 )
148
- . on ( 'mouseover' , function ( d :any ) {
149
- d3 . select ( this )
150
- . transition ( 100 )
151
- . duration ( 20 )
152
- . attr ( 'r' , 25 ) ;
153
-
154
- tooltipDiv . transition ( )
155
- . duration ( 50 )
156
- . style ( 'opacity' , 0.9 ) ;
157
-
158
- tooltipDiv . html ( filter ( d . data . stateSnapshot . children ) , this )
159
- . style ( 'left' , ( d3 . event . pageX - 90 ) + 'px' )
160
- . style ( 'top' , ( d3 . event . pageY - 65 ) + 'px' ) ;
169
+ . on ( 'mouseover' , function ( d : any ) {
170
+ d3 . select ( this ) . transition ( 100 ) . duration ( 20 ) . attr ( 'r' , 25 ) ;
171
+
172
+ tooltipDiv . transition ( ) . duration ( 50 ) . style ( 'opacity' , 0.9 ) ;
173
+
174
+ if ( d . data . stateSnapshot . children [ 0 ] . name === 'RecoilRoot' ) {
175
+ console . log ( 'enter' ) ;
176
+ this . isRecoil = true ;
177
+ }
178
+ console . log ( 'isRecoil' , this . isRecoil ) ;
179
+
180
+ console . log ( 'd.data' , d . data ) ;
181
+ console . log ( 'd.data.stateSnapshot' , d . data . stateSnapshot ) ;
182
+ console . log (
183
+ 'd.data.stateSnapshot.children' ,
184
+ d . data . stateSnapshot . children
185
+ ) ;
186
+ if ( ! this . isRecoil ) {
187
+ tooltipDiv
188
+ . html ( filterHooks ( d . data . stateSnapshot . children ) , this )
189
+ . style ( 'left' , d3 . event . pageX - 90 + 'px' )
190
+ . style ( 'top' , d3 . event . pageY - 65 + 'px' ) ;
191
+ } else {
192
+ tooltipDiv
193
+ . html (
194
+ 'Load Time : ' +
195
+ JSON . stringify (
196
+ d . data . stateSnapshot . children [ 0 ] . componentData . actualDuration
197
+ ) . substring ( 0 , 5 ) +
198
+ ' ms' ,
199
+ this
200
+ )
201
+ . style ( 'left' , d3 . event . pageX - 90 + 'px' )
202
+ . style ( 'top' , d3 . event . pageY - 65 + 'px' ) ;
203
+ }
161
204
} )
162
205
// eslint-disable-next-line no-unused-vars
163
206
// eslint-disable-next-line @typescript-eslint/no-unused-vars
164
- . on ( 'mouseout' , function ( d :any ) {
165
- d3 . select ( this )
166
- . transition ( )
167
- . duration ( 300 )
168
- . attr ( 'r' , 15 ) ;
169
-
170
- tooltipDiv . transition ( )
171
- . duration ( 400 )
172
- . style ( 'opacity' , 0 ) ;
207
+ . on ( 'mouseout' , function ( d : any ) {
208
+ d3 . select ( this ) . transition ( ) . duration ( 300 ) . attr ( 'r' , 15 ) ;
209
+
210
+ tooltipDiv . transition ( ) . duration ( 400 ) . style ( 'opacity' , 0 ) ;
173
211
} ) ;
174
212
node
175
213
. append ( 'text' )
176
214
// adjusts the y coordinates for the node text
177
215
. attr ( 'dy' , '0.5em' )
178
- . attr ( 'x' , function ( d :{ x : number ; children ?:[ ] } ) {
216
+ . attr ( 'x' , function ( d : { x : number ; children ?: [ ] } ) {
179
217
// this positions how far the text is from leaf nodes (ones without children)
180
218
// negative number before the colon moves the text of rightside nodes,
181
219
// positive number moves the text for the leftside nodes
182
220
return d . x < Math . PI === ! d . children ? 0 : 0 ;
183
221
} )
184
222
. attr ( 'text-anchor' , 'middle' )
185
223
// this arranges the angle of the text
186
- . attr ( 'transform' , function ( d :{ x :number , y :number } ) { return 'rotate(' + ( d . x < Math . PI ? d . x - Math . PI / 2 : d . x + Math . PI / 2 ) * 1 / Math . PI + ')' ; } )
187
- . text ( function ( d :{ data :{ name :number , branch :number } } ) {
224
+ . attr ( 'transform' , function ( d : { x : number ; y : number } ) {
225
+ return (
226
+ 'rotate(' +
227
+ ( ( d . x < Math . PI ? d . x - Math . PI / 2 : d . x + Math . PI / 2 ) * 1 ) /
228
+ Math . PI +
229
+ ')'
230
+ ) ;
231
+ } )
232
+ . text ( function ( d : { data : { name : number ; branch : number } } ) {
188
233
// display the name of the specific patch
189
234
return `${ d . data . name } .${ d . data . branch } ` ;
190
235
} ) ;
191
236
192
237
// allows svg to be dragged around
193
- node . call ( d3 . drag ( )
194
- . on ( 'start' , dragstarted )
195
- . on ( 'drag' , dragged )
196
- . on ( 'end' , dragended ) ) ;
238
+ node . call (
239
+ d3
240
+ . drag ( )
241
+ . on ( 'start' , dragstarted )
242
+ . on ( 'drag' , dragged )
243
+ . on ( 'end' , dragended )
244
+ ) ;
197
245
198
- chartContainer . call ( d3 . zoom ( )
199
- . extent ( [ [ 0 , 0 ] , [ width , height ] ] )
200
- . scaleExtent ( [ 0 , 8 ] ) // scaleExtent([minimum scale factor, maximum scale factor])
201
- . on ( 'zoom' , zoomed ) ) ;
246
+ // d3 zoom functionality
247
+ let zoom = d3 . zoom ( ) . on ( 'zoom' , zoomed ) ;
248
+ svgContainer . call (
249
+ zoom . transform ,
250
+ // Changes the initial view, (left, top)
251
+ d3 . zoomIdentity . translate ( width / 2 , height / 2 ) . scale ( 1 )
252
+ ) ;
253
+ // allows the canvas to be zoom-able
254
+ svgContainer . call (
255
+ d3
256
+ . zoom ( )
257
+ . scaleExtent ( [ 0 , 0.9 ] ) // [zoomOut, zoomIn]
258
+ . on ( 'zoom' , zoomed )
259
+ ) ;
260
+ // helper function that allows for zooming
261
+ function zoomed ( d : any ) {
262
+ g . attr ( 'transform' , d3 . event . transform ) ;
263
+ }
202
264
265
+ // Drag
203
266
function dragstarted ( ) {
204
267
d3 . select ( this ) . raise ( ) ;
205
268
g . attr ( 'cursor' , 'grabbing' ) ;
206
269
}
207
270
208
- function dragged ( d :{ x :number , y :number } ) {
209
- d3 . select ( this ) . attr ( 'dx' , d . x = d3 . event . x ) . attr ( 'dy' , d . y = d3 . event . y ) ;
271
+ function dragged ( d : { x : number ; y : number } ) {
272
+ d3 . select ( this )
273
+ . attr ( 'dx' , ( d . x = d3 . event . x ) )
274
+ . attr ( 'dy' , ( d . y = d3 . event . y ) ) ;
210
275
}
211
276
212
277
function dragended ( ) {
213
278
g . attr ( 'cursor' , 'grab' ) ;
214
279
}
215
280
216
- function zoomed ( ) {
217
- g . attr ( 'transform' , d3 . event . transform ) ;
218
- }
219
-
220
281
// define the div for the tooltip
221
- const tooltipDiv = d3 . select ( 'body' ) . append ( 'div' )
282
+ const tooltipDiv = d3
283
+ . select ( 'body' )
284
+ . append ( 'div' )
222
285
. attr ( 'class' , 'tooltip' )
223
286
. style ( 'opacity' , 0 ) ;
224
287
225
- function reinfeldTidierAlgo ( x :number , y :number ) {
226
- return [ ( y = + y ) * Math . cos ( x -= Math . PI / 2 ) , y * Math . sin ( x ) ] ;
288
+ function reinfeldTidierAlgo ( x : number , y : number ) {
289
+ return [ ( y = + y ) * Math . cos ( ( x -= Math . PI / 2 ) ) , y * Math . sin ( x ) ] ;
227
290
}
228
291
}
229
292
0 commit comments