@itfin/components 1.3.39 → 1.3.41
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/ITFSettings.js +9 -0
- package/src/assets/scss/components/_text-field.scss +8 -2
- package/src/assets/scss/components/select/_dropdown-toggle.scss +2 -0
- package/src/components/datepicker/DatePickerInline.vue +2 -0
- package/src/components/datepicker/MonthPicker.vue +19 -17
- package/src/components/form/index.stories.js +8 -3
- package/src/components/table/Table2.vue +13 -36
- package/src/components/table/TableBody.vue +22 -51
- package/src/components/table/TableGroup.vue +22 -14
- package/src/components/table/TableHeader.vue +5 -159
- package/src/components/table/index.stories.js +41 -6
- package/src/components/table/table.js +16 -0
- package/src/components/table/table2.scss +271 -0
- package/src/components/text-field/MoneyField.vue +12 -7
- package/src/components/text-field/TextField.vue +4 -4
- package/src/components/text-field/Textarea.vue +1 -1
package/package.json
CHANGED
package/src/ITFSettings.js
CHANGED
|
@@ -10,6 +10,7 @@ class ITFSettings {
|
|
|
10
10
|
defaultLocale: 'en_US',
|
|
11
11
|
defaultDisplayDateFormat: 'MM/dd/yyyy',
|
|
12
12
|
// defaultDisplayDateFormat: 'dd.MM.yyyy',
|
|
13
|
+
currencies: []
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
get defaultLocale() {
|
|
@@ -20,6 +21,14 @@ class ITFSettings {
|
|
|
20
21
|
this.options.defaultLocale = val;
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
get currencies() {
|
|
25
|
+
return this.options.currencies;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
set currencies(val) {
|
|
29
|
+
this.options.currencies = val;
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
get supportLanguages() {
|
|
24
33
|
return [
|
|
25
34
|
{ locale: 'en_US', name: 'English', dateFormat: 'MM/dd/yyyy' },
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
.itf-text-field {
|
|
4
4
|
&__input {
|
|
5
|
-
|
|
5
|
+
.addon + & {
|
|
6
|
+
border-top-left-radius: $input-border-radius !important;
|
|
7
|
+
border-bottom-left-radius: $input-border-radius !important;
|
|
8
|
+
}
|
|
6
9
|
-moz-appearance: textfield; // Hide Arrows From Input Number (Firefox)
|
|
7
10
|
|
|
8
11
|
&::-webkit-outer-spin-button, // Hide Arrows From Input Number (Chrome, Safari, Edge, Opera)
|
|
@@ -27,7 +30,10 @@
|
|
|
27
30
|
z-index: 10;
|
|
28
31
|
}
|
|
29
32
|
&__input {
|
|
30
|
-
|
|
33
|
+
.addon + & {
|
|
34
|
+
border-top-left-radius: $input-border-radius !important;
|
|
35
|
+
border-bottom-left-radius: $input-border-radius !important;
|
|
36
|
+
}
|
|
31
37
|
resize: none;
|
|
32
38
|
}
|
|
33
39
|
&__autogrow &__input {
|
|
@@ -39,6 +39,7 @@ class itfDatePickerInline extends Vue {
|
|
|
39
39
|
@Prop({ type: Boolean, default: false }) range;
|
|
40
40
|
@Prop({ type: Object, default: () => ({}) }) customDays;
|
|
41
41
|
@Prop({ type: [String, Date], default: '' }) minDate;
|
|
42
|
+
@Prop({ type: [String, Date], default: '' }) maxDate;
|
|
42
43
|
@Prop({
|
|
43
44
|
type: Array,
|
|
44
45
|
default: function () {
|
|
@@ -90,6 +91,7 @@ class itfDatePickerInline extends Vue {
|
|
|
90
91
|
view: (this.valueAsLuxon && !this.minView) ? 'days' : this.startView,
|
|
91
92
|
minView: this.minView,
|
|
92
93
|
minDate: this.minDate,
|
|
94
|
+
maxDate: this.maxDate,
|
|
93
95
|
selectedDates: this.valueAsLuxon ? [this.valueAsLuxon.toJSDate()] : [],
|
|
94
96
|
onSelect: ({ date }) => {
|
|
95
97
|
if (this.range && !this.calendar.rangeDateTo) {
|
|
@@ -6,28 +6,29 @@
|
|
|
6
6
|
</slot>
|
|
7
7
|
</div>
|
|
8
8
|
<input
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
ref="input"
|
|
10
|
+
readonly
|
|
11
|
+
:disabled="disabled"
|
|
12
|
+
class="form-control text-capitalize"
|
|
13
|
+
:class="{ 'is-invalid': isInvalid(), 'is-valid': isSuccess() }"
|
|
14
|
+
@focus="onFocus"
|
|
15
|
+
@blur="onBlur"
|
|
16
|
+
:value="displayValue"
|
|
17
|
+
:placeholder="placeholder"
|
|
18
18
|
/>
|
|
19
19
|
<div style="display: none">
|
|
20
20
|
<div ref="dropdown" class="itf-monthpicker__dropdown border rounded">
|
|
21
21
|
<div>
|
|
22
22
|
<itf-date-picker-inline
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
:value="value"
|
|
24
|
+
start-view="months"
|
|
25
|
+
min-view="months"
|
|
26
|
+
:min-date="minDate"
|
|
27
|
+
:max-date="maxDate"
|
|
28
|
+
only-calendar
|
|
29
|
+
:display-format="displayFormat"
|
|
30
|
+
:value-format="valueFormat"
|
|
31
|
+
@input="selectInlineDate"
|
|
31
32
|
/>
|
|
32
33
|
</div>
|
|
33
34
|
<slot name="after-calendar" />
|
|
@@ -57,6 +58,7 @@ class itfMonthPicker extends Vue {
|
|
|
57
58
|
@Prop({ type: Boolean }) disabled;
|
|
58
59
|
@Prop({ type: String, default: 'ISO' }) valueFormat;
|
|
59
60
|
@Prop({ type: [String, Date], default: '' }) minDate;
|
|
61
|
+
@Prop({ type: [String, Date], default: '' }) maxDate;
|
|
60
62
|
@Prop({ type: String, default: 'LLLL, yyyy' }) displayFormat;
|
|
61
63
|
@Prop({ type: String, default: '' }) placeholder;
|
|
62
64
|
@Prop({ type: String, default: '' }) prependIcon;
|
|
@@ -42,6 +42,8 @@ storiesOf('Common', module)
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
template: `<div>
|
|
45
|
+
<itf-app ref="app">
|
|
46
|
+
|
|
45
47
|
<p>You need wrap whole application with this tag</p>
|
|
46
48
|
|
|
47
49
|
<h2>Usage</h2>
|
|
@@ -57,8 +59,6 @@ storiesOf('Common', module)
|
|
|
57
59
|
|
|
58
60
|
<h2>Example</h2>
|
|
59
61
|
|
|
60
|
-
<itf-app ref="app">
|
|
61
|
-
|
|
62
62
|
<itf-form ref="form">
|
|
63
63
|
|
|
64
64
|
<itf-icon name="project_tnm" size="32" />
|
|
@@ -71,6 +71,7 @@ storiesOf('Common', module)
|
|
|
71
71
|
|
|
72
72
|
<itf-select
|
|
73
73
|
:options="['tnm', 'fixed', 'nonprofit']"
|
|
74
|
+
append-to-body
|
|
74
75
|
v-model="text">
|
|
75
76
|
|
|
76
77
|
<template #selected-option="{ option }">
|
|
@@ -96,7 +97,11 @@ storiesOf('Common', module)
|
|
|
96
97
|
<div class="col-12">
|
|
97
98
|
<itf-label :rules="[$v.emptyValidation()]" :value="text" label="Text field" required>
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
<itf-text-field v-model="text">
|
|
101
|
+
<template #addon>
|
|
102
|
+
<span class="input-group-text" id="basic-addon1">@</span>
|
|
103
|
+
</template>
|
|
104
|
+
</itf-text-field>
|
|
100
105
|
|
|
101
106
|
</itf-label>
|
|
102
107
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
|
|
3
|
-
<div class="scrollable scrollable-x
|
|
3
|
+
<div class="itf-table2 scrollable scrollable-x" :class="{'permanent-checkboxes': selectedIds.length}">
|
|
4
4
|
<itf-checkbox-group v-model="selectedIds">
|
|
5
5
|
<template v-for="(group, index) in groups">
|
|
6
6
|
<div class="table-view-body">
|
|
@@ -21,8 +21,11 @@
|
|
|
21
21
|
:show-add-column="showAddColumn"
|
|
22
22
|
:show-header="!noHeader"
|
|
23
23
|
:schema="schema"
|
|
24
|
+
:editable="editable"
|
|
24
25
|
:no-column-menu="noColumnMenu"
|
|
25
26
|
:no-select-all="noSelectAll"
|
|
27
|
+
:currencies="currencies"
|
|
28
|
+
:currency="currency"
|
|
26
29
|
@new="$emit('new', $event)"
|
|
27
30
|
@add-column="$emit('add-column', $event)"
|
|
28
31
|
>
|
|
@@ -39,37 +42,6 @@
|
|
|
39
42
|
</div>
|
|
40
43
|
|
|
41
44
|
</template>
|
|
42
|
-
<style lang="scss">
|
|
43
|
-
.scrollable {
|
|
44
|
-
--itf-table-hover-bg: #f2f2f2;
|
|
45
|
-
--itf-table-min-width: 45px;
|
|
46
|
-
|
|
47
|
-
body[data-theme="dark"] & {
|
|
48
|
-
--itf-table-hover-bg: #393b41;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
-webkit-overflow-scrolling: touch;
|
|
52
|
-
overflow: hidden scroll;
|
|
53
|
-
|
|
54
|
-
&.scrollable-x {
|
|
55
|
-
overflow-x: scroll;
|
|
56
|
-
padding-right: 4px;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
.last-sticky-column:after {
|
|
60
|
-
content: '';
|
|
61
|
-
background: linear-gradient(to right,#dfe0e2,rgba(255,0,0,0));
|
|
62
|
-
height: 100%;
|
|
63
|
-
width: 6px;
|
|
64
|
-
position: absolute;
|
|
65
|
-
bottom: 0;
|
|
66
|
-
right: -7px;
|
|
67
|
-
|
|
68
|
-
body[data-theme="dark"] & {
|
|
69
|
-
background: linear-gradient(to right, #707070,rgba(255,0,0,0));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
</style>
|
|
73
45
|
<script>
|
|
74
46
|
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
|
|
75
47
|
import itfCheckboxGroup from '../checkbox/CheckboxGroup.vue';
|
|
@@ -77,6 +49,7 @@ import itfButton from '../button/Button.vue';
|
|
|
77
49
|
import itfIcon from '../icon/Icon.vue';
|
|
78
50
|
import itfTableGroup from './TableGroup.vue';
|
|
79
51
|
import itfTableHeader from './TableHeader.vue';
|
|
52
|
+
import './table2.scss';
|
|
80
53
|
|
|
81
54
|
export default @Component({
|
|
82
55
|
name: 'itfTable2',
|
|
@@ -95,9 +68,11 @@ class itfTable2 extends Vue {
|
|
|
95
68
|
// @Prop({ required: true, type: Array }) columns;
|
|
96
69
|
@Prop({ required: true, type: Array }) rows;
|
|
97
70
|
@Prop({ type: String, default: null }) groupBy;
|
|
98
|
-
@Prop({ type: String, default:
|
|
71
|
+
@Prop({ type: String, default: null }) idProperty;
|
|
99
72
|
@Prop({ type: String, default: null }) stateName; // save state to storage
|
|
100
73
|
@Prop({ type: Object, default: () => ({}) }) schema;
|
|
74
|
+
@Prop() currency;
|
|
75
|
+
@Prop() currencies;
|
|
101
76
|
@Prop(Boolean) addNewRows;
|
|
102
77
|
@Prop(Boolean) columnSorting;
|
|
103
78
|
@Prop(Boolean) columnResizing;
|
|
@@ -107,6 +82,7 @@ class itfTable2 extends Vue {
|
|
|
107
82
|
@Prop(Boolean) noHeader;
|
|
108
83
|
@Prop(Boolean) noColumnMenu;
|
|
109
84
|
@Prop(Boolean) noSelectAll;
|
|
85
|
+
@Prop(Boolean) editable;
|
|
110
86
|
|
|
111
87
|
state = {
|
|
112
88
|
selectedIds: [],
|
|
@@ -166,10 +142,11 @@ class itfTable2 extends Vue {
|
|
|
166
142
|
|
|
167
143
|
get groups() {
|
|
168
144
|
const { groupBy, rows } = this;
|
|
169
|
-
|
|
170
|
-
|
|
145
|
+
const indexedRows = (rows || []).map((row, index) => ({ ...row, $index: index }));
|
|
146
|
+
if (!groupBy || !indexedRows.length) {
|
|
147
|
+
return [{ name: '', rows: indexedRows }]
|
|
171
148
|
}
|
|
172
|
-
const groups =
|
|
149
|
+
const groups = indexedRows.reduce((acc, row) => {
|
|
173
150
|
const group = row[groupBy];
|
|
174
151
|
if (!acc[group]) {
|
|
175
152
|
acc[group] = [];
|
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
<div
|
|
5
5
|
v-for="(item, n) in rows"
|
|
6
6
|
:key="n"
|
|
7
|
-
group="items"
|
|
7
|
+
group="items"
|
|
8
|
+
data-test="table-item"
|
|
9
|
+
class="table-view-item grouped draggable-item"
|
|
10
|
+
:class="{'selected': selectedIds.includes(item[idProperty])}"
|
|
11
|
+
>
|
|
8
12
|
<div class="table-row-template">
|
|
9
13
|
<div accept-group="items" class="table-view-body-space"></div>
|
|
10
14
|
<div class="shadow-area">
|
|
@@ -19,7 +23,8 @@
|
|
|
19
23
|
</div>
|
|
20
24
|
<div class="indicator sticky">
|
|
21
25
|
<div class="fill table-view-row-count" :class="{'on-rest': !noSelectAll}">
|
|
22
|
-
<span>{{ item[idProperty] }}</span>
|
|
26
|
+
<span v-if="idProperty">{{ item[idProperty] }}</span>
|
|
27
|
+
<span v-else>{{ (n + 1) }}</span>
|
|
23
28
|
</div>
|
|
24
29
|
<div v-if="!noSelectAll" class="fill on-hover">
|
|
25
30
|
<itf-checkbox :value="item[idProperty]" />
|
|
@@ -31,28 +36,28 @@
|
|
|
31
36
|
v-if="column.visible !== false"
|
|
32
37
|
:data-column="k"
|
|
33
38
|
:style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`"
|
|
34
|
-
:class="{'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'flex-grow-1': column.grow, 'px-2': !column.editable, '
|
|
35
|
-
class="table-view-item-value d-flex h-100
|
|
39
|
+
:class="{'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'flex-grow-1': column.grow, 'px-2': !(column.editable && editable), 'editable': column.editable && editable}"
|
|
40
|
+
class="table-view-item-value d-flex h-100">
|
|
36
41
|
<slot :name="`column.${column.property}`" :item="item" :column="column">
|
|
37
|
-
<template v-if="column.editable">
|
|
42
|
+
<template v-if="column.editable && editable">
|
|
38
43
|
<slot :name="`edit.${column.type}`" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)" :item="item" :column="column">
|
|
39
44
|
<itf-text-field class="w-100" v-if="column.type === 'text'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
|
|
40
45
|
<itf-hours-field
|
|
41
46
|
class="w-100"
|
|
42
|
-
placeholder="
|
|
47
|
+
placeholder="00h 00m"
|
|
43
48
|
v-else-if="column.type === 'time'"
|
|
44
49
|
:hours="getValue(item, column)"
|
|
45
50
|
@update:hours="updateValue(item, $event, n, column)"
|
|
46
51
|
/>
|
|
47
52
|
<itf-textarea class="w-100" :rows="2" autogrow v-else-if="column.type === 'textarea'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
|
|
48
|
-
<itf-money-field class="w-100" v-else-if="column.type === 'money'"
|
|
53
|
+
<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)" />
|
|
49
54
|
</slot>
|
|
50
55
|
</template>
|
|
51
|
-
<
|
|
52
|
-
<slot :name="`format.${column.type}`" :value="getValue(item, column)" :item="item" :column="column">
|
|
56
|
+
<div v-else>
|
|
57
|
+
<slot :name="`format.${column.type}`" :value="getValue(item, column)" :update="(value) => updateValue(item, value, n, column)" :item="item" :column="column">
|
|
53
58
|
{{getValue(item, column)}}
|
|
54
59
|
</slot>
|
|
55
|
-
</
|
|
60
|
+
</div>
|
|
56
61
|
</slot>
|
|
57
62
|
</div>
|
|
58
63
|
</template>
|
|
@@ -92,45 +97,6 @@
|
|
|
92
97
|
flex-direction: row;
|
|
93
98
|
}
|
|
94
99
|
|
|
95
|
-
.table-view-item-value {
|
|
96
|
-
text-overflow: ellipsis;
|
|
97
|
-
background-color: var(--bs-body-bg);
|
|
98
|
-
border-right: 1px solid var(--bs-border-color);
|
|
99
|
-
border-bottom: 1px solid var(--bs-border-color);
|
|
100
|
-
align-items: stretch;
|
|
101
|
-
display: flex;
|
|
102
|
-
position: relative;
|
|
103
|
-
min-width: var(--itf-table-min-width);
|
|
104
|
-
|
|
105
|
-
&.highlight-drop-column {
|
|
106
|
-
position: relative;
|
|
107
|
-
|
|
108
|
-
&:after {
|
|
109
|
-
content: "";
|
|
110
|
-
height: 100%;
|
|
111
|
-
z-index: 100;
|
|
112
|
-
width: 2px;
|
|
113
|
-
background: #47beff;
|
|
114
|
-
margin-left: -1px;
|
|
115
|
-
position: absolute;
|
|
116
|
-
left: 0;
|
|
117
|
-
}
|
|
118
|
-
&.right:after {
|
|
119
|
-
left: auto;
|
|
120
|
-
right: 0;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
&:hover {
|
|
124
|
-
background-color: var(--bs-tertiary-bg);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
&.sticky {
|
|
128
|
-
z-index: 4;
|
|
129
|
-
position: -webkit-sticky;
|
|
130
|
-
position: sticky;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
100
|
.table-item-inner .extra {
|
|
135
101
|
flex-grow: 1;
|
|
136
102
|
border-color: var(--bs-border-color);
|
|
@@ -143,9 +109,9 @@
|
|
|
143
109
|
z-index: 4;
|
|
144
110
|
position: -webkit-sticky;
|
|
145
111
|
position: sticky;
|
|
146
|
-
background-color: var(--
|
|
112
|
+
background-color: var(--itf-table2-row-bg);
|
|
147
113
|
//border-right: 1px solid var(--bs-border-color);
|
|
148
|
-
border-bottom: 1px solid var(--bs-border-color);
|
|
114
|
+
//border-bottom: 1px solid var(--bs-border-color);
|
|
149
115
|
display: flex;
|
|
150
116
|
align-items: center;
|
|
151
117
|
justify-content: center;
|
|
@@ -201,6 +167,7 @@
|
|
|
201
167
|
|
|
202
168
|
.table-item-inner .boundary.right {
|
|
203
169
|
left: auto;
|
|
170
|
+
border-right: 1px solid var(--itf-table-border-color);
|
|
204
171
|
right: 0;
|
|
205
172
|
}
|
|
206
173
|
|
|
@@ -255,6 +222,10 @@ class itfTableBody extends Vue {
|
|
|
255
222
|
@Prop() idProperty;
|
|
256
223
|
@Prop(Boolean) showAddColumn;
|
|
257
224
|
@Prop(Boolean) noSelectAll;
|
|
225
|
+
@Prop(Boolean) editable;
|
|
226
|
+
@Prop() selectedIds;
|
|
227
|
+
@Prop() currency;
|
|
228
|
+
@Prop() currencies;
|
|
258
229
|
|
|
259
230
|
getValue(item, column) {
|
|
260
231
|
return get(item, column.property);
|
|
@@ -22,11 +22,8 @@
|
|
|
22
22
|
</span>
|
|
23
23
|
<span class="d-flex align-items-center line-overflow group-header-value"
|
|
24
24
|
data-test="group-value-group-label-value">
|
|
25
|
-
{{ title }}
|
|
25
|
+
<slot name="group-title" :rows="rows" :title="rows">{{ title }}</slot>
|
|
26
26
|
</span>
|
|
27
|
-
<div data-test="table-group-item-count" class="table-group-item-count">
|
|
28
|
-
{{ rows.length }}
|
|
29
|
-
</div>
|
|
30
27
|
</a>
|
|
31
28
|
</div>
|
|
32
29
|
</div>
|
|
@@ -42,6 +39,7 @@
|
|
|
42
39
|
:show-add-column="showAddColumn"
|
|
43
40
|
:rows="rows"
|
|
44
41
|
:schema="schema"
|
|
42
|
+
:editable="editable"
|
|
45
43
|
:no-column-menu="noColumnMenu"
|
|
46
44
|
:no-select-all="noSelectAll"
|
|
47
45
|
:selected-ids="selectedIds"
|
|
@@ -57,8 +55,12 @@
|
|
|
57
55
|
@update="$emit('update', $event)"
|
|
58
56
|
:id-property="idProperty"
|
|
59
57
|
:rows="rows"
|
|
58
|
+
:editable="editable"
|
|
59
|
+
:currency="currency"
|
|
60
|
+
:currencies="currencies"
|
|
60
61
|
:columns="visibleColumns"
|
|
61
62
|
:no-select-all="noSelectAll"
|
|
63
|
+
:selected-ids="selectedIds"
|
|
62
64
|
:show-add-column="showAddColumn">
|
|
63
65
|
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
64
66
|
<slot :name="name" v-bind="slotData || {}"/>
|
|
@@ -74,8 +76,8 @@
|
|
|
74
76
|
class="table-row-template d-flex align-items-stretch">
|
|
75
77
|
<div class="shadow-area"></div>
|
|
76
78
|
<a href="" @click.prevent="$emit('new', title)" data-test="table-add-new-item"
|
|
77
|
-
class="d-flex align-items-center flex-grow-1 table-add-new-item
|
|
78
|
-
<span class="d-sticky d-flex align-items-center">
|
|
79
|
+
class="d-flex align-items-center flex-grow-1 table-add-new-item text-decoration-none">
|
|
80
|
+
<span class="d-sticky d-flex align-items-center py-1">
|
|
79
81
|
<itf-icon name="plus"/>
|
|
80
82
|
<span>{{ newLabel }}</span>
|
|
81
83
|
</span>
|
|
@@ -89,6 +91,7 @@
|
|
|
89
91
|
<div class="table-summary-columns d-flex tw-flex-row align-items-center">
|
|
90
92
|
<span
|
|
91
93
|
v-for="(column, n) in visibleColumns"
|
|
94
|
+
v-if="column.visible !== false"
|
|
92
95
|
:key="n"
|
|
93
96
|
:data-column="n"
|
|
94
97
|
class="position-relative line-overflow"
|
|
@@ -203,13 +206,13 @@
|
|
|
203
206
|
font-size: 1.25rem;
|
|
204
207
|
border-left: 0;
|
|
205
208
|
border-bottom: 0;
|
|
206
|
-
border-right: 1px solid var(--bs-border-color);
|
|
209
|
+
//border-right: 1px solid var(--bs-border-color);
|
|
207
210
|
|
|
208
211
|
&.header-additional-column {
|
|
209
212
|
border-radius: 0;
|
|
210
213
|
}
|
|
211
214
|
&:hover {
|
|
212
|
-
background: var(--hover-bg);
|
|
215
|
+
background: var(--itf-table-hover-bg);
|
|
213
216
|
}
|
|
214
217
|
}
|
|
215
218
|
|
|
@@ -228,7 +231,7 @@
|
|
|
228
231
|
|
|
229
232
|
.table-group-item-count {
|
|
230
233
|
padding: 0.125rem 0.5rem;
|
|
231
|
-
background-color: rgb(250 251 252 / 1);
|
|
234
|
+
//background-color: rgb(250 251 252 / 1);
|
|
232
235
|
border-radius: 0.1875rem;
|
|
233
236
|
font-weight: normal;
|
|
234
237
|
font-size: 1rem;
|
|
@@ -243,17 +246,19 @@
|
|
|
243
246
|
}
|
|
244
247
|
|
|
245
248
|
.table-add-new-item {
|
|
246
|
-
border-right: 1px solid
|
|
247
|
-
border-bottom: 1px solid
|
|
249
|
+
border-right: 1px solid var(--itf-table-border-color);
|
|
250
|
+
border-bottom: 1px solid var(--itf-table-border-color);
|
|
248
251
|
outline: none;
|
|
249
252
|
|
|
250
253
|
& > span {
|
|
251
254
|
left: var(--shadow-area-width);
|
|
252
255
|
position: sticky;
|
|
253
256
|
padding-left: var(--shadow-area-width);
|
|
257
|
+
border-left: 1px solid var(--itf-table-border-color);
|
|
258
|
+
height: 100%;
|
|
254
259
|
}
|
|
255
260
|
&:hover, &:active {
|
|
256
|
-
background: var(--hover-bg);
|
|
261
|
+
background: var(--itf-table-hover-bg);
|
|
257
262
|
}
|
|
258
263
|
}
|
|
259
264
|
|
|
@@ -272,7 +277,7 @@
|
|
|
272
277
|
padding-right: .25rem;
|
|
273
278
|
}
|
|
274
279
|
.summary-text {
|
|
275
|
-
color: var(--
|
|
280
|
+
color: var(--itf-table-summary-text);
|
|
276
281
|
}
|
|
277
282
|
&.table-summary-persist .table-summary-column,
|
|
278
283
|
&:hover .table-summary-column {
|
|
@@ -315,6 +320,8 @@ class itfTableGroup extends Vue {
|
|
|
315
320
|
@Prop() selectedIds;
|
|
316
321
|
@Prop() title;
|
|
317
322
|
@Prop() idProperty;
|
|
323
|
+
@Prop() currency;
|
|
324
|
+
@Prop() currencies;
|
|
318
325
|
@Prop(Boolean) showGrouping;
|
|
319
326
|
@Prop(Boolean) showSummary;
|
|
320
327
|
@Prop(Boolean) addNewRows;
|
|
@@ -324,6 +331,7 @@ class itfTableGroup extends Vue {
|
|
|
324
331
|
@Prop(Boolean) showHeader;
|
|
325
332
|
@Prop(Boolean) noColumnMenu;
|
|
326
333
|
@Prop(Boolean) noSelectAll;
|
|
334
|
+
@Prop(Boolean) editable;
|
|
327
335
|
@Prop({type: String, default: function() { return this.$t('components.table.new'); } }) newLabel;
|
|
328
336
|
@Prop({type: Object, default: () => ({})}) schema;
|
|
329
337
|
|
|
@@ -374,7 +382,7 @@ class itfTableGroup extends Vue {
|
|
|
374
382
|
get calculateMethods() {
|
|
375
383
|
return [
|
|
376
384
|
{ id: 'none', title: this.$t('components.table.calculateNone') },
|
|
377
|
-
{ id: 'total', title: this.$t('components.table.calculateTotal'), summary: 'Total', func: (rows, column) => rows.reduce((acc, row) => acc + (getNumber(row, column.property)), 0) },
|
|
385
|
+
{ id: 'total', title: this.$t('components.table.calculateTotal'), summary: 'Total', func: (rows, column) => round(rows.reduce((acc, row) => acc + (getNumber(row, column.property)), 0)) },
|
|
378
386
|
{ id: 'average', title: this.$t('components.table.calculateAverage'), summary: 'Average', func: (rows, column) => {
|
|
379
387
|
const sum = rows.reduce((acc, row) => acc + (getNumber(row, column.property)), 0);
|
|
380
388
|
return round(sum / rows.length, 3);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
|
|
3
|
-
<div class="itf-
|
|
3
|
+
<div class="itf-table2__header" :class="{'no-header': !visibleHeader}">
|
|
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>
|
|
@@ -33,11 +33,12 @@
|
|
|
33
33
|
v-draggable="{ handle: true, payload: { index: n, item: column }, mirror: {yAxis:false} }">
|
|
34
34
|
<itf-dropdown text append-to-body shadow ref="dropdown" class="w-100" :disabled="noColumnMenu">
|
|
35
35
|
<template #button>
|
|
36
|
-
<span :title="column.title[locale] || column.title['en_US']">
|
|
36
|
+
<span class="itf-table2__header-title" :title="column.title[locale] || column.title['en_US']">
|
|
37
37
|
<span v-if="column.icon" :class="column.icon"></span>
|
|
38
38
|
{{column.title[locale] || column.title['en_US']}}
|
|
39
|
+
<div v-if="column.prefix" class="itf-table2__subtitle" v-text="column.prefix" />
|
|
39
40
|
</span>
|
|
40
|
-
<!-- <itf-icon name="arrow_up" :size="16" class="ms-1" />-->
|
|
41
|
+
<!-- <itf-icon name="arrow_up" :size="16" class="ms-1" />-->
|
|
41
42
|
</template>
|
|
42
43
|
|
|
43
44
|
<div v-if="column.sortable">
|
|
@@ -127,162 +128,6 @@
|
|
|
127
128
|
</div>
|
|
128
129
|
|
|
129
130
|
</template>
|
|
130
|
-
<style lang="scss">
|
|
131
|
-
.itf-table-header {
|
|
132
|
-
position: sticky;
|
|
133
|
-
top: 0;
|
|
134
|
-
z-index: calc(var(--row-count) + 1);
|
|
135
|
-
|
|
136
|
-
&.no-header {
|
|
137
|
-
--table-row-height: 0px;
|
|
138
|
-
--table-small-row-size: 0px;
|
|
139
|
-
|
|
140
|
-
.table-view-header-value {
|
|
141
|
-
border-top: 0 none;
|
|
142
|
-
border-bottom: 0 none;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
.table-header.draggable-mirror{
|
|
146
|
-
z-index: 100000001;
|
|
147
|
-
background: rgba(235,237,239,0.75);
|
|
148
|
-
}
|
|
149
|
-
.table-row-template {
|
|
150
|
-
display: flex;
|
|
151
|
-
align-items: stretch;
|
|
152
|
-
height: var(--table-small-row-size);
|
|
153
|
-
user-select: none;
|
|
154
|
-
}
|
|
155
|
-
.table-view-header-value {
|
|
156
|
-
cursor: pointer;
|
|
157
|
-
align-items: center;
|
|
158
|
-
justify-content: center;
|
|
159
|
-
height: var(--table-row-height);
|
|
160
|
-
white-space: nowrap;
|
|
161
|
-
//border-top: 0;
|
|
162
|
-
border-top: 1px solid transparent;
|
|
163
|
-
border-left: 0;
|
|
164
|
-
border-right-width: thin;
|
|
165
|
-
border-bottom-width: thin;
|
|
166
|
-
border-style: solid;
|
|
167
|
-
position: relative;
|
|
168
|
-
display: flex;
|
|
169
|
-
min-width: var(--itf-table-min-width);
|
|
170
|
-
border-right-color: transparent;
|
|
171
|
-
border-bottom-color: var(--bs-border-color);
|
|
172
|
-
background-color: var(--bs-body-bg);
|
|
173
|
-
//background-color: rgb(238 238 238 / 1);
|
|
174
|
-
font-weight: 500;
|
|
175
|
-
|
|
176
|
-
&.last-sticky-column {
|
|
177
|
-
border-right-color: var(--bs-border-color);
|
|
178
|
-
}
|
|
179
|
-
&.reserved {
|
|
180
|
-
left: var(--shadow-area-width);
|
|
181
|
-
width: var(--indicator-area-width);
|
|
182
|
-
}
|
|
183
|
-
&.sticky {
|
|
184
|
-
position: sticky;
|
|
185
|
-
position: -webkit-sticky;
|
|
186
|
-
z-index: calc(var(--row-count) + 4);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
.table-header {
|
|
190
|
-
flex: 0 0 auto;
|
|
191
|
-
overflow: hidden;
|
|
192
|
-
width: 100%;
|
|
193
|
-
text-overflow: ellipsis;
|
|
194
|
-
padding-left: 0.75rem;
|
|
195
|
-
padding-right: 0.75rem;
|
|
196
|
-
gap: 0.25rem;
|
|
197
|
-
align-items: center;
|
|
198
|
-
& > div {
|
|
199
|
-
min-height: var(--table-row-height);
|
|
200
|
-
align-items: center;
|
|
201
|
-
justify-content: space-between;
|
|
202
|
-
display: flex;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
&.table-header-add-column {
|
|
206
|
-
text-overflow: clip;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
.resize-handle {
|
|
210
|
-
width: 4px;
|
|
211
|
-
height: var(--table-row-height);
|
|
212
|
-
position: absolute;
|
|
213
|
-
right: -2px;
|
|
214
|
-
top: 0;
|
|
215
|
-
background: #29ACE1;
|
|
216
|
-
border-radius: 2px;
|
|
217
|
-
z-index: 100;
|
|
218
|
-
opacity: 0;
|
|
219
|
-
cursor: ew-resize;
|
|
220
|
-
transition: .2s;
|
|
221
|
-
|
|
222
|
-
&:hover {
|
|
223
|
-
opacity: 1;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
.context-menu-toggle {
|
|
227
|
-
flex: 1 1 auto;
|
|
228
|
-
text-overflow: ellipsis;
|
|
229
|
-
white-space: nowrap;
|
|
230
|
-
overflow: hidden;
|
|
231
|
-
|
|
232
|
-
span {
|
|
233
|
-
font-size: 12px;
|
|
234
|
-
line-height: 36px;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
.itf-sortable-list {
|
|
238
|
-
display: flex;
|
|
239
|
-
}
|
|
240
|
-
.table-view-header-space {
|
|
241
|
-
height: 100%;
|
|
242
|
-
position: absolute;
|
|
243
|
-
left: 0;
|
|
244
|
-
display: none;
|
|
245
|
-
background: transparent;
|
|
246
|
-
z-index: 100;
|
|
247
|
-
width: 2px;
|
|
248
|
-
margin-left: -1px;
|
|
249
|
-
|
|
250
|
-
&.right {
|
|
251
|
-
left: auto;
|
|
252
|
-
right: 0;
|
|
253
|
-
top: 0;
|
|
254
|
-
}
|
|
255
|
-
&.active {
|
|
256
|
-
display: block;
|
|
257
|
-
&.over {
|
|
258
|
-
background: #47BEFF;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
.draggable-mirror {
|
|
263
|
-
opacity: .5;
|
|
264
|
-
}
|
|
265
|
-
.draggable-container--over .table-view-header-space {
|
|
266
|
-
display: block;
|
|
267
|
-
}
|
|
268
|
-
.draggable-container--over .draggable--over .table-view-header-space {
|
|
269
|
-
background: #47BEFF;
|
|
270
|
-
}
|
|
271
|
-
.table-view-header-space > .table-view-header-dropzone {
|
|
272
|
-
position: absolute;
|
|
273
|
-
top: 0;
|
|
274
|
-
right: -50px;
|
|
275
|
-
bottom: 0;
|
|
276
|
-
left: -50px;
|
|
277
|
-
}
|
|
278
|
-
.table-view-header-value:not(.reserved):hover {
|
|
279
|
-
background-color: var(--bs-tertiary-bg);
|
|
280
|
-
}
|
|
281
|
-
.draggable-source--is-dragging {
|
|
282
|
-
z-index: 100;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
</style>
|
|
286
131
|
<script>
|
|
287
132
|
import {Vue, Component, Prop, PropSync, Watch, Inject} from 'vue-property-decorator';
|
|
288
133
|
import itfCheckbox from '../checkbox/Checkbox.vue';
|
|
@@ -323,6 +168,7 @@ class itfTableHeader extends Vue {
|
|
|
323
168
|
@Prop(Boolean) visibleHeader;
|
|
324
169
|
@Prop(Boolean) noColumnMenu;
|
|
325
170
|
@Prop(Boolean) noSelectAll;
|
|
171
|
+
@Prop(Boolean) editable;
|
|
326
172
|
|
|
327
173
|
@Watch('selectedIds')
|
|
328
174
|
@Watch('rows')
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { storiesOf } from '@storybook/vue';
|
|
2
|
+
import ITFSettings from '../../ITFSettings';
|
|
2
3
|
import itfApp from '../app/App.vue';
|
|
3
4
|
import itfButton from '../button/Button.vue';
|
|
4
5
|
import itfTable from './Table.vue';
|
|
5
6
|
import itfTable2 from './Table2.vue';
|
|
7
|
+
import itfSelect from '../select/Select.vue';
|
|
6
8
|
|
|
7
9
|
const exampleData = [{
|
|
8
10
|
Employee: 'Cool',
|
|
@@ -72,12 +74,17 @@ const exampleData = [{
|
|
|
72
74
|
Notes: 'Test'
|
|
73
75
|
}];
|
|
74
76
|
|
|
77
|
+
ITFSettings.currencies = [
|
|
78
|
+
{ Id: '1', Code: 'USD', Title: 'USD', IsDefault: true, Symbol: '$' }
|
|
79
|
+
];
|
|
80
|
+
|
|
75
81
|
storiesOf('Common', module)
|
|
76
82
|
.add('Simple Table', () => ({
|
|
77
83
|
components: {
|
|
78
84
|
itfTable,
|
|
79
85
|
itfButton,
|
|
80
|
-
itfTable2
|
|
86
|
+
itfTable2,
|
|
87
|
+
itfSelect
|
|
81
88
|
},
|
|
82
89
|
data() {
|
|
83
90
|
return {
|
|
@@ -110,8 +117,8 @@ storiesOf('Common', module)
|
|
|
110
117
|
{
|
|
111
118
|
Id: 1,
|
|
112
119
|
summary: true,
|
|
113
|
-
Description: 'Total',
|
|
114
|
-
EmployeeId:
|
|
120
|
+
Description: 'Total asd asd dad ad ada dadad a',
|
|
121
|
+
EmployeeId: 1,
|
|
115
122
|
Total: 100,
|
|
116
123
|
FTE: 1.0,
|
|
117
124
|
Position: { Title: 'Developer', Id: 1 },
|
|
@@ -131,7 +138,7 @@ storiesOf('Common', module)
|
|
|
131
138
|
{
|
|
132
139
|
"property": "Description",
|
|
133
140
|
"title": { "en_US": "Description", "uk_UA": "Прізвище" },
|
|
134
|
-
"type": "
|
|
141
|
+
"type": "text",
|
|
135
142
|
"editable": true,
|
|
136
143
|
"sortable": false,
|
|
137
144
|
width: 200,
|
|
@@ -140,7 +147,8 @@ storiesOf('Common', module)
|
|
|
140
147
|
},
|
|
141
148
|
{
|
|
142
149
|
"property": "EmployeeId",
|
|
143
|
-
"title": { "en_US": "Employee", "uk_UA": "Імʼя" },
|
|
150
|
+
"title": { "en_US": "Employee full name", "uk_UA": "Імʼя" },
|
|
151
|
+
prefix: 'USD',
|
|
144
152
|
"type": "employee",
|
|
145
153
|
"copy": true,
|
|
146
154
|
"editable": true,
|
|
@@ -331,8 +339,35 @@ storiesOf('Common', module)
|
|
|
331
339
|
{{item.EmployeeId}}
|
|
332
340
|
</template>
|
|
333
341
|
<template #edit.employee="{ item }">
|
|
342
|
+
<itf-select
|
|
343
|
+
class="w-100"
|
|
344
|
+
v-model="item.EmployeeId"
|
|
345
|
+
:reduce="item => item.Id"
|
|
346
|
+
:get-option-label="item => item.Name"
|
|
347
|
+
:options="[{ Id: 1, Name: 'Vitalii Savchuk' }]" />
|
|
348
|
+
</template>
|
|
349
|
+
</itf-table2>
|
|
350
|
+
|
|
351
|
+
<itf-table2
|
|
352
|
+
editable
|
|
353
|
+
add-new-rows
|
|
354
|
+
@new="onAdd"
|
|
355
|
+
state-name="test"
|
|
356
|
+
:schema="schema"
|
|
357
|
+
:columns.sync="columns2" :rows="list2"
|
|
358
|
+
show-summary
|
|
359
|
+
column-sorting column-resizing show-add-column show-grouping @add-column="onAdd">
|
|
360
|
+
<template #format.employee="{ item }">
|
|
334
361
|
{{item.EmployeeId}}
|
|
335
362
|
</template>
|
|
363
|
+
<template #edit.employee="{ item }">
|
|
364
|
+
<itf-select
|
|
365
|
+
class="w-100"
|
|
366
|
+
v-model="item.EmployeeId"
|
|
367
|
+
:reduce="item => item.Id"
|
|
368
|
+
:get-option-label="item => item.Name"
|
|
369
|
+
:options="[{ Id: 1, Name: 'Vitalii Savchuk' }]" />
|
|
370
|
+
</template>
|
|
336
371
|
</itf-table2>
|
|
337
372
|
|
|
338
373
|
<br />
|
|
@@ -439,7 +474,7 @@ storiesOf('Common', module)
|
|
|
439
474
|
list2: [
|
|
440
475
|
{
|
|
441
476
|
summary: true,
|
|
442
|
-
Employee: 'Total',
|
|
477
|
+
Employee: 'Total asda das dasd ada dad adaddas',
|
|
443
478
|
Total: 100,
|
|
444
479
|
FTE: 1.0,
|
|
445
480
|
Position: 'Developer',
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
.itf-table2 {
|
|
2
|
+
--itf-table-border-color: #dbddd1;
|
|
3
|
+
--itf-table-header-bg: #f9faf5;
|
|
4
|
+
--itf-table-hover-header-bg: var(--bs-tertiary-bg);
|
|
5
|
+
--itf-table-hover-bg: #f2f2f2;
|
|
6
|
+
--itf-table-bg: var(--bs-body-bg);
|
|
7
|
+
--itf-table-min-width: 45px;
|
|
8
|
+
--itf-table-input-border-color: #aaaba6;
|
|
9
|
+
--itf-table-input-focus-border-color: #0028aa;
|
|
10
|
+
--itf-table-selected-bg: #cbd6f4;
|
|
11
|
+
--itf-table-header-subtitle-color: #aeafaa;
|
|
12
|
+
--itf-table-summary-text: var(--bs-tertiary-color);
|
|
13
|
+
|
|
14
|
+
// dark
|
|
15
|
+
body[data-theme="dark"] & {
|
|
16
|
+
--itf-table-hover-bg: #393b41;
|
|
17
|
+
--itf-table-header-bg: #0f0f0f;
|
|
18
|
+
--itf-table-hover-header-bg: #252525;
|
|
19
|
+
--itf-table-border-color: var(--bs-card-border-color);
|
|
20
|
+
--itf-table-input-focus-border-color: #252525;
|
|
21
|
+
--itf-table-selected-bg: #011534;
|
|
22
|
+
--itf-table-summary-text: #82909d80;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
&.scrollable {
|
|
26
|
+
-webkit-overflow-scrolling: touch;
|
|
27
|
+
overflow: hidden scroll;
|
|
28
|
+
}
|
|
29
|
+
&.scrollable-x {
|
|
30
|
+
overflow-x: scroll;
|
|
31
|
+
padding-right: 4px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&__header {
|
|
35
|
+
background-color: var(--itf-table-header-bg);
|
|
36
|
+
position: sticky;
|
|
37
|
+
top: 0;
|
|
38
|
+
z-index: calc(var(--row-count) + 1);
|
|
39
|
+
|
|
40
|
+
&.no-header {
|
|
41
|
+
--table-row-height: 0px;
|
|
42
|
+
--table-small-row-size: 0px;
|
|
43
|
+
|
|
44
|
+
.table-view-header-value {
|
|
45
|
+
border-top: 0 none;
|
|
46
|
+
border-bottom: 0 none;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
.table-header.draggable-mirror{
|
|
50
|
+
z-index: 100000001;
|
|
51
|
+
background: rgba(235,237,239,0.75);
|
|
52
|
+
}
|
|
53
|
+
.table-row-template {
|
|
54
|
+
display: flex;
|
|
55
|
+
align-items: stretch;
|
|
56
|
+
height: auto;
|
|
57
|
+
user-select: none;
|
|
58
|
+
}
|
|
59
|
+
.table-view-header-value {
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
align-items: center;
|
|
62
|
+
justify-content: center;
|
|
63
|
+
height: auto;
|
|
64
|
+
white-space: nowrap;
|
|
65
|
+
//border-top: 0;
|
|
66
|
+
border-top: 1px solid var(--itf-table-border-color);
|
|
67
|
+
border-left: 0;
|
|
68
|
+
border-right: 1px solid var(--itf-table-border-color);
|
|
69
|
+
border-bottom: 1px solid var(--itf-table-border-color);
|
|
70
|
+
position: relative;
|
|
71
|
+
display: flex;
|
|
72
|
+
min-width: var(--itf-table-min-width);
|
|
73
|
+
background-color: var(--itf-table-header-bg);
|
|
74
|
+
//background-color: var(--bs-body-bg);
|
|
75
|
+
//background-color: rgb(238 238 238 / 1);
|
|
76
|
+
//font-weight: 500;
|
|
77
|
+
|
|
78
|
+
&.last-sticky-column {
|
|
79
|
+
border-right-color: var(--bs-border-color);
|
|
80
|
+
}
|
|
81
|
+
&.reserved {
|
|
82
|
+
border-left: 1px solid var(--itf-table-border-color);
|
|
83
|
+
left: var(--shadow-area-width);
|
|
84
|
+
width: var(--indicator-area-width);
|
|
85
|
+
}
|
|
86
|
+
&.sticky {
|
|
87
|
+
position: sticky;
|
|
88
|
+
position: -webkit-sticky;
|
|
89
|
+
z-index: calc(var(--row-count) + 4);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
.table-header {
|
|
93
|
+
flex: 0 0 auto;
|
|
94
|
+
overflow: hidden;
|
|
95
|
+
width: 100%;
|
|
96
|
+
text-overflow: ellipsis;
|
|
97
|
+
padding-left: 0.75rem;
|
|
98
|
+
padding-right: 0.5rem;
|
|
99
|
+
gap: 0.25rem;
|
|
100
|
+
align-items: center;
|
|
101
|
+
& > div {
|
|
102
|
+
min-height: var(--table-row-height);
|
|
103
|
+
align-items: center;
|
|
104
|
+
justify-content: space-between;
|
|
105
|
+
display: flex;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&.table-header-add-column {
|
|
109
|
+
text-overflow: clip;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
.resize-handle {
|
|
113
|
+
width: 4px;
|
|
114
|
+
bottom: 0;
|
|
115
|
+
position: absolute;
|
|
116
|
+
right: -2px;
|
|
117
|
+
top: 0;
|
|
118
|
+
background: #29ACE1;
|
|
119
|
+
border-radius: 2px;
|
|
120
|
+
z-index: 100;
|
|
121
|
+
opacity: 0;
|
|
122
|
+
cursor: ew-resize;
|
|
123
|
+
transition: .2s;
|
|
124
|
+
|
|
125
|
+
&:hover {
|
|
126
|
+
opacity: 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
.context-menu-toggle {
|
|
130
|
+
flex: 1 1 auto;
|
|
131
|
+
text-overflow: ellipsis;
|
|
132
|
+
white-space: nowrap;
|
|
133
|
+
overflow: hidden;
|
|
134
|
+
|
|
135
|
+
span {
|
|
136
|
+
font-size: 12px;
|
|
137
|
+
line-height: 36px;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
.itf-sortable-list {
|
|
141
|
+
display: flex;
|
|
142
|
+
}
|
|
143
|
+
.table-view-header-space {
|
|
144
|
+
height: 100%;
|
|
145
|
+
position: absolute;
|
|
146
|
+
left: 0;
|
|
147
|
+
display: none;
|
|
148
|
+
background: transparent;
|
|
149
|
+
z-index: 100;
|
|
150
|
+
width: 2px;
|
|
151
|
+
margin-left: -1px;
|
|
152
|
+
|
|
153
|
+
&.right {
|
|
154
|
+
left: auto;
|
|
155
|
+
right: 0;
|
|
156
|
+
top: 0;
|
|
157
|
+
}
|
|
158
|
+
&.active {
|
|
159
|
+
display: block;
|
|
160
|
+
&.over {
|
|
161
|
+
background: #47BEFF;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
.draggable-mirror {
|
|
166
|
+
opacity: .5;
|
|
167
|
+
}
|
|
168
|
+
.draggable-container--over .table-view-header-space {
|
|
169
|
+
display: block;
|
|
170
|
+
}
|
|
171
|
+
.draggable-container--over .draggable--over .table-view-header-space {
|
|
172
|
+
background: #47BEFF;
|
|
173
|
+
}
|
|
174
|
+
.table-view-header-space > .table-view-header-dropzone {
|
|
175
|
+
position: absolute;
|
|
176
|
+
top: 0;
|
|
177
|
+
right: -50px;
|
|
178
|
+
bottom: 0;
|
|
179
|
+
left: -50px;
|
|
180
|
+
}
|
|
181
|
+
.table-view-header-value:not(.reserved):hover {
|
|
182
|
+
background-color: var(--itf-table-hover-header-bg);
|
|
183
|
+
}
|
|
184
|
+
.draggable-source--is-dragging {
|
|
185
|
+
z-index: 100;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
&__subtitle {
|
|
190
|
+
color: var(--itf-table-header-subtitle-color);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.table-view-item {
|
|
194
|
+
--itf-table2-row-bg: var(--itf-table-bg);
|
|
195
|
+
|
|
196
|
+
background-color: var(--itf-table2-row-bg);
|
|
197
|
+
|
|
198
|
+
&.selected {
|
|
199
|
+
--itf-table2-row-bg: var(--itf-table-selected-bg);
|
|
200
|
+
}
|
|
201
|
+
&:hover {
|
|
202
|
+
--itf-table2-row-bg: var(--itf-table-selected-bg);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.indicator {
|
|
206
|
+
border-left: 1px solid var(--itf-table-border-color);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
&:hover {
|
|
212
|
+
.table-view-item-value.editable {
|
|
213
|
+
.form-control {
|
|
214
|
+
border: 1px solid var(--itf-table-input-border-color);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
.table-view-item-value {
|
|
219
|
+
text-overflow: ellipsis;
|
|
220
|
+
align-items: stretch;
|
|
221
|
+
display: flex;
|
|
222
|
+
position: relative;
|
|
223
|
+
min-width: var(--itf-table-min-width);
|
|
224
|
+
background: var(--itf-table2-row-bg);
|
|
225
|
+
|
|
226
|
+
.itf-table2__striped & {
|
|
227
|
+
border-right: 1px solid var(--bs-border-color);
|
|
228
|
+
border-bottom: 1px solid var(--bs-border-color);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
&.editable {
|
|
232
|
+
padding: 2px;
|
|
233
|
+
|
|
234
|
+
.form-control {
|
|
235
|
+
border-radius: 0;
|
|
236
|
+
border: 1px solid transparent;
|
|
237
|
+
background-color: transparent;
|
|
238
|
+
box-shadow: none;
|
|
239
|
+
|
|
240
|
+
&:focus {
|
|
241
|
+
border-color: var(--itf-table-input-focus-border-color);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
&.highlight-drop-column {
|
|
247
|
+
position: relative;
|
|
248
|
+
|
|
249
|
+
&:after {
|
|
250
|
+
content: "";
|
|
251
|
+
height: 100%;
|
|
252
|
+
z-index: 100;
|
|
253
|
+
width: 2px;
|
|
254
|
+
background: #47beff;
|
|
255
|
+
margin-left: -1px;
|
|
256
|
+
position: absolute;
|
|
257
|
+
left: 0;
|
|
258
|
+
}
|
|
259
|
+
&.right:after {
|
|
260
|
+
left: auto;
|
|
261
|
+
right: 0;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
&.sticky {
|
|
266
|
+
z-index: 4;
|
|
267
|
+
position: -webkit-sticky;
|
|
268
|
+
position: sticky;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
17
|
<div v-if="currencySelect" class="itf-money-field__currency">
|
|
18
|
-
<span>{{ selectedCurrencyCode }}<itf-icon v-if="!currencyDisabled" name="chevron_down" /></span>
|
|
18
|
+
<span>{{ selectedCurrencyCode }}<itf-icon v-if="!currencyDisabled && currenciesList.length > 1" name="chevron_down" /></span>
|
|
19
19
|
<select v-if="!disabled && !currencyDisabled" :value="currencyId" @input="onCurrencyChanged">
|
|
20
|
-
<option v-for="currency in
|
|
20
|
+
<option v-for="currency in currenciesList" :key="currency.Id" :value="currency.Id" :selected="currencyId === currency.Id">
|
|
21
21
|
{{ currency.Symbol }}, {{ currency.Code }} - {{ currency.Title }}
|
|
22
22
|
</option>
|
|
23
23
|
</select>
|
|
@@ -77,6 +77,7 @@ import itfSelect from '../select/Select';
|
|
|
77
77
|
import itfLabel from '../form/Label';
|
|
78
78
|
import itfIcon from '../icon/Icon';
|
|
79
79
|
import {stringToNumber} from '../../helpers/formatters';
|
|
80
|
+
import ITFSettings from '../../ITFSettings';
|
|
80
81
|
|
|
81
82
|
export default @Component({
|
|
82
83
|
name: 'itfMoneyField',
|
|
@@ -101,6 +102,10 @@ class itfMoneyField extends Vue {
|
|
|
101
102
|
@Prop({ type: Number, default: -1000000000}) minValue;
|
|
102
103
|
@Prop({ type: Number, default: 1000000000}) maxValue;
|
|
103
104
|
|
|
105
|
+
get currenciesList() {
|
|
106
|
+
return this.currencies?.length ? this.currencies : ITFSettings.currencies;
|
|
107
|
+
}
|
|
108
|
+
|
|
104
109
|
get mask() {
|
|
105
110
|
return {
|
|
106
111
|
mask: Number,
|
|
@@ -128,11 +133,11 @@ class itfMoneyField extends Vue {
|
|
|
128
133
|
}
|
|
129
134
|
|
|
130
135
|
onCurrencyChanged(e) {
|
|
131
|
-
const currency = this.
|
|
136
|
+
const currency = this.currenciesList.find((c) => c.Id === parseInt(e.target.value));
|
|
132
137
|
this.$emit('update:currency', currency)
|
|
133
138
|
}
|
|
134
139
|
|
|
135
|
-
get
|
|
140
|
+
get precition() {
|
|
136
141
|
return this.selectedCurrency ? this.selectedCurrency.Precision : 2;
|
|
137
142
|
}
|
|
138
143
|
|
|
@@ -149,10 +154,10 @@ class itfMoneyField extends Vue {
|
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
get selectedCurrency() {
|
|
152
|
-
if (!this.currency || !this.
|
|
153
|
-
return null;
|
|
157
|
+
if (!this.currency || !this.currenciesList) {
|
|
158
|
+
return this.currenciesList.find(({ IsDefault }) => IsDefault) || null;
|
|
154
159
|
}
|
|
155
|
-
return this.
|
|
160
|
+
return this.currenciesList.find(({ Id }) => this.currency.Id === Id);
|
|
156
161
|
}
|
|
157
162
|
|
|
158
163
|
setValue (val) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
|
|
3
3
|
<div class="itf-text-field input-group" :class="{ 'with-addon addon-start': prependIcon, 'with-addon addon-end': clearable }">
|
|
4
|
-
<
|
|
5
|
-
<
|
|
4
|
+
<slot name="addon">
|
|
5
|
+
<div class="addon" v-if="prependIcon">
|
|
6
6
|
<itf-icon :name="prependIcon"/>
|
|
7
|
-
</
|
|
8
|
-
</
|
|
7
|
+
</div>
|
|
8
|
+
</slot>
|
|
9
9
|
|
|
10
10
|
<input
|
|
11
11
|
ref="input"
|