1- /*
2- * This Source Code Form is subject to the terms of the Mozilla Public
1+ /* This Source Code Form is subject to the terms of the Mozilla Public
32 * License, v. 2.0. If a copy of the MPL was not distributed with this
43 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
54 */
65
7- import { connect } from 'react-redux' ;
8- import { getComparePeriodLabels , getCompareChangeSummary , calculateCompareShift } from '../utils/calculateCompare' ;
9- // import { useTranslate } from 'redux/componentHooks';
10- // import * as React from 'react'; Convert from containers to components
11- // import { useState } from 'react';
12- // When this container gets converted to component,migrate to useTranslate() from componentHooks.ts
13- import translate from '../utils/translate' ;
6+ import * as React from 'react' ;
147import Plot from 'react-plotly.js' ;
15- // import { Icons } from 'plotly.js';
16- import Locales from '../types/locales' ;
178import * as moment from 'moment' ;
18- import { UnitRepresentType } from '../types/redux/units' ;
19- import { getAreaUnitConversion } from '../utils/getAreaUnitConversion' ;
20- import { selectUnitDataById } from '../redux/api/unitsApi' ;
21- import { RootState } from '../store' ;
22- import { selectGroupDataById } from '../redux/api/groupsApi' ;
23- import { selectMeterDataById } from '../redux/api/metersApi' ;
9+ import { useAppSelector } from '../redux/reduxHooks' ;
2410import {
2511 selectAreaUnit , selectComparePeriod ,
2612 selectCompareTimeInterval , selectGraphAreaNormalization ,
2713 selectSelectedUnit
2814} from '../redux/slices/graphSlice' ;
2915import { selectSelectedLanguage } from '../redux/slices/appStateSlice' ;
16+ import Locales from '../types/locales' ;
17+ import { getComparePeriodLabels , getCompareChangeSummary , calculateCompareShift } from '../utils/calculateCompare' ;
18+ import { getAreaUnitConversion } from '../utils/getAreaUnitConversion' ;
19+ import { UnitRepresentType } from '../types/redux/units' ;
20+ import { selectUnitDataById } from '../redux/api/unitsApi' ;
21+ import { selectMeterDataById } from '../redux/api/metersApi' ;
22+ import { selectGroupDataById } from '../redux/api/groupsApi' ;
23+ import { useTranslate } from '../redux/componentHooks' ;
3024
3125export interface CompareEntity {
3226 id : number ;
@@ -39,32 +33,24 @@ export interface CompareEntity {
3933 prevTotalUsage ?: number ;
4034}
4135
42- interface CompareChartContainerProps {
36+ interface CompareBarComponentProps {
4337 entity : CompareEntity ;
4438}
4539
46- /**
47- * Passes the current redux state of the of the chart container and it's props, and turns it into props for the React
48- * component, which is what will be visible on the page. Makes it possible to access
49- * your reducer state objects from within your React components.
50- * @param state The redux state
51- * @param ownProps Chart container props
52- * @returns The props object
53- */
54- function mapStateToProps ( state : RootState , ownProps : CompareChartContainerProps ) : any {
55- const comparePeriod = selectComparePeriod ( state ) ;
56- const compareTimeInterval = selectCompareTimeInterval ( state ) ;
57- const datasets : any [ ] = [ ] ;
40+ const CompareBarComponent : React . FC < CompareBarComponentProps > = ( { entity } ) => {
41+ const comparePeriod = useAppSelector ( selectComparePeriod ) ;
42+ const compareTimeInterval = useAppSelector ( selectCompareTimeInterval ) ;
5843 const periodLabels = getComparePeriodLabels ( comparePeriod ) ;
59- // The unit label depends on the unit which is in selectUnit state.
60- // Also need to determine if raw.
61- const graphingUnit = selectSelectedUnit ( state ) ;
62- // This container is not called if there is no data of there are not units so this is safe.
63- const unitDataById = selectUnitDataById ( state ) ;
64- const meterDataById = selectMeterDataById ( state ) ;
65- const groupDataById = selectGroupDataById ( state ) ;
44+
45+ const datasets : any [ ] = [ ] ;
46+ const graphingUnit = useAppSelector ( selectSelectedUnit ) ;
47+ const unitDataById = useAppSelector ( selectUnitDataById ) ;
48+ const meterDataById = useAppSelector ( selectMeterDataById ) ;
49+ const groupDataById = useAppSelector ( selectGroupDataById ) ;
6650 const selectUnitState = unitDataById [ graphingUnit ] ;
67- const locale = selectSelectedLanguage ( state ) ;
51+ const locale = useAppSelector ( selectSelectedLanguage ) ;
52+
53+ const translate = useTranslate ( ) ;
6854 let unitLabel : string = '' ;
6955 // If graphingUnit is -99 then none selected and nothing to graph so label is empty.
7056 // This will probably happen when the page is first loaded.
@@ -89,17 +75,16 @@ function mapStateToProps(state: RootState, ownProps: CompareChartContainerProps)
8975 }
9076 }
9177
92- /* TODO When I click this icon it crashes OED. The error relates to using a Hook (useState, I think)
93- outside a component. This does not use a component as the other graphics do as it is
94- a container. It either needs a modified solution or the component needs to be converted.
95- Only after the component has been converted uncomment the code below and in plotly config
78+ // Unlike line, bar, etc., testing found that the only two buttons that can be shown
79+ // (outside download plot and plotly info) is box select & lasso select. Neither is
80+ // desired so this lists the default ones to remove (those two) but does not use state
81+ // to change it dynamically.
82+ // Note: Since this is a 2D graphic and the regular bar graphic has more buttons it is
83+ // unclear why it only has these two buttons.
84+ // This website was consulted: https://plotly.com/javascript/configuration-options/#remove-modebar-buttons
85+ // on the expected buttons.
9686 // Display Plotly Buttons Feature:
97- // The number of items in defaultButtons and advancedButtons must differ as discussed below */
98- const defaultButtons : Plotly . ModeBarDefaultButtons [ ] = [ 'zoom2d' , 'pan2d' , 'select2d' , 'lasso2d' , 'zoomIn2d' , 'zoomOut2d' , 'autoScale2d' ,
99- 'resetScale2d' ] ;
100- /* const advancedButtons: Plotly.ModeBarDefaultButtons[] = ['select2d', 'lasso2d', 'autoScale2d', 'resetScale2d'];
101- // Manage button states with useState
102- const [listOfButtons, setListOfButtons] = useState(defaultButtons); */
87+ const defaultButtons : Plotly . ModeBarDefaultButtons [ ] = [ 'select2d' , 'lasso2d' ] ;
10388
10489 // Get the time shift for this comparison as a moment duration
10590 const compareShift = calculateCompareShift ( comparePeriod ) ;
@@ -142,20 +127,19 @@ function mapStateToProps(state: RootState, ownProps: CompareChartContainerProps)
142127 } ;
143128
144129 // Compose the text to display to the user.
145- const entity = ownProps . entity ;
146130 const changeSummary = getCompareChangeSummary ( entity . change , entity . identifier , periodLabels ) ;
147131
148132 const barColor = 'rgba(218, 165, 32, 1)' ;
149133
150134 let previousPeriod = entity . prevUsage ;
151135 let currentPeriod = entity . currUsage ;
152- const areaNormalization = selectGraphAreaNormalization ( state ) ;
136+ const areaNormalization = useAppSelector ( selectGraphAreaNormalization ) ;
153137 // Check if there is data to graph.
154138 if ( previousPeriod !== null && currentPeriod !== null ) {
155139 if ( areaNormalization ) {
156140 const area = entity . isGroup ? groupDataById [ entity . id ] . area : meterDataById [ entity . id ] . area ;
157141 const areaUnit = entity . isGroup ? groupDataById [ entity . id ] . areaUnit : meterDataById [ entity . id ] . areaUnit ;
158- const normalization = area * getAreaUnitConversion ( areaUnit , selectAreaUnit ( state ) ) ;
142+ const normalization = area * getAreaUnitConversion ( areaUnit , useAppSelector ( selectAreaUnit ) ) ;
159143 previousPeriod /= normalization ;
160144 currentPeriod /= normalization ;
161145 }
@@ -241,31 +225,18 @@ function mapStateToProps(state: RootState, ownProps: CompareChartContainerProps)
241225 } ;
242226 }
243227
244- // Assign all the parameters required to create the Plotly object (data, layout, config) to the variable props, returned by mapStateToProps
245- // The Plotly toolbar is displayed if displayModeBar is set to true
246- const props : any = {
247- data : datasets ,
248- layout,
249- config : {
250- displayModeBar : true ,
251- modeBarButtonsToRemove : defaultButtons ,
252- // TODO: Removes line above and uncomment below. Read above for more info
253- // modeBarButtonsToRemove: listOfButtons,
254- // modeBarButtonsToAdd: [{
255- // name: 'toggle-options',
256- // title: translate('toggle.options'),
257- // icon: Icons.pencil,
258- // click: function () {
259- // // # of items must differ so the length can tell which list of buttons is being set
260- // setListOfButtons(listOfButtons.length === defaultButtons.length ? advancedButtons : defaultButtons); // Update the state
261- // }
262- // }],
263- locale,
264- locales : Locales // makes locales available for use
265- }
266- } ;
267- props . config . locale = state . appState . selectedLanguage ;
268- return props ;
269- }
228+ return (
229+ < Plot
230+ data = { datasets }
231+ layout = { layout }
232+ config = { {
233+ displayModeBar : true ,
234+ modeBarButtonsToRemove : defaultButtons ,
235+ locale,
236+ locales : Locales
237+ } }
238+ />
239+ ) ;
240+ } ;
270241
271- export default connect ( mapStateToProps ) ( Plot ) ;
242+ export default CompareBarComponent ;
0 commit comments