@itfin/components 1.4.40 → 1.5.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.
Files changed (187) hide show
  1. package/package.json +17 -20
  2. package/src/ITFSettings.js +6 -0
  3. package/src/assets/scss/components/_button.scss +118 -0
  4. package/src/assets/scss/components/_text-field.scss +22 -8
  5. package/src/components/alert/AlertBanner.vue +75 -0
  6. package/src/components/app/App.vue +6 -3
  7. package/src/components/button/Button.vue +3 -1
  8. package/src/components/button/NativeButton.js +4 -0
  9. package/src/components/button/index.stories.js +2 -2
  10. package/src/components/checkbox/Checkbox.vue +2 -1
  11. package/src/components/checkbox/RadioBox.vue +13 -7
  12. package/src/components/copyToClipboard/CopyToClipboard.vue +4 -1
  13. package/src/components/customize/PropertiesList.vue +0 -2
  14. package/src/components/customize/PropertiesPopupMenu.vue +1 -1
  15. package/src/components/customize/PropertyItem.vue +6 -24
  16. package/src/components/datepicker/DatePicker.vue +3 -1
  17. package/src/components/datepicker/DatePickerInline.vue +2 -2
  18. package/src/components/datepicker/DateRangePickerInline.vue +6 -1
  19. package/src/components/dropdown/Dropdown.vue +1 -1
  20. package/src/components/dropdown/DropdownMenu.vue +1 -1
  21. package/src/components/editable/EditButton.vue +1 -1
  22. package/src/components/editor/plugins.js +1012 -0
  23. package/src/components/filter/FilterBadge.vue +17 -3
  24. package/src/components/filter/FilterFacetsList.vue +67 -13
  25. package/src/components/filter/FilterPanel.vue +8 -21
  26. package/src/components/filter/NewFilter.vue +305 -0
  27. package/src/components/form/Label.vue +5 -5
  28. package/src/components/icon/components/nomi-ai-alt.vue +5 -0
  29. package/src/components/icon/components/nomi-bell.vue +5 -0
  30. package/src/components/icon/components/nomi-budget.vue +4 -0
  31. package/src/components/icon/components/nomi-calendar-payment.vue +10 -0
  32. package/src/components/icon/components/nomi-card-plus.vue +1 -0
  33. package/src/components/icon/components/nomi-cash-provider.vue +9 -0
  34. package/src/components/icon/components/nomi-category-edit.vue +5 -0
  35. package/src/components/icon/components/nomi-delta.vue +7 -0
  36. package/src/components/icon/components/nomi-exit-right.vue +4 -0
  37. package/src/components/icon/components/nomi-help.vue +2 -3
  38. package/src/components/icon/components/nomi-lock.vue +1 -1
  39. package/src/components/icon/components/nomi-project.vue +2 -2
  40. package/src/components/icon/components/nomi-refresh-off.vue +4 -0
  41. package/src/components/icon/components/nomi-refresh.vue +4 -0
  42. package/src/components/icon/components/nomi-scissors.vue +1 -1
  43. package/src/components/icon/components/nomi-start.vue +28 -0
  44. package/src/components/icon/components/nomi-table-view.vue +1 -4
  45. package/src/components/icon/components/nomi-transactions-delete.vue +5 -0
  46. package/src/components/icon/components/nomi-type-array.vue +6 -0
  47. package/src/components/icon/components/nomi-type-boolean.vue +5 -0
  48. package/src/components/icon/components/nomi-type-date.vue +4 -0
  49. package/src/components/icon/components/nomi-type-null.vue +4 -0
  50. package/src/components/icon/components/nomi-type-number.vue +4 -0
  51. package/src/components/icon/components/nomi-type-object.vue +4 -0
  52. package/src/components/icon/components/nomi-type-string.vue +4 -0
  53. package/src/components/icon/components/nomi-unarchive.vue +17 -0
  54. package/src/components/icon/components/nomi-unlink.vue +10 -0
  55. package/src/components/icon/components/nomi-user.vue +3 -3
  56. package/src/components/icon/components/nomi-warning-triangle.vue +6 -0
  57. package/src/components/icon/components/nomi-warning_triangle_filled.vue +6 -0
  58. package/src/components/icon/convert-icons.js +3 -0
  59. package/src/components/icon/icons.js +390 -312
  60. package/src/components/icon/new-icons/ai-alt.svg +4 -0
  61. package/src/components/icon/new-icons/arrow-right-alt.svg +3 -0
  62. package/src/components/icon/new-icons/arrow-right.svg +3 -0
  63. package/src/components/icon/new-icons/arrow_left.svg +3 -0
  64. package/src/components/icon/new-icons/automation.svg +4 -0
  65. package/src/components/icon/new-icons/balance.svg +3 -0
  66. package/src/components/icon/new-icons/balance_turnover.svg +4 -0
  67. package/src/components/icon/new-icons/bar-horizontal.svg +6 -0
  68. package/src/components/icon/new-icons/bell.svg +4 -0
  69. package/src/components/icon/new-icons/calendar-payment.svg +9 -0
  70. package/src/components/icon/new-icons/card-plus.svg +1 -0
  71. package/src/components/icon/new-icons/cash-provider.svg +8 -0
  72. package/src/components/icon/new-icons/cash-repeat.svg +5 -0
  73. package/src/components/icon/new-icons/cash.svg +3 -0
  74. package/src/components/icon/new-icons/cashflow.svg +3 -0
  75. package/src/components/icon/new-icons/category-edit.svg +4 -0
  76. package/src/components/icon/new-icons/category.svg +4 -0
  77. package/src/components/icon/new-icons/category_alt.svg +3 -0
  78. package/src/components/icon/new-icons/chart-bars.svg +5 -0
  79. package/src/components/icon/new-icons/chart-donut.svg +3 -0
  80. package/src/components/icon/new-icons/chart-funnel.svg +5 -0
  81. package/src/components/icon/new-icons/chart-kpi.svg +7 -0
  82. package/src/components/icon/new-icons/chart-line.svg +4 -0
  83. package/src/components/icon/new-icons/chart-lines.svg +5 -0
  84. package/src/components/icon/new-icons/check-alt.svg +3 -0
  85. package/src/components/icon/new-icons/check.svg +3 -0
  86. package/src/components/icon/new-icons/chevron-down.svg +3 -0
  87. package/src/components/icon/new-icons/chevron-left.svg +3 -0
  88. package/src/components/icon/new-icons/chevron-right.svg +3 -0
  89. package/src/components/icon/new-icons/chevron-up.svg +3 -0
  90. package/src/components/icon/new-icons/collapse.svg +6 -0
  91. package/src/components/icon/new-icons/control-panel.svg +7 -0
  92. package/src/components/icon/new-icons/credit.svg +3 -0
  93. package/src/components/icon/new-icons/currencies.svg +3 -0
  94. package/src/components/icon/new-icons/debt.svg +3 -0
  95. package/src/components/icon/new-icons/delta.svg +6 -0
  96. package/src/components/icon/new-icons/demo.svg +6 -0
  97. package/src/components/icon/new-icons/dev.svg +3 -0
  98. package/src/components/icon/new-icons/dots.svg +5 -0
  99. package/src/components/icon/new-icons/duplicate.svg +4 -0
  100. package/src/components/icon/new-icons/exit-right.svg +3 -0
  101. package/src/components/icon/new-icons/export.svg +3 -0
  102. package/src/components/icon/new-icons/file.svg +3 -0
  103. package/src/components/icon/new-icons/folder.svg +3 -0
  104. package/src/components/icon/new-icons/goods-turnover.svg +3 -0
  105. package/src/components/icon/new-icons/goods.svg +4 -0
  106. package/src/components/icon/new-icons/help-alt.svg +3 -0
  107. package/src/components/icon/new-icons/help.svg +2 -3
  108. package/src/components/icon/new-icons/history.svg +6 -0
  109. package/src/components/icon/new-icons/integration.svg +3 -0
  110. package/src/components/icon/new-icons/link.svg +5 -0
  111. package/src/components/icon/new-icons/lock.svg +1 -1
  112. package/src/components/icon/new-icons/menu.svg +5 -0
  113. package/src/components/icon/new-icons/minus.svg +3 -0
  114. package/src/components/icon/new-icons/payment_calendar.svg +3 -0
  115. package/src/components/icon/new-icons/pc.svg +3 -0
  116. package/src/components/icon/new-icons/pen-alt.svg +3 -0
  117. package/src/components/icon/new-icons/planFact.svg +4 -0
  118. package/src/components/icon/new-icons/pnl.svg +7 -0
  119. package/src/components/icon/new-icons/project.svg +2 -2
  120. package/src/components/icon/new-icons/project_alt.svg +3 -0
  121. package/src/components/icon/new-icons/project_alt2.svg +3 -0
  122. package/src/components/icon/new-icons/promo.svg +3 -0
  123. package/src/components/icon/new-icons/refresh-off.svg +3 -0
  124. package/src/components/icon/new-icons/refresh.svg +3 -0
  125. package/src/components/icon/new-icons/scissors.svg +1 -1
  126. package/src/components/icon/new-icons/segment.svg +3 -0
  127. package/src/components/icon/new-icons/start.svg +27 -0
  128. package/src/components/icon/new-icons/strongbox.svg +3 -0
  129. package/src/components/icon/new-icons/subscription.svg +3 -0
  130. package/src/components/icon/new-icons/table-view.svg +1 -4
  131. package/src/components/icon/new-icons/time.svg +3 -0
  132. package/src/components/icon/new-icons/transactions_alt.svg +6 -0
  133. package/src/components/icon/new-icons/transactions_delete.svg +4 -0
  134. package/src/components/icon/new-icons/type-array.svg +5 -0
  135. package/src/components/icon/new-icons/type-boolean.svg +4 -0
  136. package/src/components/icon/new-icons/type-date.svg +3 -0
  137. package/src/components/icon/new-icons/type-null.svg +3 -0
  138. package/src/components/icon/new-icons/type-number.svg +3 -0
  139. package/src/components/icon/new-icons/type-object.svg +3 -0
  140. package/src/components/icon/new-icons/type-string.svg +3 -0
  141. package/src/components/icon/new-icons/types.svg +6 -0
  142. package/src/components/icon/new-icons/unarchive.svg +16 -0
  143. package/src/components/icon/new-icons/unlink.svg +9 -0
  144. package/src/components/icon/new-icons/user.svg +3 -3
  145. package/src/components/icon/new-icons/user_plus.svg +10 -0
  146. package/src/components/icon/new-icons/warehouse.svg +3 -0
  147. package/src/components/icon/new-icons/warning_triangle.svg +5 -0
  148. package/src/components/icon/new-icons/warning_triangle_filled.svg +5 -0
  149. package/src/components/kanban/BoardCard.vue +1 -1
  150. package/src/components/kanban/BoardCardTimer.vue +1 -1
  151. package/src/components/modal/DeleteConfirmModal.vue +10 -6
  152. package/src/components/modal/ItemEditor.vue +1 -1
  153. package/src/components/modal/Modal.vue +1 -1
  154. package/src/components/overlay/SensitiveOverlay.vue +2 -4
  155. package/src/components/panels/Panel.vue +110 -23
  156. package/src/components/panels/PanelItemEdit.vue +8 -6
  157. package/src/components/panels/PanelList.vue +164 -40
  158. package/src/components/panels/helpers.ts +41 -13
  159. package/src/components/popover/Popover.vue +105 -22
  160. package/src/components/segmented-control/SegmentedControl.vue +9 -3
  161. package/src/components/sortable/draggable.js +1 -1
  162. package/src/components/table/Table2.vue +68 -67
  163. package/src/components/table/TableBody.vue +17 -22
  164. package/src/components/table/TableGroup.vue +40 -24
  165. package/src/components/table/TableHeader.vue +86 -81
  166. package/src/components/table/TableRowToggle.vue +1 -9
  167. package/src/components/table/TableRows.vue +49 -55
  168. package/src/components/table/mobile.js +4 -0
  169. package/src/components/table/table2.scss +34 -15
  170. package/src/components/text-field/MoneyField.vue +10 -4
  171. package/src/components/text-field/TextField.vue +17 -8
  172. package/src/components/tree/TreeEditor.vue +3 -2
  173. package/src/components/view/View.vue +80 -207
  174. package/src/directives/appendToBody.js +1 -0
  175. package/src/helpers/validators.js +9 -35
  176. package/src/helpers/validators.spec.js +11 -48
  177. package/src/locales/en.js +4 -6
  178. package/src/locales/pl.js +158 -0
  179. package/src/locales/uk.js +6 -7
  180. package/src/components/icon/components/nomi-calendar-view.vue +0 -4
  181. package/src/components/icon/components/nomi-kanban-view.vue +0 -6
  182. package/src/components/icon/components/nomi-list-view.vue +0 -7
  183. package/src/components/icon/components/nomi-table-config.vue +0 -9
  184. package/src/components/icon/new-icons/calendar-view.svg +0 -3
  185. package/src/components/icon/new-icons/kanban-view.svg +0 -5
  186. package/src/components/icon/new-icons/list-view.svg +0 -6
  187. package/src/components/icon/new-icons/table-config.svg +0 -8
