cabloy 5.1.65 → 5.1.66

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 (167) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/cabloy-docs/.vitepress/config.mjs +1 -1
  3. package/cabloy-docs/backend/crud-workflow.md +33 -0
  4. package/cabloy-docs/backend/master-detail-workflow.md +149 -0
  5. package/cabloy-docs/frontend/bean-scene-authoring.md +1 -1
  6. package/cabloy-docs/frontend/cli.md +12 -1
  7. package/cabloy-docs/frontend/command-scene-authoring.md +12 -1
  8. package/cabloy-docs/frontend/component-guide.md +10 -0
  9. package/cabloy-docs/frontend/permission-formscene-action-visibility-guide.md +69 -7
  10. package/cabloy-docs/frontend/table-cell-cookbook.md +10 -0
  11. package/cabloy-docs/fullstack/backend-metadata-to-frontend-table-actions.md +83 -2
  12. package/cabloy-docs/reference/bean-scene-boilerplates.md +9 -4
  13. package/package.json +1 -1
  14. package/vona/packages-cli/cabloy-cli/package.json +1 -1
  15. package/vona/packages-cli/cabloy-cli/src/lib/local.helper.ts +38 -0
  16. package/vona/packages-cli/cli/package.json +1 -1
  17. package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoBaseName%>.tsx_ +18 -0
  18. package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoMutateName%>.tsx_ +17 -0
  19. package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoResItemName%>.tsx_ +60 -0
  20. package/vona/packages-cli/cli-set-api/cli/templates/tools/masterDetail/boilerplate/dto/<%=argv.detailDtoViewName%>.tsx_ +17 -0
  21. package/vona/packages-cli/cli-set-api/package.json +1 -1
  22. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.create.bean.ts +2 -6
  23. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.create.module.ts +3 -6
  24. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.create.suite.ts +1 -1
  25. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.create.test.ts +2 -6
  26. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.asset.ts +2 -6
  27. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.config.ts +2 -6
  28. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.constant.ts +2 -6
  29. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.error.ts +2 -6
  30. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.lib.ts +2 -6
  31. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.locale.ts +2 -6
  32. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.main.ts +2 -6
  33. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.monkey.ts +2 -6
  34. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.static.ts +2 -6
  35. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.init.types.ts +2 -6
  36. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.crud.ts +2 -6
  37. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.crudBasic.ts +2 -6
  38. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.crudStart.ts +2 -6
  39. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.masterDetail.ts +699 -0
  40. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.tools.metadata.ts +1 -2
  41. package/vona/packages-cli/cli-set-api/src/lib/beans.ts +2 -0
  42. package/vona/packages-cli/cli-set-api/src/lib/command/tools.masterDetail.ts +78 -0
  43. package/vona/packages-cli/cli-set-api/src/lib/commands.ts +2 -0
  44. package/vona/packages-vona/vona/package.json +1 -1
  45. package/vona/packages-vona/vona-core/package.json +1 -1
  46. package/vona/packages-vona/vona-core/src/lib/mappedClass/type.ts +1 -0
  47. package/vona/packages-vona/vona-core/src/lib/mappedClass/utils.ts +36 -14
  48. package/vona/packages-vona/vona-mock/package.json +1 -1
  49. package/vona/pnpm-lock.yaml +20 -11
  50. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +3 -0
  51. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +3 -0
  52. package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordBase.tsx +8 -2
  53. package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordMutate.tsx +1 -15
  54. package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordResItem.tsx +25 -5
  55. package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordView.tsx +1 -12
  56. package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +6 -4
  57. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectReq.tsx +3 -6
  58. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSummary.tsx +1 -1
  59. package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +14 -1
  60. package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +14 -1
  61. package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +1 -5
  62. package/vona/src/suite/a-training/modules/training-student/src/service/student.ts +9 -4
  63. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  64. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/package.json +1 -1
  65. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/src/lib/const/decorator.ts +3 -1
  66. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/src/lib/schema/makeSchemaLikes.ts +21 -17
  67. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/src/lib/utils.ts +44 -2
  68. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  69. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoGet.ts +2 -2
  70. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/lib/dto/dtoMutate.ts +8 -1
  71. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/relations_.ts +32 -16
  72. package/vona/src/suite-vendor/a-vona/modules/a-web/package.json +1 -1
  73. package/vona/src/suite-vendor/a-vona/modules/a-web/src/lib/decorator/bean.ts +26 -5
  74. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  75. package/zova/packages-cli/cli/package.json +3 -3
  76. package/zova/packages-cli/cli-set-front/cli/templates/create/component/boilerplateDetailsActionBulk/controller.tsx_ +31 -0
  77. package/zova/packages-cli/cli-set-front/cli/templates/rest/component.ts +21 -0
  78. package/zova/packages-cli/cli-set-front/cli/templates/rest/render.ts +4 -0
  79. package/zova/packages-cli/cli-set-front/package.json +2 -2
  80. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.bean.ts +2 -6
  81. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.mock.ts +2 -6
  82. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.module.ts +3 -6
  83. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.create.suite.ts +1 -1
  84. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.asset.ts +2 -6
  85. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.config.ts +2 -6
  86. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.constant.ts +2 -6
  87. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.error.ts +2 -6
  88. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.icon.ts +2 -6
  89. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.lib.ts +2 -6
  90. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.locale.ts +2 -6
  91. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.main.ts +2 -6
  92. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.mainSys.ts +2 -6
  93. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.monkey.ts +2 -6
  94. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.monkeySys.ts +2 -6
  95. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.init.types.ts +2 -6
  96. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.config.ts +1 -4
  97. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +2 -2
  98. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.anotherRender.ts +2 -6
  99. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.anotherStyle.ts +2 -6
  100. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.componentEmits.ts +2 -6
  101. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.componentGeneric.ts +2 -6
  102. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.componentModel.ts +2 -6
  103. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.componentProps.ts +2 -6
  104. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.componentSlots.ts +2 -6
  105. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.firstRender.ts +2 -6
  106. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.firstStyle.ts +2 -6
  107. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.pageParams.ts +2 -6
  108. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.pageQuery.ts +2 -6
  109. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.refactor.renameComponent.ts +2 -6
  110. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.tools.metadata.ts +1 -2
  111. package/zova/packages-cli/cli-set-front/src/lib/common/cliCreateComponent.ts +2 -6
  112. package/zova/packages-cli/cli-set-front/src/lib/common/cliCreatePage.ts +2 -6
  113. package/zova/packages-zova/zova/package.json +2 -2
  114. package/zova/pnpm-lock.yaml +744 -884
  115. package/zova/src/suite/a-training/modules/training-student/package.json +2 -1
  116. package/zova/src/suite/cabloy-basic/modules/basic-app/src/bean/behavior.appModal.tsx +131 -13
  117. package/zova/src/suite/cabloy-basic/modules/basic-app/src/config/config.ts +15 -0
  118. package/zova/src/suite/cabloy-basic/modules/basic-app/src/service/appModal.ts +23 -5
  119. package/zova/src/suite/cabloy-basic/modules/basic-app/src/types/appModal.ts +30 -4
  120. package/zova/src/suite/cabloy-basic/modules/basic-details/package.json +6 -1
  121. package/zova/src/suite/cabloy-basic/modules/basic-details/src/.metadata/component/blockForm.ts +31 -0
  122. package/zova/src/suite/cabloy-basic/modules/basic-details/src/.metadata/index.ts +149 -2
  123. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/command.delete.tsx +47 -0
  124. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionDelete.tsx +52 -0
  125. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionOperationsRow.tsx +44 -6
  126. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionUpdate.tsx +73 -0
  127. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionView.tsx +64 -0
  128. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.lineNumber.tsx +30 -0
  129. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/actionCreate/controller.tsx +29 -5
  130. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockDetails/controller.tsx +28 -12
  131. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockForm/controller.tsx +53 -0
  132. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockTable/controller.tsx +7 -2
  133. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockToolbarBulk/controller.tsx +3 -1
  134. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/formFieldDetails/controller.tsx +24 -12
  135. package/zova/src/suite/cabloy-basic/modules/basic-details/src/config/locale/en-us.ts +4 -0
  136. package/zova/src/suite/cabloy-basic/modules/basic-details/src/config/locale/zh-cn.ts +4 -0
  137. package/zova/src/suite/cabloy-basic/modules/basic-details/src/index.ts +1 -0
  138. package/zova/src/suite/cabloy-basic/modules/basic-details/src/lib/index.ts +1 -0
  139. package/zova/src/suite/cabloy-basic/modules/basic-details/src/lib/utils.ts +12 -0
  140. package/zova/src/suite/cabloy-basic/modules/basic-details/src/service/detail.tsx +172 -0
  141. package/zova/src/suite/cabloy-basic/modules/basic-details/src/types/detail.ts +18 -0
  142. package/zova/src/suite/cabloy-basic/modules/basic-details/src/types/details.ts +11 -0
  143. package/zova/src/suite/cabloy-basic/modules/basic-details/src/types/dialogForm.ts +22 -0
  144. package/zova/src/suite/cabloy-basic/modules/basic-details/src/types/index.ts +2 -0
  145. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  146. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/entry/controller.tsx +1 -2
  147. package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
  148. package/zova/src/suite-vendor/a-zova/modules/a-command/cli/command/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
  149. package/zova/src/suite-vendor/a-zova/modules/a-command/cli/commandBulk/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
  150. package/zova/src/suite-vendor/a-zova/modules/a-command/cli/commandDetailsRow/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +20 -0
  151. package/zova/src/suite-vendor/a-zova/modules/a-command/cli/commandRow/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +6 -1
  152. package/zova/src/suite-vendor/a-zova/modules/a-command/package.json +3 -2
  153. package/zova/src/suite-vendor/a-zova/modules/a-command/src/types/command.ts +2 -0
  154. package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
  155. package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/form/controller.tsx +1 -0
  156. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +2 -2
  157. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/lib/schema.ts +20 -4
  158. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/action.ts +2 -1
  159. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/detail/detail.ts +10 -0
  160. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/detail/details.ts +4 -1
  161. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/detail/index.ts +1 -0
  162. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/rest.ts +2 -0
  163. package/zova/src/suite-vendor/a-zova/modules/a-table/cli/detailsActionRow/boilerplate/{{sceneName}}.{{beanName}}.tsx_ +24 -0
  164. package/zova/src/suite-vendor/a-zova/modules/a-table/package.json +3 -2
  165. package/zova/src/suite-vendor/a-zova/modules/a-table/src/component/table/controller.tsx +5 -3
  166. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  167. package/zova/src/suite-vendor/a-zova/package.json +6 -6
