Passed
Push — master ( 9a2876...4f3f28 )
by Guangyu
04:12 queued 14s
created

src/components/MyEMS/Meter/MeterTrend.js   A

Complexity

Total Complexity 11
Complexity/F 0

Size

Lines of Code 406
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 11
eloc 349
mnd 11
bc 11
fnc 0
dl 0
loc 406
rs 10
bpm 0
cpm 0
noi 0
c 0
b 0
f 0
1
import React, { Fragment, useEffect, useState } from 'react';
2
import {
3
  Breadcrumb,
4
  BreadcrumbItem,
5
  Row,
6
  Col,
7
  Card,
8
  CardBody,
9
  Button,
10
  ButtonGroup,
11
  Form,
12
  FormGroup,
13
  Input,
14
  Label,
15
  CustomInput
16
} from 'reactstrap';
17
import Datetime from 'react-datetime';
18
import moment from 'moment';
19
import loadable from '@loadable/component';
20
import Cascader from 'rc-cascader';
21
import LineChart from '../common/LineChart';
22
import { getCookieValue, createCookie } from '../../../helpers/utils';
23
import withRedirect from '../../../hoc/withRedirect';
24
import { withTranslation } from 'react-i18next';
25
import { toast } from 'react-toastify';
26
import { APIBaseURL } from '../../../config';
27
28
29
const DetailedDataTable = loadable(() => import('../common/DetailedDataTable'));
30
31
const MeterTrend = ({ setRedirect, setRedirectUrl, t }) => {
32
  let current_moment = moment();
33
  useEffect(() => {
34
    let is_logged_in = getCookieValue('is_logged_in');
35
    let user_name = getCookieValue('user_name');
36
    let user_display_name = getCookieValue('user_display_name');
37
    let user_uuid = getCookieValue('user_uuid');
38
    let token = getCookieValue('token');
39
    if (is_logged_in === null || !is_logged_in) {
40
      setRedirectUrl(`/authentication/basic/login`);
41
      setRedirect(true);
42
    } else {
43
      //update expires time of cookies
44
      createCookie('is_logged_in', true, 1000 * 60 * 60 * 8);
45
      createCookie('user_name', user_name, 1000 * 60 * 60 * 8);
46
      createCookie('user_display_name', user_display_name, 1000 * 60 * 60 * 8);
47
      createCookie('user_uuid', user_uuid, 1000 * 60 * 60 * 8);
48
      createCookie('token', token, 1000 * 60 * 60 * 8);
49
    }
50
  });
51
52
  // State
53
  //Query From
54
  const [selectedSpaceName, setSelectedSpaceName] = useState(undefined);
55
  const [selectedSpaceID, setSelectedSpaceID] = useState(undefined);
56
  const [meterList, setMeterList] = useState([]);
57
  const [selectedMeter, setSelectedMeter] = useState(undefined);
58
  const [reportingPeriodBeginsDatetime, setReportingPeriodBeginsDatetime] = useState(current_moment.clone().startOf('day'));
59
  const [reportingPeriodEndsDatetime, setReportingPeriodEndsDatetime] = useState(current_moment);
60
  const [cascaderOptions, setCascaderOptions] = useState(undefined);
61
  const [isDisabled, setIsDisabled] = useState(true);
62
  //Results
63
  const [meterLineChartOptions, setMeterLineChartOptions] = useState([]);
64
  const [meterLineChartData, setMeterLineChartData] = useState({});
65
  const [meterLineChartLabels, setMeterLineChartLabels] = useState([]);
66
  const [parameterLineChartOptions, setParameterLineChartOptions] = useState([]);
67
  const [parameterLineChartData, setParameterLineChartData] = useState({});
68
  const [parameterLineChartLabels, setParameterLineChartLabels] = useState([]);
69
  const [detailedDataTableColumns, setDetailedDataTableColumns] = useState([{dataField: 'startdatetime', text: t('Datetime'), sort: true}]);
70
  const [detailedDataTableData, setDetailedDataTableData] = useState([]);
71
72
73
  useEffect(() => {
74
    let isResponseOK = false;
75
    fetch(APIBaseURL + '/spaces/tree', {
76
      method: 'GET',
77
      headers: {
78
        "Content-type": "application/json",
79
        "User-UUID": getCookieValue('user_uuid'),
80
        "Token": getCookieValue('token')
81
      },
82
      body: null,
83
84
    }).then(response => {
85
      console.log(response);
86
      if (response.ok) {
87
        isResponseOK = true;
88
      }
89
      return response.json();
90
    }).then(json => {
91
      console.log(json);
92
      if (isResponseOK) {
93
        // rename keys 
94
        json = JSON.parse(JSON.stringify([json]).split('"id":').join('"value":').split('"name":').join('"label":'));
95
        setCascaderOptions(json);
96
        setSelectedSpaceName([json[0]].map(o => o.label));
97
        setSelectedSpaceID([json[0]].map(o => o.value));
98
        // get Meters by root Space ID
99
        let isResponseOK = false;
100
        fetch(APIBaseURL + '/spaces/' + [json[0]].map(o => o.value) + '/meters', {
101
          method: 'GET',
102
          headers: {
103
            "Content-type": "application/json",
104
            "User-UUID": getCookieValue('user_uuid'),
105
            "Token": getCookieValue('token')
106
          },
107
          body: null,
108
109
        }).then(response => {
110
          if (response.ok) {
111
            isResponseOK = true;
112
          }
113
          return response.json();
114
        }).then(json => {
115
          if (isResponseOK) {
116
            json = JSON.parse(JSON.stringify([json]).split('"id":').join('"value":').split('"name":').join('"label":'));
117
            console.log(json);
118
            setMeterList(json[0]);
119
            if (json[0].length > 0) {
120
              setSelectedMeter(json[0][0].value);
121
              setIsDisabled(false);
122
            } else {
123
              setSelectedMeter(undefined);
124
              setIsDisabled(true);
125
            }
126
          } else {
127
            toast.error(json.description)
128
          }
129
        }).catch(err => {
130
          console.log(err);
131
        });
132
        // end of get Meters by root Space ID
133
      } else {
134
        toast.error(json.description);
135
      }
136
    }).catch(err => {
137
      console.log(err);
138
    });
139
140
  }, []);
141
142
  const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0';
143
144
145
  let onSpaceCascaderChange = (value, selectedOptions) => {
146
    setSelectedSpaceName(selectedOptions.map(o => o.label).join('/'));
147
    setSelectedSpaceID(value[value.length - 1]);
148
149
    let isResponseOK = false;
150
    fetch(APIBaseURL + '/spaces/' + value[value.length - 1] + '/meters', {
151
      method: 'GET',
152
      headers: {
153
        "Content-type": "application/json",
154
        "User-UUID": getCookieValue('user_uuid'),
155
        "Token": getCookieValue('token')
156
      },
157
      body: null,
158
159
    }).then(response => {
160
      if (response.ok) {
161
        isResponseOK = true;
162
      }
163
      return response.json();
164
    }).then(json => {
165
      if (isResponseOK) {
166
        json = JSON.parse(JSON.stringify([json]).split('"id":').join('"value":').split('"name":').join('"label":'));
167
        console.log(json)
168
        setMeterList(json[0]);
169
        if (json[0].length > 0) {
170
          setSelectedMeter(json[0][0].value);
171
          setIsDisabled(false);
172
        } else {
173
          setSelectedMeter(undefined);
174
          setIsDisabled(true);
175
        }
176
      } else {
177
        toast.error(json.description)
178
      }
179
    }).catch(err => {
180
      console.log(err);
181
    });
182
  }
183
184
185
  let onReportingPeriodBeginsDatetimeChange = (newDateTime) => {
186
    setReportingPeriodBeginsDatetime(newDateTime);
187
    
188
  }
189
190
  let onReportingPeriodEndsDatetimeChange = (newDateTime) => {
191
    setReportingPeriodEndsDatetime(newDateTime);
192
    
193
  }
194
195
  var getValidReportingPeriodBeginsDatetimes = function (currentDate) {
196
    return currentDate.isBefore(moment(reportingPeriodEndsDatetime, 'MM/DD/YYYY, hh:mm:ss a'));
197
  }
198
199
  var getValidReportingPeriodEndsDatetimes = function (currentDate) {
200
    return currentDate.isAfter(moment(reportingPeriodBeginsDatetime, 'MM/DD/YYYY, hh:mm:ss a'));
201
  }
202
  // Handler
203
  const handleSubmit = e => {
204
    e.preventDefault();
205
    console.log('handleSubmit');
206
    console.log(selectedSpaceID);
207
    console.log(selectedMeter);
208
    console.log(reportingPeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss'));
209
    console.log(reportingPeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss'));
210
211
    // Reinitialize tables
212
    setDetailedDataTableData([]);
213
214
    let isResponseOK = false;
215
    fetch(APIBaseURL + '/reports/metertrend?' +
216
      'meterid=' + selectedMeter +
217
      '&reportingperiodstartdatetime=' + reportingPeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss') +
218
      '&reportingperiodenddatetime=' + reportingPeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss'), {
219
      method: 'GET',
220
      headers: {
221
        "Content-type": "application/json",
222
        "User-UUID": getCookieValue('user_uuid'),
223
        "Token": getCookieValue('token')
224
      },
225
      body: null,
226
227
    }).then(response => {
228
      if (response.ok) {
229
        isResponseOK = true;
230
      }
231
      return response.json();
232
    }).then(json => {
233
      if (isResponseOK) {
234
        console.log(json)
235
        
236
        let names = Array();
237
        json['reporting_period']['names'].forEach((currentValue, index) => {
238
          names.push({ 'value': 'a' + index, 'label': currentValue });
239
        });
240
        setMeterLineChartOptions(names);
241
242
        let timestamps =  {}
243
        json['reporting_period']['timestamps'].forEach((currentValue, index) => {
244
          timestamps['a' + index] = currentValue;
245
        });
246
        setMeterLineChartLabels(timestamps);
247
248
        let values = {};
249
        json['reporting_period']['values'].forEach((currentValue, index) => {
250
          values['a'+index] = currentValue
251
        });
252
        setMeterLineChartData(values)
253
254
        names = Array();
255
        json['parameters']['names'].forEach((currentValue, index) => {
256
          names.push({ 'value': 'a' + index, 'label': currentValue });
257
        });
258
        setParameterLineChartOptions(names);
259
        
260
        timestamps = {}
261
        json['parameters']['timestamps'].forEach((currentValue, index) => {
262
          timestamps['a' + index] = currentValue;
263
        });
264
        setParameterLineChartLabels(timestamps);
265
266
        values = {}
267
        json['parameters']['values'].forEach((currentValue, index) => {
268
          values['a' + index] = currentValue;
269
        });
270
        setParameterLineChartData(values);
271
272
        let columns = [{
273
          dataField: 'startdatetime',
274
          text: t('Datetime'),
275
          sort: true
276
        }];
277
        json['reporting_period']['names'].forEach((currentValue, index) => {
278
          let column = {};
279
          column['dataField'] = 'a' + index;
280
          column['text'] = currentValue;
281
          column['sort'] = true;
282
          columns.push(column);
283
        });
284
        setDetailedDataTableColumns(columns);
285
286
        let detial_value_list = [];
287
        // choose the first point's timestamps for all points
288
        json['reporting_period']['timestamps'][0].forEach((currentValue, index) => {
289
          let detial_value = {};
290
          detial_value['id'] = index;
291
          detial_value['startdatetime'] = currentValue;
292
          json['reporting_period']['names'].forEach((currentValue1, index1) => {
293
            detial_value['a' + index1] = json['reporting_period']['values'][index1][index];
294
          });
295
          detial_value_list.push(detial_value);
296
        });
297
        setDetailedDataTableData(detial_value_list);
298
299
      } else {
300
        toast.error(json.description)
301
      }
302
    }).catch(err => {
303
      console.log(err);
304
    });
305
  };
306
307
  return (
308
    <Fragment>
309
      <div>
310
        <Breadcrumb>
311
          <BreadcrumbItem>{t('Meter Data')}</BreadcrumbItem><BreadcrumbItem active>{t('Meter Trend')}</BreadcrumbItem>
312
        </Breadcrumb>
313
      </div>
314
      <Card className="bg-light mb-3">
315
        <CardBody className="p-3">
316
          <Form onSubmit={handleSubmit}>
317
            <Row form >
318
              <Col xs="auto">
319
                <FormGroup className="form-group">
320
                  <Label className={labelClasses} for="space">
321
                    {t('Space')}
322
                  </Label>
323
                  <br />
324
                  <Cascader options={cascaderOptions}
325
                    onChange={onSpaceCascaderChange}
326
                    changeOnSelect
327
                    expandTrigger="hover">
328
                    <Input value={selectedSpaceName || ''} readOnly />
329
                  </Cascader>
330
                </FormGroup>
331
              </Col>
332
              <Col xs="auto">
333
                <FormGroup>
334
                  <Label className={labelClasses} for="meterSelect">
335
                    {t('Meter')}
336
                  </Label>
337
                  <CustomInput type="select" id="meterSelect" name="meterSelect" onChange={({ target }) => setSelectedMeter(target.value)}
338
                  >
339
                    {meterList.map((meter, index) => (
340
                      <option value={meter.value} key={meter.value}>
341
                        {meter.label}
342
                      </option>
343
                    ))}
344
                  </CustomInput>
345
                </FormGroup>
346
              </Col>
347
              <Col xs="auto">
348
                <FormGroup className="form-group">
349
                  <Label className={labelClasses} for="reportingPeriodBeginsDatetime">
350
                    {t('Reporting Period Begins')}
351
                  </Label>
352
                  <Datetime id='reportingPeriodBeginsDatetime'
353
                    value={reportingPeriodBeginsDatetime}
354
                    onChange={onReportingPeriodBeginsDatetimeChange}
355
                    isValidDate={getValidReportingPeriodBeginsDatetimes}
356
                    closeOnSelect={true} />
357
                </FormGroup>
358
              </Col>
359
              <Col xs="auto">
360
                <FormGroup className="form-group">
361
                  <Label className={labelClasses} for="reportingPeriodEndsDatetime">
362
                    {t('Reporting Period Ends')}
363
                  </Label>
364
                  <Datetime id='reportingPeriodEndsDatetime'
365
                    value={reportingPeriodEndsDatetime}
366
                    onChange={onReportingPeriodEndsDatetimeChange}
367
                    isValidDate={getValidReportingPeriodEndsDatetimes}
368
                    closeOnSelect={true} />
369
                </FormGroup>
370
              </Col>
371
              <Col xs="auto">
372
                <FormGroup>
373
                  <br></br>
374
                  <ButtonGroup id="submit">
375
                    <Button color="success" disabled={isDisabled} >{t('Submit')}</Button>
376
                  </ButtonGroup>
377
                </FormGroup>
378
              </Col>
379
            </Row>
380
          </Form>
381
        </CardBody>
382
      </Card>
383
384
      <LineChart reportingTitle={t('Trend Values')}
385
        baseTitle
386
        labels={meterLineChartLabels}
387
        data={meterLineChartData}
388
        options={meterLineChartOptions}>
389
      </LineChart>
390
391
      <LineChart reportingTitle={t('Related Parameters')}
392
        baseTitle=''
393
        labels={parameterLineChartLabels}
394
        data={parameterLineChartData}
395
        options={parameterLineChartOptions}>
396
      </LineChart>
397
      <br />
398
      <DetailedDataTable data={detailedDataTableData} title={t('Detailed Data')} columns={detailedDataTableColumns} pagesize={50} >
399
      </DetailedDataTable>
400
401
    </Fragment>
402
  );
403
};
404
405
export default withTranslation()(withRedirect(MeterTrend));
406