@@ -15,14 +15,14 @@
15
15
  <div class="table-row-template d-flex align-items-stretch"
16
16
  style="min-height: var(--group-title-height)">
17
17
  <div class="shadow-area"></div>
18
- <div class="header-wrapper" :class="{'header-additional-column': showAddColumn}" @click.prevent="toggleGroup">
18
+ <div class="header-wrapper" :class="{'header-additional-column': showAddColumn}" @click.prevent="() => toggleGroup(!isShowTable)">
19
19
  <a class="header-content position-sticky d-flex align-items-center">
20
- <itf-button icon small secondary class="collapse-arrow">
20
+ <itf-button squircle icon small secondary class="collapse-arrow">
21
21
  <itf-icon :name="isShowTable ? 'chevron_down' : 'chevron_right'"/>
22
22
  </itf-button>
23
23
  <span class="d-flex align-items-center line-overflow group-header-value text-primary"
24
24
  data-test="group-value-group-label-value">
25
- <slot name="group-title" :rows="rows" :title="title">{{ title }}</slot>
25
+ <slot name="group-title" :rows="rows" :title="title" :collapsed="!isShowTable">{{ title }}</slot>
26
26
  </span>
27
27
  </a>
28
28
  </div>
@@ -39,7 +39,6 @@
39
39
  :show-add-column="showAddColumn"
