cabloy 5.1.169 → 5.1.171

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.
Files changed (73) hide show
  1. package/.cabloy-version +1 -1
  2. package/CHANGELOG.md +16 -0
  3. package/package.json +1 -1
  4. package/repo-e2e/specs/cabloy-basic.spec.ts +45 -0
  5. package/vona/packages-cli/cli/package.json +1 -1
  6. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudBasic/boilerplate/src/dto/{{resourceName}}SelectResItem.tsx_ +4 -0
  7. package/vona/packages-cli/cli-set-api/cli/templates/tools/crudStart/boilerplate/src/dto/{{resourceName}}SelectResItem.tsx_ +4 -0
  8. package/vona/packages-cli/cli-set-api/package.json +1 -1
  9. package/vona/pnpm-lock.yaml +177 -500
  10. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +4 -0
  11. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +5 -0
  12. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/package.json +54 -0
  13. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/.metadata/index.ts +346 -0
  14. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/.metadata/this.ts +2 -0
  15. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/bean/meta.index.ts +12 -0
  16. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/bean/meta.redlock.ts +11 -0
  17. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/bean/meta.version.ts +20 -0
  18. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/controller/layoutprofile.ts +38 -0
  19. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/dto/layoutProfile.tsx +26 -0
  20. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/dto/layoutProfileLoad.tsx +13 -0
  21. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/dto/layoutProfileSave.tsx +31 -0
  22. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/entity/layoutprofile.ts +20 -0
  23. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/index.ts +2 -0
  24. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/model/layoutprofile.ts +10 -0
  25. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/service/layoutprofile.ts +64 -0
  26. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/types/index.ts +1 -0
  27. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/types/layoutprofile.ts +21 -0
  28. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/test/layoutprofile.test.ts +258 -0
  29. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/tsconfig.build.json +11 -0
  30. package/vona/src/suite-vendor/a-cabloy/modules/a-layoutprofile/tsconfig.json +7 -0
  31. package/vona/src/suite-vendor/a-cabloy/package.json +2 -1
  32. package/vona/src/suite-vendor/a-cabloy/tsconfig.json +3 -0
  33. package/zova/packages-zova/zova/package.json +2 -2
  34. package/zova/pnpm-lock.yaml +37 -22
  35. package/zova/src/suite/a-home/modules/home-base/src/service/ssrLayout.ts +20 -10
  36. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockPage/controller.tsx +44 -1
  37. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockTable/controller.tsx +1 -0
  38. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockToolbarBulk/controller.tsx +40 -25
  39. package/zova/src/suite/cabloy-basic/modules/basic-page/src/lib/selection.ts +11 -0
  40. package/zova/src/suite/cabloy-basic/modules/basic-page/test/lib/selection.test.ts +23 -0
  41. package/zova/src/suite/cabloy-basic/modules/basic-table/src/.metadata/component/actionColumnConfig.ts +31 -0
  42. package/zova/src/suite/cabloy-basic/modules/basic-table/src/.metadata/index.ts +25 -12
  43. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/actionColumnConfig/controller.tsx +260 -0
  44. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/table/render.tsx +3 -3
  45. package/zova/src/suite/cabloy-basic/modules/basic-table/src/config/locale/en-us.ts +10 -0
  46. package/zova/src/suite/cabloy-basic/modules/basic-table/src/config/locale/zh-cn.ts +10 -0
  47. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/cli/openapi.config.ts +9 -0
  48. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/package.json +53 -0
  49. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/.metadata/index.ts +140 -0
  50. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/.metadata/this.ts +2 -0
  51. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/api/layoutprofile.ts +67 -0
  52. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/api/openapi/baseURL.ts +5 -0
  53. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/api/openapi/index.ts +3 -0
  54. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/api/openapi/schemas.ts +663 -0
  55. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/api/openapi/types.ts +10150 -0
  56. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/apiSchema/layoutprofile.ts +25 -0
  57. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/index.ts +1 -0
  58. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/model/layoutprofile.ts +76 -0
  59. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/tsconfig.build.json +13 -0
  60. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/tsconfig.json +5 -0
  61. package/zova/src/suite-vendor/a-cabloy/package.json +2 -1
  62. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
  63. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/resource/tableActionBulk.ts +3 -0
  64. package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
  65. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/bodyReadyObserver.ts +13 -11
  66. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +1 -1
  67. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +64 -2
  68. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/render.tsx +2 -3
  69. package/zova/src/suite-vendor/a-zova/modules/a-table/src/lib/beanControllerTableBase.ts +10 -0
  70. package/zova/src/suite-vendor/a-zova/modules/a-table/src/types/index.ts +1 -0
  71. package/zova/src/suite-vendor/a-zova/modules/a-table/src/types/tableLayout.ts +101 -0
  72. package/zova/src/suite-vendor/a-zova/modules/a-table/test/lib/tableLayout.test.ts +112 -0
  73. package/zova/src/suite-vendor/a-zova/package.json +4 -4
