@nocobase/client-v2 3.0.0-alpha.4 → 3.0.0-alpha.6
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/es/authRedirect.d.ts +6 -2
- package/es/index.mjs +50 -50
- package/lib/index.js +24 -24
- package/package.json +7 -7
- package/src/__tests__/authRedirect.test.ts +17 -0
- package/src/authRedirect.ts +13 -5
- package/src/flow/models/base/CollectionBlockModel.tsx +9 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.initialBeforeRenderRefresh.test.ts +60 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/client-v2",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.6",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "es/index.mjs",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"@formily/antd-v5": "1.2.3",
|
|
28
28
|
"@formily/react": "^2.2.27",
|
|
29
29
|
"@formily/shared": "^2.2.27",
|
|
30
|
-
"@nocobase/evaluators": "3.0.0-alpha.
|
|
31
|
-
"@nocobase/flow-engine": "3.0.0-alpha.
|
|
32
|
-
"@nocobase/sdk": "3.0.0-alpha.
|
|
33
|
-
"@nocobase/shared": "3.0.0-alpha.
|
|
34
|
-
"@nocobase/utils": "3.0.0-alpha.
|
|
30
|
+
"@nocobase/evaluators": "3.0.0-alpha.6",
|
|
31
|
+
"@nocobase/flow-engine": "3.0.0-alpha.6",
|
|
32
|
+
"@nocobase/sdk": "3.0.0-alpha.6",
|
|
33
|
+
"@nocobase/shared": "3.0.0-alpha.6",
|
|
34
|
+
"@nocobase/utils": "3.0.0-alpha.6",
|
|
35
35
|
"ahooks": "^3.7.2",
|
|
36
36
|
"antd": "5.24.2",
|
|
37
37
|
"antd-style": "3.7.1",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"react-i18next": "^11.15.1",
|
|
49
49
|
"react-router-dom": "^6.30.1"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "3508eabe683b9a47a28d0f3425098eb58873a9d7"
|
|
52
52
|
}
|
|
@@ -347,6 +347,23 @@ describe('auth redirect helpers', () => {
|
|
|
347
347
|
);
|
|
348
348
|
});
|
|
349
349
|
|
|
350
|
+
it('should derive a scoped Portal signin href under the current sub-app basename', () => {
|
|
351
|
+
const app = {
|
|
352
|
+
getPublicPath: () => '/nocobase/v2/',
|
|
353
|
+
router: {
|
|
354
|
+
getBasename: () => '/nocobase/v2/apps/test-app/',
|
|
355
|
+
},
|
|
356
|
+
} satisfies Parameters<typeof buildV2SigninHref>[0];
|
|
357
|
+
|
|
358
|
+
expect(
|
|
359
|
+
buildV2SigninHref(app, '/nocobase/v2/apps/test-app/customer/orders', {
|
|
360
|
+
signInRoutePath: '/customer/signin',
|
|
361
|
+
}),
|
|
362
|
+
).toBe(
|
|
363
|
+
'/nocobase/v2/apps/test-app/customer/signin?redirect=%2Fnocobase%2Fv2%2Fapps%2Ftest-app%2Fcustomer%2Forders',
|
|
364
|
+
);
|
|
365
|
+
});
|
|
366
|
+
|
|
350
367
|
it('should redirect to sub-app signin with window.location.replace', () => {
|
|
351
368
|
const replace = vi.fn();
|
|
352
369
|
Object.defineProperty(globalThis.window, 'location', {
|
package/src/authRedirect.ts
CHANGED
|
@@ -328,10 +328,14 @@ export function getCurrentV2RedirectPath(app: AppLike, locationLike: LocationLik
|
|
|
328
328
|
*
|
|
329
329
|
* @param app 当前 v2 应用实例
|
|
330
330
|
* @param targetPath 登录后回跳地址
|
|
331
|
+
* @param options 可选的登录路由配置
|
|
331
332
|
* @returns 指向 v2 登录页的 href
|
|
332
333
|
*/
|
|
333
|
-
export function buildV2SigninHref(app: AppLike, targetPath: string) {
|
|
334
|
-
|
|
334
|
+
export function buildV2SigninHref(app: AppLike, targetPath: string, options?: { signInRoutePath?: string }) {
|
|
335
|
+
const signInPath = options?.signInRoutePath
|
|
336
|
+
? normalizeV2RedirectPath(app, options.signInRoutePath, options.signInRoutePath)
|
|
337
|
+
: getV2SigninPath(app);
|
|
338
|
+
return `${signInPath}?redirect=${encodeURIComponent(targetPath)}`;
|
|
335
339
|
}
|
|
336
340
|
|
|
337
341
|
/**
|
|
@@ -339,10 +343,14 @@ export function buildV2SigninHref(app: AppLike, targetPath: string) {
|
|
|
339
343
|
*
|
|
340
344
|
* @param app 当前 v2 应用实例
|
|
341
345
|
* @param targetPath 登录后回跳地址
|
|
342
|
-
* @param options
|
|
346
|
+
* @param options 跳转和登录路由选项
|
|
343
347
|
*/
|
|
344
|
-
export function redirectToV2Signin(
|
|
345
|
-
|
|
348
|
+
export function redirectToV2Signin(
|
|
349
|
+
app: AppLike,
|
|
350
|
+
targetPath: string,
|
|
351
|
+
options?: { replace?: boolean; signInRoutePath?: string },
|
|
352
|
+
) {
|
|
353
|
+
const href = buildV2SigninHref(app, targetPath, options);
|
|
346
354
|
if (options?.replace === false) {
|
|
347
355
|
window.location.href = href;
|
|
348
356
|
return;
|
|
@@ -82,6 +82,15 @@ export class CollectionBlockModel<T = DefaultStructure> extends DataBlockModel<T
|
|
|
82
82
|
const engine = this.context.engine as FlowEngine;
|
|
83
83
|
const currentVersion = this.getDirtyTrackingVersion(engine, dataSourceKey, resource, params);
|
|
84
84
|
|
|
85
|
+
if (resource instanceof MultiRecordResource && this.getDataLoadingMode() === 'manual' && !this.hasActiveFilters()) {
|
|
86
|
+
resource.setData([]);
|
|
87
|
+
resource.setMeta({ count: 0, hasNext: false });
|
|
88
|
+
resource.setPage(1);
|
|
89
|
+
resource.loading = false;
|
|
90
|
+
this.lastSeenDirtyVersion = currentVersion;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
if (forceRefresh) {
|
|
86
95
|
if (this.dirtyRefreshing) return;
|
|
87
96
|
this.dirtyRefreshing = true;
|
package/src/flow/models/base/__tests__/CollectionBlockModel.initialBeforeRenderRefresh.test.ts
CHANGED
|
@@ -128,4 +128,64 @@ describe('CollectionBlockModel initial beforeRender refresh', () => {
|
|
|
128
128
|
expect(resource.getData()).toEqual([]);
|
|
129
129
|
expect(resource.getMeta('count')).toBe(0);
|
|
130
130
|
});
|
|
131
|
+
|
|
132
|
+
it('skips forced active refresh in manual mode when filters are empty', async () => {
|
|
133
|
+
const { model, resource } = setupModelWithManualMode();
|
|
134
|
+
const refreshSpy = vi.spyOn(resource, 'refresh');
|
|
135
|
+
|
|
136
|
+
resource.setData([{ id: 2, name: 'Stale' }]);
|
|
137
|
+
resource.setMeta({ count: 1, hasNext: true });
|
|
138
|
+
resource.setPage(2);
|
|
139
|
+
resource.loading = true;
|
|
140
|
+
|
|
141
|
+
model.onActive(true);
|
|
142
|
+
await Promise.resolve();
|
|
143
|
+
await Promise.resolve();
|
|
144
|
+
|
|
145
|
+
expect(refreshSpy).not.toHaveBeenCalled();
|
|
146
|
+
expect(resource.getData()).toEqual([]);
|
|
147
|
+
expect(resource.getMeta('count')).toBe(0);
|
|
148
|
+
expect(resource.getMeta('hasNext')).toBe(false);
|
|
149
|
+
expect(resource.getMeta('page')).toBe(1);
|
|
150
|
+
expect(resource.getRequestParameter('page')).toBe(1);
|
|
151
|
+
expect(resource.loading).toBe(false);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('keeps forced active refresh in manual mode when filters are active', async () => {
|
|
155
|
+
const { model, resource } = setupModelWithManualMode();
|
|
156
|
+
const refreshSpy = vi.spyOn(resource, 'refresh').mockResolvedValue();
|
|
157
|
+
|
|
158
|
+
resource.setData([{ id: 2, name: 'Stale' }]);
|
|
159
|
+
resource.setMeta({ count: 1, hasNext: true, page: 2 });
|
|
160
|
+
model.setFilterActive('filter-form-item', true);
|
|
161
|
+
|
|
162
|
+
model.onActive(true);
|
|
163
|
+
await Promise.resolve();
|
|
164
|
+
|
|
165
|
+
expect(refreshSpy).toHaveBeenCalledTimes(1);
|
|
166
|
+
expect(resource.getData()).toEqual([{ id: 2, name: 'Stale' }]);
|
|
167
|
+
expect(resource.getMeta('count')).toBe(1);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('skips forced active refresh in manual mode when only resource filters are active', async () => {
|
|
171
|
+
const { model, resource } = setupModelWithManualMode();
|
|
172
|
+
const refreshSpy = vi.spyOn(resource, 'refresh');
|
|
173
|
+
|
|
174
|
+
resource.setData([{ id: 2, name: 'Stale' }]);
|
|
175
|
+
resource.setMeta({ count: 1, hasNext: true });
|
|
176
|
+
resource.setPage(2);
|
|
177
|
+
resource.loading = true;
|
|
178
|
+
resource.addFilterGroup('data-scope', { status: { $eq: 'active' } });
|
|
179
|
+
|
|
180
|
+
model.onActive(true);
|
|
181
|
+
await Promise.resolve();
|
|
182
|
+
|
|
183
|
+
expect(refreshSpy).not.toHaveBeenCalled();
|
|
184
|
+
expect(resource.getData()).toEqual([]);
|
|
185
|
+
expect(resource.getMeta('count')).toBe(0);
|
|
186
|
+
expect(resource.getMeta('hasNext')).toBe(false);
|
|
187
|
+
expect(resource.getMeta('page')).toBe(1);
|
|
188
|
+
expect(resource.getRequestParameter('page')).toBe(1);
|
|
189
|
+
expect(resource.loading).toBe(false);
|
|
190
|
+
});
|
|
131
191
|
});
|