@itfin/components 1.4.35 → 1.5.0

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 (202) hide show
  1. package/package.json +17 -20
  2. package/src/ITFSettings.js +6 -0
  3. package/src/assets/scss/_css_variables.scss +2 -7
  4. package/src/assets/scss/_dark-theme.scss +2 -12
  5. package/src/assets/scss/_variables.scss +34 -9
  6. package/src/assets/scss/components/_button.scss +147 -10
  7. package/src/assets/scss/components/_checkbox.scss +9 -0
  8. package/src/assets/scss/components/_datepicker.scss +3 -3
  9. package/src/assets/scss/components/_pagination.scss +4 -1
  10. package/src/assets/scss/components/_popover.scss +22 -0
  11. package/src/assets/scss/components/_segmeneted-control.scss +19 -8
  12. package/src/assets/scss/components/_select.scss +6 -8
  13. package/src/assets/scss/components/_text-field.scss +27 -11
  14. package/src/assets/scss/components/select/_dropdown-menu.scss +1 -0
  15. package/src/assets/scss/components/select/_dropdown-toggle.scss +0 -1
  16. package/src/assets/scss/directives/tooltip.scss +10 -5
  17. package/src/assets/scss/main.scss +48 -0
  18. package/src/components/alert/AlertBanner.vue +75 -0
  19. package/src/components/app/App.vue +1 -1
  20. package/src/components/button/Button.vue +3 -1
  21. package/src/components/button/NativeButton.js +4 -0
  22. package/src/components/button/index.stories.js +2 -2
  23. package/src/components/checkbox/Checkbox.vue +2 -1
  24. package/src/components/checkbox/RadioBox.vue +1 -2
  25. package/src/components/copyToClipboard/CopyToClipboard.vue +4 -1
  26. package/src/components/customize/PropertiesList.vue +0 -2
  27. package/src/components/customize/PropertiesPopupMenu.vue +1 -1
  28. package/src/components/customize/PropertyItem.vue +6 -24
  29. package/src/components/datepicker/DatePicker.vue +3 -1
  30. package/src/components/datepicker/DatePickerInline.vue +2 -2
  31. package/src/components/datepicker/DateRangePickerInline.vue +6 -1
  32. package/src/components/dropdown/Dropdown.vue +1 -1
  33. package/src/components/dropdown/DropdownMenu.vue +1 -1
  34. package/src/components/editable/EditButton.vue +1 -1
  35. package/src/components/filter/FilterBadge.vue +20 -1
  36. package/src/components/filter/FilterFacetsList.vue +67 -13
  37. package/src/components/filter/FilterPanel.vue +39 -14
  38. package/src/components/filter/NewFilter.vue +305 -0
  39. package/src/components/form/Label.vue +5 -5
  40. package/src/components/icon/components/nomi-ai-alt.vue +5 -0
  41. package/src/components/icon/components/nomi-arrow-right.vue +4 -0
  42. package/src/components/icon/components/nomi-bell.vue +5 -0
  43. package/src/components/icon/components/nomi-calendar-payment.vue +10 -0
  44. package/src/components/icon/components/nomi-card-plus.vue +1 -0
  45. package/src/components/icon/components/nomi-cash-provider.vue +9 -0
  46. package/src/components/icon/components/nomi-cash-repeat.vue +6 -0
  47. package/src/components/icon/components/nomi-category-edit.vue +5 -0
  48. package/src/components/icon/components/nomi-chavron-up.vue +4 -0
  49. package/src/components/icon/components/nomi-chavron_down.vue +4 -0
  50. package/src/components/icon/components/nomi-chavron_up.vue +4 -0
  51. package/src/components/icon/components/nomi-chevron-up.vue +4 -0
  52. package/src/components/icon/components/nomi-exit-right.vue +4 -0
  53. package/src/components/icon/components/nomi-help.vue +2 -3
  54. package/src/components/icon/components/nomi-history.vue +7 -0
  55. package/src/components/icon/components/nomi-lock.vue +1 -1
  56. package/src/components/icon/components/nomi-pen-alt.vue +4 -0
  57. package/src/components/icon/components/nomi-project.vue +2 -2
  58. package/src/components/icon/components/nomi-refresh-off.vue +4 -0
  59. package/src/components/icon/components/nomi-refresh.vue +4 -0
  60. package/src/components/icon/components/nomi-scissors.vue +1 -1
  61. package/src/components/icon/components/nomi-start.vue +28 -0
  62. package/src/components/icon/components/nomi-table-view.vue +1 -4
  63. package/src/components/icon/components/nomi-transactions-delete.vue +5 -0
  64. package/src/components/icon/components/nomi-type-array.vue +6 -0
  65. package/src/components/icon/components/nomi-type-boolean.vue +5 -0
  66. package/src/components/icon/components/nomi-type-date.vue +4 -0
  67. package/src/components/icon/components/nomi-type-null.vue +4 -0
  68. package/src/components/icon/components/nomi-type-number.vue +4 -0
  69. package/src/components/icon/components/nomi-type-object.vue +4 -0
  70. package/src/components/icon/components/nomi-type-string.vue +4 -0
  71. package/src/components/icon/components/nomi-unarchive.vue +17 -0
  72. package/src/components/icon/components/nomi-unlink.vue +10 -0
  73. package/src/components/icon/components/nomi-user.vue +3 -3
  74. package/src/components/icon/components/nomi-warning-triangle.vue +6 -0
  75. package/src/components/icon/components/nomi-warning_triangle_filled.vue +6 -0
  76. package/src/components/icon/convert-icons.js +3 -0
  77. package/src/components/icon/icons.js +390 -312
  78. package/src/components/icon/new-icons/ai-alt.svg +4 -0
  79. package/src/components/icon/new-icons/arrow-right-alt.svg +3 -0
  80. package/src/components/icon/new-icons/arrow-right.svg +3 -0
  81. package/src/components/icon/new-icons/arrow_left.svg +3 -0
  82. package/src/components/icon/new-icons/automation.svg +4 -0
  83. package/src/components/icon/new-icons/balance.svg +3 -0
  84. package/src/components/icon/new-icons/balance_turnover.svg +4 -0
  85. package/src/components/icon/new-icons/bar-horizontal.svg +6 -0
  86. package/src/components/icon/new-icons/bell.svg +4 -0
  87. package/src/components/icon/new-icons/calendar-payment.svg +9 -0
  88. package/src/components/icon/new-icons/card-plus.svg +1 -0
  89. package/src/components/icon/new-icons/cash-provider.svg +8 -0
  90. package/src/components/icon/new-icons/cash-repeat.svg +5 -0
  91. package/src/components/icon/new-icons/cash.svg +3 -0
  92. package/src/components/icon/new-icons/cashflow.svg +3 -0
  93. package/src/components/icon/new-icons/category-edit.svg +4 -0
  94. package/src/components/icon/new-icons/category.svg +4 -0
  95. package/src/components/icon/new-icons/category_alt.svg +3 -0
  96. package/src/components/icon/new-icons/chart-bars.svg +5 -0
  97. package/src/components/icon/new-icons/chart-donut.svg +3 -0
  98. package/src/components/icon/new-icons/chart-funnel.svg +5 -0
  99. package/src/components/icon/new-icons/chart-kpi.svg +7 -0
  100. package/src/components/icon/new-icons/chart-line.svg +4 -0
  101. package/src/components/icon/new-icons/chart-lines.svg +5 -0
  102. package/src/components/icon/new-icons/check-alt.svg +3 -0
  103. package/src/components/icon/new-icons/check.svg +3 -0
  104. package/src/components/icon/new-icons/chevron-down.svg +3 -0
  105. package/src/components/icon/new-icons/chevron-left.svg +3 -0
  106. package/src/components/icon/new-icons/chevron-right.svg +3 -0
  107. package/src/components/icon/new-icons/chevron-up.svg +3 -0
  108. package/src/components/icon/new-icons/collapse.svg +6 -0
  109. package/src/components/icon/new-icons/control-panel.svg +7 -0
  110. package/src/components/icon/new-icons/credit.svg +3 -0
  111. package/src/components/icon/new-icons/currencies.svg +3 -0
  112. package/src/components/icon/new-icons/debt.svg +3 -0
  113. package/src/components/icon/new-icons/demo.svg +6 -0
  114. package/src/components/icon/new-icons/dev.svg +3 -0
  115. package/src/components/icon/new-icons/dots.svg +5 -0
  116. package/src/components/icon/new-icons/duplicate.svg +4 -0
  117. package/src/components/icon/new-icons/exit-right.svg +3 -0
  118. package/src/components/icon/new-icons/export.svg +3 -0
  119. package/src/components/icon/new-icons/file.svg +3 -0
  120. package/src/components/icon/new-icons/folder.svg +3 -0
  121. package/src/components/icon/new-icons/goods-turnover.svg +3 -0
  122. package/src/components/icon/new-icons/goods.svg +4 -0
  123. package/src/components/icon/new-icons/help-alt.svg +3 -0
  124. package/src/components/icon/new-icons/help.svg +2 -3
  125. package/src/components/icon/new-icons/history.svg +6 -0
  126. package/src/components/icon/new-icons/integration.svg +3 -0
  127. package/src/components/icon/new-icons/link.svg +5 -0
  128. package/src/components/icon/new-icons/lock.svg +1 -1
  129. package/src/components/icon/new-icons/menu.svg +5 -0
  130. package/src/components/icon/new-icons/minus.svg +3 -0
  131. package/src/components/icon/new-icons/payment_calendar.svg +3 -0
  132. package/src/components/icon/new-icons/pc.svg +3 -0
  133. package/src/components/icon/new-icons/pen-alt.svg +3 -0
  134. package/src/components/icon/new-icons/planFact.svg +4 -0
  135. package/src/components/icon/new-icons/pnl.svg +7 -0
  136. package/src/components/icon/new-icons/project.svg +2 -2
  137. package/src/components/icon/new-icons/project_alt.svg +3 -0
  138. package/src/components/icon/new-icons/project_alt2.svg +3 -0
  139. package/src/components/icon/new-icons/promo.svg +3 -0
  140. package/src/components/icon/new-icons/refresh-off.svg +3 -0
  141. package/src/components/icon/new-icons/refresh.svg +3 -0
  142. package/src/components/icon/new-icons/scissors.svg +1 -1
  143. package/src/components/icon/new-icons/segment.svg +3 -0
  144. package/src/components/icon/new-icons/start.svg +27 -0
  145. package/src/components/icon/new-icons/strongbox.svg +3 -0
  146. package/src/components/icon/new-icons/subscription.svg +3 -0
  147. package/src/components/icon/new-icons/table-view.svg +1 -4
  148. package/src/components/icon/new-icons/time.svg +3 -0
  149. package/src/components/icon/new-icons/transactions_alt.svg +6 -0
  150. package/src/components/icon/new-icons/transactions_delete.svg +4 -0
  151. package/src/components/icon/new-icons/type-array.svg +5 -0
  152. package/src/components/icon/new-icons/type-boolean.svg +4 -0
  153. package/src/components/icon/new-icons/type-date.svg +3 -0
  154. package/src/components/icon/new-icons/type-null.svg +3 -0
  155. package/src/components/icon/new-icons/type-number.svg +3 -0
  156. package/src/components/icon/new-icons/type-object.svg +3 -0
  157. package/src/components/icon/new-icons/type-string.svg +3 -0
  158. package/src/components/icon/new-icons/types.svg +6 -0
  159. package/src/components/icon/new-icons/unarchive.svg +16 -0
  160. package/src/components/icon/new-icons/unlink.svg +9 -0
  161. package/src/components/icon/new-icons/user.svg +3 -3
  162. package/src/components/icon/new-icons/user_plus.svg +10 -0
  163. package/src/components/icon/new-icons/warehouse.svg +3 -0
  164. package/src/components/icon/new-icons/warning_triangle.svg +5 -0
  165. package/src/components/icon/new-icons/warning_triangle_filled.svg +5 -0
  166. package/src/components/kanban/BoardCard.vue +1 -1
  167. package/src/components/kanban/BoardCardTimer.vue +1 -1
  168. package/src/components/modal/DeleteConfirmModal.vue +10 -6
  169. package/src/components/modal/ItemEditor.vue +1 -1
  170. package/src/components/modal/Modal.vue +1 -1
  171. package/src/components/overlay/SensitiveOverlay.vue +2 -4
  172. package/src/components/panels/Panel.vue +110 -23
  173. package/src/components/panels/PanelItemEdit.vue +1 -1
  174. package/src/components/panels/PanelList.vue +65 -11
  175. package/src/components/popover/Popover.vue +105 -22
  176. package/src/components/segmented-control/SegmentedControl.vue +9 -3
  177. package/src/components/sortable/draggable.js +1 -1
  178. package/src/components/table/Table2.vue +8 -3
  179. package/src/components/table/TableBody.vue +17 -16
  180. package/src/components/table/TableGroup.vue +38 -12
  181. package/src/components/table/TableHeader.vue +83 -73
  182. package/src/components/table/TableRows.vue +15 -9
  183. package/src/components/table/mobile.js +4 -0
  184. package/src/components/table/table2.scss +9 -0
  185. package/src/components/text-field/MoneyField.vue +10 -4
  186. package/src/components/text-field/TextField.vue +17 -8
  187. package/src/components/tree/TreeEditor.vue +3 -2
  188. package/src/components/view/View.vue +86 -214
  189. package/src/directives/appendToBody.js +1 -0
  190. package/src/helpers/validators.js +9 -35
  191. package/src/helpers/validators.spec.js +11 -48
  192. package/src/locales/en.js +4 -6
  193. package/src/locales/pl.js +158 -0
  194. package/src/locales/uk.js +6 -7
  195. package/src/components/icon/components/nomi-calendar-view.vue +0 -4
  196. package/src/components/icon/components/nomi-kanban-view.vue +0 -6
  197. package/src/components/icon/components/nomi-list-view.vue +0 -7
  198. package/src/components/icon/components/nomi-table-config.vue +0 -9
  199. package/src/components/icon/new-icons/calendar-view.svg +0 -3
  200. package/src/components/icon/new-icons/kanban-view.svg +0 -5
  201. package/src/components/icon/new-icons/list-view.svg +0 -6
  202. 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
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>
@@ -51,7 +51,14 @@
51
51
  @update:columns="$emit('update:columns', $event)"
