evui 3.1.58 → 3.2.3

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.
@@ -1,4 +1,4 @@
1
- import { getCurrentInstance, nextTick } from 'vue';
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, filterInfo } = params;
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
- let store = stores.originStore;
408
- let checkSize = checkInfo.checkedRows.length;
409
- if (filterInfo.isSearch && stores.searchStore) {
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 status = checkInfo.isHeaderChecked;
441
- const checked = [];
442
- let item;
443
- let store = stores.originStore;
444
- if (filterInfo.isSearch && stores.searchStore) {
445
- store = stores.searchStore;
446
- }
447
- for (let ix = 0; ix < store.length; ix++) {
448
- item = store[ix];
449
- if (status) {
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.checkedIndex.clear();
443
+ checkInfo.checkedRows.splice(checkInfo.checkedRows.indexOf(row[ROW_DATA_INDEX]), 1);
444
+ checkInfo.checkedIndex.delete(row[ROW_INDEX]);
454
445
  }
455
-
456
- item[ROW_CHECK_INDEX] = status;
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 { filterInfo, stores, getColumnIndex } = params;
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
- return { onClickFilter, onCloseFilterWindow, onApplyFilter, setFilter };
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} makeIndex - 인덱스 생성 유무
845
+ * @param {boolean} isMakeIndex - 인덱스 생성 유무
801
846
  */
802
- const setStore = (value, makeIndex = true) => {
803
- nextTick(() => {
804
- const store = [];
805
- let checked;
806
- let selected = false;
807
- if (makeIndex) {
808
- let hasUnChecked = false;
809
-
810
- for (let ix = 0; ix < value.length; ix++) {
811
- checked = props.checked.includes(value[ix]);
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
- if (!selected) {
825
- selectInfo.selectedRow = [];
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 (filterInfo.isFiltering) {
832
- setFilter();
864
+ if (!selected) {
865
+ selectInfo.selectedRow = [];
833
866
  }
834
- if (sortInfo.sortField) {
835
- setSort();
836
- }
837
- if (elementInfo.body?.clientHeight) {
838
- updateVScroll();
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에 업데이트한다.
@@ -61,7 +61,7 @@
61
61
  :class="{ 'on': isPasswordVisible }"
62
62
  @click="changePasswordVisible"
63
63
  >
64
- <i class="ev-icon-radio-on"/>
64
+ <i :class="isPasswordVisible ? 'ev-icon-visibility' : 'ev-icon-visibility-off'"/>
65
65
  </span>
66
66
  <span
67
67
  v-if="type === 'search'"
@@ -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,20 +333,28 @@ 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
- (value) => {
344
+ (checkedList) => {
339
345
  let store = stores.treeStore;
340
346
  if (stores.searchStore.length > 0) {
341
347
  store = stores.searchStore;
342
348
  }
343
- const isCheck = store.every(n => n.checked === true);
349
+ checkInfo.checkedRows = checkedList;
344
350
  checkInfo.isHeaderChecked = false;
345
- checkInfo.checkedRows = value;
346
- for (let ix = 0; ix < store.length; ix++) {
347
- store[ix].checked = value.includes(store[ix]);
351
+ if (store.length) {
352
+ store.forEach((row) => {
353
+ row.checked = checkedList.includes(row);
354
+ });
355
+ checkInfo.isHeaderChecked = store.every(n => n.checked === true);
348
356
  }
349
- checkInfo.isHeaderChecked = isCheck;
357
+ updateVScroll();
350
358
  },
351
359
  );
352
360
  watch(
@@ -362,8 +370,6 @@ export default {
362
370
  checkInfo.isHeaderChecked = false;
363
371
  },
364
372
  );
365
- stores.treeStore = setTreeNodeStore();
366
-
367
373
  watch(
368
374
  () => props.rows,
369
375
  (newData) => {
@@ -655,10 +655,27 @@ export const filterEvent = (params) => {
655
655
  }
656
656
  const { parent } = data;
657
657
  parent.show = true;
658
- parent.expand = true;
659
658
  parent.isFilter = true;
660
659
  makeParentShow(parent);
661
660
  };
661
+ const makeChildShow = (data) => {
662
+ if (!data?.children) {
663
+ return;
664
+ }
665
+ const { children } = data;
666
+ children.forEach((node) => {
667
+ const childNode = node;
668
+ if (childNode.parent.show && childNode.parent.expand) {
669
+ childNode.show = true;
670
+ } else {
671
+ childNode.show = false;
672
+ }
673
+ childNode.isFilter = true;
674
+ if (childNode.hasChild) {
675
+ makeChildShow(childNode);
676
+ }
677
+ });
678
+ };
662
679
  let timer = null;
663
680
  const onSearch = (searchWord) => {
664
681
  if (timer) {
@@ -695,19 +712,28 @@ export const filterEvent = (params) => {
695
712
  });
696
713
  filterStores.forEach((row) => {
697
714
  row.show = true;
715
+ if (row.parent && !row.parent.expand) {
716
+ row.show = false;
717
+ }
698
718
  row.isFilter = true;
699
719
  makeParentShow(row);
720
+ makeChildShow(row);
700
721
  });
701
722
  } else {
702
723
  store.forEach((row) => {
703
724
  row.show = true;
704
725
  row.isFilter = false;
705
726
  });
727
+ store.forEach((row) => {
728
+ if (row.hasChild) {
729
+ makeChildShow(row);
730
+ }
731
+ });
706
732
  }
707
733
  if (stores.searchStore.length > 0) {
708
734
  store = stores.searchStore;
709
735
  }
710
- const isCheck = store.every(n => n.checked === true);
736
+ const isCheck = store.length > 0 && store.every(n => n.checked === true);
711
737
  checkInfo.isHeaderChecked = isCheck;
712
738
  calculatedColumn();
713
739
  updateVScroll();
Binary file