@itfin/components 1.3.67 → 1.3.69
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/datepicker/DateGranularityPicker.vue +292 -0
- package/src/components/datepicker/DatePicker.vue +2 -0
- package/src/components/datepicker/DateRangePicker.vue +4 -0
- package/src/components/datepicker/DateRangePickerInline.vue +4 -0
- package/src/components/modal/modalSrc.js +2 -2
- package/src/components/panels/PanelList.vue +6 -1
- package/src/components/table/Table2.vue +4 -0
- package/src/components/table/TableBody.vue +2 -0
- package/src/components/table/TableGroup.vue +16 -5
- package/src/components/table/TableHeader.vue +1 -1
- package/src/components/table/TableRows.vue +7 -2
- package/src/components/table/table2.scss +3 -0
- package/src/components/text-field/MoneyField.vue +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="itf-daterange-picker" :class="{ 'with-addon addon-start': prependIcon, 'with-addon addon-end': clearable }">
|
|
3
|
+
<div class="addon" v-if="prependIcon">
|
|
4
|
+
<slot name="addon">
|
|
5
|
+
<itf-icon :name="prependIcon" />
|
|
6
|
+
</slot>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="input-group form-control py-0"
|
|
9
|
+
:class="{ 'focused': focused, 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
|
|
10
|
+
ref="group">
|
|
11
|
+
<i-mask-component
|
|
12
|
+
ref="input"
|
|
13
|
+
class="form-control"
|
|
14
|
+
:class="{ 'placeholder-visible': !displayValue || !displayValue[0] }"
|
|
15
|
+
@input="updateValue($event, 0)"
|
|
16
|
+
@focus="onFocus"
|
|
17
|
+
@blur="onBlur($event, 0)"
|
|
18
|
+
:value="displayValue[0]"
|
|
19
|
+
:mask="Date"
|
|
20
|
+
:pattern="dateFormat"
|
|
21
|
+
:blocks="blocks"
|
|
22
|
+
:disabled="disabled"
|
|
23
|
+
:format="format"
|
|
24
|
+
:parse="parse"
|
|
25
|
+
:unmask="false"
|
|
26
|
+
:lazy="!focused"
|
|
27
|
+
:placeholder="placeholder"
|
|
28
|
+
/>
|
|
29
|
+
<span v-if="displayValue && displayValue[0]" class="input-group-text" :class="{'hidden': !focused && (value && !value[0])}">-</span>
|
|
30
|
+
|
|
31
|
+
<i-mask-component
|
|
32
|
+
v-if="displayValue && displayValue[0]"
|
|
33
|
+
ref="input2"
|
|
34
|
+
class="form-control"
|
|
35
|
+
@input="updateValue($event, 1)"
|
|
36
|
+
@focus="onFocus"
|
|
37
|
+
@blur="onBlur($event, 1)"
|
|
38
|
+
:value="displayValue[1]"
|
|
39
|
+
:mask="Date"
|
|
40
|
+
:pattern="dateFormat"
|
|
41
|
+
:blocks="blocks"
|
|
42
|
+
:format="format"
|
|
43
|
+
:parse="parse"
|
|
44
|
+
:unmask="false"
|
|
45
|
+
:lazy="!focused"
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
48
|
+
<div style="display: none">
|
|
49
|
+
<div ref="dropdown" class="itf-daterange-picker__dropdown d-flex gap-2">
|
|
50
|
+
<div class="p-3">
|
|
51
|
+
<itf-radio-group v-model="granularity">
|
|
52
|
+
<itf-radio v-for="(gr, n) in granularities" :key="n" :label="gr.title" :value="gr.value" />
|
|
53
|
+
</itf-radio-group>
|
|
54
|
+
</div>
|
|
55
|
+
<div>
|
|
56
|
+
<itf-date-range-picker-inline
|
|
57
|
+
:value="value"
|
|
58
|
+
only-calendar
|
|
59
|
+
:display-format="displayFormat"
|
|
60
|
+
:value-format="valueFormat"
|
|
61
|
+
:min-date="minDate"
|
|
62
|
+
:max-date="maxDate"
|
|
63
|
+
:min-view="minView"
|
|
64
|
+
@input="selectInlineDate"
|
|
65
|
+
></itf-date-range-picker-inline>
|
|
66
|
+
</div>
|
|
67
|
+
<!--itf-date-range-picker-inline
|
|
68
|
+
:value="value"
|
|
69
|
+
:start-view="startView"
|
|
70
|
+
:only-calendar="onlyCalendar"
|
|
71
|
+
:display-format="displayFormat"
|
|
72
|
+
:value-format="valueFormat"
|
|
73
|
+
:min-date="minDate"
|
|
74
|
+
:max-date="maxDate"
|
|
75
|
+
@input="selectInlineDate"
|
|
76
|
+
></itf-date-range-picker-inline-->
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div class="addon-end" v-if="clearable && value && value[0]">
|
|
81
|
+
<slot name="clear">
|
|
82
|
+
<itf-button
|
|
83
|
+
icon
|
|
84
|
+
small
|
|
85
|
+
@click="$emit('input', '')"
|
|
86
|
+
>
|
|
87
|
+
<itf-icon name="close" />
|
|
88
|
+
</itf-button>
|
|
89
|
+
</slot>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</template>
|
|
93
|
+
<script>
|
|
94
|
+
import { Vue, Component, Prop, PropSync, Inject } from 'vue-property-decorator';
|
|
95
|
+
import { IMask, IMaskComponent } from 'vue-imask';
|
|
96
|
+
import { DateTime } from 'luxon';
|
|
97
|
+
import tippy from 'tippy.js';
|
|
98
|
+
import itfIcon from '../icon/Icon';
|
|
99
|
+
import itfButton from '../button/Button';
|
|
100
|
+
import itfRadio from '../checkbox/Radio.vue';
|
|
101
|
+
import itfRadioGroup from '../checkbox/RadioGroup.vue';
|
|
102
|
+
import itfDateRangePickerInline from './DateRangePickerInline.vue';
|
|
103
|
+
import ITFSettings from '../../ITFSettings';
|
|
104
|
+
|
|
105
|
+
export default @Component({
|
|
106
|
+
name: 'itfDateRangePicker',
|
|
107
|
+
components: {
|
|
108
|
+
itfIcon,
|
|
109
|
+
itfButton,
|
|
110
|
+
itfRadio,
|
|
111
|
+
itfRadioGroup,
|
|
112
|
+
itfDateRangePickerInline,
|
|
113
|
+
IMaskComponent,
|
|
114
|
+
},
|
|
115
|
+
})
|
|
116
|
+
class itfDateGranularityPicker extends Vue {
|
|
117
|
+
@Inject({ default: null }) itemLabel;
|
|
118
|
+
|
|
119
|
+
@Prop({ default: () => ([]) }) value;
|
|
120
|
+
@Prop({ type: String, default: 'ISO' }) valueFormat;
|
|
121
|
+
@Prop({ type: String }) displayFormat;
|
|
122
|
+
// @Prop({ type: String, default: 'days', validator: (value) => ['days', 'months', 'years'].includes(value) }) startView;
|
|
123
|
+
@Prop({ type: Boolean, default: false }) onlyCalendar;
|
|
124
|
+
@Prop({ type: Boolean, default: false }) clearable;
|
|
125
|
+
@Prop({ type: String, default: '' }) placeholder;
|
|
126
|
+
@Prop({ type: String, default: '' }) prependIcon;
|
|
127
|
+
@Prop({ type: String, default: 'bottom-start' }) placement;
|
|
128
|
+
@Prop({ type: [String, Date], default: '' }) minDate;
|
|
129
|
+
@Prop({ type: [String, Date], default: ''}) maxDate;
|
|
130
|
+
@Prop(Boolean) disabled;
|
|
131
|
+
|
|
132
|
+
granularity = 'yearly';
|
|
133
|
+
|
|
134
|
+
get granularities() {
|
|
135
|
+
return [
|
|
136
|
+
{ title: 'Yearly', value: 'yearly' },
|
|
137
|
+
{ title: 'Quarterly', value: 'quarterly' },
|
|
138
|
+
{ title: 'Monthly', value: 'monthly' },
|
|
139
|
+
{ title: 'Weekly', value: 'weekly' },
|
|
140
|
+
{ title: 'Custom', value: 'manual' },
|
|
141
|
+
];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
get minView() {
|
|
145
|
+
switch (this.granularity) {
|
|
146
|
+
case 'yearly': return 'years';
|
|
147
|
+
case 'quarterly': return 'years';
|
|
148
|
+
case 'monthly': return 'months';
|
|
149
|
+
case 'manual':
|
|
150
|
+
case 'weekly': return 'days';
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
focused = false;
|
|
155
|
+
|
|
156
|
+
tooltip = null;
|
|
157
|
+
|
|
158
|
+
blocks = {
|
|
159
|
+
yyyy: {
|
|
160
|
+
mask: IMask.MaskedRange,
|
|
161
|
+
from: 1970,
|
|
162
|
+
to: 2100,
|
|
163
|
+
},
|
|
164
|
+
MM: {
|
|
165
|
+
mask: IMask.MaskedRange,
|
|
166
|
+
from: 1,
|
|
167
|
+
to: 12,
|
|
168
|
+
},
|
|
169
|
+
dd: {
|
|
170
|
+
mask: IMask.MaskedRange,
|
|
171
|
+
from: 1,
|
|
172
|
+
to: 31,
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
get dateFormat() {
|
|
177
|
+
return this.displayFormat || ITFSettings.defaultDisplayDateFormat;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
isInvalid() {
|
|
181
|
+
return this.itemLabel && this.itemLabel.isHasError();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
isSuccess() {
|
|
185
|
+
return this.itemLabel && this.itemLabel.isHasSuccess();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
mounted() {
|
|
189
|
+
// якщо в модалці, то контекст модалки, якщо ні, то аплікейшена
|
|
190
|
+
const context = this.$el.closest('.itf-append-context') || document.body;
|
|
191
|
+
this.tooltip = tippy(this.$refs.group, {
|
|
192
|
+
interactiveBorder: 30,
|
|
193
|
+
interactiveDebounce: 75,
|
|
194
|
+
animation: 'scale',
|
|
195
|
+
arrow: true,
|
|
196
|
+
content: this.$refs.dropdown,
|
|
197
|
+
allowHTML: true,
|
|
198
|
+
trigger: 'click',
|
|
199
|
+
interactive: true,
|
|
200
|
+
placement: this.placement,
|
|
201
|
+
appendTo: context
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
get valueAsLuxon() {
|
|
206
|
+
if (!this.value || this.value.length < 2 || !this.value[0] || !this.value[1]) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
if (this.valueFormat === 'ISO') {
|
|
210
|
+
return [
|
|
211
|
+
DateTime.fromISO(this.value[0]),
|
|
212
|
+
DateTime.fromISO(this.value[1]),
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
return [
|
|
216
|
+
DateTime.fromFormat(this.value[0], this.valueFormat),
|
|
217
|
+
DateTime.fromFormat(this.value[1], this.valueFormat),
|
|
218
|
+
];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
get displayValue() {
|
|
222
|
+
if (!this.valueAsLuxon || this.valueAsLuxon.length < 2) {
|
|
223
|
+
return ['', ''];
|
|
224
|
+
}
|
|
225
|
+
return [
|
|
226
|
+
this.valueAsLuxon[0].toFormat(this.dateFormat),
|
|
227
|
+
this.valueAsLuxon[1].toFormat(this.dateFormat)
|
|
228
|
+
];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
get minDateLuxon() {
|
|
232
|
+
return this.minDate && this.dateLuxon(this.minDate);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
get maxDateLuxon() {
|
|
236
|
+
return this.maxDate && this.dateLuxon(this.maxDate);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
dateLuxon(date) {
|
|
240
|
+
return (typeof date === 'string' ? DateTime.fromISO(date) : DateTime.fromJSDate(date));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
updateValue(value, index, emitEmpty = false) {
|
|
244
|
+
const val = value && DateTime.fromFormat(value, this.dateFormat);
|
|
245
|
+
if (!val || !val.isValid) {
|
|
246
|
+
if (emitEmpty) {
|
|
247
|
+
this.$emit('input', []);
|
|
248
|
+
}
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const current = [...(this.value || [])];
|
|
252
|
+
current[0] = current[0] || null;
|
|
253
|
+
current[1] = current[1] || null;
|
|
254
|
+
current[index] = (this.valueFormat === 'ISO') ? val.toISO() : val.toFormat(this.valueFormat);
|
|
255
|
+
if ((this.minDateLuxon && val < this.minDateLuxon) ||
|
|
256
|
+
(this.maxDateLuxon && val > this.maxDateLuxon)
|
|
257
|
+
) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
this.$emit('input', [...current, this.granularity]);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
format(date) {
|
|
264
|
+
return DateTime.fromJSDate(date).toFormat(this.dateFormat);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
parse(str) {
|
|
268
|
+
return DateTime.fromFormat(str, this.dateFormat).toJSDate();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
onFocus() {
|
|
272
|
+
this.focused = true;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
onBlur(e, index) {
|
|
276
|
+
this.focused = false;
|
|
277
|
+
if (this.valueAsLuxon && this.valueAsLuxon[0] && this.valueAsLuxon[1] && this.valueAsLuxon[0] > this.valueAsLuxon[1]) {
|
|
278
|
+
if ((this.minDateLuxon && (this.valueAsLuxon[0] < this.minDateLuxon || this.valueAsLuxon[1] < this.minDateLuxon)) ||
|
|
279
|
+
(this.maxDateLuxon && (this.valueAsLuxon[0] > this.maxDateLuxon || this.valueAsLuxon[1] > this.maxDateLuxon))
|
|
280
|
+
) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
this.$emit('input', [this.value[0], this.value[1], this.granularity]);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
selectInlineDate(date) {
|
|
288
|
+
this.$emit('input', [...date, this.granularity]);
|
|
289
|
+
this.tooltip.hide();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
</script>
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
:display-format="dateFormat"
|
|
45
45
|
:value-format="valueFormat"
|
|
46
46
|
:min-date="minDate"
|
|
47
|
+
:days-list="daysList"
|
|
47
48
|
@input="selectInlineDate"
|
|
48
49
|
></itf-date-picker-inline>
|
|
49
50
|
</div>
|
|
@@ -79,6 +80,7 @@ class itfDatePicker extends Vue {
|
|
|
79
80
|
@Prop({ type: [Number, String], default: 300 }) delayInput;
|
|
80
81
|
@Prop({ type: String, default: 'ISO' }) valueFormat;
|
|
81
82
|
@Prop({ type: String }) displayFormat;
|
|
83
|
+
@Prop({ type: Array }) daysList;
|
|
82
84
|
@Prop({ type: String, default: 'days', validator: (value) => ['days', 'months', 'years'].includes(value) }) startView;
|
|
83
85
|
@Prop({ type: Boolean, default: false }) onlyCalendar;
|
|
84
86
|
@Prop({ type: String, default: '' }) placeholder;
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
:value-format="valueFormat"
|
|
56
56
|
:min-date="minDate"
|
|
57
57
|
:max-date="maxDate"
|
|
58
|
+
:days-list="daysList"
|
|
58
59
|
@input="selectInlineDate"
|
|
59
60
|
></itf-date-range-picker-inline>
|
|
60
61
|
</div>
|
|
@@ -82,10 +83,12 @@ import itfIcon from '../icon/Icon';
|
|
|
82
83
|
import itfButton from '../button/Button';
|
|
83
84
|
import itfDateRangePickerInline from './DateRangePickerInline.vue';
|
|
84
85
|
import ITFSettings from '../../ITFSettings';
|
|
86
|
+
import itfDatePickerInline from "@/components/datepicker/DatePickerInline.vue";
|
|
85
87
|
|
|
86
88
|
export default @Component({
|
|
87
89
|
name: 'itfDateRangePicker',
|
|
88
90
|
components: {
|
|
91
|
+
itfDatePickerInline,
|
|
89
92
|
itfIcon,
|
|
90
93
|
itfButton,
|
|
91
94
|
itfDateRangePickerInline,
|
|
@@ -98,6 +101,7 @@ class itfDateRangePicker extends Vue {
|
|
|
98
101
|
@Prop({ default: () => ([]) }) value;
|
|
99
102
|
@Prop({ type: String, default: 'ISO' }) valueFormat;
|
|
100
103
|
@Prop({ type: String }) displayFormat;
|
|
104
|
+
@Prop({ type: Array }) daysList;
|
|
101
105
|
@Prop({ type: String, default: 'days', validator: (value) => ['days', 'months', 'years'].includes(value) }) startView;
|
|
102
106
|
@Prop({ type: Boolean, default: false }) onlyCalendar;
|
|
103
107
|
@Prop({ type: Boolean, default: false }) clearable;
|
|
@@ -37,6 +37,7 @@ class itfDatePickerInline extends Vue {
|
|
|
37
37
|
@Prop({ type: Object, default: () => ({}) }) customDays;
|
|
38
38
|
@Prop({ type: [String, Date], default: '' }) minDate;
|
|
39
39
|
@Prop({ type: [String, Date], default: '' }) maxDate;
|
|
40
|
+
@Prop({ type: String, default: 'days' }) minView;
|
|
40
41
|
@Prop({
|
|
41
42
|
type: Array,
|
|
42
43
|
default: function () {
|
|
@@ -61,6 +62,7 @@ class itfDatePickerInline extends Vue {
|
|
|
61
62
|
|
|
62
63
|
@Watch('minDate')
|
|
63
64
|
@Watch('maxDate')
|
|
65
|
+
@Watch('minView')
|
|
64
66
|
async createCalendar() {
|
|
65
67
|
if (this.calendar) {
|
|
66
68
|
this.destroyCalendar();
|
|
@@ -88,6 +90,8 @@ class itfDatePickerInline extends Vue {
|
|
|
88
90
|
altFieldDateFormat: this.valueFormat,
|
|
89
91
|
minDate: this.minDate,
|
|
90
92
|
maxDate: this.maxDate,
|
|
93
|
+
view: this.minView,
|
|
94
|
+
minView: this.minView,
|
|
91
95
|
range: true,
|
|
92
96
|
dynamicRange: true,
|
|
93
97
|
toggleSelected: false,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* --------------------------------------------------------------------------
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { defineJQueryPlugin,
|
|
8
|
+
import { defineJQueryPlugin, getElement, isRTL, isVisible, reflow } from 'bootstrap/js/src/util/index'
|
|
9
9
|
import EventHandler from 'bootstrap/js/src/dom/event-handler'
|
|
10
10
|
import SelectorEngine from 'bootstrap/js/src/dom/selector-engine'
|
|
11
11
|
import ScrollBarHelper from 'bootstrap/js/src/util/scrollbar'
|
|
@@ -337,7 +337,7 @@ class Modal extends BaseComponent {
|
|
|
337
337
|
*/
|
|
338
338
|
|
|
339
339
|
EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) {
|
|
340
|
-
const target =
|
|
340
|
+
const target = getElement(this)
|
|
341
341
|
|
|
342
342
|
if (['A', 'AREA'].includes(this.tagName)) {
|
|
343
343
|
event.preventDefault()
|
|
@@ -258,8 +258,13 @@ export default class PanelList extends Vue {
|
|
|
258
258
|
newPanel.isCloseable = false;
|
|
259
259
|
}
|
|
260
260
|
let newStack = [...this.panelsStack];
|
|
261
|
+
if (this.panels[type].permanentExpanded && newStack.length) {
|
|
262
|
+
for (const panel of newStack) {
|
|
263
|
+
panel.isCollapsed = true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
261
266
|
let isAnimation = true;
|
|
262
|
-
if (openIndex) {
|
|
267
|
+
if (typeof openIndex !== 'undefined') {
|
|
263
268
|
isAnimation = newStack.length === openIndex;
|
|
264
269
|
newStack = newStack.slice(0, openIndex);
|
|
265
270
|
}
|
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
:striped="striped"
|
|
40
40
|
:expanded-ids="expandedIds"
|
|
41
41
|
:css-property="cssProperty"
|
|
42
|
+
:sticky-header="stickyHeader"
|
|
43
|
+
:editable-property="editableProperty"
|
|
42
44
|
:sorting.sync="_sorting"
|
|
43
45
|
@update:expanded-ids="$emit('update:expanded-ids', $event)"
|
|
44
46
|
@new="$emit('new', $event)"
|
|
@@ -86,6 +88,7 @@ class itfTable2 extends Vue {
|
|
|
86
88
|
@Prop({ type: String, default: null }) idProperty;
|
|
87
89
|
@Prop({ type: String, default: null }) cssProperty;
|
|
88
90
|
@Prop({ type: String, default: null }) subrowsProperty;
|
|
91
|
+
@Prop({ type: String, default: null }) editableProperty;
|
|
89
92
|
@Prop({ default: 45 }) indicatorWidth;
|
|
90
93
|
@Prop({ type: String, default: null, validator: (val) => ['order', 'checkbox', 'toggle', 'property'].includes(val) }) indicatorType;
|
|
91
94
|
@Prop({ type: String, default: null }) stateName; // save state to storage
|
|
@@ -95,6 +98,7 @@ class itfTable2 extends Vue {
|
|
|
95
98
|
@Prop({ type: Array, default: () => [] }) expandedIds;
|
|
96
99
|
@Prop() currency;
|
|
97
100
|
@Prop() currencies;
|
|
101
|
+
@Prop(Boolean) stickyHeader;
|
|
98
102
|
@Prop(Boolean) addNewRows;
|
|
99
103
|
@Prop(Boolean) columnSorting;
|
|
100
104
|
@Prop(Boolean) columnResizing;
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
:striped="striped"
|
|
18
18
|
:expanded-all="expandedAll"
|
|
19
19
|
:css-property="cssProperty"
|
|
20
|
+
:editable-property="editableProperty"
|
|
20
21
|
@update:expanded-ids="$emit('update:expanded-ids', $event)"
|
|
21
22
|
@row-click="$emit('row-click', $event)"
|
|
22
23
|
@update="$emit('update', $event)"
|
|
@@ -186,6 +187,7 @@ class itfTableBody extends Vue {
|
|
|
186
187
|
@Prop(Boolean) editable;
|
|
187
188
|
@Prop(Boolean) expandedAll;
|
|
188
189
|
@Prop(Boolean) striped;
|
|
190
|
+
@Prop() editableProperty;
|
|
189
191
|
@Prop() selectedIds;
|
|
190
192
|
@Prop() currency;
|
|
191
193
|
@Prop() currencies;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
|
|
3
|
-
<div class="itf-table-group table-small-row">
|
|
3
|
+
<div class="itf-table-group table-small-row" :class="{'no-indicator': indicatorType === 'none'}">
|
|
4
4
|
<!-- Тут показується лінія при драг н дропі -->
|
|
5
5
|
<!--div accept-group="tablegroups" class="preline">
|
|
6
6
|
<div class="line"></div>
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
:show-add-column="showAddColumn"
|
|
72
72
|
:expanded-ids="expandedIds"
|
|
73
73
|
:css-property="cssProperty"
|
|
74
|
+
:editable-property="editableProperty"
|
|
74
75
|
@update:expanded-ids="$emit('update:expanded-ids', $event)"
|
|
75
76
|
>
|
|
76
77
|
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
@@ -146,6 +147,12 @@
|
|
|
146
147
|
//margin-top: 20px;
|
|
147
148
|
//margin-bottom: 20px ;
|
|
148
149
|
|
|
150
|
+
&.no-indicator {
|
|
151
|
+
.shadow-area + .table-view-header-value, .table-item-inner {
|
|
152
|
+
border-left: 1px solid var(--itf-table-border-color);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
149
156
|
.preline {
|
|
150
157
|
display: flex;
|
|
151
158
|
align-items: center;
|
|
@@ -344,8 +351,10 @@ class itfTableGroup extends Vue {
|
|
|
344
351
|
@Prop(Boolean) noColumnMenu;
|
|
345
352
|
@Prop(Boolean) noSelectAll;
|
|
346
353
|
@Prop(Boolean) editable;
|
|
354
|
+
@Prop() editableProperty;
|
|
347
355
|
@Prop(Boolean) expandedAll;
|
|
348
356
|
@Prop(Boolean) striped;
|
|
357
|
+
@Prop(Boolean) stickyHeader;
|
|
349
358
|
@Prop() indicatorWidth;
|
|
350
359
|
@Prop() cssProperty;
|
|
351
360
|
@PropSync('sorting', { type: Object, default: () => ({}) }) _sorting;
|
|
@@ -386,10 +395,12 @@ class itfTableGroup extends Vue {
|
|
|
386
395
|
}
|
|
387
396
|
|
|
388
397
|
mounted() {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
398
|
+
if (this.stickyHeader) {
|
|
399
|
+
this.sticky = new Sticky(`.${this.stickyId}`, {
|
|
400
|
+
wrap: true,
|
|
401
|
+
stickyClass: 'sticky',
|
|
402
|
+
});
|
|
403
|
+
}
|
|
393
404
|
}
|
|
394
405
|
|
|
395
406
|
selectSummary(method, index) {
|
|
@@ -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 v-if="indicatorType !== 'none'" class="table-view-header-value reserved sticky">
|
|
8
8
|
<itf-checkbox v-if="indicatorType !== 'none' && visibleHeader && !noSelectAll" ungrouped value="all" v-model="selectAll" ref="selectAll" />
|
|
9
9
|
</div>
|
|
10
10
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</a>
|
|
21
21
|
</div>
|
|
22
22
|
</div>
|
|
23
|
-
<div class="indicator sticky">
|
|
23
|
+
<div v-if="indicatorType !== 'none'" class="indicator sticky">
|
|
24
24
|
<div class="fill table-view-row-count" :class="{'on-rest': !noSelectAll}">
|
|
25
25
|
<span v-if="indicatorType === 'order'">{{ (n + 1) }}</span>
|
|
26
26
|
<span v-else-if="indicatorType === 'property'">{{ item[idProperty] }}</span>
|
|
@@ -54,9 +54,10 @@
|
|
|
54
54
|
:class="{'justify-content-end': column.align === 'end', 'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'flex-grow-1': column.grow, 'px-2': !(column.editable && editable), 'editable': column.editable && editable}"
|
|
55
55
|
class="table-view-item-value d-flex h-100">
|
|
56
56
|
<slot :name="`column.${column.property}`" :toggle="() => $emit('toggle', item)" :level="level" :editable="column.editable && editable" :item="item" :column="column" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)">
|
|
57
|
-
<template v-if="column.editable && editable">
|
|
57
|
+
<template v-if="column.editable && editable && (!editableProperty || item[editableProperty])">
|
|
58
58
|
<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">
|
|
59
59
|
<itf-text-field class="w-100" v-if="column.type === 'text'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
|
|
60
|
+
<itf-text-field class="w-100" v-if="column.type === 'number'" type="number" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
|
|
60
61
|
<itf-hours-field
|
|
61
62
|
class="w-100"
|
|
62
63
|
placeholder="00h 00m"
|
|
@@ -103,6 +104,8 @@
|
|
|
103
104
|
:expanded-ids="expandedIds"
|
|
104
105
|
:expanded-all="expandedAll"
|
|
105
106
|
:css-property="cssProperty"
|
|
107
|
+
:editable-property="editableProperty"
|
|
108
|
+
@update="$emit('update', $event)"
|
|
106
109
|
@toggle="$emit('toggle', $event)"
|
|
107
110
|
>
|
|
108
111
|
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
@@ -153,6 +156,7 @@ class itfTableRows extends Vue {
|
|
|
153
156
|
@Prop(Boolean) editable;
|
|
154
157
|
@Prop(Boolean) expandedAll;
|
|
155
158
|
@Prop(Boolean) striped;
|
|
159
|
+
@Prop() editableProperty;
|
|
156
160
|
@Prop() selectedIds;
|
|
157
161
|
@Prop() expandedIds;
|
|
158
162
|
@Prop() currency;
|
|
@@ -180,6 +184,7 @@ class itfTableRows extends Vue {
|
|
|
180
184
|
this.$emit('update', {
|
|
181
185
|
index,
|
|
182
186
|
item,
|
|
187
|
+
inputValue: value,
|
|
183
188
|
value: newItem,
|
|
184
189
|
column
|
|
185
190
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
:root {
|
|
2
2
|
--itf-table-border-color: #e1e1e1;
|
|
3
3
|
--itf-table-header-bg: #f8f8f8;
|
|
4
|
+
--itf-table-font-size: 1rem;
|
|
4
5
|
--itf-table-selected-bg: #f0f0f0;
|
|
5
6
|
--itf-table-alt-bg: #f9f9f9;
|
|
6
7
|
//--itf-table-border-color: #e1e1e1;
|
|
@@ -37,6 +38,8 @@ body[data-theme="dark"] {
|
|
|
37
38
|
--itf-table-summary-text: #82909d80;
|
|
38
39
|
}
|
|
39
40
|
.itf-table2 {
|
|
41
|
+
font-size: var(--itf-table-font-size);
|
|
42
|
+
|
|
40
43
|
&.scrollable {
|
|
41
44
|
-webkit-overflow-scrolling: touch;
|
|
42
45
|
overflow: hidden scroll;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="itf-money-field" :class="{'currency-arrow': !currencyDisabled, 'currency-select': currencySelect}">
|
|
2
|
+
<div class="itf-money-field ph-no-capture" :class="{'currency-arrow': !currencyDisabled, 'currency-select': currencySelect}">
|
|
3
3
|
<div :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
|