1
1
import { Component } from 'preact' ;
2
2
import { connect } from 'unistore/preact' ;
3
3
import cx from 'classnames' ;
4
-
4
+ import { Link } from 'preact-router/match' ;
5
5
import { Text , Localizer } from 'preact-i18n' ;
6
6
import style from './style.css' ;
7
7
import { WEBSOCKET_MESSAGE_TYPES , DEVICE_FEATURE_UNITS } from '../../../../../server/utils/constants' ;
8
8
import get from 'get-value' ;
9
9
import withIntlAsProp from '../../../utils/withIntlAsProp' ;
10
10
import ApexChartComponent from './ApexChartComponent' ;
11
- import ChartBoxExpanded from './Chart' ;
12
11
13
12
const ONE_HOUR_IN_MINUTES = 60 ;
14
13
const ONE_DAY_IN_MINUTES = 24 * 60 ;
@@ -26,6 +25,13 @@ const intervalByName = {
26
25
'last-year' : ONE_YEAR_IN_MINUTES
27
26
} ;
28
27
28
+ const getTypeByInterval = interval => {
29
+ if ( interval >= ONE_DAY_IN_MINUTES ) return 'hourly' ;
30
+ if ( interval >= THIRTY_DAYS_IN_MINUTES ) return 'daily' ;
31
+ if ( interval >= ONE_YEAR_IN_MINUTES ) return 'monthly' ;
32
+ return 'live' ;
33
+ } ;
34
+
29
35
const UNITS_WHEN_DOWN_IS_POSITIVE = [ DEVICE_FEATURE_UNITS . WATT_HOUR ] ;
30
36
31
37
const notNullNotUndefined = value => {
@@ -114,6 +120,7 @@ class Chartbox extends Component {
114
120
} ) ;
115
121
this . getData ( ) ;
116
122
} ;
123
+
117
124
getData = async ( ) => {
118
125
let deviceFeatures = this . props . box . device_features ;
119
126
if ( ! deviceFeatures ) {
@@ -133,12 +140,42 @@ class Chartbox extends Component {
133
140
return ;
134
141
}
135
142
await this . setState ( { loading : true } ) ;
143
+
144
+ let type ;
145
+ if ( this . props . showHistoryExpanded ) {
146
+ let intervalDate ;
147
+ if ( this . state . startDate && this . state . endDate ) {
148
+ intervalDate = ( this . state . endDate - this . state . startDate ) / 60000 ;
149
+ } else {
150
+ intervalDate = this . state . interval ;
151
+ }
152
+ if ( intervalDate <= ONE_DAY_IN_MINUTES ) {
153
+ type = 'live' ;
154
+ } else {
155
+ type = getTypeByInterval ( intervalDate , this . props . box . chart_type ) ;
156
+ }
157
+ } else {
158
+ type = getTypeByInterval ( this . state . interval , this . props . box . chart_type ) ;
159
+ }
136
160
try {
137
- const data = await this . props . httpClient . get ( `/api/v1/device_feature/aggregated_states` , {
138
- interval : this . state . interval ,
139
- max_states : 100 ,
140
- device_features : deviceFeatures . join ( ',' )
141
- } ) ;
161
+ let data ;
162
+ if ( type === 'live' ) {
163
+ data = await this . props . httpClient . get ( `/api/v1/device_feature/aggregated_states` , {
164
+ interval : this . state . interval ,
165
+ max_states : this . state . maxStatesLive ,
166
+ device_features : deviceFeatures . join ( ',' ) ,
167
+ start_date : this . state . startDate ? this . state . startDate . toISOString ( ) : null ,
168
+ end_date : this . state . endDate ? this . state . endDate . toISOString ( ) : null
169
+ } ) ;
170
+ } else {
171
+ data = await this . props . httpClient . get ( `/api/v1/device_feature/aggregated_states` , {
172
+ interval : this . state . interval ,
173
+ max_states : this . state . maxStatesNoLive ,
174
+ device_features : deviceFeatures . join ( ',' ) ,
175
+ start_date : this . state . startDate ? this . state . startDate . toISOString ( ) : undefined ,
176
+ end_date : this . state . endDate ? this . state . endDate . toISOString ( ) : undefined
177
+ } ) ;
178
+ }
142
179
143
180
let emptySeries = true ;
144
181
@@ -284,14 +321,38 @@ class Chartbox extends Component {
284
321
interval : intervalByName [ this . props . box . interval ]
285
322
} ) ;
286
323
} ;
324
+
325
+ handleZoom = async ( min , max ) => {
326
+ if ( min === null || max === null ) {
327
+ await this . setState ( {
328
+ startDate : null ,
329
+ endDate : null
330
+ } ) ;
331
+ this . getData ( ) ;
332
+ } else {
333
+ await this . setState ( {
334
+ startDate : new Date ( min ) ,
335
+ endDate : new Date ( max )
336
+ } ) ;
337
+ this . getData ( ) ;
338
+ }
339
+ } ;
340
+
287
341
constructor ( props ) {
288
342
super ( props ) ;
289
343
this . props = props ;
344
+ console . log ( 'props constructor Chart' , props ) ;
290
345
this . state = {
291
346
interval : this . props . box . interval ? intervalByName [ this . props . box . interval ] : ONE_HOUR_IN_MINUTES ,
292
347
loading : true ,
293
348
initialized : false ,
294
- height : 'small'
349
+ height : 'small' ,
350
+ startDate : null ,
351
+ endDate : null ,
352
+ dropdownOpen : false ,
353
+ selectedCriteria : 'before' ,
354
+ maxStatesLive : 10000 ,
355
+ maxStatesNoLive : 1000
295
356
} ;
296
357
}
297
358
componentDidMount ( ) {
@@ -320,6 +381,7 @@ class Chartbox extends Component {
320
381
this . updateDeviceStateWebsocket
321
382
) ;
322
383
}
384
+
323
385
render (
324
386
props ,
325
387
{
@@ -332,18 +394,26 @@ class Chartbox extends Component {
332
394
lastValueRounded,
333
395
interval,
334
396
emptySeries,
335
- unit
397
+ unit,
398
+ startDate,
399
+ endDate
336
400
}
337
401
) {
338
- const { box, displayPreview, showCloseButton, showHistoryZoom } = this . props ;
402
+ const { box, displayPreview, showHistoryExpanded } = this . props ;
403
+
339
404
const displayVariation = box . display_variation ;
340
405
const nbDeviceFeatures = box . device_features . length ;
341
406
let heightAdditional = 0 ;
342
- if ( showHistoryZoom ) {
407
+ if ( showHistoryExpanded === true ) {
408
+ console . log ( 'props render Chart' , props ) ;
409
+ console . log ( 'this render Chart' , this ) ;
410
+ }
411
+ const showAggregatedDataWarning = this . state . series && this . state . series . some ( serie => serie . data . length === this . state . maxStatesNoLive ) ;
412
+ if ( showHistoryExpanded ) {
343
413
if ( props . box . chart_type === 'timeline' && nbDeviceFeatures > 2 ) {
344
414
heightAdditional = 56 * ( nbDeviceFeatures - 2 ) ;
345
415
} else {
346
- heightAdditional = 200 ;
416
+ heightAdditional = 300 ;
347
417
}
348
418
} else if ( props . box . chart_type === 'timeline' && nbDeviceFeatures > 3 ) {
349
419
heightAdditional = 38 * ( nbDeviceFeatures - 3 ) ;
@@ -353,6 +423,14 @@ class Chartbox extends Component {
353
423
< div class = "card-body" >
354
424
< div class = "d-flex align-items-center justify-content-between" >
355
425
< div class = { cx ( style . subheader ) } > { props . box . title } </ div >
426
+ { showHistoryExpanded && ! showAggregatedDataWarning && (
427
+ < div class = { cx ( "ml-5 mr-5" , style . subheader ) } >
428
+ < Text id = "dashboard.boxes.chart.historyExpandedWarningStateLive" />
429
+ </ div >
430
+ ) }
431
+ { showHistoryExpanded && showAggregatedDataWarning && (
432
+ < div class = { cx ( "ml-5 mr-5" , style . subheader ) } > { "(ATTENTION: Données aggrégées sur l'intervalle, vous pouvez zoomer sur un intervalle plus petit pour voir les données réelles)" } </ div >
433
+ ) }
356
434
< div class = { cx ( style . msAuto , style . lh1 , 'd-flex' , 'align-items-center' ) } >
357
435
< div class = "dropdown" >
358
436
< a class = "dropdown-toggle text-muted text-nowrap" onClick = { this . toggleDropdown } >
@@ -384,7 +462,7 @@ class Chartbox extends Component {
384
462
>
385
463
< Text id = "dashboard.boxes.chart.lastDay" />
386
464
</ a >
387
- { props . box . chart_type !== 'timeline' && (
465
+ { ( props . box . chart_type !== 'timeline' || showHistoryExpanded ) && (
388
466
< a
389
467
className = { cx ( style . dropdownItemChart , {
390
468
[ style . active ] : interval === SEVEN_DAYS_IN_MINUTES
@@ -394,7 +472,7 @@ class Chartbox extends Component {
394
472
< Text id = "dashboard.boxes.chart.lastSevenDays" />
395
473
</ a >
396
474
) }
397
- { props . box . chart_type !== 'timeline' && (
475
+ { ( props . box . chart_type !== 'timeline' || showHistoryExpanded ) && (
398
476
< a
399
477
className = { cx ( style . dropdownItemChart , {
400
478
[ style . active ] : interval === THIRTY_DAYS_IN_MINUTES
@@ -404,7 +482,7 @@ class Chartbox extends Component {
404
482
< Text id = "dashboard.boxes.chart.lastThirtyDays" />
405
483
</ a >
406
484
) }
407
- { props . box . chart_type !== 'timeline' && (
485
+ { ( props . box . chart_type !== 'timeline' || showHistoryExpanded ) && (
408
486
< a
409
487
className = { cx ( style . dropdownItemChart , {
410
488
[ style . active ] : interval === THREE_MONTHS_IN_MINUTES
@@ -414,7 +492,7 @@ class Chartbox extends Component {
414
492
< Text id = "dashboard.boxes.chart.lastThreeMonths" />
415
493
</ a >
416
494
) }
417
- { props . box . chart_type !== 'timeline' && (
495
+ { ( props . box . chart_type !== 'timeline' || showHistoryExpanded ) && (
418
496
< a
419
497
className = { cx ( style . dropdownItemChart , {
420
498
[ style . active ] : interval === ONE_YEAR_IN_MINUTES
@@ -426,35 +504,16 @@ class Chartbox extends Component {
426
504
) }
427
505
</ div >
428
506
</ div >
429
- { this . state . showHistory && (
430
- < div class = { cx ( style . modalOverlay ) } >
431
- < div class = { cx ( 'card-body' , style . cardBody ) } >
432
- < ChartBoxExpanded
433
- { ...props }
434
- showHistoryZoom = { this . state . showHistory }
435
- showCloseButton = { true }
436
- onClose = { ( ) => this . setState ( { showHistory : false } ) }
437
- />
438
- </ div >
439
- </ div >
440
- ) }
441
- { showCloseButton && (
442
- < button
443
- class = { cx ( 'btn btn-outline-secondary' , style . customBtnCommon , style . closeButton ) }
444
- onClick = { ( ) => this . props . onClose ( ) }
445
- >
446
- < i class = "fe fe-x" />
447
- </ button >
448
- ) }
449
- { ! displayPreview && ! showHistoryZoom && (
507
+ { ! displayPreview && ! showHistoryExpanded && (
450
508
< Localizer >
451
- < button
509
+
510
+ < Link
452
511
class = { cx ( 'btn btn-outline-secondary' , style . customBtnCommon , style . customBtn ) }
453
- onClick = { ( ) => this . setState ( { showHistory : true } ) }
512
+ href = { `/dashboard/ ${ props . dashboardSelector } /expanded/ ${ props . x } / ${ props . y } ` }
454
513
title = { < Text id = "dashboard.boxes.chart.expandChartButtonDescription" /> }
455
514
>
456
515
< i class = "fe fe-airplay" />
457
- </ button >
516
+ </ Link >
458
517
</ Localizer >
459
518
) }
460
519
</ div >
0 commit comments