@itfin/components 1.4.33 → 1.4.35
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 +1 -1
- package/src/components/app/App.vue +6 -3
- package/src/components/checkbox/Checkbox.vue +1 -1
- package/src/components/checkbox/RadioBox.vue +13 -6
- package/src/components/datepicker/DatePickerInline.vue +62 -129
- package/src/components/filter/FilterPanel.vue +16 -37
- package/src/components/icon/components/nomi-duplicate.vue +5 -0
- package/src/components/panels/PanelItemEdit.vue +8 -6
- package/src/components/panels/PanelLink.vue +15 -6
- package/src/components/panels/PanelList.vue +3 -7
- package/src/components/panels/helpers.ts +4 -10
- package/src/components/table/Table2.vue +61 -65
- package/src/components/table/TableBody.vue +0 -6
- package/src/components/table/TableGroup.vue +4 -14
- package/src/components/table/TableHeader.vue +7 -12
- package/src/components/table/TableRowToggle.vue +1 -9
- package/src/components/table/TableRows.vue +43 -55
- package/src/components/table/table2.scss +25 -15
- package/src/components/view/View.vue +8 -15
package/package.json
CHANGED
|
@@ -74,9 +74,12 @@ class itfApp extends Vue {
|
|
|
74
74
|
try {
|
|
75
75
|
await func();
|
|
76
76
|
} catch (err) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
if (err.code !== 'ERR_CANCELED') {
|
|
78
|
+
console.error(err);
|
|
79
|
+
this.showError(err.message);
|
|
80
|
+
if (errFunc) {
|
|
81
|
+
errFunc(err);
|
|
82
|
+
}
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<div class="itf-checkbox form-check" :class="{ 'form-switch': this.switch, 'itf-checkbox__large': large, 'itf-checkbox__medium': medium }">
|
|
4
4
|
<input class="form-check-input" ref="input" :id="id" type="checkbox" name="checkbox" v-model="isChecked" :disabled="isDisabled" />
|
|
5
|
-
<label :for="id" class="form-check-label">
|
|
5
|
+
<label :for="id" class="form-check-label w-100" :class="{ 'disabled': isDisabled }">
|
|
6
6
|
<slot name="label">
|
|
7
7
|
{{label}}
|
|
8
8
|
<slot name="icon"></slot>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="itf-radio-box form-check card" :class="{ 'itf-radio__large': large, 'itf-radio__medium': medium, 'active': isChecked, 'right': right, 'left': !right }">
|
|
2
|
+
<div class="itf-radio-box form-check card" :class="{ 'disabled': disabled, 'itf-radio__large': large, 'itf-radio__medium': medium, 'active': isChecked, 'right': right, 'left': !right }">
|
|
3
3
|
<input class="form-check-input" :id="id" type="radio" :name="radioName" v-model="isChecked" :value="true" :disabled="disabled" />
|
|
4
4
|
<label :for="id" slot="label" class="form-check-label card-body">
|
|
5
5
|
|
|
@@ -18,6 +18,17 @@
|
|
|
18
18
|
position: relative;
|
|
19
19
|
cursor: pointer;
|
|
20
20
|
|
|
21
|
+
&:not(.disabled) {
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
|
|
24
|
+
.form-check-label {
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.form-check-label {
|
|
30
|
+
cursor: not-allowed;
|
|
31
|
+
}
|
|
21
32
|
&.left {
|
|
22
33
|
padding: 0 0 0 2.5rem;
|
|
23
34
|
|
|
@@ -38,13 +49,9 @@
|
|
|
38
49
|
&.active {
|
|
39
50
|
background-color: rgba(var(--bs-primary-rgb),.1) !important;
|
|
40
51
|
}
|
|
41
|
-
&:hover {
|
|
52
|
+
&:hover:not(.disabled) {
|
|
42
53
|
background-color: rgba(0,0,0,.05);
|
|
43
54
|
}
|
|
44
|
-
|
|
45
|
-
.form-check-label {
|
|
46
|
-
cursor: pointer;
|
|
47
|
-
}
|
|
48
55
|
}
|
|
49
56
|
</style>
|
|
50
57
|
<script>
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
<button
|
|
12
12
|
v-for="(item, n) in daysList"
|
|
13
13
|
:key="n"
|
|
14
|
-
:disabled="!isEnabled(item.date
|
|
15
|
-
:class="{'active': isSelected(item.date
|
|
16
|
-
@click="selectDate(item.date
|
|
14
|
+
:disabled="!isEnabled(item.date)"
|
|
15
|
+
:class="{'active': isSelected(item.date)}"
|
|
16
|
+
@click="selectDate(item.date)"
|
|
17
17
|
class="btn btn-outline-primary btn-sm text-start">
|
|
18
18
|
{{item.title}}
|
|
19
19
|
</button>
|
|
@@ -30,31 +30,29 @@ export default @Component({
|
|
|
30
30
|
name: 'itfDatePickerInline',
|
|
31
31
|
})
|
|
32
32
|
class itfDatePickerInline extends Vue {
|
|
33
|
-
@Prop() value;
|
|
33
|
+
@Prop({ type: String }) value;
|
|
34
34
|
@Prop({ type: String, default: 'yyyy-MM-dd' }) valueFormat;
|
|
35
35
|
@Prop({ type: String, default: ITFSettings.defaultDisplayDateFormat }) displayFormat;
|
|
36
|
+
@Prop({ type: String, default: 'days', validator: (value) => ['days', 'months', 'years'].includes(value) }) startView;
|
|
37
|
+
@Prop({ type: String, default: 'days', validator: (value) => ['days', 'months', 'years'].includes(value) }) minView;
|
|
36
38
|
@Prop({ type: Boolean, default: false }) onlyCalendar;
|
|
39
|
+
@Prop({ type: Boolean, default: false }) range;
|
|
37
40
|
@Prop({ type: Object, default: () => ({}) }) customDays;
|
|
38
41
|
@Prop({ type: [String, Date], default: '' }) minDate;
|
|
39
42
|
@Prop({ type: [String, Date], default: '' }) maxDate;
|
|
40
|
-
@Prop({ type: String, default: 'days' }) minView;
|
|
41
43
|
@Prop({
|
|
42
44
|
type: Array,
|
|
43
45
|
default: function () {
|
|
44
|
-
return [
|
|
45
|
-
{ title: this.$t('components.
|
|
46
|
-
{ title: this.$t('components.
|
|
47
|
-
{ title: this.$t('components.
|
|
48
|
-
{ title: this.$t('components.
|
|
49
|
-
{ title: this.$t('components.
|
|
50
|
-
{ title: this.$t('components.
|
|
51
|
-
{ title: this.$t('components.thisYear'), date: () => [DateTime.local().startOf('year'), DateTime.local().endOf('year')] },
|
|
52
|
-
{ title: this.$t('components.lastYear'), date: () => [DateTime.local().minus({ year: 1 }).startOf('year'), DateTime.local().minus({ year: 1 }).endOf('year')] },
|
|
46
|
+
return [
|
|
47
|
+
{ title: this.$t('components.today'), date: {} },
|
|
48
|
+
{ title: this.$t('components.tomorrow'), date: { days: 1 } },
|
|
49
|
+
{ title: this.$t('components.inAWeek'), date: { week: 1 } },
|
|
50
|
+
{ title: this.$t('components.inAMonth'), date: { month: 1 } },
|
|
51
|
+
{ title: this.$t('components.inAHalfYear'), date: { month: 6 } },
|
|
52
|
+
{ title: this.$t('components.inAYear'), date: { year: 1 } },
|
|
53
53
|
];
|
|
54
54
|
}
|
|
55
55
|
}) daysList;
|
|
56
|
-
@Prop(Boolean) compare;
|
|
57
|
-
@Prop({ type: Array }) range; // for compare mode
|
|
58
56
|
|
|
59
57
|
calendar = null;
|
|
60
58
|
|
|
@@ -62,17 +60,12 @@ class itfDatePickerInline extends Vue {
|
|
|
62
60
|
this.createCalendar();
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
compareMode(value) {
|
|
66
|
-
return this.calendar.compareMode(value);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
63
|
@Watch('minDate')
|
|
70
|
-
@Watch('maxDate')
|
|
71
|
-
@Watch('minView')
|
|
72
64
|
async createCalendar() {
|
|
73
65
|
if (this.calendar) {
|
|
74
66
|
this.destroyCalendar();
|
|
75
67
|
}
|
|
68
|
+
|
|
76
69
|
const [
|
|
77
70
|
{ default: AirDatepicker },
|
|
78
71
|
{ default: localeEn },
|
|
@@ -90,35 +83,28 @@ class itfDatePickerInline extends Vue {
|
|
|
90
83
|
uk: localeUk,
|
|
91
84
|
de: localeDe,
|
|
92
85
|
};
|
|
93
|
-
|
|
86
|
+
this.calendar = new AirDatepicker(this.$refs.calendar, {
|
|
94
87
|
locale: locales[this.$i18n.locale] || locales.en,
|
|
95
88
|
firstDay: 1,
|
|
96
89
|
altFieldDateFormat: this.valueFormat,
|
|
90
|
+
range: this.range,
|
|
91
|
+
view: (this.valueAsLuxon && !this.minView) ? 'days' : this.startView,
|
|
92
|
+
minView: this.minView,
|
|
97
93
|
minDate: this.minDate,
|
|
98
94
|
maxDate: this.maxDate,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
compareRange: true,
|
|
103
|
-
dynamicRange: true,
|
|
104
|
-
toggleSelected: function({ date, datepicker }) {
|
|
105
|
-
if (datepicker.selectedDates.length > 1) {
|
|
106
|
-
datepicker.selectDate(date);
|
|
107
|
-
}
|
|
108
|
-
return false;
|
|
109
|
-
},
|
|
110
|
-
selectedDates: this.valueAsLuxon
|
|
111
|
-
? [this.valueAsLuxon[0].toJSDate(), this.valueAsLuxon[1].toJSDate()]
|
|
112
|
-
: [],
|
|
113
|
-
onSelect: () => {
|
|
114
|
-
if (!this.calendar.rangeDateTo) {
|
|
95
|
+
selectedDates: this.valueAsLuxon ? [this.valueAsLuxon.toJSDate()] : [],
|
|
96
|
+
onSelect: ({ date }) => {
|
|
97
|
+
if (this.range && !this.calendar.rangeDateTo) {
|
|
115
98
|
return;
|
|
116
99
|
}
|
|
117
|
-
this.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
100
|
+
if (this.range) {
|
|
101
|
+
this.updateValue(
|
|
102
|
+
DateTime.fromJSDate(this.calendar.rangeDateFrom).toFormat(this.displayFormat),
|
|
103
|
+
false
|
|
104
|
+
);
|
|
105
|
+
} else {
|
|
106
|
+
this.updateValue(DateTime.fromJSDate(date).toFormat(this.displayFormat));
|
|
107
|
+
}
|
|
122
108
|
},
|
|
123
109
|
onRenderCell: ({ date }) => {
|
|
124
110
|
const strDate = DateTime.fromJSDate(date).toFormat('yyyy-MM-dd');
|
|
@@ -127,22 +113,13 @@ class itfDatePickerInline extends Vue {
|
|
|
127
113
|
}
|
|
128
114
|
return {
|
|
129
115
|
html: this.customDays[strDate].text || false,
|
|
130
|
-
classes: this.customDays[strDate].class || false
|
|
116
|
+
classes: this.customDays[strDate].class || false
|
|
131
117
|
};
|
|
132
118
|
},
|
|
133
|
-
};
|
|
134
|
-
if (this.compare) {
|
|
135
|
-
opts.compareRange = true;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
this.calendar = new AirDatepicker(this.$refs.calendar, opts);
|
|
119
|
+
});
|
|
139
120
|
if (this.valueAsLuxon) {
|
|
140
|
-
this.calendar.setViewDate(this.valueAsLuxon
|
|
141
|
-
}
|
|
142
|
-
if (this.compare) {
|
|
143
|
-
this.calendar.compareMode(true);
|
|
121
|
+
this.calendar.setViewDate(this.valueAsLuxon.toJSDate());
|
|
144
122
|
}
|
|
145
|
-
this.onRangeChange();
|
|
146
123
|
}
|
|
147
124
|
|
|
148
125
|
beforeDestroy() {
|
|
@@ -158,97 +135,59 @@ class itfDatePickerInline extends Vue {
|
|
|
158
135
|
}
|
|
159
136
|
|
|
160
137
|
get valueAsLuxon() {
|
|
161
|
-
if (!this.value
|
|
138
|
+
if (!this.value) {
|
|
162
139
|
return null;
|
|
163
140
|
}
|
|
164
141
|
if (this.valueFormat === 'ISO') {
|
|
165
|
-
return
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
142
|
+
return DateTime.fromISO(this.value);
|
|
143
|
+
}
|
|
144
|
+
return DateTime.fromFormat(this.value, this.valueFormat);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
get displayValue() {
|
|
148
|
+
if (!this.valueAsLuxon) {
|
|
149
|
+
return '';
|
|
169
150
|
}
|
|
170
|
-
return
|
|
171
|
-
DateTime.fromFormat(this.value[0], this.valueFormat),
|
|
172
|
-
DateTime.fromFormat(this.value[1], this.valueFormat),
|
|
173
|
-
];
|
|
151
|
+
return this.valueAsLuxon.toFormat(this.displayFormat);
|
|
174
152
|
}
|
|
175
153
|
|
|
176
|
-
updateValue(
|
|
177
|
-
const val =
|
|
178
|
-
|
|
179
|
-
if (!val || !val.isValid || !val2 || !val2.isValid) {
|
|
154
|
+
updateValue(value, emitEmpty = false) {
|
|
155
|
+
const val = value && DateTime.fromFormat(value, this.displayFormat);
|
|
156
|
+
if (!val || !val.isValid) {
|
|
180
157
|
if (emitEmpty) {
|
|
181
158
|
this.$emit('input', null);
|
|
182
159
|
}
|
|
183
160
|
return;
|
|
184
161
|
}
|
|
185
|
-
if ((this.minDateLuxon && (val < this.minDateLuxon || val2 < this.minDateLuxon)) ||
|
|
186
|
-
(this.maxDateLuxon && (val > this.maxDateLuxon || val2 > this.maxDateLuxon))
|
|
187
|
-
) {
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
162
|
if (this.valueFormat === 'ISO') {
|
|
192
|
-
return this.$emit('input',
|
|
163
|
+
return this.$emit('input', val.toISO());
|
|
193
164
|
}
|
|
194
|
-
this.$emit('input',
|
|
195
|
-
val.toFormat(this.valueFormat),
|
|
196
|
-
val2.toFormat(this.valueFormat),
|
|
197
|
-
]);
|
|
165
|
+
this.$emit('input', val.toFormat(this.valueFormat));
|
|
198
166
|
}
|
|
199
167
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return this.
|
|
168
|
+
isSelected(date) {
|
|
169
|
+
if (!this.valueAsLuxon) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return this.valueAsLuxon.hasSame(DateTime.local().plus(date), 'day');
|
|
205
173
|
}
|
|
206
174
|
|
|
207
|
-
|
|
208
|
-
return typeof
|
|
175
|
+
get minDateLuxon() {
|
|
176
|
+
return this.minDate && (typeof this.minDate === 'string' ? DateTime.fromISO(this.minDate) : DateTime.fromJSDate(this.minDate));
|
|
209
177
|
}
|
|
210
178
|
|
|
211
179
|
isEnabled(date) {
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (this.minDateLuxon) {
|
|
216
|
-
if (this.maxDateLuxon) {
|
|
217
|
-
return lxDate1 > this.minDateLuxon && lxDate2 > this.minDateLuxon && lxDate1 < this.maxDateLuxon && lxDate2 < this.maxDateLuxon;
|
|
218
|
-
} else {
|
|
219
|
-
return lxDate1 > this.minDateLuxon && lxDate2 > this.minDateLuxon;
|
|
220
|
-
}
|
|
221
|
-
} else if (this.maxDateLuxon) {
|
|
222
|
-
return lxDate1 < this.maxDateLuxon && lxDate2 < this.maxDateLuxon;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return true;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
isSelected(date) {
|
|
229
|
-
if (!this.valueAsLuxon || this.valueAsLuxon.length < 2) {
|
|
230
|
-
return false;
|
|
231
|
-
}
|
|
232
|
-
return this.valueAsLuxon[0].hasSame(date[0], 'day') &&
|
|
233
|
-
this.valueAsLuxon[1].hasSame(date[1], 'day');
|
|
180
|
+
const lxDate = DateTime.local().plus(date);
|
|
181
|
+
return !(this.minDateLuxon && lxDate < this.minDateLuxon);
|
|
234
182
|
}
|
|
235
183
|
|
|
236
184
|
selectDate(date) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
this.updateValue(lxDate1.toFormat(this.displayFormat), lxDate2.toFormat(this.displayFormat));
|
|
240
|
-
this.calendar.selectDate([lxDate1.toJSDate(), lxDate2.toJSDate()], { silent: true });
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
@Watch('range')
|
|
244
|
-
onRangeChange() {
|
|
245
|
-
if (!this.calendar) {
|
|
185
|
+
let lxDate = DateTime.local().plus(date);
|
|
186
|
+
if (this.minDateLuxon && lxDate < this.minDateLuxon) {
|
|
246
187
|
return;
|
|
247
188
|
}
|
|
248
|
-
this.calendar.
|
|
249
|
-
|
|
250
|
-
DateTime.fromFormat(this.range[1], this.valueFormat).toJSDate(),
|
|
251
|
-
] : []);
|
|
189
|
+
this.calendar.selectDate(lxDate.toJSDate());
|
|
190
|
+
this.updateValue(lxDate.toFormat(this.displayFormat));
|
|
252
191
|
}
|
|
253
192
|
|
|
254
193
|
@Watch('value')
|
|
@@ -257,13 +196,7 @@ class itfDatePickerInline extends Vue {
|
|
|
257
196
|
this.calendar && this.calendar.clear({ silent: true });
|
|
258
197
|
return;
|
|
259
198
|
}
|
|
260
|
-
|
|
261
|
-
const date2 = this.calendar.rangeDateTo && DateTime.fromJSDate(this.calendar.rangeDateTo).toFormat('yyyy-MM-dd')
|
|
262
|
-
if (date1 !== this.valueAsLuxon[0].toFormat('yyyy-MM-dd') || date2 !== this.valueAsLuxon[1].toFormat('yyyy-MM-dd')) {
|
|
263
|
-
this.$nextTick(() => {
|
|
264
|
-
this.calendar.selectDate(this.valueAsLuxon && [this.valueAsLuxon[0].toJSDate(), this.valueAsLuxon[1].toJSDate()], { silent: true });
|
|
265
|
-
});
|
|
266
|
-
}
|
|
199
|
+
this.calendar.selectDate(this.valueAsLuxon.toJSDate(), { silent: true });
|
|
267
200
|
}
|
|
268
201
|
}
|
|
269
202
|
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="itf-filter-panel d-flex flex-column align-items-start"
|
|
2
|
+
<div class="itf-filter-panel d-flex flex-column gap-3 align-items-start">
|
|
3
3
|
<div v-if="!filtersOnly" class="d-flex gap-2 justify-content-between w-100">
|
|
4
4
|
<slot name="search">
|
|
5
5
|
<div>
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
class="itf-filter-panel__badge"
|
|
36
36
|
:ref="'item-' + n"
|
|
37
37
|
v-model="filter[facet.name]"
|
|
38
|
-
:is-default="filter[facet.name]
|
|
39
|
-
:text="filter[facet.name]
|
|
38
|
+
:is-default="filter[facet.name].isDefault"
|
|
39
|
+
:text="filter[facet.name].label"
|
|
40
40
|
:type="facet.type"
|
|
41
41
|
:icon="facet.icon"
|
|
42
42
|
:options="facet.options"
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
</div>
|
|
53
53
|
<slot name="after-filters"></slot>
|
|
54
54
|
</div>
|
|
55
|
-
<div v-if="loading
|
|
55
|
+
<div v-if="loading">
|
|
56
56
|
<span class="itf-spinner"></span>
|
|
57
57
|
{{$t('loading')}}
|
|
58
58
|
</div>
|
|
@@ -177,8 +177,6 @@ class FilterPanel extends Vue {
|
|
|
177
177
|
(entries) => {
|
|
178
178
|
entries.forEach(entry => {
|
|
179
179
|
const index = parseInt(entry.target.dataset.index);
|
|
180
|
-
const filter = this.filters[index];
|
|
181
|
-
const value = this.filter[filter.name];
|
|
182
180
|
if (entry.isIntersecting) {
|
|
183
181
|
this.visibleItems.add(index); // Додаємо, якщо елемент у полі зору
|
|
184
182
|
} else {
|
|
@@ -208,7 +206,7 @@ class FilterPanel extends Vue {
|
|
|
208
206
|
|
|
209
207
|
get visibleFilters() {
|
|
210
208
|
if (this.mini) {
|
|
211
|
-
return sortBy(this.filters, (f) => this.filter[f.name].isDefault).filter(f => !f.options?.hidden);
|
|
209
|
+
return sortBy(this.filters, (f) => this.filter[f.name].isDefault).filter(f => !f.options?.hidden).slice(0, 2);
|
|
212
210
|
}
|
|
213
211
|
return this.filters.filter(f => !f.options?.hidden);
|
|
214
212
|
}
|
|
@@ -235,7 +233,15 @@ class FilterPanel extends Vue {
|
|
|
235
233
|
|
|
236
234
|
this.filters = this.staticFilters ?? [];
|
|
237
235
|
if (this.endpoint) {
|
|
238
|
-
this.
|
|
236
|
+
this.loading = true;
|
|
237
|
+
await this.$try(async () => {
|
|
238
|
+
const payload = this.panel ? this.panel.getPayload() : {};
|
|
239
|
+
const {filters, tableSchema} = await this.$axios.$get(this.endpoint, { params: payload });
|
|
240
|
+
this.filters = filters;
|
|
241
|
+
this.$emit('set-table-schema', tableSchema);
|
|
242
|
+
this.loadFiltersValue();
|
|
243
|
+
});
|
|
244
|
+
this.loading = false;
|
|
239
245
|
} else {
|
|
240
246
|
this.loadFiltersValue();
|
|
241
247
|
}
|
|
@@ -244,23 +250,6 @@ class FilterPanel extends Vue {
|
|
|
244
250
|
}
|
|
245
251
|
}
|
|
246
252
|
|
|
247
|
-
async loadData() {
|
|
248
|
-
this.loading = true;
|
|
249
|
-
await this.$try(async () => {
|
|
250
|
-
const payload = this.panel ? this.panel.getPayload() : {};
|
|
251
|
-
const {filters, tableSchema} = await this.$axios.$get(this.endpoint, {
|
|
252
|
-
preventRaceCondition: true,
|
|
253
|
-
params: payload
|
|
254
|
-
});
|
|
255
|
-
this.filters = filters;
|
|
256
|
-
this.loading = false;
|
|
257
|
-
this.$emit('set-table-schema', tableSchema);
|
|
258
|
-
this.loadFiltersValue();
|
|
259
|
-
}, () => {
|
|
260
|
-
this.loading = false;
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
253
|
toggleFilters() {
|
|
265
254
|
this.showFilters = !this.showFilters;
|
|
266
255
|
if (this.stateName) {
|
|
@@ -280,7 +269,7 @@ class FilterPanel extends Vue {
|
|
|
280
269
|
filterValue.to = payload.to;
|
|
281
270
|
} else {
|
|
282
271
|
filter[item.name] = payload[item.name] ? this.formatValue(item, { value: payload[item.name] }) : { isDefault: true, ...item.options.defaultValue };
|
|
283
|
-
filterValue[item.name] = payload[item.name];
|
|
272
|
+
filterValue[item.name] = payload[item.name] ?? filter[item.name].value;
|
|
284
273
|
}
|
|
285
274
|
}
|
|
286
275
|
}
|
|
@@ -293,7 +282,6 @@ class FilterPanel extends Vue {
|
|
|
293
282
|
this.filter = filter;
|
|
294
283
|
this.filterValue = filterValue;
|
|
295
284
|
this.$emit('input', this.filterValue);
|
|
296
|
-
this.$emit('loaded', this.filterValue);
|
|
297
285
|
this.initObserver();
|
|
298
286
|
}
|
|
299
287
|
}
|
|
@@ -330,7 +318,6 @@ class FilterPanel extends Vue {
|
|
|
330
318
|
this.panel.setPayload({ ...payload, ...this.filterValue });
|
|
331
319
|
}
|
|
332
320
|
this.$emit('input', this.filterValue);
|
|
333
|
-
this.$emit('change', this.filterValue);
|
|
334
321
|
}
|
|
335
322
|
|
|
336
323
|
get daysList() {
|
|
@@ -376,11 +363,7 @@ class FilterPanel extends Vue {
|
|
|
376
363
|
}
|
|
377
364
|
} else if (facet.type === 'date') {
|
|
378
365
|
const date = DateTime.fromISO(value.value);
|
|
379
|
-
value.label = (date.isValid ?
|
|
380
|
-
value.isDefault = facet.options.defaultValue ? value.value === facet.options.defaultValue.value : false;
|
|
381
|
-
} else if (facet.type === 'month') {
|
|
382
|
-
const date = DateTime.fromISO(value.value);
|
|
383
|
-
value.label = capitalizeFirstLetter((date.isValid ? date : DateTime.fromISO(facet.options.defaultValue.value)).toFormat('LLLL yyyy'));
|
|
366
|
+
value.label = (date.isValid ? value.value : DateTime.fromISO(facet.options.defaultValue.value ?? DateTime.now())).toFormat('dd MMM yyyy');
|
|
384
367
|
value.isDefault = facet.options.defaultValue ? value.value === facet.options.defaultValue.value : false;
|
|
385
368
|
} else if (facet.type === 'facets-list') {
|
|
386
369
|
const firstItem = facet.options.items.find(item => item.value === (Array.isArray(value.value) ? value.value[0] : value.value));
|
|
@@ -419,10 +402,6 @@ class FilterPanel extends Vue {
|
|
|
419
402
|
}
|
|
420
403
|
value.hidden = facet.options?.hidden ?? false;
|
|
421
404
|
return value;
|
|
422
|
-
|
|
423
|
-
function capitalizeFirstLetter(string) {
|
|
424
|
-
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
425
|
-
}
|
|
426
405
|
}
|
|
427
406
|
}
|
|
428
407
|
</script>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<template><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M10 14L9 14C7.11438 14 6.17157 14 5.58579 13.4142C5 12.8284 5 11.8856 5 10L5 9C5 7.11438 5 6.17157 5.58579 5.58579C6.17157 5 7.11438 5 9 5L10 5C11.8856 5 12.8284 5 13.4142 5.58579C14 6.17157 14 7.11438 14 9L14 10C14 11.8856 14 12.8284 13.4142 13.4142C12.8284 14 11.8856 14 10 14Z" fill="currentColor"/>
|
|
3
|
+
<path d="M9.40039 14C9.40039 13.0742 9.39868 12.3195 9.47852 11.7256C9.56068 11.1144 9.73818 10.5841 10.1611 10.1611C10.5841 9.73818 11.1144 9.56068 11.7256 9.47852C12.3195 9.39868 13.0742 9.40039 14 9.40039L15 9.40039C15.9258 9.40039 16.6805 9.39868 17.2744 9.47852C17.8856 9.56068 18.4159 9.73818 18.8389 10.1611C19.2618 10.5841 19.4393 11.1144 19.5215 11.7256C19.6013 12.3195 19.5996 13.0742 19.5996 14L19.5996 15C19.5996 15.9258 19.6013 16.6805 19.5215 17.2744C19.4393 17.8856 19.2618 18.4159 18.8389 18.8389C18.4159 19.2618 17.8856 19.4393 17.2744 19.5215C16.6805 19.6013 15.9258 19.5996 15 19.5996L14 19.5996C13.0742 19.5996 12.3195 19.6013 11.7256 19.5215C11.1144 19.4393 10.5841 19.2618 10.1611 18.8389C9.73818 18.4159 9.56068 17.8856 9.47852 17.2744C9.39868 16.6805 9.40039 15.9258 9.40039 15L9.40039 14Z" fill="currentColor" stroke="white" stroke-width="1.2"/>
|
|
4
|
+
</svg>
|
|
5
|
+
</template>
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-loading="loading" class="px-3 pt-2 h-100">
|
|
2
|
+
<div v-loading="loading" class="px-3 pt-2 h-100 d-flex flex-column">
|
|
3
3
|
<itf-form
|
|
4
4
|
ref="editForm"
|
|
5
|
-
class="d-flex flex-column justify-content-between
|
|
5
|
+
class="d-flex flex-column justify-content-between flex-grow-1"
|
|
6
6
|
@keydown.native.shift.enter.stop.prevent="onSaveClick"
|
|
7
7
|
@keydown.native.esc.stop.prevent="$emit('cancel')"
|
|
8
8
|
>
|
|
9
9
|
<slot></slot>
|
|
10
10
|
<div class="py-3 justify-content-end d-flex align-items-center sticky-container">
|
|
11
11
|
<div v-if="!hideFooter">
|
|
12
|
-
<itf-button v-tooltip.delay="'Hot key: Esc'" secondary :loading="loading" :disabled="loading" @click="$emit('cancel')">
|
|
13
|
-
<span>{{
|
|
12
|
+
<itf-button v-tooltip.delay="'Hot key: Esc'" secondary squircle :loading="loading" :disabled="loading" @click="$emit('cancel')">
|
|
13
|
+
<span>{{ cancelBtnText }}</span>
|
|
14
14
|
</itf-button>
|
|
15
|
-
<itf-button v-tooltip.delay="'Hot key: Shift + Enter'" primary :loading="loading" :disabled="loading" @click="onSaveClick">
|
|
16
|
-
<span>{{
|
|
15
|
+
<itf-button v-tooltip.delay="'Hot key: Shift + Enter'" primary squircle :loading="loading" :disabled="loading" @click="onSaveClick">
|
|
16
|
+
<span>{{ saveBtnText }}</span>
|
|
17
17
|
</itf-button>
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
@@ -51,6 +51,8 @@ import itfButton from '../button/Button.vue';
|
|
|
51
51
|
export default class PanelItemEdit extends Vue {
|
|
52
52
|
@Prop(Boolean) loading;
|
|
53
53
|
@Prop(Boolean) hideFooter;
|
|
54
|
+
@Prop({ type: String, default: function() { return this.$t('components.modal.save') } }) saveBtnText;
|
|
55
|
+
@Prop({ type: String, default: function() { return this.$t('components.modal.cancel') } }) cancelBtnText;
|
|
54
56
|
|
|
55
57
|
onSaveClick() {
|
|
56
58
|
if (this.$refs.editForm && !this.$refs.editForm.doValidation()) {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { Vue, Component, Inject, Prop } from 'vue-property-decorator';
|
|
6
6
|
import { IPanel } from './PanelList.vue';
|
|
7
7
|
import {stackToHash} from "@itfin/components/src/components/panels/helpers";
|
|
8
|
+
import {getRootPanelList} from "@itfin/components/src/components/panels";
|
|
8
9
|
|
|
9
10
|
@Component({
|
|
10
11
|
components: {
|
|
@@ -15,7 +16,6 @@ import {stackToHash} from "@itfin/components/src/components/panels/helpers";
|
|
|
15
16
|
}
|
|
16
17
|
})
|
|
17
18
|
export default class PanelLink extends Vue {
|
|
18
|
-
@Inject({ default: null }) panelList;
|
|
19
19
|
@Inject({ default: null }) currentPanel;
|
|
20
20
|
|
|
21
21
|
@Prop(Boolean) global: boolean;
|
|
@@ -25,6 +25,7 @@ export default class PanelLink extends Vue {
|
|
|
25
25
|
@Prop() list;
|
|
26
26
|
@Prop({ type: String, default: 'active' }) activeClass: string;
|
|
27
27
|
@Prop(Boolean) append: boolean;
|
|
28
|
+
@Prop(Boolean) replace: boolean;
|
|
28
29
|
|
|
29
30
|
get on() {
|
|
30
31
|
const handlers = {};
|
|
@@ -35,7 +36,7 @@ export default class PanelLink extends Vue {
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
get activeList() {
|
|
38
|
-
return this.list ??
|
|
39
|
+
return this.list ?? getRootPanelList();
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
get isActive() {
|
|
@@ -51,6 +52,9 @@ export default class PanelLink extends Vue {
|
|
|
51
52
|
if (!this.append) {
|
|
52
53
|
stack = stack.splice(0, this.currentPanel?.index + 1);
|
|
53
54
|
}
|
|
55
|
+
if (this.replace) {
|
|
56
|
+
stack = [];
|
|
57
|
+
}
|
|
54
58
|
const hash = stackToHash([
|
|
55
59
|
...stack,
|
|
56
60
|
{
|
|
@@ -62,13 +66,18 @@ export default class PanelLink extends Vue {
|
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
onClick(e) {
|
|
65
|
-
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
e.stopPropagation();
|
|
71
|
+
const index = this.replace ? 0 : (this.append ? undefined : this.currentPanel?.index + 1);
|
|
72
|
+
this.$emit('open', {
|
|
73
|
+
panel: this.panel,
|
|
74
|
+
payload: this.payload || {},
|
|
75
|
+
index
|
|
76
|
+
});
|
|
66
77
|
if (!this.activeList) {
|
|
67
78
|
return;
|
|
68
79
|
}
|
|
69
|
-
|
|
70
|
-
e.stopPropagation();
|
|
71
|
-
this.activeList.openPanel(this.panel, this.payload || {}, this.append ? undefined : this.currentPanel?.index + 1);
|
|
80
|
+
this.activeList.openPanel(this.panel, this.payload || {}, index);
|
|
72
81
|
}
|
|
73
82
|
}
|
|
74
83
|
</script>
|
|
@@ -218,7 +218,6 @@ export default class PanelList extends Vue {
|
|
|
218
218
|
@Prop() panels: Record<string, Component>;
|
|
219
219
|
@Prop({ default: () => {} }) searchPanel: (type: string) => boolean;
|
|
220
220
|
@Prop({ type: String, default: 'path' }) routeType: string;
|
|
221
|
-
@Prop({ type: String, default: '' }) routePrefix: string;
|
|
222
221
|
|
|
223
222
|
panelsStack:IPanel[] = [];
|
|
224
223
|
|
|
@@ -229,7 +228,6 @@ export default class PanelList extends Vue {
|
|
|
229
228
|
if (this.firstPanel) {
|
|
230
229
|
this.internalOpenPanel(this.firstPanel.type, this.firstPanel.payload);
|
|
231
230
|
}
|
|
232
|
-
console.info('created');
|
|
233
231
|
this.parsePanelHash(); // щоб панелі змінювались при перезавантаженні
|
|
234
232
|
window.addEventListener('popstate', this.handlePopState); // щоб панелі змінювались при навігації
|
|
235
233
|
}
|
|
@@ -468,9 +466,9 @@ export default class PanelList extends Vue {
|
|
|
468
466
|
}
|
|
469
467
|
|
|
470
468
|
setPanelHash() {
|
|
471
|
-
const hash = stackToHash(this.panelsStack, this.
|
|
469
|
+
const hash = stackToHash(this.panelsStack, this.routeType === 'path').replace(/^#/, '');
|
|
472
470
|
if (this.routeType === 'path') {
|
|
473
|
-
this.$router.push({ path: hash });
|
|
471
|
+
this.$router.push({ path: `/${hash}` });
|
|
474
472
|
} else {
|
|
475
473
|
this.$router.push({ hash });
|
|
476
474
|
}
|
|
@@ -480,7 +478,7 @@ export default class PanelList extends Vue {
|
|
|
480
478
|
async parsePanelHash() {
|
|
481
479
|
const hash = this.routeType === 'path' ? location.pathname : location.hash;
|
|
482
480
|
if (hash) {
|
|
483
|
-
const panels = hashToStack(hash, this.
|
|
481
|
+
const panels = hashToStack(hash, this.routeType === 'path');
|
|
484
482
|
const newStack = [];
|
|
485
483
|
this.panelsStack = [];
|
|
486
484
|
for (const panelIndex in panels) {
|
|
@@ -500,14 +498,12 @@ export default class PanelList extends Vue {
|
|
|
500
498
|
}
|
|
501
499
|
}
|
|
502
500
|
this.panelsStack = newStack;
|
|
503
|
-
console.info('set', newStack);
|
|
504
501
|
this.emitEvent('panels.changed', this.panelsStack);
|
|
505
502
|
this.updateTitle();
|
|
506
503
|
}
|
|
507
504
|
}
|
|
508
505
|
|
|
509
506
|
handlePopState() {
|
|
510
|
-
console.info('handlePopState')
|
|
511
507
|
this.parsePanelHash();
|
|
512
508
|
// виправляє проблему відкритої панелі при натисканні кнопки "назад" до першої панелі
|
|
513
509
|
if (this.panelsStack.length === 2) {
|