@@ -0,0 +1,47 @@
1
+ import type {
2
+ ICommandExecute,
3
+ ICommandDetailsRowOptionsBase,
4
+ NextCommandExecute,
5
+ } from 'zova-module-a-command';
6
+ import type { IJsxRenderContextBase, IJsxRenderContextDetails } from 'zova-module-a-openapi';
7
+ import type { IJsxRenderContextTableCell } from 'zova-module-a-table';
8
+
9
+ import { isNil } from '@cabloy/utils';
10
+ import { BeanBase } from 'zova';
11
+ import { Command } from 'zova-module-a-command';
12
+
13
+ export type TypeCommandDeleteResult = unknown;
14
+
15
+ export interface ICommandOptionsDelete extends ICommandDetailsRowOptionsBase<TypeCommandDeleteResult> {}
16
+
17
+ type DetailItem = Record<string, any>;
18
+
19
+ @Command<ICommandOptionsDelete>()
20
+ export class CommandDelete extends BeanBase implements ICommandExecute {
21
+ execute(
22
+ _options: ICommandOptionsDelete,
23
+ renderContext: IJsxRenderContextBase,
24
+ next: NextCommandExecute,
25
+ ) {
26
+ const { $celScope } = renderContext as IJsxRenderContextDetails;
27
+ const $$details = $celScope.$$details;
28
+ if (!$$details) throw new Error('should provide $$details in cell scope');
29
+ const { cellContext } = renderContext as IJsxRenderContextTableCell;
30
+ const row = cellContext?.row;
31
+ if (!row) throw new Error('should provide row in cell context');
32
+ const detailItem = row.original as DetailItem;
33
+ const detailItemIndex = row.index;
34
+ const detailItemId = detailItem.id;
35
+ const detailItems = $$details.data as DetailItem[];
36
+ if (!isNil(detailItemId)) {
37
+ $$details.data = detailItems.map(item => {
38
+ return item.id === detailItemId ? { ...item, deleted: true } : item;
39
+ });
40
+ } else {
41
+ $$details.data = detailItems.filter((_item, index) => {
42
+ return index !== detailItemIndex;
43
+ });
44
+ }
45
+ return next();
46
+ }
47
+ }
@@ -0,0 +1,52 @@
1
+ import type { IResourceDetailsActionRowOptionsBase } from 'zova-module-a-openapi';
2
+ import type {
3
+ IJsxRenderContextTableCell,
4
+ ITableCellRender,
5
+ NextTableCellRender,
6
+ } from 'zova-module-a-table';
7
+
8
+ import { BeanBase } from 'zova';
9
+ import { ZIcon } from 'zova-module-a-icon';
10
+ import { TableCell } from 'zova-module-a-table';
11
+
12
+ import { ICommandOptionsDelete } from './command.delete.jsx';
13
+
14
+ declare module 'zova-module-a-openapi' {
15
+ export interface IResourceDetailsActionRowRecord {
16
+ 'basic-details:actionDelete'?: ITableCellOptionsActionDelete;
17
+ }
18
+ }
19
+
20
+ export interface ITableCellOptionsActionDelete extends IResourceDetailsActionRowOptionsBase {}
21
+
22
+ @TableCell<ITableCellOptionsActionDelete>({
23
+ class: 'btn btn-outline btn-error join-item',
24
+ })
25
+ export class TableCellActionDelete extends BeanBase implements ITableCellRender {
26
+ render(
27
+ options: ITableCellOptionsActionDelete,
28
+ renderContext: IJsxRenderContextTableCell,
29
+ _next: NextTableCellRender,
30
+ ) {
31
+ const { $host } = renderContext;
32
+ return (
33
+ <button
34
+ class={options.class}
35
+ type="button"
36
+ onClick={async () => {
37
+ const confirmed = await $host.$performCommand('basic-commands:confirm', {
38
+ text: this.scope.locale.DeleteConfirm(),
39
+ });
40
+ if (!confirmed) return;
41
+ await $host.$performCommand(
42
+ 'basic-details:delete',
43
+ options as Partial<ICommandOptionsDelete>,
44
+ renderContext,
45
+ );
46
+ }}
47
+ >
48
+ <ZIcon name="::delete" width={24}></ZIcon>
49
+ </button>
50
+ );
51
+ }
52
+ }
@@ -1,16 +1,21 @@
1
1
  import type {
2
2
  IResourceDetailsActionRowOptionsBase,
3
3
  IResourceRenderDetailsActionRowOptionsAction,
4
+ TypeTableCellRenderComponent,
4
5
  } from 'zova-module-a-openapi';