40
40
  :show-actions="showActions"
41
41
  :id-property="idProperty"
42
- :sort-as-string="sortAsString"
43
42
  :rows="rows"
44
43
  :schema="schema"
45
44
  :editable="editable"
@@ -52,7 +51,14 @@
52
51
  @update:columns="$emit('update:columns', $event)"
53
52
  @filter="$emit('filter', $event)"
54
53
  @add-column="$emit('add-column', $event)"
55
- />
54
+ >
55
+ <template v-for="(_, name) in $slots" #[name]="slotData">
56
+ <slot :name="name" v-bind="slotData || {}"/>
57
+ </template>
58
+ <template v-for="(_, name) in $scopedSlots" #[name]="slotData">
59
+ <slot :name="name" v-bind="slotData || {}"/>
60
+ </template>
61
+ </itf-table-header>
56
62
  </div>
57
63
 
58
64
  <!-- Сама таблиця -->
@@ -62,13 +68,11 @@
62
68
  @row-click="$emit('row-click', $event)"
63
69
  :id-property="idProperty"
64
70
  :subrows-property="subrowsProperty"
65
- :async-subrows-property="asyncSubrowsProperty"
66
71
  :divider-property="dividerProperty"
67
72
  :rows="rows"
68
73
  :editable="editable"
69
74
  :currency="currency"
70
75
  :currencies="currencies"
71
- :sort-as-string="sortAsString"
72
76
  :columns="visibleColumns"
73
77
  :no-select-all="noSelectAll"
74
78
  :selected-ids="selectedIds"
@@ -81,7 +85,6 @@
81
85
  :css-property="cssProperty"
82
86
  :editable-property="editableProperty"
83
87
  :active="active"
84
- @loadChildren="$emit('loadChildren', $event)"
85
88
  @update:expanded-ids="$emit('update:expanded-ids', $event)"
86
89
  >
87
90
  <template v-for="(_, name) in $slots" #[name]="slotData">
@@ -95,11 +98,11 @@
95
98
 
96
99
  <!-- Лінія додати нову -->
97
100
  <div v-if="isShowTable && addNewRows"
