evui 3.2.0 → 3.2.1
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 +308 -290
- package/dist/evui.common.js.map +1 -1
- package/dist/evui.umd.js +308 -290
- 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/grid/Grid.vue +47 -75
- package/src/components/grid/uses.js +110 -72
- package/src/components/treeGrid/TreeGrid.vue +7 -3
package/package.json
CHANGED
|
@@ -251,7 +251,7 @@
|
|
|
251
251
|
</template>
|
|
252
252
|
|
|
253
253
|
<script>
|
|
254
|
-
import { reactive, toRefs, computed, watch, onMounted } from 'vue';
|
|
254
|
+
import { reactive, toRefs, computed, watch, onMounted, onActivated } from 'vue';
|
|
255
255
|
import FilterWindow from './grid.filter.window';
|
|
256
256
|
import Toolbar from './grid.toolbar';
|
|
257
257
|
import {
|
|
@@ -334,13 +334,14 @@ export default {
|
|
|
334
334
|
filterList: {},
|
|
335
335
|
isFiltering: computed(() =>
|
|
336
336
|
(props.option.useFilter === undefined ? true : props.option.useFilter)),
|
|
337
|
-
isSearch: false,
|
|
338
337
|
setFiltering: false,
|
|
339
338
|
showFilterWindow: false,
|
|
340
339
|
currentFilter: {
|
|
341
340
|
column: {},
|
|
342
341
|
items: [],
|
|
343
342
|
},
|
|
343
|
+
isSearch: false,
|
|
344
|
+
searchWord: '',
|
|
344
345
|
});
|
|
345
346
|
const stores = reactive({
|
|
346
347
|
viewStore: [],
|
|
@@ -428,7 +429,15 @@ export default {
|
|
|
428
429
|
onCloseFilterWindow,
|
|
429
430
|
onApplyFilter,
|
|
430
431
|
setFilter,
|
|
431
|
-
|
|
432
|
+
onSearch,
|
|
433
|
+
} = filterEvent({
|
|
434
|
+
filterInfo,
|
|
435
|
+
stores,
|
|
436
|
+
checkInfo,
|
|
437
|
+
getColumnIndex,
|
|
438
|
+
getConvertValue,
|
|
439
|
+
updateVScroll,
|
|
440
|
+
});
|
|
432
441
|
|
|
433
442
|
const {
|
|
434
443
|
setStore,
|
|
@@ -461,9 +470,17 @@ export default {
|
|
|
461
470
|
calculatedColumn();
|
|
462
471
|
setStore(props.rows);
|
|
463
472
|
});
|
|
473
|
+
onActivated(() => {
|
|
474
|
+
updateVScroll();
|
|
475
|
+
});
|
|
464
476
|
const ROW_INDEX = 0;
|
|
465
477
|
const ROW_CHECK_INDEX = 1;
|
|
466
478
|
const ROW_DATA_INDEX = 2;
|
|
479
|
+
const clearCheckInfo = () => {
|
|
480
|
+
checkInfo.checkedRows = [];
|
|
481
|
+
checkInfo.checkedIndex.clear();
|
|
482
|
+
checkInfo.isHeaderChecked = false;
|
|
483
|
+
};
|
|
467
484
|
watch(
|
|
468
485
|
() => props.columns,
|
|
469
486
|
() => {
|
|
@@ -494,24 +511,30 @@ export default {
|
|
|
494
511
|
() => props.rows,
|
|
495
512
|
(value) => {
|
|
496
513
|
setStore(value);
|
|
514
|
+
if (filterInfo.isSearch) {
|
|
515
|
+
onSearch(filterInfo.searchWord);
|
|
516
|
+
}
|
|
497
517
|
},
|
|
498
518
|
);
|
|
499
519
|
watch(
|
|
500
520
|
() => props.checked,
|
|
501
|
-
(
|
|
502
|
-
checkInfo.checkedRows =
|
|
521
|
+
(checkedList) => {
|
|
522
|
+
checkInfo.checkedRows = checkedList;
|
|
503
523
|
checkInfo.isHeaderChecked = false;
|
|
504
|
-
|
|
505
|
-
if (
|
|
506
|
-
store = stores.
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
524
|
+
checkInfo.checkedIndex.clear();
|
|
525
|
+
if (checkedList.length) {
|
|
526
|
+
const store = stores.store;
|
|
527
|
+
store.forEach((row) => {
|
|
528
|
+
row[ROW_CHECK_INDEX] = checkedList.includes(row[ROW_DATA_INDEX]);
|
|
529
|
+
if (row[ROW_CHECK_INDEX]) {
|
|
530
|
+
checkInfo.checkedIndex.add(row[ROW_INDEX]);
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
if (checkedList.length === store.length) {
|
|
534
|
+
checkInfo.isHeaderChecked = true;
|
|
535
|
+
}
|
|
514
536
|
}
|
|
537
|
+
updateVScroll();
|
|
515
538
|
},
|
|
516
539
|
);
|
|
517
540
|
watch(
|
|
@@ -523,8 +546,15 @@ export default {
|
|
|
523
546
|
watch(
|
|
524
547
|
() => checkInfo.useCheckbox.mode,
|
|
525
548
|
() => {
|
|
526
|
-
|
|
527
|
-
|
|
549
|
+
clearCheckInfo();
|
|
550
|
+
},
|
|
551
|
+
);
|
|
552
|
+
watch(
|
|
553
|
+
() => props.checked.length,
|
|
554
|
+
(checkedSize) => {
|
|
555
|
+
if (!checkedSize) {
|
|
556
|
+
clearCheckInfo();
|
|
557
|
+
}
|
|
528
558
|
},
|
|
529
559
|
);
|
|
530
560
|
watch(
|
|
@@ -553,64 +583,6 @@ export default {
|
|
|
553
583
|
setStore([], false);
|
|
554
584
|
},
|
|
555
585
|
);
|
|
556
|
-
let timer = null;
|
|
557
|
-
const onSearch = (searchWord) => {
|
|
558
|
-
if (timer) {
|
|
559
|
-
clearTimeout(timer);
|
|
560
|
-
}
|
|
561
|
-
timer = setTimeout(() => {
|
|
562
|
-
filterInfo.isSearch = false;
|
|
563
|
-
if (searchWord) {
|
|
564
|
-
const filterStores = stores.store.filter((row) => {
|
|
565
|
-
let isShow = false;
|
|
566
|
-
for (let ix = 0; ix < stores.orderedColumns.length; ix++) {
|
|
567
|
-
const column = stores.orderedColumns[ix] || {};
|
|
568
|
-
let columnValue = row[ROW_DATA_INDEX][ix];
|
|
569
|
-
let columnType = column.type;
|
|
570
|
-
if (columnValue) {
|
|
571
|
-
if (typeof columnValue === 'object') {
|
|
572
|
-
columnValue = columnValue[column.field];
|
|
573
|
-
}
|
|
574
|
-
if (!column.hide && (column?.searchable === undefined || column?.searchable)) {
|
|
575
|
-
if (!columnType) {
|
|
576
|
-
columnType = 'string';
|
|
577
|
-
}
|
|
578
|
-
columnValue = getConvertValue(columnType, columnValue).toString();
|
|
579
|
-
isShow = columnValue.toLowerCase().includes(searchWord.toString().toLowerCase());
|
|
580
|
-
if (isShow) {
|
|
581
|
-
break;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
return isShow;
|
|
587
|
-
});
|
|
588
|
-
filterInfo.isSearch = true;
|
|
589
|
-
stores.searchStore = JSON.parse(JSON.stringify(filterStores));
|
|
590
|
-
} else {
|
|
591
|
-
filterInfo.isSearch = false;
|
|
592
|
-
}
|
|
593
|
-
let store = stores.originStore;
|
|
594
|
-
let checkSize = checkInfo.checkedRows.length;
|
|
595
|
-
for (let ix = 0; ix < store.length; ix++) {
|
|
596
|
-
if (checkInfo.checkedIndex.has(store[ix][ROW_INDEX])) {
|
|
597
|
-
store[ix][ROW_CHECK_INDEX] = true;
|
|
598
|
-
} else {
|
|
599
|
-
store[ix][ROW_CHECK_INDEX] = false;
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
if (filterInfo.isSearch && stores.searchStore) {
|
|
603
|
-
store = stores.searchStore;
|
|
604
|
-
checkSize = checkInfo.checkedIndex.size;
|
|
605
|
-
}
|
|
606
|
-
if (store.length && checkSize >= store.length) {
|
|
607
|
-
checkInfo.isHeaderChecked = true;
|
|
608
|
-
} else {
|
|
609
|
-
checkInfo.isHeaderChecked = false;
|
|
610
|
-
}
|
|
611
|
-
setStore([], false);
|
|
612
|
-
}, 500);
|
|
613
|
-
};
|
|
614
586
|
const isFilterButton = field => filterInfo.isFiltering && field !== 'db-icon' && field !== 'user-icon';
|
|
615
587
|
return {
|
|
616
588
|
showHeader,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCurrentInstance
|
|
1
|
+
import { getCurrentInstance } from 'vue';
|
|
2
2
|
import { isEqual, uniqBy } from 'lodash-es';
|
|
3
3
|
import { numberWithComma } from '@/common/utils';
|
|
4
4
|
|
|
@@ -368,7 +368,7 @@ export const clickEvent = (params) => {
|
|
|
368
368
|
};
|
|
369
369
|
|
|
370
370
|
export const checkEvent = (params) => {
|
|
371
|
-
const { checkInfo, stores
|
|
371
|
+
const { checkInfo, stores } = params;
|
|
372
372
|
const { emit } = getCurrentInstance();
|
|
373
373
|
/**
|
|
374
374
|
* row에 대한 체크 상태를 해제한다.
|
|
@@ -404,20 +404,12 @@ export const checkEvent = (params) => {
|
|
|
404
404
|
}
|
|
405
405
|
checkInfo.checkedIndex.add(row[ROW_INDEX]);
|
|
406
406
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if (
|
|
410
|
-
store = stores.searchStore;
|
|
411
|
-
checkSize = checkInfo.checkedIndex.size;
|
|
412
|
-
}
|
|
413
|
-
if (checkSize >= store.length) {
|
|
407
|
+
const store = stores.store;
|
|
408
|
+
const isAllChecked = store.every(d => d[ROW_CHECK_INDEX]);
|
|
409
|
+
if (store.length && isAllChecked) {
|
|
414
410
|
checkInfo.isHeaderChecked = true;
|
|
415
411
|
}
|
|
416
412
|
} else {
|
|
417
|
-
if (checkInfo.isHeaderChecked) {
|
|
418
|
-
checkInfo.isHeaderChecked = false;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
413
|
if (checkInfo.useCheckbox.mode === 'single') {
|
|
422
414
|
checkInfo.checkedRows = [];
|
|
423
415
|
checkInfo.checkedIndex.clear();
|
|
@@ -425,8 +417,8 @@ export const checkEvent = (params) => {
|
|
|
425
417
|
checkInfo.checkedRows.splice(checkInfo.checkedRows.indexOf(row[ROW_DATA_INDEX]), 1);
|
|
426
418
|
checkInfo.checkedIndex.delete(row[ROW_INDEX]);
|
|
427
419
|
}
|
|
420
|
+
checkInfo.isHeaderChecked = false;
|
|
428
421
|
}
|
|
429
|
-
|
|
430
422
|
checkInfo.prevCheckedRow = row.slice();
|
|
431
423
|
emit('update:checked', checkInfo.checkedRows);
|
|
432
424
|
emit('check-row', event, row[ROW_INDEX], row[ROW_DATA_INDEX]);
|
|
@@ -437,28 +429,24 @@ export const checkEvent = (params) => {
|
|
|
437
429
|
* @param {object} event - 이벤트 객체
|
|
438
430
|
*/
|
|
439
431
|
const onCheckAll = (event) => {
|
|
440
|
-
const
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
checked.push(item[ROW_DATA_INDEX]);
|
|
451
|
-
checkInfo.checkedIndex.add(item[ROW_INDEX]);
|
|
432
|
+
const isHeaderChecked = checkInfo.isHeaderChecked;
|
|
433
|
+
const store = stores.store;
|
|
434
|
+
store.forEach((row) => {
|
|
435
|
+
if (isHeaderChecked) {
|
|
436
|
+
if (!checkInfo.checkedRows.includes(row[ROW_DATA_INDEX])) {
|
|
437
|
+
checkInfo.checkedRows.push(row[ROW_DATA_INDEX]);
|
|
438
|
+
}
|
|
439
|
+
if (!checkInfo.checkedIndex.has(row[ROW_INDEX])) {
|
|
440
|
+
checkInfo.checkedIndex.add(row[ROW_INDEX]);
|
|
441
|
+
}
|
|
452
442
|
} else {
|
|
453
|
-
checkInfo.
|
|
443
|
+
checkInfo.checkedRows.splice(checkInfo.checkedRows.indexOf(row[ROW_DATA_INDEX]), 1);
|
|
444
|
+
checkInfo.checkedIndex.delete(row[ROW_INDEX]);
|
|
454
445
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
checkInfo.checkedRows = checked;
|
|
460
|
-
emit('update:checked', checked);
|
|
461
|
-
emit('check-all', event, checked);
|
|
446
|
+
row[ROW_CHECK_INDEX] = isHeaderChecked;
|
|
447
|
+
});
|
|
448
|
+
emit('update:checked', checkInfo.checkedRows);
|
|
449
|
+
emit('check-all', event, checkInfo.checkedRows);
|
|
462
450
|
};
|
|
463
451
|
return { onCheck, onCheckAll };
|
|
464
452
|
};
|
|
@@ -530,7 +518,14 @@ export const sortEvent = (params) => {
|
|
|
530
518
|
|
|
531
519
|
export const filterEvent = (params) => {
|
|
532
520
|
const { props } = getCurrentInstance();
|
|
533
|
-
const {
|
|
521
|
+
const {
|
|
522
|
+
filterInfo,
|
|
523
|
+
stores,
|
|
524
|
+
checkInfo,
|
|
525
|
+
getColumnIndex,
|
|
526
|
+
getConvertValue,
|
|
527
|
+
updateVScroll,
|
|
528
|
+
} = params;
|
|
534
529
|
/**
|
|
535
530
|
* 해당 컬럼에 대한 필터 팝업을 보여준다.
|
|
536
531
|
*
|
|
@@ -708,7 +703,57 @@ export const filterEvent = (params) => {
|
|
|
708
703
|
stores.filterStore = uniqBy(filterStore, JSON.stringify);
|
|
709
704
|
}
|
|
710
705
|
};
|
|
711
|
-
|
|
706
|
+
let timer = null;
|
|
707
|
+
const onSearch = (searchWord) => {
|
|
708
|
+
if (timer) {
|
|
709
|
+
clearTimeout(timer);
|
|
710
|
+
}
|
|
711
|
+
timer = setTimeout(() => {
|
|
712
|
+
filterInfo.isSearch = false;
|
|
713
|
+
filterInfo.searchWord = searchWord;
|
|
714
|
+
if (searchWord) {
|
|
715
|
+
stores.searchStore = stores.store.filter((row) => {
|
|
716
|
+
let isShow = false;
|
|
717
|
+
for (let ix = 0; ix < stores.orderedColumns.length; ix++) {
|
|
718
|
+
const column = stores.orderedColumns[ix] || {};
|
|
719
|
+
let columnValue = row[ROW_DATA_INDEX][ix];
|
|
720
|
+
const columnType = column.type || 'string';
|
|
721
|
+
if (columnValue) {
|
|
722
|
+
if (typeof columnValue === 'object') {
|
|
723
|
+
columnValue = columnValue[column.field];
|
|
724
|
+
}
|
|
725
|
+
if (!column.hide && (column?.searchable === undefined || column?.searchable)) {
|
|
726
|
+
columnValue = getConvertValue(columnType, columnValue).toString();
|
|
727
|
+
isShow = columnValue.toLowerCase().includes(searchWord.toString().toLowerCase());
|
|
728
|
+
if (isShow) {
|
|
729
|
+
break;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
return isShow;
|
|
735
|
+
});
|
|
736
|
+
filterInfo.isSearch = true;
|
|
737
|
+
}
|
|
738
|
+
const store = stores.store;
|
|
739
|
+
let checkedCount = 0;
|
|
740
|
+
for (let ix = 0; ix < store.length; ix++) {
|
|
741
|
+
if (checkInfo.checkedIndex.has(store[ix][ROW_INDEX])) {
|
|
742
|
+
store[ix][ROW_CHECK_INDEX] = true;
|
|
743
|
+
checkedCount += 1;
|
|
744
|
+
} else {
|
|
745
|
+
store[ix][ROW_CHECK_INDEX] = false;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
if (store.length && store.length === checkedCount) {
|
|
749
|
+
checkInfo.isHeaderChecked = true;
|
|
750
|
+
} else {
|
|
751
|
+
checkInfo.isHeaderChecked = false;
|
|
752
|
+
}
|
|
753
|
+
updateVScroll();
|
|
754
|
+
}, 500);
|
|
755
|
+
};
|
|
756
|
+
return { onClickFilter, onCloseFilterWindow, onApplyFilter, setFilter, onSearch };
|
|
712
757
|
};
|
|
713
758
|
|
|
714
759
|
export const contextMenuEvent = (params) => {
|
|
@@ -797,47 +842,40 @@ export const storeEvent = (params) => {
|
|
|
797
842
|
* 전달된 데이터를 내부 store 및 속성에 저장한다.
|
|
798
843
|
*
|
|
799
844
|
* @param {array} value - row 데이터
|
|
800
|
-
* @param {boolean}
|
|
845
|
+
* @param {boolean} isMakeIndex - 인덱스 생성 유무
|
|
801
846
|
*/
|
|
802
|
-
const setStore = (value,
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
if (!checked) {
|
|
813
|
-
hasUnChecked = true;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
if (!selected && isEqual(selectInfo.selectedRow, value[ix])) {
|
|
817
|
-
selectInfo.selectedRow = value[ix];
|
|
818
|
-
selected = true;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
store.push([ix, checked, value[ix]]);
|
|
847
|
+
const setStore = (value, isMakeIndex = true) => {
|
|
848
|
+
const store = [];
|
|
849
|
+
let checked;
|
|
850
|
+
let selected = false;
|
|
851
|
+
if (isMakeIndex) {
|
|
852
|
+
let hasUnChecked = false;
|
|
853
|
+
for (let ix = 0; ix < value.length; ix++) {
|
|
854
|
+
checked = props.checked.includes(value[ix]);
|
|
855
|
+
if (!checked) {
|
|
856
|
+
hasUnChecked = true;
|
|
822
857
|
}
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
858
|
+
if (!selected && isEqual(selectInfo.selectedRow, value[ix])) {
|
|
859
|
+
selectInfo.selectedRow = value[ix];
|
|
860
|
+
selected = true;
|
|
826
861
|
}
|
|
827
|
-
|
|
828
|
-
checkInfo.isHeaderChecked = value.length > 0 ? !hasUnChecked : false;
|
|
829
|
-
stores.originStore = store;
|
|
862
|
+
store.push([ix, checked, value[ix]]);
|
|
830
863
|
}
|
|
831
|
-
if (
|
|
832
|
-
|
|
864
|
+
if (!selected) {
|
|
865
|
+
selectInfo.selectedRow = [];
|
|
833
866
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
867
|
+
checkInfo.isHeaderChecked = value.length > 0 ? !hasUnChecked : false;
|
|
868
|
+
stores.originStore = store;
|
|
869
|
+
}
|
|
870
|
+
if (filterInfo.isFiltering) {
|
|
871
|
+
setFilter();
|
|
872
|
+
}
|
|
873
|
+
if (sortInfo.sortField) {
|
|
874
|
+
setSort();
|
|
875
|
+
}
|
|
876
|
+
if (elementInfo.body?.clientHeight) {
|
|
877
|
+
updateVScroll();
|
|
878
|
+
}
|
|
841
879
|
};
|
|
842
880
|
/**
|
|
843
881
|
* 컴포넌트의 변경 데이터를 store에 업데이트한다.
|
|
@@ -162,7 +162,7 @@
|
|
|
162
162
|
</template>
|
|
163
163
|
|
|
164
164
|
<script>
|
|
165
|
-
import { reactive, toRefs, computed, watch } from 'vue';
|
|
165
|
+
import { reactive, toRefs, computed, watch, onMounted, onActivated } from 'vue';
|
|
166
166
|
import treeGridNode from './TreeGridNode';
|
|
167
167
|
import Toolbar from './treeGrid.toolbar';
|
|
168
168
|
import {
|
|
@@ -333,6 +333,12 @@ export default {
|
|
|
333
333
|
onSearch,
|
|
334
334
|
} = filterEvent({ checkInfo, stores, getConvertValue, calculatedColumn, updateVScroll });
|
|
335
335
|
|
|
336
|
+
onMounted(() => {
|
|
337
|
+
stores.treeStore = setTreeNodeStore();
|
|
338
|
+
});
|
|
339
|
+
onActivated(() => {
|
|
340
|
+
updateVScroll();
|
|
341
|
+
});
|
|
336
342
|
watch(
|
|
337
343
|
() => props.checked,
|
|
338
344
|
(value) => {
|
|
@@ -362,8 +368,6 @@ export default {
|
|
|
362
368
|
checkInfo.isHeaderChecked = false;
|
|
363
369
|
},
|
|
364
370
|
);
|
|
365
|
-
stores.treeStore = setTreeNodeStore();
|
|
366
|
-
|
|
367
371
|
watch(
|
|
368
372
|
() => props.rows,
|
|
369
373
|
(newData) => {
|