52
52
  @filter="$emit('filter', $event)"
53
53
  @add-column="$emit('add-column', $event)"
54
- />
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>
55
62
  </div>
56
63
 
57
64
  <!-- Сама таблиця -->
@@ -91,11 +98,11 @@
91
98
 
92
99
  <!-- Лінія додати нову -->
93
100
  <div v-if="isShowTable && addNewRows"
94
- class="table-row-template d-flex align-items-stretch">
101
+ class="d-flex align-items-stretch">
95
102
  <div class="shadow-area"></div>
96
103
  <a href="" @click.prevent="$emit('new', title)" data-test="table-add-new-item"
97
104
  class="d-flex align-items-center flex-grow-1 table-add-new-item text-decoration-none">
98
- <span class="d-sticky d-flex align-items-center py-1">
105
+ <span class="d-sticky d-flex align-items-center py-2 px-2">
99
106
  <itf-icon name="plus"/>
100
107
  <span>{{ newLabel }}</span>
101
108
  </span>
@@ -265,12 +272,17 @@
265
272
  }
266
273
 
267
274
  .table-add-new-item {
268
- border-right:var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
269
- border-left:var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
275
+ margin-top: -12px;
270
276
  border-bottom: var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
271
277
  outline: none;
272
278
  border-bottom-left-radius: var(--itf-table-table-border-radius);
273
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
+ }
274
286
 