@@ -0,0 +1,64 @@
1
+ import type { TableIdentity } from 'table-identity';
2
+ import type { IUser } from 'vona-module-a-user';
3
+
4
+ import { BeanBase } from 'vona';
5
+ import { Service } from 'vona-module-a-bean';
6
+ import { Core } from 'vona-module-a-core';
7
+
8
+ import type { ILayoutProfile } from '../types/layoutprofile.ts';
9
+
10
+ @Service()
11
+ export class ServiceLayoutprofile extends BeanBase {
12
+ async load(user: IUser, layoutKey: string): Promise<ILayoutProfile | undefined> {
13
+ const entity = await this.scope.model.layoutprofile.get({ userId: user.id, layoutKey });
14
+ return entity?.profile as ILayoutProfile | undefined;
15
+ }
16
+
17
+ async save(user: IUser, layoutKey: string, profile: ILayoutProfile): Promise<ILayoutProfile> {
18
+ if (await this._saveExisting(user.id, layoutKey, profile)) return profile;
19
+ return await this.scope.redlock.lockIsolate(
20
+ `layoutprofileSave.${user.id}.${layoutKey}`,
21
+ async () => await this._saveAfterLock(user.id, layoutKey, profile),
22
+ );
23
+ }
24
+
25
+ async reset(user: IUser, layoutKey: string): Promise<void> {
26
+ await this.scope.redlock.lockIsolate(
27
+ `layoutprofileSave.${user.id}.${layoutKey}`,
28
+ async () => await this._reset(user.id, layoutKey),
29
+ );
30
+ }
31
+
32
+ @Core.transaction()
33
+ private async _saveExisting(
34
+ userId: TableIdentity,
35
+ layoutKey: string,
36
+ profile: ILayoutProfile,
37
+ ): Promise<boolean> {
38
+ const entity = await this.scope.model.layoutprofile.getForUpdate({ userId, layoutKey });
39
+ if (!entity) return false;
40
+ await this.scope.model.layoutprofile.updateById(entity.id, { profile });
41
+ return true;
42
+ }
43
+
44
+ @Core.transaction()
45
+ private async _saveAfterLock(
46
+ userId: TableIdentity,
47
+ layoutKey: string,
48
+ profile: ILayoutProfile,
49
+ ): Promise<ILayoutProfile> {
50
+ const entity = await this.scope.model.layoutprofile.getForUpdate({ userId, layoutKey });
51
+ if (entity) {
52
+ await this.scope.model.layoutprofile.updateById(entity.id, { profile });
53
+ } else {
54
+ await this.scope.model.layoutprofile.insert({ userId, layoutKey, profile });
55
+ }
56
+ return profile;
57
+ }
58
+
59
+ @Core.transaction()
60
+ private async _reset(userId: TableIdentity, layoutKey: string): Promise<void> {
61
+ const entity = await this.scope.model.layoutprofile.getForUpdate({ userId, layoutKey });
62
+ if (entity) await this.scope.model.layoutprofile.deleteById(entity.id);
63
+ }
64
+ }
@@ -0,0 +1 @@
1
+ export * from './layoutprofile.ts';
@@ -0,0 +1,21 @@
1
+ import type { TableIdentity } from 'table-identity';
2
+
3
+ export type TypeLayoutProfileWidth = number | 'auto';
4
+
5
+ export interface ILayoutProfileColumn {
6
+ key: string;
7
+ visible: boolean;
8
+ width: TypeLayoutProfileWidth;
9
+ }
10
+
11
+ export interface ILayoutProfile extends Record<string, unknown> {
12
+ version: 1;
13
+ schemaFingerprint?: string;
14
+ columns: ILayoutProfileColumn[];
15
+ }
16
+
17
+ export interface ILayoutProfileRecord {
18
+ id?: TableIdentity;
19
+ layoutKey: string;
20
+ profile: ILayoutProfile;
21
+ }
@@ -0,0 +1,258 @@
1
+ import type { TableIdentity } from 'table-identity';
2
+
3
+ import { catchError } from '@cabloy/utils';
4
+ import assert from 'node:assert';
5
+ import { randomUUID } from 'node:crypto';
6
+ import { describe, it } from 'node:test';
7
+ import { app } from 'vona-mock';
8
+
9
+ import type { ILayoutProfile } from '../src/types/layoutprofile.ts';
10
+
11
+ const actionPath = '/layoutprofile';
12
+
13
+ function createTestId() {
14
+ return randomUUID().slice(0, 12);
15
+ }
16
+
17
+ function createProfile(name: string): ILayoutProfile {
18
+ return {
19
+ version: 1,
20
+ schemaFingerprint: `schema-${name}`,
21
+ columns: [
22
+ { key: 'name', visible: true, width: 'auto' },
23
+ { key: 'level', visible: false, width: 180 },
24
+ ],
25
+ };
26
+ }
27
+
28
+ async function performAs(accessToken: string, method: string, path: string, options = {}) {
29
+ return await app.bean.executor.newCtxIsolate(async () => {
30
+ return await (app.bean.executor.performAction as any)(method, path, {
31
+ ...options,
32
+ authToken: accessToken,
33
+ innerAccess: false,
34
+ });
35
+ });
36
+ }
37
+
38
+ async function registerAndSignin(name: string) {
39
+ const user = await app.bean.user.register({ name }, true);
40
+ const token = await app.bean.passport.signinMock(name as any);
41
+ return { token: token.accessToken, user };
42
+ }
43
+
44
+ async function deleteOwnedProfiles(userIds: readonly TableIdentity[], layoutKey: string) {
45
+ for (const userId of userIds) {
46
+ await app.scope('a-layoutprofile').model.layoutprofile.delete({ userId, layoutKey });
47
+ }
48
+ }
49
+
50
+ async function deleteOwnedUsers(userIds: readonly TableIdentity[]) {
51
+ for (const userId of userIds) {
52
+ await app.scope('home-user').model.roleUser.delete({ userId });
53
+ await app.bean.user.removeById(userId);
54
+ }
55
+ }
56
+
57
+ async function deleteOwnedTestData(userIds: readonly TableIdentity[], layoutKey: string) {
58
+ await deleteOwnedProfiles(userIds, layoutKey);
59
+ await deleteOwnedUsers(userIds);
60
+ }
61
+
62
+ describe('layoutprofile.test.ts', { concurrency: false }, () => {
63
+ it('rejects anonymous profile operations', async () => {
64
+ await app.bean.executor.mockCtx(async () => {
65
+ for (const [method, path, options] of [
66
+ ['get', `${actionPath}/load`, { query: { layoutKey: 'anonymous' } }],
67
+ [
68
+ 'post',
69
+ `${actionPath}/save`,
70
+ { body: { layoutKey: 'anonymous', profile: createProfile('anonymous') } },
71
+ ],
72
+ ['delete', `${actionPath}/reset`, { query: { layoutKey: 'anonymous' } }],
73
+ ] as const) {
74
+ const [, error] = await catchError(() =>
75
+ (app.bean.executor.performAction as any)(method, path, {
76
+ ...options,
77
+ innerAccess: false,
78
+ }),
79
+ );
80
+ assert.equal(error?.code, 401);
81
+ }
82
+ });
83
+ });
84
+
85
+ it('isolates profiles by authenticated user and supports reset', async () => {
86
+ await app.bean.executor.mockCtx(async () => {
87
+ const suffix = createTestId();
88
+ const layoutKey = `/training/student/${suffix}`;
89
+ let userA: TableIdentity | undefined;
90
+ let userB: TableIdentity | undefined;
91
+ try {
92
+ const customerA = await registerAndSignin(`layout-a-${suffix}`);
93
+ const customerB = await registerAndSignin(`layout-b-${suffix}`);
94
+ userA = customerA.user.id;
95
+ userB = customerB.user.id;
96
+ const profileA = createProfile('a');
97
+ const profileAUpdated = {
98
+ ...createProfile('a-updated'),
99
+ columns: [{ key: 'name', visible: false, width: 320 }],
100
+ } satisfies ILayoutProfile;
101
+ const profileB = createProfile('b');
102
+
103
+ assert.equal(
104
+ await performAs(customerA.token, 'get', `${actionPath}/load`, {
105
+ query: { layoutKey },
106
+ }),
107
+ undefined,
108
+ );
109
+ assert.deepEqual(
110
+ await performAs(customerA.token, 'post', `${actionPath}/save`, {
111
+ body: { layoutKey, profile: profileA },
112
+ }),
113
+ profileA,
114
+ );
115
+ const persistedA = await app.scope('a-layoutprofile').model.layoutprofile.get({
116
+ userId: userA,
117
+ layoutKey,
118
+ });
119
+ assert.equal(String(persistedA?.userId), String(userA));
120
+ assert.deepEqual(persistedA?.profile, profileA);
121
+
122
+ assert.equal(
123
+ await performAs(customerB.token, 'get', `${actionPath}/load`, {
124
+ query: { layoutKey },
125
+ }),
126
+ undefined,
127
+ );
128
+ assert.deepEqual(
129
+ await performAs(customerB.token, 'post', `${actionPath}/save`, {
130
+ body: { layoutKey, profile: profileB },
131
+ }),
132
+ profileB,
133
+ );
134
+ assert.deepEqual(
135
+ await performAs(customerA.token, 'post', `${actionPath}/save`, {
136
+ body: { layoutKey, profile: profileAUpdated },
137
+ }),
138
+ profileAUpdated,
139
+ );
140
+ const profilesA = await app.scope('a-layoutprofile').model.layoutprofile.select({
141
+ where: { userId: userA, layoutKey },
142
+ });
143
+ assert.equal(profilesA.length, 1);
144
+ assert.deepEqual(profilesA[0].profile, profileAUpdated);
145
+
146
+ assert.deepEqual(
147
+ await performAs(customerB.token, 'get', `${actionPath}/load`, {
148
+ query: { layoutKey },
149
+ }),
150
+ profileB,
151
+ );
152
+ assert.equal(
153
+ await performAs(customerB.token, 'delete', `${actionPath}/reset`, {
154
+ query: { layoutKey },
155
+ }),
156
+ null,
157
+ );
158
+ assert.equal(
159
+ await performAs(customerB.token, 'get', `${actionPath}/load`, {
160
+ query: { layoutKey },
161
+ }),
162
+ undefined,
163
+ );
164
+ assert.deepEqual(
165
+ await performAs(customerA.token, 'get', `${actionPath}/load`, {
166
+ query: { layoutKey },
167
+ }),
168
+ profileAUpdated,
169
+ );
170
+ } finally {
171
+ const userIds = [userA, userB].filter((id): id is TableIdentity => id !== undefined);
172
+ await deleteOwnedTestData(userIds, layoutKey);
173
+ }
174
+ });
175
+ });
176
+
177
+ it('serializes competing first saves for one user and layout key', async () => {
178
+ const suffix = createTestId();
179
+ const layoutKey = `/layout-concurrency/${suffix}`;
180
+ const fixture = await app.bean.executor.mockCtx(async () => {
181
+ const customer = await registerAndSignin(`layout-concurrency-${suffix}`);
182
+ return { token: customer.token, userId: customer.user.id };
183
+ });
184
+ const profiles = [createProfile('concurrency-a'), createProfile('concurrency-b')];
185
+ try {
186
+ const results = await Promise.allSettled(
187
+ profiles.map(profile =>
188
+ app.bean.executor.mockCtx(async () => {
189
+ return await performAs(fixture.token, 'post', `${actionPath}/save`, {
190
+ body: { layoutKey, profile },
191
+ });
192
+ }),
193
+ ),
194
+ );
195
+ assert.equal(results.filter(result => result.status === 'fulfilled').length, profiles.length);
196
+
197
+ const persisted = await app.bean.executor.mockCtx(async () => {
198
+ return await app.scope('a-layoutprofile').model.layoutprofile.select({
199
+ where: { userId: fixture.userId, layoutKey },
200
+ });
201
+ });
202
+ assert.equal(persisted.length, 1);
203
+ assert.ok(
204
+ profiles.some(profile => JSON.stringify(profile) === JSON.stringify(persisted[0].profile)),
205
+ );
206
+
207
+ const loaded = await app.bean.executor.mockCtx(async () => {
208
+ return await performAs(fixture.token, 'get', `${actionPath}/load`, {
209
+ query: { layoutKey },
210
+ });
211
+ });
212
+ assert.deepEqual(loaded, persisted[0].profile);
213
+ } finally {
214
+ await app.bean.executor.mockCtx(async () => {
215
+ await deleteOwnedTestData([fixture.userId], layoutKey);
216
+ });
217
+ }
218
+ });
219
+
220
+ it('validates the layout key and profile structure at the API boundary', async () => {
221
+ await app.bean.executor.mockCtx(async () => {
222
+ const suffix = createTestId();
223
+ const customer = await registerAndSignin(`layout-validation-${suffix}`);
224
+ const layoutKey = `/layout-validation/${suffix}`;
225
+ try {
226
+ for (const body of [
227
+ { layoutKey: '', profile: createProfile('invalid-key') },
228
+ { layoutKey, profile: { ...createProfile('version'), version: 2 } },
229
+ {
230
+ layoutKey,
231
+ profile: {
232
+ ...createProfile('width'),
233
+ columns: [{ key: 'name', visible: true, width: 0 }],
234
+ },
235
+ },
236
+ {
237
+ layoutKey,
238
+ profile: {
239
+ ...createProfile('visible'),
240
+ columns: [{ key: 'name', visible: 'yes', width: 'auto' }],
241
+ },
242
+ },
243
+ ]) {
244
+ const [, error] = await catchError(() =>
245
+ performAs(customer.token, 'post', `${actionPath}/save`, { body }),
246
+ );
247
+ assert.equal(
248
+ error?.code,
249
+ 422,
250
+ `unexpected validation result for ${JSON.stringify(body)}: ${JSON.stringify(error)}`,
251
+ );
252
+ }
253
+ } finally {
254
+ await deleteOwnedTestData([customer.user.id], layoutKey);
255
+ }
256
+ });
257
+ });
258
+ });
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.base",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "emitDeclarationOnly": true,
8
+ "outDir": "dist"
9
+ },
10
+ "include": ["src", "src/.metadata/*.ts", "src/**/*.json"]
11
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "../../tsconfig.base",
3
+ "compilerOptions": {
4
+ "noEmit": true
5
+ },
6
+ "include": ["src", "src/.metadata/*.ts", "src/**/*.json", "test"]
7
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vona-suite-a-cabloy",
3
- "version": "5.1.52",
3
+ "version": "5.1.53",
4
4
  "gitHead": "a79189b882c17af5911573896a781bbb0046d37d",
