evui 3.3.36 → 3.3.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +40 -40
  3. package/dist/evui.common.js +1907 -1832
  4. package/dist/evui.common.js.map +1 -1
  5. package/dist/evui.umd.js +1907 -1832
  6. package/dist/evui.umd.js.map +1 -1
  7. package/dist/evui.umd.min.js +1 -1
  8. package/dist/evui.umd.min.js.map +1 -1
  9. package/dist/img/{EVUI.7f3588fb.svg → EVUI.b82ee81a.svg} +292 -292
  10. package/dist/img/{icon_mysql.7ea26d5d.svg → icon_mysql.1085fdc9.svg} +78 -78
  11. package/dist/img/{icon_oracle.9009b108.svg → icon_oracle.0572d3ee.svg} +13 -13
  12. package/dist/img/{icon_postgresql.f8fffba9.svg → icon_postgresql.ee12bde8.svg} +58 -58
  13. package/package.json +61 -61
  14. package/src/common/emitter.js +20 -20
  15. package/src/common/utils.debounce.js +223 -223
  16. package/src/common/utils.js +134 -134
  17. package/src/common/utils.table.js +78 -78
  18. package/src/common/utils.throttle.js +83 -83
  19. package/src/common/utils.tree.js +18 -18
  20. package/src/components/button/Button.vue +198 -198
  21. package/src/components/button/index.js +7 -7
  22. package/src/components/buttonGroup/ButtonGroup.vue +11 -11
  23. package/src/components/buttonGroup/index.js +7 -7
  24. package/src/components/calendar/Calendar.vue +661 -661
  25. package/src/components/calendar/index.js +7 -7
  26. package/src/components/calendar/uses.js +1272 -1272
  27. package/src/components/chart/Chart.vue +189 -192
  28. package/src/components/chart/chart.core.js +870 -870
  29. package/src/components/chart/element/element.bar.js +524 -524
  30. package/src/components/chart/element/element.bar.time.js +156 -156
  31. package/src/components/chart/element/element.heatmap.js +533 -533
  32. package/src/components/chart/element/element.line.js +339 -339
  33. package/src/components/chart/element/element.pie.js +197 -197
  34. package/src/components/chart/element/element.scatter.js +184 -184
  35. package/src/components/chart/element/element.tip.js +550 -542
  36. package/src/components/chart/helpers/helpers.canvas.js +265 -265
  37. package/src/components/chart/helpers/helpers.constant.js +206 -206
  38. package/src/components/chart/helpers/helpers.util.js +346 -338
  39. package/src/components/chart/index.js +9 -9
  40. package/src/components/chart/model/index.js +4 -4
  41. package/src/components/chart/model/model.series.js +93 -93
  42. package/src/components/chart/model/model.store.js +977 -967
  43. package/src/components/chart/plugins/plugins.interaction.js +769 -769
  44. package/src/components/chart/plugins/plugins.legend.gradient.js +602 -602
  45. package/src/components/chart/plugins/plugins.legend.js +1155 -1151
  46. package/src/components/chart/plugins/plugins.pie.js +254 -254
  47. package/src/components/chart/plugins/plugins.title.js +56 -56
  48. package/src/components/chart/plugins/plugins.tooltip.js +692 -692
  49. package/src/components/chart/scale/scale.js +848 -848
  50. package/src/components/chart/scale/scale.linear.js +38 -38
  51. package/src/components/chart/scale/scale.logarithmic.js +128 -128
  52. package/src/components/chart/scale/scale.step.js +336 -336
  53. package/src/components/chart/scale/scale.time.category.js +277 -277
  54. package/src/components/chart/scale/scale.time.js +48 -48
  55. package/src/components/chart/style/chart.scss +312 -312
  56. package/src/components/chart/uses.js +264 -252
  57. package/src/components/checkbox/Checkbox.vue +200 -200
  58. package/src/components/checkbox/index.js +7 -7
  59. package/src/components/checkboxGroup/CheckboxGroup.vue +44 -44
  60. package/src/components/checkboxGroup/index.js +7 -7
  61. package/src/components/contextMenu/ContextMenu.vue +80 -80
  62. package/src/components/contextMenu/MenuList.vue +149 -149
  63. package/src/components/contextMenu/index.js +7 -7
  64. package/src/components/contextMenu/uses.js +203 -203
  65. package/src/components/datePicker/DatePicker.vue +437 -437
  66. package/src/components/datePicker/index.js +7 -7
  67. package/src/components/datePicker/uses.js +419 -419
  68. package/src/components/grid/Grid.vue +827 -827
  69. package/src/components/grid/grid.filter.window.vue +493 -493
  70. package/src/components/grid/grid.pagination.vue +75 -75
  71. package/src/components/grid/grid.summary.vue +265 -265
  72. package/src/components/grid/grid.toolbar.vue +26 -26
  73. package/src/components/grid/index.js +11 -11
  74. package/src/components/grid/style/grid.scss +263 -263
  75. package/src/components/grid/uses.js +1002 -1007
  76. package/src/components/icon/Icon.vue +49 -49
  77. package/src/components/icon/index.js +8 -8
  78. package/src/components/inputNumber/InputNumber.vue +212 -212
  79. package/src/components/inputNumber/index.js +7 -7
  80. package/src/components/inputNumber/uses.js +217 -217
  81. package/src/components/loading/Loading.vue +125 -125
  82. package/src/components/loading/index.js +7 -7
  83. package/src/components/menu/Menu.vue +68 -68
  84. package/src/components/menu/MenuItem.vue +187 -187
  85. package/src/components/menu/index.js +7 -7
  86. package/src/components/message/Message.vue +223 -223
  87. package/src/components/message/index.js +31 -31
  88. package/src/components/messageBox/MessageBox.vue +358 -358
  89. package/src/components/messageBox/index.js +22 -22
  90. package/src/components/notification/Notification.vue +316 -316
  91. package/src/components/notification/index.js +49 -49
  92. package/src/components/pagination/Pagination.vue +271 -271
  93. package/src/components/pagination/index.js +7 -7
  94. package/src/components/pagination/pageButton.vue +30 -30
  95. package/src/components/progress/Progress.vue +139 -139
  96. package/src/components/progress/index.js +7 -7
  97. package/src/components/radio/Radio.vue +159 -159
  98. package/src/components/radio/index.js +7 -7
  99. package/src/components/radioGroup/RadioGroup.vue +41 -41
  100. package/src/components/radioGroup/index.js +7 -7
  101. package/src/components/scheduler/Scheduler.vue +149 -149
  102. package/src/components/scheduler/index.js +7 -7
  103. package/src/components/scheduler/uses.js +183 -183
  104. package/src/components/select/Select.vue +440 -440
  105. package/src/components/select/index.js +7 -7
  106. package/src/components/select/uses.js +270 -270
  107. package/src/components/slider/Slider.vue +505 -505
  108. package/src/components/slider/index.js +7 -7
  109. package/src/components/slider/uses.js +390 -390
  110. package/src/components/tabPanel/TabPanel.vue +74 -74
  111. package/src/components/tabPanel/index.js +7 -7
  112. package/src/components/tabs/Tabs.vue +517 -517
  113. package/src/components/tabs/index.js +7 -7
  114. package/src/components/textField/TextField.vue +375 -375
  115. package/src/components/textField/index.js +7 -7
  116. package/src/components/timePicker/TimePicker.vue +352 -352
  117. package/src/components/timePicker/index.js +7 -7
  118. package/src/components/toggle/Toggle.vue +115 -115
  119. package/src/components/toggle/index.js +7 -7
  120. package/src/components/tree/Tree.vue +313 -313
  121. package/src/components/tree/TreeNode.vue +293 -293
  122. package/src/components/tree/index.js +7 -7
  123. package/src/components/treeGrid/TreeGrid.vue +758 -758
  124. package/src/components/treeGrid/TreeGridNode.vue +275 -275
  125. package/src/components/treeGrid/index.js +9 -9
  126. package/src/components/treeGrid/style/treeGrid.scss +261 -261
  127. package/src/components/treeGrid/treeGrid.toolbar.vue +26 -26
  128. package/src/components/treeGrid/uses.js +867 -867
  129. package/src/components/window/Window.vue +329 -329
  130. package/src/components/window/index.js +7 -7
  131. package/src/components/window/uses.js +899 -899
  132. package/src/directives/clickoutside.js +90 -90
  133. package/src/main.js +116 -116
  134. package/src/style/components/input.scss +108 -108
  135. package/src/style/functions.scss +3 -3
  136. package/src/style/index.scss +6 -6
  137. package/src/style/lib/fonts/EVUI.svg +292 -292
  138. package/src/style/lib/icon.css +888 -888
  139. package/src/style/mixins.scss +94 -94
  140. package/src/style/themes.scss +67 -67
  141. package/src/style/variables.scss +22 -22
