@itfin/components 1.3.34 → 1.3.36
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 +2 -1
- package/src/ITFSettings.js +8 -0
- package/src/assets/fonts/bootstrap-icons.woff +0 -0
- package/src/assets/fonts/bootstrap-icons.woff2 +0 -0
- package/src/assets/scss/icons.scss +2085 -0
- package/src/assets/scss/main.scss +1 -0
- package/src/components/avatar/index.stories.js +0 -1
- package/src/components/button/1.html +30 -0
- package/src/components/button/NativeButton.js +116 -0
- package/src/components/button/index.stories.js +10 -6
- package/src/components/checkbox/Checkbox.vue +5 -1
- package/src/components/dropdown/Dropdown.vue +6 -4
- package/src/components/dropdown/DropdownMenu.vue +14 -2
- package/src/components/sortable/sortable-shopify.js +1 -1
- package/src/components/table/Table2.vue +111 -33
- package/src/components/table/TableBody.vue +72 -47
- package/src/components/table/TableGroup.vue +167 -114
- package/src/components/table/TableHeader.vue +153 -36
- package/src/components/table/index.stories.js +152 -4
- package/src/components/table/sticky.js +439 -0
- package/src/components/text-field/MoneyField.vue +3 -2
- package/src/locales/en.js +1 -0
- package/src/locales/uk.js +1 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<div class="notion-overlay-container notion-default-overlay-container"
|
|
2
|
+
style="position: fixed; inset: 0px; z-index: 999; pointer-events: none; overflow: hidden;">
|
|
3
|
+
<div style="position: relative; z-index: 0;"></div>
|
|
4
|
+
<div data-overlay="true" style="pointer-events: auto; position: relative; z-index: 0;">
|
|
5
|
+
<div>
|
|
6
|
+
<div style="position: fixed; top: 0px; left: 0px; width: 100vw; height: 100vh;"></div>
|
|
7
|
+
<div style="position: fixed; left: 347px; top: 463.398px; pointer-events: none;">
|
|
8
|
+
<div style="width: 280px; height: 0px;"></div>
|
|
9
|
+
<div style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start;">
|
|
10
|
+
<div style="position: relative; top: 100%; pointer-events: auto;">
|
|
11
|
+
<div style="display: flex; align-items: center; position: relative; flex-direction: column-reverse; transform-origin: 0% top; left: 0px; top: 0px;">
|
|
12
|
+
<div role="dialog"
|
|
13
|
+
style="border-radius: 6px; background: white; backdrop-filter: none; position: relative; max-width: calc(-24px + 100vw); box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px; overflow: visible; width: 280px; min-height: 34px; max-height: 634px; display: flex; flex-direction: column;">
|
|
14
|
+
<div style="display: flex; flex-direction: column; overflow-y: auto; flex-grow: 1; height: 100%;">
|
|
15
|
+
<div style="padding: 6px 9px; font-size: 14px; min-height: 34px; display: flex; height: 100%; flex-direction: column; justify-content: space-between; flex-grow: 1; font-weight: 500;">
|
|
16
|
+
<div class="notranslate" spellcheck="true" placeholder=" "
|
|
17
|
+
data-content-editable-leaf="true" contenteditable="true"
|
|
18
|
+
style="max-width: 100%; width: 100%; white-space: pre-wrap; word-break: break-word; caret-color: rgb(55, 53, 47);">
|
|
19
|
+
d
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const CSS_CLASSES = {
|
|
2
|
+
btn: ['itf-button', 'btn'],
|
|
3
|
+
basic: ['btn-basic'],
|
|
4
|
+
primary: ['btn-primary'],
|
|
5
|
+
secondary: ['btn-secondary'],
|
|
6
|
+
large: ['btn-lg'],
|
|
7
|
+
small: ['btn-sm'],
|
|
8
|
+
block: ['itf-button__block'],
|
|
9
|
+
labeled: ['labeled'],
|
|
10
|
+
squircle: ['btn-squircle'],
|
|
11
|
+
icon: ['btn-icon'],
|
|
12
|
+
loading: ['loading'],
|
|
13
|
+
spinner: ['itf-spinner'],
|
|
14
|
+
loadingWhite: ['itf-spinner__white'],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export
|
|
18
|
+
class Button extends HTMLElement {
|
|
19
|
+
|
|
20
|
+
static get observedAttributes() {
|
|
21
|
+
return ['disabled', 'open'];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get isLoading() {
|
|
25
|
+
return this.hasAttribute('loading');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get styleClasses() {
|
|
29
|
+
let styles = [];
|
|
30
|
+
if (this.hasAttribute('color')) {
|
|
31
|
+
styles.push(`btn-${this.getAttribute('color')}`);
|
|
32
|
+
}
|
|
33
|
+
if (this.hasAttribute('block')) {
|
|
34
|
+
styles.push(CSS_CLASSES.block);
|
|
35
|
+
}
|
|
36
|
+
if (this.hasAttribute('labeled')) {
|
|
37
|
+
styles.push(CSS_CLASSES.labeled);
|
|
38
|
+
}
|
|
39
|
+
if (this.hasAttribute('squircle')) {
|
|
40
|
+
styles.push(CSS_CLASSES.squircle);
|
|
41
|
+
}
|
|
42
|
+
if (this.hasAttribute('icon')) {
|
|
43
|
+
styles.push(CSS_CLASSES.icon);
|
|
44
|
+
}
|
|
45
|
+
if (this.isLoading) {
|
|
46
|
+
styles.push(CSS_CLASSES.loading);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (this.hasAttribute('small')) {
|
|
50
|
+
styles = styles.concat(CSS_CLASSES.small);
|
|
51
|
+
} else if (this.hasAttribute('large')) {
|
|
52
|
+
styles = styles.concat(CSS_CLASSES.large);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (this.hasAttribute('primary')) {
|
|
56
|
+
styles = styles.concat(CSS_CLASSES.primary);
|
|
57
|
+
} else if (this.hasAttribute('secondary')) {
|
|
58
|
+
styles = styles.concat(CSS_CLASSES.secondary);
|
|
59
|
+
} else if (!this.hasAttribute('color')) {
|
|
60
|
+
styles = styles.concat(CSS_CLASSES.basic);
|
|
61
|
+
}
|
|
62
|
+
return styles;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get open() {
|
|
66
|
+
return this.hasAttribute('open');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get disabled() {
|
|
70
|
+
return this.hasAttribute('disabled');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
set disabled(val) {
|
|
74
|
+
if (val) {
|
|
75
|
+
this.setAttribute('tabindex', '-1');
|
|
76
|
+
this.setAttribute('disabled', '');
|
|
77
|
+
this.setAttribute('aria-disabled', 'true');
|
|
78
|
+
} else {
|
|
79
|
+
this.setAttribute('tabindex', '0');
|
|
80
|
+
this.setAttribute('aria-disabled', 'false');
|
|
81
|
+
this.removeAttribute('disabled');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
constructor() {
|
|
86
|
+
super();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
connectedCallback() {
|
|
90
|
+
const button = document.createElement('button');
|
|
91
|
+
|
|
92
|
+
const loadingText = this.getAttribute('loading-text');
|
|
93
|
+
const html = this.innerHTML;
|
|
94
|
+
this.replaceWith(button);
|
|
95
|
+
button.innerHTML = html;
|
|
96
|
+
button.classList.add(...CSS_CLASSES.btn);
|
|
97
|
+
button.classList.add(...this.styleClasses);
|
|
98
|
+
|
|
99
|
+
if (this.isLoading) {
|
|
100
|
+
button.setAttribute('disabled', 'disabled');
|
|
101
|
+
const loadingDiv = document.createElement('div');
|
|
102
|
+
const spinnerDiv = document.createElement('div');
|
|
103
|
+
spinnerDiv.classList.add(...CSS_CLASSES.spinner);
|
|
104
|
+
if (this.hasAttribute('primary') || this.hasAttribute('white')) {
|
|
105
|
+
spinnerDiv.classList.add(CSS_CLASSES.loadingWhite);
|
|
106
|
+
}
|
|
107
|
+
loadingDiv.appendChild(spinnerDiv);
|
|
108
|
+
// if (this.isLoading && loadingText) {
|
|
109
|
+
// const loadingTextDiv = document.createElement('div');
|
|
110
|
+
// loadingTextDiv.innerHTML = loadingText;
|
|
111
|
+
// loadingDiv.appendChild(loadingTextDiv);
|
|
112
|
+
// }
|
|
113
|
+
button.appendChild(loadingDiv);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -5,14 +5,18 @@ import itfLabel from '../form/Label.vue';
|
|
|
5
5
|
import itfDatePicker from '../datepicker/DatePicker.vue';
|
|
6
6
|
import itfDateRangePicker from '../datepicker/DateRangePicker.vue';
|
|
7
7
|
import itfApp from '../app/App.vue';
|
|
8
|
+
// import {Button} from './Button.js';
|
|
9
|
+
|
|
10
|
+
// window.customElements.define('itf-button', Button);
|
|
11
|
+
|
|
8
12
|
|
|
9
13
|
storiesOf('Common', module)
|
|
10
14
|
.add('Buttons', () => ({
|
|
11
15
|
components: {
|
|
16
|
+
itfButton,
|
|
12
17
|
itfApp,
|
|
13
18
|
itfForm,
|
|
14
19
|
itfLabel,
|
|
15
|
-
itfButton,
|
|
16
20
|
itfDatePicker,
|
|
17
21
|
itfDateRangePicker
|
|
18
22
|
},
|
|
@@ -62,7 +66,7 @@ storiesOf('Common', module)
|
|
|
62
66
|
|
|
63
67
|
<h3>Standart button</h3>
|
|
64
68
|
|
|
65
|
-
<itf-button primary>Primary button</itf-button>
|
|
69
|
+
<itf-button squircle primary>Primary button</itf-button>
|
|
66
70
|
<itf-button secondary>Secondary button</itf-button>
|
|
67
71
|
<itf-button>Basic button</itf-button>
|
|
68
72
|
<itf-button icon>
|
|
@@ -88,7 +92,7 @@ storiesOf('Common', module)
|
|
|
88
92
|
|
|
89
93
|
<h3>Large button</h3>
|
|
90
94
|
|
|
91
|
-
<itf-button large primary>Primary button</itf-button>
|
|
95
|
+
<itf-button squircle large primary>Primary button</itf-button>
|
|
92
96
|
<itf-button large secondary>Secondary button</itf-button>
|
|
93
97
|
<itf-button large>Basic button</itf-button>
|
|
94
98
|
<itf-button large icon>
|
|
@@ -103,12 +107,12 @@ storiesOf('Common', module)
|
|
|
103
107
|
<itf-button primary loading>Primary button</itf-button>
|
|
104
108
|
<itf-button secondary loading>Secondary button</itf-button>
|
|
105
109
|
<itf-button loading>Basic button</itf-button>
|
|
106
|
-
<itf-button primary loading small>Small button</itf-button>
|
|
110
|
+
<itf-button primary loading small loading-text="Loading...">Small button</itf-button>
|
|
107
111
|
<itf-button primary loading large>Large button</itf-button>
|
|
108
112
|
|
|
109
113
|
<h4>Test loading</h4>
|
|
110
|
-
|
|
111
|
-
<itf-button
|
|
114
|
+
{{isLoading}}
|
|
115
|
+
<itf-button onclick="testLoading" primary :loading.prop="isLoading" loading-text="Saving...">Click to test loading</itf-button>
|
|
112
116
|
|
|
113
117
|
</itf-app>
|
|
114
118
|
</div>`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
|
|
3
3
|
<div class="itf-checkbox form-check" :class="{ 'form-switch': this.switch, 'itf-checkbox__large': large, 'itf-checkbox__medium': medium }">
|
|
4
|
-
<input class="form-check-input" :id="id" type="checkbox" name="checkbox" v-model="isChecked" :disabled="isDisabled" />
|
|
4
|
+
<input class="form-check-input" ref="input" :id="id" type="checkbox" name="checkbox" v-model="isChecked" :disabled="isDisabled" />
|
|
5
5
|
<label :for="id" class="form-check-label">
|
|
6
6
|
<slot name="label">
|
|
7
7
|
{{label}}
|
|
@@ -60,5 +60,9 @@ class itfCheckbox extends Vue {
|
|
|
60
60
|
}
|
|
61
61
|
this.$emit('input', val);
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
get input() {
|
|
65
|
+
return this.$refs.input;
|
|
66
|
+
}
|
|
63
67
|
}
|
|
64
68
|
</script>
|
|
@@ -24,6 +24,7 @@ class itfDropdown extends Vue {
|
|
|
24
24
|
@Prop({ type: Boolean }) disabled;
|
|
25
25
|
@Prop({ type: Boolean }) text;
|
|
26
26
|
@Prop({ type: Boolean }) appendToBody;
|
|
27
|
+
@Prop({ type: Boolean }) appendToContext;
|
|
27
28
|
@Prop({ validator: (value) => [true, false, 'inside', 'outside'].includes(value), default: true }) autoclose;
|
|
28
29
|
@Prop({ type: Object, default: () => ({}) }) buttonOptions;
|
|
29
30
|
@Prop({ type: Object, default: () => ({}) }) menuOptions;
|
|
@@ -33,22 +34,23 @@ class itfDropdown extends Vue {
|
|
|
33
34
|
render (createElement, context) {
|
|
34
35
|
const { props, slots, data } = context;
|
|
35
36
|
const modalId = `dropdownId${globalModalIndex++}`;
|
|
36
|
-
const { buttonOptions, toggle, text,
|
|
37
|
+
const { buttonOptions, toggle, text, disabled, label, appendToBody } = props;
|
|
37
38
|
const { button, default: defaultSlot } = slots();
|
|
38
39
|
let elements = [
|
|
39
40
|
createElement(
|
|
40
41
|
text ? 'div' : itfButton,
|
|
41
42
|
{
|
|
43
|
+
staticClass: data.staticClass || '',
|
|
42
44
|
props: buttonOptions || {},
|
|
43
45
|
class: { 'dropdown-toggle': toggle },
|
|
44
|
-
attrs: { id: modalId, 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false' },
|
|
45
|
-
ref: 'toggle',
|
|
46
|
+
attrs: { id: modalId, 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false', ...(data.attrs || {}) },
|
|
46
47
|
},
|
|
47
48
|
button || label
|
|
48
49
|
),
|
|
49
|
-
createElement(
|
|
50
|
+
disabled ? null : createElement(
|
|
50
51
|
itfDropdownMenu,
|
|
51
52
|
{
|
|
53
|
+
ref: data.ref,
|
|
52
54
|
props: { ...props, toggleId: modalId },
|
|
53
55
|
},
|
|
54
56
|
defaultSlot
|
|
@@ -22,6 +22,7 @@ class itfDropdownMenu extends Vue {
|
|
|
22
22
|
@Prop({ type: Boolean }) disabled;
|
|
23
23
|
@Prop({ type: Boolean }) text;
|
|
24
24
|
@Prop({ type: Boolean }) appendToBody;
|
|
25
|
+
@Prop({ type: Boolean }) appendToContext;
|
|
25
26
|
@Prop({ type: String }) toggleId;
|
|
26
27
|
@Prop({ validator: (value) => [true, false, 'inside', 'outside'].includes(value), default: true }) autoclose;
|
|
27
28
|
@Prop({ type: Object, default: () => ({}) }) buttonOptions;
|
|
@@ -39,10 +40,14 @@ class itfDropdownMenu extends Vue {
|
|
|
39
40
|
const { default: Dropdown } = await import('bootstrap/js/src/dropdown.js');
|
|
40
41
|
let context = document.body;
|
|
41
42
|
this.modalEl = new Dropdown(toggle, {
|
|
42
|
-
reference: '
|
|
43
|
+
reference: 'parent',
|
|
43
44
|
autoClose: this.autoclose
|
|
44
45
|
});
|
|
45
|
-
if (this.
|
|
46
|
+
if (this.appendToContext && this.$el instanceof Node && this.$el.parentNode) {
|
|
47
|
+
context = this.$el.closest('.itf-append-context') || document.body;
|
|
48
|
+
this.$el.parentNode.removeChild(this.$el);
|
|
49
|
+
context.appendChild(this.$el); // should append only to body
|
|
50
|
+
} else if (this.appendToBody && this.$el instanceof Node && this.$el.parentNode) {
|
|
46
51
|
this.$el.parentNode.removeChild(this.$el);
|
|
47
52
|
context.appendChild(this.$el); // should append only to body
|
|
48
53
|
}
|
|
@@ -57,6 +62,13 @@ class itfDropdownMenu extends Vue {
|
|
|
57
62
|
});
|
|
58
63
|
}
|
|
59
64
|
|
|
65
|
+
beforeDestroy() {
|
|
66
|
+
if (this.modalEl) {
|
|
67
|
+
this.modalEl.hide();
|
|
68
|
+
this.modalEl.dispose();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
60
72
|
show() {
|
|
61
73
|
if (this.modalEl) {
|
|
62
74
|
this.modalEl.show();
|
|
@@ -1,34 +1,39 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
|
|
3
|
-
<div class="scrollable scrollable-x big-scrollbar">
|
|
4
|
-
<
|
|
5
|
-
<
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
3
|
+
<div class="scrollable scrollable-x big-scrollbar" :class="{'permanent-checkboxes': selectedIds.length}">
|
|
4
|
+
<itf-checkbox-group v-model="selectedIds">
|
|
5
|
+
<template v-for="(group, index) in groups">
|
|
6
|
+
<div class="table-view-body">
|
|
7
|
+
<itf-table-group
|
|
8
|
+
:key="index"
|
|
9
|
+
@update="$emit('update', { ...$event, group, groupIndex: index })"
|
|
10
|
+
:id-property="idProperty"
|
|
11
|
+
:columns="columns"
|
|
12
|
+
@update:columns="onColumnsUpdate"
|
|
13
|
+
:rows="group.rows"
|
|
14
|
+
:title="group.name"
|
|
15
|
+
:selected-ids.sync="selectedIds"
|
|
16
|
+
:add-new-rows="addNewRows"
|
|
17
|
+
:column-sorting="columnSorting"
|
|
18
|
+
:column-resizing="columnResizing"
|
|
19
|
+
:show-grouping="showGrouping"
|
|
20
|
+
:show-summary="showSummary"
|
|
21
|
+
:show-add-column="showAddColumn"
|
|
22
|
+
:show-header="!noHeader"
|
|
23
|
+
:schema="schema"
|
|
24
|
+
@new="$emit('new', $event)"
|
|
25
|
+
@add-column="$emit('add-column', $event)"
|
|
26
|
+
>
|
|
27
|
+
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
28
|
+
<slot :name="name" v-bind="slotData || {}" />
|
|
29
|
+
</template>
|
|
30
|
+
<template v-for="(_, name) in $scopedSlots" #[name]="slotData">
|
|
31
|
+
<slot :name="name" v-bind="slotData || {}" />
|
|
32
|
+
</template>
|
|
33
|
+
</itf-table-group>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
36
|
+
</itf-checkbox-group>
|
|
32
37
|
</div>
|
|
33
38
|
|
|
34
39
|
</template>
|
|
@@ -65,15 +70,22 @@
|
|
|
65
70
|
}
|
|
66
71
|
</style>
|
|
67
72
|
<script>
|
|
68
|
-
import { Vue, Component, Prop,
|
|
73
|
+
import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
|
|
74
|
+
import itfCheckboxGroup from '../checkbox/CheckboxGroup.vue';
|
|
69
75
|
import itfButton from '../button/Button.vue';
|
|
70
76
|
import itfIcon from '../icon/Icon.vue';
|
|
71
77
|
import itfTableGroup from './TableGroup.vue';
|
|
72
78
|
import itfTableHeader from './TableHeader.vue';
|
|
79
|
+
import itfTableBody from "@/components/table/TableBody.vue";
|
|
73
80
|
|
|
74
81
|
export default @Component({
|
|
75
82
|
name: 'itfTable2',
|
|
83
|
+
provide() {
|
|
84
|
+
return { tableEl: this }; // do not use Provide from vue-property-decorator
|
|
85
|
+
},
|
|
76
86
|
components: {
|
|
87
|
+
itfTableBody,
|
|
88
|
+
itfCheckboxGroup,
|
|
77
89
|
itfTableHeader,
|
|
78
90
|
itfButton,
|
|
79
91
|
itfIcon,
|
|
@@ -81,16 +93,72 @@ export default @Component({
|
|
|
81
93
|
}
|
|
82
94
|
})
|
|
83
95
|
class itfTable2 extends Vue {
|
|
84
|
-
@Prop({ required: true, type: Array }) columns;
|
|
96
|
+
// @Prop({ required: true, type: Array }) columns;
|
|
85
97
|
@Prop({ required: true, type: Array }) rows;
|
|
86
|
-
@Prop({ type: Number, default: 40 }) rowHeight;
|
|
87
98
|
@Prop({ type: String, default: null }) groupBy;
|
|
99
|
+
@Prop({ type: String, default: 'Id' }) idProperty;
|
|
100
|
+
@Prop({ type: String, default: null }) stateName; // save state to storage
|
|
101
|
+
@Prop({ type: Object, default: () => ({}) }) schema;
|
|
88
102
|
@Prop(Boolean) addNewRows;
|
|
89
103
|
@Prop(Boolean) columnSorting;
|
|
90
104
|
@Prop(Boolean) columnResizing;
|
|
91
105
|
@Prop(Boolean) showAddColumn;
|
|
92
106
|
@Prop(Boolean) showGrouping;
|
|
93
107
|
@Prop(Boolean) showSummary;
|
|
108
|
+
@Prop(Boolean) noHeader;
|
|
109
|
+
|
|
110
|
+
state = {
|
|
111
|
+
selectedIds: [],
|
|
112
|
+
columns: []
|
|
113
|
+
};
|
|
114
|
+
selectedIds = [];
|
|
115
|
+
|
|
116
|
+
getTableState() {
|
|
117
|
+
const list = this.schema?.properties || [];
|
|
118
|
+
let state = this.stateName ? JSON.parse(localStorage.getItem(this.stateKey) || 'null') : null;
|
|
119
|
+
if (!state) {
|
|
120
|
+
state = {
|
|
121
|
+
selectedIds: [],
|
|
122
|
+
columns: [...list]
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
state.selectedIds = [];
|
|
126
|
+
for (const column of list) {
|
|
127
|
+
const stateColumn = state.columns.find(i => i.property === column.property);
|
|
128
|
+
if (stateColumn) {
|
|
129
|
+
Object.assign(stateColumn, column);
|
|
130
|
+
} else {
|
|
131
|
+
state.columns.push(column);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
for (const column of state.columns) {
|
|
135
|
+
const originColumn = list.find(i => i.property === column.property);
|
|
136
|
+
if (!originColumn) {
|
|
137
|
+
state.columns = state.columns.filter(i => i.property !== column.property);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return state;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
get stateKey() {
|
|
144
|
+
return this.stateName ? `itf-table-${this.stateName}` : null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
saveTableState() {
|
|
148
|
+
if (!this.stateName) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
localStorage.setItem(this.stateKey, JSON.stringify(this.state));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
mounted() {
|
|
155
|
+
this.state = this.getTableState();
|
|
156
|
+
this.selectedIds = this.state.selectedIds;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get columns() {
|
|
160
|
+
return this.state?.columns || [];
|
|
161
|
+
}
|
|
94
162
|
|
|
95
163
|
get groups() {
|
|
96
164
|
const { groupBy, rows } = this;
|
|
@@ -108,8 +176,18 @@ class itfTable2 extends Vue {
|
|
|
108
176
|
return Object.entries(groups).map(([name, rows]) => ({ name, rows }));
|
|
109
177
|
}
|
|
110
178
|
|
|
179
|
+
@Watch('selectedIds')
|
|
180
|
+
onSelectedIdsUpdate(selectedIds) {
|
|
181
|
+
this.state.selectedIds = selectedIds;
|
|
182
|
+
this.saveTableState();
|
|
183
|
+
}
|
|
184
|
+
|
|
111
185
|
onColumnsUpdate(columns) {
|
|
112
|
-
|
|
186
|
+
const pinned = [...columns.filter(i => i.pinned)];
|
|
187
|
+
const unpinned = [...columns.filter(i => !i.pinned)];
|
|
188
|
+
this.state.columns = [...pinned, ...unpinned].map((item, key) => ({ ...item, index: key }));
|
|
189
|
+
this.$emit('update:columns', this.state.columns);
|
|
190
|
+
this.saveTableState();
|
|
113
191
|
}
|
|
114
192
|
}
|
|
115
193
|
</script>
|