cabloy 5.1.107 → 5.1.109
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/.cabloy-version +1 -1
- package/CHANGELOG.md +27 -0
- package/cabloy-docs/.vitepress/config.mjs +6 -0
- package/cabloy-docs/backend/multi-instance-and-instance-resolution.md +18 -0
- package/cabloy-docs/backend/runtime-and-flavors.md +2 -2
- package/cabloy-docs/backend/scripts.md +3 -2
- package/cabloy-docs/frontend/ssr-env.md +20 -0
- package/cabloy-docs/frontend/table-resource-crud-cookbook.md +33 -1
- package/cabloy-docs/fullstack/deploy-cloudflare-docker.md +136 -0
- package/package.json +1 -1
- package/vona/docker-compose-original/config/nginx/conf.d/nginx.conf +1 -1
- package/vona/env/.env +1 -1
- package/vona/pnpm-lock.yaml +16 -16
- package/vona/src/backend/config/config/config.ts +1 -1
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +2 -0
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +2 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +50 -1
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +21 -1
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +47 -1
- package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +47 -1
- package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +60 -2
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/pnpm-lock.yaml +27 -2
- package/zova/src/suite/cabloy-basic/modules/basic-form/src/.metadata/component/blockFormLayout.ts +31 -0
- package/zova/src/suite/cabloy-basic/modules/basic-form/src/.metadata/index.ts +13 -0
- package/zova/src/suite/cabloy-basic/modules/basic-form/src/component/blockFormLayout/controller.tsx +165 -0
- package/zova/src/suite/cabloy-basic/modules/basic-page/src/.metadata/component/blockFilterActions.ts +31 -0
- package/zova/src/suite/cabloy-basic/modules/basic-page/src/.metadata/index.ts +13 -0
- package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockFilter/controller.tsx +61 -31
- package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockFilterActions/controller.tsx +51 -0
- package/zova/src/suite/cabloy-basic/modules/basic-page/src/types/page.ts +10 -0
- package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockForm/controller.tsx +9 -2
- package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +5 -3
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/controller.tsx +44 -3
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/render.tsx +22 -4
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/controller.tsx +3 -2
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/lib/formLayout.ts +203 -0
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/lib/index.ts +1 -0
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/formField.ts +7 -4
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/formLayout.ts +59 -0
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/index.ts +1 -0
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/action.ts +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/resource/formLayout.ts +53 -0
- package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/resource/index.ts +1 -0
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +1 -1
- package/zova/src/suite-vendor/a-zova/package.json +4 -4
|
@@ -17,7 +17,53 @@ export interface IDtoOptionsStudentView extends IDecoratorDtoOptions {}
|
|
|
17
17
|
blocks: [
|
|
18
18
|
ZovaRender.block('basic-pageentry:blockPageEntry', {
|
|
19
19
|
blocks: [
|
|
20
|
-
ZovaRender.block('basic-pageentry:blockForm'
|
|
20
|
+
ZovaRender.block('basic-pageentry:blockForm', {
|
|
21
|
+
blocks: [
|
|
22
|
+
ZovaRender.block('basic-form:blockFormLayout', {
|
|
23
|
+
formLayout: {
|
|
24
|
+
children: [
|
|
25
|
+
{
|
|
26
|
+
type: 'tabs',
|
|
27
|
+
children: [
|
|
28
|
+
{
|
|
29
|
+
type: 'tab',
|
|
30
|
+
title: $locale('BasicInformation'),
|
|
31
|
+
children: [
|
|
32
|
+
{
|
|
33
|
+
type: 'group',
|
|
34
|
+
title: $locale('StudentProfile'),
|
|
35
|
+
children: [
|
|
36
|
+
{
|
|
37
|
+
type: 'section',
|
|
38
|
+
columns: { default: 1, md: 2 },
|
|
39
|
+
children: [
|
|
40
|
+
{ type: 'field', name: 'name' },
|
|
41
|
+
{ type: 'field', name: 'mobile' },
|
|
42
|
+
{ type: 'field', name: 'imageId' },
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: 'tab',
|
|
51
|
+
title: $locale('TrainingRecords'),
|
|
52
|
+
children: [
|
|
53
|
+
{ type: 'field', name: 'level' },
|
|
54
|
+
{
|
|
55
|
+
type: 'section',
|
|
56
|
+
children: [{ type: 'field', name: 'trainingRecords' }],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
],
|
|
66
|
+
}),
|
|
21
67
|
ZovaRender.block('basic-pageentry:blockToolbarRow', {
|
|
22
68
|
actions: [
|
|
23
69
|
ZovaRender.formActionRow('basic-form:actionBack', { permission: { public: true } }),
|
|
@@ -1,16 +1,74 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
DtoStudentCreate,
|
|
3
2
|
DtoStudentSelectRes,
|
|
4
3
|
DtoStudentSummary,
|
|
5
|
-
DtoStudentUpdate,
|
|
6
4
|
EntityStudent,
|
|
7
5
|
} from 'vona-module-training-student';
|
|
8
6
|
|
|
9
7
|
import assert from 'node:assert';
|
|
10
8
|
import { describe, it } from 'node:test';
|
|
11
9
|
import { app } from 'vona-mock';
|
|
10
|
+
import {
|
|
11
|
+
DtoStudentCreate,
|
|
12
|
+
DtoStudentSelectResItem,
|
|
13
|
+
DtoStudentUpdate,
|
|
14
|
+
DtoStudentView,
|
|
15
|
+
} from 'vona-module-training-student';
|
|
12
16
|
|
|
13
17
|
describe('student.test.ts', () => {
|
|
18
|
+
it('action:student:formLayoutMetadata', async () => {
|
|
19
|
+
await app.bean.executor.mockCtx(async () => {
|
|
20
|
+
for (const DtoClass of [DtoStudentCreate, DtoStudentUpdate, DtoStudentView]) {
|
|
21
|
+
const apiJson = await app.bean.openapi.generateJsonOfClass(DtoClass);
|
|
22
|
+
const component = Object.values(apiJson.components!.schemas as any).find(item => {
|
|
23
|
+
return (item as any).properties?.trainingRecords;
|
|
24
|
+
});
|
|
25
|
+
const blocks = (component as any)?.rest?.blocks;
|
|
26
|
+
const formLayout =
|
|
27
|
+
blocks?.[0]?.options?.blocks?.[0]?.options?.blocks?.[0]?.options?.formLayout;
|
|
28
|
+
const tabs = formLayout?.children[0];
|
|
29
|
+
const profileSection = tabs?.children[0]?.children[0]?.children[0];
|
|
30
|
+
const trainingRecordsSection = tabs?.children[1]?.children[1];
|
|
31
|
+
assert.equal(tabs?.type, 'tabs');
|
|
32
|
+
assert.equal(tabs?.id, undefined);
|
|
33
|
+
assert.equal(tabs?.children[1]?.type, 'tab');
|
|
34
|
+
assert.equal(tabs?.children[1]?.id, undefined);
|
|
35
|
+
assert.deepEqual(profileSection?.columns, { default: 1, md: 2 });
|
|
36
|
+
assert.deepEqual(
|
|
37
|
+
profileSection?.children.map(item => item.name),
|
|
38
|
+
['name', 'mobile', 'imageId'],
|
|
39
|
+
);
|
|
40
|
+
assert.equal(tabs?.children[1]?.children[0]?.name, 'level');
|
|
41
|
+
assert.deepEqual(
|
|
42
|
+
trainingRecordsSection?.children.map(item => item.name),
|
|
43
|
+
['trainingRecords'],
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('action:student:filterFormLayoutMetadata', async () => {
|
|
50
|
+
await app.bean.executor.mockCtx(async () => {
|
|
51
|
+
const apiJson = await app.bean.openapi.generateJsonOfClass(DtoStudentSelectResItem);
|
|
52
|
+
const component = Object.values(apiJson.components!.schemas as any).find(item => {
|
|
53
|
+
return (item as any).properties?._operationsRow;
|
|
54
|
+
});
|
|
55
|
+
const filterBlock = (component as any)?.rest?.blocks?.[0]?.options?.blocks?.[0];
|
|
56
|
+
assert.equal(filterBlock?.render, 'basic-page:blockFilter');
|
|
57
|
+
assert.equal(filterBlock?.options?.formFieldLayout?.inline, false);
|
|
58
|
+
assert.deepEqual(
|
|
59
|
+
filterBlock?.options?.blocks?.map(item => item.render),
|
|
60
|
+
['basic-form:blockFormLayout', 'basic-page:blockFilterActions'],
|
|
61
|
+
);
|
|
62
|
+
const formLayout = filterBlock?.options?.blocks?.[0]?.options?.formLayout;
|
|
63
|
+
assert.deepEqual(formLayout?.children[0]?.columns, { default: 1, md: 2 });
|
|
64
|
+
assert.deepEqual(
|
|
65
|
+
formLayout?.children[0]?.children.map(item => item.name),
|
|
66
|
+
['name', 'level', 'createdAt'],
|
|
67
|
+
);
|
|
68
|
+
assert.deepEqual(formLayout?.children[0]?.children[2]?.span, { default: 1, md: 2 });
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
14
72
|
it('action:student', async () => {
|
|
15
73
|
await app.bean.executor.mockCtx(async () => {
|
|
16
74
|
// data
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zova",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.137",
|
|
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.78",
|
|
49
|
-
"zova-suite-a-zova": "^5.1.
|
|
49
|
+
"zova-suite-a-zova": "^5.1.136"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"clean-package": "^2.2.0",
|
package/zova/pnpm-lock.yaml
CHANGED
|
@@ -1093,8 +1093,11 @@ importers:
|
|
|
1093
1093
|
src/suite-vendor/a-zova/modules/a-form:
|
|
1094
1094
|
dependencies:
|
|
1095
1095
|
'@tanstack/vue-form':
|
|
1096
|
-
specifier: ^1.
|
|
1097
|
-
version: 1.33.
|
|
1096
|
+
specifier: ^1.33.2
|
|
1097
|
+
version: 1.33.2(vue@3.5.38(typescript@5.9.3))
|
|
1098
|
+
'@tanstack/vue-store':
|
|
1099
|
+
specifier: ^0.11.0
|
|
1100
|
+
version: 0.11.0(vue@3.5.38(typescript@5.9.3))
|
|
1098
1101
|
devDependencies:
|
|
1099
1102
|
clean-package:
|
|
1100
1103
|
specifier: ^2.2.0
|
|
@@ -3931,6 +3934,9 @@ packages:
|
|
|
3931
3934
|
'@tanstack/form-core@1.33.0':
|
|
3932
3935
|
resolution: {integrity: sha512-AV4Pw9Dk4orFsuPBcDssfWMJFs+yMYBae7zZ4oTqrCf4ftNGQKxvrQRZeqKHG6A4TkiLeSvf2kzIjcVkrW7E6w==}
|
|
3933
3936
|
|
|
3937
|
+
'@tanstack/form-core@1.33.2':
|
|
3938
|
+
resolution: {integrity: sha512-F60zJd15bGrXKonc1kpRYnNRNfiES7F+hgvrPMrsZznPLqZtO2DIg76OU6R25kCYkqYQY5xvuKteuWcUsc587A==}
|
|
3939
|
+
|
|
3934
3940
|
'@tanstack/match-sorter-utils@8.19.4':
|
|
3935
3941
|
resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==}
|
|
3936
3942
|
engines: {node: '>=12'}
|
|
@@ -3957,6 +3963,11 @@ packages:
|
|
|
3957
3963
|
peerDependencies:
|
|
3958
3964
|
vue: ^3.4.0
|
|
3959
3965
|
|
|
3966
|
+
'@tanstack/vue-form@1.33.2':
|
|
3967
|
+
resolution: {integrity: sha512-yolxEs4XSQu2RhBpM48YgqmmpftR4v28XniH5UjGg9/Z3WOJAv+COSmWwC64ozs2OZIKF+j5ufu1ki62jtP6nA==}
|
|
3968
|
+
peerDependencies:
|
|
3969
|
+
vue: ^3.4.0
|
|
3970
|
+
|
|
3960
3971
|
'@tanstack/vue-query@5.101.1':
|
|
3961
3972
|
resolution: {integrity: sha512-w36v/HlCF2xRpdDCz7cygk99AwBWhZaT5No1dJOwqIZ1AR8q7tiovRyPFID/49gkjXG7KgXs/nHfRg+eCydH4Q==}
|
|
3962
3973
|
peerDependencies:
|
|
@@ -9729,6 +9740,12 @@ snapshots:
|
|
|
9729
9740
|
'@tanstack/pacer-lite': 0.1.1
|
|
9730
9741
|
'@tanstack/store': 0.11.0
|
|
9731
9742
|
|
|
9743
|
+
'@tanstack/form-core@1.33.2':
|
|
9744
|
+
dependencies:
|
|
9745
|
+
'@tanstack/devtools-event-client': 0.4.4
|
|
9746
|
+
'@tanstack/pacer-lite': 0.1.1
|
|
9747
|
+
'@tanstack/store': 0.11.0
|
|
9748
|
+
|
|
9732
9749
|
'@tanstack/match-sorter-utils@8.19.4':
|
|
9733
9750
|
dependencies:
|
|
9734
9751
|
remove-accents: 0.5.0
|
|
@@ -9753,6 +9770,14 @@ snapshots:
|
|
|
9753
9770
|
transitivePeerDependencies:
|
|
9754
9771
|
- '@vue/composition-api'
|
|
9755
9772
|
|
|
9773
|
+
'@tanstack/vue-form@1.33.2(vue@3.5.38(typescript@5.9.3))':
|
|
9774
|
+
dependencies:
|
|
9775
|
+
'@tanstack/form-core': 1.33.2
|
|
9776
|
+
'@tanstack/vue-store': 0.11.0(vue@3.5.38(typescript@5.9.3))
|
|
9777
|
+
vue: 3.5.38(typescript@5.9.3)
|
|
9778
|
+
transitivePeerDependencies:
|
|
9779
|
+
- '@vue/composition-api'
|
|
9780
|
+
|
|
9756
9781
|
'@tanstack/vue-query@5.101.1(vue@3.5.38(typescript@5.9.3))':
|
|
9757
9782
|
dependencies:
|
|
9758
9783
|
'@tanstack/match-sorter-utils': 8.19.4
|
package/zova/src/suite/cabloy-basic/modules/basic-form/src/.metadata/component/blockFormLayout.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TypeControllerInnerProps } from 'zova';
|
|
2
|
+
|
|
3
|
+
import { defineComponent } from 'vue';
|
|
4
|
+
import { prepareComponentOptions, useController } from 'zova';
|
|
5
|
+
|
|
6
|
+
import type { ControllerBlockFormLayoutProps } from '../../component/blockFormLayout/controller.jsx';
|
|
7
|
+
|
|
8
|
+
import { ControllerBlockFormLayout } from '../../component/blockFormLayout/controller.jsx';
|
|
9
|
+
export type ZBlockFormLayoutProps = {
|
|
10
|
+
controllerRef?: (ref: ControllerBlockFormLayout) => void;
|
|
11
|
+
} & ControllerBlockFormLayoutProps;
|
|
12
|
+
|
|
13
|
+
type ControllerInnerProps = TypeControllerInnerProps<
|
|
14
|
+
ControllerBlockFormLayoutProps,
|
|
15
|
+
keyof typeof ControllerBlockFormLayout.$propsDefault
|
|
16
|
+
>;
|
|
17
|
+
declare module 'zova-module-basic-form' {
|
|
18
|
+
export interface ControllerBlockFormLayout {
|
|
19
|
+
$props: ControllerInnerProps;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const ZBlockFormLayout = defineComponent((_props: ZBlockFormLayoutProps) => {
|
|
24
|
+
useController(ControllerBlockFormLayout, undefined, undefined);
|
|
25
|
+
return () => {};
|
|
26
|
+
}, prepareComponentOptions(ControllerBlockFormLayout.$componentOptions));
|
|
27
|
+
declare module 'zova-module-a-bean' {
|
|
28
|
+
export interface IVonaComponentRecord {
|
|
29
|
+
'basic-form:blockFormLayout': ControllerBlockFormLayoutProps;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/** controller: begin */
|
|
3
3
|
export * from '../component/actionBack/controller.jsx';
|
|
4
4
|
export * from '../component/actionSubmit/controller.jsx';
|
|
5
|
+
export * from '../component/blockFormLayout/controller.jsx';
|
|
5
6
|
|
|
6
7
|
import 'zova';
|
|
7
8
|
declare module 'zova' {
|
|
@@ -18,17 +19,24 @@ declare module 'zova-module-basic-form' {
|
|
|
18
19
|
export interface ControllerActionSubmit {
|
|
19
20
|
/** @internal */
|
|
20
21
|
get scope(): ScopeModuleBasicForm;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ControllerBlockFormLayout {
|
|
25
|
+
/** @internal */
|
|
26
|
+
get scope(): ScopeModuleBasicForm;
|
|
21
27
|
}
|
|
22
28
|
}
|
|
23
29
|
/** controller: end */
|
|
24
30
|
/** controller: begin */
|
|
25
31
|
import { ControllerActionBack } from '../component/actionBack/controller.jsx';
|
|
26
32
|
import { ControllerActionSubmit } from '../component/actionSubmit/controller.jsx';
|
|
33
|
+
import { ControllerBlockFormLayout } from '../component/blockFormLayout/controller.jsx';
|
|
27
34
|
import 'zova';
|
|
28
35
|
declare module 'zova' {
|
|
29
36
|
export interface IBeanRecordLocal {
|
|
30
37
|
'basic-form.controller.actionBack': ControllerActionBack;
|
|
31
38
|
'basic-form.controller.actionSubmit': ControllerActionSubmit;
|
|
39
|
+
'basic-form.controller.blockFormLayout': ControllerBlockFormLayout;
|
|
32
40
|
}
|
|
33
41
|
}
|
|
34
42
|
/** controller: end */
|
|
@@ -38,19 +46,24 @@ export * from './component/actionBack.js';
|
|
|
38
46
|
import { ZActionBack } from './component/actionBack.js';
|
|
39
47
|
export * from './component/actionSubmit.js';
|
|
40
48
|
import { ZActionSubmit } from './component/actionSubmit.js';
|
|
49
|
+
export * from './component/blockFormLayout.js';
|
|
50
|
+
import { ZBlockFormLayout } from './component/blockFormLayout.js';
|
|
41
51
|
export const components = {
|
|
42
52
|
'actionBack': ZActionBack,
|
|
43
53
|
'actionSubmit': ZActionSubmit,
|
|
54
|
+
'blockFormLayout': ZBlockFormLayout,
|
|
44
55
|
};
|
|
45
56
|
import 'zova';
|
|
46
57
|
declare module 'zova' {
|
|
47
58
|
export interface IComponentRecord {
|
|
48
59
|
'basic-form:actionBack': ControllerActionBack;
|
|
49
60
|
'basic-form:actionSubmit': ControllerActionSubmit;
|
|
61
|
+
'basic-form:blockFormLayout': ControllerBlockFormLayout;
|
|
50
62
|
}
|
|
51
63
|
export interface IZovaComponentRecord {
|
|
52
64
|
'basic-form:actionBack': typeof ZActionBack;
|
|
53
65
|
'basic-form:actionSubmit': typeof ZActionSubmit;
|
|
66
|
+
'basic-form:blockFormLayout': typeof ZBlockFormLayout;
|
|
54
67
|
}
|
|
55
68
|
}
|
|
56
69
|
/** components: end */
|
package/zova/src/suite/cabloy-basic/modules/basic-form/src/component/blockFormLayout/controller.tsx
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import type { IComponentOptions } from 'zova';
|
|
2
|
+
import type {
|
|
3
|
+
IJsxRenderContextForm,
|
|
4
|
+
IResolvedFormLayout,
|
|
5
|
+
IResolvedFormLayoutField,
|
|
6
|
+
IResolvedFormLayoutGroup,
|
|
7
|
+
IResolvedFormLayoutNode,
|
|
8
|
+
IResolvedFormLayoutSection,
|
|
9
|
+
IResolvedFormLayoutTab,
|
|
10
|
+
IResolvedFormLayoutTabs,
|
|
11
|
+
} from 'zova-module-a-form';
|
|
12
|
+
import type { IFormLayout, IResourceBlockOptionsBase } from 'zova-module-a-openapi';
|
|
13
|
+
|
|
14
|
+
import { classes } from 'typestyle';
|
|
15
|
+
import { useId } from 'vue';
|
|
16
|
+
import { BeanControllerBase, Use } from 'zova';
|
|
17
|
+
import { Controller } from 'zova-module-a-bean';
|
|
18
|
+
import { resolveFormLayout } from 'zova-module-a-form';
|
|
19
|
+
|
|
20
|
+
declare module 'zova-module-a-openapi' {
|
|
21
|
+
export interface IResourceBlockRecord {
|
|
22
|
+
'basic-form:blockFormLayout'?: ControllerBlockFormLayoutProps;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ControllerBlockFormLayoutProps extends IResourceBlockOptionsBase {
|
|
27
|
+
formLayout: IFormLayout;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Controller()
|
|
31
|
+
export class ControllerBlockFormLayout extends BeanControllerBase {
|
|
32
|
+
static $propsDefault = {};
|
|
33
|
+
static $componentOptions: IComponentOptions = { inheritAttrs: false, deepExtendDefault: true };
|
|
34
|
+
|
|
35
|
+
private formLayoutPlan: IResolvedFormLayout | undefined;
|
|
36
|
+
private formLayoutActiveTabs: Record<string, string | undefined> = {};
|
|
37
|
+
private formLayoutDomIdPrefix: string;
|
|
38
|
+
|
|
39
|
+
@Use({ injectionScope: 'host' })
|
|
40
|
+
$$renderContext: IJsxRenderContextForm;
|
|
41
|
+
|
|
42
|
+
protected async __init__() {
|
|
43
|
+
this.formLayoutDomIdPrefix = `basic-form-layout-${useId()}`;
|
|
44
|
+
this.formLayoutPlan = this.$computed(() => {
|
|
45
|
+
const { $$form } = this.$$renderContext;
|
|
46
|
+
const formLayout = this.$props.formLayout;
|
|
47
|
+
return resolveFormLayout(formLayout, $$form.properties);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
protected render() {
|
|
52
|
+
const plan = this.formLayoutPlan!;
|
|
53
|
+
return <>{plan.children.map(node => this._renderNode(node))}</>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private _renderNode(node: IResolvedFormLayoutNode) {
|
|
57
|
+
switch (node.type) {
|
|
58
|
+
case 'field':
|
|
59
|
+
return this._renderField(node);
|
|
60
|
+
case 'group':
|
|
61
|
+
return this._renderGroup(node);
|
|
62
|
+
case 'section':
|
|
63
|
+
return this._renderSection(node);
|
|
64
|
+
case 'tabs':
|
|
65
|
+
return this._renderTabs(node);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private _renderField(node: IResolvedFormLayoutField) {
|
|
70
|
+
const { $$form } = this.$$renderContext;
|
|
71
|
+
const span = this._gridClasses('col-span', node.span);
|
|
72
|
+
return <div class={span}>{$$form.renderField(node.name)}</div>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private _renderGroup(node: IResolvedFormLayoutGroup) {
|
|
76
|
+
return (
|
|
77
|
+
<fieldset class="fieldset mb-6 rounded-box border border-base-300 p-4">
|
|
78
|
+
{!!node.title && <legend class="fieldset-legend">{node.title}</legend>}
|
|
79
|
+
{!!node.description && <p class="mb-4 text-sm text-base-content/70">{node.description}</p>}
|
|
80
|
+
{node.children.map(child => this._renderNode(child))}
|
|
81
|
+
</fieldset>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private _renderSection(node: IResolvedFormLayoutSection) {
|
|
86
|
+
const className = classes('mb-6 grid gap-4', this._gridClasses('grid-cols', node.columns));
|
|
87
|
+
return (
|
|
88
|
+
<section>
|
|
89
|
+
{!!node.title && <h3 class="mb-1 text-lg font-semibold">{node.title}</h3>}
|
|
90
|
+
{!!node.description && <p class="mb-4 text-sm text-base-content/70">{node.description}</p>}
|
|
91
|
+
<div class={className}>{node.children.map(child => this._renderField(child))}</div>
|
|
92
|
+
</section>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private getActiveTabId(node: IResolvedFormLayoutTabs) {
|
|
97
|
+
const activeTabId = this.formLayoutActiveTabs[node.id];
|
|
98
|
+
if (node.children.some(tab => tab.id === activeTabId)) return activeTabId;
|
|
99
|
+
const fallbackTabId = node.children[0]?.id;
|
|
100
|
+
this.formLayoutActiveTabs[node.id] = fallbackTabId;
|
|
101
|
+
return fallbackTabId;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private setActiveTab(tabsId: string, tabId: string) {
|
|
105
|
+
this.formLayoutActiveTabs[tabsId] = tabId;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private _renderTabs(node: IResolvedFormLayoutTabs) {
|
|
109
|
+
const { $$form } = this.$$renderContext;
|
|
110
|
+
const activeTabId = this.getActiveTabId(node);
|
|
111
|
+
const domIdBase = `${this.formLayoutDomIdPrefix}-${node.id}`;
|
|
112
|
+
return (
|
|
113
|
+
<div class="mb-6">
|
|
114
|
+
<div role="tablist" class="tabs tabs-lifted">
|
|
115
|
+
{node.children.map(tab => {
|
|
116
|
+
const active = tab.id === activeTabId;
|
|
117
|
+
const errorFieldCount = $$form.getErrorFieldCount(tab);
|
|
118
|
+
const invalid = errorFieldCount > 0;
|
|
119
|
+
return (
|
|
120
|
+
<button
|
|
121
|
+
id={`${domIdBase}-${tab.id}-tab`}
|
|
122
|
+
role="tab"
|
|
123
|
+
type="button"
|
|
124
|
+
class={classes('tab', active && 'tab-active')}
|
|
125
|
+
aria-selected={active}
|
|
126
|
+
aria-controls={`${domIdBase}-${tab.id}-panel`}
|
|
127
|
+
onClick={() => this.setActiveTab(node.id, tab.id)}
|
|
128
|
+
>
|
|
129
|
+
{tab.title}
|
|
130
|
+
{invalid && <span class="badge badge-error badge-sm ml-1">{errorFieldCount}</span>}
|
|
131
|
+
</button>
|
|
132
|
+
);
|
|
133
|
+
})}
|
|
134
|
+
</div>
|
|
135
|
+
{node.children.map(tab => this._renderTabPanel(domIdBase, tab, tab.id === activeTabId))}
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private _renderTabPanel(domIdBase: string, tab: IResolvedFormLayoutTab, active: boolean) {
|
|
141
|
+
return (
|
|
142
|
+
<div
|
|
143
|
+
id={`${domIdBase}-${tab.id}-panel`}
|
|
144
|
+
role="tabpanel"
|
|
145
|
+
aria-labelledby={`${domIdBase}-${tab.id}-tab`}
|
|
146
|
+
hidden={!active}
|
|
147
|
+
class="rounded-box border border-base-300 bg-base-100 p-4"
|
|
148
|
+
>
|
|
149
|
+
{tab.children.map(child => this._renderNode(child))}
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private _gridClasses(
|
|
155
|
+
prefix: 'grid-cols' | 'col-span',
|
|
156
|
+
columns?: { default?: number; md?: number; lg?: number },
|
|
157
|
+
) {
|
|
158
|
+
const classes: string[] = [];
|
|
159
|
+
const valueDefault = columns?.default ?? (prefix === 'grid-cols' ? 1 : undefined);
|
|
160
|
+
if (valueDefault) classes.push(`${prefix}-${valueDefault}`);
|
|
161
|
+
if (columns?.md) classes.push(`md:${prefix}-${columns.md}`);
|
|
162
|
+
if (columns?.lg) classes.push(`lg:${prefix}-${columns.lg}`);
|
|
163
|
+
return classes.join(' ');
|
|
164
|
+
}
|
|
165
|
+
}
|
package/zova/src/suite/cabloy-basic/modules/basic-page/src/.metadata/component/blockFilterActions.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TypeControllerInnerProps } from 'zova';
|
|
2
|
+
|
|
3
|
+
import { defineComponent } from 'vue';
|
|
4
|
+
import { prepareComponentOptions, useController } from 'zova';
|
|
5
|
+
|
|
6
|
+
import type { ControllerBlockFilterActionsProps } from '../../component/blockFilterActions/controller.jsx';
|
|
7
|
+
|
|
8
|
+
import { ControllerBlockFilterActions } from '../../component/blockFilterActions/controller.jsx';
|
|
9
|
+
export type ZBlockFilterActionsProps = {
|
|
10
|
+
controllerRef?: (ref: ControllerBlockFilterActions) => void;
|
|
11
|
+
} & ControllerBlockFilterActionsProps;
|
|
12
|
+
|
|
13
|
+
type ControllerInnerProps = TypeControllerInnerProps<
|
|
14
|
+
ControllerBlockFilterActionsProps,
|
|
15
|
+
keyof typeof ControllerBlockFilterActions.$propsDefault
|
|
16
|
+
>;
|
|
17
|
+
declare module 'zova-module-basic-page' {
|
|
18
|
+
export interface ControllerBlockFilterActions {
|
|
19
|
+
$props: ControllerInnerProps;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const ZBlockFilterActions = defineComponent((_props: ZBlockFilterActionsProps) => {
|
|
24
|
+
useController(ControllerBlockFilterActions, undefined, undefined);
|
|
25
|
+
return () => {};
|
|
26
|
+
}, prepareComponentOptions(ControllerBlockFilterActions.$componentOptions));
|
|
27
|
+
declare module 'zova-module-a-bean' {
|
|
28
|
+
export interface IVonaComponentRecord {
|
|
29
|
+
'basic-page:blockFilterActions': ControllerBlockFilterActionsProps;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// eslint-disable
|
|
2
2
|
/** controller: begin */
|
|
3
3
|
export * from '../component/blockFilter/controller.jsx';
|
|
4
|
+
export * from '../component/blockFilterActions/controller.jsx';
|
|
4
5
|
export * from '../component/blockPage/controller.jsx';
|
|
5
6
|
export * from '../component/blockPager/controller.jsx';
|
|
6
7
|
export * from '../component/blockTable/controller.jsx';
|
|
@@ -18,6 +19,11 @@ declare module 'zova-module-basic-page' {
|
|
|
18
19
|
get scope(): ScopeModuleBasicPage;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
export interface ControllerBlockFilterActions {
|
|
23
|
+
/** @internal */
|
|
24
|
+
get scope(): ScopeModuleBasicPage;
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
export interface ControllerBlockPage {
|
|
22
28
|
/** @internal */
|
|
23
29
|
get scope(): ScopeModuleBasicPage;
|
|
@@ -41,6 +47,7 @@ declare module 'zova-module-basic-page' {
|
|
|
41
47
|
/** controller: end */
|
|
42
48
|
/** controller: begin */
|
|
43
49
|
import { ControllerBlockFilter } from '../component/blockFilter/controller.jsx';
|
|
50
|
+
import { ControllerBlockFilterActions } from '../component/blockFilterActions/controller.jsx';
|
|
44
51
|
import { ControllerBlockPage } from '../component/blockPage/controller.jsx';
|
|
45
52
|
import { ControllerBlockPager } from '../component/blockPager/controller.jsx';
|
|
46
53
|
import { ControllerBlockTable } from '../component/blockTable/controller.jsx';
|
|
@@ -49,6 +56,7 @@ import 'zova';
|
|
|
49
56
|
declare module 'zova' {
|
|
50
57
|
export interface IBeanRecordLocal {
|
|
51
58
|
'basic-page.controller.blockFilter': ControllerBlockFilter;
|
|
59
|
+
'basic-page.controller.blockFilterActions': ControllerBlockFilterActions;
|
|
52
60
|
'basic-page.controller.blockPage': ControllerBlockPage;
|
|
53
61
|
'basic-page.controller.blockPager': ControllerBlockPager;
|
|
54
62
|
'basic-page.controller.blockTable': ControllerBlockTable;
|
|
@@ -60,6 +68,8 @@ declare module 'zova' {
|
|
|
60
68
|
/** components: begin */
|
|
61
69
|
export * from './component/blockFilter.js';
|
|
62
70
|
import { ZBlockFilter } from './component/blockFilter.js';
|
|
71
|
+
export * from './component/blockFilterActions.js';
|
|
72
|
+
import { ZBlockFilterActions } from './component/blockFilterActions.js';
|
|
63
73
|
export * from './component/blockPage.js';
|
|
64
74
|
import { ZBlockPage } from './component/blockPage.js';
|
|
65
75
|
export * from './component/blockPager.js';
|
|
@@ -70,6 +80,7 @@ export * from './component/blockToolbarBulk.js';
|
|
|
70
80
|
import { ZBlockToolbarBulk } from './component/blockToolbarBulk.js';
|
|
71
81
|
export const components = {
|
|
72
82
|
'blockFilter': ZBlockFilter,
|
|
83
|
+
'blockFilterActions': ZBlockFilterActions,
|
|
73
84
|
'blockPage': ZBlockPage,
|
|
74
85
|
'blockPager': ZBlockPager,
|
|
75
86
|
'blockTable': ZBlockTable,
|
|
@@ -79,6 +90,7 @@ import 'zova';
|
|
|
79
90
|
declare module 'zova' {
|
|
80
91
|
export interface IComponentRecord {
|
|
81
92
|
'basic-page:blockFilter': ControllerBlockFilter;
|
|
93
|
+
'basic-page:blockFilterActions': ControllerBlockFilterActions;
|
|
82
94
|
'basic-page:blockPage': ControllerBlockPage;
|
|
83
95
|
'basic-page:blockPager': ControllerBlockPager;
|
|
84
96
|
'basic-page:blockTable': ControllerBlockTable;
|
|
@@ -86,6 +98,7 @@ export interface IComponentRecord {
|
|
|
86
98
|
}
|
|
87
99
|
export interface IZovaComponentRecord {
|
|
88
100
|
'basic-page:blockFilter': typeof ZBlockFilter;
|
|
101
|
+
'basic-page:blockFilterActions': typeof ZBlockFilterActions;
|
|
89
102
|
'basic-page:blockPage': typeof ZBlockPage;
|
|
90
103
|
'basic-page:blockPager': typeof ZBlockPager;
|
|
91
104
|
'basic-page:blockTable': typeof ZBlockTable;
|