5
5
  "description": "",
6
6
  "author": "",
@@ -8,6 +8,7 @@
8
8
  "type": "module",
9
9
  "dependencies": {
10
10
  "vona-module-a-cabloy": "workspace:^",
11
+ "vona-module-a-layoutprofile": "^5.0.1",
11
12
  "vona-module-a-markdown": "^5.0.3",
12
13
  "vona-module-a-rbac": "^5.0.6",
13
14
  "vona-module-a-socket": "workspace:^",
@@ -28,6 +28,9 @@
28
28
  },
29
29
  {
30
30
  "path": "modules/a-rbac/tsconfig.build.json"
31
+ },
32
+ {
33
+ "path": "modules/a-layoutprofile/tsconfig.build.json"
31
34
  }
32
35
  ],
33
36
  "exclude": ["modules"]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova",
3
- "version": "5.1.161",
3
+ "version": "5.1.162",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "A vue3 framework with ioc",
6
6
  "keywords": [
@@ -46,7 +46,7 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "zova-core": "^5.1.89",
49
- "zova-suite-a-zova": "^5.1.160"
49
+ "zova-suite-a-zova": "^5.1.161"
50
50
  },
51
51
  "devDependencies": {
52
52
  "clean-package": "^2.2.0",
@@ -77,7 +77,7 @@ importers:
77
77
  version: 10.6.0(postcss@8.5.28)
78
78
  axios:
79
79
  specifier: ^1.18.1
80
- version: 1.20.0(supports-color@10.2.2)
80
+ version: 1.20.0
81
81
  compression:
82
82
  specifier: ^1.8.1
83
83
  version: 1.8.2
@@ -171,6 +171,9 @@ importers:
171
171
  zova-module-a-interceptor:
172
172
  specifier: workspace:^
173
173
  version: link:src/suite-vendor/a-zova/modules/a-interceptor
174
+ zova-module-a-layoutprofile:
175
+ specifier: workspace:^
176
+ version: link:src/suite-vendor/a-cabloy/modules/a-layoutprofile
174
177
  zova-module-a-logger:
175
178
  specifier: workspace:^
176
179
  version: link:src/suite-vendor/a-zova/modules/a-logger
@@ -363,7 +366,7 @@ importers:
363
366
  devDependencies:
364
367
  '@cabloy/cli':
365
368
  specifier: ^3.1.29
366
- version: 3.1.29(supports-color@10.2.2)(vue@3.5.42(typescript@5.9.3))
369
+ version: 3.1.29(vue@3.5.42(typescript@5.9.3))
367
370
  '@cabloy/lint':
368
371
  specifier: ^5.1.32
369
372
  version: 5.1.32(@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@10.10.0(jiti@2.7.0))(supports-color@10.2.2)(typescript@5.9.3))(eslint@10.10.0(jiti@2.7.0))(typescript@5.9.3))(@typescript-eslint/typescript-estree@8.70.0(typescript@5.9.3))(@typescript-eslint/utils@8.70.0(eslint@10.10.0(jiti@2.7.0))(typescript@5.9.3))(eslint@10.10.0(jiti@2.7.0))(oxfmt@0.62.0)(oxlint@1.82.0)(supports-color@10.2.2)(typescript@5.9.3)(vue-eslint-parser@10.4.1(eslint@10.10.0(jiti@2.7.0)))
