evui 3.4.32 → 3.4.34
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.
- package/dist/evui.common.js +4167 -1115
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +4167 -1115
- package/dist/evui.umd.js.map +1 -1
- package/dist/evui.umd.min.js +1 -1
- package/dist/evui.umd.min.js.map +1 -1
- package/package.json +3 -2
- package/src/common/utils.bignumber.js +67 -0
- package/src/components/chart/plugins/plugins.interaction.js +7 -1
- package/src/components/contextMenu/MenuList.vue +1 -1
- package/src/components/contextMenu/uses.js +4 -4
- package/src/components/grid/Grid.vue +1 -0
- package/src/components/grid/GridSummary.vue +74 -34
- package/src/components/grid/uses.js +11 -9
- package/src/components/select/uses.js +5 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evui",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.34",
|
|
4
4
|
"description": "A EXEM Library project",
|
|
5
5
|
"author": "exem <dev_client@ex-em.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"vue-resize-observer": "^2.0.15",
|
|
28
28
|
"vue3-observe-visibility": "^0.1.2",
|
|
29
29
|
"vue-router": "^4.0.0-0",
|
|
30
|
-
"vuex": "^4.0.0-0"
|
|
30
|
+
"vuex": "^4.0.0-0",
|
|
31
|
+
"bignumber.js": "^9.1.2"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@vue/cli-plugin-babel": "~4.5.0",
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import BigNumber from 'bignumber.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Convert Number to BigNumber
|
|
5
|
+
* @param {Number} value
|
|
6
|
+
* @return {BigNumber}
|
|
7
|
+
*/
|
|
8
|
+
function toBigNumber(value) { return new BigNumber(value); }
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* plus(+)
|
|
12
|
+
* @param {Number} num1
|
|
13
|
+
* @param {Number} num2
|
|
14
|
+
* @return {Number}
|
|
15
|
+
*/
|
|
16
|
+
function bnPlus(num1, num2) {
|
|
17
|
+
return toBigNumber(num1).plus(toBigNumber(num2)).toNumber();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* minus(-)
|
|
22
|
+
* @param {Number} num1
|
|
23
|
+
* @param {Number} num2
|
|
24
|
+
* @return {Number}
|
|
25
|
+
*/
|
|
26
|
+
function bnMinus(num1, num2) {
|
|
27
|
+
return toBigNumber(num1).minus(toBigNumber(num2)).toNumber();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* multiply(*)
|
|
32
|
+
* @param {Number} num1
|
|
33
|
+
* @param {Number} num2
|
|
34
|
+
* @return {Number}
|
|
35
|
+
*/
|
|
36
|
+
function bnMultiply(num1, num2) {
|
|
37
|
+
return toBigNumber(num1).multipliedBy(toBigNumber(num2)).toNumber();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* divide(/)
|
|
42
|
+
* @param {Number} dividend
|
|
43
|
+
* @param {Number} divisor
|
|
44
|
+
* @return {Number}
|
|
45
|
+
*/
|
|
46
|
+
function bnDivide(dividend, divisor) {
|
|
47
|
+
return toBigNumber(dividend).dividedBy(toBigNumber((divisor))).toNumber();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* floor
|
|
52
|
+
* @param {Number} num
|
|
53
|
+
* @param {Number} decimal
|
|
54
|
+
* @return {Number}
|
|
55
|
+
*/
|
|
56
|
+
function bnFloor(num, decimal) {
|
|
57
|
+
return toBigNumber(num).decimalPlaces(decimal, BigNumber.ROUND_DOWN).toNumber();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
toBigNumber,
|
|
62
|
+
bnPlus,
|
|
63
|
+
bnMinus,
|
|
64
|
+
bnMultiply,
|
|
65
|
+
bnDivide,
|
|
66
|
+
bnFloor,
|
|
67
|
+
};
|
|
@@ -737,6 +737,7 @@ const modules = {
|
|
|
737
737
|
items[sId] = item;
|
|
738
738
|
|
|
739
739
|
const formattedTxt = this.getFormattedTooltipValue({
|
|
740
|
+
seriesId: sId,
|
|
740
741
|
seriesName: sName,
|
|
741
742
|
value: gdata,
|
|
742
743
|
itemData: item.data,
|
|
@@ -774,12 +775,13 @@ const modules = {
|
|
|
774
775
|
|
|
775
776
|
/**
|
|
776
777
|
* get formatted value for tooltip
|
|
778
|
+
* @param seriesId
|
|
777
779
|
* @param seriesName
|
|
778
780
|
* @param value
|
|
779
781
|
* @param itemData
|
|
780
782
|
* @returns {string}
|
|
781
783
|
*/
|
|
782
|
-
getFormattedTooltipValue({ seriesName, value, itemData }) {
|
|
784
|
+
getFormattedTooltipValue({ seriesId, seriesName, value, itemData }) {
|
|
783
785
|
const opt = this.options;
|
|
784
786
|
const isHorizontal = !!opt.horizontal;
|
|
785
787
|
const tooltipOpt = opt.tooltip;
|
|
@@ -794,18 +796,21 @@ const modules = {
|
|
|
794
796
|
value,
|
|
795
797
|
name: seriesName,
|
|
796
798
|
percentage: itemData?.percentage,
|
|
799
|
+
seriesId,
|
|
797
800
|
});
|
|
798
801
|
} else if (opt.type === 'heatMap') {
|
|
799
802
|
formattedTxt = tooltipValueFormatter({
|
|
800
803
|
x: itemData?.x,
|
|
801
804
|
y: itemData?.y,
|
|
802
805
|
value: value > -1 ? value : 'error',
|
|
806
|
+
seriesId,
|
|
803
807
|
});
|
|
804
808
|
} else {
|
|
805
809
|
formattedTxt = tooltipValueFormatter({
|
|
806
810
|
x: isHorizontal ? value : itemData?.x,
|
|
807
811
|
y: isHorizontal ? itemData?.y : value,
|
|
808
812
|
name: seriesName,
|
|
813
|
+
seriesId,
|
|
809
814
|
});
|
|
810
815
|
}
|
|
811
816
|
}
|
|
@@ -848,6 +853,7 @@ const modules = {
|
|
|
848
853
|
);
|
|
849
854
|
|
|
850
855
|
const formattedValue = this.getFormattedTooltipValue({
|
|
856
|
+
seriesId: sId,
|
|
851
857
|
seriesName: series.name,
|
|
852
858
|
value: hasData?.o,
|
|
853
859
|
itemData: hasData,
|
|
@@ -190,14 +190,14 @@ export const useMenuList = () => {
|
|
|
190
190
|
/**
|
|
191
191
|
* 항목에 마우스엔터 시 발생하는 이벤트
|
|
192
192
|
* @param e - 마우스 이벤트 (showChild에 넘김)
|
|
193
|
-
* @param
|
|
193
|
+
* @param item - 마우스오버된 메뉴
|
|
194
194
|
* @returns null
|
|
195
195
|
*/
|
|
196
|
-
const mouseenterLi = async (e,
|
|
197
|
-
if (!children || !Array.isArray(children)) {
|
|
196
|
+
const mouseenterLi = async (e, item) => {
|
|
197
|
+
if (!item.children || !Array.isArray(item.children) || item.disabled) {
|
|
198
198
|
hideChild();
|
|
199
199
|
} else {
|
|
200
|
-
await showChild(e, children);
|
|
200
|
+
await showChild(e, item.children);
|
|
201
201
|
}
|
|
202
202
|
};
|
|
203
203
|
|
|
@@ -801,6 +801,7 @@ export default {
|
|
|
801
801
|
contextMenuItems: [],
|
|
802
802
|
columnMenu: null,
|
|
803
803
|
columnMenuItems: [],
|
|
804
|
+
hiddenColumnMenuItem: props.option.hiddenColumnMenuItem || {},
|
|
804
805
|
customContextMenu: props.option.customContextMenu || [],
|
|
805
806
|
gridSettingMenu: null,
|
|
806
807
|
gridSettingContextMenuItems: [],
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
</div>
|
|
54
54
|
<div
|
|
55
55
|
v-else
|
|
56
|
-
:title="getSummaryValue(column
|
|
56
|
+
:title="getSummaryValue(column)"
|
|
57
57
|
>
|
|
58
|
-
{{ getSummaryValue(column
|
|
58
|
+
{{ getSummaryValue(column)}}
|
|
59
59
|
</div>
|
|
60
60
|
</span>
|
|
61
61
|
<span
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
<script>
|
|
72
72
|
import { computed, watch, ref, nextTick } from 'vue';
|
|
73
73
|
import { numberWithComma } from '@/common/utils';
|
|
74
|
+
import { bnDivide, bnFloor, bnPlus } from '@/common/utils.bignumber';
|
|
74
75
|
|
|
75
76
|
export default {
|
|
76
77
|
name: 'EvGridSummary',
|
|
@@ -101,77 +102,119 @@ export default {
|
|
|
101
102
|
},
|
|
102
103
|
},
|
|
103
104
|
setup(props) {
|
|
105
|
+
const DECIMAL = {
|
|
106
|
+
max: 20,
|
|
107
|
+
default: 3,
|
|
108
|
+
};
|
|
104
109
|
const summaryRef = ref();
|
|
105
110
|
const ROW_DATA_INDEX = 2;
|
|
106
111
|
const stores = computed(() => props.stores);
|
|
107
112
|
const columns = computed(() => props.orderedColumns);
|
|
108
113
|
const showCheckbox = computed(() => props.useCheckbox);
|
|
109
114
|
const styleInfo = computed(() => props.styleOption);
|
|
115
|
+
|
|
116
|
+
const getValidDecimal = (decimal) => {
|
|
117
|
+
if (decimal == null || decimal < 0) {
|
|
118
|
+
return DECIMAL.default;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (decimal > DECIMAL.max) {
|
|
122
|
+
return DECIMAL.max;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return decimal;
|
|
126
|
+
};
|
|
127
|
+
|
|
110
128
|
const getConvertValue = (column, value) => {
|
|
129
|
+
if (typeof value === 'string' && value.length === 0) {
|
|
130
|
+
return value;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const { type, decimal } = column;
|
|
111
134
|
let convertValue = value;
|
|
112
135
|
|
|
113
|
-
if (
|
|
136
|
+
if (type === 'number') {
|
|
114
137
|
convertValue = numberWithComma(value);
|
|
115
138
|
convertValue = convertValue === false ? value : convertValue;
|
|
116
|
-
} else if (
|
|
117
|
-
const floatValue = convertValue.toFixed(
|
|
139
|
+
} else if (type === 'float') {
|
|
140
|
+
const floatValue = convertValue.toFixed(getValidDecimal(decimal ?? DECIMAL.default));
|
|
118
141
|
convertValue = floatValue.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
119
142
|
}
|
|
120
143
|
|
|
121
144
|
return convertValue;
|
|
122
145
|
};
|
|
146
|
+
|
|
123
147
|
const getColumnIndex = field => columns.value.findIndex(column => column.field === field);
|
|
124
|
-
const getSummaryValue = (column
|
|
148
|
+
const getSummaryValue = (column) => {
|
|
149
|
+
const {
|
|
150
|
+
type,
|
|
151
|
+
field,
|
|
152
|
+
summaryType,
|
|
153
|
+
summaryDecimal,
|
|
154
|
+
summaryOnlyTopParent,
|
|
155
|
+
} = column;
|
|
156
|
+
|
|
125
157
|
let result = '';
|
|
126
|
-
const columnIndex = getColumnIndex(
|
|
158
|
+
const columnIndex = getColumnIndex(field);
|
|
127
159
|
if (columnIndex >= 0) {
|
|
128
160
|
if (summaryType === 'count') {
|
|
129
161
|
return stores.value.store.length;
|
|
130
162
|
}
|
|
131
|
-
if (
|
|
163
|
+
if (type === 'number' || type === 'float') {
|
|
132
164
|
let columnValues = [];
|
|
133
165
|
if (props.isTree) {
|
|
134
166
|
columnValues = stores.value.store.reduce((acc, cur) => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
} else {
|
|
140
|
-
acc.push(cur.data?.[column.field]);
|
|
167
|
+
if (summaryOnlyTopParent) {
|
|
168
|
+
if (!cur.parent) {
|
|
169
|
+
acc.push(cur.data?.[field]);
|
|
141
170
|
}
|
|
142
|
-
|
|
143
|
-
|
|
171
|
+
} else {
|
|
172
|
+
acc.push(cur.data?.[field]);
|
|
173
|
+
}
|
|
174
|
+
return acc;
|
|
175
|
+
}, []);
|
|
144
176
|
} else {
|
|
145
177
|
columnValues = stores.value.store.map(row => row[ROW_DATA_INDEX][columnIndex]);
|
|
146
178
|
}
|
|
147
179
|
switch (summaryType) {
|
|
148
|
-
case 'sum':
|
|
149
|
-
|
|
180
|
+
case 'sum': {
|
|
181
|
+
const sumValue = columnValues.reduce((prev, curr) => {
|
|
150
182
|
const value = Number(curr);
|
|
151
183
|
if (!Number.isNaN(value)) {
|
|
152
|
-
return prev
|
|
184
|
+
return bnPlus(prev, value);
|
|
153
185
|
}
|
|
154
186
|
return prev;
|
|
155
187
|
}, 0);
|
|
188
|
+
|
|
189
|
+
result = sumValue && bnFloor(
|
|
190
|
+
sumValue, getValidDecimal(summaryDecimal ?? DECIMAL.default),
|
|
191
|
+
);
|
|
156
192
|
break;
|
|
157
|
-
|
|
158
|
-
|
|
193
|
+
}
|
|
194
|
+
case 'average': {
|
|
195
|
+
const sumValue = columnValues.reduce((prev, curr) => {
|
|
159
196
|
const value = Number(curr);
|
|
160
197
|
if (!Number.isNaN(value)) {
|
|
161
|
-
return prev
|
|
198
|
+
return bnPlus(prev, value);
|
|
162
199
|
}
|
|
163
200
|
return prev;
|
|
164
|
-
}, 0)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
201
|
+
}, 0);
|
|
202
|
+
result = sumValue && bnFloor(
|
|
203
|
+
bnDivide(sumValue, columnValues.length),
|
|
204
|
+
getValidDecimal(summaryDecimal ?? DECIMAL.default),
|
|
205
|
+
);
|
|
168
206
|
break;
|
|
169
|
-
|
|
170
|
-
|
|
207
|
+
}
|
|
208
|
+
case 'max': {
|
|
209
|
+
const filteredNullValues = columnValues.filter(value => value != null);
|
|
210
|
+
result = filteredNullValues.length ? Math.max(...filteredNullValues) : '';
|
|
171
211
|
break;
|
|
172
|
-
|
|
173
|
-
|
|
212
|
+
}
|
|
213
|
+
case 'min': {
|
|
214
|
+
const filteredNullValues = columnValues.filter(value => value != null);
|
|
215
|
+
result = filteredNullValues.length ? Math.min(...filteredNullValues) : '';
|
|
174
216
|
break;
|
|
217
|
+
}
|
|
175
218
|
default:
|
|
176
219
|
break;
|
|
177
220
|
}
|
|
@@ -188,10 +231,7 @@ export default {
|
|
|
188
231
|
fields.forEach((name, idx) => {
|
|
189
232
|
const columnIndex = getColumnIndex(name);
|
|
190
233
|
if (columnIndex >= 0) {
|
|
191
|
-
const value = getSummaryValue(
|
|
192
|
-
stores.value.orderedColumns[columnIndex],
|
|
193
|
-
column.summaryType,
|
|
194
|
-
);
|
|
234
|
+
const value = getSummaryValue(stores.value.orderedColumns[columnIndex]);
|
|
195
235
|
result = result.replace(`{${idx}}`, value);
|
|
196
236
|
}
|
|
197
237
|
});
|
|
@@ -309,7 +309,6 @@ export const resizeEvent = (params) => {
|
|
|
309
309
|
const minWidth = isRenderer(stores.orderedColumns[columnIndex])
|
|
310
310
|
? resizeInfo.rendererMinWidth : resizeInfo.minWidth;
|
|
311
311
|
const columnRect = columnEl.getBoundingClientRect();
|
|
312
|
-
const maxRight = bodyEl.getBoundingClientRect().right - headerLeft;
|
|
313
312
|
const resizeLineEl = elementInfo.resizeLine;
|
|
314
313
|
const minLeft = columnRect.left - headerLeft + minWidth;
|
|
315
314
|
const startLeft = columnRect.right - headerLeft;
|
|
@@ -324,9 +323,7 @@ export const resizeEvent = (params) => {
|
|
|
324
323
|
const handleMouseMove = (evt) => {
|
|
325
324
|
const deltaLeft = evt.clientX - startMouseLeft;
|
|
326
325
|
const proxyLeft = startLeft + deltaLeft;
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
resizeWidth = Math.min(maxRight, resizeWidth);
|
|
326
|
+
const resizeWidth = Math.max(minLeft, proxyLeft);
|
|
330
327
|
|
|
331
328
|
resizeLineEl.style.left = `${resizeWidth}px`;
|
|
332
329
|
};
|
|
@@ -1025,21 +1022,19 @@ export const contextMenuEvent = (params) => {
|
|
|
1025
1022
|
const sortable = column.sortable === undefined ? true : column.sortable;
|
|
1026
1023
|
const filterable = filterInfo.isFiltering
|
|
1027
1024
|
&& column.filterable === undefined ? true : column.filterable;
|
|
1028
|
-
|
|
1029
|
-
contextInfo.columnMenuItems = [];
|
|
1030
|
-
return;
|
|
1031
|
-
}
|
|
1032
|
-
contextInfo.columnMenuItems = [
|
|
1025
|
+
const columnMenuItems = [
|
|
1033
1026
|
{
|
|
1034
1027
|
text: 'Ascending',
|
|
1035
1028
|
iconClass: 'ev-icon-allow2-up',
|
|
1036
1029
|
disabled: !sortable,
|
|
1030
|
+
hidden: contextInfo.hiddenColumnMenuItem?.ascending,
|
|
1037
1031
|
click: () => onSort(column, 'asc'),
|
|
1038
1032
|
},
|
|
1039
1033
|
{
|
|
1040
1034
|
text: 'Descending',
|
|
1041
1035
|
iconClass: 'ev-icon-allow2-down',
|
|
1042
1036
|
disabled: !sortable,
|
|
1037
|
+
hidden: contextInfo.hiddenColumnMenuItem?.descending,
|
|
1043
1038
|
click: () => onSort(column, 'desc'),
|
|
1044
1039
|
},
|
|
1045
1040
|
{
|
|
@@ -1062,14 +1057,21 @@ export const contextMenuEvent = (params) => {
|
|
|
1062
1057
|
filterInfo.filteringColumn = column;
|
|
1063
1058
|
},
|
|
1064
1059
|
disabled: !filterable,
|
|
1060
|
+
hidden: contextInfo.hiddenColumnMenuItem?.filter,
|
|
1065
1061
|
},
|
|
1066
1062
|
{
|
|
1067
1063
|
text: 'Hide',
|
|
1068
1064
|
iconClass: 'ev-icon-visibility-off',
|
|
1069
1065
|
disabled: !useGridSetting.value || stores.orderedColumns.length === 1,
|
|
1066
|
+
hidden: contextInfo.hiddenColumnMenuItem?.hide,
|
|
1070
1067
|
click: () => setColumnHidden(column.field),
|
|
1071
1068
|
},
|
|
1072
1069
|
];
|
|
1070
|
+
contextInfo.columnMenuItems = [];
|
|
1071
|
+
if (!sortable && !filterable) {
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
contextInfo.columnMenuItems = columnMenuItems.filter(item => !item.hidden);
|
|
1073
1075
|
}
|
|
1074
1076
|
};
|
|
1075
1077
|
/**
|
|
@@ -277,7 +277,11 @@ export const useDropdown = (param) => {
|
|
|
277
277
|
|
|
278
278
|
watch(() => mv.value, (curr) => {
|
|
279
279
|
if (props.multiple && props.checkable) {
|
|
280
|
-
|
|
280
|
+
if (curr.length === 0) {
|
|
281
|
+
allCheck.value = false;
|
|
282
|
+
} else {
|
|
283
|
+
allCheck.value = curr.length === filteredItems.value.filter(item => !item.disabled).length;
|
|
284
|
+
}
|
|
281
285
|
changeDropboxPosition();
|
|
282
286
|
}
|
|
283
287
|
});
|