cabloy 5.1.108 → 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.
Files changed (39) hide show
  1. package/.cabloy-version +1 -1
  2. package/CHANGELOG.md +17 -0
  3. package/cabloy-docs/frontend/table-resource-crud-cookbook.md +33 -1
  4. package/package.json +1 -1
  5. package/vona/pnpm-lock.yaml +16 -16
  6. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +2 -0
  7. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +2 -0
  8. package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +50 -1
  9. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +21 -1
  10. package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +47 -1
  11. package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +47 -1
  12. package/vona/src/suite/a-training/modules/training-student/test/student.test.ts +60 -2
  13. package/zova/packages-zova/zova/package.json +2 -2
  14. package/zova/pnpm-lock.yaml +27 -2
  15. package/zova/src/suite/cabloy-basic/modules/basic-form/src/.metadata/component/blockFormLayout.ts +31 -0
  16. package/zova/src/suite/cabloy-basic/modules/basic-form/src/.metadata/index.ts +13 -0
  17. package/zova/src/suite/cabloy-basic/modules/basic-form/src/component/blockFormLayout/controller.tsx +165 -0
  18. package/zova/src/suite/cabloy-basic/modules/basic-page/src/.metadata/component/blockFilterActions.ts +31 -0
  19. package/zova/src/suite/cabloy-basic/modules/basic-page/src/.metadata/index.ts +13 -0
  20. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockFilter/controller.tsx +61 -31
  21. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockFilterActions/controller.tsx +51 -0
  22. package/zova/src/suite/cabloy-basic/modules/basic-page/src/types/page.ts +10 -0
  23. package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockForm/controller.tsx +9 -2
  24. package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +5 -3
  25. package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/controller.tsx +44 -3
  26. package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/render.tsx +22 -4
  27. package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/controller.tsx +3 -2
  28. package/zova/src/suite-vendor/a-zova/modules/a-form/src/lib/formLayout.ts +203 -0
  29. package/zova/src/suite-vendor/a-zova/modules/a-form/src/lib/index.ts +1 -0
  30. package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/formField.ts +7 -4
  31. package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/formLayout.ts +59 -0
  32. package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/index.ts +1 -0
  33. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
  34. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/action.ts +1 -1
  35. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/resource/formLayout.ts +53 -0
  36. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/resource/index.ts +1 -0
  37. package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
  38. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +1 -1
  39. package/zova/src/suite-vendor/a-zova/package.json +4 -4
@@ -33,13 +33,34 @@ export class RenderForm extends BeanRenderBase {
33
33
  return children;
34
34
  }
35
35
 
