@webitel/ui-datalist 26.8.2 → 26.8.4
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/card/composables/__tests__/useCardRouting.spec.ts +146 -0
- package/src/modules/card/composables/useCardRouting.ts +12 -6
- package/src/modules/card/composables/useNestedCardComponent.ts +8 -5
- package/src/modules/card/stores/createCardStore.ts +1 -1
- package/src/modules/table/__tests__/createTableStore.spec.ts +186 -0
- package/src/modules/table/createTableStore.store.ts +55 -39
- package/types/.tsbuildinfo +1 -1
- package/types/modules/card/composables/useCardRouting.d.ts +10 -6
- package/types/modules/card/composables/useNestedCardComponent.d.ts +6 -2
- package/types/modules/card/stores/createCardStore.d.ts +10 -10
- package/types/modules/filters/modules/filterConfig/components/case-service/config.d.ts +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { effectScope, nextTick, type Ref, reactive, ref } from 'vue';
|
|
3
|
+
|
|
4
|
+
import type { CardItemId } from '../../types/CardStore.types';
|
|
5
|
+
import { useCardRouting } from '../useCardRouting';
|
|
6
|
+
|
|
7
|
+
const mocks = vi.hoisted(() => ({
|
|
8
|
+
route: {
|
|
9
|
+
params: {},
|
|
10
|
+
} as {
|
|
11
|
+
params: Record<string, string>;
|
|
12
|
+
},
|
|
13
|
+
replace: vi.fn(),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
vi.mock('vue-router', () => ({
|
|
17
|
+
useRoute: () => mocks.route,
|
|
18
|
+
useRouter: () => ({
|
|
19
|
+
replace: mocks.replace,
|
|
20
|
+
}),
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A nested card lives inside its parent's card page, so the parent can be
|
|
25
|
+
* created underneath it: `route.params.id` goes from `'new'` to a real id while
|
|
26
|
+
* the popup is already mounted. A `parentId` captured as a plain string at
|
|
27
|
+
* setup keeps addressing `'new'`, and every nested request goes to
|
|
28
|
+
* `<entity>/new/<nested>`.
|
|
29
|
+
*
|
|
30
|
+
* [WTEL-10348](https://webitel.atlassian.net/browse/WTEL-10348)
|
|
31
|
+
*/
|
|
32
|
+
describe('useCardRouting', () => {
|
|
33
|
+
const run = (options: {
|
|
34
|
+
itemId: Ref<CardItemId>;
|
|
35
|
+
routeParamName?: string;
|
|
36
|
+
parentId?: (() => CardItemId) | string;
|
|
37
|
+
}) => {
|
|
38
|
+
const scope = effectScope(true);
|
|
39
|
+
const routing = scope.run(() => useCardRouting(options));
|
|
40
|
+
|
|
41
|
+
if (!routing) throw new Error('useCardRouting returned nothing');
|
|
42
|
+
|
|
43
|
+
return routing;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
mocks.replace.mockReset();
|
|
48
|
+
mocks.replace.mockResolvedValue(undefined);
|
|
49
|
+
mocks.route = reactive({
|
|
50
|
+
params: {},
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('resolves a getter parent on read instead of capturing it', () => {
|
|
55
|
+
mocks.route.params = {
|
|
56
|
+
id: 'new',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const { parentId } = run({
|
|
60
|
+
itemId: ref(null),
|
|
61
|
+
routeParamName: 'bucketId',
|
|
62
|
+
parentId: () => mocks.route.params.id,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
expect(parentId.value).toBe('new');
|
|
66
|
+
|
|
67
|
+
mocks.route.params = {
|
|
68
|
+
id: '42',
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
expect(parentId.value).toBe('42');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('keeps accepting a plain string parent', () => {
|
|
75
|
+
const { parentId } = run({
|
|
76
|
+
itemId: ref(null),
|
|
77
|
+
routeParamName: 'bucketId',
|
|
78
|
+
parentId: '42',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
expect(parentId.value).toBe('42');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('writes the server id into the route of a newly created nested item', async () => {
|
|
85
|
+
mocks.route.params = {
|
|
86
|
+
id: '42',
|
|
87
|
+
bucketId: 'new',
|
|
88
|
+
};
|
|
89
|
+
const itemId = ref<CardItemId>(null);
|
|
90
|
+
|
|
91
|
+
run({
|
|
92
|
+
itemId,
|
|
93
|
+
routeParamName: 'bucketId',
|
|
94
|
+
parentId: () => mocks.route.params.id,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
itemId.value = 7;
|
|
98
|
+
await nextTick();
|
|
99
|
+
|
|
100
|
+
expect(mocks.replace).toHaveBeenCalledWith({
|
|
101
|
+
params: {
|
|
102
|
+
id: '42',
|
|
103
|
+
bucketId: 7,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('leaves the route alone for a nested item that already had an id', async () => {
|
|
109
|
+
mocks.route.params = {
|
|
110
|
+
id: '42',
|
|
111
|
+
bucketId: '7',
|
|
112
|
+
};
|
|
113
|
+
const itemId = ref<CardItemId>(null);
|
|
114
|
+
|
|
115
|
+
run({
|
|
116
|
+
itemId,
|
|
117
|
+
routeParamName: 'bucketId',
|
|
118
|
+
parentId: () => mocks.route.params.id,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
itemId.value = 7;
|
|
122
|
+
await nextTick();
|
|
123
|
+
|
|
124
|
+
expect(mocks.replace).not.toHaveBeenCalled();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('writes the server id into the route of a top-level card', async () => {
|
|
128
|
+
mocks.route.params = {
|
|
129
|
+
id: 'new',
|
|
130
|
+
};
|
|
131
|
+
const itemId = ref<CardItemId>(null);
|
|
132
|
+
|
|
133
|
+
run({
|
|
134
|
+
itemId,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
itemId.value = 42;
|
|
138
|
+
await nextTick();
|
|
139
|
+
|
|
140
|
+
expect(mocks.replace).toHaveBeenCalledWith({
|
|
141
|
+
params: {
|
|
142
|
+
id: 42,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -1,35 +1,41 @@
|
|
|
1
|
-
import { computed, type Ref, watch } from 'vue';
|
|
1
|
+
import { computed, type MaybeRefOrGetter, type Ref, toValue, watch } from 'vue';
|
|
2
2
|
import { useRoute, useRouter } from 'vue-router';
|
|
3
3
|
|
|
4
|
-
import type { CardItemId } from '../types/CardStore.types';
|
|
4
|
+
import type { CardItemId, CardParentId } from '../types/CardStore.types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Routing logic shared by top-level and nested card components.
|
|
8
8
|
*
|
|
9
9
|
* - `routeParamName` — which `route.params` key holds the item ID (default: `'id'`)
|
|
10
10
|
* - `parentId` — when provided, the card is treated as nested: URL is updated
|
|
11
|
-
* only when a newly created item receives its server-assigned ID
|
|
11
|
+
* only when a newly created item receives its server-assigned ID. Pass a ref
|
|
12
|
+
* or a getter whenever the parent can be created while the card is already
|
|
13
|
+
* mounted — a popup living inside its parent's card page watches
|
|
14
|
+
* `route.params.id` go from `'new'` to a real id underneath it, and a plain
|
|
15
|
+
* string captured at setup would keep addressing `'new'`.
|
|
12
16
|
*/
|
|
13
17
|
export const useCardRouting = ({
|
|
14
18
|
itemId,
|
|
15
19
|
routeParamName = 'id',
|
|
16
|
-
parentId,
|
|
20
|
+
parentId: rawParentId,
|
|
17
21
|
manualSetup = false,
|
|
18
22
|
}: {
|
|
19
23
|
itemId: Ref<CardItemId>;
|
|
20
24
|
routeParamName?: string;
|
|
21
|
-
parentId?:
|
|
25
|
+
parentId?: MaybeRefOrGetter<CardParentId>;
|
|
22
26
|
manualSetup?: boolean;
|
|
23
27
|
}) => {
|
|
24
28
|
const router = useRouter();
|
|
25
29
|
const route = useRoute();
|
|
26
30
|
|
|
27
31
|
const routeId = computed(() => route.params[routeParamName]);
|
|
32
|
+
/** resolved on read, so a nested card always addresses the current parent */
|
|
33
|
+
const parentId = computed(() => toValue(rawParentId));
|
|
28
34
|
|
|
29
35
|
if (!manualSetup) {
|
|
30
36
|
const unwatch = watch(itemId, async (next, prev) => {
|
|
31
37
|
if (next && !prev) {
|
|
32
|
-
if (!parentId || routeId.value === 'new') {
|
|
38
|
+
if (!parentId.value || routeId.value === 'new') {
|
|
33
39
|
await router.replace({
|
|
34
40
|
params: {
|
|
35
41
|
...route.params,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type StoreDefinition, storeToRefs } from 'pinia';
|
|
2
|
-
import { watch } from 'vue';
|
|
2
|
+
import { type MaybeRefOrGetter, watch } from 'vue';
|
|
3
3
|
|
|
4
|
+
import type { CardParentId } from '../types/CardStore.types';
|
|
4
5
|
import { useCardComponent } from './useCardComponent';
|
|
5
6
|
import { useCardRouting } from './useCardRouting';
|
|
6
7
|
|
|
@@ -9,7 +10,9 @@ import { useCardRouting } from './useCardRouting';
|
|
|
9
10
|
*
|
|
10
11
|
* Wraps `useCardComponent` with `manualSetup: true` and delegates
|
|
11
12
|
* routing to `useCardRouting`. Pass `parentId` from the component —
|
|
12
|
-
* its presence indicates a nested card context.
|
|
13
|
+
* its presence indicates a nested card context. A ref or getter is read on
|
|
14
|
+
* every `initialize`, so a popup mounted while its parent was still `'new'`
|
|
15
|
+
* follows the parent's real id instead of addressing `'new'` forever.
|
|
13
16
|
*
|
|
14
17
|
* @example
|
|
15
18
|
* ```ts
|
|
@@ -34,7 +37,7 @@ export const useNestedCardComponent = <
|
|
|
34
37
|
useCardStore: StoreDefinition;
|
|
35
38
|
onLoadErrorHandler?: (err: unknown) => void;
|
|
36
39
|
routeParamName: string;
|
|
37
|
-
parentId?:
|
|
40
|
+
parentId?: MaybeRefOrGetter<CardParentId>;
|
|
38
41
|
}) => {
|
|
39
42
|
const cardSetup = useCardComponent<CardEntity>({
|
|
40
43
|
useCardStore,
|
|
@@ -46,7 +49,7 @@ export const useNestedCardComponent = <
|
|
|
46
49
|
const { itemId } = storeToRefs(cardStore);
|
|
47
50
|
const { initialize, $reset } = cardStore;
|
|
48
51
|
|
|
49
|
-
const { routeId } = useCardRouting({
|
|
52
|
+
const { routeId, parentId: currentParentId } = useCardRouting({
|
|
50
53
|
itemId,
|
|
51
54
|
routeParamName,
|
|
52
55
|
parentId,
|
|
@@ -58,7 +61,7 @@ export const useNestedCardComponent = <
|
|
|
58
61
|
if (value) {
|
|
59
62
|
initialize({
|
|
60
63
|
itemId: value === 'new' ? null : value,
|
|
61
|
-
parentId,
|
|
64
|
+
parentId: currentParentId.value,
|
|
62
65
|
});
|
|
63
66
|
} else {
|
|
64
67
|
$reset();
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { createPinia, setActivePinia } from 'pinia';
|
|
3
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { defineComponent, h } from 'vue';
|
|
5
|
+
import { createMemoryHistory, createRouter, type Router } from 'vue-router';
|
|
6
|
+
|
|
7
|
+
import type { DatalistTableHeader } from '../../types/tableStore.types';
|
|
8
|
+
import { createTableStore } from '../createTableStore.store';
|
|
9
|
+
|
|
10
|
+
const routes = [
|
|
11
|
+
{
|
|
12
|
+
path: '/cases',
|
|
13
|
+
name: 'cases',
|
|
14
|
+
component: {
|
|
15
|
+
template: '<div />',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const headers = [
|
|
21
|
+
{
|
|
22
|
+
value: 'name',
|
|
23
|
+
field: 'name',
|
|
24
|
+
show: true,
|
|
25
|
+
sort: null,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
value: 'subject',
|
|
29
|
+
field: 'subject',
|
|
30
|
+
show: true,
|
|
31
|
+
sort: null,
|
|
32
|
+
},
|
|
33
|
+
] as DatalistTableHeader[];
|
|
34
|
+
|
|
35
|
+
const flush = async () => {
|
|
36
|
+
for (let i = 0; i < 5; i += 1) {
|
|
37
|
+
await new Promise((resolve) => setTimeout(resolve));
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
`setupStore` runs once per store, and the watchers it depends on must outlive
|
|
43
|
+
every component that renders the table. Registering them from the caller left
|
|
44
|
+
them owned by that component's effect scope, so a card tab that had been
|
|
45
|
+
walked away from came back inert — it loaded once and then ignored sort,
|
|
46
|
+
pagination, page size, column visibility and filters
|
|
47
|
+
([WTEL-10308](https://webitel.atlassian.net/browse/WTEL-10308), fixed by
|
|
48
|
+
[WTEL-10277](https://webitel.atlassian.net/browse/WTEL-10277)).
|
|
49
|
+
|
|
50
|
+
Tables that keep persistence were spared by accident back then: their setup
|
|
51
|
+
awaits the restore, so the watchers landed with no active scope. Both settings
|
|
52
|
+
are covered here, because that difference was invisible until it broke.
|
|
53
|
+
*/
|
|
54
|
+
describe('tableStoreBody', () => {
|
|
55
|
+
let router: Router;
|
|
56
|
+
let getList: ReturnType<typeof vi.fn>;
|
|
57
|
+
|
|
58
|
+
beforeEach(async () => {
|
|
59
|
+
localStorage.clear();
|
|
60
|
+
sessionStorage.clear();
|
|
61
|
+
setActivePinia(createPinia());
|
|
62
|
+
|
|
63
|
+
router = createRouter({
|
|
64
|
+
history: createMemoryHistory(),
|
|
65
|
+
routes,
|
|
66
|
+
});
|
|
67
|
+
await router.push('/cases');
|
|
68
|
+
await router.isReady();
|
|
69
|
+
|
|
70
|
+
getList = vi.fn().mockResolvedValue({
|
|
71
|
+
items: [],
|
|
72
|
+
next: false,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
a tab on a card page: the table component is unmounted and mounted back as
|
|
78
|
+
the user walks the tabs, and the store outlives all of it
|
|
79
|
+
*/
|
|
80
|
+
const mountTab = (useStore: ReturnType<typeof createTableStore>) => {
|
|
81
|
+
const Tab = defineComponent({
|
|
82
|
+
setup() {
|
|
83
|
+
const store = useStore();
|
|
84
|
+
/* a nested list is initialized with the card's id */
|
|
85
|
+
store.initialize({
|
|
86
|
+
parentId: '42',
|
|
87
|
+
});
|
|
88
|
+
return () => h('div');
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return mount(Tab, {
|
|
93
|
+
global: {
|
|
94
|
+
plugins: [
|
|
95
|
+
router,
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
describe.each([
|
|
102
|
+
[
|
|
103
|
+
'with persistence',
|
|
104
|
+
false,
|
|
105
|
+
],
|
|
106
|
+
[
|
|
107
|
+
'without persistence',
|
|
108
|
+
true,
|
|
109
|
+
],
|
|
110
|
+
])('%s', (_label, disablePersistence) => {
|
|
111
|
+
let useStore: ReturnType<typeof createTableStore>;
|
|
112
|
+
|
|
113
|
+
beforeEach(async () => {
|
|
114
|
+
useStore = createTableStore(`cases-${disablePersistence}/datalist`, {
|
|
115
|
+
apiModule: {
|
|
116
|
+
getList,
|
|
117
|
+
},
|
|
118
|
+
headers,
|
|
119
|
+
disablePersistence,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const first = mountTab(useStore);
|
|
123
|
+
await flush();
|
|
124
|
+
first.unmount();
|
|
125
|
+
await flush();
|
|
126
|
+
|
|
127
|
+
mountTab(useStore);
|
|
128
|
+
await flush();
|
|
129
|
+
|
|
130
|
+
getList.mockClear();
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('reloads on sort after the component is remounted', async () => {
|
|
134
|
+
const store = useStore();
|
|
135
|
+
|
|
136
|
+
store.updateSort(store.headers[0]);
|
|
137
|
+
await flush();
|
|
138
|
+
|
|
139
|
+
expect(getList).toHaveBeenCalled();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('reloads on size change after the component is remounted', async () => {
|
|
143
|
+
const store = useStore();
|
|
144
|
+
|
|
145
|
+
store.updateSize(20);
|
|
146
|
+
await flush();
|
|
147
|
+
|
|
148
|
+
expect(getList).toHaveBeenCalled();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('reloads on page change after the component is remounted', async () => {
|
|
152
|
+
const store = useStore();
|
|
153
|
+
|
|
154
|
+
store.updatePage(2);
|
|
155
|
+
await flush();
|
|
156
|
+
|
|
157
|
+
expect(getList).toHaveBeenCalled();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('reloads on search after the component is remounted', async () => {
|
|
161
|
+
const store = useStore();
|
|
162
|
+
|
|
163
|
+
store.addFilter({
|
|
164
|
+
name: 'search',
|
|
165
|
+
value: 'lorem',
|
|
166
|
+
});
|
|
167
|
+
await flush();
|
|
168
|
+
|
|
169
|
+
expect(getList).toHaveBeenCalled();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('reloads on a hidden column after the component is remounted', async () => {
|
|
173
|
+
const store = useStore();
|
|
174
|
+
|
|
175
|
+
store.updateShownHeaders(
|
|
176
|
+
store.headers.map((header, index) => ({
|
|
177
|
+
...header,
|
|
178
|
+
show: index === 0,
|
|
179
|
+
})),
|
|
180
|
+
);
|
|
181
|
+
await flush();
|
|
182
|
+
|
|
183
|
+
expect(getList).toHaveBeenCalled();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import deepEqual from 'deep-equal';
|
|
2
2
|
import set from 'lodash/set';
|
|
3
|
-
import { type Ref, ref, toRaw, watch } from 'vue';
|
|
3
|
+
import { nextTick, type Ref, ref, toRaw, watch } from 'vue';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
createDatalistStore,
|
|
@@ -247,6 +247,53 @@ export const tableStoreBody = <Entity extends Identifiable>(
|
|
|
247
247
|
}
|
|
248
248
|
};
|
|
249
249
|
|
|
250
|
+
let loadingAfterFiltersChange = false;
|
|
251
|
+
|
|
252
|
+
watch(
|
|
253
|
+
[
|
|
254
|
+
() => filtersManager.value.getAllValues(),
|
|
255
|
+
sort,
|
|
256
|
+
fields,
|
|
257
|
+
size,
|
|
258
|
+
],
|
|
259
|
+
async () => {
|
|
260
|
+
if (!isStoreSetUp.value) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/*
|
|
265
|
+
* @author @Lera24
|
|
266
|
+
* https://webitel.atlassian.net/browse/WTEL-7597?focusedCommentId=697115
|
|
267
|
+
* */
|
|
268
|
+
if (isReorderingColumn.value) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
loadingAfterFiltersChange = true;
|
|
272
|
+
updatePage(1);
|
|
273
|
+
await loadDataList();
|
|
274
|
+
loadingAfterFiltersChange = false;
|
|
275
|
+
},
|
|
276
|
+
/* filtersManager requires deep watching for its values */
|
|
277
|
+
{
|
|
278
|
+
deep: true,
|
|
279
|
+
},
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
watch(
|
|
283
|
+
[
|
|
284
|
+
page,
|
|
285
|
+
],
|
|
286
|
+
() => {
|
|
287
|
+
if (!isStoreSetUp.value) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (!loadingAfterFiltersChange && !isAppendDataList) {
|
|
292
|
+
return loadDataList();
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
);
|
|
296
|
+
|
|
250
297
|
const setupStore = async () => {
|
|
251
298
|
if (isStoreSetUp.value) {
|
|
252
299
|
return;
|
|
@@ -260,44 +307,13 @@ export const tableStoreBody = <Entity extends Identifiable>(
|
|
|
260
307
|
]);
|
|
261
308
|
}
|
|
262
309
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
size,
|
|
271
|
-
],
|
|
272
|
-
async () => {
|
|
273
|
-
/*
|
|
274
|
-
* @author @Lera24
|
|
275
|
-
* https://webitel.atlassian.net/browse/WTEL-7597?focusedCommentId=697115
|
|
276
|
-
* */
|
|
277
|
-
if (isReorderingColumn.value) {
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
loadingAfterFiltersChange = true;
|
|
281
|
-
updatePage(1);
|
|
282
|
-
await loadDataList();
|
|
283
|
-
loadingAfterFiltersChange = false;
|
|
284
|
-
},
|
|
285
|
-
/* filtersManager requires deep watching for its values */
|
|
286
|
-
{
|
|
287
|
-
deep: true,
|
|
288
|
-
},
|
|
289
|
-
);
|
|
290
|
-
|
|
291
|
-
watch(
|
|
292
|
-
[
|
|
293
|
-
page,
|
|
294
|
-
],
|
|
295
|
-
() => {
|
|
296
|
-
if (!loadingAfterFiltersChange && !isAppendDataList) {
|
|
297
|
-
return loadDataList();
|
|
298
|
-
}
|
|
299
|
-
},
|
|
300
|
-
);
|
|
310
|
+
/*
|
|
311
|
+
* lets any reactive updates the restore above just made (e.g. to
|
|
312
|
+
* sort/fields/filters) finish flushing through the watchers above
|
|
313
|
+
* while `isStoreSetUp` is still false, before they start reacting to
|
|
314
|
+
* real changes
|
|
315
|
+
*/
|
|
316
|
+
await nextTick();
|
|
301
317
|
|
|
302
318
|
isStoreSetUp.value = true;
|
|
303
319
|
};
|