@webitel/ui-datalist 1.1.65 → 1.1.67
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/modules/filters/__tests__/createTableFiltersStore.spec.ts +143 -0
- package/src/modules/filters/createTableFiltersStore.ts +23 -5
- package/src/modules/filters/modules/filterConfig/components/contact-group/contact-group-filter-value-field.vue +40 -25
- package/src/modules/headers/__tests__/createTableHeadersStore.spec.ts +169 -0
- package/src/modules/headers/createTableHeadersStore.ts +26 -7
- package/src/modules/pagination/__tests__/createTablePaginationStore.spec.ts +134 -0
- package/src/modules/pagination/createTablePaginationStore.ts +32 -4
- package/src/modules/persist/PersistedStorage.types.ts +14 -0
- package/src/modules/persist/__tests__/useLocalStoragePersistedStorage.spec.ts +66 -0
- package/src/modules/persist/__tests__/usePersistedStorage.spec.ts +357 -0
- package/src/modules/persist/__tests__/useRoutePersistedStorage.spec.ts +145 -0
- package/src/modules/persist/usePersistedStorage.ts +93 -60
- package/src/modules/persist/useRoutePersistedStorage.ts +40 -18
- package/src/modules/table/createTableStore.store.ts +37 -0
- package/types/.tsbuildinfo +1 -1
- package/types/modules/filter-presets/stores/createFilterPresetsStore.d.ts +1 -0
- package/types/modules/filters/createTableFiltersStore.d.ts +2 -0
- package/types/modules/filters/modules/filterConfig/components/contact-group/contact-group-filter-value-field.vue.d.ts +4 -4
- package/types/modules/headers/createTableHeadersStore.d.ts +2 -0
- package/types/modules/pagination/createTablePaginationStore.d.ts +2 -0
- package/types/modules/permissions-page/stores/createPermissionsStore.d.ts +2 -0
- package/types/modules/persist/PersistedStorage.types.d.ts +13 -0
- package/types/modules/table/createTableStore.store.d.ts +2 -0
package/package.json
CHANGED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { createApp } from 'vue';
|
|
3
|
+
import { createMemoryHistory, createRouter, type Router } from 'vue-router';
|
|
4
|
+
|
|
5
|
+
import { tableFiltersStoreBody } from '../createTableFiltersStore';
|
|
6
|
+
|
|
7
|
+
const routes = [
|
|
8
|
+
{
|
|
9
|
+
path: '/cases',
|
|
10
|
+
name: 'cases',
|
|
11
|
+
component: {
|
|
12
|
+
template: '<div />',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const namespace = 'cases';
|
|
18
|
+
|
|
19
|
+
describe('tableFiltersStoreBody', () => {
|
|
20
|
+
let router: Router;
|
|
21
|
+
let runWithRouter: <T>(fn: () => T) => T;
|
|
22
|
+
|
|
23
|
+
beforeEach(async () => {
|
|
24
|
+
localStorage.clear();
|
|
25
|
+
|
|
26
|
+
router = createRouter({
|
|
27
|
+
history: createMemoryHistory(),
|
|
28
|
+
routes,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const app = createApp({});
|
|
32
|
+
app.use(router);
|
|
33
|
+
|
|
34
|
+
await router.push('/cases');
|
|
35
|
+
await router.isReady();
|
|
36
|
+
|
|
37
|
+
runWithRouter = (fn) => app.runWithContext(fn);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const setUpStore = async () => {
|
|
41
|
+
const store = tableFiltersStoreBody(namespace);
|
|
42
|
+
await runWithRouter(() => store.setupPersistence());
|
|
43
|
+
return store;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
it('starts with no filters', () => {
|
|
47
|
+
const store = tableFiltersStoreBody(namespace);
|
|
48
|
+
|
|
49
|
+
expect(store.filtersList.value).toEqual([]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('adds, updates and deletes a filter', () => {
|
|
53
|
+
const store = tableFiltersStoreBody(namespace);
|
|
54
|
+
|
|
55
|
+
store.addFilter({
|
|
56
|
+
name: 'status',
|
|
57
|
+
value: 'open',
|
|
58
|
+
});
|
|
59
|
+
expect(store.hasFilter('status')).toBe(true);
|
|
60
|
+
|
|
61
|
+
store.updateFilter({
|
|
62
|
+
name: 'status',
|
|
63
|
+
value: 'closed',
|
|
64
|
+
});
|
|
65
|
+
expect(store.filtersManager.getFilter('status')?.value).toBe('closed');
|
|
66
|
+
|
|
67
|
+
store.deleteFilter({
|
|
68
|
+
name: 'status',
|
|
69
|
+
});
|
|
70
|
+
expect(store.hasFilter('status')).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('keeps searchMode', () => {
|
|
74
|
+
const store = tableFiltersStoreBody(namespace);
|
|
75
|
+
|
|
76
|
+
store.updateSearchMode('subject');
|
|
77
|
+
|
|
78
|
+
expect(store.searchMode.value).toBe('subject');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('persistence', () => {
|
|
82
|
+
it('restores filters from the route query', async () => {
|
|
83
|
+
await router.push({
|
|
84
|
+
name: 'cases',
|
|
85
|
+
query: {
|
|
86
|
+
filters: JSON.stringify({
|
|
87
|
+
status_val: 'open',
|
|
88
|
+
}),
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const store = await setUpStore();
|
|
93
|
+
|
|
94
|
+
expect(store.filtersManager.getFilter('status')?.value).toBe('open');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('writes an added filter into the route query', async () => {
|
|
98
|
+
const store = await setUpStore();
|
|
99
|
+
|
|
100
|
+
store.addFilter({
|
|
101
|
+
name: 'status',
|
|
102
|
+
value: 'open',
|
|
103
|
+
});
|
|
104
|
+
await new Promise((resolve) => setTimeout(resolve));
|
|
105
|
+
|
|
106
|
+
expect(router.currentRoute.value.query.filters).toContain('open');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('keeps searchMode out of the route query', async () => {
|
|
110
|
+
const store = await setUpStore();
|
|
111
|
+
|
|
112
|
+
store.updateSearchMode('subject');
|
|
113
|
+
await new Promise((resolve) => setTimeout(resolve));
|
|
114
|
+
|
|
115
|
+
expect(router.currentRoute.value.query.searchMode).toBeUndefined();
|
|
116
|
+
expect(localStorage.getItem(`${namespace}/searchMode`)).toBe('subject');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('syncPersistence', () => {
|
|
121
|
+
it('publishes the applied filters', async () => {
|
|
122
|
+
const store = await setUpStore();
|
|
123
|
+
store.addFilter({
|
|
124
|
+
name: 'status',
|
|
125
|
+
value: 'open',
|
|
126
|
+
});
|
|
127
|
+
await new Promise((resolve) => setTimeout(resolve));
|
|
128
|
+
await router.push('/cases');
|
|
129
|
+
|
|
130
|
+
await runWithRouter(() => store.syncPersistence());
|
|
131
|
+
|
|
132
|
+
expect(router.currentRoute.value.query.filters).toContain('open');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('publishes nothing while no filter is applied', async () => {
|
|
136
|
+
const store = await setUpStore();
|
|
137
|
+
|
|
138
|
+
await runWithRouter(() => store.syncPersistence());
|
|
139
|
+
|
|
140
|
+
expect(router.currentRoute.value.query).toEqual({});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { computed, reactive, ref } from 'vue';
|
|
2
2
|
|
|
3
3
|
import { createDatalistStore } from '../_shared/createDatalistStore';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
type PersistedStorageController,
|
|
6
|
+
PersistedStorageType,
|
|
7
|
+
} from '../persist/PersistedStorage.types';
|
|
5
8
|
import { usePersistedStorage } from '../persist/usePersistedStorage';
|
|
6
9
|
import type { Identifiable } from '../types/createDatalistStore.types';
|
|
7
10
|
import type { useTableStoreConfig } from '../types/tableStore.types';
|
|
@@ -40,8 +43,10 @@ export const tableFiltersStoreBody = (
|
|
|
40
43
|
|
|
41
44
|
const filtersList = computed(() => filtersManager.getFiltersList());
|
|
42
45
|
|
|
46
|
+
let persistedStorageControllers: PersistedStorageController[] = [];
|
|
47
|
+
|
|
43
48
|
const setupPersistence = () => {
|
|
44
|
-
const
|
|
49
|
+
const filtersStorage = usePersistedStorage({
|
|
45
50
|
name: 'filters',
|
|
46
51
|
|
|
47
52
|
value: computed(
|
|
@@ -75,7 +80,7 @@ export const tableFiltersStoreBody = (
|
|
|
75
80
|
},
|
|
76
81
|
});
|
|
77
82
|
|
|
78
|
-
const
|
|
83
|
+
const searchModeStorage = usePersistedStorage({
|
|
79
84
|
name: 'searchMode',
|
|
80
85
|
value: searchMode,
|
|
81
86
|
storages: [
|
|
@@ -95,12 +100,24 @@ export const tableFiltersStoreBody = (
|
|
|
95
100
|
},
|
|
96
101
|
});
|
|
97
102
|
|
|
103
|
+
persistedStorageControllers = [
|
|
104
|
+
filtersStorage,
|
|
105
|
+
searchModeStorage,
|
|
106
|
+
];
|
|
107
|
+
|
|
98
108
|
return Promise.all([
|
|
99
|
-
|
|
100
|
-
|
|
109
|
+
filtersStorage.restore(),
|
|
110
|
+
searchModeStorage.restore(),
|
|
101
111
|
]);
|
|
102
112
|
};
|
|
103
113
|
|
|
114
|
+
/* sequentially: every route write is a router.replace() on top of the current query */
|
|
115
|
+
const syncPersistence = async () => {
|
|
116
|
+
for (const controller of persistedStorageControllers) {
|
|
117
|
+
await controller.sync();
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
104
121
|
return {
|
|
105
122
|
filtersManager,
|
|
106
123
|
isRestoring,
|
|
@@ -116,6 +133,7 @@ export const tableFiltersStoreBody = (
|
|
|
116
133
|
updateSearchMode,
|
|
117
134
|
|
|
118
135
|
setupPersistence,
|
|
136
|
+
syncPersistence,
|
|
119
137
|
};
|
|
120
138
|
};
|
|
121
139
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
:label="labelValue"
|
|
4
4
|
:search-method="props.filterConfig.searchRecords"
|
|
5
5
|
:v="!disableValidation && vList"
|
|
6
|
-
:model-value="
|
|
6
|
+
:model-value="value.list"
|
|
7
7
|
data-key="id"
|
|
8
8
|
option-value="id"
|
|
9
9
|
v-bind="$attrs"
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
<wt-checkbox
|
|
13
13
|
v-if="!props.filterConfig?.hideUnassigned"
|
|
14
14
|
:label="t('reusable.showUnassigned')"
|
|
15
|
-
:selected="!!
|
|
15
|
+
:selected="!!value.unassigned"
|
|
16
16
|
:v="!disableValidation && vUnassigned"
|
|
17
|
-
@update:selected="
|
|
17
|
+
@update:selected="handleInput('unassigned', !!$event)"
|
|
18
18
|
/>
|
|
19
19
|
</template>
|
|
20
20
|
|
|
@@ -27,12 +27,6 @@ import { useI18n } from 'vue-i18n';
|
|
|
27
27
|
|
|
28
28
|
import { IContactGroupFilterConfig } from './index';
|
|
29
29
|
|
|
30
|
-
const props = defineProps<{
|
|
31
|
-
filterConfig: IContactGroupFilterConfig;
|
|
32
|
-
disableValidation?: boolean;
|
|
33
|
-
hideLabel?: boolean;
|
|
34
|
-
}>();
|
|
35
|
-
|
|
36
30
|
type ModelValue = {
|
|
37
31
|
list?: string[];
|
|
38
32
|
unassigned?: boolean | null;
|
|
@@ -45,39 +39,62 @@ const model = defineModel<ModelValue>({
|
|
|
45
39
|
}),
|
|
46
40
|
});
|
|
47
41
|
|
|
42
|
+
const value = computed<ModelValue>(
|
|
43
|
+
() =>
|
|
44
|
+
model.value ?? {
|
|
45
|
+
list: [],
|
|
46
|
+
unassigned: null,
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const handleInput = <K extends keyof ModelValue>(
|
|
51
|
+
key: K,
|
|
52
|
+
newFieldValue: ModelValue[K],
|
|
53
|
+
) => {
|
|
54
|
+
model.value = {
|
|
55
|
+
...value.value,
|
|
56
|
+
[key]: newFieldValue,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const changeListValue = (event: string[]) => {
|
|
61
|
+
if (!event.length && !value.value.unassigned) {
|
|
62
|
+
model.value = {};
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
handleInput('list', event);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const props = defineProps<{
|
|
69
|
+
filterConfig: IContactGroupFilterConfig;
|
|
70
|
+
disableValidation?: boolean;
|
|
71
|
+
hideLabel?: boolean;
|
|
72
|
+
}>();
|
|
73
|
+
|
|
48
74
|
const emit = defineEmits<{
|
|
49
75
|
'update:invalid': [
|
|
50
76
|
boolean,
|
|
51
77
|
];
|
|
52
78
|
}>();
|
|
79
|
+
|
|
53
80
|
const { t } = useI18n();
|
|
54
81
|
|
|
55
82
|
const labelValue = computed(() =>
|
|
56
83
|
props?.hideLabel ? undefined : t('webitelUI.filters.filterValue'),
|
|
57
84
|
);
|
|
58
85
|
|
|
59
|
-
const changeListValue = (event: string[]) => {
|
|
60
|
-
if (!event.length && !model.value.unassigned) {
|
|
61
|
-
model.value = {};
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
model.value = {
|
|
65
|
-
...model.value,
|
|
66
|
-
list: event,
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
86
|
const v$ = useVuelidate<{
|
|
70
87
|
model: ModelValue;
|
|
71
88
|
}>(
|
|
72
89
|
computed(() => ({
|
|
73
90
|
model: {
|
|
74
91
|
list: {
|
|
75
|
-
required: requiredIf(() => !
|
|
92
|
+
required: requiredIf(() => !value.value.unassigned),
|
|
76
93
|
},
|
|
77
94
|
unassigned: {
|
|
78
95
|
required: requiredIf(
|
|
79
96
|
() =>
|
|
80
|
-
!!props.filterConfig?.hideUnassigned && !
|
|
97
|
+
!!props.filterConfig?.hideUnassigned && !value.value.list?.length,
|
|
81
98
|
),
|
|
82
99
|
},
|
|
83
100
|
},
|
|
@@ -106,11 +123,9 @@ onMounted(() => {
|
|
|
106
123
|
});
|
|
107
124
|
|
|
108
125
|
watch(
|
|
109
|
-
() => v
|
|
126
|
+
() => v$.value.$invalid,
|
|
110
127
|
(invalid) => {
|
|
111
|
-
|
|
112
|
-
emit('update:invalid', invalid);
|
|
113
|
-
}
|
|
128
|
+
emit('update:invalid', invalid);
|
|
114
129
|
},
|
|
115
130
|
{
|
|
116
131
|
immediate: true,
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { createApp } from 'vue';
|
|
3
|
+
import { createMemoryHistory, createRouter, type Router } from 'vue-router';
|
|
4
|
+
|
|
5
|
+
import type { DatalistTableHeader } from '../../types/tableStore.types';
|
|
6
|
+
import { tableHeadersStoreBody } from '../createTableHeadersStore';
|
|
7
|
+
|
|
8
|
+
const routes = [
|
|
9
|
+
{
|
|
10
|
+
path: '/cases',
|
|
11
|
+
name: 'cases',
|
|
12
|
+
component: {
|
|
13
|
+
template: '<div />',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const id = 'cases/headers';
|
|
19
|
+
|
|
20
|
+
const rawHeaders = [
|
|
21
|
+
{
|
|
22
|
+
field: 'name',
|
|
23
|
+
show: true,
|
|
24
|
+
sort: null,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
field: 'subject',
|
|
28
|
+
show: true,
|
|
29
|
+
sort: null,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
field: 'createdAt',
|
|
33
|
+
show: false,
|
|
34
|
+
sort: null,
|
|
35
|
+
},
|
|
36
|
+
] as DatalistTableHeader[];
|
|
37
|
+
|
|
38
|
+
/* route writes are queued, so several ticks are needed for all of them to land */
|
|
39
|
+
const flushWrites = async () => {
|
|
40
|
+
for (let i = 0; i < 5; i += 1) {
|
|
41
|
+
await new Promise((resolve) => setTimeout(resolve));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const createStore = () =>
|
|
46
|
+
tableHeadersStoreBody({
|
|
47
|
+
rawHeaders: rawHeaders.map((header) => ({
|
|
48
|
+
...header,
|
|
49
|
+
})),
|
|
50
|
+
id,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('tableHeadersStoreBody', () => {
|
|
54
|
+
let router: Router;
|
|
55
|
+
let runWithRouter: <T>(fn: () => T) => T;
|
|
56
|
+
|
|
57
|
+
beforeEach(async () => {
|
|
58
|
+
localStorage.clear();
|
|
59
|
+
|
|
60
|
+
router = createRouter({
|
|
61
|
+
history: createMemoryHistory(),
|
|
62
|
+
routes,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const app = createApp({});
|
|
66
|
+
app.use(router);
|
|
67
|
+
|
|
68
|
+
await router.push('/cases');
|
|
69
|
+
await router.isReady();
|
|
70
|
+
|
|
71
|
+
runWithRouter = (fn) => app.runWithContext(fn);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const setUpStore = async () => {
|
|
75
|
+
const store = createStore();
|
|
76
|
+
await runWithRouter(() => store.setupPersistence());
|
|
77
|
+
return store;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
it('exposes the shown headers and their fields', () => {
|
|
81
|
+
const store = createStore();
|
|
82
|
+
|
|
83
|
+
expect(store.shownHeaders.value.map(({ field }) => field)).toEqual([
|
|
84
|
+
'name',
|
|
85
|
+
'subject',
|
|
86
|
+
]);
|
|
87
|
+
expect(store.fields.value).toEqual([
|
|
88
|
+
'name',
|
|
89
|
+
'subject',
|
|
90
|
+
]);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('has no sort by default', () => {
|
|
94
|
+
expect(createStore().sort.value).toBeNull();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('encodes the sorted column into a sort query', () => {
|
|
98
|
+
const store = createStore();
|
|
99
|
+
|
|
100
|
+
store.updateSort(store.headers.value[0], 'desc');
|
|
101
|
+
|
|
102
|
+
expect(store.sort.value).toBe('-name');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('collects the widths of resized columns', () => {
|
|
106
|
+
const store = createStore();
|
|
107
|
+
|
|
108
|
+
store.columnResize({
|
|
109
|
+
columnName: 'name',
|
|
110
|
+
columnWidth: '100px',
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(store.columnWidths.value).toEqual({
|
|
114
|
+
name: '100px',
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('persistence', () => {
|
|
119
|
+
it('restores shown fields from the route query', async () => {
|
|
120
|
+
await router.push({
|
|
121
|
+
name: 'cases',
|
|
122
|
+
query: {
|
|
123
|
+
fields: 'createdAt',
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const store = await setUpStore();
|
|
128
|
+
|
|
129
|
+
expect(store.fields.value).toEqual([
|
|
130
|
+
'createdAt',
|
|
131
|
+
]);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('writes a changed sort into the route query', async () => {
|
|
135
|
+
const store = await setUpStore();
|
|
136
|
+
|
|
137
|
+
store.updateSort(store.headers.value[0], 'asc');
|
|
138
|
+
await flushWrites();
|
|
139
|
+
|
|
140
|
+
expect(router.currentRoute.value.query.sort).toBe('+name');
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe('syncPersistence', () => {
|
|
145
|
+
it('publishes a customized column set', async () => {
|
|
146
|
+
const store = await setUpStore();
|
|
147
|
+
store.updateShownHeaders(
|
|
148
|
+
store.headers.value.map((header) => ({
|
|
149
|
+
...header,
|
|
150
|
+
show: header.field === 'name',
|
|
151
|
+
})),
|
|
152
|
+
);
|
|
153
|
+
await flushWrites();
|
|
154
|
+
await router.push('/cases');
|
|
155
|
+
|
|
156
|
+
await runWithRouter(() => store.syncPersistence());
|
|
157
|
+
|
|
158
|
+
expect(router.currentRoute.value.query.fields).toBe('name');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('publishes nothing while the columns are still default', async () => {
|
|
162
|
+
const store = await setUpStore();
|
|
163
|
+
|
|
164
|
+
await runWithRouter(() => store.syncPersistence());
|
|
165
|
+
|
|
166
|
+
expect(router.currentRoute.value.query).toEqual({});
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
});
|
|
@@ -4,7 +4,10 @@ import { SortSymbols } from '@webitel/ui-sdk/scripts/sortQueryAdapters';
|
|
|
4
4
|
import { computed, nextTick, ref } from 'vue';
|
|
5
5
|
|
|
6
6
|
import { createDatalistStore } from '../_shared/createDatalistStore';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
type PersistedStorageController,
|
|
9
|
+
PersistedStorageType,
|
|
10
|
+
} from '../persist/PersistedStorage.types';
|
|
8
11
|
import { usePersistedStorage } from '../persist/usePersistedStorage';
|
|
9
12
|
import type { Identifiable } from '../types/createDatalistStore.types';
|
|
10
13
|
import type {
|
|
@@ -223,8 +226,10 @@ export const tableHeadersStoreBody = ({
|
|
|
223
226
|
});
|
|
224
227
|
};
|
|
225
228
|
|
|
229
|
+
let persistedStorageControllers: PersistedStorageController[] = [];
|
|
230
|
+
|
|
226
231
|
const setupPersistence = async () => {
|
|
227
|
-
const
|
|
232
|
+
const fieldsStorage = usePersistedStorage({
|
|
228
233
|
name: 'fields',
|
|
229
234
|
value: fields,
|
|
230
235
|
storages: [
|
|
@@ -247,12 +252,12 @@ export const tableHeadersStoreBody = ({
|
|
|
247
252
|
},
|
|
248
253
|
});
|
|
249
254
|
|
|
250
|
-
const
|
|
255
|
+
const sortStorage = usePersistedStorage({
|
|
251
256
|
name: 'sort',
|
|
252
257
|
value: sort,
|
|
253
258
|
});
|
|
254
259
|
|
|
255
|
-
const
|
|
260
|
+
const columnWidthsStorage = usePersistedStorage({
|
|
256
261
|
name: 'columnWidths',
|
|
257
262
|
value: columnWidths,
|
|
258
263
|
storages: [
|
|
@@ -278,13 +283,26 @@ export const tableHeadersStoreBody = ({
|
|
|
278
283
|
},
|
|
279
284
|
});
|
|
280
285
|
|
|
286
|
+
persistedStorageControllers = [
|
|
287
|
+
fieldsStorage,
|
|
288
|
+
sortStorage,
|
|
289
|
+
columnWidthsStorage,
|
|
290
|
+
];
|
|
291
|
+
|
|
281
292
|
return Promise.allSettled([
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
293
|
+
fieldsStorage.restore(),
|
|
294
|
+
sortStorage.restore(),
|
|
295
|
+
columnWidthsStorage.restore(),
|
|
285
296
|
]);
|
|
286
297
|
};
|
|
287
298
|
|
|
299
|
+
/* sequentially: every route write is a router.replace() on top of the current query */
|
|
300
|
+
const syncPersistence = async () => {
|
|
301
|
+
for (const controller of persistedStorageControllers) {
|
|
302
|
+
await controller.sync();
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
288
306
|
const getHeaderByField = (field: string) => {
|
|
289
307
|
return headers.value.find((header) => header.field === field);
|
|
290
308
|
};
|
|
@@ -334,6 +352,7 @@ export const tableHeadersStoreBody = ({
|
|
|
334
352
|
columnReorder,
|
|
335
353
|
|
|
336
354
|
setupPersistence,
|
|
355
|
+
syncPersistence,
|
|
337
356
|
$reset,
|
|
338
357
|
};
|
|
339
358
|
};
|