evui 3.1.54 → 3.1.58

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.1.54",
3
+ "version": "3.1.58",
4
4
  "description": "A EXEM Library project",
5
5
  "author": "exem <dev_client@ex-em.com>",
6
6
  "license": "MIT",
@@ -106,14 +106,8 @@ import { onMounted, onBeforeUnmount, watch, onDeactivated } from 'vue';
106
106
  });
107
107
 
108
108
  const redrawChart = () => {
109
- if (isInit) {
110
- evChart.update({
111
- updateSeries: false,
112
- updateSelTip: {
113
- update: false,
114
- keepDomain: false,
115
- },
116
- });
109
+ if (evChart && 'resize' in evChart && isInit) {
110
+ evChart.resize();
117
111
  }
118
112
  };
119
113
 
@@ -90,7 +90,6 @@ class EvChart {
90
90
  this.axesRange = this.getAxesRange();
91
91
  this.labelOffset = this.getLabelOffset();
92
92
 
93
- this.initScale();
94
93
  this.drawChart();
95
94
 
96
95
  if (tooltip.use) {
@@ -131,6 +130,7 @@ class EvChart {
131
130
  * @returns {undefined}
132
131
  */
133
132
  drawChart(hitInfo) {
133
+ this.initScale();
134
134
  this.labelRange = this.getAxesLabelRange();
135
135
  this.axesSteps = this.calculateSteps();
136
136
  this.drawAxis(hitInfo);
@@ -644,8 +644,8 @@ class EvChart {
644
644
  this.bufferCtx.restore();
645
645
  this.bufferCtx.save();
646
646
 
647
- this.getChartDOMRect();
648
647
  this.initScale();
648
+ this.chartRect = this.getChartRect();
649
649
  this.drawChart();
650
650
  }
651
651
 
@@ -658,7 +658,6 @@ class EvChart {
658
658
  render(hitInfo) {
659
659
  this.clear();
660
660
  this.chartRect = this.getChartRect();
661
- this.initScale();
662
661
  this.drawChart(hitInfo);
663
662
  }
664
663
 
@@ -151,7 +151,6 @@ class Bar {
151
151
  this.drawBar({
152
152
  ctx,
153
153
  positions: { x, y, w, h },
154
- isTop: item.isTop,
155
154
  });
156
155
 
157
156
  if (showValue.use) {
@@ -213,7 +212,6 @@ class Bar {
213
212
  this.drawBar({
214
213
  ctx,
215
214
  positions: { x, y, w, h: this.isHorizontal ? -h : h },
216
- isTop: item.data.isTop,
217
215
  });
218
216
 
219
217
  if (showValue.use) {
@@ -411,7 +409,7 @@ class Bar {
411
409
  ctx.restore();
412
410
  }
413
411
 
414
- drawBar({ ctx, positions, isTop }) {
412
+ drawBar({ ctx, positions }) {
415
413
  const isHorizontal = this.isHorizontal;
416
414
  const isStackBar = 'stackIndex' in this;
417
415
  const isBorderRadius = this.borderRadius && this.borderRadius > 0;
@@ -423,7 +421,7 @@ class Bar {
423
421
  return;
424
422
  }
425
423
 
426
- if ((!isStackBar && isBorderRadius) || (isStackBar && isBorderRadius && isTop)) {
424
+ if (isBorderRadius && !isStackBar) {
427
425
  try {
428
426
  this.drawRoundedRect(ctx, positions);
429
427
  } catch (e) {
@@ -26,7 +26,7 @@ const modules = {
26
26
 
27
27
  if (series && sData) {
28
28
  if (series.isExistGrp && series.stackIndex) {
29
- series.data = this.addSeriesStackDS(sData, label, series);
29
+ series.data = this.addSeriesStackDS(sData, label, series.bsIds, series.stackIndex);
30
30
  } else {
31
31
  series.data = this.addSeriesDS(sData, label);
32
32
  }
@@ -173,12 +173,12 @@ const modules = {
173
173
  * Take data and label to create stack data for each series
174
174
  * @param {object} data chart series info
175
175
  * @param {object} label chart label
176
- * @param {object} series series Information
176
+ * @param {array} bsIds stacked base data ID List
177
+ * @param {number} sIdx series ordered index
177
178
  *
178
179
  * @returns {array} data for each series
179
180
  */
180
- addSeriesStackDS(data, label, series) {
181
- const bsIds = series.bsIds; // stacked base data ID List
181
+ addSeriesStackDS(data, label, bsIds, sIdx = 0) {
182
182
  const isHorizontal = this.options.horizontal;
183
183
  const sdata = [];
184
184
 
@@ -201,8 +201,6 @@ const modules = {
201
201
  };
202
202
 
203
203
  data.forEach((curr, index) => {
204
- const { stackIndex, show: isShowSeries } = series;
205
- const isTop = true; // is top position on stack (Stacked or not, default is true)
206
204
  const baseIndex = bsIds.length - 1 < 0 ? 0 : bsIds.length - 1;
207
205
  let bdata = getBaseDataPosition(baseIndex, index); // base(previous) series data
208
206
  let odata = curr; // current series original data
@@ -216,7 +214,7 @@ const modules = {
216
214
  }
217
215
 
218
216
  const oData = odata?.value ?? odata;
219
- if (stackIndex > 0) {
217
+ if (sIdx > 0) {
220
218
  if (oData != null) {
221
219
  gdata = bdata + oData;
222
220
  } else {
@@ -228,14 +226,7 @@ const modules = {
228
226
  gdata = oData;
229
227
  }
230
228
 
231
- if (gdata && isShowSeries) {
232
- for (let idx = baseIndex; idx > -1; idx--) {
233
- const prevSeriesData = this.seriesList[bsIds[idx]];
234
- prevSeriesData.data[index].isTop = false;
235
- }
236
- }
237
-
238
- sdata.push(this.addData(gdata, ldata, odata, bdata, isTop));
229
+ sdata.push(this.addData(gdata, ldata, odata, bdata));
239
230
  }
240
231
  });
241
232
 
@@ -276,11 +267,10 @@ const modules = {
276
267
  * @param {object} ldata label data (x-axis value for vertical chart)
277
268
  * @param {object} odata original data (without stacked value)
278
269
  * @param {object} bdata base data (stacked value)
279
- * @param {boolean} isTop is top position on stack (Stacked or not, default is true)
280
270
 
281
271
  * @returns {object} data for each graph point
282
272
  */
283
- addData(gdata, ldata, odata = null, bdata = null, isTop = true) {
273
+ addData(gdata, ldata, odata = null, bdata = null) {
284
274
  let data;
285
275
  let gdataValue = null;
286
276
  let odataValue = null;
@@ -312,7 +302,6 @@ const modules = {
312
302
  data.w = null;
313
303
  data.h = null;
314
304
  data.dataColor = gdataColor ?? odataColor;
315
- data.isTop = isTop;
316
305
 
317
306
  return data;
318
307
  },
@@ -175,7 +175,7 @@ const modules = {
175
175
  * @returns {undefined}
176
176
  */
177
177
  dragStart(evt, type) {
178
- const [offsetX, offsetY] = this.getMousePosition(evt);
178
+ let [offsetX, offsetY] = this.getMousePosition(evt);
179
179
  const chartRect = this.chartRect;
180
180
  const labelOffset = this.labelOffset;
181
181
  const range = {
@@ -185,11 +185,20 @@ const modules = {
185
185
  y2: chartRect.y2 - labelOffset.bottom,
186
186
  };
187
187
 
188
- // check graph range
189
- if (offsetX < range.x1 || offsetX > range.x2
190
- || offsetY < range.y1 || offsetY > range.y2
191
- ) {
192
- return;
188
+ if (offsetX < range.x1) {
189
+ offsetX = range.x1;
190
+ }
191
+
192
+ if (offsetX > range.x2) {
193
+ offsetX = range.x2;
194
+ }
195
+
196
+ if (offsetY < range.y1) {
197
+ offsetY = range.y1;
198
+ }
199
+
200
+ if (offsetY > range.y2) {
201
+ offsetY = range.y2;
193
202
  }
194
203
 
195
204
  this.dragInfo = {
@@ -219,11 +219,11 @@ const modules = {
219
219
  let prev = a.data.o;
220
220
  let next = b.data.o;
221
221
 
222
- if (!prev) {
222
+ if (prev === null || prev === undefined) {
223
223
  prev = isHorizontal ? a.data.x : a.data.y;
224
224
  }
225
225
 
226
- if (!next) {
226
+ if (next === null || next === undefined) {
227
227
  next = isHorizontal ? b.data.x : b.data.y;
228
228
  }
229
229
  return next - prev;
@@ -9,11 +9,7 @@
9
9
  <template #toolbarWrapper>
10
10
  <slot
11
11
  name="toolbar"
12
- :item="{
13
- onRefresh: onRefresh,
14
- onDelete: onDelete,
15
- onSearch: onSearch,
16
- }"
12
+ :item="{ onSearch: onSearch }"
17
13
  >
18
14
  </slot>
19
15
  </template>
@@ -97,7 +93,7 @@
97
93
  <span
98
94
  :title="column.caption"
99
95
  class="column-name"
100
- @click.stop="onSort(column.field)"
96
+ @click.stop="onSort(column)"
101
97
  >
102
98
  {{ column.caption }}
103
99
  </span>
@@ -206,9 +202,6 @@
206
202
  :item="{
207
203
  row,
208
204
  column,
209
- onRowDelete: onRowDelete,
210
- onRowEdit: onRowEdit,
211
- onDetailPopup: onDetailPopup,
212
205
  }"
213
206
  >
214
207
  </slot>
@@ -253,18 +246,12 @@
253
246
  @apply-filter="onApplyFilter"
254
247
  @before-close="onCloseFilterWindow"
255
248
  />
256
- <ev-window
257
- v-model:visible="isDetailPopWin"
258
- title="DETAIL POPUP"
259
- >
260
- <div>{{detailPopData}}</div>
261
- </ev-window>
262
249
  </div>
263
250
  </div>
264
251
  </template>
265
252
 
266
253
  <script>
267
- import { reactive, ref, toRefs, computed, watch, onMounted, getCurrentInstance } from 'vue';
254
+ import { reactive, toRefs, computed, watch, onMounted } from 'vue';
268
255
  import FilterWindow from './grid.filter.window';
269
256
  import Toolbar from './grid.toolbar';
270
257
  import {
@@ -331,7 +318,6 @@ export default {
331
318
  getColumnIndex,
332
319
  setPixelUnit,
333
320
  } = commonFunctions();
334
- const { ctx } = getCurrentInstance();
335
321
  const showHeader = computed(() =>
336
322
  (props.option.showHeader === undefined ? true : props.option.showHeader));
337
323
  const stripeStyle = computed(() => (props.option.style?.stripe || false));
@@ -625,51 +611,6 @@ export default {
625
611
  setStore([], false);
626
612
  }, 500);
627
613
  };
628
- const onRefresh = () => {
629
- console.log('On click refresh button');
630
- };
631
- const onDelete = () => {
632
- ctx.$messagebox({
633
- title: 'Delete',
634
- message: 'Are you sure you want to delete checked item?',
635
- iconClass: 'ev-icon-trash3',
636
- onClose: (type) => {
637
- if (type === 'ok') {
638
- stores.originStore = stores.store.filter(item => !item[1]);
639
- setStore([], false);
640
- }
641
- },
642
- });
643
- };
644
- const onRowDelete = (index) => {
645
- ctx.$messagebox({
646
- title: 'Delete',
647
- message: 'Are you sure you want to delete this item?',
648
- iconClass: 'ev-icon-trash3',
649
- onClose: (type) => {
650
- if (type === 'ok') {
651
- stores.originStore = stores.store.filter(item => item[0] !== index);
652
- setStore([], false);
653
- }
654
- },
655
- });
656
- // emit
657
- };
658
- const onRowEdit = (row) => {
659
- ctx.$messagebox({
660
- title: 'Edit',
661
- message: row[2],
662
- iconClass: 'ev-icon-pencil',
663
- showCancelBtn: false,
664
- });
665
- // emit
666
- };
667
- const isDetailPopWin = ref(false);
668
- const detailPopData = ref('');
669
- const onDetailPopup = (row) => {
670
- isDetailPopWin.value = true;
671
- detailPopData.value = row[2];
672
- };
673
614
  const isFilterButton = field => filterInfo.isFiltering && field !== 'db-icon' && field !== 'user-icon';
674
615
  return {
675
616
  showHeader,
@@ -685,8 +626,6 @@ export default {
685
626
  ...toRefs(checkInfo),
686
627
  ...toRefs(sortInfo),
687
628
  ...toRefs(contextInfo),
688
- isDetailPopWin,
689
- detailPopData,
690
629
  isRenderer,
691
630
  getComponentName,
692
631
  getConvertValue,
@@ -713,12 +652,7 @@ export default {
713
652
  updateData,
714
653
  setContextMenu,
715
654
  onContextMenu,
716
- onRefresh,
717
- onDelete,
718
655
  onSearch,
719
- onRowEdit,
720
- onRowDelete,
721
- onDetailPopup,
722
656
  isFilterButton,
723
657
  };
724
658
  },
@@ -475,17 +475,20 @@ export const sortEvent = (params) => {
475
475
  /**
476
476
  * sort 이벤트를 처리한다.
477
477
  *
478
- * @param {string} field - 컬럼 field
478
+ * @param {object} column - 컬럼 정보
479
479
  */
480
- const onSort = (field) => {
481
- if (sortInfo.sortField !== field) {
482
- order.orders = ['asc', 'desc', 'init'];
483
- sortInfo.sortField = field;
484
- }
485
- sortInfo.sortOrder = order.dequeue();
486
- order.enqueue(sortInfo.sortOrder);
480
+ const onSort = (column) => {
481
+ const sortable = column.sortable === undefined ? true : column.sortable;
482
+ if (sortable) {
483
+ if (sortInfo.sortField !== column?.field) {
484
+ order.orders = ['asc', 'desc', 'init'];
485
+ sortInfo.sortField = column?.field;
486
+ }
487
+ sortInfo.sortOrder = order.dequeue();
488
+ order.enqueue(sortInfo.sortOrder);
487
489
 
488
- sortInfo.isSorting = true;
490
+ sortInfo.isSorting = true;
491
+ }
489
492
  };
490
493
  /**
491
494
  * 설정값에 따라 해당 컬럼 데이터에 대해 정렬한다.
@@ -4,6 +4,7 @@
4
4
  :class="{
5
5
  checked: modelValue,
6
6
  disabled,
7
+ readonly,
7
8
  }"
8
9
  :style="{
9
10
  width: `${width}px`,
@@ -24,6 +25,10 @@ export default {
24
25
  type: Boolean,
25
26
  default: false,
26
27
  },
28
+ readonly: {
29
+ type: Boolean,
30
+ default: false,
31
+ },
27
32
  disabled: {
28
33
  type: Boolean,
29
34
  default: false,
@@ -51,7 +56,7 @@ export default {
51
56
  },
52
57
  });
53
58
  const clickMv = () => {
54
- if (!props.disabled) {
59
+ if (!props.disabled && !props.readonly) {
55
60
  mv.value = !mv.value;
56
61
  }
57
62
  };
@@ -95,12 +100,14 @@ export default {
95
100
  left: calc(100% - 17px);
96
101
  }
97
102
 
98
- &.disabled {
103
+ &.readonly {
99
104
  opacity: .6;
105
+ cursor: default;
106
+ }
100
107
 
101
- &:hover {
102
- cursor: not-allowed;
103
- }
108
+ &.disabled {
109
+ opacity: .6;
110
+ cursor: not-allowed;
104
111
  }
105
112
  }
106
113
 
@@ -246,6 +246,7 @@ export default {
246
246
  treeStore: [],
247
247
  viewStore: [],
248
248
  filterStore: [],
249
+ searchStore: computed(() => stores.treeStore.filter(item => item.isFilter)),
249
250
  treeRows: props.rows,
250
251
  showTreeStore: computed(() => stores.treeStore.filter(item => item.show)),
251
252
  orderedColumns: computed(() =>
@@ -330,20 +331,22 @@ export default {
330
331
 
331
332
  const {
332
333
  onSearch,
333
- } = filterEvent({ stores, getConvertValue, calculatedColumn, updateVScroll });
334
+ } = filterEvent({ checkInfo, stores, getConvertValue, calculatedColumn, updateVScroll });
334
335
 
335
336
  watch(
336
337
  () => props.checked,
337
338
  (value) => {
338
- const store = stores.treeStore;
339
+ let store = stores.treeStore;
340
+ if (stores.searchStore.length > 0) {
341
+ store = stores.searchStore;
342
+ }
343
+ const isCheck = store.every(n => n.checked === true);
339
344
  checkInfo.isHeaderChecked = false;
340
345
  checkInfo.checkedRows = value;
341
346
  for (let ix = 0; ix < store.length; ix++) {
342
347
  store[ix].checked = value.includes(store[ix]);
343
348
  }
344
- if (value.length && store.length === value.length) {
345
- checkInfo.isHeaderChecked = true;
346
- }
349
+ checkInfo.isHeaderChecked = isCheck;
347
350
  },
348
351
  );
349
352
  watch(
@@ -418,11 +418,14 @@ export const checkEvent = (params) => {
418
418
  * @param {array} rowData - row 데이터
419
419
  */
420
420
  const onCheck = (event, rowData) => {
421
+ let store = stores.treeStore;
422
+ if (stores.searchStore.length > 0) {
423
+ store = stores.searchStore;
424
+ }
421
425
  const isSingleMode = () => checkInfo.useCheckbox.mode === 'single';
422
- const checkedHeader = (store) => {
423
- if (checkInfo.checkedRows.length === store.length) {
424
- checkInfo.isHeaderChecked = true;
425
- }
426
+ const checkedHeader = (checkStore) => {
427
+ const isCheck = checkStore.every(n => n.checked === true);
428
+ checkInfo.isHeaderChecked = isCheck;
426
429
  };
427
430
  const unCheckedHeader = () => {
428
431
  if (checkInfo.isHeaderChecked) {
@@ -455,7 +458,7 @@ export const checkEvent = (params) => {
455
458
  onSingleMode();
456
459
  if (rowData.checked) {
457
460
  addCheckedRow(rowData);
458
- checkedHeader(stores.treeStore);
461
+ checkedHeader(store);
459
462
  } else {
460
463
  unCheckedHeader();
461
464
  removeCheckedRow(rowData);
@@ -472,10 +475,13 @@ export const checkEvent = (params) => {
472
475
  * @param {object} event - 이벤트 객체
473
476
  */
474
477
  const onCheckAll = (event) => {
475
- const store = stores.treeStore;
476
478
  const status = checkInfo.isHeaderChecked;
477
479
  const checked = [];
478
480
  let item;
481
+ let store = stores.treeStore;
482
+ if (status && stores.searchStore.length > 0) {
483
+ store = stores.searchStore;
484
+ }
479
485
  for (let ix = 0; ix < store.length; ix++) {
480
486
  item = store[ix];
481
487
  if (status) {
@@ -484,6 +490,11 @@ export const checkEvent = (params) => {
484
490
  item.checked = status;
485
491
  }
486
492
  checkInfo.checkedRows = checked;
493
+ if (stores.searchStore.length > 0) {
494
+ store.forEach((node) => {
495
+ onCheckChildren(node);
496
+ });
497
+ }
487
498
  emit('update:checked', checked);
488
499
  emit('check-all', event, checked);
489
500
  };
@@ -637,7 +648,7 @@ export const treeEvent = (params) => {
637
648
  };
638
649
 
639
650
  export const filterEvent = (params) => {
640
- const { stores, getConvertValue, calculatedColumn, updateVScroll } = params;
651
+ const { checkInfo, stores, getConvertValue, calculatedColumn, updateVScroll } = params;
641
652
  const makeParentShow = (data) => {
642
653
  if (!data?.parent) {
643
654
  return;
@@ -654,26 +665,29 @@ export const filterEvent = (params) => {
654
665
  clearTimeout(timer);
655
666
  }
656
667
  timer = setTimeout(() => {
657
- stores.treeStore.forEach((row) => {
668
+ let store = stores.treeStore;
669
+ store.forEach((row) => {
658
670
  row.show = false;
659
671
  row.isFilter = false;
660
672
  });
661
673
  if (searchWord) {
662
- const filterStores = stores.treeStore.filter((row) => {
674
+ const filterStores = store.filter((row) => {
663
675
  let isSameWord = false;
664
676
  for (let ix = 0; ix < stores.orderedColumns.length; ix++) {
665
677
  const column = stores.orderedColumns[ix] || {};
666
678
  let columnValue = row[column.field];
667
679
  let columnType = column.type;
668
680
  if (columnValue) {
669
- if (!columnType) {
670
- columnType = 'string';
671
- }
672
- columnValue = getConvertValue(columnType, columnValue).toString();
673
- isSameWord = columnValue.toLowerCase()
674
- .includes(searchWord.toString().toLowerCase());
675
- if (isSameWord) {
676
- break;
681
+ if (!column.hide && (column?.searchable === undefined || column?.searchable)) {
682
+ if (!columnType) {
683
+ columnType = 'string';
684
+ }
685
+ columnValue = getConvertValue(columnType, columnValue).toString();
686
+ isSameWord = columnValue.toLowerCase()
687
+ .includes(searchWord.toString().toLowerCase());
688
+ if (isSameWord) {
689
+ break;
690
+ }
677
691
  }
678
692
  }
679
693
  }
@@ -685,11 +699,16 @@ export const filterEvent = (params) => {
685
699
  makeParentShow(row);
686
700
  });
687
701
  } else {
688
- stores.treeStore.forEach((row) => {
702
+ store.forEach((row) => {
689
703
  row.show = true;
690
704
  row.isFilter = false;
691
705
  });
692
706
  }
707
+ if (stores.searchStore.length > 0) {
708
+ store = stores.searchStore;
709
+ }
710
+ const isCheck = store.every(n => n.checked === true);
711
+ checkInfo.isHeaderChecked = isCheck;
693
712
  calculatedColumn();
694
713
  updateVScroll();
695
714
  }, 500);
@@ -27,6 +27,7 @@
27
27
  }"
28
28
  @mousedown="startDrag"
29
29
  @mousemove="moveMouse"
30
+ @click="setFocus"
30
31
  >
31
32
  <div
32
33
  v-if="$slots.header || iconClass || title"
@@ -84,11 +85,17 @@
84
85
  </template>
85
86
 
86
87
  <script>
87
- import { useEscKeydownEvent, useModel, useMouseEvent } from './uses';
88
+ import { useEscCloseAndFocusable, useModel, useMouseEvent } from './uses';
88
89
 
89
90
  export default {
90
91
  name: 'EvWindow',
91
92
  props: {
93
+ style: {
94
+ type: Object,
95
+ default() {
96
+ return {};
97
+ },
98
+ },
92
99
  visible: {
93
100
  type: Boolean,
94
101
  default: false,
@@ -153,6 +160,10 @@ export default {
153
160
  type: Boolean,
154
161
  default: false,
155
162
  },
163
+ focusable: {
164
+ type: Boolean,
165
+ default: false,
166
+ },
156
167
  },
157
168
  emits: [
158
169
  'update:visible',
@@ -187,7 +198,7 @@ export default {
187
198
  removeUnit,
188
199
  });
189
200
 
190
- useEscKeydownEvent({ closeWin, windowRef });
201
+ const { setFocus } = useEscCloseAndFocusable({ closeWin, windowRef });
191
202
 
192
203
  return {
193
204
  windowRef,
@@ -200,6 +211,8 @@ export default {
200
211
  startDrag,
201
212
  moveMouse,
202
213
  clickExpandBtn,
214
+
215
+ setFocus,
203
216
  };
204
217
  },
205
218
  };