@@ -438,7 +441,7 @@ importers:
438
441
  dependencies:
439
442
  '@cabloy/cli':
440
443
  specifier: ^3.1.29
441
- version: 3.1.29(supports-color@10.2.2)(vue@3.5.42(typescript@5.9.3))
444
+ version: 3.1.29(vue@3.5.42(typescript@5.9.3))
442
445
  '@cabloy/process-helper':
443
446
  specifier: ^3.1.8
444
447
  version: 3.1.8
@@ -472,7 +475,7 @@ importers:
472
475
  version: 7.29.7(@babel/core@7.29.7)
473
476
  '@cabloy/cli':
474
477
  specifier: ^3.1.29
475
- version: 3.1.29(supports-color@10.2.2)(vue@3.5.42(typescript@5.9.3))
478
+ version: 3.1.29(vue@3.5.42(typescript@5.9.3))
476
479
  '@cabloy/extend':
477
480
  specifier: ^3.2.8
478
481
  version: 3.2.8
@@ -870,7 +873,7 @@ importers:
870
873
  specifier: ^5.1.89
871
874
  version: link:../zova-core
872
875
  zova-suite-a-zova:
873
- specifier: ^5.1.158
876
+ specifier: ^5.1.161
874
877
  version: link:../../src/suite-vendor/a-zova