@@ -1,967 +1,977 @@
1
- import { reverse } from 'lodash-es';
2
- import Util from '../helpers/helpers.util';
3
-
4
- const modules = {
5
- /**
6
- * Take chart data and labels to create normalized data and min/max info
7
- * @param {object} data chart series info
8
- * @param {object} label chart label
9
- *
10
- * @returns {undefined}
11
- */
12
- createDataSet(data, label) {
13
- Object.keys(this.seriesInfo.charts).forEach((typeKey) => {
14
- const seriesIDs = this.seriesInfo.charts[typeKey];
15
-
16
- if (seriesIDs.length) {
17
- if (typeKey === 'pie') {
18
- if (this.options.sunburst) {
19
- this.createSunburstDataSet(data);
20
- } else {
21
- this.createPieDataSet(data, seriesIDs);
22
- }
23
- } else if (typeKey === 'scatter') {
24
- seriesIDs.forEach((seriesID) => {
25
- const series = this.seriesList[seriesID];
26
- const sData = data[seriesID];
27
-
28
- if (series && sData) {
29
- series.data = this.addSeriesDSforScatter(sData);
30
- series.minMax = this.getSeriesMinMax(series.data);
31
- }
32
- });
33
- } else if (typeKey === 'heatMap') {
34
- seriesIDs.forEach((seriesID) => {
35
- const series = this.seriesList[seriesID];
36
- const sData = data[seriesID];
37
-
38
- if (series && sData) {
39
- series.labels = label;
40
- series.data = this.addSeriesDSForHeatMap(sData);
41
- series.minMax = this.getSeriesMinMax(series.data);
42
- series.valueOpt = this.getSeriesValueOptForHeatMap(series);
43
- }
44
- });
45
- } else {
46
- seriesIDs.forEach((seriesID) => {
47
- const series = this.seriesList[seriesID];
48
- const sData = data[seriesID];
49
-
50
- if (series && sData) {
51
- if (series.isExistGrp && series.stackIndex) {
52
- series.data = this.addSeriesStackDS(sData, label, series.bsIds, series.stackIndex);
53
- } else {
54
- series.data = this.addSeriesDS(sData, label);
55
- }
56
- series.minMax = this.getSeriesMinMax(series.data);
57
- }
58
- });
59
- }
60
- }
61
- });
62
- },
63
-
64
- /**
65
- * Take chart data and to create normalized pie data
66
- * @param {object} data chart series info
67
- *
68
- * @returns {undefined}
69
- */
70
- createSunburstDataSet(data) {
71
- this.pieDataSet = [];
72
- const ds = this.pieDataSet;
73
- const sunburstQueue = [];
74
-
75
- for (let ix = 0; ix < data.length; ix++) {
76
- const slice = data[ix];
77
- const series = this.seriesList[slice.id];
78
- let showChildren = false;
79
-
80
- if (!ds[0]) {
81
- ds[0] = { ir: 0, or: 0, total: 0, data: [] };
82
- }
83
-
84
- if (series.show) {
85
- ds[0].total += slice.value || 0;
86
- ds[0].data.push({ parent: '$ev-root', id: slice.id, value: slice.value, sa: 0, ea: 0 });
87
-
88
- if (slice.children) {
89
- for (let jx = 0; jx < slice.children.length; jx++) {
90
- const childSeries = this.seriesList[slice.children[jx].id];
91
- if (childSeries.show) {
92
- showChildren = true;
93
- }
94
- sunburstQueue.push({ parent: slice.id, data: slice.children[jx], depth: 1 });
95
- }
96
- } else {
97
- const dummy = {
98
- id: 'dummy',
99
- value: slice.value,
100
- };
101
- sunburstQueue.push({ parent: slice.id, data: dummy, depth: 1 });
102
- }
103
-
104
- if (!showChildren) {
105
- const dummy = {
106
- id: 'dummy',
107
- value: slice.value,
108
- };
109
- sunburstQueue.push({ parent: slice.id, data: dummy, depth: 1 });
110
- }
111
- }
112
- }
113
-
114
- ds[0].data.sort((a, b) => b.value - a.value);
115
-
116
- while (sunburstQueue.length) {
117
- const item = sunburstQueue.shift();
118
- const parent = item.parent;
119
- const slice = item.data;
120
- const depth = item.depth;
121
- let showChildren = false;
122
-
123
- if (!ds[depth]) {
124
- ds[depth] = { ir: 0, or: 0, total: {}, data: [] };
125
- }
126
-
127
- if (!ds[depth].total[parent]) {
128
- ds[depth].total[parent] = 0;
129
- }
130
-
131
- const series = this.seriesList[slice.id];
132
- if (slice.id === 'dummy') {
133
- ds[depth].data.push({ parent, id: 'dummy', value: slice.value, sa: 0, ea: 0 });
134
- ds[depth].total[parent] += slice.value;
135
- } else if (series && series.show) {
136
- ds[depth].data.push({ parent, id: slice.id, value: slice.value, sa: 0, ea: 0 });
137
- ds[depth].total[parent] += slice.value;
138
-
139
- if (slice.children) {
140
- for (let ix = 0; ix < slice.children.length; ix++) {
141
- if (this.seriesList[slice.children[ix].id].show) {
142
- showChildren = true;
143
- }
144
- sunburstQueue.push({ parent: slice.id, data: slice.children[ix], depth: depth + 1 });
145
- }
146
- } else {
147
- const dummy = {
148
- id: 'dummy',
149
- value: slice.value,
150
- };
151
- sunburstQueue.push({ parent: slice.id, data: dummy, depth: depth + 1 });
152
- }
153
-
154
- if (!showChildren) {
155
- const dummy = {
156
- id: 'dummy',
157
- value: slice.value,
158
- };
159
- sunburstQueue.push({ parent: slice.id, data: dummy, depth: depth + 1 });
160
- }
161
- }
162
-
163
- ds[depth].data.sort((a, b) => b.value - a.value);
164
- }
165
- },
166
-
167
- /**
168
- * Take chart data and to create normalized pie data
169
- * @param {object} data chart data
170
- * @param {String[]} seriesIDs chart series info
171
- *
172
- * @returns {undefined}
173
- */
174
- createPieDataSet(data, seriesIDs) {
175
- this.pieDataSet = [];
176
- const ds = this.pieDataSet;
177
- ds[0] = { data: [], ir: 0, or: 0, total: 0 };
178
-
179
- seriesIDs.forEach((sId) => {
180
- if (this.seriesList[sId].show) {
181
- const value = data[sId][0] ?? 0;
182
- ds[0].total += value;
183
- ds[0].data.push({ id: sId, value, sa: 0, ea: 0 });
184
- }
185
- });
186
-
187
- ds.forEach((item) => {
188
- item.data.sort((a, b) => b.value - a.value);
189
- });
190
- },
191
-
192
- /**
193
- * Take data and label to create stack data for each series
194
- * @param {object} data chart series info
195
- * @param {object} label chart label
196
- * @param {array} bsIds stacked base data ID List
197
- * @param {number} sIdx series ordered index
198
- *
199
- * @returns {array} data for each series
200
- */
201
- addSeriesStackDS(data, label, bsIds, sIdx = 0) {
202
- const isHorizontal = this.options.horizontal;
203
- const sdata = [];
204
-
205
- const getBaseDataPosition = (baseIndex, dataIndex) => {
206
- const nextBaseSeriesIndex = baseIndex - 1;
207
- const baseSeries = this.seriesList[bsIds[baseIndex]];
208
- const baseDataList = baseSeries.data;
209
- const baseData = baseDataList[dataIndex];
210
- const position = isHorizontal ? baseData?.x : baseData?.y;
211
-
212
- if (position == null || !baseSeries.show) {
213
- if (nextBaseSeriesIndex > -1) {
214
- return getBaseDataPosition(nextBaseSeriesIndex, dataIndex);
215
- }
216
-
217
- return 0;
218
- }
219
-
220
- return position;
221
- };
222
-
223
- data.forEach((curr, index) => {
224
- const baseIndex = bsIds.length - 1 < 0 ? 0 : bsIds.length - 1;
225
- let bdata = getBaseDataPosition(baseIndex, index); // base(previous) series data
226
- let odata = curr; // current series original data
227
- let ldata = label[index]; // label data
228
- let gdata = curr; // current series data which added previous series's value
229
-
230
- if (bdata != null && ldata != null) {
231
- if (gdata && typeof gdata === 'object' && (curr.x || curr.y)) {
232
- odata = isHorizontal ? curr.x : curr.y;
233
- ldata = isHorizontal ? curr.y : curr.x;
234
- }
235
-
236
- const oData = odata?.value ?? odata;
237
- if (sIdx > 0) {
238
- if (oData != null) {
239
- gdata = bdata + oData;
240
- } else {
241
- gdata = null;
242
- bdata = 0;
243
- }
244
- } else {
245
- bdata = 0;
246
- gdata = oData;
247
- }
248
-
249
- sdata.push(this.addData(gdata, ldata, odata, bdata));
250
- }
251
- });
252
-
253
- return sdata;
254
- },
255
-
256
- /**
257
- * Take data and label to create data for each series
258
- * @param {object} data chart series info
259
- * @param {object} label chart label
260
- *
261
- * @returns {array} data for each series
262
- */
263
- addSeriesDS(data, label) {
264
- const isHorizontal = this.options.horizontal;
265
- const sdata = [];
266
-
267
- data.forEach((curr, index) => {
268
- let gdata = curr;
269
- let ldata = label[index];
270
-
271
- if (gdata && typeof gdata === 'object' && (curr.x || curr.y)) {
272
- gdata = isHorizontal ? curr.x : curr.y;
273
- ldata = isHorizontal ? curr.y : curr.x;
274
- }
275
-
276
- if (ldata !== null) {
277
- sdata.push(this.addData(gdata, ldata, gdata));
278
- }
279
- });
280
-
281
- return sdata;
282
- },
283
-
284
- /**
285
- * Take data to create data for each series
286
- * @param {array} data data array for each series
287
- * @returns {array} data info added position and etc
288
- */
289
- addSeriesDSforScatter(data) {
290
- return data.map((item) => {
291
- const ldata = item.x;
292
- const gdata = {
293
- value: item.y,
294
- color: item?.color || null,
295
- };
296
-
297
- return this.addData(gdata, ldata, gdata);
298
- });
299
- },
300
-
301
- /**
302
- * Take data to create data for each series
303
- * @param {array} data data array for each series
304
- * @param {object} label chart label
305
- *
306
- * @returns {array} data info added position and etc
307
- */
308
- addSeriesDSForHeatMap(data) {
309
- return data.map(({ x, y, value }) => ({
310
- x,
311
- y,
312
- o: value,
313
- xp: null,
314
- yp: null,
315
- w: null,
316
- h: null,
317
- dataColor: null,
318
- cId: null,
319
- }));
320
- },
321
-
322
- /**
323
- * Take data to create data object for graph
324
- * @param {object} gdata graph data (y-axis value for vertical chart)
325
- * @param {object} ldata label data (x-axis value for vertical chart)
326
- * @param {object} odata original data (without stacked value)
327
- * @param {object} bdata base data (stacked value)
328
-
329
- * @returns {object} data for each graph point
330
- */
331
- addData(gdata, ldata, odata = null, bdata = null) {
332
- let data;
333
- let gdataValue = null;
334
- let odataValue = null;
335
- let gdataColor = null;
336
- let odataColor = null;
337
-
338
- if (gdata !== null && typeof gdata === 'object') {
339
- gdataValue = gdata.value;
340
- gdataColor = gdata.color;
341
- } else {
342
- gdataValue = gdata;
343
- }
344
-
345
- if (odata !== null && typeof odata === 'object') {
346
- odataValue = odata.value;
347
- odataColor = odata.color;
348
- } else {
349
- odataValue = odata;
350
- }
351
-
352
- if (this.options.horizontal) {
353
- data = { x: gdataValue, y: ldata, o: odataValue, b: bdata };
354
- } else {
355
- data = { x: ldata, y: gdataValue, o: odataValue, b: bdata };
356
- }
357
-
358
- data.xp = null;
359
- data.yp = null;
360
- data.w = null;
361
- data.h = null;
362
- data.dataColor = gdataColor ?? odataColor;
363
-
364
- return data;
365
- },
366
-
367
- /**
368
- * Take series data to create min/max info for each series
369
- * @param {object} data series data
370
- *
371
- * @returns {object} min/max info for series
372
- */
373
- getSeriesMinMax(data) {
374
- const def = { minX: null, minY: null, maxX: null, maxY: null, maxDomain: null };
375
- const isHorizontal = this.options.horizontal;
376
-
377
- if (data.length) {
378
- return data.reduce((acc, p, index) => {
379
- const minmax = acc;
380
- const px = p.x?.value || p.x;
381
- const py = p.y?.value || p.y;
382
-
383
- if (px <= minmax.minX) {
384
- minmax.minX = (px === null) ? 0 : px;
385
- }
386
- if (py <= minmax.minY) {
387
- minmax.minY = (py === null) ? 0 : py;
388
- }
389
- if (px >= minmax.maxX) {
390
- minmax.maxX = (px === null) ? 0 : px;
391
-
392
- if (isHorizontal && px !== null) {
393
- minmax.maxDomain = py;
394
- minmax.maxDomainIndex = index;
395
- }
396
- }
397
- if (py >= minmax.maxY) {
398
- minmax.maxY = (py === null) ? 0 : py;
399
-
400
- if (!isHorizontal && py !== null) {
401
- minmax.maxDomain = px;
402
- minmax.maxDomainIndex = index;
403
- }
404
- }
405
-
406
- return minmax;
407
- }, {
408
- minX: data[0].x,
409
- minY: data[0].y,
410
- maxX: data[0].x,
411
- maxY: data[0].y,
412
- maxDomain: isHorizontal ? data[0].y : data[0].x,
413
- maxDomainIndex: 0,
414
- });
415
- }
416
-
417
- return def;
418
- },
419
-
420
- getSeriesValueOptForHeatMap(series) {
421
- const { data, colorState, isGradient } = series;
422
- const colorOpt = this.options.heatMapColor;
423
- const categoryCnt = colorOpt.categoryCnt;
424
- const decimalPoint = colorOpt.decimalPoint;
425
-
426
- let minValue;
427
- let maxValue = 0;
428
-
429
- let isExistError = false;
430
- data.forEach(({ o: value }) => {
431
- if (maxValue < value) {
432
- maxValue = Math.max(maxValue, value);
433
- }
434
-
435
- if (value < 0) {
436
- isExistError = true;
437
- } else if (minValue === undefined) {
438
- minValue = value;
439
- } else {
440
- minValue = Math.min(minValue, value);
441
- }
442
- });
443
-
444
- if (
445
- isExistError
446
- && !isGradient
447
- && colorState.length === categoryCnt
448
- ) {
449
- colorState.push({
450
- id: `color#${categoryCnt}`,
451
- color: colorOpt.error,
452
- state: 'normal',
453
- show: true,
454
- });
455
- }
456
-
457
- let interval = maxValue > minValue ? Math.floor((maxValue - minValue) / categoryCnt) : 1;
458
- if ((maxValue - minValue) <= categoryCnt) {
459
- if (decimalPoint > 0) {
460
- interval = +((maxValue - minValue) / categoryCnt).toFixed(decimalPoint);
461
- } else {
462
- interval = 1;
463
- }
464
- }
465
-
466
- return {
467
- min: minValue,
468
- max: maxValue,
469
- interval,
470
- existError: isExistError,
471
- decimalPoint,
472
- };
473
- },
474
-
475
- /**
476
- * Get graph items for each series by label index
477
- * @param {number} labelIndex label index
478
- *
479
- * @returns {object} graph item
480
- */
481
- getItemByLabelIndex(labelIndex) {
482
- if (labelIndex < 0) {
483
- return false;
484
- }
485
-
486
- const sIds = Object.keys(this.seriesList);
487
- const isHorizontal = !!this.options.horizontal;
488
-
489
- let maxl = null;
490
- let maxp = null;
491
- let maxg = null;
492
- let maxSID = '';
493
- let acc = 0;
494
- let useStack = false;
495
- let findInfo = false;
496
-
497
- if (labelIndex > -1) {
498
- for (let ix = 0; ix < sIds.length; ix++) {
499
- const sId = sIds[ix];
500
- const series = this.seriesList[sId];
501
- const data = series.data[labelIndex];
502
-
503
- if (data && series.show && series.showLegend) {
504
- const ldata = isHorizontal ? data.y : data.x;
505
- const lp = isHorizontal ? data.yp : data.xp;
506
-
507
- if (ldata !== null && ldata !== undefined) {
508
- const g = isHorizontal ? data.o || data.x : data.o || data.y;
509
-
510
- if (series.stackIndex) {
511
- acc += !isNaN(data.o) ? data.o : 0;
512
- useStack = true;
513
- } else {
514
- acc += data.y;
515
- }
516
-
517
- if (maxg === null || maxg <= g) {
518
- maxg = g;
519
- maxSID = sId;
520
- maxl = ldata;
521
- maxp = lp;
522
- }
523
- }
524
- }
525
- }
526
-
527
- findInfo = {
528
- label: maxl,
529
- pos: maxp,
530
- value: maxg === null ? 0 : maxg,
531
- sId: maxSID,
532
- acc,
533
- useStack,
534
- maxIndex: labelIndex,
535
- };
536
- }
537
-
538
- return findInfo;
539
- },
540
-
541
- getItem({ seriesID, dataIndex }, useApproximate = false) {
542
- const dataInfo = this.getDataByValues(seriesID, dataIndex);
543
-
544
- if (!dataInfo || !dataInfo?.xp || !dataInfo?.yp) {
545
- return null;
546
- }
547
-
548
- return this.getItemByPosition([dataInfo.xp, dataInfo.yp], useApproximate);
549
- },
550
-
551
- /**
552
- *
553
- * @param seriesID
554
- * @param dataIndex
555
- * @returns {*}
556
- */
557
- getDataByValues(seriesID, dataIndex) {
558
- const series = this.seriesList[seriesID];
559
- if (!series || isNaN(dataIndex) || dataIndex < 0 || series?.data.length <= dataIndex) {
560
- return false;
561
- }
562
-
563
- return series.data[dataIndex];
564
- },
565
-
566
- /**
567
- * Find graph item by position x and y
568
- * @param {array} offset position x and y
569
- * @param {boolean} useApproximate if it's true. it'll look for closed item on mouse position
570
- *
571
- * @returns {object} clicked item information
572
- */
573
- getItemByPosition(offset, useApproximate = false) {
574
- const seriesIDs = Object.keys(this.seriesList);
575
- const isHorizontal = !!this.options.horizontal;
576
-
577
- let maxType = null;
578
- let maxLabel = null;
579
- let maxValuePos = null;
580
- let maxValue = null;
581
- let maxSeriesID = '';
582
- let acc = 0;
583
- let useStack = false;
584
- let maxIndex = null;
585
-
586
- for (let ix = 0; ix < seriesIDs.length; ix++) {
587
- const seriesID = seriesIDs[ix];
588
- const series = this.seriesList[seriesID];
589
- const findFn = useApproximate ? series.findApproximateData : series.findGraphData;
590
-
591
- if (findFn) {
592
- const item = findFn.call(series, offset, isHorizontal);
593
- const data = item.data;
594
- const index = item.index;
595
-
596
- if (data) {
597
- if (Util.isPieType(item.type)) {
598
- maxLabel = seriesID;
599
- maxSeriesID = seriesID;
600
- maxValuePos = (data.ea - data.sa) / 2;
601
- maxValue = data.o;
602
- maxIndex = data.index;
603
- maxType = item.type;
604
- } else {
605
- const ldata = isHorizontal ? data.y : data.x;
606
- const lp = isHorizontal ? data.yp : data.xp;
607
-
608
- if (ldata !== null && ldata !== undefined) {
609
- const g = isHorizontal ? data.o || data.x : data.o || data.y;
610
-
611
- if (series.stackIndex) {
612
- acc += !isNaN(data.o) ? data.o : 0;
613
- useStack = true;
614
- } else {
615
- acc += data.y;
616
- }
617
-
618
- if (maxValue === null || maxValue <= g) {
619
- maxValue = g;
620
- maxSeriesID = seriesID;
621
- maxLabel = ldata;
622
- maxValuePos = lp;
623
- maxIndex = index;
624
- maxType = series.type;
625
- }
626
- }
627
- }
628
- }
629
- }
630
- }
631
-
632
- return {
633
- type: maxType,
634
- label: maxLabel,
635
- pos: maxValuePos,
636
- value: maxValue ?? 0,
637
- sId: maxSeriesID,
638
- acc,
639
- useStack,
640
- maxIndex,
641
- };
642
- },
643
-
644
- /**
645
- * Find seriesId by position x and y
646
- * @param {array} offset position x and y
647
- *
648
- * @returns {object} clicked series id
649
- */
650
- getSeriesIdByPosition(offset) {
651
- const [clickedX, clickedY] = offset;
652
- const chartRect = this.chartRect;
653
- const labelOffset = this.labelOffset;
654
- const aPos = {
655
- x1: chartRect.x1 + labelOffset.left,
656
- x2: chartRect.x2 - labelOffset.right,
657
- y1: chartRect.y1 + labelOffset.top,
658
- y2: chartRect.y2 - labelOffset.bottom,
659
- };
660
- const valueAxes = this.axesY[0];
661
- const labelAxes = this.axesX[0];
662
- const valueStartPoint = aPos[valueAxes.units.rectStart];
663
- const valueEndPoint = aPos[valueAxes.units.rectEnd];
664
- const labelStartPoint = aPos[labelAxes.units.rectStart];
665
- const labelEndPoint = aPos[labelAxes.units.rectEnd];
666
-
667
- const result = { sId: null };
668
-
669
- if (clickedY > valueEndPoint && clickedY < valueStartPoint
670
- && clickedX < labelEndPoint && clickedX > labelStartPoint) {
671
- let hitSeries;
672
- let positionList;
673
- const hitItem = this.findHitItem(offset);
674
- const hitSeriesList = Object.keys(hitItem.items);
675
-
676
- switch (this.options.type) {
677
- case 'line': {
678
- const orderedSeriesList = this.seriesInfo.charts.line;
679
- const isStackChart = Object.values(this.seriesList).some(({ stackIndex }) => stackIndex);
680
-
681
- if (hitSeriesList.length) { // 클릭한 위치에 data 가 존재하는 경우
682
- if (isStackChart) {
683
- positionList = orderedSeriesList.filter(sId => hitSeriesList.includes(sId))
684
- .map(sId => ({ sId, position: hitItem.items[sId]?.data?.yp }));
685
- hitSeries = positionList.find(({ position }) => clickedY > position)?.sId;
686
- } else {
687
- hitSeries = Object.entries(hitItem.items).find(([, { hit }]) => hit)?.[0];
688
- }
689
- } else { // 클릭한 위치에 data 가 존재하지 않는 경우
690
- const visibleSeriesList = orderedSeriesList.filter(sId => this.seriesList[sId].show);
691
- positionList = visibleSeriesList.map(sId => ({
692
- sId,
693
- position: this.seriesList[sId].data?.map(({ xp, yp }) => [xp, yp]),
694
- }));
695
- const dataIndex = positionList[0].position?.findIndex(([xp]) => xp >= clickedX);
696
- const vectorList = positionList.map(({ sId, position }) => ({
697
- sId,
698
- vector: { start: position[dataIndex - 1], end: position[dataIndex] },
699
- }));
700
-
701
- const isEmptyVector = (arr => !arr || !Array.isArray(arr) || arr?.length !== 2);
702
-
703
- // canvas 의 클릭 위치값은 제 4 사분면의 위치이므로 clickedY, y1, y2 의 값은 음수를 취한다.
704
- if (isStackChart) {
705
- hitSeries = vectorList.find(({ vector }) => {
706
- if (isEmptyVector(vector?.start) && isEmptyVector(vector?.end)) {
707
- return false;
708
- }
709
-
710
- const [x1, y1] = vector.start;
711
- const [x2, y2] = vector.end;
712
- const v1 = [x2 - x1, y1 - y2];
713
- const v2 = [x2 - clickedX, clickedY - y2];
714
- const xp = v1[0] * v2[1] - v1[1] * v2[0];
715
-
716
- return vector.start.every(v => typeof v === 'number')
717
- && vector.end.every(v => typeof v === 'number')
718
- && xp > 0;
719
- })?.sId;
720
- } else {
721
- hitSeries = vectorList.find(({ vector }) => {
722
- if (isEmptyVector(vector?.start) && isEmptyVector(vector?.end)) {
723
- return false;
724
- }
725
-
726
- const [x1, y1] = vector.start;
727
- const [x2, y2] = vector.end;
728
- const a = (y1 - y2) / (x2 - x1);
729
- const b = -1;
730
- const c = -y1 - a * x1;
731
- const distance = Math.abs(a * clickedX - b * clickedY + c)
732
- / Math.sqrt(a ** 2 + b ** 2);
733
-
734
- return distance < 3;
735
- })?.sId;
736
- }
737
- }
738
- break;
739
- }
740
- default:
741
- break;
742
- }
743
-
744
- result.sId = hitSeries;
745
- }
746
-
747
- return result;
748
- },
749
- /**
750
- * Find label info by position x and y
751
- * @param {array} offset position x and y
752
- *
753
- * @returns {object} clicked label information
754
- */
755
- getLabelInfoByPosition(offset) {
756
- const [x, y] = offset;
757
- const aPos = {
758
- x1: this.chartRect.x1 + this.labelOffset.left,
759
- x2: this.chartRect.x2 - this.labelOffset.right,
760
- y1: this.chartRect.y1 + this.labelOffset.top,
761
- y2: this.chartRect.y2 - this.labelOffset.bottom,
762
- };
763
-
764
- const scale = this.options.horizontal ? this.axesY[0] : this.axesX[0];
765
- const startPoint = aPos[scale.units.rectStart];
766
- const endPoint = aPos[scale.units.rectEnd];
767
-
768
- let labelIndex;
769
- let hitInfo;
770
- if (scale.labels) {
771
- const labelGap = (endPoint - startPoint) / scale.labels.length;
772
- const index = Math.floor(((this.options.horizontal ? y : x) - startPoint) / labelGap);
773
- labelIndex = scale.labels.length > index ? index : -1;
774
- } else {
775
- hitInfo = this.getItemByPosition(offset, this.options.selectLabel.useApproximateValue);
776
- labelIndex = hitInfo.maxIndex ?? -1;
777
- }
778
-
779
- return {
780
- labelIndex,
781
- hitInfo,
782
- };
783
- },
784
-
785
- /**
786
- * Create min/max information for all of data
787
- * @property seriesList
788
- *
789
- * @returns {object} min/max info for all of data
790
- */
791
- getStoreMinMax() {
792
- const keys = Object.keys(this.seriesList);
793
- const isHorizontal = this.options.horizontal;
794
- const def = {
795
- x: [{ min: null, max: null }],
796
- y: [{ min: null, max: null }],
797
- };
798
-
799
- if (keys.length) {
800
- return keys.reduce((acc, key) => {
801
- const minmax = acc;
802
- const series = this.seriesList[key];
803
- const smm = series.minMax;
804
- const axisX = series.xAxisIndex;
805
- const axisY = series.yAxisIndex;
806
-
807
- if (!minmax.x[axisX]) {
808
- minmax.x[axisX] = { min: null, max: null, maxSID: null };
809
- }
810
- if (!minmax.y[axisY]) {
811
- minmax.y[axisY] = { min: null, max: null, maxSID: null };
812
- }
813
-
814
- if (smm && series.show) {
815
- if (!isHorizontal) {
816
- if (smm.minX !== null
817
- && ((minmax.x[axisX].min === null || (smm.minX < minmax.x[axisX].min)))) {
818
- minmax.x[axisX].min = smm.minX;
819
- }
820
- if (minmax.y[axisY].min === null || (smm.minY < minmax.y[axisY].min)) {
821
- minmax.y[axisY].min = smm.minY;
822
- }
823
- } else {
824
- if (minmax.x[axisX].min === null || (smm.minX < minmax.x[axisX].min)) {
825
- minmax.x[axisX].min = smm.minX;
826
- }
827
- if (smm.minY !== null
828
- && (minmax.y[axisY].min === null || (smm.minY < minmax.y[axisY].min))) {
829
- minmax.y[axisY].min = smm.minY;
830
- }
831
- }
832
- if (smm.maxX >= minmax.x[axisX].max) {
833
- minmax.x[axisX].max = smm.maxX;
834
- minmax.x[axisX].maxSID = key;
835
- }
836
- if (smm.maxY >= minmax.y[axisY].max) {
837
- minmax.y[axisY].max = smm.maxY;
838
- minmax.y[axisX].maxSID = key;
839
- }
840
- }
841
-
842
- return minmax;
843
- }, {
844
- x: [{ min: null, max: null, maxSID: null }],
845
- y: [{ min: null, max: null, maxSID: null }],
846
- });
847
- }
848
-
849
- return def;
850
- },
851
-
852
- calculateAngle() {
853
- const pieDataSet = this.pieDataSet;
854
-
855
- let slice;
856
- let value;
857
- let parent;
858
- let totalValue;
859
-
860
- let sliceAngle;
861
- let startAngle;
862
- let endAngle;
863
- let totalAngle;
864
- let isDummy;
865
-
866
- const dummyIndex = [];
867
- const saStore = {
868
- '$ev-root': 1.5 * Math.PI,
869
- };
870
-
871
- for (let ix = 0; ix < pieDataSet.length; ix++) {
872
- const pie = pieDataSet[ix];
873
- isDummy = true;
874
-
875
- for (let jx = 0; jx < pie.data.length; jx++) {
876
- slice = pie.data[jx];
877
- value = slice.value;
878
-
879
- if (isDummy) {
880
- isDummy = slice.id === 'dummy';
881
- }
882
-
883
- if (!ix) {
884
- startAngle = saStore['$ev-root'];
885
- sliceAngle = 2 * Math.PI * (value / pie.total);
886
- endAngle = startAngle + sliceAngle;
887
-
888
- slice.sa = startAngle;
889
- slice.ea = endAngle;
890
- saStore['$ev-root'] += sliceAngle;
891
- } else {
892
- parent = this.getParentInfo(ix - 1, slice.parent);
893
- if (!parent) {
894
- break;
895
- }
896
-
897
- if (!saStore[slice.parent]) {
898
- saStore[slice.parent] = parent.sa;
899
- }
900
-
901
- startAngle = saStore[slice.parent];
902
- totalAngle = parent.ea - parent.sa;
903
- totalValue = pie.total[slice.parent] || 0;
904
- sliceAngle = totalAngle * (value / totalValue);
905
- endAngle = startAngle + sliceAngle;
906
-
907
- slice.sa = startAngle;
908
- slice.ea = endAngle;
909
-
910
- saStore[slice.parent] += sliceAngle;
911
- }
912
- }
913
-
914
- if (isDummy) {
915
- dummyIndex.push(ix);
916
- }
917
- }
918
-
919
- for (let ix = 0; ix < dummyIndex.length; ix++) {
920
- this.pieDataSet.splice(dummyIndex, 1);
921
- }
922
-
923
- if (this.options.reverse) {
924
- this.pieDataSet = reverse(this.pieDataSet);
925
- }
926
- },
927
-
928
- getParentInfo(depth, parentId) {
929
- for (let ix = depth; ix >= 0; ix--) {
930
- const pie = this.pieDataSet[ix];
931
- for (let jx = 0; jx < pie.data.length; jx++) {
932
- if (pie.data[jx].id === parentId) {
933
- return pie.data[jx];
934
- }
935
- }
936
- }
937
-
938
- return null;
939
- },
940
-
941
- /**
942
- * Get Aggregations (
943
- * @returns {{}}
944
- */
945
- getAggregations() {
946
- const allData = this.data.data;
947
- const series = this.data.series;
948
- const aggregationDataSet = {};
949
- const seriesIds = Object.keys(series);
950
-
951
- seriesIds?.forEach((sId) => {
952
- const dataList = allData[sId].map(data => (data.value ? data.value : data));
953
-
954
- const min = (Math.min(...dataList));
955
- const max = (Math.max(...dataList));
956
- const total = (dataList.reduce((a, b) => a + b, 0));
957
- const avg = (total / dataList.length || 0);
958
- const last = (dataList[dataList.length - 1]);
959
-
960
- aggregationDataSet[sId] = { min, max, avg, total, last };
961
- });
962
-
963
- return aggregationDataSet;
964
- },
965
- };
966
-
967
- export default modules;
1
+ import { reverse } from 'lodash-es';
2
+ import Util from '../helpers/helpers.util';
3
+
4
+ const modules = {
5
+ /**
6
+ * Take chart data and labels to create normalized data and min/max info
7
+ * @param {object} data chart series info
8
+ * @param {object} label chart label
9
+ *
10
+ * @returns {undefined}
11
+ */
12
+ createDataSet(data, label) {
13
+ Object.keys(this.seriesInfo.charts).forEach((typeKey) => {
14
+ const seriesIDs = this.seriesInfo.charts[typeKey];
15
+
16
+ if (seriesIDs.length) {
17
+ if (typeKey === 'pie') {
18
+ if (this.options.sunburst) {
19
+ this.createSunburstDataSet(data);
20
+ } else {
21
+ this.createPieDataSet(data, seriesIDs);
22
+ }
23
+ } else if (typeKey === 'scatter') {
24
+ seriesIDs.forEach((seriesID) => {
25
+ const series = this.seriesList[seriesID];
26
+ const sData = data[seriesID];
27
+
28
+ if (series && sData) {
29
+ series.data = this.addSeriesDSforScatter(sData);
30
+ series.minMax = this.getSeriesMinMax(series.data);
31
+ }
32
+ });
33
+ } else if (typeKey === 'heatMap') {
34
+ seriesIDs.forEach((seriesID) => {
35
+ const series = this.seriesList[seriesID];
36
+ const sData = data[seriesID];
37
+
38
+ if (series && sData) {
39
+ series.labels = label;
40
+ series.data = this.addSeriesDSForHeatMap(sData);
41
+ series.minMax = this.getSeriesMinMax(series.data);
42
+ series.valueOpt = this.getSeriesValueOptForHeatMap(series);
43
+ }
44
+ });
45
+ } else {
46
+ seriesIDs.forEach((seriesID) => {
47
+ const series = this.seriesList[seriesID];
48
+ const sData = data[seriesID];
49
+
50
+ if (series && sData) {
51
+ if (series.isExistGrp && series.stackIndex) {
52
+ series.data = this.addSeriesStackDS(sData, label, series.bsIds, series.stackIndex);
53
+ } else {
54
+ series.data = this.addSeriesDS(sData, label);
55
+ }
56
+ series.minMax = this.getSeriesMinMax(series.data);
57
+ }
58
+ });
59
+ }
60
+ }
61
+ });
62
+ },
63
+
64
+ /**
65
+ * Take chart data and to create normalized pie data
66
+ * @param {object} data chart series info
67
+ *
68
+ * @returns {undefined}
69
+ */
70
+ createSunburstDataSet(data) {
71
+ this.pieDataSet = [];
72
+ const ds = this.pieDataSet;
73
+ const sunburstQueue = [];
74
+
75
+ for (let ix = 0; ix < data.length; ix++) {
76
+ const slice = data[ix];
77
+ const series = this.seriesList[slice.id];
78
+ let showChildren = false;
79
+
80
+ if (!ds[0]) {
81
+ ds[0] = { ir: 0, or: 0, total: 0, data: [] };
82
+ }
83
+
84
+ if (series.show) {
85
+ ds[0].total += slice.value || 0;
86
+ ds[0].data.push({ parent: '$ev-root', id: slice.id, value: slice.value, sa: 0, ea: 0 });
87
+
88
+ if (slice.children) {
89
+ for (let jx = 0; jx < slice.children.length; jx++) {
90
+ const childSeries = this.seriesList[slice.children[jx].id];
91
+ if (childSeries.show) {
92
+ showChildren = true;
93
+ }
94
+ sunburstQueue.push({ parent: slice.id, data: slice.children[jx], depth: 1 });
95
+ }
96
+ } else {
97
+ const dummy = {
98
+ id: 'dummy',
99
+ value: slice.value,
100
+ };
101
+ sunburstQueue.push({ parent: slice.id, data: dummy, depth: 1 });
102
+ }
103
+
104
+ if (!showChildren) {
105
+ const dummy = {
106
+ id: 'dummy',
107
+ value: slice.value,
108
+ };
109
+ sunburstQueue.push({ parent: slice.id, data: dummy, depth: 1 });
110
+ }
111
+ }
112
+ }
113
+
114
+ ds[0].data.sort((a, b) => b.value - a.value);
115
+
116
+ while (sunburstQueue.length) {
117
+ const item = sunburstQueue.shift();
118
+ const parent = item.parent;
119
+ const slice = item.data;
120
+ const depth = item.depth;
121
+ let showChildren = false;
122
+
123
+ if (!ds[depth]) {
124
+ ds[depth] = { ir: 0, or: 0, total: {}, data: [] };
125
+ }
126
+
127
+ if (!ds[depth].total[parent]) {
128
+ ds[depth].total[parent] = 0;
129
+ }
130
+
131
+ const series = this.seriesList[slice.id];
132
+ if (slice.id === 'dummy') {
133
+ ds[depth].data.push({ parent, id: 'dummy', value: slice.value, sa: 0, ea: 0 });
134
+ ds[depth].total[parent] += slice.value;
135
+ } else if (series && series.show) {
136
+ ds[depth].data.push({ parent, id: slice.id, value: slice.value, sa: 0, ea: 0 });
137
+ ds[depth].total[parent] += slice.value;
138
+
139
+ if (slice.children) {
140
+ for (let ix = 0; ix < slice.children.length; ix++) {
141
+ if (this.seriesList[slice.children[ix].id].show) {
142
+ showChildren = true;
143
+ }
144
+ sunburstQueue.push({ parent: slice.id, data: slice.children[ix], depth: depth + 1 });
145
+ }
146
+ } else {
147
+ const dummy = {
148
+ id: 'dummy',
149
+ value: slice.value,
150
+ };
151
+ sunburstQueue.push({ parent: slice.id, data: dummy, depth: depth + 1 });
152
+ }
153
+
154
+ if (!showChildren) {
155
+ const dummy = {
156
+ id: 'dummy',
157
+ value: slice.value,
158
+ };
159
+ sunburstQueue.push({ parent: slice.id, data: dummy, depth: depth + 1 });
160
+ }
161
+ }
162
+
163
+ ds[depth].data.sort((a, b) => b.value - a.value);
164
+ }
165
+ },
166
+
167
+ /**
168
+ * Take chart data and to create normalized pie data
169
+ * @param {object} data chart data
170
+ * @param {String[]} seriesIDs chart series info
171
+ *
172
+ * @returns {undefined}
173
+ */
174
+ createPieDataSet(data, seriesIDs) {
175
+ this.pieDataSet = [];
176
+ const ds = this.pieDataSet;
177
+ ds[0] = { data: [], ir: 0, or: 0, total: 0 };
178
+
179
+ seriesIDs.forEach((sId) => {
180
+ if (this.seriesList[sId].show) {
181
+ const value = data[sId][0] ?? 0;
182
+ ds[0].total += value;
183
+ ds[0].data.push({ id: sId, value, sa: 0, ea: 0 });
184
+ }
185
+ });
186
+
187
+ ds.forEach((item) => {
188
+ item.data.sort((a, b) => b.value - a.value);
189
+ });
190
+ },
191
+
192
+ /**
193
+ * Take data and label to create stack data for each series
194
+ * @param {object} data chart series info
195
+ * @param {object} label chart label
196
+ * @param {array} bsIds stacked base data ID List
197
+ * @param {number} sIdx series ordered index
198
+ *
199
+ * @returns {array} data for each series
200
+ */
201
+ addSeriesStackDS(data, label, bsIds, sIdx = 0) {
202
+ const isHorizontal = this.options.horizontal;
203
+ const sdata = [];
204
+
205
+ const getBaseDataPosition = (baseIndex, dataIndex) => {
206
+ const nextBaseSeriesIndex = baseIndex - 1;
207
+ const baseSeries = this.seriesList[bsIds[baseIndex]];
208
+ const baseDataList = baseSeries.data;
209
+ const baseData = baseDataList[dataIndex];
210
+ const position = isHorizontal ? baseData?.x : baseData?.y;
211
+
212
+ if (position == null || !baseSeries.show) {
213
+ if (nextBaseSeriesIndex > -1) {
214
+ return getBaseDataPosition(nextBaseSeriesIndex, dataIndex);
215
+ }
216
+
217
+ return 0;
218
+ }
219
+
220
+ return position;
221
+ };
222
+
223
+ data.forEach((curr, index) => {
224
+ const baseIndex = bsIds.length - 1 < 0 ? 0 : bsIds.length - 1;
225
+ let bdata = getBaseDataPosition(baseIndex, index); // base(previous) series data
226
+ let odata = curr; // current series original data
227
+ let ldata = label[index]; // label data
228
+ let gdata = curr; // current series data which added previous series's value
229
+
230
+ if (bdata != null && ldata != null) {
231
+ if (gdata && typeof gdata === 'object' && (curr.x || curr.y)) {
232
+ odata = isHorizontal ? curr.x : curr.y;
233
+ ldata = isHorizontal ? curr.y : curr.x;
234
+ }
235
+
236
+ const oData = odata?.value ?? odata;
237
+ if (sIdx > 0) {
238
+ if (oData != null) {
239
+ gdata = bdata + oData;
240
+ } else {
241
+ gdata = null;
242
+ bdata = 0;
243
+ }
244
+ } else {
245
+ bdata = 0;
246
+ gdata = oData;
247
+ }
248
+
249
+ sdata.push(this.addData(gdata, ldata, odata, bdata));
250
+ }
251
+ });
252
+
253
+ return sdata;
254
+ },
255
+
256
+ /**
257
+ * Take data and label to create data for each series
258
+ * @param {object} data chart series info
259
+ * @param {object} label chart label
260
+ *
261
+ * @returns {array} data for each series
262
+ */
263
+ addSeriesDS(data, label) {
264
+ const isHorizontal = this.options.horizontal;
265
+ const sdata = [];
266
+
267
+ data.forEach((curr, index) => {
268
+ let gdata = curr;
269
+ let ldata = label[index];
270
+
271
+ if (gdata && typeof gdata === 'object' && (curr.x || curr.y)) {
272
+ gdata = isHorizontal ? curr.x : curr.y;
273
+ ldata = isHorizontal ? curr.y : curr.x;
274
+ }
275
+
276
+ if (ldata !== null) {
277
+ sdata.push(this.addData(gdata, ldata, gdata));
278
+ }
279
+ });
280
+
281
+ return sdata;
282
+ },
283
+
284
+ /**
285
+ * Take data to create data for each series
286
+ * @param {array} data data array for each series
287
+ * @returns {array} data info added position and etc
288
+ */
289
+ addSeriesDSforScatter(data) {
290
+ return data.map((item) => {
291
+ const ldata = item.x;
292
+ const gdata = {
293
+ value: item.y,
294
+ color: item?.color || null,
295
+ };
296
+
297
+ return this.addData(gdata, ldata, gdata);
298
+ });
299
+ },
300
+
301
+ /**
302
+ * Take data to create data for each series
303
+ * @param {array} data data array for each series
304
+ * @param {object} label chart label
305
+ *
306
+ * @returns {array} data info added position and etc
307
+ */
308
+ addSeriesDSForHeatMap(data) {
309
+ return data.map(({ x, y, value }) => ({
310
+ x,
311
+ y,
312
+ o: value,
313
+ xp: null,
314
+ yp: null,
315
+ w: null,
316
+ h: null,
317
+ dataColor: null,
318
+ cId: null,
319
+ }));
320
+ },
321
+
322
+ /**
323
+ * Take data to create data object for graph
324
+ * @param {object} gdata graph data (y-axis value for vertical chart)
325
+ * @param {object} ldata label data (x-axis value for vertical chart)
326
+ * @param {object} odata original data (without stacked value)
327
+ * @param {object} bdata base data (stacked value)
328
+
329
+ * @returns {object} data for each graph point
330
+ */
331
+ addData(gdata, ldata, odata = null, bdata = null) {
332
+ let data;
333
+ let gdataValue = null;
334
+ let odataValue = null;
335
+ let gdataColor = null;
336
+ let odataColor = null;
337
+
338
+ if (gdata !== null && typeof gdata === 'object') {
339
+ gdataValue = gdata.value;
340
+ gdataColor = gdata.color;
341
+ } else {
342
+ gdataValue = gdata ?? null;
343
+ }
344
+
345
+ if (odata !== null && typeof odata === 'object') {
346
+ odataValue = odata.value;
347
+ odataColor = odata.color;
348
+ } else {
349
+ odataValue = odata ?? null;
350
+ }
351
+
352
+ if (this.options.horizontal) {
353
+ data = { x: gdataValue, y: ldata, o: odataValue, b: bdata };
354
+ } else {
355
+ data = { x: ldata, y: gdataValue, o: odataValue, b: bdata };
356
+ }
357
+
358
+ data.xp = null;
359
+ data.yp = null;
360
+ data.w = null;
361
+ data.h = null;
362
+ data.dataColor = gdataColor ?? odataColor;
363
+
364
+ return data;
365
+ },
366
+
367
+ /**
368
+ * Take series data to create min/max info for each series
369
+ * @param {object} data series data
370
+ *
371
+ * @returns {object} min/max info for series
372
+ */
373
+ getSeriesMinMax(data) {
374
+ const def = { minX: null, minY: null, maxX: null, maxY: null, maxDomain: null };
375
+ const isHorizontal = this.options.horizontal;
376
+
377
+ if (data.length) {
378
+ return data.reduce((acc, p, index) => {
379
+ const minmax = acc;
380
+ const px = p.x?.value || p.x;
381
+ const py = p.y?.value || p.y;
382
+
383
+ if (px <= minmax.minX) {
384
+ minmax.minX = (px === null) ? 0 : px;
385
+ }
386
+ if (py <= minmax.minY) {
387
+ minmax.minY = (py === null) ? 0 : py;
388
+ }
389
+ if (px >= minmax.maxX) {
390
+ minmax.maxX = (px === null) ? 0 : px;
391
+
392
+ if (isHorizontal && px !== null) {
393
+ minmax.maxDomain = py;
394
+ minmax.maxDomainIndex = index;
395
+ }
396
+ }
397
+ if (py >= minmax.maxY) {
398
+ minmax.maxY = (py === null) ? 0 : py;
399
+
400
+ if (!isHorizontal && py !== null) {
401
+ minmax.maxDomain = px;
402
+ minmax.maxDomainIndex = index;
403
+ }
404
+ }
405
+
406
+ return minmax;
407
+ }, {
408
+ minX: data[0].x,
409
+ minY: data[0].y,
410
+ maxX: data[0].x,
411
+ maxY: data[0].y,
412
+ maxDomain: isHorizontal ? data[0].y : data[0].x,
413
+ maxDomainIndex: 0,
414
+ });
415
+ }
416
+
417
+ return def;
418
+ },
419
+
420
+ getSeriesValueOptForHeatMap(series) {
421
+ const { data, colorState, isGradient } = series;
422
+ const colorOpt = this.options.heatMapColor;
423
+ const categoryCnt = colorOpt.categoryCnt;
424
+ const decimalPoint = colorOpt.decimalPoint;
425
+
426
+ let minValue;
427
+ let maxValue = 0;
428
+
429
+ let isExistError = false;
430
+ data.forEach(({ o: value }) => {
431
+ if (maxValue < value) {
432
+ maxValue = Math.max(maxValue, value);
433
+ }
434
+
435
+ if (value < 0) {
436
+ isExistError = true;
437
+ } else if (minValue === undefined) {
438
+ minValue = value;
439
+ } else {
440
+ minValue = Math.min(minValue, value);
441
+ }
442
+ });
443
+
444
+ if (
445
+ isExistError
446
+ && !isGradient
447
+ && colorState.length === categoryCnt
448
+ ) {
449
+ colorState.push({
450
+ id: `color#${categoryCnt}`,
451
+ color: colorOpt.error,
452
+ state: 'normal',
453
+ show: true,
454
+ });
455
+ }
456
+
457
+ let interval = maxValue > minValue ? Math.floor((maxValue - minValue) / categoryCnt) : 1;
458
+ if ((maxValue - minValue) <= categoryCnt) {
459
+ if (decimalPoint > 0) {
460
+ interval = +((maxValue - minValue) / categoryCnt).toFixed(decimalPoint);
461
+ } else {
462
+ interval = 1;
463
+ }
464
+ }
465
+
466
+ return {
467
+ min: minValue,
468
+ max: maxValue,
469
+ interval,
470
+ existError: isExistError,
471
+ decimalPoint,
472
+ };
473
+ },
474
+
475
+ /**
476
+ * Get graph items for each series by label index
477
+ * @param {number} labelIndex label index
478
+ *
479
+ * @returns {object} graph item
480
+ */
481
+ getItemByLabelIndex(labelIndex) {
482
+ if (labelIndex < 0) {
483
+ return false;
484
+ }
485
+
486
+ const sIds = Object.keys(this.seriesList);
487
+ const isHorizontal = !!this.options.horizontal;
488
+
489
+ let maxl = null;
490
+ let maxp = null;
491
+ let maxg = null;
492
+ let maxSID = '';
493
+ let acc = 0;
494
+ let useStack = false;
495
+ let findInfo = false;
496
+
497
+ if (labelIndex > -1) {
498
+ for (let ix = 0; ix < sIds.length; ix++) {
499
+ const sId = sIds[ix];
500
+ const series = this.seriesList[sId];
501
+ const data = series.data[labelIndex];
502
+
503
+ if (data && series.show && series.showLegend) {
504
+ const ldata = isHorizontal ? data.y : data.x;
505
+ const lp = isHorizontal ? data.yp : data.xp;
506
+
507
+ if (ldata !== null && ldata !== undefined) {
508
+ const g = isHorizontal ? data.o || data.x : data.o || data.y;
509
+
510
+ if (series.stackIndex) {
511
+ acc += !isNaN(data.o) ? data.o : 0;
512
+ useStack = true;
513
+ } else {
514
+ acc += data.y;
515
+ }
516
+
517
+ if (maxg === null || maxg <= g) {
518
+ maxg = g;
519
+ maxSID = sId;
520
+ maxl = ldata;
521
+ maxp = lp;
522
+ }
523
+ }
524
+ }
525
+ }
526
+
527
+ findInfo = {
528
+ label: maxl,
529
+ pos: maxp,
530
+ value: maxg === null ? 0 : maxg,
531
+ sId: maxSID,
532
+ acc,
533
+ useStack,
534
+ maxIndex: labelIndex,
535
+ };
536
+ }
537
+
538
+ return findInfo;
539
+ },
540
+
541
+ getItem({ seriesID, dataIndex }, useApproximate = false) {
542
+ const dataInfo = this.getDataByValues(seriesID, dataIndex);
543
+
544
+ if (!dataInfo || !dataInfo?.xp || !dataInfo?.yp) {
545
+ return null;
546
+ }
547
+
548
+ return this.getItemByPosition([dataInfo.xp, dataInfo.yp], useApproximate);
549
+ },
550
+
551
+ /**
552
+ *
553
+ * @param seriesID
554
+ * @param dataIndex
555
+ * @returns {*}
556
+ */
557
+ getDataByValues(seriesID, dataIndex) {
558
+ const series = this.seriesList[seriesID];
559
+ if (!series || isNaN(dataIndex) || dataIndex < 0 || series?.data.length <= dataIndex) {
560
+ return false;
561
+ }
562
+
563
+ return series.data[dataIndex];
564
+ },
565
+
566
+ /**
567
+ * Find graph item by position x and y
568
+ * @param {array} offset position x and y
569
+ * @param {boolean} useApproximate if it's true. it'll look for closed item on mouse position
570
+ *
571
+ * @returns {object} clicked item information
572
+ */
573
+ getItemByPosition(offset, useApproximate = false) {
574
+ const seriesIDs = Object.keys(this.seriesList);
575
+ const isHorizontal = !!this.options.horizontal;
576
+
577
+ let maxType = null;
578
+ let maxLabel = null;
579
+ let maxValuePos = null;
580
+ let maxValue = null;
581
+ let maxSeriesID = '';
582
+ let acc = 0;
583
+ let useStack = false;
584
+ let maxIndex = null;
585
+
586
+ for (let ix = 0; ix < seriesIDs.length; ix++) {
587
+ const seriesID = seriesIDs[ix];
588
+ const series = this.seriesList[seriesID];
589
+ const findFn = useApproximate ? series.findApproximateData : series.findGraphData;
590
+
591
+ if (findFn) {
592
+ const item = findFn.call(series, offset, isHorizontal);
593
+ const data = item.data;
594
+ const index = item.index;
595
+
596
+ if (data) {
597
+ if (Util.isPieType(item.type)) {
598
+ maxLabel = seriesID;
599
+ maxSeriesID = seriesID;
600
+ maxValuePos = (data.ea - data.sa) / 2;
601
+ maxValue = data.o;
602
+ maxIndex = data.index;
603
+ maxType = item.type;
604
+ } else {
605
+ const ldata = isHorizontal ? data.y : data.x;
606
+ const lp = isHorizontal ? data.yp : data.xp;
607
+
608
+ if (ldata !== null && ldata !== undefined) {
609
+ const g = isHorizontal ? data.o || data.x : data.o || data.y;
610
+
611
+ if (series.stackIndex) {
612
+ acc += !isNaN(data.o) ? data.o : 0;
613
+ useStack = true;
614
+ } else {
615
+ acc += data.y;
616
+ }
617
+
618
+ if (maxValue === null || maxValue <= g) {
619
+ maxValue = g;
620
+ maxSeriesID = seriesID;
621
+ maxLabel = ldata;
622
+ maxValuePos = lp;
623
+ maxIndex = index;
624
+ maxType = series.type;
625
+ }
626
+ }
627
+ }
628
+ }
629
+ }
630
+ }
631
+
632
+ return {
633
+ type: maxType,
634
+ label: maxLabel,
635
+ pos: maxValuePos,
636
+ value: maxValue ?? 0,
637
+ sId: maxSeriesID,
638
+ acc,
639
+ useStack,
640
+ maxIndex,
641
+ };
642
+ },
643
+
644
+ /**
645
+ * Find seriesId by position x and y
646
+ * @param {array} offset position x and y
647
+ *
648
+ * @returns {object} clicked series id
649
+ */
650
+ getSeriesIdByPosition(offset) {
651
+ const [clickedX, clickedY] = offset;
652
+ const chartRect = this.chartRect;
653
+ const labelOffset = this.labelOffset;
654
+ const aPos = {
655
+ x1: chartRect.x1 + labelOffset.left,
656
+ x2: chartRect.x2 - labelOffset.right,
657
+ y1: chartRect.y1 + labelOffset.top,
658
+ y2: chartRect.y2 - labelOffset.bottom,
659
+ };
660
+ const valueAxes = this.axesY[0];
661
+ const labelAxes = this.axesX[0];
662
+ const valueStartPoint = aPos[valueAxes.units.rectStart];
663
+ const valueEndPoint = aPos[valueAxes.units.rectEnd];
664
+ const labelStartPoint = aPos[labelAxes.units.rectStart];
665
+ const labelEndPoint = aPos[labelAxes.units.rectEnd];
666
+
667
+ const result = { sId: null };
668
+
669
+ if (clickedY > valueEndPoint && clickedY < valueStartPoint
670
+ && clickedX < labelEndPoint && clickedX > labelStartPoint) {
671
+ let hitSeries;
672
+ let positionList;
673
+ const hitItem = this.findHitItem(offset);
674
+ const hitSeriesList = Object.keys(hitItem.items);
675
+
676
+ switch (this.options.type) {
677
+ case 'line': {
678
+ const orderedSeriesList = this.seriesInfo.charts.line;
679
+ const isStackChart = Object.values(this.seriesList).some(({ stackIndex }) => stackIndex);
680
+
681
+ if (hitSeriesList.length) { // 클릭한 위치에 data 가 존재하는 경우
682
+ if (isStackChart) {
683
+ positionList = orderedSeriesList.filter(sId => hitSeriesList.includes(sId))
684
+ .map(sId => ({ sId, position: hitItem.items[sId]?.data?.yp }));
685
+ hitSeries = positionList.find(({ position }) => clickedY > position)?.sId;
686
+ } else {
687
+ hitSeries = Object.entries(hitItem.items).find(([, { hit }]) => hit)?.[0];
688
+ }
689
+ } else { // 클릭한 위치에 data 가 존재하지 않는 경우
690
+ const visibleSeriesList = orderedSeriesList.filter(sId => this.seriesList[sId].show);
691
+ positionList = visibleSeriesList.map(sId => ({
692
+ sId,
693
+ position: this.seriesList[sId].data?.map(({ xp, yp }) => [xp, yp]),
694
+ }));
695
+ const dataIndex = positionList[0].position?.findIndex(([xp]) => xp >= clickedX);
696
+ const vectorList = positionList.map(({ sId, position }) => ({
697
+ sId,
698
+ vector: { start: position[dataIndex - 1], end: position[dataIndex] },
699
+ }));
700
+
701
+ const isEmptyVector = (arr => !arr || !Array.isArray(arr) || arr?.length !== 2);
702
+
703
+ // canvas 의 클릭 위치값은 제 4 사분면의 위치이므로 clickedY, y1, y2 의 값은 음수를 취한다.
704
+ if (isStackChart) {
705
+ hitSeries = vectorList.find(({ vector }) => {
706
+ if (isEmptyVector(vector?.start) && isEmptyVector(vector?.end)) {
707
+ return false;
708
+ }
709
+
710
+ const [x1, y1] = vector.start;
711
+ const [x2, y2] = vector.end;
712
+ const v1 = [x2 - x1, y1 - y2];
713
+ const v2 = [x2 - clickedX, clickedY - y2];
714
+ const xp = v1[0] * v2[1] - v1[1] * v2[0];
715
+
716
+ return vector.start.every(v => typeof v === 'number')
717
+ && vector.end.every(v => typeof v === 'number')
718
+ && xp > 0;
719
+ })?.sId;
720
+ } else {
721
+ hitSeries = vectorList.find(({ vector }) => {
722
+ if (isEmptyVector(vector?.start) && isEmptyVector(vector?.end)) {
723
+ return false;
724
+ }
725
+
726
+ const [x1, y1] = vector.start;
727
+ const [x2, y2] = vector.end;
728
+ const a = (y1 - y2) / (x2 - x1);
729
+ const b = -1;
730
+ const c = -y1 - a * x1;
731
+ const distance = Math.abs(a * clickedX - b * clickedY + c)
732
+ / Math.sqrt(a ** 2 + b ** 2);
733
+
734
+ return distance < 3;
735
+ })?.sId;
736
+ }
737
+ }
738
+ break;
739
+ }
740
+ default:
741
+ break;
742
+ }
743
+
744
+ result.sId = hitSeries;
745
+ }
746
+
747
+ return result;
748
+ },
749
+ /**
750
+ * Find label info by position x and y
751
+ * @param {array} offset position x and y
752
+ *
753
+ * @returns {object} clicked label information
754
+ */
755
+ getLabelInfoByPosition(offset) {
756
+ const [x, y] = offset;
757
+ const aPos = {
758
+ x1: this.chartRect.x1 + this.labelOffset.left,
759
+ x2: this.chartRect.x2 - this.labelOffset.right,
760
+ y1: this.chartRect.y1 + this.labelOffset.top,
761
+ y2: this.chartRect.y2 - this.labelOffset.bottom,
762
+ };
763
+
764
+ const scale = this.options.horizontal ? this.axesY[0] : this.axesX[0];
765
+ const startPoint = aPos[scale.units.rectStart];
766
+ const endPoint = aPos[scale.units.rectEnd];
767
+
768
+ let labelIndex;
769
+ let hitInfo;
770
+ if (scale.labels) {
771
+ const labelGap = (endPoint - startPoint) / scale.labels.length;
772
+ const index = Math.floor(((this.options.horizontal ? y : x) - startPoint) / labelGap);
773
+ labelIndex = scale.labels.length > index ? index : -1;
774
+ } else {
775
+ hitInfo = this.getItemByPosition(offset, this.options.selectLabel.useApproximateValue);
776
+ labelIndex = hitInfo.maxIndex ?? -1;
777
+ }
778
+
779
+ return {
780
+ labelIndex,
781
+ hitInfo,
782
+ };
783
+ },
784
+
785
+ /**
786
+ * Create min/max information for all of data
787
+ * @property seriesList
788
+ *
789
+ * @returns {object} min/max info for all of data
790
+ */
791
+ getStoreMinMax() {
792
+ const keys = Object.keys(this.seriesList);
793
+ const isHorizontal = this.options.horizontal;
794
+ const def = {
795
+ x: [{ min: null, max: null }],
796
+ y: [{ min: null, max: null }],
797
+ };
798
+
799
+ if (keys.length) {
800
+ return keys.reduce((acc, key) => {
801
+ const minmax = acc;
802
+ const series = this.seriesList[key];
803
+ const smm = series.minMax;
804
+ const axisX = series.xAxisIndex;
805
+ const axisY = series.yAxisIndex;
806
+
807
+ if (!minmax.x[axisX]) {
808
+ minmax.x[axisX] = { min: null, max: null, maxSID: null };
809
+ }
810
+ if (!minmax.y[axisY]) {
811
+ minmax.y[axisY] = { min: null, max: null, maxSID: null };
812
+ }
813
+
814
+ if (smm && series.show) {
815
+ if (!isHorizontal) {
816
+ if (smm.minX !== null
817
+ && ((minmax.x[axisX].min === null || (smm.minX < minmax.x[axisX].min)))) {
818
+ minmax.x[axisX].min = smm.minX;
819
+ }
820
+ if (minmax.y[axisY].min === null || (smm.minY < minmax.y[axisY].min)) {
821
+ minmax.y[axisY].min = smm.minY;
822
+ }
823
+ } else {
824
+ if (minmax.x[axisX].min === null || (smm.minX < minmax.x[axisX].min)) {
825
+ minmax.x[axisX].min = smm.minX;
826
+ }
827
+ if (smm.minY !== null
828
+ && (minmax.y[axisY].min === null || (smm.minY < minmax.y[axisY].min))) {
829
+ minmax.y[axisY].min = smm.minY;
830
+ }
831
+ }
832
+ if (smm.maxX >= minmax.x[axisX].max) {
833
+ minmax.x[axisX].max = smm.maxX;
834
+ minmax.x[axisX].maxSID = key;
835
+ }
836
+ if (smm.maxY >= minmax.y[axisY].max) {
837
+ minmax.y[axisY].max = smm.maxY;
838
+ minmax.y[axisX].maxSID = key;
839
+ }
840
+ }
841
+
842
+ return minmax;
843
+ }, {
844
+ x: [{ min: null, max: null, maxSID: null }],
845
+ y: [{ min: null, max: null, maxSID: null }],
846
+ });
847
+ }
848
+
849
+ return def;
850
+ },
851
+
852
+ calculateAngle() {
853
+ const pieDataSet = this.pieDataSet;
854
+
855
+ let slice;
856
+ let value;
857
+ let parent;
858
+ let totalValue;
859
+
860
+ let sliceAngle;
861
+ let startAngle;
862
+ let endAngle;
863
+ let totalAngle;
864
+ let isDummy;
865
+
866
+ const dummyIndex = [];
867
+ const saStore = {
868
+ '$ev-root': 1.5 * Math.PI,
869
+ };
870
+
871
+ for (let ix = 0; ix < pieDataSet.length; ix++) {
872
+ const pie = pieDataSet[ix];
873
+ isDummy = true;
874
+
875
+ for (let jx = 0; jx < pie.data.length; jx++) {
876
+ slice = pie.data[jx];
877
+ value = slice.value;
878
+
879
+ if (isDummy) {
880
+ isDummy = slice.id === 'dummy';
881
+ }
882
+
883
+ if (!ix) {
884
+ startAngle = saStore['$ev-root'];
885
+ sliceAngle = 2 * Math.PI * (value / pie.total);
886
+ endAngle = startAngle + sliceAngle;
887
+
888
+ slice.sa = startAngle;
889
+ slice.ea = endAngle;
890
+ saStore['$ev-root'] += sliceAngle;
891
+ } else {
892
+ parent = this.getParentInfo(ix - 1, slice.parent);
893
+ if (!parent) {
894
+ break;
895
+ }
896
+
897
+ if (!saStore[slice.parent]) {
898
+ saStore[slice.parent] = parent.sa;
899
+ }
900
+
901
+ startAngle = saStore[slice.parent];
902
+ totalAngle = parent.ea - parent.sa;
903
+ totalValue = pie.total[slice.parent] || 0;
904
+ sliceAngle = totalAngle * (value / totalValue);
905
+ endAngle = startAngle + sliceAngle;
906
+
907
+ slice.sa = startAngle;
908
+ slice.ea = endAngle;
909
+
910
+ saStore[slice.parent] += sliceAngle;
911
+ }
912
+ }
913
+
914
+ if (isDummy) {
915
+ dummyIndex.push(ix);
916
+ }
917
+ }
918
+
919
+ for (let ix = 0; ix < dummyIndex.length; ix++) {
920
+ this.pieDataSet.splice(dummyIndex, 1);
921
+ }
922
+
923
+ if (this.options.reverse) {
924
+ this.pieDataSet = reverse(this.pieDataSet);
925
+ }
926
+ },
927
+
928
+ getParentInfo(depth, parentId) {
929
+ for (let ix = depth; ix >= 0; ix--) {
930
+ const pie = this.pieDataSet[ix];
931
+ for (let jx = 0; jx < pie.data.length; jx++) {
932
+ if (pie.data[jx].id === parentId) {
933
+ return pie.data[jx];
934
+ }
935
+ }
936
+ }
937
+
938
+ return null;
939
+ },
940
+
941
+ /**
942
+ * Get Aggregations (
943
+ * @returns {{}}
944
+ */
945
+ getAggregations() {
946
+ const allData = this.data.data;
947
+ const series = this.data.series;
948
+ const aggregationDataSet = {};
949
+ const seriesIds = Object.keys(series);
950
+
951
+ seriesIds?.forEach((sId) => {
952
+ const dataList = allData[sId].map(data => (data?.value ? data.value : data));
953
+ const last = (dataList[dataList.length - 1]);
954
+
955
+ const dataListExcludedNull = dataList.filter(value => value !== undefined && value !== null);
956
+ const min = (Math.min(...dataListExcludedNull));
957
+ const max = (Math.max(...dataListExcludedNull));
958
+ const total = (dataListExcludedNull.reduce((a, b) => a + b, 0));
959
+ const avg = (total / dataListExcludedNull.length || 0);
960
+
961
+ if (!Util.checkSafeInteger(min)
962
+ || !Util.checkSafeInteger(max)
963
+ || !Util.checkSafeInteger(avg)
964
+ || !Util.checkSafeInteger(total)
965
+ || !Util.checkSafeInteger(last)
966
+ ) {
967
+ console.warn('[EVUI][Chart] The aggregated value exceeds 9007199254740991 or less then -9007199254740991.');
968
+ }
969
+
970
+ aggregationDataSet[sId] = { min, max, avg, total, last };
971
+ });
972
+
973
+ return aggregationDataSet;
974
+ },
975
+ };
976
+
977
+ export default modules;