@itfin/components 1.3.36 → 1.3.37

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": "@itfin/components",
3
- "version": "1.3.36",
3
+ "version": "1.3.37",
4
4
  "author": "Vitalii Savchuk <esvit666@gmail.com>",
5
5
  "scripts": {
6
6
  "serve": "vue-cli-service serve",
@@ -8,5 +8,9 @@
8
8
  .page-link {
9
9
  border-radius: .5rem;
10
10
  }
11
+
12
+ &.disabled .page-link {
13
+ background-color: transparent;
14
+ }
11
15
  }
12
16
  }
@@ -32,7 +32,7 @@ class itfDropdown extends Vue {
32
32
  modalId = '';
33
33
 
34
34
  render (createElement, context) {
35
- const { props, slots, data } = context;
35
+ const { props, slots, data, listeners } = context;
36
36
  const modalId = `dropdownId${globalModalIndex++}`;
37
37
  const { buttonOptions, toggle, text, disabled, label, appendToBody } = props;
38
38
  const { button, default: defaultSlot } = slots();
@@ -52,6 +52,18 @@ class itfDropdown extends Vue {
52
52
  {
53
53
  ref: data.ref,
54
54
  props: { ...props, toggleId: modalId },
55
+ on: {
56
+ open: () => {
57
+ if (listeners.open) {
58
+ listeners.open();
59
+ }
60
+ },
61
+ close: () => {
62
+ if (listeners.close) {
63
+ listeners.close();
64
+ }
65
+ }
66
+ }
55
67
  },
56
68
  defaultSlot
57
69
  )
@@ -52,24 +52,27 @@ class itfDropdownMenu extends Vue {
52
52
  context.appendChild(this.$el); // should append only to body
53
53
  }
54
54
 
55
- this.$el.addEventListener('shown.bs.dropdown', () => {
56
- setTimeout(() => {
57
- this.$emit('open');
58
- }, 500);
55
+ toggle.addEventListener('shown.bs.dropdown', () => {
56
+ this.$emit('open');
59
57
  });
60
- this.$el.addEventListener('hidden.bs.dropdown', () => {
58
+ toggle.addEventListener('hidden.bs.dropdown', () => {
61
59
  this.$emit('close');
62
60
  });
63
61
  }
64
62
 
65
63
  beforeDestroy() {
66
- if (this.modalEl) {
67
- this.modalEl.hide();
68
- this.modalEl.dispose();
64
+ try {
65
+ if (this.modalEl) {
66
+ this.modalEl.hide();
67
+ this.modalEl.dispose();
68
+ }
69
+ } catch (err) {
70
+ // ignore
69
71
  }
70
72
  }
71
73
 
72
74
  show() {
75
+ console.info('p[en')
73
76
  if (this.modalEl) {
74
77
  this.modalEl.show();
75
78
  }
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
 
3
3
  <nav aria-label="Page navigation example">
4
- <ul class="pagination itf-pagination">
4
+ <ul class="pagination itf-pagination px-3">
5
5
  <li
6
6
  v-for="(page, n) in pagesArr"
7
7
  :key="n"
@@ -21,6 +21,8 @@
21
21
  :show-add-column="showAddColumn"
22
22
  :show-header="!noHeader"
23
23
  :schema="schema"
24
+ :no-column-menu="noColumnMenu"
25
+ :no-select-all="noSelectAll"
24
26
  @new="$emit('new', $event)"
25
27
  @add-column="$emit('add-column', $event)"
26
28
  >
@@ -41,7 +43,6 @@
41
43
  .scrollable {
42
44
  --itf-table-hover-bg: #f2f2f2;
43
45
  --itf-table-min-width: 45px;
44
- --itf-table-line-height: 35px;
45
46
 
46
47
  body[data-theme="dark"] & {
47
48
  --itf-table-hover-bg: #393b41;
@@ -76,7 +77,6 @@ import itfButton from '../button/Button.vue';
76
77
  import itfIcon from '../icon/Icon.vue';
77
78
  import itfTableGroup from './TableGroup.vue';
78
79
  import itfTableHeader from './TableHeader.vue';
79
- import itfTableBody from "@/components/table/TableBody.vue";
80
80
 
81
81
  export default @Component({
82
82
  name: 'itfTable2',
@@ -84,7 +84,6 @@ export default @Component({
84
84
  return { tableEl: this }; // do not use Provide from vue-property-decorator
85
85
  },
86
86
  components: {
87
- itfTableBody,
88
87
  itfCheckboxGroup,
89
88
  itfTableHeader,
90
89
  itfButton,
@@ -106,6 +105,8 @@ class itfTable2 extends Vue {
106
105
  @Prop(Boolean) showGrouping;
107
106
  @Prop(Boolean) showSummary;
108
107
  @Prop(Boolean) noHeader;
108
+ @Prop(Boolean) noColumnMenu;
109
+ @Prop(Boolean) noSelectAll;
109
110
 
110
111
  state = {
111
112
  selectedIds: [],
@@ -126,7 +127,10 @@ class itfTable2 extends Vue {
126
127
  for (const column of list) {
127
128
  const stateColumn = state.columns.find(i => i.property === column.property);
128
129
  if (stateColumn) {
129
- Object.assign(stateColumn, column);
130
+ Object.assign(stateColumn, {
131
+ ...column,
132
+ width: stateColumn.width
133
+ });
130
134
  } else {
131
135
  state.columns.push(column);
132
136
  }
@@ -18,10 +18,10 @@
18
18
  </div>
19
19
  </div>
20
20
  <div class="indicator sticky">
21
- <div class="fill on-rest table-view-row-count">
22
- <!-- <span>{{ item[idProperty] }}</span>-->
21
+ <div class="fill table-view-row-count" :class="{'on-rest': !noSelectAll}">
22
+ <span>{{ item[idProperty] }}</span>
23
23
  </div>
24
- <div class="fill on-hover">
24
+ <div v-if="!noSelectAll" class="fill on-hover">
25
25
  <itf-checkbox :value="item[idProperty]" />
26
26
  </div>
27
27
  </div>
@@ -30,22 +30,27 @@
30
30
  <div
31
31
  v-if="column.visible !== false"
32
32
  :data-column="k"
33
- :style="`width: ${column.width}px; left: ${column.left}px;`"
34
- :class="{'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'flex-grow-1': column.grow}"
33
+ :style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`"
34
+ :class="{'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'flex-grow-1': column.grow, 'px-2': !column.editable, 'p-1': column.editable}"
35
35
  class="table-view-item-value d-flex h-100 align-items-stretch">
36
- <slot :name="`column.${column.name}`" :item="item" :column="column">
36
+ <slot :name="`column.${column.property}`" :item="item" :column="column">
37
37
  <template v-if="column.editable">
38
- <slot :name="`edit.${column.type}`" :value="getValue(item, column)" :item="item" :column="column">
39
- <div class="px-1 py-1 w-100">
40
- <itf-text-field v-if="column.type === 'text'" :value="getValue(item, column)" @input="updateValue(item, $event, n)" />
41
- <itf-textarea autogrow v-else-if="column.type === 'textarea'" :value="getValue(item, column)" @input="updateValue(item, $event)" />
42
- <itf-money-field v-else-if="column.type === 'money'" no-currency-sign currency-disabled :currency-select="false" :value="getValue(item, column)" @input="updateValue(item, $event)" />
43
- </div>
38
+ <slot :name="`edit.${column.type}`" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)" :item="item" :column="column">
39
+ <itf-text-field class="w-100" v-if="column.type === 'text'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
40
+ <itf-hours-field
41
+ class="w-100"
42
+ placeholder="0h 0m"
43
+ v-else-if="column.type === 'time'"
44
+ :hours="getValue(item, column)"
45
+ @update:hours="updateValue(item, $event, n, column)"
46
+ />
47
+ <itf-textarea class="w-100" :rows="2" autogrow v-else-if="column.type === 'textarea'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
48
+ <itf-money-field class="w-100" v-else-if="column.type === 'money'" no-currency-sign currency-disabled :currency-select="false" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
44
49
  </slot>
45
50
  </template>
46
51
  <template v-else>
47
52
  <slot :name="`format.${column.type}`" :value="getValue(item, column)" :item="item" :column="column">
48
- <div class="px-2 w-100">{{getValue(item, column)}}</div>
53
+ {{getValue(item, column)}}
49
54
  </slot>
50
55
  </template>
51
56
  </slot>
@@ -59,6 +64,19 @@
59
64
  </div>
60
65
  </div>
61
66
  </div>
67
+
68
+ <div v-if="!rows.length" data-test="table-no-results" class="table-view-item">
69
+ <div class="table-row-template">
70
+ <div accept-group="items" class="table-view-body-space"></div>
71
+ <div class="shadow-area"></div>
72
+ <div class="indicator sticky"></div>
73
+ <div class="table-item-inner">
74
+ <div class="table-view-item-value w-100 align-items-center p-3">
75
+ {{$t('components.table.noResults')}}
76
+ </div>
77
+ </div>
78
+ </div>
79
+ </div>
62
80
  </div>
63
81
  </template>
64
82
  <style lang="scss">
@@ -82,7 +100,6 @@
82
100
  align-items: stretch;
83
101
  display: flex;
84
102
  position: relative;
85
- line-height: var(--itf-table-line-height);
86
103
  min-width: var(--itf-table-min-width);
87
104
 
88
105
  &.highlight-drop-column {
@@ -212,11 +229,13 @@
212
229
  <script>
213
230
  import { Vue, Component, Prop } from 'vue-property-decorator';
214
231
  import get from 'lodash/get';
232
+ import set from 'lodash/set';
215
233
  // import { RecycleScroller } from 'vue-virtual-scroller'
216
234
  import itfCheckbox from '../checkbox/Checkbox.vue';
217
235
  import itfTextField from '../text-field/TextField.vue';
218
236
  import itfMoneyField from '../text-field/MoneyField.vue';
219
237
  import itfTextarea from '../text-field/Textarea.vue';
238
+ import itfHoursField from '../text-field/HoursField.vue';
220
239
  // import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';
221
240
 
222
241
  export default @Component({
@@ -224,6 +243,7 @@ export default @Component({
224
243
  components: {
225
244
  itfCheckbox,
226
245
  itfMoneyField,
246
+ itfHoursField,
227
247
  itfTextarea,
228
248
  itfTextField,
229
249
  // RecycleScroller
@@ -234,6 +254,7 @@ class itfTableBody extends Vue {
234
254
  @Prop() rows;
235
255
  @Prop() idProperty;
236
256
  @Prop(Boolean) showAddColumn;
257
+ @Prop(Boolean) noSelectAll;
237
258
 
238
259
  getValue(item, column) {
239
260
  return get(item, column.property);
@@ -247,8 +268,10 @@ class itfTableBody extends Vue {
247
268
  return this.columns.findIndex((column) => column.lastPinned);
248
269
  }
249
270
 
250
- updateValue(item, value, index) {
251
- this.$emit('update', { index, item, value });
271
+ updateValue(item, value, index, column) {
272
+ const newItem = { ...item };
273
+ set(newItem, column.property, value);
274
+ this.$emit('update', { index, item, value: newItem });
252
275
  }
253
276
  }
254
277
  </script>
@@ -42,6 +42,8 @@
42
42
  :show-add-column="showAddColumn"
43
43
  :rows="rows"
44
44
  :schema="schema"
45
+ :no-column-menu="noColumnMenu"
46
+ :no-select-all="noSelectAll"
45
47
  :selected-ids="selectedIds"
46
48
  @update:selectedIds="$emit('update:selectedIds', $event)"
47
49
  @update:columns="$emit('update:columns', $event)"
@@ -56,6 +58,7 @@
56
58
  :id-property="idProperty"
57
59
  :rows="rows"
58
60
  :columns="visibleColumns"
61
+ :no-select-all="noSelectAll"
59
62
  :show-add-column="showAddColumn">
60
63
  <template v-for="(_, name) in $slots" #[name]="slotData">
61
64
  <slot :name="name" v-bind="slotData || {}"/>
@@ -80,7 +83,7 @@
80
83
  </div>
81
84
 
82
85
  <!-- Групування -->
83
- <div v-if="isShowTable && showSummary" class="table-row-template d-flex align-items-stretch table-summary">
86
+ <div v-if="isShowTable && showSummary" class="table-row-template d-flex align-items-stretch table-summary" :class="{'table-summary-persist': persistSummary}">
84
87
  <div class="shadow-area"></div>
85
88
 
86
89
  <div class="table-summary-columns d-flex tw-flex-row align-items-center">
@@ -88,51 +91,27 @@
88
91
  v-for="(column, n) in visibleColumns"
89
92
  :key="n"
90
93
  :data-column="n"
91
- class="table-summary-column position-relative line-overflow"
92
- :style="`width: ${column.width}px;`">
93
- <itf-dropdown text>
94
+ class="position-relative line-overflow"
95
+ :style="`width: ${column.width}px; max-width: ${column.width}px;`">
96
+ <itf-dropdown append-to-context text right @open="persistSummary = true" @close="persistSummary = false">
94
97
  <template #button>
95
98
  <span data-test="summary-column" class="invisible-summary d-flex align-items-center justify-content-end flex-auto">
96
- <span class="summary-placeholder align-items-center justify-content-center">
97
- Summary
99
+ <span v-if="column.calculate === 'none' || !column.calculate" class="table-summary-column summary-placeholder align-items-center justify-content-center">
100
+ {{$t('components.table.calculate')}}
98
101
  <itf-icon name="chevron_down" />
99
102
  </span>
103
+ <span v-else>
104
+ <span class="summary-text text-uppercase pe-2">{{getCalculateMethodTitle(column.calculate)}}</span>
105
+ <span>{{getCalculateMethodValue(column.calculate, column)}}</span>
106
+ </span>
100
107
  </span>
101
108
  </template>
102
109
 
103
- <ul class="dropdown-menu show ps-0" aria-labelledby="dropdownMenuOffset">
104
- <li v-if="column.sortable">
105
- <a class="dropdown-item d-flex align-items-center" href="javascript:;">
106
- <itf-icon name="arrow_up" :size="16" class="me-1" />
107
- Sort By Asc
108
- </a>
109
- </li>
110
- <li v-if="column.sortable">
111
- <a class="dropdown-item d-flex align-items-center" href="javascript:;">
112
- <itf-icon name="arrow_down" :size="16" class="me-1" />
113
- Sort By Desc
114
- </a>
115
- </li>
116
- <li v-if="column.groupable">
117
- <a class="dropdown-item d-flex align-items-center" href="javascript:;">
118
- <itf-icon name="episodes" :size="16" class="me-1" />
119
- Group By
120
- </a>
121
- </li>
122
- <li>
123
- <a class="dropdown-item d-flex align-items-center" href="javascript:;" @click="togglePinned(n)">
124
- <itf-icon :name="column.pinned ? 'checkbox_checked' : 'checkbox_empty'" :size="16" class="me-1" />
125
- <span v-if="column.pinned">Unpin Column</span>
126
- <span v-else>Pin Column</span>
127
- </a>
128
- </li>
129
- <li>
130
- <a class="dropdown-item d-flex align-items-center" href="javascript:;" @click="hideColumn(n)">
131
- <itf-icon name="eye_no" :size="16" class="me-1" />
132
- Hide
133
- </a>
134
- </li>
135
- </ul>
110
+ <div v-for="(method, m) in calculateMethods" :key="method.id">
111
+ <a class="dropdown-item d-flex align-items-center" href="javascript:;" @click="selectSummary(method, n)">
112
+ {{method.title}}
113
+ </a>
114
+ </div>
136
115
  </itf-dropdown>
137
116
  </span>
138
117
  </div>
@@ -290,16 +269,22 @@
290
269
  opacity: 0.05;
291
270
  font-size: .85rem;
292
271
  padding-right: .25rem;
293
-
294
- &:hover {
295
- opacity: 1;
296
- }
272
+ }
273
+ .summary-text {
274
+ color: var(--bs-tertiary-color);
275
+ }
276
+ &.table-summary-persist .table-summary-column,
277
+ &:hover .table-summary-column {
278
+ opacity: 1;
297
279
  }
298
280
  }
299
281
  }
300
282
  </style>
301
283
  <script>
284
+ import get from 'lodash/get';
302
285
  import sortBy from 'lodash/sortBy';
286
+ import uniq from "lodash/uniq";
287
+ import round from "lodash/round";
303
288
  import {Vue, Component, Prop, Watch} from 'vue-property-decorator';
304
289
  import itfDropdown from '../dropdown/Dropdown.vue';
305
290
  import itfButton from '../button/Button.vue';
@@ -308,6 +293,11 @@ import itfTableBody from './TableBody.vue';
308
293
  import itfTableHeader from './TableHeader.vue';
309
294
  import Sticky from "./sticky";
310
295
 
296
+ function getNumber(item, prop) {
297
+ const num = Number(get(item, prop));
298
+ return Number.isNaN(num) ? 0 : num;
299
+ }
300
+
311
301
  export default @Component({
312
302
  name: 'itfTableGroup',
313
303
  components: {
@@ -331,10 +321,13 @@ class itfTableGroup extends Vue {
331
321
  @Prop(Boolean) columnResizing;
332
322
  @Prop(Boolean) showAddColumn;
333
323
  @Prop(Boolean) showHeader;
324
+ @Prop(Boolean) noColumnMenu;
325
+ @Prop(Boolean) noSelectAll;
334
326
  @Prop({type: String, default: function() { return this.$t('components.new'); } }) newLabel;
335
327
  @Prop({type: Object, default: () => ({})}) schema;
336
328
 
337
329
  isShowTable = true;
330
+ persistSummary = false;
338
331
 
339
332
  get visibleColumns() {
340
333
  let list = this.columns;
@@ -369,7 +362,47 @@ class itfTableGroup extends Vue {
369
362
  wrap: true,
370
363
  stickyClass: 'sticky',
371
364
  });
372
- console.info(this.sticky);
365
+ }
366
+
367
+ selectSummary(method, index) {
368
+ const columns = [...this.columns];
369
+ columns[index].calculate = method.id;
370
+ this.$emit('update:columns', columns);
371
+ }
372
+
373
+ get calculateMethods() {
374
+ return [
375
+ { id: 'none', title: this.$t('components.table.calculateNone') },
376
+ { id: 'total', title: this.$t('components.table.calculateTotal'), summary: 'Total', func: (rows, column) => rows.reduce((acc, row) => acc + (getNumber(row, column.property)), 0) },
377
+ { id: 'average', title: this.$t('components.table.calculateAverage'), summary: 'Average', func: (rows, column) => {
378
+ const sum = rows.reduce((acc, row) => acc + (getNumber(row, column.property)), 0);
379
+ return round(sum / rows.length, 3);
380
+ } },
381
+ { id: 'min', title: this.$t('components.table.calculateMin'), summary: 'Min', func: (rows, column) => Math.min(...rows.map(row => getNumber(row, column.property))) },
382
+ { id: 'max', title: this.$t('components.table.calculateMax'), summary: 'Max', func: (rows, column) => Math.max(...rows.map(row => getNumber(row, column.property))) },
383
+ { id: 'countAll', title: this.$t('components.table.calculateCountAll'), summary: 'Count', func: (rows) => rows.length },
384
+ { id: 'countValues', title: this.$t('components.table.calculateCountValues'), summary: 'Values', func: (rows, column) => rows.filter(row => !!get(row, column.property)).length },
385
+ { id: 'countUniqueValues', title: this.$t('components.table.calculateCountUniqueValues'), summary: 'Unique', func: (rows, column) => uniq(rows.filter(row => !!get(row, column.property))).length },
386
+ { id: 'countEmpty', title: this.$t('components.table.calculateCountEmpty'), summary: 'Empty', func: (rows, column) => rows.filter(row => !get(row, column.property)).length },
387
+ { id: 'countNotEmpty', title: this.$t('components.table.calculateCountNotEmpty'), summary: 'Not Empty', func: (rows, column) => rows.filter(row => !!get(row, column.property)).length },
388
+ { id: 'percentEmpty', title: this.$t('components.table.calculatePercentEmpty'), summary: 'Empty', func: (rows, column) => {
389
+ const empty = rows.filter(row => !get(row, column.property)).length;
390
+ return round(empty / rows.length * 100, 3) + '%';
391
+ } },
392
+ { id: 'percentNotEmpty', title: this.$t('components.table.calculatePercentNotEmpty'), summary: 'Not Empty', func: (rows, column) => {
393
+ const notEmpty = rows.filter(row => !!get(row, column.property)).length;
394
+ return round(notEmpty / rows.length * 100, 3) + '%';
395
+ } },
396
+ ];
397
+ }
398
+
399
+ getCalculateMethodTitle(methodName) {
400
+ return this.calculateMethods.find(method => method.id === methodName)?.summary;
401
+ }
402
+
403
+ getCalculateMethodValue(methodName, column) {
404
+ const method = this.calculateMethods.find(method => method.id === methodName);
405
+ return method?.func ? method.func(this.rows, column) : '';
373
406
  }
374
407
  }
375
408
  </script>
@@ -5,7 +5,7 @@
5
5
  <div accept-group="items" class="table-view-body-space" v-dropzone="{ payload: 0 }"></div>
6
6
  <div class="shadow-area"></div>
7
7
  <div class="table-view-header-value reserved sticky">
8
- <itf-checkbox v-if="visibleHeader" ungrouped value="all" v-model="selectAll" ref="selectAll" />
8
+ <itf-checkbox v-if="visibleHeader && !noSelectAll" ungrouped value="all" v-model="selectAll" ref="selectAll" />
9
9
  </div>
10
10
 
11
11
  <template v-for="(column, n) in visibleAttributes">
@@ -17,7 +17,7 @@
17
17
  :data-id="column.Id"
18
18
  :class="{'sticky': column.pinned, 'last-sticky-column': n === lastPinnedIndex, 'flex-grow-1': column.grow, [`justify-content-${column.align || 'start'}`]: true}"
19
19
  class="table-view-header-value"
20
- :style="`width: ${column.width}px; left: ${column.left}px;`">
20
+ :style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`">
21
21
  <!-- Не треба видаляти колонки, бо вони потрібні для збереження ширини -->
22
22
  <div v-if="visibleHeader" accept-group="tablecolumns"
23
23
  class="table-view-header-space"
@@ -31,7 +31,7 @@
31
31
  @drop="reorderColumns"
32
32
  v-drag-handle
33
33
  v-draggable="{ handle: true, payload: { index: n, item: column }, mirror: {yAxis:false} }">
34
- <itf-dropdown text append-to-body shadow ref="dropdown" class="w-100">
34
+ <itf-dropdown text append-to-body shadow ref="dropdown" class="w-100" :disabled="noColumnMenu">
35
35
  <template #button>
36
36
  <span :title="column.title[locale] || column.title['en_US']">
37
37
  <span v-if="column.icon" :class="column.icon"></span>
@@ -43,32 +43,32 @@
43
43
  <div v-if="column.sortable">
44
44
  <a class="dropdown-item d-flex align-items-center" href="javascript:;">
45
45
  <itf-icon name="arrow_up" :size="16" class="me-1" />
46
- Sort ascending
46
+ {{$t('components.table.sortAscending')}}
47
47
  </a>
48
48
  </div>
49
49
  <div v-if="column.sortable">
50
50
  <a class="dropdown-item d-flex align-items-center" href="javascript:;">
51
51
  <itf-icon name="arrow_down" :size="16" class="me-1" />
52
- Sort descending
52
+ {{$t('components.table.sortAscending')}}
53
53
  </a>
54
54
  </div>
55
55
  <div v-if="column.groupable">
56
56
  <a class="dropdown-item d-flex align-items-center" href="javascript:;">
57
57
  <itf-icon name="episodes" :size="16" class="me-1" />
58
- Group By
58
+ {{$t('components.table.groupBy')}}
59
59
  </a>
60
60
  </div>
61
61
  <div>
62
62
  <a class="dropdown-item d-flex align-items-center" href="javascript:;" @click="togglePinned(n)">
63
63
  <itf-icon :name="column.pinned ? 'checkbox_checked' : 'checkbox_empty'" :size="16" class="me-1" />
64
- <span v-if="column.pinned">Unfreeze column</span>
65
- <span v-else>Freeze up to column</span>
64
+ <span v-if="column.pinned">{{$t('components.table.unfreezeColumn')}}</span>
65
+ <span v-else>{{$t('components.table.freezeColumn')}}</span>
66
66
  </a>
67
67
  </div>
68
- <div>
68
+ <div v-if="showAddColumn">
69
69
  <a class="dropdown-item d-flex align-items-center" href="javascript:;" @click="hideColumn(n)">
70
70
  <itf-icon name="eye_no" :size="16" class="me-1" />
71
- Hide in view
71
+ {{$t('components.table.hideColumn')}}
72
72
  </a>
73
73
  </div>
74
74
  </itf-dropdown>
@@ -92,7 +92,7 @@
92
92
 
93
93
  <itf-sortable :value="sortedColumns" @input="onSortColumns">
94
94
  <template v-for="(column, k) in sortedColumns">
95
- <div :key="`column${k}`" class="d-flex align-items-center justify-content-between px-2 py-1">
95
+ <div :key="`column${k}`" class="d-flex align-items-center justify-content-between" :class="{'px-2 py-1': column.visible !== false}">
96
96
  <template v-if="column.visible !== false">
97
97
  <div class="d-flex justify-content-between flex-grow-1">
98
98
  <div>
@@ -111,7 +111,7 @@
111
111
  </itf-sortable>
112
112
 
113
113
  <div v-if="invisibleColumns.length">
114
- <div class="dropdown-header">Add column</div>
114
+ <div class="dropdown-header">{{$t('components.table.addColumn')}}</div>
115
115
  <template v-for="(column, k) in invisibleColumns">
116
116
  <a href="" @click.prevent="addColumn(column)" :key="`inv-column${k}`" class="dropdown-item d-flex align-items-center justify-content-between px-2 py-1">
117
117
  <div>
@@ -321,6 +321,8 @@ class itfTableHeader extends Vue {
321
321
  @Prop(Boolean) columnResizing;
322
322
  @Prop(Boolean) showAddColumn;
323
323
  @Prop(Boolean) visibleHeader;
324
+ @Prop(Boolean) noColumnMenu;
325
+ @Prop(Boolean) noSelectAll;
324
326
 
325
327
  @Watch('selectedIds')
326
328
  @Watch('rows')
@@ -433,6 +435,7 @@ class itfTableHeader extends Vue {
433
435
  newWidth = Math.max(columnWidth + delta, 100);
434
436
  columns.forEach((column) => {
435
437
  column.style.width = `${newWidth}px`;
438
+ column.style['max-width'] = `${newWidth}px`;
436
439
  });
437
440
  };
438
441
  const mouseUpHandler = () => {
@@ -324,7 +324,9 @@ storiesOf('Common', module)
324
324
  @new="onAdd"
325
325
  state-name="test"
326
326
  :schema="schema"
327
- :columns.sync="columns2" :rows="list2" column-sorting column-resizing show-add-column show-grouping @add-column="onAdd">
327
+ :columns.sync="columns2" :rows="list2"
328
+ show-summary
329
+ column-sorting column-resizing show-add-column show-grouping @add-column="onAdd">
328
330
  <template #format.employee="{ item }">
329
331
  {{item.EmployeeId}}
330
332
  </template>
@@ -1,16 +1,16 @@
1
1
  <template>
2
2
  <div class="itf-money-field" :class="{'currency-arrow': !currencyDisabled, 'currency-select': currencySelect}">
3
- <div :style="`--itf-money-field-padding-left: ${noCurrencySign ? 0 : selectedCurrencySymbol.length * 0.6 + 1}rem`">
3
+ <div class="input-group h-100" :style="`--itf-money-field-padding-left: ${noCurrencySign ? 1 : selectedCurrencySymbol.length * 0.6 + 1}rem`">
4
4
  <span class="itf-money-field__prepend" v-if="!noCurrencySign">{{ selectedCurrencySymbol }}</span>
5
5
  <i-mask-component
6
- ref="input"
7
- v-bind="mask"
8
- class="form-control"
9
- :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
10
- @input="setValue"
11
- :value="maskedValue"
12
- :unmask="false"
13
- :disabled="disabled"
6
+ ref="input"
7
+ v-bind="mask"
8
+ class="form-control"
9
+ :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
10
+ @input="setValue"
11
+ :value="maskedValue"
12
+ :unmask="false"
13
+ :disabled="disabled"
14
14
  />
15
15
  </div>
16
16
 
package/src/locales/en.js CHANGED
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable comma-dangle */
2
2
  module.exports = {
3
- new: 'New',
4
3
  today: 'Today',
5
4
  tomorrow: 'Tomorrow',
6
5
  inAWeek: 'In a week',
@@ -97,5 +96,29 @@ module.exports = {
97
96
  },
98
97
  copyToClipboard: {
99
98
  copyingToClipboardWasSuccessful: 'Copying to clipboard was successful',
99
+ },
100
+ table: {
101
+ new: 'New',
102
+ noResults: 'No items',
103
+ sortAscending: 'Sort ascending',
104
+ sortDescending: 'Sort descending',
105
+ groupBy: 'Group by',
106
+ hideColumn: 'Hide in view',
107
+ freezeColumn: 'Freeze up to column',
108
+ unfreezeColumn: 'Unfreeze column',
109
+ addColumn: 'Add column',
110
+ calculate: 'Calculate',
111
+ calculateNone: 'None',
112
+ calculateTotal: 'Total',
113
+ calculateCountAll: 'Count all',
114
+ calculateAverage: 'Average',
115
+ calculateMin: 'Min',
116
+ calculateMax: 'Max',
117
+ calculateCountValues: 'Count values',
118
+ calculateCountUniqueValues: 'Count unique values',
119
+ calculateCountEmpty: 'Count empty',
120
+ calculateCountNotEmpty: 'Count not empty',
121
+ calculatePercentEmpty: 'Percent empty',
122
+ calculatePercentNotEmpty: 'Percent not empty',
100
123
  }
101
124
  };
package/src/locales/uk.js CHANGED
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable comma-dangle */
2
2
  module.exports = {
3
- new: 'Додати',
4
3
  today: 'Сьогодні',
5
4
  tomorrow: 'Завтра',
6
5
  inAWeek: 'Через тиждень',
@@ -97,5 +96,29 @@ module.exports = {
97
96
  },
98
97
  copyToClipboard: {
99
98
  copyingToClipboardWasSuccessful: 'Скопійовано в буфер',
99
+ },
100
+ table: {
101
+ new: 'Додати',
102
+ noResults: 'Немає записів',
103
+ sortAscending: 'Сортувати за зростанням',
104
+ sortDescending: 'Сортувати за спаданням',
105
+ groupBy: 'Групувати',
106
+ hideColumn: 'Приховати колонку',
107
+ freezeColumn: 'Закріпити колонку',
108
+ unfreezeColumn: 'Відкріпити колонку',
109
+ addColumn: 'Додати колонку',
110
+ calculate: 'Обчислення',
111
+ calculateNone: 'Немає',
112
+ calculateTotal: 'Всього',
113
+ calculateCountAll: 'Кількість',
114
+ calculateAverage: 'Середнє',
115
+ calculateMin: 'Мінімум',
116
+ calculateMax: 'Максимум',
117
+ calculateCountValues: 'Кількість значень',
118
+ calculateCountUniqueValues: 'Кількість унікальних значень',
119
+ calculateCountEmpty: 'Кількість порожніх',
120
+ calculateCountNotEmpty: 'Кількість не порожніх',
121
+ calculatePercentEmpty: 'Відсоток порожніх',
122
+ calculatePercentNotEmpty: 'Відсоток не порожніх',
100
123
  }
101
124
  };
@@ -1,30 +0,0 @@
1
- <div class="notion-overlay-container notion-default-overlay-container"
2
- style="position: fixed; inset: 0px; z-index: 999; pointer-events: none; overflow: hidden;">
3
- <div style="position: relative; z-index: 0;"></div>
4
- <div data-overlay="true" style="pointer-events: auto; position: relative; z-index: 0;">
5
- <div>
6
- <div style="position: fixed; top: 0px; left: 0px; width: 100vw; height: 100vh;"></div>
7
- <div style="position: fixed; left: 347px; top: 463.398px; pointer-events: none;">
8
- <div style="width: 280px; height: 0px;"></div>
9
- <div style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start;">
10
- <div style="position: relative; top: 100%; pointer-events: auto;">
11
- <div style="display: flex; align-items: center; position: relative; flex-direction: column-reverse; transform-origin: 0% top; left: 0px; top: 0px;">
12
- <div role="dialog"
13
- style="border-radius: 6px; background: white; backdrop-filter: none; position: relative; max-width: calc(-24px + 100vw); box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px; overflow: visible; width: 280px; min-height: 34px; max-height: 634px; display: flex; flex-direction: column;">
14
- <div style="display: flex; flex-direction: column; overflow-y: auto; flex-grow: 1; height: 100%;">
15
- <div style="padding: 6px 9px; font-size: 14px; min-height: 34px; display: flex; height: 100%; flex-direction: column; justify-content: space-between; flex-grow: 1; font-weight: 500;">
16
- <div class="notranslate" spellcheck="true" placeholder=" "
17
- data-content-editable-leaf="true" contenteditable="true"
18
- style="max-width: 100%; width: 100%; white-space: pre-wrap; word-break: break-word; caret-color: rgb(55, 53, 47);">
19
- d
20
- </div>
21
- </div>
22
- </div>
23
- </div>
24
- </div>
25
- </div>
26
- </div>
27
- </div>
28
- </div>
29
- </div>
30
- </div>