2
2
// See the LICENCE file in the repository root for full licence text.
3
3
4
4
import * as d3 from 'd3' ;
5
- import { first , groupBy , kebabCase , last , map , sumBy } from 'lodash' ;
5
+ import { first , groupBy , kebabCase , keyBy , last , map } from 'lodash' ;
6
6
import moment from 'moment' ;
7
7
import { fadeIn , fadeOut } from 'utils/fade' ;
8
8
import { formatNumber } from 'utils/html' ;
@@ -11,7 +11,6 @@ import { parseJson } from 'utils/json';
11
11
interface BuildHistory {
12
12
created_at : string ;
13
13
label : string ;
14
- normalized ?: number ;
15
14
user_count : number ;
16
15
}
17
16
@@ -36,7 +35,6 @@ export default class ChangelogChart {
36
35
private autoHideTooltip ?: number ;
37
36
private chartData ?: ChartData ;
38
37
private data : d3 . Series < DataObj , string > [ ] = [ ] ;
39
- private hasData = false ;
40
38
private height = 0 ;
41
39
private readonly hoverArea ;
42
40
private readonly scales ;
@@ -53,6 +51,10 @@ export default class ChangelogChart {
53
51
private x ?: Date ;
54
52
private y ?: number ;
55
53
54
+ private get hasData ( ) {
55
+ return this . data . length > 0 ;
56
+ }
57
+
56
58
constructor ( area : HTMLElement ) {
57
59
this . scales = {
58
60
class : d3 . scaleOrdinal < string > ( ) ,
@@ -118,15 +120,15 @@ export default class ChangelogChart {
118
120
loadData ( ) {
119
121
this . chartData = parseJson ( 'json-chart-config' ) ;
120
122
121
- const { data, hasData } = this . normalizeData ( this . chartData . build_history ) ;
123
+ const data = this . normalizeData ( this . chartData . build_history ) ;
122
124
123
125
const stack = d3
124
126
. stack < DataObj , string > ( )
125
127
. keys ( this . chartData . order )
126
- . value ( ( d , val ) => ( d . builds [ val ] ?. normalized ?? 0 ) ) ;
128
+ . offset ( d3 . stackOffsetExpand )
129
+ . value ( ( d , val ) => ( d . builds [ val ] ?. user_count ?? 0 ) ) ;
127
130
128
131
this . data = stack ( data ) ;
129
- this . hasData = this . chartData . build_history . length > 0 && hasData ;
130
132
131
133
this . resize ( ) ;
132
134
}
@@ -157,53 +159,20 @@ export default class ChangelogChart {
157
159
private normalizeData ( rawData : BuildHistory [ ] ) {
158
160
// normalize the user count values
159
161
// and parse data into a form digestible by d3.stack()
160
-
161
- let resetLabel : string | null = null ;
162
- let hasData : boolean | null = null ;
163
-
164
162
const sortedData = groupBy ( rawData , 'created_at' ) ;
165
163
166
- const data = map ( sortedData , ( values , timestamp ) => {
167
- let sum = sumBy ( values , 'user_count' ) ;
168
-
169
- if ( sum === 0 ) {
170
- let fakedVal = resetLabel != null
171
- ? values . find ( ( val ) => val . label === resetLabel )
172
- : null ;
173
-
174
- if ( fakedVal == null ) {
175
- fakedVal = last ( values ) ;
176
- resetLabel = fakedVal ?. label ?? null ;
177
- }
178
-
179
- if ( fakedVal ) fakedVal . user_count = 1 ;
180
- sum = 1 ;
181
- } else {
182
- hasData ??= true ;
183
- }
184
-
164
+ return map ( sortedData , ( values , timestamp ) : DataObj => {
185
165
// parse date stored in strings to JS Date object for use by
186
166
// d3 domains, and format it into a string shown on the tooltip
187
- const m = moment ( values [ 0 ] . created_at ) ;
167
+ const m = moment ( timestamp ) ;
188
168
189
- const obj : DataObj = {
190
- builds : { } ,
169
+ return {
170
+ builds : keyBy ( values , 'label' ) ,
191
171
created_at : timestamp ,
192
172
date : m . toDate ( ) ,
193
173
date_formatted : m . format ( 'YYYY/MM/DD' ) ,
194
174
} ;
195
-
196
- for ( const val of values ) {
197
- obj . builds [ val . label ] = val ;
198
- obj . builds [ val . label ] . normalized = val . user_count / sum ;
199
- }
200
-
201
- return obj ;
202
175
} ) ;
203
-
204
- hasData ??= false ;
205
-
206
- return { data, hasData } ;
207
176
}
208
177
209
178
private setDimensions ( ) {
0 commit comments