evui 3.3.25 → 3.3.28

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.
@@ -183,9 +183,7 @@ const modules = {
183
183
  this.onLegendBoxLeave = () => {
184
184
  this.legendDragInfo.dragging = false;
185
185
 
186
- const lineDOM = this.containerDOM.getElementsByClassName('ev-chart-legend-line')[0];
187
- const targetDOM = lineDOM.getElementsByClassName('ev-chart-legend-thumb')[0];
188
- this.clearOverlay(targetDOM);
186
+ this.clearOverlay();
189
187
 
190
188
  const seriesList = Object.values(this.seriesList);
191
189
  if (!seriesList.length) {
@@ -256,7 +254,7 @@ const modules = {
256
254
 
257
255
  clearOverlay() {
258
256
  const targetDOM = this.containerDOM.getElementsByClassName('ev-chart-legend-line')[0];
259
- const overlayDOM = targetDOM.getElementsByClassName('ev-chart-legend-overlay')[0];
257
+ const overlayDOM = targetDOM?.getElementsByClassName('ev-chart-legend-overlay')[0];
260
258
  if (overlayDOM) {
261
259
  targetDOM.removeChild(overlayDOM);
262
260
 
@@ -307,13 +305,15 @@ const modules = {
307
305
 
308
306
  overlayDOM.appendChild(tooltipDOM);
309
307
  overlayDOM.appendChild(itemDOM);
310
- targetDOM.appendChild(overlayDOM);
308
+ targetDOM?.appendChild(overlayDOM);
311
309
 
312
- const thumbDOM = targetDOM.getElementsByClassName('ev-chart-legend-thumb')[0];
313
- const labels = thumbDOM.children;
314
- labels.forEach((labelDOM) => {
315
- labelDOM.style.opacity = 0.2;
316
- });
310
+ const thumbDOM = targetDOM?.getElementsByClassName('ev-chart-legend-thumb')[0];
311
+ if (thumbDOM) {
312
+ const labels = thumbDOM.children;
313
+ labels.forEach((labelDOM) => {
314
+ labelDOM.style.opacity = 0.2;
315
+ });
316
+ }
317
317
  },
318
318
 
319
319
  createLegendHandle(type) {
@@ -21,6 +21,7 @@ const modules = {
21
21
  let startAngle = 1.5 * Math.PI;
22
22
  let endAngle;
23
23
  let series;
24
+ let percentage;
24
25
 
25
26
  const centerX = chartRect.width / 2;
26
27
  const centerY = chartRect.height / 2;
@@ -57,6 +58,7 @@ const modules = {
57
58
  for (let jx = 0; jx < pie.data.length; jx++) {
58
59
  slice = pie.data[jx];
59
60
  value = slice.value;
61
+ percentage = (value / pie.total) * 100;
60
62
  sliceAngle = 2 * Math.PI * (value / pie.total);
61
63
  endAngle = startAngle + sliceAngle;
62
64
 
@@ -83,7 +85,7 @@ const modules = {
83
85
  series.doughnutHoleSize = radius * (pieOption.doughnutHoleSize ?? 0);
84
86
  series.startAngle = startAngle;
85
87
  series.endAngle = endAngle;
86
- series.data = { o: value };
88
+ series.data = { o: value, percentage };
87
89
 
88
90
  series.draw(ctx, strokeOptions);
89
91
  startAngle += sliceAngle;
@@ -61,16 +61,21 @@
61
61
  </span>
62
62
  </div>
63
63
  </template>
64
- <template v-else-if="mv[0] && mv[mv.length - 1]">
65
- <div class="ev-select-tag num">
64
+ <template v-else>
65
+ <div
66
+ v-if="mv[0]"
67
+ class="ev-select-tag num"
68
+ >
66
69
  <span class="ev-tag-name"> {{ mv[0] }} </span>
67
70
  </div>
68
- <div class="ev-select-tag num">
69
- <span class="ev-tag-name"> ~ </span>
70
- </div>
71
- <div class="ev-select-tag num">
72
- <span class="ev-tag-name"> {{ mv[mv.length - 1] }} </span>
73
- </div>
71
+ <template v-if="mv[mv.length - 1]">
72
+ <div class="ev-select-tag num">
73
+ <span class="ev-tag-name"> ~ </span>
74
+ </div>
75
+ <div class="ev-select-tag num">
76
+ <span class="ev-tag-name"> {{ mv[mv.length - 1] }} </span>
77
+ </div>
78
+ </template>
74
79
  </template>
75
80
  </div>
76
81
  </template>
@@ -95,7 +100,14 @@
95
100
  v-if="usedShortcuts.length"
96
101
  class="ev-date-picker-dropbox__button-layout"
97
102
  >
98
- <ev-button-group>
103
+ <ev-button
104
+ v-if="usedShortcuts.length === 1"
105
+ :type="usedShortcuts[0].isActive ? 'primary' : 'default'"
106
+ @click="clickShortcut(usedShortcuts[0].key)"
107
+ >
108
+ {{ usedShortcuts[0].label }}
109
+ </ev-button>
110
+ <ev-button-group v-else>
99
111
  <ev-button
100
112
  v-for="button in usedShortcuts"
101
113
  :key="button.key"
@@ -195,7 +207,7 @@ export default {
195
207
  const timeReg = new RegExp(/(HH|2[0-3]|[01][0-9]):(mm|[0-5][0-9]):(ss|[0-5][0-9])/);
196
208
  return (multiType ? ['weekday', 'week', 'date'].indexOf(multiType) !== -1 : true)
197
209
  && (multiDayLimit ? typeof multiDayLimit === 'number' && multiDayLimit > 0 : true)
198
- && (disabledDate ? typeof disabledDate === 'function' : true)
210
+ && (disabledDate ? (typeof disabledDate === 'function' || Array.isArray(disabledDate)) : true)
199
211
  && (tagShorten !== undefined ? typeof tagShorten === 'boolean' : true)
200
212
  && Array.isArray(timeFormat)
201
213
  ? timeFormat.every(v => !!(!v || timeReg.exec(v)))
@@ -36,7 +36,7 @@ export const useModel = () => {
36
36
  // mode: 'date' or 'dateTime'시 input box의 입력된 텍스트값
37
37
  let currentValue;
38
38
  if (['dateTimeRange', 'dateTime'].includes(props.mode) && timeFormat) {
39
- if (props.mode === 'dateTimeRange' && props.modelValue.length) {
39
+ if (props.mode === 'dateTimeRange' && Array.isArray(props.modelValue) && props.modelValue.length === 2) {
40
40
  const [fromDate, toDate] = props.modelValue;
41
41
  const [fromTimeFormat, toTimeFormat] = timeFormat;
42
42
 
@@ -300,19 +300,41 @@ export const useShortcuts = (param) => {
300
300
 
301
301
  let targetKey;
302
302
  if (isRange) {
303
+ const timeFormat = props.options?.timeFormat;
303
304
  const [fromDate, toDate] = mv.value;
304
- const targetShortcut = usedShortcuts.find(({ shortcutDate }) => {
305
- const [sFromDate, sToDate] = shortcutDate();
306
- const isCorrectFromDate = formatDate(sFromDate) === formatDate(fromDate);
307
- const isCorrectToDate = formatDate(sToDate) === formatDate(toDate);
308
- return isCorrectFromDate && isCorrectToDate;
309
- });
305
+ let targetShortcut;
306
+ if (props.mode === 'dateTimeRange' && timeFormat?.length) {
307
+ targetShortcut = usedShortcuts.find(({ shortcutDate }) => {
308
+ const [sFromDate, sToDate] = shortcutDate();
309
+ const [fromTimeFormat, toTimeFormat] = timeFormat;
310
+ const formatFromDate = getChangedValueByTimeFormat(
311
+ fromTimeFormat,
312
+ formatDateTime(sFromDate),
313
+ );
314
+ const formatToDate = getChangedValueByTimeFormat(
315
+ toTimeFormat,
316
+ formatDateTime(sToDate),
317
+ );
318
+ const isCorrectFromDate = formatFromDate === formatDateTime(fromDate);
319
+ const isCorrectToDate = formatToDate === formatDateTime(toDate);
320
+ return isCorrectFromDate && isCorrectToDate;
321
+ });
322
+ } else {
323
+ targetShortcut = usedShortcuts.find(({ shortcutDate }) => {
324
+ const [sFromDate, sToDate] = shortcutDate();
325
+ const formatFunc = props.mode === 'dateTimeRange' ? formatDateTime : formatDate;
326
+ const isCorrectFromDate = formatFunc(sFromDate) === formatFunc(fromDate);
327
+ const isCorrectToDate = formatFunc(sToDate) === formatFunc(toDate);
328
+ return isCorrectFromDate && isCorrectToDate;
329
+ });
330
+ }
310
331
  targetKey = targetShortcut?.key;
311
332
  } else {
312
- const date = formatDate(mv.value);
333
+ const formatFunc = props.mode === 'dateTime' ? formatDateTime : formatDate;
334
+ const date = formatFunc(mv.value);
313
335
  const targetShortcut = usedShortcuts.find(({ shortcutDate }) => {
314
- const sDate = formatDate(shortcutDate());
315
- return sDate === formatDate(date);
336
+ const sDate = formatFunc(shortcutDate());
337
+ return sDate === date;
316
338
  });
317
339
  targetKey = targetShortcut?.key;
318
340
  }
@@ -375,7 +397,11 @@ export const useShortcuts = (param) => {
375
397
  && props?.options?.multiDayLimit > curr.length
376
398
  ) {
377
399
  return;
378
- } else if (props.mode === 'dateTime' || props.mode === 'dateTimeRange') {
400
+ } else if (
401
+ props.mode === 'dateRange'
402
+ || props.mode === 'dateTime'
403
+ || props.mode === 'dateTimeRange'
404
+ ) {
379
405
  currentValue.value = curr;
380
406
  return;
381
407
  } else if (props.mode === 'date') {
@@ -498,7 +498,6 @@ export const checkEvent = (params) => {
498
498
 
499
499
  export const sortEvent = (params) => {
500
500
  const { sortInfo, stores, getColumnIndex, updatePagingInfo } = params;
501
- const { props } = getCurrentInstance();
502
501
  function OrderQueue() {
503
502
  this.orders = ['asc', 'desc', 'init'];
504
503
  this.dequeue = () => this.orders.shift();
@@ -542,35 +541,46 @@ export const sortEvent = (params) => {
542
541
  return;
543
542
  }
544
543
  const index = getColumnIndex(sortInfo.sortField);
545
- const type = props.columns[index]?.type || 'string';
544
+ const type = stores.orderedColumns[index]?.type || 'string';
546
545
  const sortFn = sortInfo.sortOrder === 'desc' ? setDesc : setAsc;
547
546
  const numberSortFn = sortInfo.sortOrder === 'desc' ? numberSetDesc : numberSetAsc;
547
+ const getColumnValue = (a, b) => {
548
+ let aCol = a[ROW_DATA_INDEX][index];
549
+ let bCol = b[ROW_DATA_INDEX][index];
550
+ if (a[ROW_DATA_INDEX][index] && typeof a[ROW_DATA_INDEX][index] === 'object') {
551
+ aCol = a[ROW_DATA_INDEX][index][stores.orderedColumns[index]?.field];
552
+ bCol = b[ROW_DATA_INDEX][index][stores.orderedColumns[index]?.field];
553
+ }
554
+ return { aCol, bCol };
555
+ };
548
556
  switch (type) {
549
557
  case 'string':
550
558
  stores.store.sort((a, b) => {
551
- if (!a[ROW_DATA_INDEX][index] || typeof a[ROW_DATA_INDEX][index] === 'string') {
552
- a[ROW_DATA_INDEX][index] = a[ROW_DATA_INDEX][index] || '';
553
- b[ROW_DATA_INDEX][index] = b[ROW_DATA_INDEX][index] || '';
554
- return sortFn(a[ROW_DATA_INDEX][index]?.toLowerCase(),
555
- b[ROW_DATA_INDEX][index]?.toLowerCase());
559
+ let { aCol, bCol } = getColumnValue(a, b);
560
+ if ((!aCol || typeof aCol === 'string') && (!bCol || typeof bCol === 'string')) {
561
+ aCol = aCol || '';
562
+ bCol = bCol || '';
563
+ return sortFn(aCol?.toLowerCase(), bCol?.toLowerCase());
556
564
  }
557
565
  return 0;
558
566
  });
559
567
  break;
560
568
  case 'stringNumber':
561
569
  stores.store.sort((a, b) => {
562
- if (!a[ROW_DATA_INDEX][index] || typeof a[ROW_DATA_INDEX][index] === 'string' || typeof a[ROW_DATA_INDEX][index] === 'number') {
563
- a[ROW_DATA_INDEX][index] = a[ROW_DATA_INDEX][index] === '' ? null : a[ROW_DATA_INDEX][index];
564
- b[ROW_DATA_INDEX][index] = b[ROW_DATA_INDEX][index] === '' ? null : b[ROW_DATA_INDEX][index];
565
- return numberSortFn(a[ROW_DATA_INDEX][index] ?? null, b[ROW_DATA_INDEX][index] ?? null);
570
+ let { aCol, bCol } = getColumnValue(a, b);
571
+ if (!aCol || typeof aCol === 'string' || typeof aCol === 'number') {
572
+ aCol = aCol === '' ? null : aCol;
573
+ bCol = bCol === '' ? null : bCol;
574
+ return numberSortFn(aCol ?? null, bCol ?? null);
566
575
  }
567
576
  return 0;
568
577
  });
569
578
  break;
570
579
  default:
571
580
  stores.store.sort((a, b) => {
572
- if (!a[ROW_DATA_INDEX][index] || typeof a[ROW_DATA_INDEX][index] === 'number' || typeof a[ROW_DATA_INDEX][index] === 'boolean') {
573
- return numberSortFn(a[ROW_DATA_INDEX][index] ?? null, b[ROW_DATA_INDEX][index] ?? null);
581
+ const { aCol, bCol } = getColumnValue(a, b);
582
+ if (!aCol || typeof aCol === 'number' || typeof aCol === 'boolean') {
583
+ return numberSortFn(aCol ?? null, bCol ?? null);
574
584
  }
575
585
  return 0;
576
586
  });
@@ -178,7 +178,7 @@
178
178
  <grid-pagination
179
179
  v-if="usePage && !isInfinite"
180
180
  v-model="currentPage"
181
- :total="pageTotal"
181
+ :total="showTreeStore.length"
182
182
  :per-page="perPage"
183
183
  :visible-page="visiblePage"
184
184
  :show-page-info="showPageInfo"
@@ -543,19 +543,21 @@ export default {
543
543
  highlightNode.show = true;
544
544
  highlightNode.isFilter = true;
545
545
  setParentShow(highlightNode);
546
+ // tree 에 보여지는 데이터 기준으로 index 다시 구하기
547
+ const highlightIndex = stores.showTreeStore
548
+ .map(node => node.index)
549
+ .indexOf(highlightNode.index);
546
550
  if (pageInfo.usePage && !pageInfo.isInfinite) {
547
- const highlightNodeIndex = (stores.showTreeStore
548
- .map(node => node.index)
549
- .indexOf(highlightNode.index)
550
- ) + 1; // tree 에 보여지는 데이터 기준으로 index 다시 구하기
551
- pageInfo.highlightPage = Math.ceil(highlightNodeIndex / pageInfo.perPage) || 1;
551
+ const page = Math.ceil(highlightIndex / pageInfo.perPage);
552
+ pageInfo.highlightPage = highlightIndex === pageInfo.perPage ? page + 1 : page || 1;
553
+ // 페이지 이동
552
554
  if (pageInfo.highlightPage !== pageInfo.currentPage) {
553
555
  pageInfo.currentPage = pageInfo.highlightPage;
554
556
  pageInfo.isHighlight = true;
555
557
  return;
556
558
  }
557
559
  }
558
- elementInfo.body.scrollTop = resizeInfo.rowHeight * styleInfo.highlightIdx;
560
+ elementInfo.body.scrollTop = resizeInfo.rowHeight * highlightIndex;
559
561
  }
560
562
  },
561
563
  );
@@ -640,7 +642,10 @@ export default {
640
642
  }
641
643
  updateVScroll();
642
644
  if (current === pageInfo.highlightPage && pageInfo.isHighlight) {
643
- elementInfo.body.scrollTop = resizeInfo.rowHeight * styleInfo.highlightIdx;
645
+ const highlightIndex = stores.pagingStore
646
+ .map(node => node.index)
647
+ .indexOf(styleInfo.highlightIdx);
648
+ elementInfo.body.scrollTop = resizeInfo.rowHeight * highlightIndex;
644
649
  pageInfo.isHighlight = !pageInfo.isHighlight;
645
650
  }
646
651
  });
@@ -360,10 +360,12 @@ export const clickEvent = (params) => {
360
360
  const getClickedRowData = (event, row) => {
361
361
  const tagName = event.target.tagName.toLowerCase();
362
362
  let cellInfo = {};
363
- if (tagName === 'td') {
364
- cellInfo = event.target.dataset;
365
- } else {
366
- cellInfo = event.target.closest('td').dataset;
363
+ if (event.target.offsetParent) {
364
+ if (tagName === 'td') {
365
+ cellInfo = event.target.dataset;
366
+ } else {
367
+ cellInfo = event.target.closest('td').dataset;
368
+ }
367
369
  }
368
370
  return {
369
371
  event,