98
- class="table-row-template table-row-template__new-row d-flex align-items-stretch">
101
+ class="d-flex align-items-stretch">
99
102
  <div class="shadow-area"></div>
100
103
  <a href="" @click.prevent="$emit('new', title)" data-test="table-add-new-item"
101
104
  class="d-flex align-items-center flex-grow-1 table-add-new-item text-decoration-none">
102
- <span class="d-sticky d-flex align-items-center py-1 px-2 small">
105
+ <span class="d-sticky d-flex align-items-center py-2 px-2">
103
106
  <itf-icon name="plus"/>
104
107
  <span>{{ newLabel }}</span>
105
108
  </span>
@@ -268,20 +271,21 @@
268
271
  min-height: var(--table-small-row-size);
269
272
  }
270
273
 
271
- .table-row-template.table-row-template__new-row {
272
- min-height: 2rem;
273
- }
274
274
  .table-add-new-item {
275
- background-color: var(--itf-table-header-bg);
276
- border-right:var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
277
- border-left:var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
275
+ margin-top: -12px;
278
276
  border-bottom: var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
279
277
  outline: none;
280
278
  border-bottom-left-radius: var(--itf-table-table-border-radius);
281
279
  border-bottom-right-radius: var(--itf-table-table-border-radius);
280
+ border-right: var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
281
+
282
+ > .d-sticky {
283
+ border-left: var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
284
+ border-bottom-left-radius: var(--itf-table-table-border-radius);
285
+ }
282
286
 
283
287
  & > span {
284
- left: calc(var(--shadow-area-width) + 4px);
288
+ left: var(--shadow-area-width);
285
289
  position: sticky;
286
290
  padding-left: var(--shadow-area-width);
287
291
  //border-left: var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
@@ -344,6 +348,7 @@ import itfIcon from '../icon/Icon.vue';
344
348
  import itfTableBody from './TableBody.vue';
345
349
  import itfTableHeader from './TableHeader.vue';
346
350
  import Sticky from "./sticky";
351
+ import { getIsMobileView } from "./mobile";
347
352
 
348
353
  function getNumber(item, prop) {
349
354
  const num = Number(get(item, prop));
@@ -367,7 +372,6 @@ class itfTableGroup extends Vue {
367
372
  @Prop() title;
368
373
  @Prop() idProperty;
369
374
  @Prop() subrowsProperty;
370
- @Prop() asyncSubrowsProperty;
371
375
  @Prop() dividerProperty;
372
376
  @Prop() currency;
373
377
  @Prop() currencies;
@@ -387,7 +391,6 @@ class itfTableGroup extends Vue {
387
391
  @Prop(Boolean) expandedAll;
388
392
  @Prop(Boolean) striped;
389
393
  @Prop(Boolean) stickyHeader;
390
- @Prop(Boolean) sortAsString;
391
394
  @Prop() indicatorWidth;
392
395
  @Prop() shadowWidth;
393
396
  @Prop() cssProperty;
@@ -396,10 +399,14 @@ class itfTableGroup extends Vue {
396
399
  @Prop({type: String, default: function() { return this.$t('components.table.new'); } }) newLabel;
397
400
  @Prop({type: Object, default: () => ({})}) schema;
398
401
  @Prop() expandedIds;
402
+ @Prop() collapsedGroupIds;
399
403
 
400
- isShowTable = true;
401
404
  persistSummary = false;
402
405
 
406
+ get isShowTable() {
407
+ return typeof this.collapsedGroupIds !== 'undefined' ? !this.collapsedGroupIds.includes(this.title) : true;
408
+ }
409
+
403
410
  get visibleColumns() {
404
411
  let list = this.columns;
405
412
  list = sortBy(list, (column) => column.index);
@@ -407,8 +414,8 @@ class itfTableGroup extends Vue {
407
414
  const pinned = list.filter((column) => column.pinned && column.visible !== false);
408
415
  list = list.map((column, index) => {
409
416
  const item = {...column};
410
- item.left = (item.pinned && item.visible !== false) ? left : 0;
411
- left = (item.pinned && item.visible !== false) ? left + column.width : left;
417
+ item.left = (item.pinned && !getIsMobileView() && item.visible !== false) ? left : 0;
418
+ left = (item.pinned && !getIsMobileView() && item.visible !== false) ? left + column.width : left;
412
419
  item.lastPinned = index === pinned.length - 1;
413
420
  return item
414
421
  });
@@ -420,8 +427,17 @@ class itfTableGroup extends Vue {
420
427
  this.$emit('update:columns', columns);
421
428
  }
422
429
 
423
- toggleGroup() {
424
- this.isShowTable = !this.isShowTable;
430
+ toggleGroup(val) {
431
+ let expanded = this.collapsedGroupIds ? [...this.collapsedGroupIds] : [];
432
+ if (!val) {
433
+ if (!expanded.includes(this.title)) {
434
+ expanded.push(this.title);
435
+ }
436
+ } else {
437
+ expanded = expanded.filter(id => id !== this.title);
438
+ }
439
+ console.info(expanded, this.title, val);
440
+ this.$emit('update:collapsed-group-ids', expanded);
425
441
  }
426
442
 
427
443
  get stickyId() {
@@ -4,8 +4,8 @@
4
4
  <div ref="container" class="table-row-template">
5
5
  <div accept-group="items" class="table-view-body-space" v-dropzone="{ payload: 0 }"></div>
6
6
  <div class="shadow-area"></div>
7
- <div v-if="indicatorType !== 'none'" class="table-view-header-value reserved sticky">
8
- <itf-checkbox v-if="indicatorType !== 'none' && visibleHeader && !noSelectAll" ungrouped value="all" v-model="selectAll" ref="selectAll" />
7
+ <div class="table-view-header-value reserved sticky" data-test="table-header-checkbox">
8
+ <itf-checkbox v-if="indicatorType === 'checkbox' && visibleHeader && !noSelectAll" ungrouped value="all" v-model="selectAll" ref="selectAll" />
9
9
  </div>
10
10
 
11
11
  <template v-for="(column, n) in visibleAttributes">
@@ -15,7 +15,7 @@
15
15
  data-test="table-header-column"
16
16
  :data-column="n"
17
17
  :data-id="column.Id"
18
- :class="{'sticky': column.pinned, 'active': sortColumnParams[column.property], 'last-sticky-column': n === lastPinnedIndex, [`justify-content-${column.align || 'start'}`]: true}"
18
+ :class="{'sticky': column.pinned && !getIsMobileView(), 'active': sortColumnParams[column.property], 'last-sticky-column': n === lastPinnedIndex && !getIsMobileView(), [`justify-content-${column.align || 'start'}`]: true}"
19
19
  class="table-view-header-value"
20
20
  :style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`">
21
21
  <!-- Не треба видаляти колонки, бо вони потрібні для збереження ширини -->
@@ -29,87 +29,90 @@
29
29
  <div v-if="visibleHeader" group="tablecolumns"
30
30
  class="table-header"
31
31
  @drop="reorderColumns"
32
- v-draggable="{ dragHandleClass: null, handle: true, payload: { index: n, item: column }, mirror: {yAxis:false} }">
33
- <itf-dropdown text append-to-body shadow ref="dropdown" class="w-100" :disabled="noColumnMenu">
34
- <template #button>
35
- <div class="itf-table2__header-title d-flex w-100 align-items-center" :title="getTitle(column.title)">
36
- <itf-icon class="itf-table2__header-icon" new v-if="column.icon" :name="column.icon"></itf-icon>
37
- <div class="flex-grow-1 w-100 itf-table2__title-container d-flex align-items-center" :class="{'justify-content-end': column.align === 'end'}">
38
- <div class="itf-table2__title text-truncate">
39
- {{getTitle(column.title)}}
40
- <div v-if="column.prefix" class="itf-table2__subtitle text-truncate" :class="{'text-end': column.align === 'end'}" v-text="column.prefix" />
32
+ v-draggable="{ handle: true, payload: { index: n, item: column }, mirror: {yAxis:false} }">
33
+ <div class="d-flex align-items-center gap-1">
34
+ <itf-dropdown text append-to-body shadow ref="dropdown" class="w-100" :disabled="noColumnMenu">
35
+ <template #button>
36
+ <div class="d-flex align-items-start justify-content-between">
37
+ <div class="itf-table2__header-title d-flex w-100 align-items-center" :title="getTitle(column.title)">
38
+ <itf-icon class="itf-table2__header-icon" new v-if="column.icon" :name="column.icon"></itf-icon>
39
+ <div class="flex-grow-1 w-100 itf-table2__title-container d-flex align-items-center" :class="{'justify-content-end': column.align === 'end'}">
40
+ <div class="itf-table2__title text-truncate">{{getTitle(column.title)}}</div>
41
+ <div v-if="column.prefix" class="itf-table2__subtitle text-truncate" v-text="column.prefix" />
42
+ </div>
41
43
  </div>
44
+ <itf-icon v-if="sortColumnParams[column.property]" :name="sortColumnParams[column.property] === 'asc' ? 'sort-asc' : 'sort-desc'" new :size="20" class="ms-1" />
42
45
  </div>
43
- </div>
44
- <itf-icon v-if="sortColumnParams[column.property]" :name="sortColumnParams[column.property] === 'asc' ? 'sort-asc' : 'sort-desc'" new :size="20" class="ms-1" />
45
- </template>
46
- <div class="dropdown-header">
47
- {{$t('components.table.actions')}}
48
- </div>
49
-
50
- <div v-if="column.groupable">
51
- <a class="dropdown-item d-flex align-items-center" href="javascript:;">
52
- <itf-icon name="episodes" :size="16" class="me-1" />
53
- {{$t('components.table.groupBy')}}
54
- </a>
55
- </div>
56
- <div>
57
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="togglePinned(n)">
58
- <itf-icon v-if="column.pinned" name="pin" new />
59
- <itf-icon v-else name="pin" new />
60
-
61
- <span v-if="column.pinned">{{$t('components.table.unfreezeColumn')}}</span>
62
- <span v-else>{{$t('components.table.freezeColumn')}}</span>
63
- </a>
64
- </div>
65
- <div v-if="showAddColumn">
66
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="hideColumn(n)">
67
- <itf-icon name="hide" new />
68
-
69
- {{$t('components.table.hideColumn')}}
70
- </a>
71
- </div>
72
- <div v-if="column.filtrable">
73
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="$emit('filter', column)">
74
- <itf-icon name="filter" new />
75
-
76
- {{$t('components.table.filter')}}
77
- </a>
78
- </div>
79
- <div v-if="canMoveColumn(1, column)">
80
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="moveColumn(1, column)">
81
- <itf-icon name="move-right" new />
82
-
83
- {{$t('components.table.moveRight')}}
84
- </a>
85
- </div>
86
-
87
- <div v-if="canMoveColumn(-1, column)">
88
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="moveColumn(-1, column)">
89
- <itf-icon name="move-left" new />
90
-
91
- {{$t('components.table.moveLeft')}}
92
- </a>
93
- </div>
94
-
95
- <template v-if="column.sortable">
46
+ </template>
96
47
  <div class="dropdown-header">
97
- {{$t('components.table.sorting')}}
48
+ {{$t('components.table.actions')}}
98
49
  </div>
99
- <div>
100
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="sortBy(column, 'asc')">
101
- <itf-icon name="sort-asc" new />
102
- {{$t('components.table.sortAscending')}}
50
+
51
+ <div v-if="column.groupable">
52
+ <a class="dropdown-item d-flex align-items-center" href="javascript:;">
53
+ <itf-icon name="episodes" :size="16" class="me-1" />
54
+ {{$t('components.table.groupBy')}}
103
55
  </a>
104
56
  </div>
105
57
  <div>
106
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="sortBy(column, 'desc')">
107
- <itf-icon name="sort-desc" new />
108
- {{$t('components.table.sortDescending')}}
58
+ <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="togglePinned(n)">
59
+ <itf-icon v-if="column.pinned" name="pin" new />
60
+ <itf-icon v-else name="pin" new />
61
+
62
+ <span v-if="column.pinned">{{$t('components.table.unfreezeColumn')}}</span>
63
+ <span v-else>{{$t('components.table.freezeColumn')}}</span>
64
+ </a>
65
+ </div>
66
+ <div v-if="showAddColumn">
67
+ <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="hideColumn(n)">
68
+ <itf-icon name="hide" new />
69
+
70
+ {{$t('components.table.hideColumn')}}
71
+ </a>
72
+ </div>
73
+ <div v-if="column.filtrable">
74
+ <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="$emit('filter', column)">
75
+ <itf-icon name="filter" new />
76
+
77
+ {{$t('components.table.filter')}}
78
+ </a>
79
+ </div>
80
+ <div v-if="canMoveColumn(1, column)">
81
+ <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="moveColumn(1, column)">
82
+ <itf-icon name="move-right" new />
83
+
84
+ {{$t('components.table.moveRight')}}
109
85
  </a>
110
86
  </div>
111
- </template>
112
- </itf-dropdown>
87
+
88
+ <div v-if="canMoveColumn(-1, column)">
89
+ <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="moveColumn(-1, column)">
90
+ <itf-icon name="move-left" new />
91
+
92
+ {{$t('components.table.moveLeft')}}
93
+ </a>
94
+ </div>
95
+
96
+ <template v-if="column.sortable">
97
+ <div class="dropdown-header">
98
+ {{$t('components.table.sorting')}}
99
+ </div>
100
+ <div>
101
+ <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="sortBy(column, 'asc')">
102
+ <itf-icon name="sort-asc" new />
103
+ {{$t('components.table.sortAscending')}}
104
+ </a>
105
+ </div>
106
+ <div>
107
+ <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="sortBy(column, 'desc')">
108
+ <itf-icon name="sort-desc" new />
109
+ {{$t('components.table.sortDescending')}}
110
+ </a>
111
+ </div>
112
+ </template>
113
+ </itf-dropdown>
114
+ <slot :name="`header.${column.property}.after`" v-bind="{ column }"></slot>
115
+ </div>
113
116
  <div v-if="columnSorting" v-drag-handle class="itf-table2__drag-column">
114
117
  <svg width="35" height="23" viewBox="0 0 35 23" fill="none" xmlns="http://www.w3.org/2000/svg">
115
118
  <g filter="url(#filter0_d_1081_25763)">
@@ -164,6 +167,7 @@ import createDraggable from '../sortable/draggable';
164
167
  import itfDropdown from '../dropdown/Dropdown.vue';
165
168
  import itfSortable from '../sortable/Sortable.vue';
166
169
  import settings from "../../ITFSettings";
170
+ import { getIsMobileView } from "./mobile";
167
171
 
168
172
  const { Node, ...draggableDirectives } = createDraggable();
169
173
 
@@ -196,7 +200,6 @@ class itfTableHeader extends Vue {
196
200
  @Prop(Boolean) noColumnMenu;
197
201
  @Prop(Boolean) noSelectAll;
198
202
  @Prop(Boolean) editable;
199
- @Prop(Boolean) sortAsString;
200
203
  @Prop() idProperty;
201
204
  @Prop() indicatorType;
202
205
 
@@ -210,6 +213,10 @@ class itfTableHeader extends Vue {
210
213
  }
211
214
  }
212
215
 
216
+ getIsMobileView() {
217
+ return getIsMobileView();
218
+ }
219
+
213
220
  get sortColumnParams() {
214
221
  if (typeof this._sorting === 'string'){
215
222
  return this._sorting[0] === '-' ? {[this._sorting.substring(1)]: 'desc'} : {[this._sorting]: 'asc'};
@@ -235,7 +242,7 @@ class itfTableHeader extends Vue {
235
242
 
236
243
  set selectAll(val) {
237
244
  if (val) {
238
- this.$emit('update:selectedIds', this.rows.map(r => r[this.idProperty]));
245
+ this.$emit('update:selectedIds', this.rows.filter(r => !r.isDisabled).map(r => r[this.idProperty]));
239
246
  } else {
240
247
  this.$emit('update:selectedIds', []);
241
248
  }
@@ -414,10 +421,8 @@ class itfTableHeader extends Vue {
414
421
  }
415
422
 
416
423
  sortBy(column, order) {
417
- let sort = { [column.property]: order };
418
- if (this.sortAsString) {
419
- sort = order === 'desc' ? `-${column.property}` : column.property;
420
- }
424
+ let sort = order === 'desc' ? `-${column.property}` : column.property;
425
+ console.info(sort);
421
426
  this.$emit('update:sorting', sort);
422
427
  }
423
428
  }
@@ -2,10 +2,7 @@
2
2
  <div>
3
3
  <div @click.prevent.stop="toggle" class="d-flex align-items-center flex-nowrap" :class="{'active-toggle': visible}">
4
4
  <div class="item-toggle text-muted">
5
- <template v-if="visible && loading">
6
- <div class="itf-spinner"></div>
7
- </template>
8
- <template v-else-if="visible && expanded">
5
+ <template v-if="visible && expanded">
9
6
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
10
7
  width="16" height="16" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
11
8
  <path d="M184.7,413.1l2.1-1.8l156.5-136c5.3-4.6,8.6-11.5,8.6-19.2c0-7.7-3.4-14.6-8.6-19.2L187.1,101l-2.6-2.3
@@ -26,10 +23,6 @@
26
23
  </div>
27
24
  </template>
28
25
  <style lang="scss" scoped>
29
- .itf-spinner {
30
- width: 1rem;
31
- height: 1rem;
32
- }
33
26
  .active-toggle {
34
27
  cursor: pointer;
35
28
  }
@@ -50,7 +43,6 @@ export default @Component({
50
43
  class itfTableRowToggle extends Vue {
51
44
  @Prop(Boolean) expanded;
52
45
  @Prop(Boolean) visible;
53
- @Prop(Boolean) loading;
54
46
 
55
47
  toggle() {
56
48
  this.$emit('toggle');
@@ -6,7 +6,7 @@
6
6
  group="items"
7
7
  data-test="table-item"
8
8
  class="table-view-item grouped draggable-item"
9
- :class="{'selected': selectedIds.includes(item[idProperty]), 'active': isActive(item[idProperty]), [cssProperty && item[cssProperty]]: !!item[cssProperty]}"
9
+ :class="{'selected': selectedIds.includes(item[idProperty]), 'active': isActive(item[idProperty]), 'disabled': item.isDisabled, [cssProperty && item[cssProperty]]: !!item[cssProperty]}"
10
10
  >
11
11
  <div class="table-row-template">
12
12
  <div accept-group="items" class="table-view-body-space"></div>
@@ -24,23 +24,7 @@
24
24
  <div v-if="indicatorType !== 'none'" class="table-view-row-count">
25
25
  <span v-if="indicatorType === 'order'">{{ (n + 1) }}</span>
26
26
  <span v-else-if="indicatorType === 'property'">{{ item[idProperty] }}</span>
27
- <span v-else-if="indicatorType === 'checkbox'"><itf-checkbox :value="item[idProperty]" /></span>
28
- <a href="" @click.prevent.stop="$emit('toggle', item)" v-else-if="indicatorType === 'toggle'">
29
- <template v-if="subrowsProperty && item[subrowsProperty] && item[subrowsProperty].length">
30
- <template v-if="item[subrowsProperty] && item[subrowsProperty].length && !isExpanded(item)">
31
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-square" viewBox="0 0 16 16">
32
- <path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
33
- <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4"/>
34
- </svg>
35
- </template>
36
- <template v-else>
37
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash-square" viewBox="0 0 16 16">
38
- <path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
39
- <path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8"/>
40
- </svg>
41
- </template>
42
- </template>
43
- </a>
27
+ <span v-else-if="indicatorType === 'checkbox'"><itf-checkbox :disabled="item.isDisabled" :value="item[idProperty]" /></span>
44
28
  </div>
45
29
  </div>
46
30
  <div accept-group="items" class="table-item-inner" @click="$emit('row-click', item)">
@@ -49,37 +33,37 @@
49
33
  v-if="column.visible !== false"
50
34
  :data-column="k"
51
35
  :style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`"
52
- :class="{'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'editable': column.editable && editable}"
36
+ :class="{[column.cssClass]: !!column.cssClass, 'justify-content-end': column.align === 'end', 'sticky': column.pinned && !getIsMobileView(), 'last-sticky-column': k === lastPinnedIndex && !getIsMobileView(), 'editable': column.editable && editable}"
53
37
  class="table-view-item-value d-flex h-100">
54
- <div class="table-view-item-value-content align-items-center" :class="{'justify-content-end': column.align === 'end', 'px-2': !(column.editable && editable)}">
55
- <slot
56
- :name="`column.${column.property}`"
57
- :toggle="() => $emit('toggle', item)"
58
- :hasSubitems="hasSubitems(item)"
59
- :isExpanded="!!(hasSubitems(item) && !isExpanded(item))"
60
- :level="level" :editable="column.editable && editable" :item="item" :column="column" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)">
61
- <template v-if="column.editable && editable && (!editableProperty || item[editableProperty])">
62
- <slot :name="`edit.${column.type}`" :level="level" :toggle="() => $emit('toggle', item)" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)" :item="item" :column="column">
63
- <itf-text-field class="w-100 h-100" v-if="column.type === 'text'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
64
- <itf-text-field class="w-100 h-100" v-if="column.type === 'number'" type="number" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
65
- <itf-hours-field
66
- class="w-100 h-100"
67
- placeholder="00h 00m"
68
- v-else-if="column.type === 'time'"
69
- :hours="getValue(item, column)"
70
- @update:hours="updateValue(item, $event, n, column)"
71
- />
72
- <itf-textarea class="w-100 h-100" :rows="1" autogrow v-else-if="column.type === 'textarea'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
73
- <itf-money-field class="w-100 h-100" currency-disabled :currency="currency" :currencies="currencies" v-else-if="column.type === 'money'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
74
- <itf-select class="w-100 h-100" v-else-if="column.type === 'select'" :reduce="(item) => item.value" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" :options="column.options"></itf-select>
75
- </slot>
76
- </template>
77
- <span v-else class="text-truncate">
78
- <slot :name="`format.${column.type}`" :toggle="() => $emit('toggle', item)" :level="level" :value="getValue(item, column)" :update="(value) => updateValue(item, value, n, column)" :item="item" :column="column">
79
- {{getValue(item, column)}}
80
- </slot>
81
- </span>
82
- </slot>
38
+ <div class="table-view-item-value-content" :class="{'px-2': !(column.editable && editable), 'py-1': (column.editable && editable)}">
39
+ <slot
40
+ :name="`column.${column.property}`"
41
+ :toggle="() => $emit('toggle', item)"
42
+ :hasSubitems="!!(subrowsProperty && item[subrowsProperty] && item[subrowsProperty].length)"
43
+ :isExpanded="!!(item[subrowsProperty] && item[subrowsProperty].length && !isExpanded(item))"
44
+ :level="level" :editable="column.editable && editable" :item="item" :column="column" :updateFields="(val) => updateValues(item, val, n, column)" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)">
45
+ <template v-if="column.editable && editable && (!editableProperty || item[editableProperty])">
46
+ <slot :name="`edit.${column.type}`" :level="level" :toggle="() => $emit('toggle', item)" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)" :item="item" :column="column">
47
+ <itf-text-field class="w-100" v-if="column.type === 'text'" :postfix="column.postfix" :maxlength="column.maxlength" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
48
+ <itf-text-field class="w-100" v-if="column.type === 'number'" :postfix="column.postfix" :max="column.max" :min="column.min" :step="column.step" :maxlength="column.maxlength" type="number" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
49
+ <itf-hours-field
50
+ class="w-100 h-100"
51
+ placeholder="00h 00m"
52
+ v-else-if="column.type === 'time'"
53
+ :hours="getValue(item, column)"
54
+ @update:hours="updateValue(item, $event, n, column)"
55
+ />
56
+ <itf-textarea class="w-100" :rows="1" autogrow v-else-if="column.type === 'textarea'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
57
+ <itf-money-field class="w-100" currency-disabled :currency="currency" :currencies="currencies" v-else-if="column.type === 'money'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
58
+ <itf-select class="w-100" v-else-if="column.type === 'select'" :reduce="(item) => item.value" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" :options="column.options"></itf-select>
59
+ </slot>
60
+ </template>
61
+ <div v-else class="h-100 align-items-center d-flex w-100">
62
+ <slot :name="`format.${column.type}`" :toggle="() => $emit('toggle', item)" :level="level" :value="getValue(item, column)" :update="(value) => updateValue(item, value, n, column)" :item="item" :column="column">
63
+ {{getValue(item, column)}}
64
+ </slot>
65
+ </div>
66
+ </slot>
83
67
  </div>
84
68
  </div>
85
69
  </template>
@@ -102,7 +86,6 @@
102
86
  :columns="columns"
103
87
  :id-property="idProperty"
104
88
  :subrows-property="subrowsProperty"
105
- :async-subrows-property="asyncSubrowsProperty"
106
89
  :show-add-column="showAddColumn"
107
90
  :show-actions="showActions"
108
91
  :no-select-all="noSelectAll"
@@ -115,6 +98,7 @@
115
98
  :expanded-all="expandedAll"
116
99
  :css-property="cssProperty"
117
100
  :editable-property="editableProperty"
101
+ :active="active"
118
102
  @update="$emit('update', $event)"
119
103
  @toggle="$emit('toggle', $event)"
120
104
  >
@@ -142,6 +126,7 @@ import itfTextarea from '../text-field/Textarea.vue';
142
126
  import itfHoursField from '../text-field/HoursField.vue';
143
127
  import itfSelect from '../select/Select.vue';
144
128
  import itfTableBody from './TableBody.vue';
129
+ import { getIsMobileView } from "./mobile";
145
130
  // import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';
146
131
 
147
132
  export default @Component({
@@ -162,7 +147,6 @@ class itfTableRows extends Vue {
162
147
  @Prop() rows;
163
148
  @Prop() idProperty;
164
149
  @Prop() subrowsProperty;
165
- @Prop() asyncSubrowsProperty;
166
150
  @Prop() dividerProperty;
167
151
  @Prop() active;
168
152
  @Prop(Boolean) showAddColumn;
@@ -192,10 +176,8 @@ class itfTableRows extends Vue {
192
176
  return this.columns.findIndex((column) => column.lastPinned);
193
177
  }
194
178
 
195
- hasSubitems(item) {
196
- const hasFactItems = this.subrowsProperty && item[this.subrowsProperty] && item[this.subrowsProperty].length;
197
- const hasPlanItems = this.asyncSubrowsProperty && item[this.asyncSubrowsProperty] && item[this.asyncSubrowsProperty];
198
- return !!(hasFactItems || hasPlanItems);
179
+ getIsMobileView() {
180
+ return getIsMobileView();
199
181
  }
200
182
 
201
183
  updateValue(item, value, index, column) {
@@ -212,8 +194,20 @@ class itfTableRows extends Vue {
212
194
  }
213
195
  }
214
196
 
197
+ updateValues(item, values, index, column) {
198
+ const newItem = { ...item };
199
+ Object.assign(newItem, values);
200
+ this.$emit('update', {
201
+ index,
202
+ item,
203
+ inputValue: values,
204
+ value: newItem,
205
+ column
206
+ });
207
+ }
208
+
215
209
  isActive(id) {
216
- if (!this.idProperty || !this.active) {
210
+ if (!this.idProperty) {
217
211
  return false;
218
212
  }
219
213
  if (Array.isArray(this.active)) {
@@ -0,0 +1,4 @@
1
+ export
2
+ function getIsMobileView() {
3
+ return window.matchMedia('(max-width: 768px)').matches;
4
+ }