5
6
  import type {
6
7
  IJsxRenderContextTableCell,
8
+ IJsxRenderContextTableColumn,
7
9
  ITableCellRender,
8
10
  NextTableCellRender,
9
11
  } from 'zova-module-a-table';
10
12
 
13
+ import { VNode } from 'vue';
11
14
  import { BeanBase } from 'zova';
12
15
  import { TableCell } from 'zova-module-a-table';
13
16
 
17
+ import { checkPermission } from '../lib/utils.js';
18
+
14
19
  declare module 'zova-module-a-openapi' {
15
20
  export interface IResourceDetailsActionRowRecord {
16
21
  'basic-details:actionOperationsRow'?: ITableCellOptionsActionOperationsRow;
@@ -21,14 +26,47 @@ export interface ITableCellOptionsActionOperationsRow extends IResourceDetailsAc
21
26
  actions?: IResourceRenderDetailsActionRowOptionsAction[];
22
27
  }
23
28
 
24
- @TableCell<ITableCellOptionsActionOperationsRow>()
29
+ @TableCell<ITableCellOptionsActionOperationsRow>({
30
+ class: 'join',
31
+ })
25
32
  export class TableCellActionOperationsRow extends BeanBase implements ITableCellRender {
33
+ async checkVisible(
34
+ options: ITableCellOptionsActionOperationsRow,
35
+ renderContext: IJsxRenderContextTableColumn,
36
+ ): Promise<boolean> {
37
+ const { $celScope, $$table } = renderContext;
38
+ const actions = options.actions;
39
+ if (!actions || actions.length === 0) return false;
40
+ // renders
41
+ const renders: TypeTableCellRenderComponent[] = [];
42
+ for (const action of actions) {
43
+ const actionName = action.name;
44
+ const actionRender = action.render;
45
+ const permissionHint = action.options?.permission;
46
+ if (checkPermission($celScope.formMeta!.formScene!, permissionHint)) {
47
+ if (!actionRender) throw new Error(`should specify action render: ${actionName}`);
48
+ renders.push(actionRender);
49
+ }
50
+ }
51
+ await $$table.cellRenderPrepare(renders);
52
+ return renders.length > 0;
53
+ }
54
+
26
55
  render(
27
- _options: ITableCellOptionsActionOperationsRow,
28
- _renderContext: IJsxRenderContextTableCell,
29
- next: NextTableCellRender,
56
+ options: ITableCellOptionsActionOperationsRow,
57
+ renderContext: IJsxRenderContextTableCell,
58
+ _next: NextTableCellRender,
30
59
  ) {
31
- return <div>sssss</div>;
32
- return next();
60
+ const { $celScope, $$table } = renderContext;
61
+ const actions = options.actions;
62
+ if (!actions || actions.length === 0) return;
63
+ const domActions: VNode[] = [];
64
+ actions.forEach((action, index) => {
65
+ const permissionHint = action.options?.permission;
66
+ if (!checkPermission($celScope.formMeta!.formScene!, permissionHint)) return;
67
+ const options2 = Object.assign({ key: index }, action.options);
68
+ domActions.push($$table.cellRender(action.render!, options2, renderContext));
69
+ });
70
+ return <div class={options.class}>{domActions}</div>;
33
71
  }
34
72
  }
@@ -0,0 +1,73 @@
1
+ import type { IResourceDetailsActionRowOptionsBase } from 'zova-module-a-openapi';
2
+ import type {
3
+ IJsxRenderContextTableCell,
4
+ ITableCellRender,
5
+ NextTableCellRender,
6
+ } from 'zova-module-a-table';
7
+ import type { AppModalItem, IModalDialogOptions } from 'zova-module-basic-app';
8
+
9
+ import { BeanBase, deepExtend } from 'zova';
10
+ import { TypeFormOnSubmitData } from 'zova-module-a-form';
11
+ import { IIconRecord, ZIcon } from 'zova-module-a-icon';
12
+ import { TableCell } from 'zova-module-a-table';
13
+
14
+ import { ServiceDetail } from '../service/detail.jsx';
15
+ import { IDialogFormOptions } from '../types/dialogForm.js';
16
+
17
+ declare module 'zova-module-a-openapi' {
18
+ export interface IResourceDetailsActionRowRecord {
19
+ 'basic-details:actionUpdate'?: ITableCellOptionsActionUpdate;
20
+ }
21
+ }
22
+
23
+ export interface ITableCellOptionsActionUpdate extends IResourceDetailsActionRowOptionsBase {
24
+ dialogOptions?: IModalDialogOptions & { icon?: keyof IIconRecord; title?: string };
25
+ }
26
+
27
+ @TableCell<ITableCellOptionsActionUpdate>({
28
+ class: 'btn btn-outline btn-primary join-item',
29
+ })
30
+ export class TableCellActionUpdate extends BeanBase implements ITableCellRender {
31
+ render(
32
+ options: ITableCellOptionsActionUpdate,
33
+ renderContext: IJsxRenderContextTableCell,
34
+ _next: NextTableCellRender,
35
+ ) {
36
+ const { ctx, $celScope, cellContext } = renderContext;
37
+ return (
38
+ <button
39
+ class={options.class}
40
+ type="button"
41
+ onClick={async () => {
42
+ const $$details = $celScope.$$details;
43
+ if (!$$details) throw new Error('should provide $$details in cell scope');
44
+ const detailItem = cellContext.row.original as Record<string, any>;
45
+ const detailItemIndex = cellContext.row.index;
46
+ const serverDetail = await ctx.bean._newBean(ServiceDetail, true, {
47
+ locale: this.scope.locale,
48
+ schema: $$details.schemaForm,
49
+ data: deepExtend({}, detailItem),
50
+ formScene: 'edit',
51
+ schemaScene: 'form',
52
+ icon: options.dialogOptions?.icon,
53
+ title: options.dialogOptions?.title ?? this.scope.locale.EditDetail(),
54
+ dialogOptions: options.dialogOptions,
55
+ onSubmitData: (
56
+ data: TypeFormOnSubmitData<Record<string, any>>,
57
+ dialog: AppModalItem,
58
+ ) => {
59
+ const detailItemNew = deepExtend({}, detailItem, data.value);
60
+ $$details.data = $$details.data.map((item, index) => {
61
+ return index === detailItemIndex ? detailItemNew : item;
62
+ });
63
+ dialog.close();
64
+ },
65
+ } satisfies IDialogFormOptions);
66
+ serverDetail.openDialogForm();
67
+ }}
68
+ >
69
+ <ZIcon name="::draft" width={24}></ZIcon>
70
+ </button>
71
+ );
72
+ }
73
+ }
@@ -0,0 +1,64 @@
1
+ import type { IResourceDetailsActionRowOptionsBase } from 'zova-module-a-openapi';
2
+ import type {
3
+ IJsxRenderContextTableCell,
4
+ ITableCellRender,
5
+ NextTableCellRender,
6
+ } from 'zova-module-a-table';
7
+
8
+ import { BeanBase } from 'zova';
9
+ import { IIconRecord } from 'zova-module-a-icon';
10
+ import { TableCell } from 'zova-module-a-table';
11
+ import { IModalDialogOptions } from 'zova-module-basic-app';
12
+
13
+ import { ServiceDetail } from '../service/detail.jsx';
14
+ import { IDialogFormOptions } from '../types/dialogForm.js';
15
+
16
+ declare module 'zova-module-a-openapi' {
17
+ export interface IResourceDetailsActionRowRecord {
18
+ 'basic-details:actionView'?: ITableCellOptionsActionView;
19
+ }
20
+ }
21
+
22
+ export interface ITableCellOptionsActionView extends IResourceDetailsActionRowOptionsBase {
23
+ dialogOptions?: IModalDialogOptions & { icon?: keyof IIconRecord; title?: string };
24
+ }
25
+
26
+ @TableCell<ITableCellOptionsActionView>({
27
+ class: 'hover:text-blue-500',
28
+ })
29
+ export class TableCellActionView extends BeanBase implements ITableCellRender {
30
+ render(
31
+ options: ITableCellOptionsActionView,
32
+ renderContext: IJsxRenderContextTableCell,
33
+ next: NextTableCellRender,
34
+ ) {
35
+ const { ctx, $celScope, cellContext } = renderContext;
36
+ const value = next();
37
+ return (
38
+ <a
39
+ class={options.class}
40
+ href="#"
41
+ onClick={async e => {
42
+ e.preventDefault();
43
+ e.stopPropagation();
44
+ const $$details = $celScope.$$details;
45
+ if (!$$details) throw new Error('should provide $$details in cell scope');
46
+ const detailItem = cellContext.row.original as Record<string, any>;
47
+ const serverDetail = await ctx.bean._newBean(ServiceDetail, true, {
48
+ locale: this.scope.locale,
49
+ schema: $$details.schemaForm,
50
+ data: detailItem,
51
+ formScene: 'view',
52
+ schemaScene: 'form-view',
53
+ icon: options.dialogOptions?.icon,
54
+ title: options.dialogOptions?.title ?? this.scope.locale.EditDetail(),
55
+ dialogOptions: options.dialogOptions,
56
+ } satisfies IDialogFormOptions);
57
+ serverDetail.openDialogForm();
58
+ }}
59
+ >
60
+ {value}
61
+ </a>
62
+ );
63
+ }
64
+ }
@@ -0,0 +1,30 @@
1
+ import type { IResourceTableCellOptionsBase } from 'zova-module-a-openapi';
2
+ import type {
3
+ IJsxRenderContextTableCell,
4
+ ITableCellRender,
5
+ NextTableCellRender,
6
+ } from 'zova-module-a-table';
7
+
8
+ import { BeanBase } from 'zova';
9
+ import { TableCell } from 'zova-module-a-table';
10
+
11
+ declare module 'zova-module-a-openapi' {
12
+ export interface IResourceTableCellRecord {
13
+ 'basic-details:lineNumber'?: ITableCellOptionsLineNumber;
14
+ }
15
+ }
16
+
17
+ export interface ITableCellOptionsLineNumber extends IResourceTableCellOptionsBase {}
18
+
19
+ @TableCell<ITableCellOptionsLineNumber>()
20
+ export class TableCellLineNumber extends BeanBase implements ITableCellRender {
21
+ render(
22
+ _options: ITableCellOptionsLineNumber,
23
+ renderContext: IJsxRenderContextTableCell,
24
+ _next: NextTableCellRender,
25
+ ) {
26
+ const { cellContext } = renderContext;
27
+ const row = cellContext?.row;
28
+ return row.index + 1;
29
+ }
30
+ }
@@ -3,9 +3,15 @@ import type {
3
3
  IJsxRenderContextDetails,
4
4
  IResourceDetailsActionBulkOptionsBase,
5
5
  } from 'zova-module-a-openapi';
6
+ import type { AppModalItem, IModalDialogOptions } from 'zova-module-basic-app';
6
7
 
7
8
  import { BeanControllerBase, Use } from 'zova';
8
9
  import { Controller } from 'zova-module-a-bean';
10
+ import { TypeFormOnSubmitData } from 'zova-module-a-form';
11
+ import { IIconRecord } from 'zova-module-a-icon';
12
+
13
+ import { ServiceDetail } from '../../service/detail.jsx';
14
+ import { IDialogFormOptions } from '../../types/dialogForm.js';
9
15
 
10
16
  declare module 'zova-module-a-openapi' {
11
17
  export interface IResourceDetailsActionBulkRecord {
@@ -13,7 +19,9 @@ declare module 'zova-module-a-openapi' {
13
19
  }
14
20
  }
15
21
 
16
- export interface ControllerActionCreateProps extends IResourceDetailsActionBulkOptionsBase {}
22
+ export interface ControllerActionCreateProps extends IResourceDetailsActionBulkOptionsBase {
23
+ dialogOptions?: IModalDialogOptions & { icon?: keyof IIconRecord; title?: string };
24
+ }
17
25
 
18
26
  @Controller()
19
27
  export class ControllerActionCreate extends BeanControllerBase {
@@ -23,16 +31,32 @@ export class ControllerActionCreate extends BeanControllerBase {
23
31
  @Use({ injectionScope: 'host' })
24
32
  $$renderContext: IJsxRenderContextDetails;
25
33
 
26
- protected async __init__() {}
27
-
28
34
  protected render() {
29
35
  return (
30
36
  <button
31
37
  class={this.$props.class}
32
38
  type="button"
33
39
  onClick={async () => {
34
- console.log('create');
35
- // await this.$performCommand('basic-commands:create', this.$props, this.$$renderContext);
40
+ const { $$details } = this.$$renderContext;
41
+ const serverDetail = await this.bean._newBean(ServiceDetail, true, {
42
+ locale: this.scope.locale,
43
+ schema: $$details.schemaForm,
44
+ data: {},
45
+ formScene: 'create',
46
+ schemaScene: 'form-create',
47
+ icon: this.$props.dialogOptions?.icon,
48
+ title: this.$props.dialogOptions?.title ?? this.scope.locale.AddDetail(),
49
+ dialogOptions: this.$props.dialogOptions,
50
+ onSubmitData: (
51
+ data: TypeFormOnSubmitData<Record<string, any>>,
52
+ dialog: AppModalItem,
53
+ ) => {
54
+ const detailItem = data.value;
55
+ $$details.data = [...$$details.data, detailItem];
56
+ dialog.close();
57
+ },
58
+ } satisfies IDialogFormOptions);
59
+ serverDetail.openDialogForm();
36
60
  }}
37
61
  >
38
62
  {this.scope.locale.AddDetail()}
@@ -5,12 +5,11 @@ import { ZovaJsx } from 'zova-jsx';
5
5
  import { Controller } from 'zova-module-a-bean';
6
6
  import {
7
7
  IDetailsScope,
8
+ IFormMeta,
8
9
  IJsxRenderContextDetails,
9
- IPermissionHintDetailsActionBulk,
10
10
  IResourceBlockOptionsBase,
11
11
  IResourceRenderBlockOptionsBlock,
12
12
  ISchemaObjectExtensionField,
13
- TypeFormScene,
14
13
  } from 'zova-module-a-openapi';
15
14
  import { BeanControllerTableBase } from 'zova-module-a-table';
16
15
 
@@ -24,8 +23,9 @@ export interface ControllerBlockDetailsProps<
24
23
  TData extends {} = {},
25
24
  > extends IResourceBlockOptionsBase {
26
25
  blocks?: IResourceRenderBlockOptionsBlock[];
27
- formScene?: TypeFormScene;
26
+ formMeta?: IFormMeta;
28
27
  schemaRow?: ISchemaObjectExtensionField;
28
+ schemaForm?: ISchemaObjectExtensionField;
29
29
  getDetailItems?: () => TData[] | undefined;
30
30
  setDetailItems?: (detailItems: TData[]) => void;
31
31
  }
@@ -50,21 +50,24 @@ export class ControllerBlockDetails<TData extends {} = {}> extends BeanControlle
50
50
  return this.$props.getDetailItems?.() ?? [];
51
51
  }
52
52
 
53
+ set data(detailItems: TData[]) {
54
+ this.$props.setDetailItems?.(detailItems);
55
+ }
56
+
57
+ get formMeta() {
58
+ return this.$props.formMeta!;
59
+ }
60
+
53
61
  get formScene() {
54
- return this.$props.formScene!;
62
+ return this.formMeta.formScene!;
55
63
  }
56
64
 
57
65
  get schemaRow() {
58
66
  return this.$props.schemaRow!;
59
67
  }
60
68
 
61
- public checkPermission(permissionHint?: IPermissionHintDetailsActionBulk): boolean {
62
- const formScene = this.formScene;
63
- const formSceneHint = permissionHint?.formScene;
64
- if (!formSceneHint) return true;
65
- if (Array.isArray(formSceneHint) && formSceneHint.includes(formScene!)) return true;
66
- if (formSceneHint === formScene) return true;
67
- return false;
69
+ get schemaForm() {
70
+ return this.$props.schemaForm!;
68
71
  }
69
72
 
70
73
  private _prepareJsx() {
@@ -83,7 +86,20 @@ export class ControllerBlockDetails<TData extends {} = {}> extends BeanControlle
83
86
  }
84
87
 
85
88
  private _prepareJsxCelScope(): IDetailsScope {
86
- return {};
89
+ // eslint-disable-next-line
90
+ const self = this;
91
+ const $$details = this.$customRef(() => {
92
+ return {
93
+ get() {
94
+ return self;
95
+ },
96
+ set(_value) {},
97
+ };
98
+ }) as any;
99
+ return {
100
+ formMeta: this.formMeta,
101
+ $$details,
102
+ };
87
103
  }
88
104
 
89
105
  protected render() {
@@ -0,0 +1,53 @@
1
+ import type { IComponentOptions } from 'zova';
2
+ import type { IResourceBlockOptionsBase, IJsxRenderContextDetail } from 'zova-module-a-openapi';
3
+
4
+ import { BeanControllerBase, Use } from 'zova';
5
+ import { Controller } from 'zova-module-a-bean';
6
+ import { BeanControllerFormBase, ZForm } from 'zova-module-a-form';
7
+
8
+ declare module 'zova-module-a-openapi' {
9
+ export interface IResourceBlockRecord {
10
+ 'basic-details:blockForm'?: ControllerBlockFormProps;
11
+ }
12
+ }
13
+
14
+ export interface ControllerBlockFormProps extends IResourceBlockOptionsBase {}
15
+
16
+ @Controller()
17
+ export class ControllerBlockForm extends BeanControllerBase {
18
+ static $propsDefault = {};
19
+ static $componentOptions: IComponentOptions = { inheritAttrs: false, deepExtendDefault: true };
20
+
21
+ formRef: BeanControllerFormBase;
22
+
23
+ @Use({ injectionScope: 'host' })
24
+ $$renderContext: IJsxRenderContextDetail;
25
+
26
+ protected async __init__() {}
27
+
28
+ protected render() {
29
+ const { $$detail } = this.$$renderContext;
30
+ return (
31
+ <ZForm
32
+ class={this.$props.class}
33
+ controllerRef={ref => {
34
+ this.formRef = ref;
35
+ $$detail.formRef = ref;
36
+ }}
37
+ data={$$detail.formData}
38
+ schema={$$detail.formSchema}
39
+ schemaScene={$$detail.schemaScene}
40
+ formMeta={$$detail.formMeta}
41
+ formProvider={$$detail.formProvider}
42
+ formScope={$$detail.jsxCelScope}
43
+ onSubmitData={data => $$detail.submitData(data)}
44
+ onShowError={async ({ error }) => {
45
+ await this.$performCommand('basic-commands:alert', {
46
+ type: 'error',
47
+ text: error.message,
48
+ });
49
+ }}
50
+ ></ZForm>
51
+ );
52
+ }
53
+ }
@@ -27,7 +27,9 @@ export class ControllerBlockTable<TData extends {} = {}> extends BeanControllerB
27
27
 
28
28
  protected render() {
29
29
  const { $$details } = this.$$renderContext;
30
- const data = [{ id: 1, name: 'yang' }] as any;
30
+ const data = ($$details.data as TData[]).filter(
31
+ item => (item as Record<string, any>).deleted !== true,
32
+ );
31
33
  return (
32
34
  <ZTable<TData>
33
35
  class={this.$props.class}
@@ -35,9 +37,12 @@ export class ControllerBlockTable<TData extends {} = {}> extends BeanControllerB
35
37
  this.tableRef = ref;
36
38
  $$details.tableRef = ref as unknown as BeanControllerTableBase<{}>;
37
39
  }}
38
- data={data ?? ($$details.data as unknown as TData[])}
40
+ data={data}
39
41
  schema={$$details.schemaRow}
40
42
  tableScope={$$details.jsxCelScope}
43
+ getRowId={(_originalRow: TData, index: number) => {
44
+ return String(index);
45
+ }}
41
46
  ></ZTable>
42
47
  );
43
48
  }
@@ -9,6 +9,8 @@ import { VNode } from 'vue';
9
9
  import { BeanControllerBase, Use } from 'zova';
10
10
  import { Controller } from 'zova-module-a-bean';
11
11
 
12
+ import { checkPermission } from '../../lib/utils.js';
13
+
12
14
  declare module 'zova-module-a-openapi' {
13
15
  export interface IResourceBlockRecord {
14
16
  'basic-details:blockToolbarBulk'?: ControllerBlockToolbarBulkProps;
@@ -46,7 +48,7 @@ export class ControllerBlockToolbarBulk extends BeanControllerBase {
46
48
  const domActions: VNode[] = [];
47
49
  actions.forEach((action, index) => {
48
50
  const permissionHint = action.options?.permission;
49
- if (!$$details.checkPermission(permissionHint)) return;
51
+ if (!checkPermission($$details.formScene, permissionHint)) return;
50
52
  const options = Object.assign({ key: index }, action.options);
51
53
  const domAction = $jsx.render(action.render!, options, $celScope, this.$$renderContext);
52
54
  if (!domAction) return;
@@ -14,7 +14,7 @@ import { VNode } from 'vue';
14
14
  import { BeanControllerBase, deepExtend } from 'zova';
15
15
  import { ZovaJsx } from 'zova-jsx';
16
16
  import { Controller } from 'zova-module-a-bean';
17
- import { ZFormField } from 'zova-module-a-form';
17
+ import { formMetaFromFormScene, ZFormField } from 'zova-module-a-form';
18
18
 
19
19
  declare module 'zova-module-a-openapi' {
20
20
  export interface IResourceFormFieldRecord {
@@ -22,7 +22,9 @@ declare module 'zova-module-a-openapi' {
22
22
  }
23
23
  }
24
24
 
25
- export interface IResourceFormFieldDetailsOptions extends IResourceFormFieldOptionsBase {}
25
+ export interface IResourceFormFieldDetailsOptions extends IResourceFormFieldOptionsBase {
26
+ // schemaRow?:
27
+ }
26
28
 
27
29
  export interface ControllerFormFieldDetailsProps extends IFormFieldComponentOptions {
28
30
  options?: IResourceFormFieldDetailsOptions;
@@ -60,19 +62,17 @@ export class ControllerFormFieldDetails extends BeanControllerBase {
60
62
  $$formField: ControllerFormField,
61
63
  ) {
62
64
  const { propsBucket } = formFieldRenderContext;
63
- // schema
64
- const schemaName = $$formField.property?.items?.$ref;
65
- if (!schemaName) {
66
- return <div>Should specify the detail schema</div>;
67
- }
68
- const schemaRow: ISchemaObjectExtensionField | undefined = this.$sdk.getSchema(
69
- schemaName!,
70
- ).data;
65
+ // schemaRow
66
+ const schemaRow = this._getSchemaRow($$formField);
71
67
  if (!schemaRow) return;
72
- // formScene
68
+ // schemaForm
69
+ const schemaForm = $$formField.property!.items;
70
+ if (!schemaForm) return;
71
+ // formMeta
73
72
  const formScene: TypeFormScene = propsBucket.readonly
74
73
  ? 'view'
75
74
  : $$formField.formMeta!.formScene!;
75
+ const formMeta = formMetaFromFormScene(formScene);
76
76
  // blocks
77
77
  const blocks = schemaRow?.rest?.blocks;
78
78
  if (!blocks || blocks.length === 0) return;
@@ -81,8 +81,9 @@ export class ControllerFormFieldDetails extends BeanControllerBase {
81
81
  const options = deepExtend(
82
82
  { key: index },
83
83
  {
84
- formScene,
84
+ formMeta,
85
85
  schemaRow,
86
+ schemaForm,
86
87
  getDetailItems: () => {
87
88
  return propsBucket.value;
88
89
  },
@@ -102,4 +103,15 @@ export class ControllerFormFieldDetails extends BeanControllerBase {
102
103
  });
103
104
  return <div>{domBlocks}</div>;
104
105
  }
106
+
107
+ private _getSchemaRow($$formField: ControllerFormField): ISchemaObjectExtensionField | undefined {
108
+ const fieldNameAux = `_${$$formField.name}`;
109
+ const propertyAux = $$formField.$$form.getFieldProperty(fieldNameAux);
110
+ // schema
111
+ const schemaName = propertyAux?.items?.$ref;
112
+ if (!schemaName) {
113
+ throw new Error(`Should specify the schemaRow of detail by auxiliary Field: ${fieldNameAux}`);
114
+ }
115
+ return this.$sdk.getSchema(schemaName!).data;
116
+ }
105
117
  }
@@ -1,3 +1,7 @@
1
1
  export default {
2
2
  AddDetail: 'Add Detail',
3
+ EditDetail: 'Edit Detail',
4
+ Cancel: 'Cancel',
5
+ OK: 'OK',
6
+ DeleteConfirm: 'Are you sure you want to delete this detail?',
3
7
  };
@@ -1,3 +1,7 @@
1
1
  export default {
2
2
  AddDetail: '新增明细',
3
+ EditDetail: '编辑明细',
4
+ Cancel: '取消',
5
+ OK: '确认',
6
+ DeleteConfirm: '您确认要删除本明细吗?',
3
7
  };