875
878
  devDependencies:
876
879
  clean-package:
@@ -973,13 +976,25 @@ importers:
973
976
 
974
977
  src/suite-vendor/a-cabloy:
975
978
  dependencies:
979
+ zova-module-a-layoutprofile:
980
+ specifier: ^5.0.2
981
+ version: link:modules/a-layoutprofile
976
982
  zova-module-a-rbac:
977
983
  specifier: ^5.0.1
978
984
  version: link:modules/a-rbac
979
985
  zova-module-rest-resource:
980
- specifier: ^5.1.52
986
+ specifier: ^5.1.54
981
987
  version: link:modules/rest-resource
982
988
 
989
+ src/suite-vendor/a-cabloy/modules/a-layoutprofile:
990
+ devDependencies:
991
+ clean-package:
992
+ specifier: ^2.2.0
993
+ version: 2.2.0
994
+ rimraf:
995
+ specifier: ^6.1.3
996
+ version: 6.1.3
997
+
983
998
  src/suite-vendor/a-cabloy/modules/a-rbac:
984
999
  devDependencies:
985
1000
  clean-package:
@@ -1058,7 +1073,7 @@ importers:
1058
1073
  specifier: ^5.1.26
1059
1074
  version: link:modules/a-app
1060
1075
  zova-module-a-bean:
