Passed
Push — master ( f78e7a...ced4c1 )
by Guangyu
09:26 queued 14s
created

myems-web/src/components/MyEMS/common/MultiTrendChart.js   A

Complexity

Total Complexity 11
Complexity/F 0

Size

Lines of Code 216
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 11
eloc 164
dl 0
loc 216
rs 10
c 0
b 0
f 0
mnd 11
bc 11
fnc 0
bpm 0
cpm 0
noi 0
1
import React, { useState, useContext, useEffect, useRef } from 'react';
2
import { Row, Col, Card, CardBody, CustomInput } from 'reactstrap';
3
import { rgbaColor, themeColors, isIterableArray } from '../../../helpers/utils';
4
import {
5
  Chart as ChartJS,
6
  CategoryScale,
7
  LinearScale,
8
  PointElement,
9
  BarElement,
10
  Tooltip,
11
  Legend,
12
} from 'chart.js';
13
import { withTranslation } from 'react-i18next';
14
import { Chart } from 'react-chartjs-2';
15
import AppContext from '../../../context/Context';
16
import ChartDataLabels from 'chartjs-plugin-datalabels';
17
18
19
ChartJS.register(
20
  CategoryScale,
21
  LinearScale,
22
  PointElement,
23
  BarElement,
24
  Tooltip,
25
  Legend,
26
);
27
28
const MultiTrendChart = ({
29
  reportingTitle,
30
  baseTitle,
31
  reportingTooltipTitle,
32
  baseTooltipTitle,
33
  reportingLabels,
34
  baseLabels,
35
  reportingData,
36
  baseData,
37
  rates,
38
  options,
39
  t
40
}) => {
41
  const [selectedLabel, setSelectedLabel] = useState('a0');
42
  const [option, setOption] = useState('a0');
43
  const { isDark } = useContext(AppContext);
44
  const chartRef = useRef(null);
45
  const [lineData, setLineData] = useState({
46
    datasets: [],
47
  });  
48
  useEffect(() => {
49
    const chart = chartRef.current;
50
    if (chart) {
51
      const ctx = chart.ctx;
52
      const gradientFill = isDark
53
        ? ctx.createLinearGradient(0, 0, 0, ctx.canvas.height)
54
        : ctx.createLinearGradient(0, 0, 0, 250);
55
      gradientFill.addColorStop(0, isDark ? 'rgba(44,123,229, 0.5)' : 'rgba(255, 255, 255, 0.3)');
56
      gradientFill.addColorStop(1, isDark ? 'transparent' : 'rgba(255, 255, 255, 0)');
57
      
58
      const chartData = {
59
        datasets: [{
60
            data: rates,
61
            borderColor: rgbaColor(isDark ? themeColors.primary : '#000', 0.8) ,
62
            backgroundColor: gradientFill,
63
            type: 'line',
64
            yAxisID: 'y1',
65
            tooltip: {
66
              callbacks: {
67
                label: function(context){
68
                  return context.raw + '%';
69
                }
70
              }
71
            },
72
            datalabels: {
73
              formatter: function(value, context) {
74
                return value + '%';
75
              },
76
              color: isDark ? themeColors.light : themeColors.dark,
77
              align: 'end',
78
              anchor: 'end',
79
            }
80
          },{
81
            label: baseTitle,
82
            data: baseData[option],
83
            backgroundColor: '#4463b6',
84
            stack: "base",
85
            tension: 0.4,
86
            datalabels: {
87
              display: function(context){
88
                return false;
89
               }
90
            },
91
          },{
92
            label: reportingTitle,
93
            data: reportingData[option],
94
            backgroundColor: '#e87637',
95
            stack: "reporting",
96
            tension: 0.4,
97
            datalabels: {
98
              display: function(context){
99
                return false;
100
               }
101
            },
102
          },],
103
        labels: reportingLabels[selectedLabel],
104
      };
105
      setLineData(chartData);
106
    }
107
  }, [baseData, reportingData, option, baseLabels, reportingLabels, rates]);
108
109
  const config = {
110
    plugins: [ChartDataLabels],
111
    options: {
112
      plugins: {
113
        legend: {
114
          display: false,
115
        },
116
        tooltip: {
117
            xPadding: 20,
118
            yPadding: 10,
119
            displayColors: false,
120
            callbacks: {
121
            title: function(context){
122
                if (context[0].datasetIndex) {
123
                    return `${reportingLabels[selectedLabel][context[0].dataIndex]}`;
124
                } else {
125
                    return `${baseLabels[selectedLabel][context[0].dataIndex]}`;
126
                }
127
            },    
128
            label: function(context){
129
                if (context.datasetIndex) {
130
                    return `${reportingTooltipTitle} - ${context.raw}`;
131
                } else {
132
                    return `${baseTooltipTitle} - ${context.raw}`;
133
                }
134
            }
135
            }
136
        },
137
      },
138
      interaction: {
139
        intersect: false,
140
        mode: 'x',
141
        },
142
      scales: {
143
        x: {
144
            display: true,
145
            ticks: {
146
                fontColor: rgbaColor('#fff', 0.8),
147
                fontStyle: 600,
148
                color: isDark ? themeColors.light : themeColors.dark
149
            },
150
            stacked: true,
151
        },
152
        y: {
153
            display: true,
154
            gridLines: {
155
                color: rgbaColor('#000', 0.1)
156
            },
157
            ticks: {
158
              color: isDark ? themeColors.light : themeColors.dark
159
            },
160
            stack: true,
161
        },
162
        y1: {
163
          type: 'linear',
164
          display: true,
165
          position: 'right',
166
          grid: {
167
            drawOnChartArea: false,
168
          },
169
          suggestedMax: 100,
170
          ticks: {
171
            callback: function(value, index, ticks){
172
              return value + '%';
173
            },
174
            color: isDark ? themeColors.light : themeColors.dark
175
          }
176
        },
177
      },
178
      hover: { mode: 'label' },
179
    }
180
  };
181
182
  return (
183
    <Card className="mb-3">
184
      <CardBody className="rounded-soft">
185
        <Row className="text-white align-items-center no-gutters">
186
          <Col>
187
            <h4 className="text-lightSlateGray mb-0">{reportingTitle}</h4>
188
            <p className="fs--1 font-weight-semi-bold">
189
              {baseTitle}
190
            </p>
191
          </Col>
192
          {isIterableArray(options) &&
193
            <Col xs="auto" className="d-none d-sm-block">
194
              <CustomInput
195
                id="ddd"
196
                type="select"
197
                bsSize="sm"
198
                className="mb-3 shadow"
199
                value={option}
200
                onChange={({ target }) => {setOption(target.value); setSelectedLabel(target.value); chartRef.current.update();}}
201
              >
202
                {options.map(({ value, label }) => (
203
                    <option key={value} value={value}>{label}</option>
204
                  ))}
205
              </CustomInput>
206
            </Col>
207
          }
208
        </Row>
209
        <Chart ref={chartRef} type="bar" data={lineData} options={config.options} plugins={config.plugins} width={1618} height={218} />
210
      </CardBody> 
211
    </Card>
212
  );
213
};
214
215
export default withTranslation()(MultiTrendChart);
216
217