36
+ private _renderFromBlocks() {
37
+ const blocks = this.$props.blocks;
38
+ if (!blocks || blocks.length === 0) {
39
+ return this._renderSchema();
40
+ }
41
+ const celScope = this.getFormScope();
42
+ const jsxRenderContext = this.getFormJsxRenderContext(celScope);
43
+ const domBlocks: VNode[] = [];
44
+ blocks.forEach((block, index) => {
45
+ const options = Object.assign({ key: index }, block.options);
46
+ const domBlock = this.zovaJsx.render(block.render!, options, celScope, jsxRenderContext);
47
+ if (!domBlock) return;
48
+ if (Array.isArray(domBlock)) {
49
+ domBlocks.push(...domBlock);
50
+ } else {
51
+ domBlocks.push(domBlock);
52
+ }
53
+ });
54
+ return domBlocks;
55
+ }
56
+
36
57
  private _renderBodyInner() {
37
58
  const FormTag = this.$props.formTag;
38
59
  return this.$slotDefault ? (
39
60
  this.$slotDefault(this)
40
61
  ) : (
41
62
  <>
42
- {this._renderSchema()}
63
+ {this.$props.blocks ? this._renderFromBlocks() : this._renderSchema()}
43
64
  {FormTag === 'form' && <button type="submit" style={{ display: 'none' }}></button>}
44
65
  </>
45
66
  );
@@ -48,9 +69,6 @@ export class RenderForm extends BeanRenderBase {
48
69
  private _renderProps() {
49
70
  const FormTag = this.$props.formTag;
50
71
  const props: any = {};
51
- if (this.$props.inline) {
52
- props.class = 'inline';
53
- }
54
72
  if (FormTag === 'form') {
55
73
  props.onSubmit = (e: SubmitEvent) => {
56
74
  if (this.$props.onFormSubmit) {
@@ -1,5 +1,6 @@
1
1
  import { isNil } from '@cabloy/utils';
2
- import { useField, useStore } from '@tanstack/vue-form';
2
+ import { useField } from '@tanstack/vue-form';
3
+ import { useSelector } from '@tanstack/vue-store';
3
4
  import { markRaw } from 'vue';
4
5
  import z from 'zod';
5
6
  import { BeanControllerBase, deepEqual, IComponentOptions, Use } from 'zova';
@@ -139,7 +140,7 @@ export class ControllerFormField<TParentData extends {} = {}> extends BeanContro
139
140
  private _createField() {
140
141
  const options = this._getFormFieldOptions();
141
142
  const field = markRaw(useField(options as any)) as any;
142
- const fieldState = useStore(field.api.store, state => state) as any;
143
+ const fieldState = useSelector(field.api.store, state => state) as any;
143
144
  return { api: field.api, state: fieldState };
144
145
  }
145
146
 
@@ -0,0 +1,203 @@
1
+ import type {
2
+ IFormLayout,
3
+ IFormLayoutField,
4
+ IFormLayoutNode,
5
+ IFormLayoutTab,
6
+ IFormLayoutTabs,
7
+ ISchemaObjectExtensionField,
8
+ } from 'zova-module-a-openapi';
9
+
10
+ import type {
11
+ IFormLayoutDiagnostic,
12
+ IResolvedFormLayout,
13
+ IResolvedFormLayoutField,
14
+ IResolvedFormLayoutGroup,
15
+ IResolvedFormLayoutNode,
16
+ IResolvedFormLayoutSection,
17
+ IResolvedFormLayoutTab,
18
+ IResolvedFormLayoutTabs,
19
+ } from '../types/formLayout.js';
20
+
21
+ export function resolveFormLayout(
22
+ layout: IFormLayout,
23
+ properties: ISchemaObjectExtensionField[] | undefined,
24
+ ): IResolvedFormLayout {
25
+ const propertyNames = new Set(
26
+ properties
27
+ ?.filter(item => item.rest?.visible !== false)
28
+ .map(item => item.key)
29
+ .filter(Boolean) as string[],
30
+ );
31
+ const fieldNames = new Set<string>();
32
+ const nodeIds = new Set<string>();
33
+ const diagnostics: IFormLayoutDiagnostic[] = [];
34
+ const fieldTabPaths: IResolvedFormLayout['fieldTabPaths'] = {};
35
+ const children = layout.children
36
+ .map((node, index) =>
37
+ resolveNode(
38
+ node,
39
+ [index],
40
+ [],
41
+ propertyNames,
42
+ fieldNames,
43
+ nodeIds,
44
+ diagnostics,
45
+ fieldTabPaths,
46
+ ),
47
+ )
48
+ .filter(Boolean) as IResolvedFormLayoutNode[];
49
+ for (const property of properties ?? []) {
50
+ const name = property.key;
51
+ if (!name || !propertyNames.has(name) || fieldNames.has(name)) continue;
52
+ fieldNames.add(name);
53
+ children.push({ type: 'field', name });
54
+ }
55
+ return { children, fieldTabPaths, diagnostics };
56
+ }
57
+
58
+ function resolveNode(
59
+ node: IFormLayoutNode,
60
+ indexPath: number[],
61
+ tabPath: IResolvedFormLayout['fieldTabPaths'][string],
62
+ propertyNames: Set<string>,
63
+ fieldNames: Set<string>,
64
+ nodeIds: Set<string>,
65
+ diagnostics: IFormLayoutDiagnostic[],
66
+ fieldTabPaths: IResolvedFormLayout['fieldTabPaths'],
67
+ ): IResolvedFormLayoutNode | undefined {
68
+ if (node.type === 'field') {
69
+ return resolveField(node, tabPath, propertyNames, fieldNames, diagnostics, fieldTabPaths);
70
+ }
71
+ if (node.type === 'tabs') {
72
+ return resolveTabs(
73
+ node,
74
+ indexPath,
75
+ propertyNames,
76
+ fieldNames,
77
+ nodeIds,
78
+ diagnostics,
79
+ fieldTabPaths,
80
+ );
81
+ }
82
+ const id = resolveId(node, indexPath);
83
+ if (!registerId(id, nodeIds, diagnostics)) return;
84
+ if (node.type === 'section') {
85
+ const children = node.children
86
+ .map(item =>
87
+ resolveField(item, tabPath, propertyNames, fieldNames, diagnostics, fieldTabPaths),
88
+ )
89
+ .filter(Boolean) as IResolvedFormLayoutField[];
90
+ return children.length ? { ...node, id, children } : undefined;
91
+ }
92
+ const children = node.children
93
+ .map((item, index) =>
94
+ resolveNode(
95
+ item,
96
+ [...indexPath, index],
97
+ tabPath,
98
+ propertyNames,
99
+ fieldNames,
100
+ nodeIds,
101
+ diagnostics,
102
+ fieldTabPaths,
103
+ ),
104
+ )
105
+ .filter(Boolean) as Array<
106
+ IResolvedFormLayoutField | IResolvedFormLayoutGroup | IResolvedFormLayoutSection
107
+ >;
108
+ return children.length ? { ...node, id, children } : undefined;
109
+ }
110
+
111
+ function resolveTabs(
112
+ node: IFormLayoutTabs,
113
+ indexPath: number[],
114
+ propertyNames: Set<string>,
115
+ fieldNames: Set<string>,
116
+ nodeIds: Set<string>,
117
+ diagnostics: IFormLayoutDiagnostic[],
118
+ fieldTabPaths: IResolvedFormLayout['fieldTabPaths'],
119
+ ): IResolvedFormLayoutTabs | undefined {
120
+ const id = resolveId(node, indexPath);
121
+ if (!registerId(id, nodeIds, diagnostics)) return;
122
+ const children = node.children
123
+ .map((tab, index) =>
124
+ resolveTab(
125
+ tab,
126
+ [...indexPath, index],
127
+ id,
128
+ propertyNames,
129
+ fieldNames,
130
+ nodeIds,
131
+ diagnostics,
132
+ fieldTabPaths,
133
+ ),
134
+ )
135
+ .filter(Boolean) as IResolvedFormLayoutTab[];
136
+ return children.length ? { ...node, id, children } : undefined;
137
+ }
138
+
139
+ function resolveTab(
140
+ node: IFormLayoutTab,
141
+ indexPath: number[],
142
+ tabsId: string,
143
+ propertyNames: Set<string>,
144
+ fieldNames: Set<string>,
145
+ nodeIds: Set<string>,
146
+ diagnostics: IFormLayoutDiagnostic[],
147
+ fieldTabPaths: IResolvedFormLayout['fieldTabPaths'],
148
+ ): IResolvedFormLayoutTab | undefined {
149
+ const id = resolveId(node, indexPath);
150
+ if (!registerId(id, nodeIds, diagnostics)) return;
151
+ const tabPath = [{ tabsId, tabId: id }];
152
+ const children = node.children
153
+ .map((item, index) =>
154
+ resolveNode(
155
+ item,
156
+ [...indexPath, index],
157
+ tabPath,
158
+ propertyNames,
159
+ fieldNames,
160
+ nodeIds,
161
+ diagnostics,
162
+ fieldTabPaths,
163
+ ),
164
+ )
165
+ .filter(Boolean) as Array<
166
+ IResolvedFormLayoutField | IResolvedFormLayoutGroup | IResolvedFormLayoutSection
167
+ >;
168
+ return children.length ? { ...node, id, children } : undefined;
169
+ }
170
+
171
+ function resolveField(
172
+ node: IFormLayoutField,
173
+ tabPath: IResolvedFormLayout['fieldTabPaths'][string],
174
+ propertyNames: Set<string>,
175
+ fieldNames: Set<string>,
176
+ diagnostics: IFormLayoutDiagnostic[],
177
+ fieldTabPaths: IResolvedFormLayout['fieldTabPaths'],
178
+ ): IResolvedFormLayoutField | undefined {
179
+ if (!propertyNames.has(node.name)) {
180
+ diagnostics.push({ type: 'unknownField', value: node.name });
181
+ return;
182
+ }
183
+ if (fieldNames.has(node.name)) {
184
+ diagnostics.push({ type: 'duplicateField', value: node.name });
185
+ return;
186
+ }
187
+ fieldNames.add(node.name);
188
+ fieldTabPaths[node.name] = tabPath;
189
+ return node;
190
+ }
191
+
192
+ function resolveId(node: { type: string; id?: string }, indexPath: number[]) {
193
+ return node.id || `${node.type}-${indexPath.join('-')}`;
194
+ }
195
+
196
+ function registerId(id: string, ids: Set<string>, diagnostics: IFormLayoutDiagnostic[]) {
197
+ if (!ids.has(id)) {
198
+ ids.add(id);
199
+ return true;
200
+ }
201
+ diagnostics.push({ type: 'duplicateId', value: id });
202
+ return false;
203
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './beanControllerFormBase.js';
2
2
  export * from './beanControllerPageFormBase.js';
3
3
  export * from './utils.js';
4
+ export * from './formLayout.js';
@@ -17,7 +17,7 @@ import { types } from 'typestyle';
17
17
 
18
18
  import type { ControllerForm } from '../component/form/controller.jsx';
19
19
  import type { ControllerFormField } from '../component/formField/controller.jsx';
20
- import type { TypeBehaviorFormFieldOptions } from './form.js';
20
+ import type { IFormScope, TypeBehaviorFormFieldOptions } from './form.js';
21
21
 
22
22
  export type HTMLInputElementType =
23
23
  | 'text'
@@ -139,7 +139,10 @@ export interface IJsxRenderContextFormField<
139
139
  $$form: ControllerForm<TParentData, TSubmitMeta>;
140
140
  }
141
141
 
142
- export interface IJsxRenderContextForm<TParentData extends {} = {}> extends IJsxRenderContextBase {
143
- $celScope: IFormFieldScope<TParentData>;
144
- $$form: ControllerForm<TParentData>;
142
+ export interface IJsxRenderContextForm<
143
+ TParentData extends {} = {},
144
+ TSubmitMeta = never,
145
+ > extends IJsxRenderContextBase {
146
+ $celScope: IFormScope;
147
+ $$form: ControllerForm<TParentData, TSubmitMeta>;
145
148
  }
@@ -0,0 +1,59 @@
1
+ import type { IFormLayoutResponsiveColumns } from 'zova-module-a-openapi';
2
+
3
+ export interface IResolvedFormLayout {
4
+ children: IResolvedFormLayoutNode[];
5
+ fieldTabPaths: Record<string, IResolvedFormLayoutTabRef[]>;
6
+ diagnostics: IFormLayoutDiagnostic[];
7
+ }
8
+
9
+ export interface IResolvedFormLayoutField {
10
+ type: 'field';
11
+ name: string;
12
+ span?: IFormLayoutResponsiveColumns;
13
+ }
14
+
15
+ export interface IResolvedFormLayoutGroup {
16
+ type: 'group';
17
+ id: string;
18
+ title?: string;
19
+ description?: string;
20
+ children: Array<IResolvedFormLayoutField | IResolvedFormLayoutGroup | IResolvedFormLayoutSection>;
21
+ }
22
+
23
+ export interface IResolvedFormLayoutSection {
24
+ type: 'section';
25
+ id: string;
26
+ title?: string;
27
+ description?: string;
28
+ columns?: IFormLayoutResponsiveColumns;
29
+ children: IResolvedFormLayoutField[];
30
+ }
31
+
32
+ export interface IResolvedFormLayoutTabs {
33
+ type: 'tabs';
34
+ id: string;
35
+ children: IResolvedFormLayoutTab[];
36
+ }
37
+
38
+ export interface IResolvedFormLayoutTab {
39
+ type: 'tab';
40
+ id: string;
41
+ title: string;
42
+ children: Array<IResolvedFormLayoutField | IResolvedFormLayoutGroup | IResolvedFormLayoutSection>;
43
+ }
44
+
45
+ export interface IResolvedFormLayoutTabRef {
46
+ tabsId: string;
47
+ tabId: string;
48
+ }
49
+
50
+ export type IResolvedFormLayoutNode =
51
+ | IResolvedFormLayoutField
52
+ | IResolvedFormLayoutGroup
53
+ | IResolvedFormLayoutSection
54
+ | IResolvedFormLayoutTabs;
55
+
56
+ export interface IFormLayoutDiagnostic {
57
+ type: 'duplicateField' | 'unknownField' | 'duplicateId';
58
+ value: string;
59
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './form.js';
2
2
  export * from './formField.js';
3
+ export * from './formLayout.js';
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-module-a-openapi",
3
- "version": "5.1.43",
3
+ "version": "5.1.44",
4
4
  "gitHead": "09d901d17140a80ee0764211b441cda72fd94663",
5
5
  "description": "",
6
6
  "keywords": [
@@ -31,7 +31,7 @@ export interface IJsxRenderSceneRecord {
31
31
  // table: never;
32
32
  tableColumn: never;
33
33
  tableCell: never;
34
- // form: never;
34
+ form: never;
35
35
  formField: never;
36
36
  //
37
37
  details: never;
@@ -0,0 +1,53 @@
1
+ export interface IFormLayout {
2
+ children: IFormLayoutNode[];
3
+ }
4
+
5
+ export type TypeFormLayoutColumns = 1 | 2 | 3 | 4;
6
+
7
+ export interface IFormLayoutResponsiveColumns {
8
+ default?: TypeFormLayoutColumns;
9
+ md?: TypeFormLayoutColumns;
10
+ lg?: TypeFormLayoutColumns;
11
+ }
12
+
13
+ export interface IFormLayoutField {
14
+ type: 'field';
15
+ name: string;
16
+ span?: IFormLayoutResponsiveColumns;
17
+ }
18
+
19
+ export interface IFormLayoutGroup {
20
+ type: 'group';
21
+ id?: string;
22
+ title?: string;
23
+ description?: string;
24
+ children: Array<IFormLayoutField | IFormLayoutGroup | IFormLayoutSection>;
25
+ }
26
+
27
+ export interface IFormLayoutSection {
28
+ type: 'section';
29
+ id?: string;
30
+ title?: string;
31
+ description?: string;
32
+ columns?: IFormLayoutResponsiveColumns;
33
+ children: IFormLayoutField[];
34
+ }
35
+
36
+ export interface IFormLayoutTabs {
37
+ type: 'tabs';
38
+ id?: string;
39
+ children: IFormLayoutTab[];
40
+ }
41
+
42
+ export interface IFormLayoutTab {
43
+ type: 'tab';
44
+ id?: string;
45
+ title: string;
46
+ children: Array<IFormLayoutField | IFormLayoutGroup | IFormLayoutSection>;
47
+ }
48
+
49
+ export type IFormLayoutNode =
50
+ | IFormLayoutField
51
+ | IFormLayoutGroup
52
+ | IFormLayoutSection
53
+ | IFormLayoutTabs;
@@ -2,6 +2,7 @@ export * from './block.js';
2
2
  export * from './formActionRow.js';
3
3
  export * from './formField.js';
4
4
  export * from './formFieldLayout.js';
5
+ export * from './formLayout.js';
5
6
  export * from './tableAction.js';
6
7
  export * from './tableActionBulk.js';
7
8
  export * from './tableActionRow.js';
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-module-a-ssr",
3
- "version": "5.1.29",
3
+ "version": "5.1.30",
4
4
  "gitHead": "09d901d17140a80ee0764211b441cda72fd94663",
5
5
  "description": "",
6
6
  "keywords": [
@@ -193,7 +193,7 @@ export class CtxSSR extends BeanSimple {
193
193
  : stringifyStyle(normalizeStyle(clientValue));
194
194
  el.setAttribute(key, expected as string);
195
195
  }
196
- } else if (['id', 'name', 'for', 'd'].includes(key)) {
196
+ } else if (['id', 'name', 'for', 'd', 'aria-labelledby', 'aria-controls'].includes(key)) {
197
197
  ignore = true;
198
198
  if (clientValue !== undefined) {
199
199
  expected = String(clientValue);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zova-suite-a-zova",
3
- "version": "5.1.135",
3
+ "version": "5.1.136",
4
4
  "gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
5
5
  "description": "zova",
6
6
  "license": "MIT",
@@ -16,17 +16,17 @@
16
16
  "zova-module-a-boundary": "^5.1.21",
17
17
  "zova-module-a-command": "^5.1.33",
18
18
  "zova-module-a-fetch": "^5.1.23",
19
- "zova-module-a-form": "^5.1.43",
19
+ "zova-module-a-form": "^5.1.44",
20
20
  "zova-module-a-icon": "^5.1.26",
21
21
  "zova-module-a-interceptor": "^5.1.29",
22
22
  "zova-module-a-logger": "^5.1.26",
23
23
  "zova-module-a-meta": "^5.1.21",
24
24
  "zova-module-a-model": "^5.1.33",
25
- "zova-module-a-openapi": "^5.1.43",
25
+ "zova-module-a-openapi": "^5.1.44",
26
26
  "zova-module-a-router": "^5.1.30",
27
27
  "zova-module-a-routerstack": "^5.1.26",
28
28
  "zova-module-a-routertabs": "^5.1.33",
29
- "zova-module-a-ssr": "^5.1.29",
29
+ "zova-module-a-ssr": "^5.1.30",
30
30
  "zova-module-a-ssrhmr": "^5.1.22",
31
31
  "zova-module-a-ssrserver": "^5.1.23",
32
32
  "zova-module-a-style": "^5.1.32",