cabloy 5.1.98 → 5.1.100

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 (141) hide show
  1. package/.cabloy-version +1 -1
  2. package/.claude/hooks/contract-loop-gate.ts +151 -44
  3. package/CHANGELOG.md +28 -0
  4. package/CLAUDE.md +2 -0
  5. package/cabloy-docs/.vitepress/config.mjs +4 -0
  6. package/cabloy-docs/backend/controller-aop-guide.md +0 -1
  7. package/cabloy-docs/frontend/a-openapi-under-the-hood.md +1 -1
  8. package/cabloy-docs/frontend/generated-contract-consumption-entry-branch.md +1 -1
  9. package/cabloy-docs/frontend/generated-contract-consumption-list-branch.md +1 -1
  10. package/cabloy-docs/frontend/generated-contract-consumption-verify-playbook.md +1 -1
  11. package/cabloy-docs/frontend/model-resource-owner-pattern.md +1 -1
  12. package/cabloy-docs/frontend/model-state-guide.md +3 -1
  13. package/cabloy-docs/frontend/resource-entry-page-deep-dive.md +2 -2
  14. package/cabloy-docs/frontend/resource-list-page-deep-dive.md +1 -1
  15. package/cabloy-docs/frontend/rest-resource-source-reading-map.md +2 -2
  16. package/cabloy-docs/frontend/rest-resource-under-the-hood.md +4 -4
  17. package/cabloy-docs/frontend/use-state-data-best-practices.md +384 -0
  18. package/package.json +1 -1
  19. package/scripts/upgrade.ts +2 -0
  20. package/vona/packages-cli/cli/package.json +1 -1
  21. package/vona/packages-cli/cli-set-api/package.json +1 -1
  22. package/vona/packages-vona/vona/package.json +1 -1
  23. package/vona/packages-vona/vona-core/package.json +1 -1
  24. package/vona/packages-vona/vona-core/src/lib/bean/beanBase.ts +9 -9
  25. package/vona/packages-vona/vona-mock/package.json +1 -1
  26. package/vona/pnpm-lock.yaml +56 -56
  27. package/vona/pnpm-workspace.yaml +1 -1
  28. package/vona/src/suite/a-training/modules/training-record/src/bean/fileScene.dossierFile.ts +22 -0
  29. package/vona/src/suite/a-training/modules/training-record/src/bean/meta.version.ts +1 -0
  30. package/vona/src/suite/a-training/modules/training-record/src/config/locale/en-us.ts +1 -0
  31. package/vona/src/suite/a-training/modules/training-record/src/config/locale/zh-cn.ts +1 -0
  32. package/vona/src/suite/a-training/modules/training-record/src/dto/recordDossierFileView.ts +47 -0
  33. package/vona/src/suite/a-training/modules/training-record/src/dto/recordSelectResItem.tsx +13 -0
  34. package/vona/src/suite/a-training/modules/training-record/src/dto/recordView.tsx +13 -0
  35. package/vona/src/suite/a-training/modules/training-record/src/entity/record.tsx +16 -5
  36. package/vona/src/suite/a-training/modules/training-record/src/index.ts +2 -0
  37. package/vona/src/suite/a-training/modules/training-record/src/lib/index.ts +1 -0
  38. package/vona/src/suite/a-training/modules/training-record/src/lib/resolveDossierFiles.ts +34 -0
  39. package/vona/src/suite/a-training/modules/training-record/test/record.test.ts +209 -123
  40. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +1 -0
  41. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +1 -0
  42. package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordBase.tsx +18 -1
  43. package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +0 -2
  44. package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +1 -0
  45. package/vona/src/suite-vendor/a-file/modules/a-file/package.json +5 -3
  46. package/vona/src/suite-vendor/a-file/modules/a-file/src/bean/bean.fileUploadPolicy.ts +28 -0
  47. package/vona/src/suite-vendor/a-file/modules/a-file/src/controller/file.ts +8 -0
  48. package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileUploadPolicyRequest.ts +15 -0
  49. package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileUploadPolicyResponse.ts +30 -0
  50. package/vona/src/suite-vendor/a-file/package.json +2 -2
  51. package/vona/src/suite-vendor/a-image/modules/a-image/package.json +1 -1
  52. package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/bean.imageUploadPolicy.ts +27 -0
  53. package/vona/src/suite-vendor/a-image/modules/a-image/src/controller/image.ts +8 -0
  54. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadPolicyRequest.ts +15 -0
  55. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadPolicyResponse.ts +27 -0
  56. package/vona/src/suite-vendor/a-image/modules/image-native/package.json +1 -1
  57. package/vona/src/suite-vendor/a-image/modules/image-native/src/controller/image.ts +1 -1
  58. package/vona/src/suite-vendor/a-image/package.json +1 -1
  59. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
  60. package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
  61. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/.metadata/index.ts +24 -9
  62. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +87 -73
  63. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permissionActionByRoles.ts +27 -0
  64. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permissionUser.ts +20 -0
  65. package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
  66. package/vona/src/suite-vendor/a-vona/modules/a-startup/src/service/startup.ts +4 -3
  67. package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +1 -1
  68. package/vona/src/suite-vendor/a-vona/modules/a-upload/src/bean/interceptor.upload.ts +5 -1
  69. package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
  70. package/vona/src/suite-vendor/a-vona/modules/a-user/src/.metadata/index.ts +0 -13
  71. package/vona/src/suite-vendor/a-vona/modules/a-user/src/lib/passport.ts +0 -7
  72. package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
  73. package/vona/src/suite-vendor/a-vona/modules/a-version/src/bean/meta.version.ts +2 -24
  74. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  75. package/zova/packages-utils/zova-jsx/package.json +2 -2
  76. package/zova/packages-zova/zova/package.json +3 -3
  77. package/zova/packages-zova/zova-core/package.json +1 -1
  78. package/zova/packages-zova/zova-core/src/bean/beanBase.ts +9 -13
  79. package/zova/pnpm-lock.yaml +24 -9
  80. package/zova/src/suite/a-demo/modules/demo-basic/src/page/toolOne/controller.tsx +2 -2
  81. package/zova/src/suite/a-demo/modules/demo-todo/src/page/todo/controller.tsx +2 -2
  82. package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/controller.tsx +2 -2
  83. package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/controller.tsx +2 -2
  84. package/zova/src/suite/a-home/modules/home-login/src/page/login/controller.tsx +2 -2
  85. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockDetails/controller.tsx +5 -1
  86. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockTable/controller.tsx +20 -15
  87. package/zova/src/suite/cabloy-basic/modules/basic-details/src/service/detail.tsx +6 -1
  88. package/zova/src/suite/cabloy-basic/modules/basic-file/cli/openapi.config.ts +9 -0
  89. package/zova/src/suite/cabloy-basic/modules/basic-file/package.json +58 -0
  90. package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/component/formFieldFile.ts +31 -0
  91. package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/index.ts +222 -0
  92. package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/locales.ts +7 -0
  93. package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/this.ts +2 -0
  94. package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/file.ts +121 -0
  95. package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/baseURL.ts +5 -0
  96. package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/index.ts +3 -0
  97. package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/schemas.ts +306 -0
  98. package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/types.ts +5718 -0
  99. package/zova/src/suite/cabloy-basic/modules/basic-file/src/apiSchema/file.ts +40 -0
  100. package/zova/src/suite/cabloy-basic/modules/basic-file/src/bean/tableCell.file.tsx +187 -0
  101. package/zova/src/suite/cabloy-basic/modules/basic-file/src/component/formFieldFile/controller.tsx +534 -0
  102. package/zova/src/suite/cabloy-basic/modules/basic-file/src/config/locale/en-us.ts +15 -0
  103. package/zova/src/suite/cabloy-basic/modules/basic-file/src/config/locale/zh-cn.ts +15 -0
  104. package/zova/src/suite/cabloy-basic/modules/basic-file/src/index.ts +4 -0
  105. package/zova/src/suite/cabloy-basic/modules/basic-file/src/lib/file.ts +74 -0
  106. package/zova/src/suite/cabloy-basic/modules/basic-file/src/lib/index.ts +1 -0
  107. package/zova/src/suite/cabloy-basic/modules/basic-file/src/model/file.ts +23 -0
  108. package/zova/src/suite/cabloy-basic/modules/basic-file/src/types/file.ts +12 -0
  109. package/zova/src/suite/cabloy-basic/modules/basic-file/src/types/index.ts +1 -0
  110. package/zova/src/suite/cabloy-basic/modules/basic-file/tsconfig.build.json +13 -0
  111. package/zova/src/suite/cabloy-basic/modules/basic-file/tsconfig.json +5 -0
  112. package/zova/src/suite/cabloy-basic/modules/basic-image/src/.metadata/index.ts +61 -0
  113. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/image.ts +38 -1
  114. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/imageNativeImage.ts +31 -0
  115. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/schemas.ts +52 -0
  116. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/types.ts +614 -1
  117. package/zova/src/suite/cabloy-basic/modules/basic-image/src/apiSchema/image.ts +10 -0
  118. package/zova/src/suite/cabloy-basic/modules/basic-image/src/apiSchema/imageNativeImage.ts +13 -0
  119. package/zova/src/suite/cabloy-basic/modules/basic-image/src/component/formFieldImage/controller.tsx +126 -53
  120. package/zova/src/suite/cabloy-basic/modules/basic-image/src/model/image.ts +23 -0
  121. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockPage/controller.tsx +44 -4
  122. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockTable/controller.tsx +17 -12
  123. package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockPageEntry/controller.tsx +2 -2
  124. package/zova/src/suite/cabloy-basic/modules/basic-resource/src/component/formFieldResourcePicker/controller.tsx +2 -2
  125. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/table/controller.tsx +7 -2
  126. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/table/render.tsx +34 -33
  127. package/zova/src/suite/cabloy-basic/package.json +1 -0
  128. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  129. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +5 -3
  130. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/entry/controller.tsx +2 -2
  131. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/resource/controller.tsx +2 -2
  132. package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
  133. package/zova/src/suite-vendor/a-zova/modules/a-model/package.json +1 -1
  134. package/zova/src/suite-vendor/a-zova/modules/a-model/src/lib/utils.ts +17 -17
  135. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
  136. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/model/sdk.ts +8 -3
  137. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  138. package/zova/src/suite-vendor/a-zova/package.json +4 -4
  139. package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permission.ts +0 -17
  140. package/vona/src/suite-vendor/a-vona/modules/a-user/src/bean/guard.userName.ts +0 -35
  141. /package/vona/patches/{zova-core@5.1.76.patch → zova-core@5.1.77.patch} +0 -0