1061
- specifier: ^5.1.33
1076
+ specifier: ^5.1.35
1062
1077
  version: link:modules/a-bean
1063
1078
  zova-module-a-behavior:
1064
1079
  specifier: ^5.1.26
@@ -1094,19 +1109,19 @@ importers:
1094
1109
  specifier: ^5.1.36
1095
1110
  version: link:modules/a-model
1096
1111
  zova-module-a-openapi:
1097
- specifier: ^5.1.53
1112
+ specifier: ^5.1.54
1098
1113
  version: link:modules/a-openapi
1099
1114
  zova-module-a-router:
1100
- specifier: ^5.1.35
1115
+ specifier: ^5.1.37
1101
1116
  version: link:modules/a-router
1102
1117
  zova-module-a-routerstack:
1103
- specifier: ^5.1.27
1118
+ specifier: ^5.1.29
1104
1119
  version: link:modules/a-routerstack
1105
1120
  zova-module-a-routertabs:
1106
1121
  specifier: ^5.1.34
1107
1122
  version: link:modules/a-routertabs
1108
1123
  zova-module-a-ssr:
1109
- specifier: ^5.1.38
1124
+ specifier: ^5.1.39
1110
1125
  version: link:modules/a-ssr
1111
1126
  zova-module-a-ssrhmr:
