evui 3.4.9 → 3.4.10
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 +4725 -4511
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +4725 -4511
- 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 +1 -1
- package/src/components/chart/chart.core.js +0 -5
- package/src/components/chart/plugins/plugins.interaction.js +5 -3
- package/src/components/chart/plugins/plugins.scrollbar.js +17 -23
- package/src/components/chart/scale/scale.js +7 -2
- package/src/components/grid/Grid.vue +29 -20
- package/src/components/grid/grid.filterSetting.vue +13 -2
- package/src/components/grid/uses.js +92 -71
- package/src/components/treeGrid/TreeGrid.vue +32 -1
- package/src/components/treeGrid/TreeGridNode.vue +63 -8
- package/src/components/treeGrid/style/treeGrid.scss +14 -1
- package/src/components/treeGrid/uses.js +4 -2
package/package.json
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import throttle from '@/common/utils.throttle';
|
|
2
1
|
import { mobileCheck } from '@/common/utils';
|
|
3
2
|
import Model from './model';
|
|
4
3
|
import TimeScale from './scale/scale.time';
|
|
@@ -134,10 +133,6 @@ class EvChart {
|
|
|
134
133
|
|
|
135
134
|
if (tooltip.use) {
|
|
136
135
|
this.createTooltipDOM();
|
|
137
|
-
|
|
138
|
-
if (tooltip.throttledMove) {
|
|
139
|
-
this.onMouseMove = throttle(this.onMouseMove, 30);
|
|
140
|
-
}
|
|
141
136
|
}
|
|
142
137
|
|
|
143
138
|
this.createEventFunctions?.();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { numberWithComma } from '@/common/utils';
|
|
2
|
+
import throttle from '@/common/utils.throttle';
|
|
2
3
|
import { cloneDeep, defaultsDeep, inRange } from 'lodash-es';
|
|
3
4
|
import dayjs from 'dayjs';
|
|
4
5
|
|
|
@@ -33,11 +34,9 @@ const modules = {
|
|
|
33
34
|
this.overlayClear();
|
|
34
35
|
|
|
35
36
|
if (Object.keys(hitInfo.items).length) {
|
|
36
|
-
if (
|
|
37
|
+
if (tooltip.use) {
|
|
37
38
|
this.drawItemsHighlight(hitInfo, ctx);
|
|
38
|
-
}
|
|
39
39
|
|
|
40
|
-
if (tooltip.use) {
|
|
41
40
|
if (tooltip?.formatter?.html) {
|
|
42
41
|
this.drawCustomTooltip(hitInfo?.items);
|
|
43
42
|
this.setCustomTooltipLayoutPosition(hitInfo, e);
|
|
@@ -349,6 +348,9 @@ const modules = {
|
|
|
349
348
|
if (this.options?.tooltip?.useScrollbar) {
|
|
350
349
|
this.overlayCanvas.addEventListener('wheel', this.onWheel, { passive: false });
|
|
351
350
|
}
|
|
351
|
+
if (this.options?.tooltip?.throttledMove) {
|
|
352
|
+
this.onMouseMove = throttle(this.onMouseMove, 30);
|
|
353
|
+
}
|
|
352
354
|
|
|
353
355
|
this.overlayCanvas.addEventListener('mousemove', this.onMouseMove);
|
|
354
356
|
this.overlayCanvas.addEventListener('mouseleave', this.onMouseLeave);
|
|
@@ -33,6 +33,7 @@ const module = {
|
|
|
33
33
|
scrollbarOpt.type = axisOpt?.[0]?.type;
|
|
34
34
|
scrollbarOpt.range = axisOpt?.[0]?.range || null;
|
|
35
35
|
|
|
36
|
+
this.initScrollbarRange(dir);
|
|
36
37
|
this.createScrollbarLayout(dir);
|
|
37
38
|
this.createScrollbar(dir);
|
|
38
39
|
this.createScrollEvent(dir);
|
|
@@ -40,31 +41,29 @@ const module = {
|
|
|
40
41
|
}
|
|
41
42
|
},
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
initScrollbarRange(dir) {
|
|
44
45
|
const scrollbarOpt = this.scrollbar[dir];
|
|
45
46
|
const axesType = scrollbarOpt.type;
|
|
46
47
|
|
|
47
48
|
if (scrollbarOpt.range?.length) {
|
|
48
49
|
const [min, max] = scrollbarOpt.range;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (+min < +minMax.min || +max > +minMax.max) {
|
|
62
|
-
return true;
|
|
50
|
+
let limitMin;
|
|
51
|
+
let limitMax;
|
|
52
|
+
|
|
53
|
+
if ((truthyNumber(min) && truthyNumber(max))) {
|
|
54
|
+
if (axesType === 'step') {
|
|
55
|
+
const labels = this.options.type === 'heatMap' ? this.data.labels[dir] : this.data.labels;
|
|
56
|
+
limitMin = 0;
|
|
57
|
+
limitMax = labels.length - 1;
|
|
58
|
+
} else {
|
|
59
|
+
const minMax = this.minMax[dir]?.[0];
|
|
60
|
+
limitMin = +minMax.min;
|
|
61
|
+
limitMax = +minMax.max;
|
|
63
62
|
}
|
|
63
|
+
scrollbarOpt.range[0] = +min < limitMin ? limitMin : +min;
|
|
64
|
+
scrollbarOpt.range[1] = +max > limitMax ? limitMax : +max;
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
-
return false;
|
|
68
67
|
},
|
|
69
68
|
|
|
70
69
|
/**
|
|
@@ -95,6 +94,7 @@ const module = {
|
|
|
95
94
|
const isUpdateAxesRange = !isEqual(newOpt?.[0]?.range, axisOpt?.[0]?.range);
|
|
96
95
|
if (isUpdateAxesRange || updateData) {
|
|
97
96
|
this.scrollbar[dir].range = newOpt?.[0]?.range || null;
|
|
97
|
+
this.initScrollbarRange(dir);
|
|
98
98
|
}
|
|
99
99
|
this.scrollbar[dir].use = !!newOpt?.[0].scrollbar?.use;
|
|
100
100
|
},
|
|
@@ -104,16 +104,10 @@ const module = {
|
|
|
104
104
|
*/
|
|
105
105
|
updateScrollbarPosition() {
|
|
106
106
|
if (this.scrollbar.x?.use && this.scrollbar.x?.isInit) {
|
|
107
|
-
if (this.checkValidRange('x')) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
107
|
this.setScrollbarPosition('x');
|
|
111
108
|
}
|
|
112
109
|
|
|
113
110
|
if (this.scrollbar.y?.use && this.scrollbar.y?.isInit) {
|
|
114
|
-
if (this.checkValidRange('y')) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
111
|
this.setScrollbarPosition('y');
|
|
118
112
|
}
|
|
119
113
|
},
|
|
@@ -74,8 +74,13 @@ class Scale {
|
|
|
74
74
|
|
|
75
75
|
const range = scrollbarOpt?.use ? scrollbarOpt?.range : this.range;
|
|
76
76
|
if (range?.length === 2) {
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
if (this.options.type === 'heatMap') {
|
|
78
|
+
maxValue = range[1] > +minMax.max ? +minMax.max : range[1];
|
|
79
|
+
minValue = range[0] < +minMax.min ? +minMax.min : range[0];
|
|
80
|
+
} else {
|
|
81
|
+
maxValue = range[1];
|
|
82
|
+
minValue = range[0];
|
|
83
|
+
}
|
|
79
84
|
} else {
|
|
80
85
|
maxValue = minMax.max;
|
|
81
86
|
minValue = minMax.min;
|
|
@@ -54,21 +54,24 @@
|
|
|
54
54
|
/>
|
|
55
55
|
<div
|
|
56
56
|
class="filtering-items__item"
|
|
57
|
-
@click="onClickFilteringItem(
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
@click.stop="onClickFilteringItem(
|
|
58
|
+
{
|
|
59
|
+
caption: filteringItemsByColumn[field]?.[idx].caption,
|
|
60
|
+
field: field,
|
|
61
|
+
},
|
|
62
|
+
filteringItemsByColumn[field],
|
|
60
63
|
)"
|
|
61
64
|
>
|
|
62
65
|
<span class="filtering-items__item--title">
|
|
63
|
-
{{ filteringItemsByColumn[field]?.[
|
|
66
|
+
{{ filteringItemsByColumn[field]?.[idx].caption }}
|
|
64
67
|
</span>
|
|
65
68
|
<span
|
|
66
69
|
v-if="filteringItemsByColumn[field].length < 2"
|
|
67
70
|
class="filtering-items__item--value"
|
|
68
|
-
:title="`${filteringItemsByColumn[field][
|
|
71
|
+
:title="`${filteringItemsByColumn[field][idx].value}`"
|
|
69
72
|
>
|
|
70
|
-
{{ filteringItemsByColumn[field]?.[
|
|
71
|
-
{{ filteringItemsByColumn[field]?.[
|
|
73
|
+
{{ filteringItemsByColumn[field]?.[idx].comparison }}
|
|
74
|
+
{{ filteringItemsByColumn[field]?.[idx].value }}
|
|
72
75
|
</span>
|
|
73
76
|
<span
|
|
74
77
|
v-else
|
|
@@ -108,7 +111,7 @@
|
|
|
108
111
|
/>
|
|
109
112
|
<div class="filtering-items__item">
|
|
110
113
|
<span class="filtering-items__item--title">
|
|
111
|
-
{{
|
|
114
|
+
{{ selectedFilteringColumn.caption }}
|
|
112
115
|
</span>
|
|
113
116
|
<span class="filtering-items__item--value">
|
|
114
117
|
{{ field.comparison }}
|
|
@@ -117,7 +120,11 @@
|
|
|
117
120
|
<ev-icon
|
|
118
121
|
class="filtering-items__item--remove"
|
|
119
122
|
icon="ev-icon-s-close"
|
|
120
|
-
@click="removeFiltering(
|
|
123
|
+
@click="removeFiltering(
|
|
124
|
+
{
|
|
125
|
+
field: selectedFilteringColumn.field,
|
|
126
|
+
idx,
|
|
127
|
+
})"
|
|
121
128
|
/>
|
|
122
129
|
</div>
|
|
123
130
|
</template>
|
|
@@ -318,7 +325,6 @@
|
|
|
318
325
|
}"
|
|
319
326
|
@scroll="onScroll"
|
|
320
327
|
@contextmenu="onContextMenu($event)"
|
|
321
|
-
@contextmenu.prevent="menu.show"
|
|
322
328
|
>
|
|
323
329
|
<!-- vScroll Top -->
|
|
324
330
|
<div
|
|
@@ -423,7 +429,6 @@
|
|
|
423
429
|
<span
|
|
424
430
|
class="row-contextmenu__btn"
|
|
425
431
|
@click="onContextMenu($event)"
|
|
426
|
-
@click.prevent="menu.show"
|
|
427
432
|
>
|
|
428
433
|
<slot name="contextmenuIcon"></slot>
|
|
429
434
|
</span>
|
|
@@ -433,7 +438,6 @@
|
|
|
433
438
|
icon="ev-icon-warning2"
|
|
434
439
|
class="row-contextmenu__btn"
|
|
435
440
|
@click="onContextMenu($event)"
|
|
436
|
-
@click.prevent="menu.show"
|
|
437
441
|
/>
|
|
438
442
|
</template>
|
|
439
443
|
</td>
|
|
@@ -697,6 +701,7 @@ export default {
|
|
|
697
701
|
isSorting: false,
|
|
698
702
|
sortField: '',
|
|
699
703
|
sortOrder: '',
|
|
704
|
+
sortColumn: {},
|
|
700
705
|
});
|
|
701
706
|
const contextInfo = reactive({
|
|
702
707
|
menu: null,
|
|
@@ -767,7 +772,7 @@ export default {
|
|
|
767
772
|
const {
|
|
768
773
|
onSort,
|
|
769
774
|
setSort,
|
|
770
|
-
} = sortEvent({ sortInfo, stores,
|
|
775
|
+
} = sortEvent({ sortInfo, stores, updatePagingInfo });
|
|
771
776
|
|
|
772
777
|
const {
|
|
773
778
|
onSearch,
|
|
@@ -845,7 +850,7 @@ export default {
|
|
|
845
850
|
const {
|
|
846
851
|
onRowClick,
|
|
847
852
|
onRowDblClick,
|
|
848
|
-
} = clickEvent({ selectInfo, stores
|
|
853
|
+
} = clickEvent({ selectInfo, stores });
|
|
849
854
|
|
|
850
855
|
const {
|
|
851
856
|
onDragStart,
|
|
@@ -1049,7 +1054,10 @@ export default {
|
|
|
1049
1054
|
const filteringItemsRef = ref(null);
|
|
1050
1055
|
const isShowFilteringItemsBox = ref(false);
|
|
1051
1056
|
const isShowColumnFilteringItems = ref(false);
|
|
1052
|
-
const
|
|
1057
|
+
const selectedFilteringColumn = reactive({
|
|
1058
|
+
caption: '',
|
|
1059
|
+
field: '',
|
|
1060
|
+
});
|
|
1053
1061
|
const selectedFilteringItems = ref([]);
|
|
1054
1062
|
const operatorItems = [
|
|
1055
1063
|
{ name: 'AND', value: 'and' },
|
|
@@ -1057,13 +1065,14 @@ export default {
|
|
|
1057
1065
|
];
|
|
1058
1066
|
const isExpandColumnFilteringItems = ref(false);
|
|
1059
1067
|
|
|
1060
|
-
const onClickFilteringItem = (field, filters) => {
|
|
1061
|
-
|
|
1068
|
+
const onClickFilteringItem = ({ caption, field }, filters) => {
|
|
1069
|
+
selectedFilteringColumn.caption = caption;
|
|
1070
|
+
selectedFilteringColumn.field = field;
|
|
1062
1071
|
selectedFilteringItems.value = filters;
|
|
1063
1072
|
if (filters?.length > 1) { // open filtering items box
|
|
1064
1073
|
isShowFilteringItemsBox.value = true;
|
|
1065
1074
|
const x = filteringItemsRef.value.getBoundingClientRect().left;
|
|
1066
|
-
const y = filteringItemsRef.value.getBoundingClientRect().top
|
|
1075
|
+
const y = window.pageYOffset + filteringItemsRef.value.getBoundingClientRect().top
|
|
1067
1076
|
+ filteringItemsRef.value.getBoundingClientRect().height;
|
|
1068
1077
|
filteringItemsBoxPosition.boxTop = `${y}px`;
|
|
1069
1078
|
filteringItemsBoxPosition.boxLeft = `${x}px`;
|
|
@@ -1120,7 +1129,7 @@ export default {
|
|
|
1120
1129
|
setStore([], false);
|
|
1121
1130
|
};
|
|
1122
1131
|
const removeFiltering = ({ field, idx }) => {
|
|
1123
|
-
filterInfo.filteringItemsByColumn[field]
|
|
1132
|
+
filterInfo.filteringItemsByColumn[field]?.splice(idx, 1);
|
|
1124
1133
|
if (!filterInfo.filteringItemsByColumn[field].length) {
|
|
1125
1134
|
delete filterInfo.filteringItemsByColumn[field];
|
|
1126
1135
|
}
|
|
@@ -1199,7 +1208,7 @@ export default {
|
|
|
1199
1208
|
isShowColumnFilteringItems,
|
|
1200
1209
|
operatorItems,
|
|
1201
1210
|
selectedFilteringItems,
|
|
1202
|
-
|
|
1211
|
+
selectedFilteringColumn,
|
|
1203
1212
|
filteringItemsRef,
|
|
1204
1213
|
isShowFilteringItemsBox,
|
|
1205
1214
|
...toRefs(filteringItemsBoxPosition),
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
v-model="item.value"
|
|
48
48
|
class="ev-grid-filter-setting__row--value"
|
|
49
49
|
:disabled="item.comparison === 'isEmpty' || item.comparison === 'isNotEmpty'"
|
|
50
|
+
@input="validateValue($props.column.type, item)"
|
|
50
51
|
/>
|
|
51
52
|
<div
|
|
52
53
|
class="ev-grid-filter-setting__row--button"
|
|
@@ -80,6 +81,7 @@
|
|
|
80
81
|
<script>
|
|
81
82
|
import { clickoutside } from '@/directives/clickoutside';
|
|
82
83
|
import { computed, onBeforeMount, ref, watch } from 'vue';
|
|
84
|
+
import { cloneDeep } from 'lodash-es';
|
|
83
85
|
|
|
84
86
|
export default {
|
|
85
87
|
name: 'EVGridFilterSetting',
|
|
@@ -169,6 +171,7 @@ export default {
|
|
|
169
171
|
comparison: '=',
|
|
170
172
|
operator,
|
|
171
173
|
value: '',
|
|
174
|
+
caption: filteringColumn.value.caption,
|
|
172
175
|
});
|
|
173
176
|
};
|
|
174
177
|
const removeRow = (idx) => {
|
|
@@ -199,8 +202,9 @@ export default {
|
|
|
199
202
|
() => props.isShow,
|
|
200
203
|
(isShow) => {
|
|
201
204
|
const rowList = [];
|
|
205
|
+
const items = cloneDeep(props.items);
|
|
202
206
|
if (isShow && filteringColumn.value.field) {
|
|
203
|
-
if (!
|
|
207
|
+
if (!items[filteringColumn.value.field]?.length) {
|
|
204
208
|
rowList.push({
|
|
205
209
|
comparison: '=',
|
|
206
210
|
operator: 'and',
|
|
@@ -208,7 +212,7 @@ export default {
|
|
|
208
212
|
caption: filteringColumn.value.caption,
|
|
209
213
|
});
|
|
210
214
|
} else {
|
|
211
|
-
|
|
215
|
+
items[filteringColumn.value.field].forEach((row) => {
|
|
212
216
|
rowList.push(row);
|
|
213
217
|
});
|
|
214
218
|
}
|
|
@@ -232,6 +236,12 @@ export default {
|
|
|
232
236
|
onBeforeMount(() => {
|
|
233
237
|
initWrapperDiv();
|
|
234
238
|
});
|
|
239
|
+
|
|
240
|
+
const validateValue = (type, item) => {
|
|
241
|
+
if (type === 'number' || type === 'float') {
|
|
242
|
+
item.value = item.value.trim();
|
|
243
|
+
}
|
|
244
|
+
};
|
|
235
245
|
return {
|
|
236
246
|
filteringItems,
|
|
237
247
|
isShowFilterSetting,
|
|
@@ -244,6 +254,7 @@ export default {
|
|
|
244
254
|
applyFiltering,
|
|
245
255
|
changeComparison,
|
|
246
256
|
getSelectTitle,
|
|
257
|
+
validateValue,
|
|
247
258
|
};
|
|
248
259
|
},
|
|
249
260
|
};
|
|
@@ -332,7 +332,7 @@ export const resizeEvent = (params) => {
|
|
|
332
332
|
|
|
333
333
|
export const clickEvent = (params) => {
|
|
334
334
|
const { emit } = getCurrentInstance();
|
|
335
|
-
const { selectInfo, stores
|
|
335
|
+
const { selectInfo, stores } = params;
|
|
336
336
|
const getClickedRowData = (event, row) => {
|
|
337
337
|
const tagName = event.target.tagName.toLowerCase();
|
|
338
338
|
let cellInfo = {};
|
|
@@ -355,7 +355,7 @@ export const clickEvent = (params) => {
|
|
|
355
355
|
* @param {object} event - 이벤트 객체
|
|
356
356
|
* @param {array} row - row 데이터
|
|
357
357
|
*/
|
|
358
|
-
let
|
|
358
|
+
let clickTimer = null;
|
|
359
359
|
let lastIndex = -1;
|
|
360
360
|
const onRowClick = (event, row, isRight) => {
|
|
361
361
|
if (event.target.parentElement.classList?.contains('row-checkbox-input')) {
|
|
@@ -395,8 +395,10 @@ export const clickEvent = (params) => {
|
|
|
395
395
|
}
|
|
396
396
|
};
|
|
397
397
|
|
|
398
|
-
|
|
399
|
-
|
|
398
|
+
if (clickTimer) {
|
|
399
|
+
clearTimeout(clickTimer);
|
|
400
|
+
}
|
|
401
|
+
clickTimer = setTimeout(() => {
|
|
400
402
|
if (selectInfo.useSelect) {
|
|
401
403
|
const rowData = row[ROW_DATA_INDEX];
|
|
402
404
|
const selected = row[ROW_SELECT_INDEX];
|
|
@@ -423,7 +425,6 @@ export const clickEvent = (params) => {
|
|
|
423
425
|
lastIndex = row[ROW_INDEX];
|
|
424
426
|
emit('update:selected', selectInfo.selectedRow);
|
|
425
427
|
emit('click-row', getClickedRowData(event, row));
|
|
426
|
-
setContextMenu();
|
|
427
428
|
}
|
|
428
429
|
}, 100);
|
|
429
430
|
return true;
|
|
@@ -435,7 +436,9 @@ export const clickEvent = (params) => {
|
|
|
435
436
|
* @param {array} row - row 데이터
|
|
436
437
|
*/
|
|
437
438
|
const onRowDblClick = (event, row) => {
|
|
438
|
-
|
|
439
|
+
if (clickTimer) {
|
|
440
|
+
clearTimeout(clickTimer);
|
|
441
|
+
}
|
|
439
442
|
emit('dblclick-row', getClickedRowData(event, row));
|
|
440
443
|
};
|
|
441
444
|
return { onRowClick, onRowDblClick };
|
|
@@ -523,7 +526,7 @@ export const checkEvent = (params) => {
|
|
|
523
526
|
};
|
|
524
527
|
|
|
525
528
|
export const sortEvent = (params) => {
|
|
526
|
-
const { sortInfo, stores,
|
|
529
|
+
const { sortInfo, stores, updatePagingInfo } = params;
|
|
527
530
|
function OrderQueue() {
|
|
528
531
|
this.orders = ['asc', 'desc', 'init'];
|
|
529
532
|
this.dequeue = () => this.orders.shift();
|
|
@@ -539,6 +542,7 @@ export const sortEvent = (params) => {
|
|
|
539
542
|
const onSort = (column, sortOrder) => {
|
|
540
543
|
const sortable = column.sortable === undefined ? true : column.sortable;
|
|
541
544
|
if (sortable) {
|
|
545
|
+
sortInfo.sortColumn = column;
|
|
542
546
|
if (sortInfo.sortField !== column?.field) {
|
|
543
547
|
order.orders = ['asc', 'desc', 'init'];
|
|
544
548
|
sortInfo.sortField = column?.field;
|
|
@@ -574,8 +578,8 @@ export const sortEvent = (params) => {
|
|
|
574
578
|
});
|
|
575
579
|
return;
|
|
576
580
|
}
|
|
577
|
-
const index =
|
|
578
|
-
const type =
|
|
581
|
+
const index = sortInfo.sortColumn.index;
|
|
582
|
+
const type = sortInfo.sortColumn.type || 'string';
|
|
579
583
|
const sortFn = sortInfo.sortOrder === 'desc' ? setDesc : setAsc;
|
|
580
584
|
const numberSortFn = sortInfo.sortOrder === 'desc' ? numberSetDesc : numberSetAsc;
|
|
581
585
|
const getColumnValue = (a, b) => {
|
|
@@ -641,25 +645,26 @@ export const filterEvent = (params) => {
|
|
|
641
645
|
/**
|
|
642
646
|
* 전달받은 문자열 내 해당 키워드가 존재하는지 확인한다.
|
|
643
647
|
*
|
|
644
|
-
* @param {string}
|
|
645
|
-
* @param {string}
|
|
648
|
+
* @param {string} conditionValue - 검색 키워드
|
|
649
|
+
* @param {string} value - 기준 문자열
|
|
650
|
+
* @param {string} pos - 시작, 끝나는 문자열
|
|
646
651
|
* @returns {boolean} 문자열 내 키워드 존재 유무
|
|
647
652
|
*/
|
|
648
|
-
const findLike = (
|
|
649
|
-
if (typeof
|
|
653
|
+
const findLike = (conditionValue, value, pos) => {
|
|
654
|
+
if (typeof conditionValue !== 'string' || value === null) {
|
|
650
655
|
return false;
|
|
651
656
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
let
|
|
657
|
+
const baseValueLower = value.toLowerCase();
|
|
658
|
+
const conditionValueLower = conditionValue.toLowerCase();
|
|
659
|
+
let result = baseValueLower.includes(conditionValueLower);
|
|
655
660
|
if (pos) {
|
|
656
661
|
if (pos === 'start') {
|
|
657
|
-
|
|
662
|
+
result = baseValueLower.startsWith(conditionValueLower);
|
|
658
663
|
} else if (pos === 'end') {
|
|
659
|
-
|
|
664
|
+
result = baseValueLower.endsWith(conditionValueLower);
|
|
660
665
|
}
|
|
661
666
|
}
|
|
662
|
-
return
|
|
667
|
+
return result;
|
|
663
668
|
};
|
|
664
669
|
/**
|
|
665
670
|
* 필터 조건에 따라 문자열을 확인한다.
|
|
@@ -681,13 +686,13 @@ export const filterEvent = (params) => {
|
|
|
681
686
|
} else if (comparison === '!=') {
|
|
682
687
|
result = conditionValue.toLowerCase() !== value.toLowerCase();
|
|
683
688
|
} else if (comparison === '%s%') {
|
|
684
|
-
result = findLike(
|
|
689
|
+
result = findLike(conditionValue, value);
|
|
685
690
|
} else if (comparison === 'notLike') {
|
|
686
|
-
result = !findLike(
|
|
691
|
+
result = !findLike(conditionValue, value);
|
|
687
692
|
} else if (comparison === 's%') {
|
|
688
|
-
result = findLike(
|
|
693
|
+
result = findLike(conditionValue, value, 'start');
|
|
689
694
|
} else if (comparison === '%s') {
|
|
690
|
-
result = findLike(
|
|
695
|
+
result = findLike(conditionValue, value, 'end');
|
|
691
696
|
} else if (comparison === 'isEmpty') {
|
|
692
697
|
result = value === undefined || value === null || value === '';
|
|
693
698
|
} else if (comparison === 'isNotEmpty') {
|
|
@@ -765,33 +770,36 @@ export const filterEvent = (params) => {
|
|
|
765
770
|
* 전체 데이터에서 설정된 필터 적용 후 결과를 filterStore 에 저장한다.
|
|
766
771
|
*/
|
|
767
772
|
const setFilter = () => {
|
|
768
|
-
let filterStore = [];
|
|
769
|
-
let isApply = false;
|
|
770
|
-
|
|
771
773
|
const filteringItemsByColumn = filterInfo.filteringItemsByColumn;
|
|
772
774
|
const fields = Object.keys(filteringItemsByColumn);
|
|
773
775
|
const originStore = stores.originStore;
|
|
776
|
+
let filterStore = [];
|
|
774
777
|
let filteredOnce = false;
|
|
778
|
+
|
|
775
779
|
fields.forEach((field) => {
|
|
776
780
|
const filters = filteringItemsByColumn[field];
|
|
777
781
|
const index = getColumnIndex(field);
|
|
778
782
|
const columnType = props.columns[index].type;
|
|
779
783
|
|
|
780
|
-
filters.forEach((
|
|
781
|
-
isApply = true;
|
|
784
|
+
filters.forEach((item, ix) => {
|
|
782
785
|
if (!filterStore.length && !filteredOnce) {
|
|
783
786
|
filterStore = getFilteringData(originStore, columnType, {
|
|
784
|
-
...
|
|
787
|
+
...item,
|
|
785
788
|
index,
|
|
786
789
|
});
|
|
787
|
-
} else if (
|
|
790
|
+
} else if (ix === 0 && filterInfo.columnOperator === 'or') {
|
|
788
791
|
filterStore.push(...getFilteringData(originStore, columnType, {
|
|
789
|
-
...
|
|
792
|
+
...item,
|
|
793
|
+
index,
|
|
794
|
+
}));
|
|
795
|
+
} else if (item.operator === 'or') {
|
|
796
|
+
filterStore.push(...getFilteringData(originStore, columnType, {
|
|
797
|
+
...item,
|
|
790
798
|
index,
|
|
791
799
|
}));
|
|
792
800
|
} else {
|
|
793
801
|
filterStore = getFilteringData(filterStore, columnType, {
|
|
794
|
-
...
|
|
802
|
+
...item,
|
|
795
803
|
index,
|
|
796
804
|
});
|
|
797
805
|
}
|
|
@@ -799,19 +807,19 @@ export const filterEvent = (params) => {
|
|
|
799
807
|
});
|
|
800
808
|
});
|
|
801
809
|
|
|
802
|
-
if (!
|
|
810
|
+
if (!filteredOnce) {
|
|
803
811
|
stores.filterStore = originStore;
|
|
804
812
|
} else {
|
|
805
813
|
stores.filterStore = uniqBy(filterStore, JSON.stringify);
|
|
806
814
|
}
|
|
807
815
|
};
|
|
808
816
|
|
|
809
|
-
let
|
|
817
|
+
let searchTimer = null;
|
|
810
818
|
const onSearch = (searchWord) => {
|
|
811
|
-
if (
|
|
812
|
-
clearTimeout(
|
|
819
|
+
if (searchTimer) {
|
|
820
|
+
clearTimeout(searchTimer);
|
|
813
821
|
}
|
|
814
|
-
|
|
822
|
+
searchTimer = setTimeout(() => {
|
|
815
823
|
filterInfo.isSearch = false;
|
|
816
824
|
filterInfo.searchWord = searchWord;
|
|
817
825
|
if (searchWord) {
|
|
@@ -880,35 +888,65 @@ export const contextMenuEvent = (params) => {
|
|
|
880
888
|
/**
|
|
881
889
|
* 컨텍스트 메뉴를 설정한다.
|
|
882
890
|
*
|
|
883
|
-
* @param {
|
|
891
|
+
* @param {object} event - 이벤트 객체
|
|
884
892
|
*/
|
|
885
|
-
|
|
893
|
+
let contextmenuTimer = null;
|
|
894
|
+
const setContextMenu = (e) => {
|
|
895
|
+
if (contextmenuTimer) {
|
|
896
|
+
clearTimeout(contextmenuTimer);
|
|
897
|
+
}
|
|
886
898
|
const menuItems = [];
|
|
899
|
+
contextmenuTimer = setTimeout(() => {
|
|
900
|
+
if (contextInfo.customContextMenu.length) {
|
|
901
|
+
const customItems = contextInfo.customContextMenu.map(
|
|
902
|
+
(item) => {
|
|
903
|
+
const menuItem = item;
|
|
904
|
+
if (menuItem.validate) {
|
|
905
|
+
menuItem.disabled = !menuItem.validate(menuItem.itemId, selectInfo.selectedRow);
|
|
906
|
+
}
|
|
887
907
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
(item) => {
|
|
891
|
-
const menuItem = item;
|
|
892
|
-
if (menuItem.validate) {
|
|
893
|
-
menuItem.disabled = !menuItem.validate(menuItem.itemId, selectInfo.selectedRow);
|
|
894
|
-
}
|
|
908
|
+
menuItem.selectedRow = selectInfo.selectedRow ?? [];
|
|
909
|
+
menuItem.contextmenuInfo = selectInfo.contextmenuInfo ?? [];
|
|
895
910
|
|
|
896
|
-
|
|
897
|
-
|
|
911
|
+
return menuItem;
|
|
912
|
+
});
|
|
898
913
|
|
|
899
|
-
|
|
900
|
-
|
|
914
|
+
menuItems.push(...customItems);
|
|
915
|
+
}
|
|
901
916
|
|
|
902
|
-
menuItems
|
|
917
|
+
contextInfo.contextMenuItems = menuItems;
|
|
918
|
+
contextInfo.menu.show(e);
|
|
919
|
+
}, 200);
|
|
920
|
+
};
|
|
921
|
+
/**
|
|
922
|
+
* 마우스 우클릭 이벤트를 처리한다.
|
|
923
|
+
*
|
|
924
|
+
* @param {object} event - 이벤트 객체
|
|
925
|
+
*/
|
|
926
|
+
const onContextMenu = (e) => {
|
|
927
|
+
e.preventDefault();
|
|
928
|
+
const target = e.target;
|
|
929
|
+
const rowIndex = target.closest('.row')?.dataset?.index;
|
|
930
|
+
let clickedRow = null;
|
|
931
|
+
if (rowIndex) {
|
|
932
|
+
clickedRow = stores.viewStore.find(row => row[ROW_INDEX] === +rowIndex)?.[ROW_DATA_INDEX];
|
|
933
|
+
}
|
|
934
|
+
if (clickedRow) {
|
|
935
|
+
selectInfo.contextmenuInfo = [clickedRow];
|
|
936
|
+
setContextMenu(e);
|
|
903
937
|
}
|
|
904
|
-
|
|
905
|
-
contextInfo.contextMenuItems = menuItems;
|
|
906
938
|
};
|
|
939
|
+
/**
|
|
940
|
+
* 컬럼 기능을 수행하는 Contextmenu 를 생성한다.
|
|
941
|
+
*
|
|
942
|
+
* @param {object} event - 이벤트 객체
|
|
943
|
+
* @param {object} column - 컬럼 정보
|
|
944
|
+
*/
|
|
907
945
|
const onColumnContextMenu = (event, column) => {
|
|
908
946
|
if (event.target.className === 'column-name') {
|
|
909
947
|
const sortable = column.sortable === undefined ? true : column.sortable;
|
|
910
948
|
const filterable = filterInfo.isFiltering
|
|
911
|
-
|
|
949
|
+
&& column.filterable === undefined ? true : column.filterable;
|
|
912
950
|
contextInfo.columnMenuItems = [
|
|
913
951
|
{
|
|
914
952
|
text: 'Ascending',
|
|
@@ -952,23 +990,6 @@ export const contextMenuEvent = (params) => {
|
|
|
952
990
|
];
|
|
953
991
|
}
|
|
954
992
|
};
|
|
955
|
-
/**
|
|
956
|
-
* 마우스 우클릭 이벤트를 처리한다.
|
|
957
|
-
*
|
|
958
|
-
* @param {object} event - 이벤트 객체
|
|
959
|
-
*/
|
|
960
|
-
const onContextMenu = (event) => {
|
|
961
|
-
const target = event.target;
|
|
962
|
-
const rowIndex = target.closest('.row')?.dataset?.index;
|
|
963
|
-
let clickedRow = null;
|
|
964
|
-
if (rowIndex) {
|
|
965
|
-
clickedRow = stores.viewStore.find(row => row[ROW_INDEX] === +rowIndex)?.[ROW_DATA_INDEX];
|
|
966
|
-
}
|
|
967
|
-
if (clickedRow) {
|
|
968
|
-
selectInfo.contextmenuInfo = [clickedRow];
|
|
969
|
-
// setContextMenu();
|
|
970
|
-
}
|
|
971
|
-
};
|
|
972
993
|
return {
|
|
973
994
|
setContextMenu,
|
|
974
995
|
onContextMenu,
|