@@ -19,35 +19,13 @@ import {
19
19
} from "./constants" ;
20
20
import { Bar } from "./Bar" ;
21
21
22
- // When displaying the chart we must consider the time intervals to display the
23
- // data. For example, if the total time is 10 seconds, we should display the
24
- // data in 200ms intervals. However, if the total time is 1 minute, we should
25
- // display the data in 5 seconds intervals. To achieve this, we define the
26
- // dimensions object that contains the time intervals for the chart.
27
- const dimensions = {
28
- small : 500 ,
29
- default : 5_000 ,
30
- } ;
31
-
32
- export type ChartProps = {
33
- data : DataSection [ ] ;
34
- onBarClick : ( label : string , section : string ) => void ;
35
- } ;
36
-
37
- // This chart can split data into sections. Eg. display the provisioning timings
38
- // in one section and the scripting time in another
22
+ // Data can be divided into sections. For example, display the provisioning
23
+ // timings in one section and the scripting timings in another.
39
24
type DataSection = {
40
25
name : string ;
41
26
timings : Timing [ ] ;
42
27
} ;
43
28
44
- // Useful to perform chart operations without requiring additional information
45
- // such as labels or counts, which are only used for display purposes.
46
- export type Duration = {
47
- startedAt : Date ;
48
- endedAt : Date ;
49
- } ;
50
-
51
29
export type Timing = Duration & {
52
30
/**
53
31
* Label that will be displayed on the Y axis.
@@ -59,31 +37,43 @@ export type Timing = Duration & {
59
37
* clearly indicate to the user that the timing encompasses multiple time
60
38
* blocks.
61
39
*/
62
- count : number ;
40
+ childrenCount : number ;
41
+ } ;
42
+
43
+ // Extracts the 'startedAt' and 'endedAt' date fields from the main Timing type.
44
+ // This is useful for performing chart operations without needing additional
45
+ // information like labels or children count, which are only used for display
46
+ // purposes.
47
+ export type Duration = {
48
+ startedAt : Date ;
49
+ endedAt : Date ;
50
+ } ;
51
+
52
+ export type ChartProps = {
53
+ data : DataSection [ ] ;
54
+ onBarClick : ( label : string , section : string ) => void ;
63
55
} ;
64
56
65
57
export const Chart : FC < ChartProps > = ( { data, onBarClick } ) => {
66
58
const totalDuration = duration ( data . flatMap ( ( d ) => d . timings ) ) ;
67
59
const totalTime = durationTime ( totalDuration ) ;
68
- // Use smaller dimensions for the chart if the total time is less than 10
69
- // seconds; otherwise, use default intervals.
70
- const dimension = totalTime < 10_000 ? dimensions . small : dimensions . default ;
71
-
72
- // XAxis intervals
73
- const intervalsCount = Math . ceil ( totalTime / dimension ) ;
74
- const intervals = Array . from (
75
- { length : intervalsCount } ,
76
- ( _ , i ) => i * dimension + dimension ,
60
+
61
+ // XAxis ticks
62
+ const tickSpacing = calcTickSpacing ( totalTime ) ;
63
+ const ticksCount = Math . ceil ( totalTime / tickSpacing ) ;
64
+ const ticks = Array . from (
65
+ { length : ticksCount } ,
66
+ ( _ , i ) => i * tickSpacing + tickSpacing ,
77
67
) ;
78
68
79
- // Helper function to convert time into pixel size, used for setting bar width
80
- // and offset
69
+ // Helper function to convert the tick spacing into pixel size. This is used
70
+ // for setting the bar width and offset.
81
71
const calcSize = ( time : number ) : number => {
82
- return ( columnWidth * time ) / dimension ;
72
+ return ( columnWidth * time ) / tickSpacing ;
83
73
} ;
84
74
85
75
const formatTime = ( time : number ) : string => {
86
- if ( dimension === dimensions . small ) {
76
+ if ( tickSpacing <= 1_000 ) {
87
77
return `${ time . toLocaleString ( ) } ms` ;
88
78
}
89
79
return `${ ( time / 1_000 ) . toLocaleString ( undefined , {
@@ -112,7 +102,7 @@ export const Chart: FC<ChartProps> = ({ data, onBarClick }) => {
112
102
</ YAxis >
113
103
114
104
< div css = { styles . main } >
115
- < XAxis labels = { intervals . map ( formatTime ) } />
105
+ < XAxis labels = { ticks . map ( formatTime ) } />
116
106
< div css = { styles . content } >
117
107
{ data . map ( ( section ) => {
118
108
return (
@@ -129,16 +119,16 @@ export const Chart: FC<ChartProps> = ({ data, onBarClick }) => {
129
119
afterLabel = { formatTime ( durationTime ( t ) ) }
130
120
aria-labelledby = { `${ t . label } -label` }
131
121
ref = { applyBarHeightToLabel }
132
- disabled = { t . count <= 1 }
122
+ disabled = { t . childrenCount <= 1 }
133
123
onClick = { ( ) => {
134
- if ( t . count <= 1 ) {
124
+ if ( t . childrenCount <= 1 ) {
135
125
return ;
136
126
}
137
127
onBarClick ( t . label , section . name ) ;
138
128
} }
139
129
>
140
- { t . count > 1 && (
141
- < TimingBlocks size = { size } count = { t . count } />
130
+ { t . childrenCount > 1 && (
131
+ < TimingBlocks size = { size } count = { t . childrenCount } />
142
132
) }
143
133
</ Bar >
144
134
) ;
@@ -147,13 +137,30 @@ export const Chart: FC<ChartProps> = ({ data, onBarClick }) => {
147
137
) ;
148
138
} ) }
149
139
150
- < XGrid columns = { intervals . length } />
140
+ < XGrid columns = { ticks . length } />
151
141
</ div >
152
142
</ div >
153
143
</ div >
154
144
) ;
155
145
} ;
156
146
147
+ // When displaying the chart we must consider the time intervals to display the
148
+ // data. For example, if the total time is 10 seconds, we should display the
149
+ // data in 200ms intervals. However, if the total time is 1 minute, we should
150
+ // display the data in 5 seconds intervals. To achieve this, we define the
151
+ // dimensions object that contains the time intervals for the chart.
152
+ const tickSpacings = [ 100 , 500 , 5_000 ] ;
153
+
154
+ const calcTickSpacing = ( totalTime : number ) : number => {
155
+ const spacings = tickSpacings . slice ( ) . reverse ( ) ;
156
+ for ( const s of spacings ) {
157
+ if ( totalTime > s ) {
158
+ return s ;
159
+ }
160
+ }
161
+ return spacings [ 0 ] ;
162
+ } ;
163
+
157
164
// Ensures the sidebar label remains vertically aligned with its corresponding bar.
158
165
const applyBarHeightToLabel = ( bar : HTMLDivElement | null ) => {
159
166
if ( ! bar ) {
0 commit comments