1112
1127
  specifier: ^5.1.23
@@ -1118,7 +1133,7 @@ importers:
1118
1133
  specifier: ^5.1.35
1119
1134
  version: link:modules/a-style
1120
1135
  zova-module-a-table:
1121
- specifier: ^5.1.40
1136
+ specifier: ^5.1.43
1122
1137
  version: link:modules/a-table
1123
1138
  zova-module-a-zod:
1124
1139
  specifier: ^5.1.37
@@ -1198,7 +1213,7 @@ importers:
1198
1213
  dependencies:
1199
1214
  axios:
1200
1215
  specifier: ^1.18.1
1201
- version: 1.20.0(supports-color@10.2.2)
1216
+ version: 1.20.0
1202
1217
  devDependencies:
1203
1218
  clean-package:
1204
1219
  specifier: ^2.2.0
@@ -1471,7 +1486,7 @@ importers:
1471
1486
  devDependencies:
1472
1487
  '@cabloy/cli':
1473
1488
  specifier: ^3.1.29
1474
- version: 3.1.29(supports-color@10.2.2)(vue@3.5.42(typescript@5.9.3))
1489
+ version: 3.1.29(vue@3.5.42(typescript@5.9.3))
1475
1490
  '@types/luxon':
1476
1491
  specifier: ^3.7.1
1477
1492
  version: 3.7.5
@@ -8814,7 +8829,7 @@ snapshots:
8814
8829
 
8815
8830
  '@bufbuild/protobuf@2.15.0': {}
8816
8831
 
8817
- '@cabloy/cli@3.1.29(supports-color@10.2.2)(vue@3.5.42(typescript@5.9.3))':
8832
+ '@cabloy/cli@3.1.29(vue@3.5.42(typescript@5.9.3))':
8818
8833
  dependencies:
8819
8834
  '@babel/parser': 7.29.8
8820
8835
  '@cabloy/module-glob': 5.3.18
@@ -8823,7 +8838,7 @@ snapshots:
8823
8838
  '@cabloy/utils': 2.1.27
8824
8839
  '@cabloy/word-utils': link:packages-utils/word-utils
8825
8840
  '@npmcli/config': 10.12.0
8826
- '@zhennann/common-bin': 4.0.1(supports-color@10.2.2)
8841
+ '@zhennann/common-bin': 4.0.1
8827
8842
  '@zhennann/ejs': 3.0.1
8828
8843
  boxen: 4.2.0
8829
8844
  chalk: 3.0.0
@@ -11011,7 +11026,7 @@ snapshots:
11011
11026
 
11012
11027
  '@vue/shared@3.5.13': {}
11013
11028
 
11014
- '@zhennann/common-bin@4.0.1(supports-color@10.2.2)':
11029
+ '@zhennann/common-bin@4.0.1':
11015
11030
  dependencies:
11016
11031
  chalk: 4.1.2
11017
11032
  change-case: 4.1.2
@@ -11045,7 +11060,7 @@ snapshots:
11045
11060
 
11046
11061
  acorn@8.18.0: {}
11047
11062
 
11048
- agent-base@6.0.2(supports-color@10.2.2):
11063
+ agent-base@6.0.2:
11049
11064
  dependencies:
11050
11065
  debug: 4.4.3(supports-color@10.2.2)
11051
11066
  transitivePeerDependencies:
@@ -11153,11 +11168,11 @@ snapshots:
11153
11168
  dependencies:
11154
11169
  possible-typed-array-names: 1.1.0
11155
11170
 
11156
- axios@1.20.0(supports-color@10.2.2):
11171
+ axios@1.20.0:
11157
11172
  dependencies:
11158
11173
  follow-redirects: 1.16.0
11159
11174
  form-data: 4.0.6
11160
- https-proxy-agent: 5.0.1(supports-color@10.2.2)
11175
+ https-proxy-agent: 5.0.1
11161
11176
  proxy-from-env: 2.1.0
11162
11177
  transitivePeerDependencies:
11163
11178
  - debug
@@ -12552,9 +12567,9 @@ snapshots:
12552
12567
  statuses: 2.0.2
