@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.
- package/package.json +17 -20
- package/src/ITFSettings.js +6 -0
- package/src/assets/scss/components/_button.scss +118 -0
- package/src/assets/scss/components/_text-field.scss +22 -8
- package/src/components/alert/AlertBanner.vue +75 -0
- package/src/components/app/App.vue +6 -3
- package/src/components/button/Button.vue +3 -1
- package/src/components/button/NativeButton.js +4 -0
- package/src/components/button/index.stories.js +2 -2
- package/src/components/checkbox/Checkbox.vue +2 -1
- package/src/components/checkbox/RadioBox.vue +13 -7
- package/src/components/copyToClipboard/CopyToClipboard.vue +4 -1
- package/src/components/customize/PropertiesList.vue +0 -2
- package/src/components/customize/PropertiesPopupMenu.vue +1 -1
- package/src/components/customize/PropertyItem.vue +6 -24
- package/src/components/datepicker/DatePicker.vue +3 -1
- package/src/components/datepicker/DatePickerInline.vue +2 -2
- package/src/components/datepicker/DateRangePickerInline.vue +6 -1
- package/src/components/dropdown/Dropdown.vue +1 -1
- package/src/components/dropdown/DropdownMenu.vue +1 -1
- package/src/components/editable/EditButton.vue +1 -1
- package/src/components/editor/plugins.js +1012 -0
- package/src/components/filter/FilterBadge.vue +17 -3
- package/src/components/filter/FilterFacetsList.vue +67 -13
- package/src/components/filter/FilterPanel.vue +8 -21
- package/src/components/filter/NewFilter.vue +305 -0
- package/src/components/form/Label.vue +5 -5
- package/src/components/icon/components/nomi-ai-alt.vue +5 -0
- package/src/components/icon/components/nomi-bell.vue +5 -0
- package/src/components/icon/components/nomi-budget.vue +4 -0
- package/src/components/icon/components/nomi-calendar-payment.vue +10 -0
- package/src/components/icon/components/nomi-card-plus.vue +1 -0
- package/src/components/icon/components/nomi-cash-provider.vue +9 -0
- package/src/components/icon/components/nomi-category-edit.vue +5 -0
- package/src/components/icon/components/nomi-delta.vue +7 -0
- package/src/components/icon/components/nomi-exit-right.vue +4 -0
- package/src/components/icon/components/nomi-help.vue +2 -3
- package/src/components/icon/components/nomi-lock.vue +1 -1
- package/src/components/icon/components/nomi-project.vue +2 -2
- package/src/components/icon/components/nomi-refresh-off.vue +4 -0
- package/src/components/icon/components/nomi-refresh.vue +4 -0
- package/src/components/icon/components/nomi-scissors.vue +1 -1
- package/src/components/icon/components/nomi-start.vue +28 -0
- package/src/components/icon/components/nomi-table-view.vue +1 -4
- package/src/components/icon/components/nomi-transactions-delete.vue +5 -0
- package/src/components/icon/components/nomi-type-array.vue +6 -0
- package/src/components/icon/components/nomi-type-boolean.vue +5 -0
- package/src/components/icon/components/nomi-type-date.vue +4 -0
- package/src/components/icon/components/nomi-type-null.vue +4 -0
- package/src/components/icon/components/nomi-type-number.vue +4 -0
- package/src/components/icon/components/nomi-type-object.vue +4 -0
- package/src/components/icon/components/nomi-type-string.vue +4 -0
- package/src/components/icon/components/nomi-unarchive.vue +17 -0
- package/src/components/icon/components/nomi-unlink.vue +10 -0
- package/src/components/icon/components/nomi-user.vue +3 -3
- package/src/components/icon/components/nomi-warning-triangle.vue +6 -0
- package/src/components/icon/components/nomi-warning_triangle_filled.vue +6 -0
- package/src/components/icon/convert-icons.js +3 -0
- package/src/components/icon/icons.js +390 -312
- package/src/components/icon/new-icons/ai-alt.svg +4 -0
- package/src/components/icon/new-icons/arrow-right-alt.svg +3 -0
- package/src/components/icon/new-icons/arrow-right.svg +3 -0
- package/src/components/icon/new-icons/arrow_left.svg +3 -0
- package/src/components/icon/new-icons/automation.svg +4 -0
- package/src/components/icon/new-icons/balance.svg +3 -0
- package/src/components/icon/new-icons/balance_turnover.svg +4 -0
- package/src/components/icon/new-icons/bar-horizontal.svg +6 -0
- package/src/components/icon/new-icons/bell.svg +4 -0
- package/src/components/icon/new-icons/calendar-payment.svg +9 -0
- package/src/components/icon/new-icons/card-plus.svg +1 -0
- package/src/components/icon/new-icons/cash-provider.svg +8 -0
- package/src/components/icon/new-icons/cash-repeat.svg +5 -0
- package/src/components/icon/new-icons/cash.svg +3 -0
- package/src/components/icon/new-icons/cashflow.svg +3 -0
- package/src/components/icon/new-icons/category-edit.svg +4 -0
- package/src/components/icon/new-icons/category.svg +4 -0
- package/src/components/icon/new-icons/category_alt.svg +3 -0
- package/src/components/icon/new-icons/chart-bars.svg +5 -0
- package/src/components/icon/new-icons/chart-donut.svg +3 -0
- package/src/components/icon/new-icons/chart-funnel.svg +5 -0
- package/src/components/icon/new-icons/chart-kpi.svg +7 -0
- package/src/components/icon/new-icons/chart-line.svg +4 -0
- package/src/components/icon/new-icons/chart-lines.svg +5 -0
- package/src/components/icon/new-icons/check-alt.svg +3 -0
- package/src/components/icon/new-icons/check.svg +3 -0
- package/src/components/icon/new-icons/chevron-down.svg +3 -0
- package/src/components/icon/new-icons/chevron-left.svg +3 -0
- package/src/components/icon/new-icons/chevron-right.svg +3 -0
- package/src/components/icon/new-icons/chevron-up.svg +3 -0
- package/src/components/icon/new-icons/collapse.svg +6 -0
- package/src/components/icon/new-icons/control-panel.svg +7 -0
- package/src/components/icon/new-icons/credit.svg +3 -0
- package/src/components/icon/new-icons/currencies.svg +3 -0
- package/src/components/icon/new-icons/debt.svg +3 -0
- package/src/components/icon/new-icons/delta.svg +6 -0
- package/src/components/icon/new-icons/demo.svg +6 -0
- package/src/components/icon/new-icons/dev.svg +3 -0
- package/src/components/icon/new-icons/dots.svg +5 -0
- package/src/components/icon/new-icons/duplicate.svg +4 -0
- package/src/components/icon/new-icons/exit-right.svg +3 -0
- package/src/components/icon/new-icons/export.svg +3 -0
- package/src/components/icon/new-icons/file.svg +3 -0
- package/src/components/icon/new-icons/folder.svg +3 -0
- package/src/components/icon/new-icons/goods-turnover.svg +3 -0
- package/src/components/icon/new-icons/goods.svg +4 -0
- package/src/components/icon/new-icons/help-alt.svg +3 -0
- package/src/components/icon/new-icons/help.svg +2 -3
- package/src/components/icon/new-icons/history.svg +6 -0
- package/src/components/icon/new-icons/integration.svg +3 -0
- package/src/components/icon/new-icons/link.svg +5 -0
- package/src/components/icon/new-icons/lock.svg +1 -1
- package/src/components/icon/new-icons/menu.svg +5 -0
- package/src/components/icon/new-icons/minus.svg +3 -0
- package/src/components/icon/new-icons/payment_calendar.svg +3 -0
- package/src/components/icon/new-icons/pc.svg +3 -0
- package/src/components/icon/new-icons/pen-alt.svg +3 -0
- package/src/components/icon/new-icons/planFact.svg +4 -0
- package/src/components/icon/new-icons/pnl.svg +7 -0
- package/src/components/icon/new-icons/project.svg +2 -2
- package/src/components/icon/new-icons/project_alt.svg +3 -0
- package/src/components/icon/new-icons/project_alt2.svg +3 -0
- package/src/components/icon/new-icons/promo.svg +3 -0
- package/src/components/icon/new-icons/refresh-off.svg +3 -0
- package/src/components/icon/new-icons/refresh.svg +3 -0
- package/src/components/icon/new-icons/scissors.svg +1 -1
- package/src/components/icon/new-icons/segment.svg +3 -0
- package/src/components/icon/new-icons/start.svg +27 -0
- package/src/components/icon/new-icons/strongbox.svg +3 -0
- package/src/components/icon/new-icons/subscription.svg +3 -0
- package/src/components/icon/new-icons/table-view.svg +1 -4
- package/src/components/icon/new-icons/time.svg +3 -0
- package/src/components/icon/new-icons/transactions_alt.svg +6 -0
- package/src/components/icon/new-icons/transactions_delete.svg +4 -0
- package/src/components/icon/new-icons/type-array.svg +5 -0
- package/src/components/icon/new-icons/type-boolean.svg +4 -0
- package/src/components/icon/new-icons/type-date.svg +3 -0
- package/src/components/icon/new-icons/type-null.svg +3 -0
- package/src/components/icon/new-icons/type-number.svg +3 -0
- package/src/components/icon/new-icons/type-object.svg +3 -0
- package/src/components/icon/new-icons/type-string.svg +3 -0
- package/src/components/icon/new-icons/types.svg +6 -0
- package/src/components/icon/new-icons/unarchive.svg +16 -0
- package/src/components/icon/new-icons/unlink.svg +9 -0
- package/src/components/icon/new-icons/user.svg +3 -3
- package/src/components/icon/new-icons/user_plus.svg +10 -0
- package/src/components/icon/new-icons/warehouse.svg +3 -0
- package/src/components/icon/new-icons/warning_triangle.svg +5 -0
- package/src/components/icon/new-icons/warning_triangle_filled.svg +5 -0
- package/src/components/kanban/BoardCard.vue +1 -1
- package/src/components/kanban/BoardCardTimer.vue +1 -1
- package/src/components/modal/DeleteConfirmModal.vue +10 -6
- package/src/components/modal/ItemEditor.vue +1 -1
- package/src/components/modal/Modal.vue +1 -1
- package/src/components/overlay/SensitiveOverlay.vue +2 -4
- package/src/components/panels/Panel.vue +110 -23
- package/src/components/panels/PanelItemEdit.vue +8 -6
- package/src/components/panels/PanelList.vue +164 -40
- package/src/components/panels/helpers.ts +41 -13
- package/src/components/popover/Popover.vue +105 -22
- package/src/components/segmented-control/SegmentedControl.vue +9 -3
- package/src/components/sortable/draggable.js +1 -1
- package/src/components/table/Table2.vue +68 -67
- package/src/components/table/TableBody.vue +17 -22
- package/src/components/table/TableGroup.vue +40 -24
- package/src/components/table/TableHeader.vue +86 -81
- package/src/components/table/TableRowToggle.vue +1 -9
- package/src/components/table/TableRows.vue +49 -55
- package/src/components/table/mobile.js +4 -0
- package/src/components/table/table2.scss +34 -15
- package/src/components/text-field/MoneyField.vue +10 -4
- package/src/components/text-field/TextField.vue +17 -8
- package/src/components/tree/TreeEditor.vue +3 -2
- package/src/components/view/View.vue +80 -207
- package/src/directives/appendToBody.js +1 -0
- package/src/helpers/validators.js +9 -35
- package/src/helpers/validators.spec.js +11 -48
- package/src/locales/en.js +4 -6
- package/src/locales/pl.js +158 -0
- package/src/locales/uk.js +6 -7
- package/src/components/icon/components/nomi-calendar-view.vue +0 -4
- package/src/components/icon/components/nomi-kanban-view.vue +0 -6
- package/src/components/icon/components/nomi-list-view.vue +0 -7
- package/src/components/icon/components/nomi-table-config.vue +0 -9
- package/src/components/icon/new-icons/calendar-view.svg +0 -3
- package/src/components/icon/new-icons/kanban-view.svg +0 -5
- package/src/components/icon/new-icons/list-view.svg +0 -6
- package/src/components/icon/new-icons/table-config.svg +0 -8
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
--itf-table-alt-bg: #F9FAFB;
|
|
8
8
|
--itf-table-alt-selected-bg: #eff1f3;
|
|
9
9
|
--itf-table-header-bg: #f5f7f8;
|
|
10
|
-
--itf-table-header-color: #
|
|
10
|
+
--itf-table-header-color: #7A818EA5;
|
|
11
11
|
--itf-table-mirror-bg: #F2F4F7;
|
|
12
12
|
--itf-table-border-color: transparent; //var(--itf-table-header-bg);
|
|
13
|
-
--itf-table-header-border-color: #
|
|
13
|
+
--itf-table-header-border-color: #7A818E33;
|
|
14
14
|
--itf-table-border-base-color: var(--itf-table-header-bg); // кольори границь таблиці без внутрішніх рядків
|
|
15
15
|
--itf-table-border-base-width: 2px;
|
|
16
16
|
--itf-table-hover-header-bg: #dfe5ef;
|
|
@@ -23,8 +23,6 @@
|
|
|
23
23
|
--itf-table-summary-text: var(--bs-tertiary-color);
|
|
24
24
|
--itf-table-table-border-radius: 1rem;
|
|
25
25
|
--itf-table-header-height: 2.25rem;
|
|
26
|
-
--itf-table-divider-bg: #F7F8FA;
|
|
27
|
-
--itf-table-divider-border: rgba(238, 238, 238, 1);
|
|
28
26
|
|
|
29
27
|
--group-title-height: 40px;
|
|
30
28
|
--table-row-height: none;
|
|
@@ -45,9 +43,6 @@ body[data-theme="dark"] {
|
|
|
45
43
|
--itf-table-selected-bg: #011534;
|
|
46
44
|
--itf-table-active-bg: #022e72;
|
|
47
45
|
--itf-table-summary-text: #82909d80;
|
|
48
|
-
--itf-table-border-base-color: var(--itf-table-header-bg);
|
|
49
|
-
--itf-table-divider-bg: #0f0f0f;
|
|
50
|
-
--itf-table-divider-border: rgb(100, 100, 100, .1);
|
|
51
46
|
}
|
|
52
47
|
.itf-table2 {
|
|
53
48
|
font-size: var(--itf-table-content-font-size, var(--itf-table-font-size));
|
|
@@ -65,7 +60,7 @@ body[data-theme="dark"] {
|
|
|
65
60
|
height: 100%;
|
|
66
61
|
}
|
|
67
62
|
.scroller {
|
|
68
|
-
|
|
63
|
+
margin-bottom: 12px;
|
|
69
64
|
}
|
|
70
65
|
.scrollable-x {
|
|
71
66
|
overflow-x: scroll;
|
|
@@ -102,18 +97,34 @@ body[data-theme="dark"] {
|
|
|
102
97
|
position: sticky;
|
|
103
98
|
top: 0;
|
|
104
99
|
bottom: 0;
|
|
105
|
-
right:
|
|
100
|
+
right: -.5rem;
|
|
106
101
|
z-index: 8;
|
|
107
|
-
padding-right: 5px;
|
|
108
|
-
padding-left: 5px;
|
|
109
102
|
display: flex;
|
|
110
103
|
align-items: center;
|
|
104
|
+
|
|
105
|
+
@media (max-width: 768px) {
|
|
106
|
+
position: relative;
|
|
107
|
+
opacity: 1;
|
|
108
|
+
}
|
|
111
109
|
}
|
|
112
110
|
.on-hover {
|
|
113
111
|
opacity: 0;
|
|
112
|
+
width: 0;
|
|
113
|
+
padding: 4px .5rem;
|
|
114
|
+
overflow: hidden;
|
|
114
115
|
pointer-events: none;
|
|
116
|
+
position: absolute;
|
|
117
|
+
right: 0;
|
|
118
|
+
background: linear-gradient(90deg, transparent 0, var(--itf-table2-row-bg) 10px);
|
|
119
|
+
|
|
120
|
+
@media (max-width: 768px) {
|
|
121
|
+
width: max-content;
|
|
122
|
+
opacity: 1;
|
|
123
|
+
position: relative;
|
|
124
|
+
}
|
|
115
125
|
}
|
|
116
126
|
.table-row-template:hover .on-hover {
|
|
127
|
+
width: max-content;
|
|
117
128
|
opacity: 1;
|
|
118
129
|
pointer-events: all;
|
|
119
130
|
}
|
|
@@ -229,6 +240,9 @@ body[data-theme="dark"] {
|
|
|
229
240
|
&:not(.draggable-container--is-dragging):hover .table-view-header-value {
|
|
230
241
|
z-index: 39;
|
|
231
242
|
}
|
|
243
|
+
&:not(.draggable-container--is-dragging):hover .sticky {
|
|
244
|
+
z-index: 40;
|
|
245
|
+
}
|
|
232
246
|
&:after {
|
|
233
247
|
content: "";
|
|
234
248
|
position: absolute;
|
|
@@ -437,14 +451,20 @@ body[data-theme="dark"] {
|
|
|
437
451
|
.indicator {
|
|
438
452
|
border-left: var(--itf-table-border-base-width) solid var(--itf-table2-border-color);
|
|
439
453
|
}
|
|
454
|
+
|
|
455
|
+
&.disabled {
|
|
456
|
+
.table-view-item-value {
|
|
457
|
+
opacity: 0.5;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
440
460
|
}
|
|
441
461
|
|
|
442
462
|
&__row-divider {
|
|
443
|
-
background-color:
|
|
463
|
+
background-color: #F7F8FA;
|
|
444
464
|
height: 5px;
|
|
445
465
|
padding: 0;
|
|
446
|
-
border-top: 1px solid
|
|
447
|
-
border-bottom: 1px solid
|
|
466
|
+
border-top: 1px solid rgba(238, 238, 238, 1);
|
|
467
|
+
border-bottom: 1px solid rgba(238, 238, 238, 1);
|
|
448
468
|
}
|
|
449
469
|
//&:hover, &.permanent-editable-border {
|
|
450
470
|
// .table-view-item-value.editable {
|
|
@@ -457,7 +477,6 @@ body[data-theme="dark"] {
|
|
|
457
477
|
position: relative;
|
|
458
478
|
z-index: 2;
|
|
459
479
|
width: 100%;
|
|
460
|
-
display: flex;
|
|
461
480
|
height: 100%;
|
|
462
481
|
background: var(--itf-table2-row-bg)
|
|
463
482
|
}
|
|
@@ -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] ===
|
|
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="{ '
|
|
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="
|
|
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="{ '
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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
|
|
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
|
|
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" />
|
|
@@ -4,25 +4,26 @@
|
|
|
4
4
|
<itf-filter-panel
|
|
5
5
|
:search-placeholder="searchPlaceholder"
|
|
6
6
|
search
|
|
7
|
-
|
|
7
|
+
:visible="!noFilters"
|
|
8
|
+
:filters-only="filtersOnly"
|
|
9
|
+
ref="filters"
|
|
10
|
+
:mini="panel.isMultiple()"
|
|
8
11
|
class="py-2 px-3"
|
|
9
|
-
:static-filters="filters"
|
|
10
12
|
:endpoint="filtersEndpoint"
|
|
11
13
|
:panel="panel"
|
|
12
14
|
v-model="filter"
|
|
13
15
|
@loaded="onFilterSet($event, true)"
|
|
14
16
|
@change="onFilterSet($event, false)"
|
|
15
|
-
@set-table-schema="setTableSchema"
|
|
16
17
|
>
|
|
17
18
|
<template #after-filter-btn>
|
|
18
|
-
<itf-dropdown v-if="$refs.table &&
|
|
19
|
+
<itf-dropdown v-if="$refs.table && schema" shadow append-to-context :button-options="{ default: true, icon: true }" class="h-100" autoclose="outside">
|
|
19
20
|
<template #button>
|
|
20
|
-
<itf-icon new name="table-
|
|
21
|
+
<itf-icon new name="table-view" />
|
|
21
22
|
</template>
|
|
22
23
|
<div class="dropdown-header">
|
|
23
24
|
{{ $t('components.table.columns') }}
|
|
24
25
|
</div>
|
|
25
|
-
<a v-for="(property, n) of
|
|
26
|
+
<a v-for="(property, n) of schema.properties" :key="n" href="" @click.stop.prevent="$refs.table.toggleVisibility(property.property)" class="dropdown-item justify-content-between d-flex gap-3">
|
|
26
27
|
<div class="d-flex align-items-center gap-1">
|
|
27
28
|
<itf-icon v-if="property.icon" :size="24" new :name="property.icon" />
|
|
28
29
|
{{getTitle(property.title)}}
|
|
@@ -41,101 +42,64 @@
|
|
|
41
42
|
</div>
|
|
42
43
|
</a>
|
|
43
44
|
</itf-dropdown>
|
|
44
|
-
<itf-dropdown v-if="downloadEndpoint" shadow append-to-context :button-options="{ default: true, small: true }" class="h-100" autoclose="outside">
|
|
45
|
-
<template #button>
|
|
46
|
-
<itf-icon name="download"/>
|
|
47
|
-
{{ $t('export') }}
|
|
48
|
-
</template>
|
|
49
|
-
<a v-for="(item, n) in getDownloadLinks()" target="_blank" :key="n" :href="item.link" class="dropdown-item">
|
|
50
|
-
{{item.title}}
|
|
51
|
-
</a>
|
|
52
|
-
</itf-dropdown>
|
|
53
|
-
|
|
54
|
-
<slot name="before-tabs"></slot>
|
|
55
|
-
|
|
56
|
-
<itf-segmented-control
|
|
57
|
-
v-if="tabs.length > 1"
|
|
58
|
-
class="small"
|
|
59
|
-
v-model="currentTab"
|
|
60
|
-
item-key="value"
|
|
61
|
-
:items="tabs"
|
|
62
|
-
>
|
|
63
|
-
<template #item="{ item }">
|
|
64
|
-
<div class="d-flex align-items-center">
|
|
65
|
-
<itf-icon class="text-muted" new :name="item.icon" />
|
|
66
|
-
{{item.text}}
|
|
67
|
-
</div>
|
|
68
|
-
</template>
|
|
69
|
-
</itf-segmented-control>
|
|
70
45
|
</template>
|
|
71
46
|
</itf-filter-panel>
|
|
72
47
|
|
|
73
|
-
<div
|
|
74
|
-
<div class="position-
|
|
75
|
-
|
|
48
|
+
<div class="flex-grow-1 px-3 d-flex flex-column">
|
|
49
|
+
<div class="position-relative flex-grow-1">
|
|
50
|
+
<itf-table
|
|
51
|
+
ref="table"
|
|
52
|
+
style="--shadow-area-width: 0px;"
|
|
53
|
+
absolute
|
|
54
|
+
striped
|
|
55
|
+
clickable
|
|
56
|
+
column-sorting
|
|
57
|
+
column-resizing
|
|
58
|
+
:indicator-type="indicatorType"
|
|
59
|
+
class="permanent-checkboxes"
|
|
60
|
+
divider-property="hasDivider"
|
|
61
|
+
subrows-property="children"
|
|
62
|
+
:state-name="stateName"
|
|
63
|
+
id-property="id"
|
|
64
|
+
:rows="preparedItems"
|
|
65
|
+
:schema="schema"
|
|
66
|
+
:sorting="sorting"
|
|
67
|
+
:active="activeIds"
|
|
68
|
+
:show-actions="showActions"
|
|
69
|
+
:expanded-ids.sync="expandedIds"
|
|
70
|
+
v-model="selectedIds"
|
|
71
|
+
@row-click="$emit('open', $event)"
|
|
72
|
+
@update:sorting="updateSorting($event)"
|
|
73
|
+
>
|
|
74
|
+
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
75
|
+
<slot :name="name" v-bind="slotData || {}"/>
|
|
76
|
+
</template>
|
|
77
|
+
<template v-for="(_, name) in $scopedSlots" #[name]="slotData">
|
|
78
|
+
<slot :name="name" v-bind="slotData || {}"/>
|
|
79
|
+
</template>
|
|
80
|
+
</itf-table>
|
|
76
81
|
</div>
|
|
77
82
|
</div>
|
|
78
|
-
<slot v-else-if="currentTab === 'board'" name="kanban-view"></slot>
|
|
79
|
-
<slot v-else-if="currentTab === 'calendar'" name="calendar-view"></slot>
|
|
80
|
-
<slot v-else name="table-view">
|
|
81
|
-
<div class="flex-grow-1 px-3 d-flex flex-column">
|
|
82
|
-
<div class="position-relative flex-grow-1">
|
|
83
|
-
<itf-table
|
|
84
|
-
ref="table"
|
|
85
|
-
style="--shadow-area-width: 0px;"
|
|
86
|
-
absolute
|
|
87
|
-
striped
|
|
88
|
-
clickable
|
|
89
|
-
column-sorting
|
|
90
|
-
column-resizing
|
|
91
|
-
:indicator-type="indicatorType"
|
|
92
|
-
class="permanent-checkboxes"
|
|
93
|
-
:state-name="stateName"
|
|
94
|
-
id-property="id"
|
|
95
|
-
:sort-as-string="sortAsString"
|
|
96
|
-
:rows="items"
|
|
97
|
-
:group-by="groupBy"
|
|
98
|
-
:schema="tableSchema"
|
|
99
|
-
:sorting.sync="sorting"
|
|
100
|
-
:active="activeIds"
|
|
101
|
-
:no-select-all="noSelectAll"
|
|
102
|
-
:show-actions="showActions"
|
|
103
|
-
:indicator-width="indicatorWidth"
|
|
104
|
-
v-model="selectedIds"
|
|
105
|
-
@row-click="$emit('open', $event)"
|
|
106
|
-
@update:sorting="updateSorting($event)"
|
|
107
|
-
>
|
|
108
|
-
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
109
|
-
<slot :name="name" v-bind="slotData || {}"/>
|
|
110
|
-
</template>
|
|
111
|
-
<template v-for="(_, name) in $scopedSlots" #[name]="slotData">
|
|
112
|
-
<slot :name="name" v-bind="slotData || {}"/>
|
|
113
|
-
</template>
|
|
114
|
-
</itf-table>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
</slot>
|
|
118
83
|
|
|
119
84
|
<itf-pagination
|
|
120
85
|
class="my-2 px-3"
|
|
121
|
-
v-if="showPagination"
|
|
122
86
|
show-size
|
|
123
87
|
:size="size"
|
|
124
|
-
:items="
|
|
88
|
+
:items="preparedItems"
|
|
125
89
|
:pages="countPages"
|
|
126
90
|
:value="page"
|
|
127
91
|
@input="updatePage($event)"
|
|
128
92
|
@per-page="updateSizePerPage($event)"
|
|
129
93
|
>
|
|
130
94
|
<template #center>
|
|
131
|
-
<slot name="pagination-center"
|
|
95
|
+
<slot name="pagination-center" />
|
|
132
96
|
</template>
|
|
133
97
|
</itf-pagination>
|
|
134
98
|
</div>
|
|
135
99
|
|
|
136
100
|
</template>
|
|
137
101
|
<script>
|
|
138
|
-
import {Vue, ModelSync, Component, Prop, Inject
|
|
102
|
+
import { Vue, ModelSync, Component, Prop, Inject } from 'vue-property-decorator';
|
|
139
103
|
import loading from '../../directives/loading';
|
|
140
104
|
import itfTable from '../table/Table2.vue';
|
|
141
105
|
import itfFilterPanel from '../filter/FilterPanel.vue';
|
|
@@ -143,16 +107,11 @@ import itfPagination from '../pagination/Pagination2.vue';
|
|
|
143
107
|
import itfTableBody from "../table/TableBody.vue";
|
|
144
108
|
import itfIcon from "../icon/Icon.vue";
|
|
145
109
|
import itfDropdown from "../dropdown/Dropdown.vue";
|
|
146
|
-
import itfSegmentedControl from '../segmented-control/SegmentedControl.vue';
|
|
147
|
-
import itfButton from '@itfin/components/src/components/button/Button.vue';
|
|
148
110
|
|
|
149
111
|
export default @Component({
|
|
150
112
|
name: 'itfView',
|
|
151
113
|
components: {
|
|
152
|
-
|
|
153
|
-
itfSegmentedControl,
|
|
154
|
-
itfDropdown,
|
|
155
|
-
itfIcon,
|
|
114
|
+
itfDropdown, itfIcon,
|
|
156
115
|
itfPagination,
|
|
157
116
|
itfFilterPanel,
|
|
158
117
|
itfTableBody,
|
|
@@ -167,32 +126,24 @@ class itfView extends Vue {
|
|
|
167
126
|
@ModelSync('value', 'input') selectedIds;
|
|
168
127
|
|
|
169
128
|
@Prop({ type: Boolean }) loading;
|
|
129
|
+
@Prop({ type: Boolean }) filtersOnly;
|
|
130
|
+
@Prop({ type: Boolean }) noFilters;
|
|
170
131
|
@Prop({ type: Array }) filters;
|
|
171
|
-
@Prop({ type: Object }) schema;
|
|
132
|
+
@Prop({ type: Object, required: true }) schema;
|
|
133
|
+
// @Prop({ default: 20 }) size;
|
|
134
|
+
// @Prop({ default: 1 }) page;
|
|
172
135
|
@Prop(String) defaultSorting;
|
|
173
136
|
@Prop(String) endpoint;
|
|
174
137
|
@Prop(String) filtersEndpoint;
|
|
175
138
|
@Prop(String) itemsKey;
|
|
176
|
-
@Prop({ type: String, default: null }) groupBy;
|
|
177
|
-
@Prop({ type: String, default: null }) downloadEndpoint; // префікс апі для завантаження
|
|
178
|
-
@Prop({ type: String, default: 'totals' }) totalsKey;
|
|
179
139
|
@Prop(String) panelKey;
|
|
180
140
|
@Prop(String) stateName;
|
|
181
141
|
@Prop({ type: String, default: 'checkbox' }) indicatorType;
|
|
182
|
-
@Prop({ type: String, default: 'list' }) tab;
|
|
183
142
|
@Prop({ type: String, default () { return this.$t('components.table.search'); } }) searchPlaceholder;
|
|
184
143
|
@Prop() panel;
|
|
144
|
+
@Prop() hardFilter; // встановлює жорсткий фільтр, наприклад, треба завжди показувати лише по контрагенту
|
|
185
145
|
@Prop(Boolean) showActions;
|
|
186
|
-
@Prop({ type:
|
|
187
|
-
@Prop(Boolean) listViewEnabled;
|
|
188
|
-
@Prop(Boolean) kanbanViewEnabled;
|
|
189
|
-
@Prop(Boolean) calendarViewEnabled;
|
|
190
|
-
@Prop(Boolean) noSelectAll;
|
|
191
|
-
@Prop({ type: Boolean, default: true }) tableViewEnabled;
|
|
192
|
-
@Prop(Boolean) sortAsString;
|
|
193
|
-
@Prop(Boolean) oldFormat;
|
|
194
|
-
@Prop({ default: 45 }) indicatorWidth;
|
|
195
|
-
@Prop({type: Function, default: null }) onSplitSlectedIds // якщо потрібно розділяти вибрані рядки в таблиці на дві групи
|
|
146
|
+
@Prop({ type: Array, default: () => [] }) disabledIds;
|
|
196
147
|
|
|
197
148
|
page = 1;
|
|
198
149
|
total = 0;
|
|
@@ -202,74 +153,11 @@ class itfView extends Vue {
|
|
|
202
153
|
filter = {};
|
|
203
154
|
loadingData = false;
|
|
204
155
|
activeIds = [];
|
|
205
|
-
|
|
206
|
-
totals = null;
|
|
207
|
-
|
|
208
|
-
@Watch('selectedIds', { deep: true, immediate: true })
|
|
209
|
-
updateSelectedIds() {
|
|
210
|
-
if(this.onSplitSlectedIds && this.items.length && this.selectedIds.length) {
|
|
211
|
-
this.onSplitSlectedIds(this.selectedIds, this.items);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
getDownloadLinks() {
|
|
216
|
-
const state = this.$refs.table ? this.$refs.table.getTableState() : null;
|
|
217
|
-
const filter = { ...this.filter };
|
|
218
|
-
const sorting = this.sorting;
|
|
219
|
-
const filterableColumnsNames = (state?.columns ?? []).filter(column => column.visible).map(column => column.property);
|
|
220
|
-
|
|
221
|
-
const filterWithValue = Object.fromEntries(Object.entries(filter).filter(([_, value]) => typeof value !== 'undefined'));
|
|
222
|
-
const params = {
|
|
223
|
-
...filterWithValue,
|
|
224
|
-
sort: sorting
|
|
225
|
-
};
|
|
226
|
-
if (filterableColumnsNames.length) {
|
|
227
|
-
params.columns = filterableColumnsNames.join(',')
|
|
228
|
-
}
|
|
229
|
-
const xlsQueryParams = new URLSearchParams({ ...params, format: 'xlsx' }).toString();
|
|
230
|
-
const csvQueryParams = new URLSearchParams({ ...params, format: 'csv' }).toString();
|
|
231
|
-
return [
|
|
232
|
-
{ title: 'Excel (xlsx)', link: `${this.downloadEndpoint}?${xlsQueryParams}` },
|
|
233
|
-
{ title: 'Plain text (csv)', link: `${this.downloadEndpoint}?${csvQueryParams}` },
|
|
234
|
-
];
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
get currentTab() {
|
|
238
|
-
return this.tab;
|
|
239
|
-
}
|
|
156
|
+
expandedIds = [];
|
|
240
157
|
|
|
241
|
-
|
|
242
|
-
this
|
|
243
|
-
this.
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
get tabs() {
|
|
247
|
-
const views = [];
|
|
248
|
-
if (this.listViewEnabled) {
|
|
249
|
-
views.push({ value: 'list', text: this.$t('list'), icon: 'list-view' });
|
|
250
|
-
}
|
|
251
|
-
if (this.kanbanViewEnabled) {
|
|
252
|
-
views.push({ value: 'board', text: this.$t('board'), icon: 'kanban-view' });
|
|
253
|
-
}
|
|
254
|
-
if (this.calendarViewEnabled) {
|
|
255
|
-
views.push({ value: 'calendar', text: this.$t('calendar'), icon: 'calendar-view' });
|
|
256
|
-
}
|
|
257
|
-
if (this.tableViewEnabled) {
|
|
258
|
-
views.push({ value: 'table', text: this.$t('table'), icon: 'table-view' });
|
|
259
|
-
}
|
|
260
|
-
return views;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
get tableSchema() {
|
|
264
|
-
if (this.tableColumns) {
|
|
265
|
-
return {
|
|
266
|
-
properties: this.tableColumns
|
|
267
|
-
}
|
|
268
|
-
} else if (this.schema) {
|
|
269
|
-
return this.schema
|
|
270
|
-
} else {
|
|
271
|
-
return {}
|
|
272
|
-
}
|
|
158
|
+
get preparedItems() {
|
|
159
|
+
const disabledIdsSet = new Set(this.disabledIds);
|
|
160
|
+
return this.items.map(item => ({ ...item, isDisabled: disabledIdsSet.has(item.id) }));
|
|
273
161
|
}
|
|
274
162
|
|
|
275
163
|
created() {
|
|
@@ -291,42 +179,39 @@ class itfView extends Vue {
|
|
|
291
179
|
}
|
|
292
180
|
}
|
|
293
181
|
|
|
294
|
-
async loadData() {
|
|
182
|
+
async loadData(reloadFilters = false) {
|
|
295
183
|
if (!this.endpoint) {
|
|
296
184
|
return;
|
|
297
185
|
}
|
|
186
|
+
if (reloadFilters) {
|
|
187
|
+
this.loadFilters();
|
|
188
|
+
}
|
|
298
189
|
this.$emit('load', this.filter);
|
|
299
190
|
this.loadingData = true;
|
|
300
191
|
await this.$try(async () => {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
filter = Object.keys(filter).reduce((acc, key) => {
|
|
304
|
-
acc[`filter[${key}]`] = filter[key];
|
|
305
|
-
return acc;
|
|
306
|
-
}, {})
|
|
307
|
-
}
|
|
308
|
-
const { data, headers } = await this.$axios.get(this.endpoint, {
|
|
192
|
+
const res = await this.$axios.$get(this.endpoint, {
|
|
193
|
+
preventRaceCondition: true,
|
|
309
194
|
params: {
|
|
310
|
-
...filter,
|
|
195
|
+
...Object.assign(this.filter ?? {}, this.hardFilter ?? {}),
|
|
311
196
|
page: this.page,
|
|
312
197
|
size: this.size,
|
|
313
198
|
sort: this.sorting
|
|
314
199
|
}
|
|
315
200
|
});
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
this
|
|
323
|
-
this.totals = data[this.totalsKey];
|
|
324
|
-
this.page = data.meta.page;
|
|
325
|
-
this.total = data.meta.total;
|
|
326
|
-
this.size = data.meta.size;
|
|
201
|
+
this.selectedIds = [];
|
|
202
|
+
this.items = res[this.itemsKey];
|
|
203
|
+
this.page = res.meta.page;
|
|
204
|
+
this.total = res.meta.total;
|
|
205
|
+
this.size = res.meta.size;
|
|
206
|
+
if (res.columns) {
|
|
207
|
+
this.$emit('columns-loaded', res.columns);
|
|
327
208
|
}
|
|
209
|
+
|
|
210
|
+
this.$emit('update:items', this.items);
|
|
211
|
+
this.loadingData = false;
|
|
212
|
+
}, () => {
|
|
213
|
+
this.loadingData = false;
|
|
328
214
|
});
|
|
329
|
-
this.loadingData = false;
|
|
330
215
|
this.$emit('loaded', this.filter);
|
|
331
216
|
}
|
|
332
217
|
|
|
@@ -349,16 +234,14 @@ class itfView extends Vue {
|
|
|
349
234
|
|
|
350
235
|
updatePage (val) {
|
|
351
236
|
this.page = val;
|
|
352
|
-
this.
|
|
353
|
-
this.setPanelPayload({ page: val });
|
|
237
|
+
this.setPanelPayload({ page: val === 1 ? null : val });
|
|
354
238
|
this.loadData();
|
|
355
239
|
}
|
|
356
240
|
|
|
357
241
|
updateSizePerPage (val) {
|
|
358
242
|
this.page = 1;
|
|
359
243
|
this.size = val;
|
|
360
|
-
this.
|
|
361
|
-
this.setPanelPayload({ page: 1, size: val });
|
|
244
|
+
this.setPanelPayload({ page: null, size: val });
|
|
362
245
|
this.loadData();
|
|
363
246
|
localStorage.setItem('sizePerPage', val);
|
|
364
247
|
}
|
|
@@ -394,20 +277,10 @@ class itfView extends Vue {
|
|
|
394
277
|
this.loadData();
|
|
395
278
|
}
|
|
396
279
|
|
|
397
|
-
|
|
398
|
-
this.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
getSorting() {
|
|
402
|
-
return this.sorting;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
getFilter() {
|
|
406
|
-
return this.filter;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
getTableState() {
|
|
410
|
-
return this.$refs.table ? this.$refs.table.getTableState() : null;
|
|
280
|
+
loadFilters() {
|
|
281
|
+
if (this.filtersEndpoint) {
|
|
282
|
+
this.$refs.filters?.loadData();
|
|
283
|
+
}
|
|
411
284
|
}
|
|
412
285
|
}
|
|
413
286
|
</script>
|