evui 3.4.32 → 3.4.33

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evui",
3
- "version": "3.4.32",
3
+ "version": "3.4.33",
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
+ };
@@ -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, column.summaryType)"
56
+ :title="getSummaryValue(column)"
57
57
  >
58
- {{ getSummaryValue(column, column.summaryType)}}
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 (column.type === 'number') {
136
+ if (type === 'number') {
114
137
  convertValue = numberWithComma(value);
115
138
  convertValue = convertValue === false ? value : convertValue;
116
- } else if (column.type === 'float') {
117
- const floatValue = convertValue.toFixed(column.decimal ?? 3);
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, summaryType) => {
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(column.field);
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 (column.type === 'number' || column.type === 'float') {
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
- if (column.summaryOnlyTopParent) {
136
- if (!cur.parent) {
137
- acc.push(cur.data?.[column.field]);
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
- return acc;
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
- result = columnValues.reduce((prev, curr) => {
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 + value;
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
- case 'average':
158
- result = columnValues.reduce((prev, curr) => {
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 + value;
198
+ return bnPlus(prev, value);
162
199
  }
163
200
  return prev;
164
- }, 0) / columnValues.length;
165
- if (result % 1 !== 0) {
166
- result = result.toFixed(1);
167
- }
201
+ }, 0);
202
+ result = sumValue && bnFloor(
203
+ bnDivide(sumValue, columnValues.length),
204
+ getValidDecimal(summaryDecimal ?? DECIMAL.default),
205
+ );
168
206
  break;
169
- case 'max':
170
- result = Math.max(...columnValues);
207
+ }
208
+ case 'max': {
209
+ const filteredNullValues = columnValues.filter(value => value != null);
210
+ result = filteredNullValues.length ? Math.max(...filteredNullValues) : '';
171
211
  break;
172
- case 'min':
173
- result = Math.min(...columnValues);
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
- let resizeWidth = Math.max(minLeft, proxyLeft);
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
- if (!sortable && !filterable) {
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
- allCheck.value = curr.length === filteredItems.value.filter(item => !item.disabled).length;
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
  });