12553
12568
  toidentifier: 1.0.1
12554
12569
 
12555
- https-proxy-agent@5.0.1(supports-color@10.2.2):
12570
+ https-proxy-agent@5.0.1:
12556
12571
  dependencies:
12557
- agent-base: 6.0.2(supports-color@10.2.2)
12572
+ agent-base: 6.0.2
12558
12573
  debug: 4.4.3(supports-color@10.2.2)
12559
12574
  transitivePeerDependencies:
12560
12575
  - supports-color
@@ -37,17 +37,26 @@ export class ServiceSsrLayout extends BeanBase {
37
37
  `<script id="__leftDrawerOpenJS">
38
38
  ${this.options?.sidebarLeftOpenPCCapability ? this._getJsHandlerSidebar() : ''}
39
39
  ${this._getJsHandlerPageContainer()}
40
- window.ssr_body_ready_handler=()=>{
41
- ${this.options?.sidebarLeftOpenPCCapability ? 'window.ssr_body_ready_handler_sidebar();' : ''}
42
- window.ssr_body_ready_handler_pageContainer();
40
+ window.ssr_body_ready_handler=__targets=>{
41
+ ${this.options?.sidebarLeftOpenPCCapability ? 'window.ssr_body_ready_handler_sidebar(__targets);' : ''}
42
+ window.ssr_body_ready_handler_pageContainer(__targets);
43
43
  };
44
44
  window.ssr_body_ready_condition=()=>{
45
+ const __domDrawerContainer=document.querySelector('#q-app>.drawer');
45
46
  const __domPageContainer=document.querySelector('#q-app>.drawer>.drawer-content');
46
- return __domPageContainer;
47
+ ${this.options?.sidebarLeftOpenPCCapability ? "const __domDrawer=document.querySelector('#q-app>.drawer>.drawer-side');" : ''}
48
+ return __domDrawerContainer&&__domPageContainer${this.options?.sidebarLeftOpenPCCapability ? '&&__domDrawer' : ''}?{
49
+ drawerContainer:__domDrawerContainer,
50
+ pageContainer:__domPageContainer,
51
+ ${this.options?.sidebarLeftOpenPCCapability ? 'drawer:__domDrawer,' : ''}
52
+ }:undefined;
47
53
  };
48
- window.ssr_body_ready_callback=()=>{
49
- window.ssr_body_ready_handler();
50
- document.querySelector('#__leftDrawerOpenJS').remove();
54
+ window.ssr_body_ready_callback=__targets=>{
55
+ try{
56
+ window.ssr_body_ready_handler(__targets);
57
+ }finally{
58
+ document.querySelector('#__leftDrawerOpenJS')?.remove();
59
+ }
51
60
  };
52
61
  </script>`.replaceAll('\n', '') + getBodyReadyObserverScript();
53
62
  }
@@ -61,7 +70,7 @@ export class ServiceSsrLayout extends BeanBase {
61
70
  }
62
71
 
63
72
  private _getJsHandlerSidebar() {
64
- return `window.ssr_body_ready_handler_sidebar=()=>{
73
+ return `window.ssr_body_ready_handler_sidebar=__targets=>{
65
74
  const __belowBreakpoint=document.documentElement.clientWidth <= ${this.options?.sidebarBreakpoint};
66
75
  let __leftDrawerOpen;
67
76
  if(__belowBreakpoint){
@@ -70,10 +79,11 @@ export class ServiceSsrLayout extends BeanBase {
70
79
  const __leftDrawerOpenPC=window.ssr_load_local('sidebarLeftOpenPC');
71
80
  __leftDrawerOpen=__leftDrawerOpenPC!==undefined?__leftDrawerOpenPC:${this.options?.sidebarLeftOpenPCFallback ?? false};
72
81
  }
73
- const __domDrawerContainer=document.querySelector('#q-app>.drawer');
74
- const __domDrawer=document.querySelector('#q-app>.drawer>.drawer-side');
82
+ const __domDrawerContainer=__targets?.drawerContainer;
83
+ const __domDrawer=__targets?.drawer;
75
84
  const sidebarWidth = '${this.scope.config.layout.sidebar.width}px';
76
85
  const navbarHeight = '${this.scope.config.layout.navbar.height}px';
86
+ if(!__domDrawerContainer||!__domDrawer)return;
77
87
  if(__leftDrawerOpen){
78
88
  __domDrawer.style.transform='translateX(0px)';
79
89
  __domDrawer.style.width=sidebarWidth;