@itfin/components 1.4.27 → 1.4.28
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/panels/Panel.vue +44 -7
- package/src/components/panels/PanelItemEdit.vue +8 -6
- package/src/components/panels/PanelLink.vue +15 -6
- package/src/components/panels/PanelList.vue +102 -33
- package/src/components/panels/helpers.ts +29 -11
- package/src/components/panels/index.ts +43 -0
- 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/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>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div tabindex="-1" :class="{'b-panel': !nocard, 'b-panel__collapsed': collapsed, 'b-panel__active': !collapsed}">
|
|
3
|
+
<slot name="before-header"></slot>
|
|
3
4
|
<div v-if="collapsed && !nocard" class="b-panel__expand" @click.stop.prevent="expandPanel">
|
|
4
5
|
<itf-button v-if="closeable" icon small class="b-panel__expand_button" @click="closePanel">
|
|
5
6
|
<itf-icon name="cross" />
|
|
@@ -12,19 +13,24 @@
|
|
|
12
13
|
</div>
|
|
13
14
|
<div v-if="!nocard" v-show="!collapsed" class="b-panel-header px-3 pt-3 pb-2">
|
|
14
15
|
<slot name="header">
|
|
15
|
-
<div class="d-flex gap-3 align-items-center">
|
|
16
|
-
<itf-button
|
|
17
|
-
<itf-icon name="
|
|
16
|
+
<div class="d-flex gap-3 align-items-center" style="min-width: 0">
|
|
17
|
+
<itf-button icon default class="d-md-none open-menu-button" @click="$emit('open-menu')">
|
|
18
|
+
<itf-icon name="menu" new />
|
|
18
19
|
</itf-button>
|
|
19
20
|
<slot name="title">
|
|
20
|
-
<div class="b-panel__title fw-bold mb-0 h2" v-text="title"></div>
|
|
21
|
+
<div style="min-width: 0" class="b-panel__title fw-bold mb-0 h2 text-truncate" v-text="title"></div>
|
|
21
22
|
</slot>
|
|
22
23
|
</div>
|
|
23
24
|
<div class="d-flex gap-1">
|
|
24
25
|
<slot name="buttons"></slot>
|
|
25
|
-
<
|
|
26
|
-
<itf-icon
|
|
27
|
-
|
|
26
|
+
<template v-if="expandable">
|
|
27
|
+
<itf-button v-if="!isFullSize" icon default class="b-panel__expand_button d-none d-md-block" @click="fullsizePanel">
|
|
28
|
+
<itf-icon new name="expand" />
|
|
29
|
+
</itf-button>
|
|
30
|
+
<itf-button v-else icon default class="b-panel__expand_button d-none d-md-block" @click="collapsePanel">
|
|
31
|
+
<itf-icon new name="collapse" />
|
|
32
|
+
</itf-button>
|
|
33
|
+
</template>
|
|
28
34
|
<itf-button v-if="closeable" icon default class="b-panel__expand_button" @click="closePanel">
|
|
29
35
|
<itf-icon new name="close" />
|
|
30
36
|
</itf-button>
|
|
@@ -37,10 +43,36 @@
|
|
|
37
43
|
</div>
|
|
38
44
|
</template>
|
|
39
45
|
<style lang="scss">
|
|
46
|
+
@keyframes bellRing {
|
|
47
|
+
0% {
|
|
48
|
+
transform: rotate(0deg);
|
|
49
|
+
}
|
|
50
|
+
10% {
|
|
51
|
+
transform: rotate(30deg);
|
|
52
|
+
}
|
|
53
|
+
20% {
|
|
54
|
+
transform: rotate(0deg);
|
|
55
|
+
}
|
|
56
|
+
30% {
|
|
57
|
+
transform: rotate(30deg);
|
|
58
|
+
}
|
|
59
|
+
40% {
|
|
60
|
+
transform: rotate(0deg);
|
|
61
|
+
}
|
|
62
|
+
100% {
|
|
63
|
+
transform: rotate(0deg);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
40
67
|
.b-panel {
|
|
41
68
|
--b-panel-bg: var(--bs-body-bg);
|
|
42
69
|
--b-panel-color: var(--bs-body-color);
|
|
43
70
|
--b-panel-box-shadow: 0px 2px 6px 0px rgba(21,23,25,.05);
|
|
71
|
+
--b-panel-white: #ffffff;
|
|
72
|
+
--b-panel-info: #5981c0;
|
|
73
|
+
--b-panel-success: #10834e;
|
|
74
|
+
--b-panel-warning: #cda277;
|
|
75
|
+
--b-panel-danger: #A90B00;
|
|
44
76
|
|
|
45
77
|
margin-left: 8px;
|
|
46
78
|
|
|
@@ -158,6 +190,7 @@ class Panel extends Vue {
|
|
|
158
190
|
@Prop() panel;
|
|
159
191
|
@Prop(Boolean) collapsed;
|
|
160
192
|
@Prop(Boolean) closeable;
|
|
193
|
+
@Prop(Boolean) isFullSize;
|
|
161
194
|
@Prop(Boolean) expandable;
|
|
162
195
|
@Prop(Boolean) animate;
|
|
163
196
|
@Prop(Boolean) nocard;
|
|
@@ -170,6 +203,10 @@ class Panel extends Vue {
|
|
|
170
203
|
this.$emit('expand');
|
|
171
204
|
}
|
|
172
205
|
|
|
206
|
+
collapsePanel() {
|
|
207
|
+
this.$emit('collapse');
|
|
208
|
+
}
|
|
209
|
+
|
|
173
210
|
fullsizePanel() {
|
|
174
211
|
this.$emit('fullsize');
|
|
175
212
|
}
|
|
@@ -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>
|
|
@@ -17,14 +17,20 @@
|
|
|
17
17
|
:icon="panel.icon"
|
|
18
18
|
:payload="panel.payload"
|
|
19
19
|
:expandable="panelsStack.length > 1"
|
|
20
|
+
:isFullSize="isFullSize"
|
|
20
21
|
:collapsed="panel.isCollapsed"
|
|
21
22
|
:closeable="panel.isCloseable"
|
|
22
23
|
:animate="panel.isAnimate"
|
|
23
24
|
@open="openPanel($event[0], $event[1], n + 1)"
|
|
24
25
|
@expand="expandPanel(panel)"
|
|
25
26
|
@fullsize="fullsizePanel(panel)"
|
|
27
|
+
@collapse="collapsePanel(panel)"
|
|
26
28
|
@close="closePanel(panel)"
|
|
29
|
+
@open-menu="$emit('open-menu', panel.type, panel.payload)"
|
|
27
30
|
>
|
|
31
|
+
<template #before-header>
|
|
32
|
+
<slot name="before-header" :panel="panel" :index="n" :payload="panel.payload"></slot>
|
|
33
|
+
</template>
|
|
28
34
|
<slot
|
|
29
35
|
:name="panel.type"
|
|
30
36
|
:panel="panel"
|
|
@@ -34,9 +40,9 @@
|
|
|
34
40
|
:close="() => closePanel(panel)"
|
|
35
41
|
:expand="() => expandPanel(panel)"
|
|
36
42
|
:fullsize="() => fullsizePanel(panel)">
|
|
37
|
-
<component
|
|
43
|
+
<component v-if="panel.components.default" :is="panel.components.default" :panel="panel" :payload="panel.payload" />
|
|
38
44
|
</slot>
|
|
39
|
-
<template v-if="$scopedSlots[`${panel.type}.title`] ||
|
|
45
|
+
<template v-if="$scopedSlots[`${panel.type}.title`] || panel.components.title" #title>
|
|
40
46
|
<slot
|
|
41
47
|
:name="`${panel.type}.title`"
|
|
42
48
|
:panel="panel"
|
|
@@ -46,10 +52,10 @@
|
|
|
46
52
|
:close="() => closePanel(panel)"
|
|
47
53
|
:expand="() => expandPanel(panel)"
|
|
48
54
|
:fullsize="() => fullsizePanel(panel)">
|
|
49
|
-
<component v-if="
|
|
55
|
+
<component v-if="panel.components.title" :is="panel.components.title" :panel="panel" :payload="panel.payload" />
|
|
50
56
|
</slot>
|
|
51
57
|
</template>
|
|
52
|
-
<template v-if="$scopedSlots[`${panel.type}.buttons`] ||
|
|
58
|
+
<template v-if="$scopedSlots[`${panel.type}.buttons`] || panel.components.buttons" #buttons>
|
|
53
59
|
<slot
|
|
54
60
|
:name="`${panel.type}.buttons`"
|
|
55
61
|
:panel="panel"
|
|
@@ -59,10 +65,10 @@
|
|
|
59
65
|
:close="() => closePanel(panel)"
|
|
60
66
|
:expand="() => expandPanel(panel)"
|
|
61
67
|
:fullsize="() => fullsizePanel(panel)">
|
|
62
|
-
<component v-if="
|
|
68
|
+
<component v-if="panel.components.buttons" :is="panel.components.buttons" :panel="panel" :payload="panel.payload" />
|
|
63
69
|
</slot>
|
|
64
70
|
</template>
|
|
65
|
-
<template v-if="$scopedSlots[`${panel.type}.header`] ||
|
|
71
|
+
<template v-if="$scopedSlots[`${panel.type}.header`] || panel.components.header" #header>
|
|
66
72
|
<slot
|
|
67
73
|
:name="`${panel.type}.header`"
|
|
68
74
|
:panel="panel"
|
|
@@ -72,7 +78,7 @@
|
|
|
72
78
|
:close="() => closePanel(panel)"
|
|
73
79
|
:expand="() => expandPanel(panel)"
|
|
74
80
|
:fullsize="() => fullsizePanel(panel)">
|
|
75
|
-
<component v-if="
|
|
81
|
+
<component v-if="panel.components.header" :is="panel.components.header" :panel="panel" :payload="panel.payload" />
|
|
76
82
|
</slot>
|
|
77
83
|
</template>
|
|
78
84
|
</panel>
|
|
@@ -148,7 +154,6 @@ $double-an-time: $an-time * 2;
|
|
|
148
154
|
//transition: opacity $an-time linear;
|
|
149
155
|
}
|
|
150
156
|
}
|
|
151
|
-
|
|
152
157
|
//.slide-enter-active > div {
|
|
153
158
|
// opacity: 0;
|
|
154
159
|
//}
|
|
@@ -159,8 +164,10 @@ $double-an-time: $an-time * 2;
|
|
|
159
164
|
</style>
|
|
160
165
|
<script lang="ts">
|
|
161
166
|
import { Vue, Component, Prop } from 'vue-property-decorator';
|
|
162
|
-
import
|
|
163
|
-
import
|
|
167
|
+
import itfIcon from '../icon/Icon.vue';
|
|
168
|
+
import Panel from './Panel.vue';
|
|
169
|
+
import {hashToStack, stackToHash} from "@itfin/components/src/components/panels/helpers";
|
|
170
|
+
import {emitGlobalEvent, setRootPanelList} from "@itfin/components/src/components/panels";
|
|
164
171
|
|
|
165
172
|
interface VisualOptions {
|
|
166
173
|
title: string;
|
|
@@ -195,6 +202,7 @@ export interface IPanel {
|
|
|
195
202
|
|
|
196
203
|
@Component({
|
|
197
204
|
components: {
|
|
205
|
+
itfIcon,
|
|
198
206
|
Panel
|
|
199
207
|
},
|
|
200
208
|
directives: {
|
|
@@ -208,12 +216,15 @@ export interface IPanel {
|
|
|
208
216
|
export default class PanelList extends Vue {
|
|
209
217
|
@Prop() firstPanel: IPanel;
|
|
210
218
|
@Prop() panels: Record<string, Component>;
|
|
219
|
+
@Prop({ default: () => {} }) searchPanel: (type: string) => boolean;
|
|
220
|
+
@Prop({ type: String, default: 'path' }) routeType: string;
|
|
211
221
|
|
|
212
222
|
panelsStack:IPanel[] = [];
|
|
213
223
|
|
|
214
224
|
nextId:number = 0;
|
|
215
225
|
|
|
216
226
|
created() {
|
|
227
|
+
setRootPanelList(this);
|
|
217
228
|
if (this.firstPanel) {
|
|
218
229
|
this.internalOpenPanel(this.firstPanel.type, this.firstPanel.payload);
|
|
219
230
|
}
|
|
@@ -267,18 +278,30 @@ export default class PanelList extends Vue {
|
|
|
267
278
|
this.panelsStack = newStack;
|
|
268
279
|
}
|
|
269
280
|
|
|
270
|
-
internalOpenPanel(type: string, payload: any = {}, openIndex?: number, noEvents = false) {
|
|
271
|
-
|
|
272
|
-
|
|
281
|
+
async internalOpenPanel(type: string, payload: any = {}, openIndex?: number, noEvents = false) {
|
|
282
|
+
let panel = this.panels[type];
|
|
283
|
+
if (!panel) {
|
|
284
|
+
panel = await this.searchPanel(type, this.panels);
|
|
285
|
+
if (!panel) {
|
|
286
|
+
console.error(`Panel type "${type}" not found`);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
panel.type = type;
|
|
273
290
|
}
|
|
274
|
-
if (typeof
|
|
291
|
+
if (typeof panel.caption !== 'function') {
|
|
275
292
|
throw new Error('Panel component must have a "caption" function');
|
|
276
293
|
}
|
|
277
294
|
const newPanel:any = {
|
|
278
295
|
id: this.nextId++,
|
|
279
|
-
nocard:
|
|
280
|
-
title:
|
|
281
|
-
icon:
|
|
296
|
+
nocard: panel.nocard,
|
|
297
|
+
title: panel.caption(this.$t.bind(this), payload),
|
|
298
|
+
icon: panel.icon ? panel.icon(this.$t.bind(this), payload) : null,
|
|
299
|
+
components: {
|
|
300
|
+
default: panel.default ?? undefined,
|
|
301
|
+
buttons: panel.buttons ?? undefined,
|
|
302
|
+
header: panel.header ?? undefined,
|
|
303
|
+
title: panel.title ?? undefined,
|
|
304
|
+
},
|
|
282
305
|
type,
|
|
283
306
|
payload,
|
|
284
307
|
isCollapsed: false,
|
|
@@ -289,7 +312,7 @@ export default class PanelList extends Vue {
|
|
|
289
312
|
newPanel.isCloseable = false;
|
|
290
313
|
}
|
|
291
314
|
let newStack = [...this.panelsStack];
|
|
292
|
-
if (
|
|
315
|
+
if (panel.permanentExpanded && newStack.length) {
|
|
293
316
|
for (const panel of newStack) {
|
|
294
317
|
panel.isCollapsed = true;
|
|
295
318
|
}
|
|
@@ -299,25 +322,32 @@ export default class PanelList extends Vue {
|
|
|
299
322
|
isAnimation = newStack.length === openIndex;
|
|
300
323
|
newStack = newStack.slice(0, openIndex);
|
|
301
324
|
}
|
|
325
|
+
if (newStack.length > 0 && !newStack.find(p => !p.isCollapsed)) {
|
|
326
|
+
// якщо немає відкритих панелей, то перша панель має бути розгорнута
|
|
327
|
+
newStack[0].isCollapsed = false;
|
|
328
|
+
}
|
|
302
329
|
this.panelsStack = newStack;
|
|
303
330
|
return new Promise(res => {
|
|
304
331
|
this.$nextTick(() => { // щоб панелі змінювались при редагуванні
|
|
305
332
|
const n = newStack.length;
|
|
306
333
|
newPanel.isAnimate = isAnimation;
|
|
307
|
-
newPanel.permanentExpanded = !!
|
|
334
|
+
newPanel.permanentExpanded = !!panel.permanentExpanded;
|
|
308
335
|
newPanel.emit = (event, ...args) => this.emitEvent(event, ...args);
|
|
309
|
-
newPanel.open = (type, payload) => this.openPanel(type, payload, n + 1);
|
|
336
|
+
newPanel.open = (type, payload, index?:number) => this.openPanel(type, payload, index ?? n + 1);
|
|
310
337
|
newPanel.close = () => this.closePanel(newPanel);
|
|
311
338
|
newPanel.expand = () => this.expandPanel(newPanel);
|
|
312
339
|
newPanel.getTitle = () => newPanel.title;
|
|
313
340
|
newPanel.getIcon = () => newPanel.icon;
|
|
314
|
-
newPanel.setTitle = (title: string) => { newPanel.title = title; };
|
|
341
|
+
newPanel.setTitle = (title: string) => { newPanel.title = title; this.updateTitle() };
|
|
315
342
|
newPanel.setIcon = (icon: string) => { newPanel.icon = icon; };
|
|
316
|
-
newPanel.on = (eventName, func: (event: string, ...args: any[]) => any) => {
|
|
317
|
-
|
|
318
|
-
|
|
343
|
+
newPanel.on = (eventName: string|string[], func: (event: string, ...args: any[]) => any) => {
|
|
344
|
+
const eventNames = Array.isArray(eventName) ? eventName : [eventName];
|
|
345
|
+
for (const evName of eventNames) {
|
|
346
|
+
if (!newPanel.__events[evName]) {
|
|
347
|
+
newPanel.__events[evName] = [];
|
|
348
|
+
}
|
|
349
|
+
newPanel.__events[evName].push(func);
|
|
319
350
|
}
|
|
320
|
-
newPanel.__events[eventName].push(func);
|
|
321
351
|
};
|
|
322
352
|
newPanel.off = (eventName, func: (event: string, ...args: any[]) => any) => {
|
|
323
353
|
if (newPanel.__events[eventName]) {
|
|
@@ -337,9 +367,7 @@ export default class PanelList extends Vue {
|
|
|
337
367
|
newPanel.getPayload = () => newPanel.payload;
|
|
338
368
|
newPanel.setPayload = (value: any) => {
|
|
339
369
|
newPanel.payload = value;
|
|
340
|
-
|
|
341
|
-
newPanel.icon = this.panels[type].icon ? this.panels[type].icon(this.$t.bind(this), payload) : null,
|
|
342
|
-
this.setPanelHash()
|
|
370
|
+
this.setPanelHash();
|
|
343
371
|
}
|
|
344
372
|
newStack.push(newPanel);
|
|
345
373
|
this.panelsStack = newStack;
|
|
@@ -353,12 +381,19 @@ export default class PanelList extends Vue {
|
|
|
353
381
|
});
|
|
354
382
|
}
|
|
355
383
|
|
|
384
|
+
updateTitle() {
|
|
385
|
+
const titles = this.panelsStack.map(p => p.getTitle()).filter(Boolean).reverse();
|
|
386
|
+
this.$root.$options.head.titleChunk = titles.join(' / ');
|
|
387
|
+
this.$meta().refresh();
|
|
388
|
+
}
|
|
389
|
+
|
|
356
390
|
async openPanel(type: string, payload: any, openIndex?: number) {
|
|
357
391
|
await this.internalOpenPanel(type, payload, openIndex);
|
|
358
|
-
this.setPanelHash()
|
|
392
|
+
this.setPanelHash();
|
|
359
393
|
}
|
|
360
394
|
|
|
361
395
|
emitEvent(event: string, ...args: any[]) {
|
|
396
|
+
emitGlobalEvent(event, ...args);
|
|
362
397
|
for (const panel of this.panelsStack) {
|
|
363
398
|
if (panel.__events[event]) {
|
|
364
399
|
for (const func of panel.__events[event]) {
|
|
@@ -388,12 +423,40 @@ export default class PanelList extends Vue {
|
|
|
388
423
|
fullsizePanel(panel: IPanel) {
|
|
389
424
|
const newStack = [...this.panelsStack];
|
|
390
425
|
for (const p of newStack) {
|
|
426
|
+
p.isLastOpened = !p.isCollapsed && p !== panel;
|
|
391
427
|
p.isCollapsed = p !== panel;
|
|
392
428
|
}
|
|
393
429
|
this.panelsStack = newStack;
|
|
394
430
|
this.setPanelHash();
|
|
395
431
|
}
|
|
396
432
|
|
|
433
|
+
get isFullSize() {
|
|
434
|
+
return this.panelsStack.filter(p => !p.isCollapsed).length === 1;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
expandPanel(panel: IPanel) {
|
|
438
|
+
const newStack = [...this.panelsStack];
|
|
439
|
+
const index = newStack.findIndex(p => p.id === panel.id);
|
|
440
|
+
newStack[index].isCollapsed = false;
|
|
441
|
+
this.panelsStack = newStack;
|
|
442
|
+
this.ensureOnlyTwoOpenPanels(panel.id);
|
|
443
|
+
this.setPanelHash();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
collapsePanel(panel: IPanel) {
|
|
447
|
+
const newStack = [...this.panelsStack];
|
|
448
|
+
const currenctIndex = newStack.findIndex(p => p.id === panel.id);
|
|
449
|
+
const lastOpenedIndex = newStack.findIndex(p => p.isLastOpened);
|
|
450
|
+
if (lastOpenedIndex !== -1) { // якщо зебрежена остання відкрита панель
|
|
451
|
+
newStack[lastOpenedIndex].isCollapsed = false
|
|
452
|
+
} else if (newStack[currenctIndex-1]) { // якщо після оновлення сторінки відсутнє значення "остання відкрита", то відкриваємо ту, що зліва
|
|
453
|
+
newStack[currenctIndex-1].isCollapsed = false;
|
|
454
|
+
}
|
|
455
|
+
this.panelsStack = newStack;
|
|
456
|
+
this.ensureOnlyTwoOpenPanels(panel.id);
|
|
457
|
+
this.setPanelHash();
|
|
458
|
+
}
|
|
459
|
+
|
|
397
460
|
getPanels(type) {
|
|
398
461
|
return this.panelsStack.filter(panel => panel.type === type);
|
|
399
462
|
}
|
|
@@ -403,14 +466,19 @@ export default class PanelList extends Vue {
|
|
|
403
466
|
}
|
|
404
467
|
|
|
405
468
|
setPanelHash() {
|
|
406
|
-
const hash = stackToHash(this.panelsStack).replace(/^#/, '');
|
|
407
|
-
this
|
|
469
|
+
const hash = stackToHash(this.panelsStack, this.routeType === 'path').replace(/^#/, '');
|
|
470
|
+
if (this.routeType === 'path') {
|
|
471
|
+
this.$router.push({ path: `/${hash}` });
|
|
472
|
+
} else {
|
|
473
|
+
this.$router.push({ hash });
|
|
474
|
+
}
|
|
475
|
+
this.updateTitle();
|
|
408
476
|
}
|
|
409
477
|
|
|
410
478
|
async parsePanelHash() {
|
|
411
|
-
const
|
|
479
|
+
const hash = this.routeType === 'path' ? location.pathname : location.hash;
|
|
412
480
|
if (hash) {
|
|
413
|
-
const panels = hashToStack(hash);
|
|
481
|
+
const panels = hashToStack(hash, this.routeType === 'path');
|
|
414
482
|
const newStack = [];
|
|
415
483
|
this.panelsStack = [];
|
|
416
484
|
for (const panelIndex in panels) {
|
|
@@ -431,6 +499,7 @@ export default class PanelList extends Vue {
|
|
|
431
499
|
}
|
|
432
500
|
this.panelsStack = newStack;
|
|
433
501
|
this.emitEvent('panels.changed', this.panelsStack);
|
|
502
|
+
this.updateTitle();
|
|
434
503
|
}
|
|
435
504
|
}
|
|
436
505
|
|
|
@@ -1,33 +1,51 @@
|
|
|
1
|
+
import JSON5 from 'json5'
|
|
2
|
+
import {isPathType} from "./index";
|
|
3
|
+
|
|
1
4
|
export interface IPanel {
|
|
2
5
|
type: string;
|
|
3
6
|
payload?: any;
|
|
4
7
|
isCollapsed?: boolean;
|
|
5
8
|
}
|
|
6
9
|
|
|
10
|
+
const COLLAPSE_SYMBOL = '~'
|
|
11
|
+
const PARAMS_SYMBOL = ';'
|
|
12
|
+
|
|
7
13
|
export function stackToHash(stack: IPanel[]) {
|
|
8
14
|
const hash = stack.map(panel => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
let json = JSON5.stringify(panel.payload || {});
|
|
16
|
+
json = json.substring(1, json.length - 1); // Remove the outer {}
|
|
17
|
+
return `${panel.type}${panel.isCollapsed ? COLLAPSE_SYMBOL : ''}${json ? PARAMS_SYMBOL : ''}${json}`;
|
|
18
|
+
}).join(isPathType() ? '/' : '&');
|
|
19
|
+
return isPathType() ? `/${hash}` : `#${hash}`;
|
|
12
20
|
}
|
|
13
21
|
|
|
14
22
|
|
|
15
23
|
export function hashToStack(hash: string|undefined): IPanel[] {
|
|
16
24
|
let stack:IPanel[] = [];
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
const str = hash.replace(isPathType() ? /^\// : /^#/, '');
|
|
26
|
+
if (str) {
|
|
27
|
+
stack = str.split(isPathType() ? '/' : '&').map(item => {
|
|
28
|
+
if (!item.includes(PARAMS_SYMBOL)) {
|
|
29
|
+
return { type: item.replace(COLLAPSE_SYMBOL, ''), isCollapsed: item.includes(COLLAPSE_SYMBOL), payload: {} };
|
|
30
|
+
}
|
|
31
|
+
const [type, payload] = item.split(PARAMS_SYMBOL);
|
|
32
|
+
const isCollapsed = type.includes(COLLAPSE_SYMBOL);
|
|
23
33
|
let payloadObj:any = {};
|
|
24
34
|
try {
|
|
25
|
-
|
|
35
|
+
let json = decodeURIComponent(payload);
|
|
36
|
+
if (!json.startsWith('{')) {
|
|
37
|
+
json = `{${json}`; // Ensure it starts with a '{' to be valid JSON
|
|
38
|
+
}
|
|
39
|
+
if (!json.endsWith('}')) {
|
|
40
|
+
json += '}'; // Ensure it ends with a '}' to be valid JSON
|
|
41
|
+
}
|
|
42
|
+
payloadObj = JSON5.parse(json);
|
|
26
43
|
} catch (e) {
|
|
27
44
|
// ignore
|
|
45
|
+
console.warn(`Error parsing payload for type ${type}:`, payload, e);
|
|
28
46
|
}
|
|
29
47
|
return {
|
|
30
|
-
type: type.replace(
|
|
48
|
+
type: type.replace(COLLAPSE_SYMBOL, ''),
|
|
31
49
|
isCollapsed,
|
|
32
50
|
payload: payloadObj
|
|
33
51
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const PanelsSettings = {
|
|
2
|
+
pathType: 'path', // 'hash' | 'path'
|
|
3
|
+
rootPanelList: null, // This will be set to the root panel list when the app is initialized
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export function getPanelsSettings() {
|
|
7
|
+
return PanelsSettings;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getRootPanelList() {
|
|
11
|
+
return PanelsSettings.rootPanelList;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isPathType() {
|
|
15
|
+
return PanelsSettings.pathType === 'path';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function setPanelsPathType(settings: any) {
|
|
19
|
+
PanelsSettings.pathType = settings.pathType ?? 'path';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function setRootPanelList(rootPanelList: any) {
|
|
23
|
+
PanelsSettings.rootPanelList = rootPanelList;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function emitGlobalEvent(eventName: string, data: any) {
|
|
27
|
+
const event = new CustomEvent(`panel:${eventName}`, { detail: data });
|
|
28
|
+
window.dispatchEvent(event);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function onGlobalEvent(eventName: string|string[], callback: (event: CustomEvent) => void) {
|
|
32
|
+
const eventNames = Array.isArray(eventName) ? eventName : [eventName];
|
|
33
|
+
for (const name of eventNames) {
|
|
34
|
+
window.addEventListener(`panel:${name}`, callback);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function offGlobalEvent(eventName: string|string[], callback: (event: CustomEvent) => void) {
|
|
39
|
+
const eventNames = Array.isArray(eventName) ? eventName : [eventName];
|
|
40
|
+
for (const name of eventNames) {
|
|
41
|
+
window.removeEventListener(`panel:${name}`, callback);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -7,9 +7,11 @@
|
|
|
7
7
|
'permanent-checkboxes': selectedIds.length
|
|
8
8
|
}" :style="{ '--indicator-area-width': `${indicatorType === 'none' ? 1 : indicatorWidth}px`, '--shadow-area-width': `${shadowWidth}px` }">
|
|
9
9
|
<itf-notice-popout :visible="showGroupOperations" class="rounded-3 bg-black text-white">
|
|
10
|
-
<div class="d-flex gap-2 ps-
|
|
11
|
-
<
|
|
12
|
-
|
|
10
|
+
<div class="d-flex gap-2 ps-2 align-items-center small itf-table2_mass-operations">
|
|
11
|
+
<slot name="group-operations-count">
|
|
12
|
+
<div>{{$tc('components.table.selectedItems', selectedIds.length, { n: selectedIds.length })}}</div>
|
|
13
|
+
<div class="opacity-50">•</div>
|
|
14
|
+
</slot>
|
|
13
15
|
<a href="" class="me-3 opacity-50 text-white text-decoration-none" @click.stop.prevent="selectedIds = []">{{$t('components.table.cancelSelected')}}</a>
|
|
14
16
|
<div>
|
|
15
17
|
<slot name="group-operations"></slot>
|
|
@@ -17,64 +19,61 @@
|
|
|
17
19
|
</div>
|
|
18
20
|
</itf-notice-popout>
|
|
19
21
|
<div class="scrollable scrollable-x">
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
</div>
|
|
76
|
-
</template>
|
|
77
|
-
</itf-checkbox-group>
|
|
22
|
+
<itf-checkbox-group v-model="selectedIds">
|
|
23
|
+
<template v-for="(group, index) in groups">
|
|
24
|
+
<div class="table-view-body">
|
|
25
|
+
<itf-table-group
|
|
26
|
+
:key="index"
|
|
27
|
+
@update="$emit('update', { ...$event, group, groupIndex: index })"
|
|
28
|
+
@row-click="$emit('row-click', $event)"
|
|
29
|
+
:id-property="idProperty"
|
|
30
|
+
:columns="columns"
|
|
31
|
+
@update:columns="onColumnsUpdate"
|
|
32
|
+
:rows="group.rows"
|
|
33
|
+
:title="group.name"
|
|
34
|
+
:selected-ids.sync="selectedIds"
|
|
35
|
+
:add-new-rows="addNewRows"
|
|
36
|
+
:shadow-width="shadowWidth"
|
|
37
|
+
:column-sorting="columnSorting"
|
|
38
|
+
:column-resizing="columnResizing"
|
|
39
|
+
:show-grouping="showGrouping"
|
|
40
|
+
:show-summary="showSummary"
|
|
41
|
+
:show-add-column="showAddColumn"
|
|
42
|
+
:show-actions="showActions"
|
|
43
|
+
:show-header="!noHeader"
|
|
44
|
+
:schema="schema"
|
|
45
|
+
:editable="editable"
|
|
46
|
+
:no-column-menu="noColumnMenu"
|
|
47
|
+
:no-select-all="noSelectAll"
|
|
48
|
+
:currencies="currencies"
|
|
49
|
+
:currency="currency"
|
|
50
|
+
:subrows-property="subrowsProperty"
|
|
51
|
+
:divider-property="dividerProperty"
|
|
52
|
+
:indicator-type="indicatorType"
|
|
53
|
+
:expanded-all="expandedAll"
|
|
54
|
+
:indicatorWidth="indicatorWidth"
|
|
55
|
+
:striped="striped"
|
|
56
|
+
:expanded-ids="expandedIds"
|
|
57
|
+
:css-property="cssProperty"
|
|
58
|
+
:sticky-header="stickyHeader"
|
|
59
|
+
:editable-property="editableProperty"
|
|
60
|
+
:sorting.sync="_sorting"
|
|
61
|
+
:active="active"
|
|
62
|
+
@update:expanded-ids="$emit('update:expanded-ids', $event)"
|
|
63
|
+
@new="$emit('new', $event)"
|
|
64
|
+
@filter="$emit('filter', $event)"
|
|
65
|
+
@add-column="$emit('add-column', $event)"
|
|
66
|
+
>
|
|
67
|
+
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
68
|
+
<slot :name="name" v-bind="slotData || {}" />
|
|
69
|
+
</template>
|
|
70
|
+
<template v-for="(_, name) in $scopedSlots" #[name]="slotData">
|
|
71
|
+
<slot :name="name" v-bind="slotData || {}" />
|
|
72
|
+
</template>
|
|
73
|
+
</itf-table-group>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
</itf-checkbox-group>
|
|
78
77
|
</div>
|
|
79
78
|
</div>
|
|
80
79
|
|
|
@@ -105,13 +104,11 @@ export default @Component({
|
|
|
105
104
|
})
|
|
106
105
|
class itfTable2 extends Vue {
|
|
107
106
|
// @Prop({ required: true, type: Array }) columns;
|
|
108
|
-
@Prop(Boolean) sortAsString;
|
|
109
107
|
@Prop({ required: true, type: Array }) rows;
|
|
110
108
|
@Prop({ type: String, default: null }) groupBy;
|
|
111
109
|
@Prop({ type: String, default: null }) idProperty;
|
|
112
110
|
@Prop({ type: String, default: null }) cssProperty;
|
|
113
111
|
@Prop({ type: String, default: null }) subrowsProperty;
|
|
114
|
-
@Prop({ type: String, default: null }) asyncSubrowsProperty;
|
|
115
112
|
@Prop({ type: String, default: null }) dividerProperty;
|
|
116
113
|
@Prop({ type: String, default: null }) editableProperty;
|
|
117
114
|
@Prop({ default: null }) active;
|
|
@@ -247,8 +244,7 @@ class itfTable2 extends Vue {
|
|
|
247
244
|
@Watch('selectedIds')
|
|
248
245
|
onSelectedIdsUpdate(selectedIds) {
|
|
249
246
|
this.state.selectedIds = selectedIds;
|
|
250
|
-
|
|
251
|
-
// this.saveTableState();
|
|
247
|
+
this.saveTableState();
|
|
252
248
|
}
|
|
253
249
|
|
|
254
250
|
onColumnsUpdate(columns) {
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
:columns="columns"
|
|
8
8
|
:id-property="idProperty"
|
|
9
9
|
:subrows-property="subrowsProperty"
|
|
10
|
-
:async-subrows-property="asyncSubrowsProperty"
|
|
11
10
|
:divider-property="dividerProperty"
|
|
12
11
|
:show-add-column="showAddColumn"
|
|
13
12
|
:show-actions="showActions"
|
|
@@ -145,7 +144,6 @@ class itfTableBody extends Vue {
|
|
|
145
144
|
@Prop() rows;
|
|
146
145
|
@Prop() idProperty;
|
|
147
146
|
@Prop() subrowsProperty;
|
|
148
|
-
@Prop() asyncSubrowsProperty;
|
|
149
147
|
@Prop() dividerProperty;
|
|
150
148
|
@Prop() active;
|
|
151
149
|
@Prop(Boolean) showAddColumn;
|
|
@@ -166,10 +164,6 @@ class itfTableBody extends Vue {
|
|
|
166
164
|
this.$emit('update:expanded-ids', this.expandedIds.includes(item[this.idProperty])
|
|
167
165
|
? this.expandedIds.filter((id) => id !== item[this.idProperty])
|
|
168
166
|
: [...this.expandedIds, item[this.idProperty]]);
|
|
169
|
-
|
|
170
|
-
if (this.asyncSubrowsProperty && item[this.asyncSubrowsProperty] && item[this.asyncSubrowsProperty]) {
|
|
171
|
-
this.$emit('loadChildren', item);
|
|
172
|
-
}
|
|
173
167
|
}
|
|
174
168
|
}
|
|
175
169
|
</script>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div class="shadow-area"></div>
|
|
18
18
|
<div class="header-wrapper" :class="{'header-additional-column': showAddColumn}" @click.prevent="toggleGroup">
|
|
19
19
|
<a class="header-content position-sticky d-flex align-items-center">
|
|
20
|
-
<itf-button icon small secondary class="collapse-arrow">
|
|
20
|
+
<itf-button squircle icon small secondary class="collapse-arrow">
|
|
21
21
|
<itf-icon :name="isShowTable ? 'chevron_down' : 'chevron_right'"/>
|
|
22
22
|
</itf-button>
|
|
23
23
|
<span class="d-flex align-items-center line-overflow group-header-value text-primary"
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
:show-add-column="showAddColumn"
|
|
40
40
|
:show-actions="showActions"
|
|
41
41
|
:id-property="idProperty"
|
|
42
|
-
:sort-as-string="sortAsString"
|
|
43
42
|
:rows="rows"
|
|
44
43
|
:schema="schema"
|
|
45
44
|
:editable="editable"
|
|
@@ -62,13 +61,11 @@
|
|
|
62
61
|
@row-click="$emit('row-click', $event)"
|
|
63
62
|
:id-property="idProperty"
|
|
64
63
|
:subrows-property="subrowsProperty"
|
|
65
|
-
:async-subrows-property="asyncSubrowsProperty"
|
|
66
64
|
:divider-property="dividerProperty"
|
|
67
65
|
:rows="rows"
|
|
68
66
|
:editable="editable"
|
|
69
67
|
:currency="currency"
|
|
70
68
|
:currencies="currencies"
|
|
71
|
-
:sort-as-string="sortAsString"
|
|
72
69
|
:columns="visibleColumns"
|
|
73
70
|
:no-select-all="noSelectAll"
|
|
74
71
|
:selected-ids="selectedIds"
|
|
@@ -81,7 +78,6 @@
|
|
|
81
78
|
:css-property="cssProperty"
|
|
82
79
|
:editable-property="editableProperty"
|
|
83
80
|
:active="active"
|
|
84
|
-
@loadChildren="$emit('loadChildren', $event)"
|
|
85
81
|
@update:expanded-ids="$emit('update:expanded-ids', $event)"
|
|
86
82
|
>
|
|
87
83
|
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
@@ -95,11 +91,11 @@
|
|
|
95
91
|
|
|
96
92
|
<!-- Лінія додати нову -->
|
|
97
93
|
<div v-if="isShowTable && addNewRows"
|
|
98
|
-
class="table-row-template
|
|
94
|
+
class="table-row-template d-flex align-items-stretch">
|
|
99
95
|
<div class="shadow-area"></div>
|
|
100
96
|
<a href="" @click.prevent="$emit('new', title)" data-test="table-add-new-item"
|
|
101
97
|
class="d-flex align-items-center flex-grow-1 table-add-new-item text-decoration-none">
|
|
102
|
-
<span class="d-sticky d-flex align-items-center py-1
|
|
98
|
+
<span class="d-sticky d-flex align-items-center py-1">
|
|
103
99
|
<itf-icon name="plus"/>
|
|
104
100
|
<span>{{ newLabel }}</span>
|
|
105
101
|
</span>
|
|
@@ -268,11 +264,7 @@
|
|
|
268
264
|
min-height: var(--table-small-row-size);
|
|
269
265
|
}
|
|
270
266
|
|
|
271
|
-
.table-row-template.table-row-template__new-row {
|
|
272
|
-
min-height: 2rem;
|
|
273
|
-
}
|
|
274
267
|
.table-add-new-item {
|
|
275
|
-
background-color: var(--itf-table-header-bg);
|
|
276
268
|
border-right:var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
|
|
277
269
|
border-left:var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
|
|
278
270
|
border-bottom: var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
|
|
@@ -281,7 +273,7 @@
|
|
|
281
273
|
border-bottom-right-radius: var(--itf-table-table-border-radius);
|
|
282
274
|
|
|
283
275
|
& > span {
|
|
284
|
-
left:
|
|
276
|
+
left: var(--shadow-area-width);
|
|
285
277
|
position: sticky;
|
|
286
278
|
padding-left: var(--shadow-area-width);
|
|
287
279
|
//border-left: var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
|
|
@@ -367,7 +359,6 @@ class itfTableGroup extends Vue {
|
|
|
367
359
|
@Prop() title;
|
|
368
360
|
@Prop() idProperty;
|
|
369
361
|
@Prop() subrowsProperty;
|
|
370
|
-
@Prop() asyncSubrowsProperty;
|
|
371
362
|
@Prop() dividerProperty;
|
|
372
363
|
@Prop() currency;
|
|
373
364
|
@Prop() currencies;
|
|
@@ -387,7 +378,6 @@ class itfTableGroup extends Vue {
|
|
|
387
378
|
@Prop(Boolean) expandedAll;
|
|
388
379
|
@Prop(Boolean) striped;
|
|
389
380
|
@Prop(Boolean) stickyHeader;
|
|
390
|
-
@Prop(Boolean) sortAsString;
|
|
391
381
|
@Prop() indicatorWidth;
|
|
392
382
|
@Prop() shadowWidth;
|
|
393
383
|
@Prop() cssProperty;
|
|
@@ -4,8 +4,8 @@
|
|
|
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
|
|
8
|
-
<itf-checkbox v-if="indicatorType
|
|
7
|
+
<div class="table-view-header-value reserved sticky">
|
|
8
|
+
<itf-checkbox v-if="indicatorType === 'checkbox' && visibleHeader && !noSelectAll" ungrouped value="all" v-model="selectAll" ref="selectAll" />
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<template v-for="(column, n) in visibleAttributes">
|
|
@@ -29,16 +29,14 @@
|
|
|
29
29
|
<div v-if="visibleHeader" group="tablecolumns"
|
|
30
30
|
class="table-header"
|
|
31
31
|
@drop="reorderColumns"
|
|
32
|
-
v-draggable="{
|
|
32
|
+
v-draggable="{ handle: true, payload: { index: n, item: column }, mirror: {yAxis:false} }">
|
|
33
33
|
<itf-dropdown text append-to-body shadow ref="dropdown" class="w-100" :disabled="noColumnMenu">
|
|
34
34
|
<template #button>
|
|
35
35
|
<div class="itf-table2__header-title d-flex w-100 align-items-center" :title="getTitle(column.title)">
|
|
36
36
|
<itf-icon class="itf-table2__header-icon" new v-if="column.icon" :name="column.icon"></itf-icon>
|
|
37
37
|
<div class="flex-grow-1 w-100 itf-table2__title-container d-flex align-items-center" :class="{'justify-content-end': column.align === 'end'}">
|
|
38
|
-
<div class="itf-table2__title text-truncate">
|
|
39
|
-
|
|
40
|
-
<div v-if="column.prefix" class="itf-table2__subtitle text-truncate" :class="{'text-end': column.align === 'end'}" v-text="column.prefix" />
|
|
41
|
-
</div>
|
|
38
|
+
<div class="itf-table2__title text-truncate">{{getTitle(column.title)}}</div>
|
|
39
|
+
<div v-if="column.prefix" class="itf-table2__subtitle text-truncate" v-text="column.prefix" />
|
|
42
40
|
</div>
|
|
43
41
|
</div>
|
|
44
42
|
<itf-icon v-if="sortColumnParams[column.property]" :name="sortColumnParams[column.property] === 'asc' ? 'sort-asc' : 'sort-desc'" new :size="20" class="ms-1" />
|
|
@@ -196,7 +194,6 @@ class itfTableHeader extends Vue {
|
|
|
196
194
|
@Prop(Boolean) noColumnMenu;
|
|
197
195
|
@Prop(Boolean) noSelectAll;
|
|
198
196
|
@Prop(Boolean) editable;
|
|
199
|
-
@Prop(Boolean) sortAsString;
|
|
200
197
|
@Prop() idProperty;
|
|
201
198
|
@Prop() indicatorType;
|
|
202
199
|
|
|
@@ -414,10 +411,8 @@ class itfTableHeader extends Vue {
|
|
|
414
411
|
}
|
|
415
412
|
|
|
416
413
|
sortBy(column, order) {
|
|
417
|
-
let sort = {
|
|
418
|
-
|
|
419
|
-
sort = order === 'desc' ? `-${column.property}` : column.property;
|
|
420
|
-
}
|
|
414
|
+
let sort = order === 'desc' ? `-${column.property}` : column.property;
|
|
415
|
+
console.info(sort);
|
|
421
416
|
this.$emit('update:sorting', sort);
|
|
422
417
|
}
|
|
423
418
|
}
|
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
<div>
|
|
3
3
|
<div @click.prevent.stop="toggle" class="d-flex align-items-center flex-nowrap" :class="{'active-toggle': visible}">
|
|
4
4
|
<div class="item-toggle text-muted">
|
|
5
|
-
<template v-if="visible &&
|
|
6
|
-
<div class="itf-spinner"></div>
|
|
7
|
-
</template>
|
|
8
|
-
<template v-else-if="visible && expanded">
|
|
5
|
+
<template v-if="visible && expanded">
|
|
9
6
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
10
7
|
width="16" height="16" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
|
11
8
|
<path d="M184.7,413.1l2.1-1.8l156.5-136c5.3-4.6,8.6-11.5,8.6-19.2c0-7.7-3.4-14.6-8.6-19.2L187.1,101l-2.6-2.3
|
|
@@ -26,10 +23,6 @@
|
|
|
26
23
|
</div>
|
|
27
24
|
</template>
|
|
28
25
|
<style lang="scss" scoped>
|
|
29
|
-
.itf-spinner {
|
|
30
|
-
width: 1rem;
|
|
31
|
-
height: 1rem;
|
|
32
|
-
}
|
|
33
26
|
.active-toggle {
|
|
34
27
|
cursor: pointer;
|
|
35
28
|
}
|
|
@@ -50,7 +43,6 @@ export default @Component({
|
|
|
50
43
|
class itfTableRowToggle extends Vue {
|
|
51
44
|
@Prop(Boolean) expanded;
|
|
52
45
|
@Prop(Boolean) visible;
|
|
53
|
-
@Prop(Boolean) loading;
|
|
54
46
|
|
|
55
47
|
toggle() {
|
|
56
48
|
this.$emit('toggle');
|
|
@@ -25,22 +25,6 @@
|
|
|
25
25
|
<span v-if="indicatorType === 'order'">{{ (n + 1) }}</span>
|
|
26
26
|
<span v-else-if="indicatorType === 'property'">{{ item[idProperty] }}</span>
|
|
27
27
|
<span v-else-if="indicatorType === 'checkbox'"><itf-checkbox :value="item[idProperty]" /></span>
|
|
28
|
-
<a href="" @click.prevent.stop="$emit('toggle', item)" v-else-if="indicatorType === 'toggle'">
|
|
29
|
-
<template v-if="subrowsProperty && item[subrowsProperty] && item[subrowsProperty].length">
|
|
30
|
-
<template v-if="item[subrowsProperty] && item[subrowsProperty].length && !isExpanded(item)">
|
|
31
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-square" viewBox="0 0 16 16">
|
|
32
|
-
<path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
|
|
33
|
-
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4"/>
|
|
34
|
-
</svg>
|
|
35
|
-
</template>
|
|
36
|
-
<template v-else>
|
|
37
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-dash-square" viewBox="0 0 16 16">
|
|
38
|
-
<path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2z"/>
|
|
39
|
-
<path d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8"/>
|
|
40
|
-
</svg>
|
|
41
|
-
</template>
|
|
42
|
-
</template>
|
|
43
|
-
</a>
|
|
44
28
|
</div>
|
|
45
29
|
</div>
|
|
46
30
|
<div accept-group="items" class="table-item-inner" @click="$emit('row-click', item)">
|
|
@@ -49,37 +33,37 @@
|
|
|
49
33
|
v-if="column.visible !== false"
|
|
50
34
|
:data-column="k"
|
|
51
35
|
:style="`width: ${column.width}px; max-width: ${column.width}px; left: ${column.left}px;`"
|
|
52
|
-
:class="{'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'editable': column.editable && editable}"
|
|
36
|
+
:class="{'justify-content-end': column.align === 'end', 'sticky': column.pinned, 'last-sticky-column': k === lastPinnedIndex, 'editable': column.editable && editable}"
|
|
53
37
|
class="table-view-item-value d-flex h-100">
|
|
54
|
-
<div class="table-view-item-value-content
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
38
|
+
<div class="table-view-item-value-content" :class="{'px-2': !(column.editable && editable)}">
|
|
39
|
+
<slot
|
|
40
|
+
:name="`column.${column.property}`"
|
|
41
|
+
:toggle="() => $emit('toggle', item)"
|
|
42
|
+
:hasSubitems="!!(subrowsProperty && item[subrowsProperty] && item[subrowsProperty].length)"
|
|
43
|
+
:isExpanded="!!(item[subrowsProperty] && item[subrowsProperty].length && !isExpanded(item))"
|
|
44
|
+
:level="level" :editable="column.editable && editable" :item="item" :column="column" :updateFields="(val) => updateValues(item, val, n, column)" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)">
|
|
45
|
+
<template v-if="column.editable && editable && (!editableProperty || item[editableProperty])">
|
|
46
|
+
<slot :name="`edit.${column.type}`" :level="level" :toggle="() => $emit('toggle', item)" :update="(val) => updateValue(item, val, n, column)" :value="getValue(item, column)" :item="item" :column="column">
|
|
47
|
+
<itf-text-field class="w-100 h-100" v-if="column.type === 'text'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
|
|
48
|
+
<itf-text-field class="w-100 h-100" v-if="column.type === 'number'" type="number" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
|
|
49
|
+
<itf-hours-field
|
|
50
|
+
class="w-100 h-100"
|
|
51
|
+
placeholder="00h 00m"
|
|
52
|
+
v-else-if="column.type === 'time'"
|
|
53
|
+
:hours="getValue(item, column)"
|
|
54
|
+
@update:hours="updateValue(item, $event, n, column)"
|
|
55
|
+
/>
|
|
56
|
+
<itf-textarea class="w-100 h-100" :rows="1" autogrow v-else-if="column.type === 'textarea'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
|
|
57
|
+
<itf-money-field class="w-100 h-100" currency-disabled :currency="currency" :currencies="currencies" v-else-if="column.type === 'money'" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" />
|
|
58
|
+
<itf-select class="w-100 h-100" v-else-if="column.type === 'select'" :reduce="(item) => item.value" :value="getValue(item, column)" @input="updateValue(item, $event, n, column)" :options="column.options"></itf-select>
|
|
59
|
+
</slot>
|
|
60
|
+
</template>
|
|
61
|
+
<div v-else class="h-100 align-items-center d-flex w-100">
|
|
62
|
+
<slot :name="`format.${column.type}`" :toggle="() => $emit('toggle', item)" :level="level" :value="getValue(item, column)" :update="(value) => updateValue(item, value, n, column)" :item="item" :column="column">
|
|
63
|
+
{{getValue(item, column)}}
|
|
64
|
+
</slot>
|
|
65
|
+
</div>
|
|
66
|
+
</slot>
|
|
83
67
|
</div>
|
|
84
68
|
</div>
|
|
85
69
|
</template>
|
|
@@ -102,7 +86,6 @@
|
|
|
102
86
|
:columns="columns"
|
|
103
87
|
:id-property="idProperty"
|
|
104
88
|
:subrows-property="subrowsProperty"
|
|
105
|
-
:async-subrows-property="asyncSubrowsProperty"
|
|
106
89
|
:show-add-column="showAddColumn"
|
|
107
90
|
:show-actions="showActions"
|
|
108
91
|
:no-select-all="noSelectAll"
|
|
@@ -162,7 +145,6 @@ class itfTableRows extends Vue {
|
|
|
162
145
|
@Prop() rows;
|
|
163
146
|
@Prop() idProperty;
|
|
164
147
|
@Prop() subrowsProperty;
|
|
165
|
-
@Prop() asyncSubrowsProperty;
|
|
166
148
|
@Prop() dividerProperty;
|
|
167
149
|
@Prop() active;
|
|
168
150
|
@Prop(Boolean) showAddColumn;
|
|
@@ -192,12 +174,6 @@ class itfTableRows extends Vue {
|
|
|
192
174
|
return this.columns.findIndex((column) => column.lastPinned);
|
|
193
175
|
}
|
|
194
176
|
|
|
195
|
-
hasSubitems(item) {
|
|
196
|
-
const hasFactItems = this.subrowsProperty && item[this.subrowsProperty] && item[this.subrowsProperty].length;
|
|
197
|
-
const hasPlanItems = this.asyncSubrowsProperty && item[this.asyncSubrowsProperty] && item[this.asyncSubrowsProperty];
|
|
198
|
-
return !!(hasFactItems || hasPlanItems);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
177
|
updateValue(item, value, index, column) {
|
|
202
178
|
const newItem = { ...item };
|
|
203
179
|
if (newItem[column.property] !== value) {
|
|
@@ -212,8 +188,20 @@ class itfTableRows extends Vue {
|
|
|
212
188
|
}
|
|
213
189
|
}
|
|
214
190
|
|
|
191
|
+
updateValues(item, values, index, column) {
|
|
192
|
+
const newItem = { ...item };
|
|
193
|
+
Object.assign(newItem, values);
|
|
194
|
+
this.$emit('update', {
|
|
195
|
+
index,
|
|
196
|
+
item,
|
|
197
|
+
inputValue: values,
|
|
198
|
+
value: newItem,
|
|
199
|
+
column
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
215
203
|
isActive(id) {
|
|
216
|
-
if (!this.idProperty
|
|
204
|
+
if (!this.idProperty) {
|
|
217
205
|
return false;
|
|
218
206
|
}
|
|
219
207
|
if (Array.isArray(this.active)) {
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
--itf-table-alt-bg: #F9FAFB;
|
|
8
8
|
--itf-table-alt-selected-bg: #eff1f3;
|
|
9
9
|
--itf-table-header-bg: #f5f7f8;
|
|
10
|
-
--itf-table-header-color: #
|
|
10
|
+
--itf-table-header-color: #7A818EA5;
|
|
11
11
|
--itf-table-mirror-bg: #F2F4F7;
|
|
12
12
|
--itf-table-border-color: transparent; //var(--itf-table-header-bg);
|
|
13
|
-
--itf-table-header-border-color: #
|
|
13
|
+
--itf-table-header-border-color: #7A818E33;
|
|
14
14
|
--itf-table-border-base-color: var(--itf-table-header-bg); // кольори границь таблиці без внутрішніх рядків
|
|
15
15
|
--itf-table-border-base-width: 2px;
|
|
16
16
|
--itf-table-hover-header-bg: #dfe5ef;
|
|
@@ -23,8 +23,6 @@
|
|
|
23
23
|
--itf-table-summary-text: var(--bs-tertiary-color);
|
|
24
24
|
--itf-table-table-border-radius: 1rem;
|
|
25
25
|
--itf-table-header-height: 2.25rem;
|
|
26
|
-
--itf-table-divider-bg: #F7F8FA;
|
|
27
|
-
--itf-table-divider-border: rgba(238, 238, 238, 1);
|
|
28
26
|
|
|
29
27
|
--group-title-height: 40px;
|
|
30
28
|
--table-row-height: none;
|
|
@@ -45,9 +43,6 @@ body[data-theme="dark"] {
|
|
|
45
43
|
--itf-table-selected-bg: #011534;
|
|
46
44
|
--itf-table-active-bg: #022e72;
|
|
47
45
|
--itf-table-summary-text: #82909d80;
|
|
48
|
-
--itf-table-border-base-color: var(--itf-table-header-bg);
|
|
49
|
-
--itf-table-divider-bg: #0f0f0f;
|
|
50
|
-
--itf-table-divider-border: rgb(100, 100, 100, .1);
|
|
51
46
|
}
|
|
52
47
|
.itf-table2 {
|
|
53
48
|
font-size: var(--itf-table-content-font-size, var(--itf-table-font-size));
|
|
@@ -65,7 +60,7 @@ body[data-theme="dark"] {
|
|
|
65
60
|
height: 100%;
|
|
66
61
|
}
|
|
67
62
|
.scroller {
|
|
68
|
-
|
|
63
|
+
margin-bottom: 12px;
|
|
69
64
|
}
|
|
70
65
|
.scrollable-x {
|
|
71
66
|
overflow-x: scroll;
|
|
@@ -102,18 +97,34 @@ body[data-theme="dark"] {
|
|
|
102
97
|
position: sticky;
|
|
103
98
|
top: 0;
|
|
104
99
|
bottom: 0;
|
|
105
|
-
right:
|
|
100
|
+
right: -.5rem;
|
|
106
101
|
z-index: 8;
|
|
107
|
-
padding-right: 5px;
|
|
108
|
-
padding-left: 5px;
|
|
109
102
|
display: flex;
|
|
110
103
|
align-items: center;
|
|
104
|
+
|
|
105
|
+
@media (max-width: 768px) {
|
|
106
|
+
position: relative;
|
|
107
|
+
opacity: 1;
|
|
108
|
+
}
|
|
111
109
|
}
|
|
112
110
|
.on-hover {
|
|
113
111
|
opacity: 0;
|
|
112
|
+
width: 0;
|
|
113
|
+
padding: 4px .5rem;
|
|
114
|
+
overflow: hidden;
|
|
114
115
|
pointer-events: none;
|
|
116
|
+
position: absolute;
|
|
117
|
+
right: 0;
|
|
118
|
+
background: linear-gradient(90deg, transparent 0, var(--itf-table2-row-bg) 10px);
|
|
119
|
+
|
|
120
|
+
@media (max-width: 768px) {
|
|
121
|
+
width: max-content;
|
|
122
|
+
opacity: 1;
|
|
123
|
+
position: relative;
|
|
124
|
+
}
|
|
115
125
|
}
|
|
116
126
|
.table-row-template:hover .on-hover {
|
|
127
|
+
width: max-content;
|
|
117
128
|
opacity: 1;
|
|
118
129
|
pointer-events: all;
|
|
119
130
|
}
|
|
@@ -440,11 +451,11 @@ body[data-theme="dark"] {
|
|
|
440
451
|
}
|
|
441
452
|
|
|
442
453
|
&__row-divider {
|
|
443
|
-
background-color:
|
|
454
|
+
background-color: #F7F8FA;
|
|
444
455
|
height: 5px;
|
|
445
456
|
padding: 0;
|
|
446
|
-
border-top: 1px solid
|
|
447
|
-
border-bottom: 1px solid
|
|
457
|
+
border-top: 1px solid rgba(238, 238, 238, 1);
|
|
458
|
+
border-bottom: 1px solid rgba(238, 238, 238, 1);
|
|
448
459
|
}
|
|
449
460
|
//&:hover, &.permanent-editable-border {
|
|
450
461
|
// .table-view-item-value.editable {
|
|
@@ -457,7 +468,6 @@ body[data-theme="dark"] {
|
|
|
457
468
|
position: relative;
|
|
458
469
|
z-index: 2;
|
|
459
470
|
width: 100%;
|
|
460
|
-
display: flex;
|
|
461
471
|
height: 100%;
|
|
462
472
|
background: var(--itf-table2-row-bg)
|
|
463
473
|
}
|