275
287
  & > span {
276
288
  left: var(--shadow-area-width);
@@ -336,6 +348,7 @@ import itfIcon from '../icon/Icon.vue';
336
348
  import itfTableBody from './TableBody.vue';
337
349
  import itfTableHeader from './TableHeader.vue';
338
350
  import Sticky from "./sticky";
351
+ import { getIsMobileView } from "./mobile";
339
352
 
340
353
  function getNumber(item, prop) {
341
354
  const num = Number(get(item, prop));
@@ -386,10 +399,14 @@ class itfTableGroup extends Vue {
386
399
  @Prop({type: String, default: function() { return this.$t('components.table.new'); } }) newLabel;
387
400
  @Prop({type: Object, default: () => ({})}) schema;
388
401
  @Prop() expandedIds;
402
+ @Prop() collapsedGroupIds;
389
403
 
390
- isShowTable = true;
391
404
  persistSummary = false;
392
405
 
406
+ get isShowTable() {
407
+ return typeof this.collapsedGroupIds !== 'undefined' ? !this.collapsedGroupIds.includes(this.title) : true;
408
+ }
409
+
393
410
  get visibleColumns() {
394
411
  let list = this.columns;
395
412
  list = sortBy(list, (column) => column.index);
@@ -397,8 +414,8 @@ class itfTableGroup extends Vue {
397
414
  const pinned = list.filter((column) => column.pinned && column.visible !== false);
398
415
  list = list.map((column, index) => {
399
416
  const item = {...column};
400
- item.left = (item.pinned && item.visible !== false) ? left : 0;
401
- 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;
402
419
  item.lastPinned = index === pinned.length - 1;
403
420
  return item
404
421
  });
@@ -410,8 +427,17 @@ class itfTableGroup extends Vue {
410
427
  this.$emit('update:columns', columns);
411
428
  }
412
429
 
413
- toggleGroup() {
414
- 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);
415
441
  }
416
442
 
417
443
  get stickyId() {
@@ -4,7 +4,7 @@
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 class="table-view-header-value reserved sticky">
7
+ <div class="table-view-header-value reserved sticky" data-test="table-header-checkbox">
8
8
  <itf-checkbox v-if="indicatorType === 'checkbox' && visibleHeader && !noSelectAll" ungrouped value="all" v-model="selectAll" ref="selectAll" />
9
9
  </div>
10
10
 
@@ -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
  <!-- Не треба видаляти колонки, бо вони потрібні для збереження ширини -->
@@ -30,84 +30,89 @@
30
30
  class="table-header"
31
31
  @drop="reorderColumns"
32
32
  v-draggable="{ 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">{{getTitle(column.title)}}</div>
39
- <div v-if="column.prefix" class="itf-table2__subtitle text-truncate" v-text="column.prefix" />
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>
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" />
40
45
  </div>
41
- </div>
42
- <itf-icon v-if="sortColumnParams[column.property]" :name="sortColumnParams[column.property] === 'asc' ? 'sort-asc' : 'sort-desc'" new :size="20" class="ms-1" />
43
- </template>
44
- <div class="dropdown-header">
45
- {{$t('components.table.actions')}}
46
- </div>
47
-
48
- <div v-if="column.groupable">
49
- <a class="dropdown-item d-flex align-items-center" href="javascript:;">
50
- <itf-icon name="episodes" :size="16" class="me-1" />
51
- {{$t('components.table.groupBy')}}
52
- </a>
53
- </div>
54
- <div>
55
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="togglePinned(n)">
56
- <itf-icon v-if="column.pinned" name="pin" new />
57
- <itf-icon v-else name="pin" new />
58
-
59
- <span v-if="column.pinned">{{$t('components.table.unfreezeColumn')}}</span>
60
- <span v-else>{{$t('components.table.freezeColumn')}}</span>
61
- </a>
62
- </div>
63
- <div v-if="showAddColumn">
64
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="hideColumn(n)">
65
- <itf-icon name="hide" new />
66
-
67
- {{$t('components.table.hideColumn')}}
68
- </a>
69
- </div>
70
- <div v-if="column.filtrable">
71
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="$emit('filter', column)">
72
- <itf-icon name="filter" new />
73
-
74
- {{$t('components.table.filter')}}
75
- </a>
76
- </div>
77
- <div v-if="canMoveColumn(1, column)">
78
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="moveColumn(1, column)">
79
- <itf-icon name="move-right" new />
80
-
81
- {{$t('components.table.moveRight')}}
82
- </a>
83
- </div>
84
-
85
- <div v-if="canMoveColumn(-1, column)">
86
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="moveColumn(-1, column)">
87
- <itf-icon name="move-left" new />
88
-
89
- {{$t('components.table.moveLeft')}}
90
- </a>
91
- </div>
92
-
93
- <template v-if="column.sortable">
46
+ </template>
94
47
  <div class="dropdown-header">
95
- {{$t('components.table.sorting')}}
48
+ {{$t('components.table.actions')}}
96
49
  </div>
97
- <div>
98
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="sortBy(column, 'asc')">
99
- <itf-icon name="sort-asc" new />
100
- {{$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')}}
101
55
  </a>
102
56
  </div>
103
57
  <div>
104
- <a class="dropdown-item d-flex align-items-center gap-1" href="javascript:;" @click="sortBy(column, 'desc')">
105
- <itf-icon name="sort-desc" new />
106
- {{$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')}}
85
+ </a>
86
+ </div>
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')}}
107
93
  </a>
108
94
  </div>
109
- </template>
110
- </itf-dropdown>
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>
111
116
  <div v-if="columnSorting" v-drag-handle class="itf-table2__drag-column">
112
117
  <svg width="35" height="23" viewBox="0 0 35 23" fill="none" xmlns="http://www.w3.org/2000/svg">
113
118
  <g filter="url(#filter0_d_1081_25763)">
@@ -162,6 +167,7 @@ import createDraggable from '../sortable/draggable';
162
167
  import itfDropdown from '../dropdown/Dropdown.vue';
163
168
  import itfSortable from '../sortable/Sortable.vue';
164
169
  import settings from "../../ITFSettings";
170
+ import { getIsMobileView } from "./mobile";
165
171
 
166
172
  const { Node, ...draggableDirectives } = createDraggable();
167
173
 
@@ -207,6 +213,10 @@ class itfTableHeader extends Vue {
207
213
  }
208
214
  }
209
215
 
216
+ getIsMobileView() {
217
+ return getIsMobileView();
218
+ }
219
+
210
220
  get sortColumnParams() {
211
221
  if (typeof this._sorting === 'string'){
212
222
  return this._sorting[0] === '-' ? {[this._sorting.substring(1)]: 'desc'} : {[this._sorting]: 'asc'};
@@ -232,7 +242,7 @@ class itfTableHeader extends Vue {
232
242
 
233
243
  set selectAll(val) {
234
244
  if (val) {
235
- 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]));
236
246
  } else {
237
247
  this.$emit('update:selectedIds', []);
238
248
  }
@@ -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,7 +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>
27
+ <span v-else-if="indicatorType === 'checkbox'"><itf-checkbox :disabled="item.isDisabled" :value="item[idProperty]" /></span>
28
28
  </div>
29
29
  </div>
30
30
  <div accept-group="items" class="table-item-inner" @click="$emit('row-click', item)">
@@ -33,9 +33,9 @@
33
33
  v-if="column.visible !== false"
34
34
  :data-column="k"
35
35
  :style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`"
36
- :class="{'justify-content-end': column.align === 'end', '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}"
37
37
  class="table-view-item-value d-flex h-100">
38
- <div class="table-view-item-value-content" :class="{'px-2': !(column.editable && editable)}">
38
+ <div class="table-view-item-value-content" :class="{'px-2': !(column.editable && editable), 'py-1': (column.editable && editable)}">
39
39
  <slot
40
40
  :name="`column.${column.property}`"
41
41
  :toggle="() => $emit('toggle', item)"
@@ -44,8 +44,8 @@
44
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
45
  <template v-if="column.editable && editable && (!editableProperty || item[editableProperty])">
46
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 h-100" v-if="column.type === 'text'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
48
- <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)" />
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
49
  <itf-hours-field
50
50
  class="w-100 h-100"
51
51
  placeholder="00h 00m"
@@ -53,9 +53,9 @@
53
53
  :hours="getValue(item, column)"
54
54
  @update:hours="updateValue(item, $event, n, column)"
55
55
  />
56
- <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)" />
57
- <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)" />
58
- <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>
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
59
  </slot>
60
60
  </template>
61
61
  <div v-else class="h-100 align-items-center d-flex w-100">
@@ -98,6 +98,7 @@
98
98
  :expanded-all="expandedAll"
99
99
  :css-property="cssProperty"
100
100
  :editable-property="editableProperty"
101
+ :active="active"
101
102
  @update="$emit('update', $event)"
102
103
  @toggle="$emit('toggle', $event)"
103
104
  >
@@ -125,6 +126,7 @@ import itfTextarea from '../text-field/Textarea.vue';
125
126
  import itfHoursField from '../text-field/HoursField.vue';
126
127
  import itfSelect from '../select/Select.vue';
127
128
  import itfTableBody from './TableBody.vue';
129
+ import { getIsMobileView } from "./mobile";
128
130
  // import 'vue-virtual-scroller/dist/vue-virtual-scroller.css';
129
131
 
130
132
  export default @Component({
@@ -174,6 +176,10 @@ class itfTableRows extends Vue {
174
176
  return this.columns.findIndex((column) => column.lastPinned);
175
177
  }
176
178
 
179
+ getIsMobileView() {
180
+ return getIsMobileView();
181
+ }
182
+
177
183
  updateValue(item, value, index, column) {
178
184
  const newItem = { ...item };
179
185
  if (newItem[column.property] !== value) {
@@ -0,0 +1,4 @@
1
+ export
2
+ function getIsMobileView() {
3
+ return window.matchMedia('(max-width: 768px)').matches;
4
+ }
@@ -240,6 +240,9 @@ body[data-theme="dark"] {
240
240
  &:not(.draggable-container--is-dragging):hover .table-view-header-value {
241
241
  z-index: 39;
242
242
  }
243
+ &:not(.draggable-container--is-dragging):hover .sticky {
244
+ z-index: 40;
245
+ }
243
246
  &:after {
244
247
  content: "";
245
248
  position: absolute;
@@ -448,6 +451,12 @@ body[data-theme="dark"] {
448
451
  .indicator {
449
452
  border-left: var(--itf-table-border-base-width) solid var(--itf-table2-border-color);
450
453
  }
454
+
455
+ &.disabled {
456
+ .table-view-item-value {
457
+ opacity: 0.5;
458
+ }
459
+ }
451
460
  }
452
461
 
453
462
  &__row-divider {
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="itf-money-field ph-no-capture" :class="{'currency-arrow': !currencyDisabled, 'currency-select': currencySelect}">
3
- <div :class="{'input-group h-100': noCurrencySign}" :style="`--itf-money-field-padding-left: ${noCurrencySign ? 1 : selectedCurrencySymbol.length * 0.6 + 1}rem`">
3
+ <div class="h-100" :class="{'input-group h-100': noCurrencySign}" :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
6
  ref="input"
@@ -9,6 +9,7 @@
9
9
  :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
10
10
  @input="setValue"
11
11
  :value="maskedValue"
12
+ :placeholder="placeholder"
12
13
  :unmask="false"
13
14
  :disabled="disabled"
14
15
  />
@@ -100,6 +101,7 @@ class itfMoneyField extends Vue {
100
101
  @Inject({ default: null }) itemLabel;
101
102
 
102
103
  @Model('input', { default: '' }) value;
104
+ @Prop({ default: '' }) placeholder;
103
105
  @Prop({ type: Object, default: null }) currency;
104
106
  @Prop({ type: Boolean, default: false }) noCurrencySign;
105
107
  @Prop({ type: Boolean, default: false }) disabled;
@@ -145,7 +147,7 @@ class itfMoneyField extends Vue {
145
147
  }
146
148
 
147
149
  onCurrencyChanged(e) {
148
- const currency = this.currenciesList.find((c) => c[this.itemKey] === parseInt(e.target.value));
150
+ const currency = this.currenciesList.find((c) => `${c[this.itemKey]}` === `${e.target.value}`);
149
151
  this.$emit('update:currency', currency)
150
152
  }
151
153
 
@@ -154,11 +156,11 @@ class itfMoneyField extends Vue {
154
156
  }
155
157
 
156
158
  get selectedCurrencySymbol() {
157
- return this.selectedCurrency ? this.selectedCurrency[this.symbolKey] : '#';
159
+ return this.selectedCurrency ? this.selectedCurrency[this.symbolKey] : '';
158
160
  }
159
161
 
160
162
  get selectedCurrencyCode() {
161
- return this.selectedCurrency ? this.selectedCurrency[this.codeKey] : '###';
163
+ return this.selectedCurrency ? this.selectedCurrency[this.codeKey] : '';
162
164
  }
163
165
 
164
166
  get currencyId() {
@@ -173,6 +175,10 @@ class itfMoneyField extends Vue {
173
175
  }
174
176
 
175
177
  setValue (val) {
178
+ if (val === '') {
179
+ this.$emit('input', '');
180
+ return;
181
+ }
176
182
  if (!isNumeric(val) || (val || '').toString().match(/\..*0$/)) { // що не видаляло останній нуль вкінці
177
183
  return;
178
184
  }
@@ -1,17 +1,18 @@
1
1
  <template>
2
2
 
3
- <div class="itf-text-field input-group" :class="{ 'with-addon addon-start': prependIcon, 'with-addon addon-end': clearable }">
3
+ <div class="itf-text-field input-group form-control p-0" :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess() }">
4
4
  <slot name="addon">
5
- <div class="addon" v-if="prependIcon">
6
- <itf-icon :name="prependIcon"/>
5
+ <div class="input-group-text prepend text-muted" v-if="prependIcon">
6
+ <itf-icon :size="small ? 18 : 20" :name="prependIcon"/>
7
7
  </div>
8
8
  </slot>
9
9
 
10
10
  <input
11
+ :name="`text-field-${_uid}`"
11
12
  ref="input"
12
13
  autocomplete="off"
13
14
  :placeholder="placeholder"
14
- :class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess(), 'form-control-sm': small }"
15
+ :class="{ 'form-control-sm': small }"
15
16
  class="itf-text-field__input form-control"
16
17
  :type="type"
17
18
  :value="value"
@@ -24,12 +25,16 @@
24
25
  @blur="$emit('blur', $event)"
25
26
  @focus="$emit('focus', $event)"
26
27
  @change="$emit('change', $event.target.value)"
28
+ :maxlength="maxlength"
27
29
  :min="min"
28
30
  :max="max"
29
31
  :step="step"
30
32
  />
33
+ <div class="input-group-text append text-muted" v-if="postfix">
34
+ {{ postfix }}
35
+ </div>
31
36
 
32
- <div class="addon-end" v-if="clearable && value">
37
+ <template v-if="clearable && value">
33
38
  <slot name="clear">
34
39
  <itf-button
35
40
  icon
@@ -39,7 +44,7 @@
39
44
  <itf-icon name="close" />
40
45
  </itf-button>
41
46
  </slot>
42
- </div>
47
+ </template>
43
48
  </div>
44
49
 
45
50
  </template>
@@ -64,10 +69,14 @@ class itfTextField extends Vue {
64
69
  @Prop() step;
65
70
  @Prop() min;
66
71
  @Prop() max;
72
+ @Prop() maxlength;
73
+ @Prop() postfix;
67
74
  @Prop(Boolean) clearable;
68
75
  @Prop(Boolean) disabled;
69
76
  @Prop(Boolean) readonly;
70
77
  @Prop(Boolean) small;
78
+ @Prop({ type: Boolean, default: undefined }) invalid;
79
+ @Prop({ type: Boolean, default: undefined }) valid;
71
80
  @Prop({ type: String, default: 'text' }) type;
72
81
  @Prop({ type: [Number, String], default: 0 }) delayInput;
73
82
 
@@ -78,11 +87,11 @@ class itfTextField extends Vue {
78
87
  }
79
88
 
80
89
  isInvalid() {
81
- return this.itemLabel && this.itemLabel.isHasError();
90
+ return typeof this.invalid !== 'undefined' ? this.invalid : (this.itemLabel && this.itemLabel.isHasError());
82
91
  }
83
92
 
84
93
  isSuccess() {
85
- return this.itemLabel && this.itemLabel.isHasSuccess();
94
+ return typeof this.valid !== 'undefined' ? this.valid : (this.itemLabel && this.itemLabel.isHasSuccess());
86
95
  }
87
96
 
88
97
  insertTextToCurrentPosition(text) {
@@ -25,10 +25,11 @@
25
25
  @keyup.enter="(e)=>{$emit('click',{event:e,ele:e.target,node,knode})}"
26
26
  @click="(e)=>{$emit('click',{event:e,ele:e.target,node,knode})}"
27
27
  >
28
- <div v-if="node.level >= toggleStartLevel" class="itf-tree-editor_node_toggle ps-2">
28
+ <div v-if="node.level >= toggleStartLevel" class="itf-tree-editor_node_toggle">
29
29
  <itf-button
30
- v-if="autoToggleTree && node.level >= toggleStartLevel && node.Children && node.Children.length > 0"
30
+ v-if="autoToggleTree && node.level >= toggleStartLevel && node[itemChildren] && node[itemChildren].length > 0"
31
31
  small
32
+ icon
32
33
  @click.stop="toggleNode($event, node, knode)"
33
34
  >
34
35
  <itf-icon v-if="isNodeToggled(node)" name="plus" size="24" />