@@ -0,0 +1,40 @@
1
+ import type { IApiSchemaOptions } from 'zova-module-a-api';
2
+
3
+ import { BeanBase } from 'zova';
4
+ import { ApiSchema } from 'zova-module-a-api';
5
+
6
+ import {
7
+ ApiApiFilegetUploadPolicyPath,
8
+ ApiApiFilecreateUploadTokenPath,
9
+ ApiApiFileuploadPath,
10
+ ApiApiFilecreateDirectUploadPath,
11
+ ApiApiFileuploadUrlPath,
12
+ ApiApiFiledownloadPath,
13
+ } from '../api/file.js';
14
+
15
+ @ApiSchema()
16
+ export class ApiSchemaFile extends BeanBase {
17
+ getUploadPolicy(options?: IApiSchemaOptions) {
18
+ return this.$sdk.createApiSchemas(ApiApiFilegetUploadPolicyPath, 'post', options);
19
+ }
20
+
21
+ createUploadToken(options?: IApiSchemaOptions) {
22
+ return this.$sdk.createApiSchemas(ApiApiFilecreateUploadTokenPath, 'post', options);
23
+ }
24
+
25
+ upload(options?: IApiSchemaOptions) {
26
+ return this.$sdk.createApiSchemas(ApiApiFileuploadPath, 'post', options);
27
+ }
28
+
29
+ createDirectUpload(options?: IApiSchemaOptions) {
30
+ return this.$sdk.createApiSchemas(ApiApiFilecreateDirectUploadPath, 'post', options);
31
+ }
32
+
33
+ uploadUrl(options?: IApiSchemaOptions) {
34
+ return this.$sdk.createApiSchemas(ApiApiFileuploadUrlPath, 'post', options);
35
+ }
36
+
37
+ download(options?: IApiSchemaOptions) {
38
+ return this.$sdk.createApiSchemas(ApiApiFiledownloadPath, 'get', options);
39
+ }
40
+ }
@@ -0,0 +1,187 @@
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
+ import type { IFilePreviewItem } from '../types/file.js';
12
+
13
+ import {
14
+ collectFileRelationPreviewItems,
15
+ inferFileRelationName,
16
+ resolveFileDownloadUrl,
17
+ } from '../lib/index.js';
18
+
19
+ declare module 'zova-module-a-openapi' {
20
+ export interface IResourceTableCellRecord {
21
+ 'basic-file:file'?: ITableCellOptionsFile;
22
+ }
23
+ }
24
+
25
+ export interface ITableCellOptionsFile extends IResourceTableCellOptionsBase {
26
+ relationName?: string;
27
+ }
28
+
29
+ interface ITableCellFileDownloadItem {
30
+ key: string;
31
+ label: string;
32
+ downloadUrl?: string;
33
+ }
34
+
35
+ @TableCell<ITableCellOptionsFile>()
36
+ export class TableCellFile extends BeanBase implements ITableCellRender {
37
+ render(
38
+ options: ITableCellOptionsFile,
39
+ renderContext: IJsxRenderContextTableCell,
40
+ next: NextTableCellRender,
41
+ ) {
42
+ const value = next();
43
+ const relationName = inferFileRelationName(renderContext.$celScope.name, options.relationName);
44
+ const relationValue = relationName
45
+ ? renderContext.cellContext.row.original[relationName]
46
+ : undefined;
47
+ const relationItems = collectFileRelationPreviewItems(relationValue);
48
+ if (relationItems.length === 0) return this._renderSummaryContent(value, 0);
49
+
50
+ const firstItem = relationItems[0];
51
+ const summaryLabel = this._resolveSummaryLabel(firstItem, value);
52
+ const contentNode = this._renderSummaryContent(summaryLabel, relationItems.length);
53
+ if (relationItems.length === 1) {
54
+ return this._renderDirectLink(firstItem, contentNode);
55
+ }
56
+
57
+ const downloadItems = relationItems.map((item, index) =>
58
+ this._normalizeDownloadItem(item, index),
59
+ );
60
+ const hasDownloadableItem = downloadItems.some(item => !!item.downloadUrl);
61
+ if (!hasDownloadableItem) return contentNode;
62
+
63
+ return this._renderDownloadSelect(renderContext, downloadItems, contentNode);
64
+ }
65
+
66
+ private _renderSummaryContent(label: unknown, count: number) {
67
+ return (
68
+ <span class="inline-flex min-w-0 items-center gap-2">
69
+ <span class="truncate">{label}</span>
70
+ {count > 1 && (
71
+ <span class="badge badge-sm border-0 whitespace-nowrap px-2 badge-neutral text-neutral-content">
72
+ +{count - 1}
73
+ </span>
74
+ )}
75
+ </span>
76
+ );
77
+ }
78
+
79
+ private _renderDirectLink(item: IFilePreviewItem, contentNode: unknown) {
80
+ const downloadUrl = this._resolveDownloadUrl(item);
81
+ if (!downloadUrl) return contentNode;
82
+ return (
83
+ <a
84
+ class="link link-hover inline-flex min-w-0 items-center"
85
+ href={downloadUrl}
86
+ target="_blank"
87
+ rel="noreferrer"
88
+ onClick={event => {
89
+ event.stopPropagation();
90
+ }}
91
+ >
92
+ {contentNode}
93
+ </a>
94
+ );
95
+ }
96
+
97
+ private _renderDownloadSelect(
98
+ renderContext: IJsxRenderContextTableCell,
99
+ items: ITableCellFileDownloadItem[],
100
+ contentNode: unknown,
101
+ ) {
102
+ const fieldTitle = renderContext.$celScope.property?.title ?? renderContext.$celScope.name;
103
+ const placeholder = this.scope.locale.DownloadFile();
104
+ return (
105
+ <span class="relative inline-flex min-w-0 max-w-full items-center">
106
+ <span class="inline-flex min-w-0 max-w-full items-center">{contentNode}</span>
107
+ <select
108
+ class="absolute inset-0 h-full w-full cursor-pointer opacity-0"
109
+ aria-label={fieldTitle}
110
+ title={placeholder}
111
+ onClick={event => {
112
+ event.stopPropagation();
113
+ }}
114
+ onMousedown={event => {
115
+ event.stopPropagation();
116
+ }}
117
+ onChange={event => {
118
+ event.stopPropagation();
119
+ const target = event.target as HTMLSelectElement;
120
+ const selectedValue = target.value;
121
+ target.value = '';
122
+ if (selectedValue === '') return;
123
+ const selectedItem = items.find(item => item.key === selectedValue);
124
+ if (!selectedItem?.downloadUrl) return;
125
+ this._openDownloadUrl(selectedItem.downloadUrl);
126
+ }}
127
+ >
128
+ <option value="">{placeholder}</option>
129
+ {items.map(item => (
130
+ <option key={item.key} value={item.key} disabled={!item.downloadUrl}>
131
+ {item.label}
132
+ </option>
133
+ ))}
134
+ </select>
135
+ </span>
136
+ );
137
+ }
138
+
139
+ private _normalizeDownloadItem(
140
+ item: IFilePreviewItem,
141
+ index: number,
142
+ ): ITableCellFileDownloadItem {
143
+ return {
144
+ key: `${String(item.id)}:${index}`,
145
+ label: this._formatFileLabel(item),
146
+ downloadUrl: this._resolveDownloadUrl(item),
147
+ };
148
+ }
149
+
150
+ private _resolveSummaryLabel(item: IFilePreviewItem, fallbackValue: unknown): string {
151
+ return (
152
+ (item.filename ?? this._stringifyFallbackValue(fallbackValue)) || this._formatFileId(item)
153
+ );
154
+ }
155
+
156
+ private _formatFileLabel(item: IFilePreviewItem): string {
157
+ return item.filename ?? this._formatFileId(item);
158
+ }
159
+
160
+ private _formatFileId(item: IFilePreviewItem): string {
161
+ return `#${String(item.id)}`;
162
+ }
163
+
164
+ private _stringifyFallbackValue(value: unknown): string {
165
+ if (typeof value === 'string') return value;
166
+ if (typeof value === 'number' || typeof value === 'bigint' || typeof value === 'boolean') {
167
+ return String(value);
168
+ }
169
+ return '';
170
+ }
171
+
172
+ private _openDownloadUrl(downloadUrl: string) {
173
+ const anchor = globalThis.document?.createElement('a');
174
+ if (!anchor) {
175
+ globalThis.open?.(downloadUrl, '_blank');
176
+ return;
177
+ }
178
+ anchor.href = downloadUrl;
179
+ anchor.target = '_blank';
180
+ anchor.rel = 'noreferrer';
181
+ anchor.click();
182
+ }
183
+
184
+ private _resolveDownloadUrl(item: IFilePreviewItem): string | undefined {
185
+ return resolveFileDownloadUrl(item.downloadUrl, this.sys.config.api.baseURL);
186
+ }
187
+ }