@itfin/components 1.3.99 → 1.4.0
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/button/Button.vue +4 -2
- package/src/components/card/BentoCard.vue +70 -19
- package/src/components/card/BentoGrid.vue +21 -8
- package/src/components/filter/FilterAmountRange.vue +50 -42
- package/src/components/filter/FilterBadge.vue +27 -22
- package/src/components/filter/FilterFacetsList.vue +21 -17
- package/src/components/filter/FilterPanel.vue +141 -44
- package/src/components/filter/index.stories.js +0 -2
- package/src/components/form/Label.vue +19 -2
- package/src/components/icon/Icon.vue +4 -2
- package/src/components/icon/components/fi_fingerprint.vue +4 -0
- package/src/components/icon/components/nomi-ai.vue +6 -0
- package/src/components/icon/components/nomi-arrow-down.vue +4 -0
- package/src/components/icon/components/nomi-arrow-right-top.vue +4 -0
- package/src/components/icon/components/nomi-arrow-up.vue +4 -0
- package/src/components/icon/components/nomi-arrow_down.vue +4 -0
- package/src/components/icon/components/nomi-arrow_up.vue +4 -0
- package/src/components/icon/components/nomi-arrows.vue +7 -0
- package/src/components/icon/components/nomi-calendar-alt.vue +4 -0
- package/src/components/icon/components/nomi-calendar-alt2.vue +4 -0
- package/src/components/icon/components/nomi-calendar.vue +11 -0
- package/src/components/icon/components/nomi-card.vue +4 -0
- package/src/components/icon/components/nomi-clear.vue +4 -0
- package/src/components/icon/components/nomi-close.vue +5 -0
- package/src/components/icon/components/nomi-counterparty.vue +4 -0
- package/src/components/icon/components/nomi-dashboard.vue +4 -0
- package/src/components/icon/components/nomi-expand.vue +7 -0
- package/src/components/icon/components/nomi-eye-close.vue +4 -0
- package/src/components/icon/components/nomi-eye-open.vue +4 -0
- package/src/components/icon/components/nomi-eye.vue +4 -0
- package/src/components/icon/components/nomi-filter.vue +4 -0
- package/src/components/icon/components/nomi-help.vue +5 -0
- package/src/components/icon/components/nomi-hide.vue +4 -0
- package/src/components/icon/components/nomi-logout.vue +5 -0
- package/src/components/icon/components/nomi-money.vue +4 -0
- package/src/components/icon/components/nomi-move-left.vue +4 -0
- package/src/components/icon/components/nomi-move-right.vue +4 -0
- package/src/components/icon/components/nomi-pen.vue +5 -0
- package/src/components/icon/components/nomi-person.vue +5 -0
- package/src/components/icon/components/nomi-pin.vue +7 -0
- package/src/components/icon/components/nomi-project.vue +4 -0
- package/src/components/icon/components/nomi-recurrence.vue +2 -0
- package/src/components/icon/components/nomi-repeat.vue +7 -0
- package/src/components/icon/components/nomi-report.vue +4 -0
- package/src/components/icon/components/nomi-scissors.vue +4 -0
- package/src/components/icon/components/nomi-settings.vue +4 -0
- package/src/components/icon/components/nomi-sort-asc.vue +7 -0
- package/src/components/icon/components/nomi-sort-desc.vue +7 -0
- package/src/components/icon/components/nomi-table-view.vue +4 -0
- package/src/components/icon/components/nomi-tag.vue +4 -0
- package/src/components/icon/components/nomi-target.vue +4 -0
- package/src/components/icon/components/nomi-text.vue +6 -0
- package/src/components/icon/components/nomi-transactions.vue +8 -0
- package/src/components/icon/components/nomi-trash.vue +4 -0
- package/src/components/icon/components/nomi-unpin.vue +7 -0
- package/src/components/icon/components/nomi-user.vue +5 -0
- package/src/components/icon/convert-icons.js +11 -0
- package/src/components/icon/icons.js +332 -286
- package/src/components/icon/new-icons/ai.svg +5 -0
- package/src/components/icon/new-icons/arrow-down.svg +3 -0
- package/src/components/icon/new-icons/arrow-right-top.svg +3 -0
- package/src/components/icon/new-icons/arrow-up.svg +3 -0
- package/src/components/icon/new-icons/arrow_down.svg +3 -0
- package/src/components/icon/new-icons/arrow_up.svg +3 -0
- package/src/components/icon/new-icons/arrows.svg +6 -0
- package/src/components/icon/new-icons/calendar-alt.svg +3 -0
- package/src/components/icon/new-icons/calendar-alt2.svg +3 -0
- package/src/components/icon/new-icons/calendar.svg +10 -0
- package/src/components/icon/new-icons/card.svg +3 -0
- package/src/components/icon/new-icons/clear.svg +3 -0
- package/src/components/icon/new-icons/close.svg +4 -0
- package/src/components/icon/new-icons/counterparty.svg +3 -0
- package/src/components/icon/new-icons/dashboard.svg +3 -0
- package/src/components/icon/new-icons/expand.svg +6 -0
- package/src/components/icon/new-icons/eye-close.svg +3 -0
- package/src/components/icon/new-icons/eye-open.svg +3 -0
- package/src/components/icon/new-icons/eye.svg +3 -0
- package/src/components/icon/new-icons/filter.svg +3 -0
- package/src/components/icon/new-icons/help.svg +4 -0
- package/src/components/icon/new-icons/hide.svg +3 -0
- package/src/components/icon/new-icons/logout.svg +4 -0
- package/src/components/icon/new-icons/money.svg +3 -0
- package/src/components/icon/new-icons/move-left.svg +3 -0
- package/src/components/icon/new-icons/move-right.svg +3 -0
- package/src/components/icon/new-icons/pen.svg +4 -0
- package/src/components/icon/new-icons/person.svg +4 -0
- package/src/components/icon/new-icons/pin.svg +6 -0
- package/src/components/icon/new-icons/project.svg +3 -0
- package/src/components/icon/new-icons/recurrence.svg +1 -0
- package/src/components/icon/new-icons/repeat.svg +6 -0
- package/src/components/icon/new-icons/report.svg +3 -0
- package/src/components/icon/new-icons/scissors.svg +3 -0
- package/src/components/icon/new-icons/settings.svg +3 -0
- package/src/components/icon/new-icons/sort-asc.svg +6 -0
- package/src/components/icon/new-icons/sort-desc.svg +6 -0
- package/src/components/icon/new-icons/table-view.svg +3 -0
- package/src/components/icon/new-icons/tag.svg +3 -0
- package/src/components/icon/new-icons/target.svg +3 -0
- package/src/components/icon/new-icons/text.svg +5 -0
- package/src/components/icon/new-icons/transactions.svg +7 -0
- package/src/components/icon/new-icons/trash.svg +3 -0
- package/src/components/icon/new-icons/unpin.svg +6 -0
- package/src/components/icon/new-icons/user.svg +4 -0
- package/src/components/modal/DeleteConfirmModal.vue +0 -2
- package/src/components/modal/ItemEditor.vue +1 -5
- package/src/components/pagination/Pagination.vue +3 -2
- package/src/components/pagination/Pagination2.vue +179 -0
- package/src/components/panels/Panel.vue +23 -7
- package/src/components/panels/PanelItemEdit.vue +62 -0
- package/src/components/panels/PanelLink.vue +26 -6
- package/src/components/panels/PanelList.vue +27 -26
- package/src/components/panels/helpers.spec.ts +27 -0
- package/src/components/panels/helpers.ts +37 -0
- package/src/components/popover/NoticePopout.vue +1 -1
- package/src/components/select/Select.vue +1 -1
- package/src/components/sortable/draggable.js +2 -1
- package/src/components/table/Table2.vue +35 -8
- package/src/components/table/TableBody.vue +10 -18
- package/src/components/table/TableGroup.vue +30 -14
- package/src/components/table/TableHeader.vue +122 -73
- package/src/components/table/TableRowToggle.vue +51 -0
- package/src/components/table/TableRows.vue +20 -29
- package/src/components/table/index.stories.js +22 -200
- package/src/components/table/table2.scss +237 -68
- package/src/components/text-field/MoneyField.vue +23 -21
- package/src/components/text-field/TextField.vue +12 -8
- package/src/components/tree/TreeEditor.vue +615 -0
- package/src/components/view/View.vue +244 -0
- package/src/components/view/index.stories.js +588 -0
- package/src/helpers/formatters.js +14 -1
- package/src/helpers/tree/cdbl.js +32 -0
- package/src/helpers/tree/cint.js +43 -0
- package/src/helpers/tree/domDrag.js +911 -0
- package/src/helpers/tree/domFinds.js +20 -0
- package/src/helpers/tree/domGetPointFromEvent.js +53 -0
- package/src/helpers/tree/domIsClientXYIn.js +65 -0
- package/src/helpers/tree/domRemove.js +50 -0
- package/src/helpers/tree/evem.js +27 -0
- package/src/helpers/tree/genID.js +56 -0
- package/src/helpers/tree/isEle.js +28 -0
- package/src/helpers/tree/isestr.js +35 -0
- package/src/helpers/tree/isint.js +40 -0
- package/src/helpers/tree/isnbr.js +24 -0
- package/src/helpers/tree/isnum.js +38 -0
- package/src/helpers/tree/ispint.js +41 -0
- package/src/helpers/tree/isstr.js +27 -0
- package/src/helpers/tree.js +30 -0
- package/src/helpers/vuetifyColor.js +136 -0
- package/src/locales/en.js +17 -0
- package/src/locales/uk.js +17 -0
|
@@ -10,20 +10,23 @@
|
|
|
10
10
|
<div class="b-panel__expand_text" v-text="title"></div>
|
|
11
11
|
</a>
|
|
12
12
|
</div>
|
|
13
|
-
<div v-if="!nocard" v-show="!collapsed" class="b-panel-header px-3 pt-3">
|
|
13
|
+
<div v-if="!nocard" v-show="!collapsed" class="b-panel-header px-3 pt-3 pb-2">
|
|
14
14
|
<slot name="header">
|
|
15
|
-
<div>
|
|
15
|
+
<div class="d-flex gap-3 align-items-center">
|
|
16
|
+
<itf-button v-if="closeable" icon default class="d-md-none" @click="closePanel">
|
|
17
|
+
<itf-icon name="chevron_left" />
|
|
18
|
+
</itf-button>
|
|
16
19
|
<slot name="title">
|
|
17
|
-
<div class="b-panel__title
|
|
20
|
+
<div class="b-panel__title fw-bold mb-0 h2" v-text="title"></div>
|
|
18
21
|
</slot>
|
|
19
22
|
</div>
|
|
20
23
|
<div class="d-flex gap-1">
|
|
21
24
|
<slot name="buttons"></slot>
|
|
22
|
-
<itf-button v-if="expandable" icon
|
|
23
|
-
<itf-icon name="expand" />
|
|
25
|
+
<itf-button v-if="expandable" icon default class="b-panel__expand_button d-none d-md-block" @click="fullsizePanel">
|
|
26
|
+
<itf-icon new name="expand" />
|
|
24
27
|
</itf-button>
|
|
25
|
-
<itf-button v-if="closeable" icon
|
|
26
|
-
<itf-icon name="
|
|
28
|
+
<itf-button v-if="closeable" icon default class="b-panel__expand_button" @click="closePanel">
|
|
29
|
+
<itf-icon new name="close" />
|
|
27
30
|
</itf-button>
|
|
28
31
|
</div>
|
|
29
32
|
</slot>
|
|
@@ -51,6 +54,18 @@
|
|
|
51
54
|
background: var(--b-panel-bg);
|
|
52
55
|
box-shadow: var(--b-panel-box-shadow);
|
|
53
56
|
|
|
57
|
+
@media (max-width: 768px) {
|
|
58
|
+
margin: 0;
|
|
59
|
+
height: 100%;
|
|
60
|
+
min-width: 0 !important;
|
|
61
|
+
|
|
62
|
+
position: absolute;
|
|
63
|
+
top: 0;
|
|
64
|
+
left: 0;
|
|
65
|
+
right: 0;
|
|
66
|
+
bottom: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
54
69
|
&__collapsed {
|
|
55
70
|
flex-basis: 38px;
|
|
56
71
|
flex-grow: 0;
|
|
@@ -140,6 +155,7 @@ class Panel extends Vue {
|
|
|
140
155
|
@Prop() title;
|
|
141
156
|
@Prop() icon;
|
|
142
157
|
@Prop() payload;
|
|
158
|
+
@Prop() panel;
|
|
143
159
|
@Prop(Boolean) collapsed;
|
|
144
160
|
@Prop(Boolean) closeable;
|
|
145
161
|
@Prop(Boolean) expandable;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-loading="loading" class="px-3 pt-2 h-100">
|
|
3
|
+
<itf-form
|
|
4
|
+
ref="editForm"
|
|
5
|
+
class="d-flex flex-column justify-content-between h-100"
|
|
6
|
+
@keydown.native.shift.enter.stop.prevent="onSaveClick"
|
|
7
|
+
@keydown.native.esc.stop.prevent="$emit('cancel')"
|
|
8
|
+
>
|
|
9
|
+
<slot></slot>
|
|
10
|
+
<div class="py-3 justify-content-end d-flex align-items-center sticky-container">
|
|
11
|
+
<div v-if="!hideFooter">
|
|
12
|
+
<itf-button v-tooltip.delay="'Hot key: Esc'" secondary squircle :loading="loading" :disabled="loading" @click="$emit('cancel')">
|
|
13
|
+
<span>{{ $t('components.modal.cancel') }}</span>
|
|
14
|
+
</itf-button>
|
|
15
|
+
<itf-button v-tooltip.delay="'Hot key: Shift + Enter'" primary squircle :loading="loading" :disabled="loading" @click="onSaveClick">
|
|
16
|
+
<span>{{ $t('components.modal.save') }}</span>
|
|
17
|
+
</itf-button>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</itf-form>
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
23
|
+
<style lang="scss" scoped>
|
|
24
|
+
.sticky-container {
|
|
25
|
+
position: sticky;
|
|
26
|
+
top: auto;
|
|
27
|
+
bottom: 0;
|
|
28
|
+
z-index: 999;
|
|
29
|
+
background-color: var(--bs-body-bg);
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
32
|
+
<script>
|
|
33
|
+
import { Vue, Component, Prop } from 'vue-property-decorator';
|
|
34
|
+
import tooltip from '../../directives/tooltip';
|
|
35
|
+
import loading from '../../directives/loading';
|
|
36
|
+
import itfForm from '../form/Form.vue';
|
|
37
|
+
import itfButton from '../button/Button.vue';
|
|
38
|
+
|
|
39
|
+
@Component({
|
|
40
|
+
components: {
|
|
41
|
+
itfForm,
|
|
42
|
+
itfButton
|
|
43
|
+
},
|
|
44
|
+
directives: {
|
|
45
|
+
tooltip,
|
|
46
|
+
loading
|
|
47
|
+
},
|
|
48
|
+
filters: {
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
export default class PanelItemEdit extends Vue {
|
|
52
|
+
@Prop(Boolean) loading;
|
|
53
|
+
@Prop(Boolean) hideFooter;
|
|
54
|
+
|
|
55
|
+
onSaveClick() {
|
|
56
|
+
if (this.$refs.editForm && !this.$refs.editForm.doValidation()) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.$emit('save');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<a :href="link" :target="target" v-on="on"><slot></slot></a>
|
|
2
|
+
<a :href="link" :target="target" v-on="on" :class="{[activeClass]: isActive}"><slot></slot></a>
|
|
3
3
|
</template>
|
|
4
4
|
<script lang="ts">
|
|
5
5
|
import { Vue, Component, Inject, Prop } from 'vue-property-decorator';
|
|
6
6
|
import { IPanel } from './PanelList.vue';
|
|
7
|
+
import {stackToHash} from "@itfin/components/src/components/panels/helpers";
|
|
7
8
|
|
|
8
9
|
@Component({
|
|
9
10
|
components: {
|
|
@@ -17,9 +18,12 @@ export default class PanelLink extends Vue {
|
|
|
17
18
|
@Inject({ default: null }) panelList;
|
|
18
19
|
@Inject({ default: null }) currentPanel;
|
|
19
20
|
|
|
21
|
+
@Prop(Boolean) global: boolean;
|
|
20
22
|
@Prop(String) panel: string;
|
|
21
23
|
@Prop() payload: payload;
|
|
22
24
|
@Prop() target: string;
|
|
25
|
+
@Prop() list;
|
|
26
|
+
@Prop({ type: String, default: 'active' }) activeClass: string;
|
|
23
27
|
@Prop(Boolean) append: boolean;
|
|
24
28
|
|
|
25
29
|
get on() {
|
|
@@ -30,25 +34,41 @@ export default class PanelLink extends Vue {
|
|
|
30
34
|
return handlers;
|
|
31
35
|
}
|
|
32
36
|
|
|
37
|
+
get activeList() {
|
|
38
|
+
return this.list ?? this.panelList;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get isActive() {
|
|
42
|
+
if (!this.activeList) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
let stack = this.activeList.getCurrentStack();
|
|
46
|
+
return stack.find(s => s.type === this.panel);
|
|
47
|
+
}
|
|
48
|
+
|
|
33
49
|
get link() {
|
|
34
|
-
let stack = this.
|
|
50
|
+
let stack = this.activeList?.getCurrentStack() ?? [];
|
|
35
51
|
if (!this.append) {
|
|
36
|
-
stack = stack.splice(0, this.currentPanel
|
|
52
|
+
stack = stack.splice(0, this.currentPanel?.index + 1);
|
|
37
53
|
}
|
|
38
|
-
const hash =
|
|
54
|
+
const hash = stackToHash([
|
|
39
55
|
...stack,
|
|
40
56
|
{
|
|
41
57
|
type: this.panel,
|
|
42
58
|
payload: this.payload || {}
|
|
43
59
|
}
|
|
44
60
|
]);
|
|
45
|
-
return
|
|
61
|
+
return hash;
|
|
46
62
|
}
|
|
47
63
|
|
|
48
64
|
onClick(e) {
|
|
65
|
+
console.info(this.activeList);
|
|
66
|
+
if (!this.activeList) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
49
69
|
e.preventDefault();
|
|
50
70
|
e.stopPropagation();
|
|
51
|
-
this.
|
|
71
|
+
this.activeList.openPanel(this.panel, this.payload || {}, this.append ? undefined : this.currentPanel?.index + 1);
|
|
52
72
|
}
|
|
53
73
|
}
|
|
54
74
|
</script>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<panel
|
|
12
12
|
:key="n"
|
|
13
13
|
:index="n"
|
|
14
|
+
:panel="panel"
|
|
14
15
|
:title="panel.title"
|
|
15
16
|
:nocard="panel.nocard"
|
|
16
17
|
:icon="panel.icon"
|
|
@@ -129,25 +130,37 @@ $double-an-time: $an-time * 2;
|
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
|
|
133
|
+
@media (max-width: 768px) {
|
|
134
|
+
@keyframes slidein {
|
|
135
|
+
0% {
|
|
136
|
+
max-width: 100%;
|
|
137
|
+
}
|
|
138
|
+
100% {
|
|
139
|
+
max-width: 100%;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
132
144
|
.b-panel {
|
|
133
145
|
transition: min-width $an-time linear, flex-grow $an-time linear;
|
|
134
146
|
|
|
135
147
|
> div {
|
|
136
|
-
transition: opacity $an-time linear;
|
|
148
|
+
//transition: opacity $an-time linear;
|
|
137
149
|
}
|
|
138
150
|
}
|
|
139
151
|
|
|
140
|
-
|
|
141
|
-
opacity: 0;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
opacity: 0 !important;
|
|
146
|
-
}
|
|
152
|
+
//.slide-enter-active > div {
|
|
153
|
+
// opacity: 0;
|
|
154
|
+
//}
|
|
155
|
+
//
|
|
156
|
+
//.opacity-null > div {
|
|
157
|
+
// opacity: 0 !important;
|
|
158
|
+
//}
|
|
147
159
|
</style>
|
|
148
160
|
<script lang="ts">
|
|
149
161
|
import { Vue, Component, Prop } from 'vue-property-decorator';
|
|
150
162
|
import Panel from './Panel.vue';
|
|
163
|
+
import {hashToStack, stackToHash} from "@itfin/components/src/components/panels/helpers";
|
|
151
164
|
|
|
152
165
|
interface VisualOptions {
|
|
153
166
|
title: string;
|
|
@@ -177,6 +190,7 @@ export interface IPanel {
|
|
|
177
190
|
getPayload: () => any;
|
|
178
191
|
setPayload: (value: any) => void;
|
|
179
192
|
__events: Record<string, ((event: string, ...args: any[]) => any)[]>;
|
|
193
|
+
permanentExpanded: boolean;
|
|
180
194
|
}
|
|
181
195
|
|
|
182
196
|
@Component({
|
|
@@ -199,7 +213,6 @@ export default class PanelList extends Vue {
|
|
|
199
213
|
|
|
200
214
|
nextId:number = 0;
|
|
201
215
|
|
|
202
|
-
|
|
203
216
|
created() {
|
|
204
217
|
if (this.firstPanel) {
|
|
205
218
|
this.internalOpenPanel(this.firstPanel.type, this.firstPanel.payload);
|
|
@@ -291,6 +304,7 @@ export default class PanelList extends Vue {
|
|
|
291
304
|
this.$nextTick(() => { // щоб панелі змінювались при редагуванні
|
|
292
305
|
const n = newStack.length;
|
|
293
306
|
newPanel.isAnimate = isAnimation;
|
|
307
|
+
newPanel.permanentExpanded = !!this.panels[type].permanentExpanded;
|
|
294
308
|
newPanel.emit = (event, ...args) => this.emitEvent(event, ...args);
|
|
295
309
|
newPanel.open = (type, payload) => this.openPanel(type, payload, n + 1);
|
|
296
310
|
newPanel.close = () => this.closePanel(newPanel);
|
|
@@ -362,7 +376,7 @@ export default class PanelList extends Vue {
|
|
|
362
376
|
openPanel.isCollapsed = false;
|
|
363
377
|
}
|
|
364
378
|
const openPanelIndex = this.panelsStack.findIndex(p => p === openPanel);
|
|
365
|
-
if (openPanelIndex > 0) {
|
|
379
|
+
if (openPanelIndex > 0 && !openPanel?.permanentExpanded) {
|
|
366
380
|
this.panelsStack[openPanelIndex - 1].isCollapsed = false;
|
|
367
381
|
}
|
|
368
382
|
this.ensureOnlyTwoOpenPanels(openPanel.id);
|
|
@@ -388,30 +402,17 @@ export default class PanelList extends Vue {
|
|
|
388
402
|
return [...this.panelsStack];
|
|
389
403
|
}
|
|
390
404
|
|
|
391
|
-
getLink(stack: IPanel[]) {
|
|
392
|
-
return stack.map(panel => {
|
|
393
|
-
return `${panel.type}${panel.isCollapsed ? '' : '!'}=${JSON.stringify(panel.payload || {})}`;
|
|
394
|
-
}).join('&');
|
|
395
|
-
}
|
|
396
|
-
|
|
397
405
|
setPanelHash() {
|
|
398
|
-
const hash =
|
|
406
|
+
const hash = stackToHash(this.panelsStack).replace(/^#/, '');
|
|
399
407
|
this.$router.push({ hash });
|
|
400
408
|
}
|
|
401
409
|
|
|
402
410
|
async parsePanelHash() {
|
|
403
411
|
const {hash} = location;
|
|
404
412
|
if (hash) {
|
|
405
|
-
const panels = hash
|
|
406
|
-
const [type, payload] = item.split('=');
|
|
407
|
-
const isCollapsed = !item.includes('!');
|
|
408
|
-
return {
|
|
409
|
-
type: type.replace('!', ''),
|
|
410
|
-
isCollapsed,
|
|
411
|
-
payload: JSON.parse(decodeURIComponent(payload))
|
|
412
|
-
};
|
|
413
|
-
});
|
|
413
|
+
const panels = hashToStack(hash);
|
|
414
414
|
const newStack = [];
|
|
415
|
+
this.panelsStack = [];
|
|
415
416
|
for (const panelIndex in panels) {
|
|
416
417
|
const panel = panels[panelIndex];
|
|
417
418
|
if (this.panelsStack[panelIndex] && this.panelsStack[panelIndex].type === panel.type) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {stackToHash, hashToStack} from "./helpers";
|
|
2
|
+
|
|
3
|
+
describe('panel helpers', () => {
|
|
4
|
+
test('stackToHash', () => {
|
|
5
|
+
const stack = [
|
|
6
|
+
{ type: 'a', payload: { a: 1 }, isCollapsed: false },
|
|
7
|
+
{ type: 'b', payload: { b: 2 }, isCollapsed: true },
|
|
8
|
+
{ type: 'c', payload: { c: 3 }, isCollapsed: false }
|
|
9
|
+
];
|
|
10
|
+
expect(stackToHash(stack)).toBe('a!={"a":1}&b={"b":2}&c!={"c":3}');
|
|
11
|
+
});
|
|
12
|
+
test('hashToStack', () => {
|
|
13
|
+
const stack = [
|
|
14
|
+
{ type: 'a', payload: { a: 1 }, isCollapsed: false },
|
|
15
|
+
{ type: 'b', payload: { b: 2 }, isCollapsed: true },
|
|
16
|
+
{ type: 'c', payload: { c: 3 }, isCollapsed: false }
|
|
17
|
+
];
|
|
18
|
+
expect(hashToStack('a!={"a":1}&b={"b":2}&c!={"c":3}')).toEqual(stack);
|
|
19
|
+
expect(hashToStack('a!={"a')).toEqual([
|
|
20
|
+
{
|
|
21
|
+
"isCollapsed": false,
|
|
22
|
+
"payload": {},
|
|
23
|
+
"type": "a"
|
|
24
|
+
}
|
|
25
|
+
]);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface IPanel {
|
|
2
|
+
type: string;
|
|
3
|
+
payload?: any;
|
|
4
|
+
isCollapsed?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function stackToHash(stack: IPanel[]) {
|
|
8
|
+
const hash = stack.map(panel => {
|
|
9
|
+
return `${panel.type}${panel.isCollapsed ? '' : '!'}=${JSON.stringify(panel.payload || {})}`;
|
|
10
|
+
}).join('&');
|
|
11
|
+
return `#${hash}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export function hashToStack(hash: string|undefined): IPanel[] {
|
|
16
|
+
let stack:IPanel[] = [];
|
|
17
|
+
if (hash) {
|
|
18
|
+
const str = hash.replace(/^#/, '');
|
|
19
|
+
|
|
20
|
+
stack = str.split('&').map(item => {
|
|
21
|
+
const [type, payload] = item.split('=');
|
|
22
|
+
const isCollapsed = !type.includes('!');
|
|
23
|
+
let payloadObj:any = {};
|
|
24
|
+
try {
|
|
25
|
+
payloadObj = JSON.parse(decodeURIComponent(payload));
|
|
26
|
+
} catch (e) {
|
|
27
|
+
// ignore
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
type: type.replace('!', ''),
|
|
31
|
+
isCollapsed,
|
|
32
|
+
payload: payloadObj
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return stack;
|
|
37
|
+
}
|
|
@@ -632,7 +632,7 @@ export default {
|
|
|
632
632
|
default(dropdownList, component, { width, top, left }) {
|
|
633
633
|
dropdownList.style.top = top
|
|
634
634
|
dropdownList.style.left = left
|
|
635
|
-
dropdownList.style.minWidth = width
|
|
635
|
+
dropdownList.style.minWidth = width;
|
|
636
636
|
dropdownList.style.width = 'max-content';
|
|
637
637
|
},
|
|
638
638
|
},
|
|
@@ -7,13 +7,14 @@ const SORTABLE_ATTRIBUTES = ['drag-ignore-handle', 'scrollable'];
|
|
|
7
7
|
|
|
8
8
|
const DEFAULT_OPTIONS = {
|
|
9
9
|
draggableClass: DRAGGABLE_CLASS,
|
|
10
|
-
dragHandleClass: DRAG_HANDLE_CLASS,
|
|
10
|
+
// dragHandleClass: DRAG_HANDLE_CLASS,
|
|
11
11
|
delay: 200,
|
|
12
12
|
tresholdDistance: 2,
|
|
13
13
|
draggable: `.${DRAGGABLE_CLASS}`,
|
|
14
14
|
handle: `.${DRAG_HANDLE_CLASS}`,
|
|
15
15
|
ignoreHandleClassList: SORTABLE_ATTRIBUTES,
|
|
16
16
|
mirror: {
|
|
17
|
+
// appendTo: '.itf-table2 .itf-table2__header',
|
|
17
18
|
yAxis: false,
|
|
18
19
|
constrainDimensions: true
|
|
19
20
|
},
|
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
'table-absolute': absolute,
|
|
6
6
|
'table-clickable': clickable,
|
|
7
7
|
'permanent-checkboxes': selectedIds.length
|
|
8
|
-
}" :style="{ '--indicator-area-width': `${indicatorType === 'none' ? 1 : indicatorWidth}px` }">
|
|
9
|
-
<itf-notice-popout :visible="showGroupOperations" class="rounded-
|
|
10
|
-
<div class="d-flex gap-
|
|
11
|
-
<div
|
|
8
|
+
}" :style="{ '--indicator-area-width': `${indicatorType === 'none' ? 1 : indicatorWidth}px`, '--shadow-area-width': `${shadowWidth}px` }">
|
|
9
|
+
<itf-notice-popout :visible="showGroupOperations" class="rounded-3 bg-black text-white">
|
|
10
|
+
<div class="d-flex gap-2 ps-3 align-items-center small itf-table2_mass-operations">
|
|
11
|
+
<div>{{$tc('components.table.selectedItems', selectedIds.length, { n: selectedIds.length })}}</div>
|
|
12
|
+
<div class="opacity-50">•</div>
|
|
13
|
+
<a href="" class="me-3 opacity-50 text-white text-decoration-none" @click.stop.prevent="selectedIds = []">{{$t('components.table.cancelSelected')}}</a>
|
|
12
14
|
<div>
|
|
13
15
|
<slot name="group-operations"></slot>
|
|
14
16
|
</div>
|
|
@@ -29,6 +31,7 @@
|
|
|
29
31
|
:title="group.name"
|
|
30
32
|
:selected-ids.sync="selectedIds"
|
|
31
33
|
:add-new-rows="addNewRows"
|
|
34
|
+
:shadow-width="shadowWidth"
|
|
32
35
|
:column-sorting="columnSorting"
|
|
33
36
|
:column-resizing="columnResizing"
|
|
34
37
|
:show-grouping="showGrouping"
|
|
@@ -43,6 +46,7 @@
|
|
|
43
46
|
:currencies="currencies"
|
|
44
47
|
:currency="currency"
|
|
45
48
|
:subrows-property="subrowsProperty"
|
|
49
|
+
:divider-property="dividerProperty"
|
|
46
50
|
:indicator-type="indicatorType"
|
|
47
51
|
:expanded-all="expandedAll"
|
|
48
52
|
:indicatorWidth="indicatorWidth"
|
|
@@ -53,9 +57,9 @@
|
|
|
53
57
|
:editable-property="editableProperty"
|
|
54
58
|
:sorting.sync="_sorting"
|
|
55
59
|
:active="active"
|
|
56
|
-
:sort-as-string="sortAsString"
|
|
57
60
|
@update:expanded-ids="$emit('update:expanded-ids', $event)"
|
|
58
61
|
@new="$emit('new', $event)"
|
|
62
|
+
@filter="$emit('filter', $event)"
|
|
59
63
|
@add-column="$emit('add-column', $event)"
|
|
60
64
|
>
|
|
61
65
|
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
@@ -103,9 +107,11 @@ class itfTable2 extends Vue {
|
|
|
103
107
|
@Prop({ type: String, default: null }) idProperty;
|
|
104
108
|
@Prop({ type: String, default: null }) cssProperty;
|
|
105
109
|
@Prop({ type: String, default: null }) subrowsProperty;
|
|
110
|
+
@Prop({ type: String, default: null }) dividerProperty;
|
|
106
111
|
@Prop({ type: String, default: null }) editableProperty;
|
|
107
112
|
@Prop({ default: null }) active;
|
|
108
113
|
@Prop({ default: 45 }) indicatorWidth;
|
|
114
|
+
@Prop({ default: 0 }) shadowWidth;
|
|
109
115
|
@Prop({ type: String, default: null, validator: (val) => ['order', 'checkbox', 'toggle', 'property', 'none'].includes(val) }) indicatorType;
|
|
110
116
|
@Prop({ type: String, default: null }) stateName; // save state to storage
|
|
111
117
|
@Prop({ type: Object, default: () => ({}) }) schema;
|
|
@@ -114,7 +120,6 @@ class itfTable2 extends Vue {
|
|
|
114
120
|
@Prop({ type: Array, default: () => [] }) expandedIds;
|
|
115
121
|
@Prop() currency;
|
|
116
122
|
@Prop() currencies;
|
|
117
|
-
@Prop(Boolean) sortAsString;
|
|
118
123
|
@Prop(Boolean) stickyHeader;
|
|
119
124
|
@Prop(Boolean) addNewRows;
|
|
120
125
|
@Prop(Boolean) columnSorting;
|
|
@@ -138,7 +143,29 @@ class itfTable2 extends Vue {
|
|
|
138
143
|
};
|
|
139
144
|
|
|
140
145
|
get showGroupOperations() {
|
|
141
|
-
return !!this.$slots['group-operations'] && this.selectedIds.length > 0;
|
|
146
|
+
return !!(this.$slots['group-operations'] || this.$scopedSlots['group-operations']) && this.selectedIds.length > 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
resetSettings() {
|
|
150
|
+
const list = this.schema?.properties || [];
|
|
151
|
+
this.state = {
|
|
152
|
+
selectedIds: [],
|
|
153
|
+
columns: [...list]
|
|
154
|
+
};
|
|
155
|
+
this.saveTableState();
|
|
156
|
+
this.onSchemaUpdate();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
getColumnVisibility(property) {
|
|
160
|
+
return this.state.columns.find(i => i.property === property)?.visible ?? true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
toggleVisibility(property) {
|
|
164
|
+
const column = this.state.columns.find(i => i.property === property);
|
|
165
|
+
if (column) {
|
|
166
|
+
column.visible = !column.visible;
|
|
167
|
+
}
|
|
168
|
+
this.onColumnsUpdate(this.columns);
|
|
142
169
|
}
|
|
143
170
|
|
|
144
171
|
getTableState() {
|
|
@@ -153,6 +180,7 @@ class itfTable2 extends Vue {
|
|
|
153
180
|
state.selectedIds = [];
|
|
154
181
|
for (const column of list) {
|
|
155
182
|
const stateColumnIndex = state.columns.findIndex(i => i.property === column.property);
|
|
183
|
+
column.visible = (typeof column.visible === 'undefined') ? true : !!column.visible;
|
|
156
184
|
if (stateColumnIndex === -1) {
|
|
157
185
|
state.columns.push(column);
|
|
158
186
|
} else {
|
|
@@ -181,7 +209,6 @@ class itfTable2 extends Vue {
|
|
|
181
209
|
}
|
|
182
210
|
|
|
183
211
|
mounted() {
|
|
184
|
-
console.info(this.$scopedSlots)
|
|
185
212
|
this.onSchemaUpdate();
|
|
186
213
|
}
|
|
187
214
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
:columns="columns"
|
|
8
8
|
:id-property="idProperty"
|
|
9
9
|
:subrows-property="subrowsProperty"
|
|
10
|
+
:divider-property="dividerProperty"
|
|
10
11
|
:show-add-column="showAddColumn"
|
|
11
12
|
:show-actions="showActions"
|
|
12
13
|
:no-select-all="noSelectAll"
|
|
@@ -69,7 +70,7 @@
|
|
|
69
70
|
|
|
70
71
|
.scroller > .table-view-item:last-child {
|
|
71
72
|
.table-item-inner, .indicator {
|
|
72
|
-
border-bottom:
|
|
73
|
+
border-bottom: var(--itf-table-border-base-width) solid var(--itf-table-border-base-color);
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -91,31 +92,21 @@
|
|
|
91
92
|
display: flex;
|
|
92
93
|
align-items: center;
|
|
93
94
|
justify-content: center;
|
|
94
|
-
min-width: var(--itf-table-min-width);
|
|
95
|
+
min-width: 1rem;//var(--itf-table-min-width);
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
.table-row-template, .table-view-header-value {
|
|
98
99
|
.form-check {
|
|
100
|
+
font-size: 16px;
|
|
99
101
|
padding: 0;
|
|
100
102
|
margin-bottom: 0;
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
101
105
|
|
|
102
106
|
.form-check-input {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
.table-row-template {
|
|
108
|
-
.on-hover {
|
|
109
|
-
display: none;
|
|
110
|
-
}
|
|
111
|
-
&:hover, .permanent-checkboxes & {
|
|
112
|
-
.on-rest {
|
|
113
|
-
display: none;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.on-hover {
|
|
117
|
-
opacity: 1;
|
|
118
|
-
display: block;
|
|
107
|
+
--bs-form-check-bg: #fff;
|
|
108
|
+
margin: 0;
|
|
109
|
+
border: 1px solid #0000001A;
|
|
119
110
|
}
|
|
120
111
|
}
|
|
121
112
|
}
|
|
@@ -153,6 +144,7 @@ class itfTableBody extends Vue {
|
|
|
153
144
|
@Prop() rows;
|
|
154
145
|
@Prop() idProperty;
|
|
155
146
|
@Prop() subrowsProperty;
|
|
147
|
+
@Prop() dividerProperty;
|
|
156
148
|
@Prop() active;
|
|
157
149
|
@Prop(Boolean) showAddColumn;
|
|
158
150
|
@Prop(Boolean) showActions;
|