Passed
Push — master ( c23847...6dac30 )
by Guangyu
04:22 queued 10s
created

RealtimeChart.componentDidMount   D

Complexity

Conditions 11

Size

Total Lines 104
Code Lines 81

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 81
dl 0
loc 104
rs 4.4018
c 0
b 0
f 0
cc 11

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like RealtimeChart.componentDidMount often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import React, { Component } from 'react';
2
import { Line } from 'react-chartjs-2';
3
import range from 'lodash/range';
4
import { Card, CardHeader, CardBody, ListGroup, ListGroupItem } from 'reactstrap';
5
import { rgbaColor } from '../../../helpers/utils';
6
import { withTranslation } from 'react-i18next';
7
import uuid from 'uuid/v1';
8
import { APIBaseURL } from '../../../config';
9
import { getCookieValue, createCookie } from '../../../helpers/utils';
10
import { toast } from 'react-toastify';
11
12
13
const trendLog = [
14
];
15
const dividerBorder = '1px solid rgba(255, 255, 255, 0.15)';
16
const listItemBorderColor = 'rgba(255, 255, 255, 0.05)';
17
18
const chartOptions = {
19
  legend: { display: false },
20
  scales: {
21
    yAxes: [
22
      {
23
        display: true,
24
        stacked: false
25
      }
26
    ],
27
    xAxes: [
28
      {
29
        stacked: false,
30
        ticks: { display: false },
31
        categoryPercentage: 1.0,
32
        gridLines: {
33
          color: rgbaColor('#fff', 0.1),
34
          display: true
35
        }
36
      }
37
    ]
38
  }
39
};
40
41
class RealtimeChart extends Component {
42
  _isMounted = false;
43
  refreshInterval;
44
  refreshTimeout;
45
  state = {
46
    trendLog,
47
    currentEnergyValue: trendLog[trendLog.length - 1],
48
    chartData: {
49
      labels: range(1, 60),
50
      datasets: [
51
        {
52
          label: 'Users',
53
          backgroundColor: rgbaColor('#fff', 0.3),
54
        }
55
      ]
56
    },
57
    pointList: [],
58
  };
59
60
  componentWillUnmount() {
61
    this._isMounted = false;
62
    clearInterval(this.refreshInterval);
63
    clearTimeout(this.refreshTimeout);
64
  }
65
66
  componentDidMount() {
67
    this._isMounted = true;
68
    // fetch meter realtime data at the first time
69
    let isResponseOK = false;
70
    fetch(APIBaseURL + '/reports/meterrealtime?meterid=' + this.props.meterId, {
71
      method: 'GET',
72
      headers: {
73
        "Content-type": "application/json",
74
        "User-UUID": getCookieValue('user_uuid'),
75
        "Token": getCookieValue('token')
76
      },
77
      body: null,
78
79
    }).then(response => {
80
      if (response.ok) {
81
        isResponseOK = true;
82
      }
83
      return response.json();
84
    }).then(json => {
85
      if (isResponseOK) {
86
        console.log(json);
87
        const trendLog = json['energy_value']['values'];
88
        const currentEnergyValue = undefined;
89
        const pointList = [];
90
        if (trendLog.length > 0) {
91
          currentEnergyValue = trendLog[trendLog.length - 1];
92
        }
93
        json['parameters']['names'].forEach((currentName, index) => {
94
          let pointItem = {}
95
          pointItem['name'] = currentName;
96
          pointItem['value'] = undefined;
97
          let currentValues = json['parameters']['values'][index];
98
          if (currentValues.length > 0) {
99
            pointItem['value'] = currentValues[currentValues.length - 1];
100
          }
101
          pointList.push(pointItem);
102
        });
103
        if (this._isMounted) {
104
          this.setState({ 
105
            trendLog: trendLog, 
106
            currentEnergyValue: currentEnergyValue,
107
            pointList: pointList,
108
          });
109
        }
110
        // todo
111
      } else {
112
        toast.error(json.description)
113
      }
114
    }).catch(err => {
115
      console.log(err);
116
    });
117
118
    //fetch meter realtime data at regular intervals
119
    this.refreshInterval = setInterval(() => {
120
      let isResponseOK = false;
121
      fetch(APIBaseURL + '/reports/meterrealtime?meterid=' + this.props.meterId, {
122
        method: 'GET',
123
        headers: {
124
          "Content-type": "application/json",
125
          "User-UUID": getCookieValue('user_uuid'),
126
          "Token": getCookieValue('token')
127
        },
128
        body: null,
129
130
      }).then(response => {
131
        if (response.ok) {
132
          isResponseOK = true;
133
        }
134
        return response.json();
135
      }).then(json => {
136
        if (isResponseOK) {
137
          console.log(json);
138
          const trendLog = json['energy_value']['values'];
139
          const currentEnergyValue = undefined;
140
          const pointList = [];
141
          if (trendLog.length > 0) {
142
            currentEnergyValue = trendLog[trendLog.length - 1];
143
          }
144
          json['parameters']['names'].forEach((currentName, index) => {
145
            let pointItem = {}
146
            pointItem['name'] = currentName;
147
            pointItem['value'] = undefined;
148
            let currentValues = json['parameters']['values'][index];
149
            if (currentValues.length > 0) {
150
              pointItem['value'] = currentValues[currentValues.length - 1];
151
            }
152
            pointList.push(pointItem);
153
          });
154
          if (this._isMounted) {
155
            this.setState({ 
156
              trendLog: trendLog, 
157
              currentEnergyValue: currentEnergyValue,
158
              pointList: pointList,
159
            });
160
          }
161
          // todo
162
        } else {
163
          toast.error(json.description)
164
        }
165
      }).catch(err => {
166
        console.log(err);
167
      });
168
    }, (60 + Math.floor(Math.random() * Math.floor(10))) * 1000); // use random interval to avoid paralels requests 
169
  }
170
171
  render() {
172
    const { t } = this.props;
173
    const chartData = {
174
      ...this.state.chartData,
175
      datasets: [
176
        {
177
          ...this.state.chartData.datasets[0],
178
          data: this.state.trendLog
179
        }
180
      ]
181
    };
182
183
    return (
184
      <Card className="h-100 bg-gradient">
185
        <CardHeader className="bg-transparent">
186
          <h5 className="text-white">{this.props.meterName}</h5>
187
          <div className="real-time-user display-1 font-weight-normal text-white">{this.state.currentEnergyValue}</div>
188
        </CardHeader>
189
        <CardBody className="text-white fs--1">
190
          <p className="pb-2" style={{ borderBottom: dividerBorder }}>
191
          {t('Trend in the last hour of Energy Value Point (UNIT)', {'UNIT': 'kWh'})}
192
          </p>
193
          <Line data={chartData} options={chartOptions} width={10} height={4} />
194
          <ListGroup flush className="mt-4">
195
          
196
            <ListGroupItem
197
              className="bg-transparent d-flex justify-content-between px-0 py-1 font-weight-semi-bold border-top-0"
198
              style={{ borderColor: listItemBorderColor }}
199
            >
200
              <p className="mb-0">{t('Related Parameters')}</p>
201
              <p className="mb-0">{t('Realtime Value')}</p>
202
            </ListGroupItem>
203
            {this.state.pointList.map(pointItem => (
204
              <ListGroupItem key={uuid()}
205
                className="bg-transparent d-flex justify-content-between px-0 py-1"
206
                style={{ borderColor: listItemBorderColor }}
207
              >
208
                <p className="mb-0">{pointItem['name']}</p>
209
                <p className="mb-0">{pointItem['value']}</p>
210
              </ListGroupItem>
211
            ))}
212
          </ListGroup>
213
        </CardBody>
214
      </Card>
215
    );
216
  }
217
}
218
219
export default  withTranslation()(RealtimeChart);
220