cabloy 5.1.97 → 5.1.99
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/.claude/hooks/contract-loop-gate.ts +151 -44
- package/CHANGELOG.md +48 -0
- package/CLAUDE.md +2 -0
- package/cabloy-docs/.vitepress/config.mjs +11 -0
- package/cabloy-docs/backend/controller-aop-guide.md +0 -1
- package/cabloy-docs/backend/image-guide.md +544 -0
- package/cabloy-docs/frontend/a-openapi-under-the-hood.md +1 -1
- package/cabloy-docs/frontend/generated-contract-consumption-entry-branch.md +1 -1
- package/cabloy-docs/frontend/generated-contract-consumption-list-branch.md +1 -1
- package/cabloy-docs/frontend/generated-contract-consumption-verify-playbook.md +1 -1
- package/cabloy-docs/frontend/image-guide.md +512 -0
- package/cabloy-docs/frontend/introduction.md +2 -0
- package/cabloy-docs/frontend/ioc-and-beans.md +34 -3
- package/cabloy-docs/frontend/model-architecture.md +2 -0
- package/cabloy-docs/frontend/model-resource-owner-pattern.md +3 -1
- package/cabloy-docs/frontend/model-state-guide.md +5 -1
- package/cabloy-docs/frontend/reading-zova-for-vue-developers.md +10 -8
- package/cabloy-docs/frontend/resource-entry-page-deep-dive.md +2 -2
- package/cabloy-docs/frontend/resource-list-page-deep-dive.md +1 -1
- package/cabloy-docs/frontend/rest-resource-source-reading-map.md +2 -2
- package/cabloy-docs/frontend/rest-resource-under-the-hood.md +4 -4
- package/cabloy-docs/frontend/server-data.md +2 -0
- package/cabloy-docs/frontend/state-architecture-for-vue-developers.md +218 -0
- package/cabloy-docs/frontend/system-startup-guide.md +2 -0
- package/cabloy-docs/frontend/use-state-data-best-practices.md +384 -0
- package/cabloy-docs/frontend/zova-vs-vue3-comparison.md +11 -10
- package/cabloy-docs/fullstack/image-workflow.md +403 -0
- package/cabloy-docs/fullstack/introduction.md +1 -0
- package/package.json +1 -1
- package/scripts/upgrade.ts +2 -0
- package/vona/package.original.json +0 -1
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/packages-vona/vona-core/package.json +1 -1
- package/vona/packages-vona/vona-core/src/lib/bean/beanBase.ts +9 -9
- package/vona/packages-vona/vona-mock/package.json +1 -1
- package/vona/pnpm-lock.yaml +424 -47
- package/vona/src/suite/a-training/modules/training-record/src/bean/fileScene.dossierFile.ts +22 -0
- package/vona/src/suite/a-training/modules/training-record/src/bean/meta.version.ts +1 -0
- package/vona/src/suite/a-training/modules/training-record/src/config/locale/en-us.ts +1 -0
- package/vona/src/suite/a-training/modules/training-record/src/config/locale/zh-cn.ts +1 -0
- package/vona/src/suite/a-training/modules/training-record/src/dto/recordDossierFileView.ts +47 -0
- package/vona/src/suite/a-training/modules/training-record/src/dto/recordSelectResItem.tsx +13 -0
- package/vona/src/suite/a-training/modules/training-record/src/dto/recordView.tsx +13 -0
- package/vona/src/suite/a-training/modules/training-record/src/entity/record.tsx +16 -5
- package/vona/src/suite/a-training/modules/training-record/src/index.ts +2 -0
- package/vona/src/suite/a-training/modules/training-record/src/lib/index.ts +1 -0
- package/vona/src/suite/a-training/modules/training-record/src/lib/resolveDossierFiles.ts +34 -0
- package/vona/src/suite/a-training/modules/training-record/test/record.test.ts +209 -123
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +1 -0
- package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +1 -0
- package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordBase.tsx +18 -1
- package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +0 -2
- package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +1 -0
- package/vona/src/suite/cabloy-basic/modules/basic-siteadmin/src/bean/ssrSite.admin.ts +4 -0
- package/vona/src/suite/cabloy-basic/modules/basic-siteweb/src/bean/ssrSite.web.ts +4 -0
- package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/cli/ssrSite/boilerplate/{{sceneName}}.{{beanName}}.ts_ +3 -0
- package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/src/service/ssrHandler.ts +11 -2
- package/vona/src/suite-vendor/a-cabloy/modules/a-ssr/src/types/ssrSite.ts +6 -0
- package/vona/src/suite-vendor/a-cabloy/package.json +1 -1
- package/vona/src/suite-vendor/a-file/modules/a-file/cli/fileProvider/boilerplate/{{sceneName}}.{{beanName}}.ts_ +23 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/cli/fileScene/boilerplate/{{sceneName}}.{{beanName}}.ts_ +5 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/package.json +68 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/.metadata/index.ts +425 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/.metadata/locales.ts +18 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/bean/bean.file.ts +322 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/bean/bean.fileProvider.ts +62 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/bean/bean.fileUploadPolicy.ts +224 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/bean/meta.redlock.ts +11 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/bean/meta.version.ts +38 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/config/config.ts +16 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/config/locale/en-us.ts +1 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/config/locale/zh-cn.ts +1 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/controller/file.ts +175 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileDirectUploadRequest.ts +33 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileDirectUploadResponse.ts +41 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileDownloadRequest.ts +12 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileUploadPolicyRequest.ts +15 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileUploadPolicyResponse.ts +30 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileUploadResponse.ts +59 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileUploadTokenRequest.ts +24 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileUploadTokenResponse.ts +16 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/dto/fileUploadUrlRequest.ts +33 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/entity/file.ts +55 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/entity/fileProvider.ts +24 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/index.ts +4 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/lib/fileProvider.ts +7 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/lib/fileScene.ts +7 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/lib/fileUploadValidation.ts +15 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/lib/index.ts +3 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/model/file.ts +10 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/model/fileProvider.ts +10 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/types/file.ts +144 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/types/fileProvider.ts +111 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/types/fileScene.ts +53 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/src/types/index.ts +3 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-file/modules/a-file/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-file/modules/file-cloudflare/package.json +53 -0
- package/vona/src/suite-vendor/a-file/modules/file-cloudflare/src/.metadata/index.ts +104 -0
- package/vona/src/suite-vendor/a-file/modules/file-cloudflare/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-file/modules/file-cloudflare/src/bean/fileProvider.cloudflare.ts +123 -0
- package/vona/src/suite-vendor/a-file/modules/file-cloudflare/src/index.ts +1 -0
- package/vona/src/suite-vendor/a-file/modules/file-cloudflare/src/service/fileCloudflare.ts +245 -0
- package/vona/src/suite-vendor/a-file/modules/file-cloudflare/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-file/modules/file-cloudflare/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/package.json +50 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/src/.metadata/index.ts +111 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/src/.metadata/this.ts +2 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/src/bean/fileProvider.native.ts +125 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/src/config/config.ts +7 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/src/index.ts +1 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/src/service/fileNative.ts +125 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/tsconfig.build.json +11 -0
- package/vona/src/suite-vendor/a-file/modules/file-native/tsconfig.json +7 -0
- package/vona/src/suite-vendor/a-file/package.json +14 -0
- package/vona/src/suite-vendor/a-file/tsconfig.base.json +4 -0
- package/vona/src/suite-vendor/a-file/tsconfig.json +16 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/package.json +4 -1
- package/vona/src/suite-vendor/a-image/modules/a-image/src/.metadata/index.ts +61 -3
- package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/bean.image.ts +336 -152
- package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/bean.imageProvider.ts +21 -14
- package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/bean.imageUploadPolicy.ts +86 -11
- package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/meta.index.ts +12 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/meta.redlock.ts +1 -1
- package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/meta.version.ts +3 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/schedule.imageDraftPrune.ts +29 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/config/config.ts +3 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/controller/image.ts +32 -54
- package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageDirectUploadFinalizeRequest.ts +13 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageDirectUploadFinalizeResponse.ts +10 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageDirectUploadResponse.ts +10 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadPolicyRequest.ts +15 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadPolicyResponse.ts +27 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadResponse.ts +10 -1
- package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageView.ts +10 -1
- package/vona/src/suite-vendor/a-image/modules/a-image/src/entity/image.ts +10 -1
- package/vona/src/suite-vendor/a-image/modules/a-image/src/lib/imageUploadValidation.ts +15 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/lib/index.ts +1 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/types/image.ts +18 -0
- package/vona/src/suite-vendor/a-image/modules/a-image/src/types/imageProvider.ts +28 -2
- package/vona/src/suite-vendor/a-image/modules/image-cloudflare/package.json +1 -1
- package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/bean/imageProvider.cloudflare.ts +13 -1
- package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/service/imageCloudflare.ts +26 -0
- package/vona/src/suite-vendor/a-image/modules/image-native/package.json +6 -2
- package/vona/src/suite-vendor/a-image/modules/image-native/src/.metadata/index.ts +37 -0
- package/vona/src/suite-vendor/a-image/modules/image-native/src/bean/imageProvider.native.ts +21 -1
- package/vona/src/suite-vendor/a-image/modules/image-native/src/controller/image.ts +57 -0
- package/vona/src/suite-vendor/a-image/modules/image-native/src/service/imageNative.ts +142 -34
- package/vona/src/suite-vendor/a-image/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/entity.ts +2 -4
- package/vona/src/suite-vendor/a-vona/modules/a-ormutils/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ormutils/src/lib/columns.ts +7 -3
- package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/.metadata/index.ts +24 -9
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/bean.permission.ts +87 -73
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permissionActionByRoles.ts +27 -0
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permissionUser.ts +20 -0
- package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-startup/src/service/startup.ts +4 -3
- package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-upload/src/bean/interceptor.upload.ts +5 -1
- package/vona/src/suite-vendor/a-vona/modules/a-user/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-user/src/.metadata/index.ts +0 -13
- package/vona/src/suite-vendor/a-vona/modules/a-user/src/lib/passport.ts +0 -7
- package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-version/src/bean/meta.version.ts +2 -24
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/zova/packages-utils/zova-jsx/package.json +2 -2
- package/zova/packages-zova/zova/package.json +3 -3
- package/zova/packages-zova/zova-core/package.json +1 -1
- package/zova/packages-zova/zova-core/src/bean/beanBase.ts +9 -13
- package/zova/pnpm-lock.yaml +418 -411
- package/zova/src/suite/a-demo/modules/demo-basic/src/page/toolOne/controller.tsx +2 -2
- package/zova/src/suite/a-demo/modules/demo-todo/src/page/todo/controller.tsx +2 -2
- package/zova/src/suite/a-home/modules/home-layoutadmin/src/component/layoutAdmin/controller.tsx +2 -2
- package/zova/src/suite/a-home/modules/home-layoutweb/src/component/layoutWeb/controller.tsx +2 -2
- package/zova/src/suite/a-home/modules/home-login/src/page/login/controller.tsx +2 -2
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockDetails/controller.tsx +5 -1
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/blockTable/controller.tsx +20 -15
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/service/detail.tsx +6 -1
- package/zova/src/suite/cabloy-basic/modules/basic-file/cli/openapi.config.ts +9 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/package.json +58 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/component/formFieldFile.ts +31 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/index.ts +222 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/locales.ts +7 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/.metadata/this.ts +2 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/file.ts +121 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/baseURL.ts +5 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/index.ts +3 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/schemas.ts +306 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/api/openapi/types.ts +5718 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/apiSchema/file.ts +40 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/bean/tableCell.file.tsx +187 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/component/formFieldFile/controller.tsx +534 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/config/locale/en-us.ts +15 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/config/locale/zh-cn.ts +15 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/index.ts +4 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/lib/file.ts +74 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/lib/index.ts +1 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/model/file.ts +23 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/types/file.ts +12 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/src/types/index.ts +1 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/tsconfig.build.json +13 -0
- package/zova/src/suite/cabloy-basic/modules/basic-file/tsconfig.json +5 -0
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/.metadata/index.ts +61 -0
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/image.ts +38 -1
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/imageNativeImage.ts +31 -0
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/schemas.ts +52 -0
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/types.ts +614 -1
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/apiSchema/image.ts +10 -0
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/apiSchema/imageNativeImage.ts +13 -0
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/component/formFieldImage/controller.tsx +126 -62
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/model/image.ts +23 -0
- package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockPage/controller.tsx +44 -4
- package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockTable/controller.tsx +17 -12
- package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockPageEntry/controller.tsx +2 -2
- package/zova/src/suite/cabloy-basic/modules/basic-resource/src/component/formFieldResourcePicker/controller.tsx +2 -2
- package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/table/controller.tsx +7 -2
- package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/table/render.tsx +34 -33
- package/zova/src/suite/cabloy-basic/package.json +1 -0
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +5 -3
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/entry/controller.tsx +2 -2
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/resource/controller.tsx +2 -2
- package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/modules/a-model/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-model/src/lib/utils.ts +17 -17
- 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/model/sdk.ts +8 -3
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +4 -4
- package/vona/src/suite-vendor/a-vona/modules/a-permission/src/bean/summerCache.permission.ts +0 -17
- package/vona/src/suite-vendor/a-vona/modules/a-user/src/bean/guard.userName.ts +0 -35
|
@@ -4,15 +4,21 @@ import { BeanBase } from 'zova';
|
|
|
4
4
|
import { ApiSchema } from 'zova-module-a-api';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
+
ApiApiImagegetUploadPolicyPath,
|
|
7
8
|
ApiApiImagecreateUploadTokenPath,
|
|
8
9
|
ApiApiImageuploadPath,
|
|
9
10
|
ApiApiImagecreateDirectUploadPath,
|
|
11
|
+
ApiApiImagefinalizeDirectUploadPath,
|
|
10
12
|
ApiApiImageuploadUrlPath,
|
|
11
13
|
ApiApiImagedeliveryPath,
|
|
12
14
|
} from '../api/image.js';
|
|
13
15
|
|
|
14
16
|
@ApiSchema()
|
|
15
17
|
export class ApiSchemaImage extends BeanBase {
|
|
18
|
+
getUploadPolicy(options?: IApiSchemaOptions) {
|
|
19
|
+
return this.$sdk.createApiSchemas(ApiApiImagegetUploadPolicyPath, 'post', options);
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
createUploadToken(options?: IApiSchemaOptions) {
|
|
17
23
|
return this.$sdk.createApiSchemas(ApiApiImagecreateUploadTokenPath, 'post', options);
|
|
18
24
|
}
|
|
@@ -25,6 +31,10 @@ export class ApiSchemaImage extends BeanBase {
|
|
|
25
31
|
return this.$sdk.createApiSchemas(ApiApiImagecreateDirectUploadPath, 'post', options);
|
|
26
32
|
}
|
|
27
33
|
|
|
34
|
+
finalizeDirectUpload(options?: IApiSchemaOptions) {
|
|
35
|
+
return this.$sdk.createApiSchemas(ApiApiImagefinalizeDirectUploadPath, 'post', options);
|
|
36
|
+
}
|
|
37
|
+
|
|
28
38
|
uploadUrl(options?: IApiSchemaOptions) {
|
|
29
39
|
return this.$sdk.createApiSchemas(ApiApiImageuploadUrlPath, 'post', options);
|
|
30
40
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
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 { ApiApiImageNativeImagedirectUploadPath } from '../api/imageNativeImage.js';
|
|
7
|
+
|
|
8
|
+
@ApiSchema()
|
|
9
|
+
export class ApiSchemaImageNativeImage extends BeanBase {
|
|
10
|
+
directUpload(options?: IApiSchemaOptions) {
|
|
11
|
+
return this.$sdk.createApiSchemas(ApiApiImageNativeImagedirectUploadPath, 'post', options);
|
|
12
|
+
}
|
|
13
|
+
}
|
package/zova/src/suite/cabloy-basic/modules/basic-image/src/component/formFieldImage/controller.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import { CircleStencil, Cropper, RectangleStencil } from 'vue-advanced-cropper';
|
|
|
9
9
|
import { BeanControllerBase, ClientOnly, Use } from 'zova';
|
|
10
10
|
import { Controller } from 'zova-module-a-bean';
|
|
11
11
|
import { ZFormField } from 'zova-module-a-form';
|
|
12
|
+
import { $QueryEnsureLoaded } from 'zova-module-a-model';
|
|
12
13
|
import {
|
|
13
14
|
buildImagePreviewTitle,
|
|
14
15
|
inferImageRelationName,
|
|
@@ -17,6 +18,8 @@ import {
|
|
|
17
18
|
} from 'zova-module-basic-image';
|
|
18
19
|
|
|
19
20
|
import type { IImageTransformOptions } from '../../types/image.js';
|
|
21
|
+
|
|
22
|
+
import { ModelImage } from '../../model/image.js';
|
|
20
23
|
import 'vue-advanced-cropper/dist/style.css';
|
|
21
24
|
|
|
22
25
|
declare module 'zova-module-a-openapi' {
|
|
@@ -49,21 +52,18 @@ export interface IResourceFormFieldImageOptions extends IResourceFormFieldOption
|
|
|
49
52
|
cropAspectRatio?: number;
|
|
50
53
|
cropShape?: 'rect' | 'round';
|
|
51
54
|
resize?: IResourceFormFieldImageResizeOptions;
|
|
52
|
-
upload?: {
|
|
53
|
-
providerName?: string;
|
|
54
|
-
provider?: string;
|
|
55
|
-
clientName?: string;
|
|
56
|
-
maxSize?: number;
|
|
57
|
-
mimeTypes?: string[];
|
|
58
|
-
extensions?: string[];
|
|
59
|
-
accept?: string | string[];
|
|
60
|
-
};
|
|
61
55
|
}
|
|
62
56
|
|
|
63
57
|
export interface ControllerFormFieldImageProps extends IFormFieldComponentOptions {
|
|
64
58
|
options?: IResourceFormFieldImageOptions;
|
|
65
59
|
}
|
|
66
60
|
|
|
61
|
+
interface IUploadPolicyState {
|
|
62
|
+
acceptAttr: string;
|
|
63
|
+
multiple: boolean;
|
|
64
|
+
pending: boolean;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
67
|
interface IImagePreviewItem {
|
|
68
68
|
id: TableIdentity;
|
|
69
69
|
url?: string;
|
|
@@ -76,7 +76,6 @@ interface IImagePreviewItem {
|
|
|
76
76
|
export class ControllerFormFieldImage extends BeanControllerBase {
|
|
77
77
|
static $propsDefault = {
|
|
78
78
|
options: {
|
|
79
|
-
accept: ['image/png', 'image/jpeg', 'image/webp'],
|
|
80
79
|
maxCount: 1,
|
|
81
80
|
enableCrop: true,
|
|
82
81
|
cropAspectRatio: 1,
|
|
@@ -99,6 +98,10 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
99
98
|
currentValue?: TableIdentity | TableIdentity[] | string;
|
|
100
99
|
currentOptions: IResourceFormFieldImageOptions = {};
|
|
101
100
|
$$formField?: ControllerFormField;
|
|
101
|
+
|
|
102
|
+
@Use()
|
|
103
|
+
$$modelImage: ModelImage;
|
|
104
|
+
|
|
102
105
|
uploadedPreviewMap: Record<string, IImagePreviewItem> = {};
|
|
103
106
|
|
|
104
107
|
@Use({ injectionScope: 'host' })
|
|
@@ -117,7 +120,9 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
117
120
|
this.$$formField = $$formField;
|
|
118
121
|
this.currentValue = propsBucket.value as any;
|
|
119
122
|
this.currentOptions = propsBucket.options ?? {};
|
|
120
|
-
const
|
|
123
|
+
const uploadPolicyState = this._getUploadPolicyState(this.currentOptions);
|
|
124
|
+
const items = this._getPreviewItems(propsBucket.value, uploadPolicyState.multiple);
|
|
125
|
+
const maxCount = this._getMaxCount(this.currentOptions);
|
|
121
126
|
const hasValidationError = !$$formField.field.state.meta.isValid;
|
|
122
127
|
const cardClass = classes(
|
|
123
128
|
'rounded-box border border-base-300 bg-base-100 p-4',
|
|
@@ -126,29 +131,38 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
126
131
|
);
|
|
127
132
|
return (
|
|
128
133
|
<div class={cardClass}>
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
class="hidden"
|
|
134
|
-
type="file"
|
|
135
|
-
accept={this._getAcceptAttr(propsBucket.options)}
|
|
136
|
-
multiple={!!propsBucket.options?.multiple}
|
|
137
|
-
onChange={event => {
|
|
138
|
-
void this._handleFileChange(event, propsBucket.disableNotifyChanged);
|
|
139
|
-
}}
|
|
140
|
-
/>
|
|
141
|
-
<div class="flex flex-wrap items-center gap-3">
|
|
142
|
-
<button
|
|
143
|
-
type="button"
|
|
144
|
-
class={classes('btn btn-primary', this.isUploading && 'btn-disabled')}
|
|
145
|
-
onClick={() => {
|
|
146
|
-
if (this.isUploading) return;
|
|
147
|
-
this.fileInputRef?.click();
|
|
134
|
+
<ClientOnly>
|
|
135
|
+
<input
|
|
136
|
+
ref={ref => {
|
|
137
|
+
this.fileInputRef = ref as HTMLInputElement;
|
|
148
138
|
}}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
139
|
+
class="hidden"
|
|
140
|
+
type="file"
|
|
141
|
+
accept={uploadPolicyState.acceptAttr}
|
|
142
|
+
multiple={uploadPolicyState.multiple}
|
|
143
|
+
onChange={event => {
|
|
144
|
+
void this._handleFileChange(event, propsBucket.disableNotifyChanged);
|
|
145
|
+
}}
|
|
146
|
+
/>
|
|
147
|
+
</ClientOnly>
|
|
148
|
+
<div class="flex flex-wrap items-center gap-3">
|
|
149
|
+
{items.length < maxCount && (
|
|
150
|
+
<button
|
|
151
|
+
type="button"
|
|
152
|
+
disabled={this.isUploading || uploadPolicyState.pending}
|
|
153
|
+
class={classes(
|
|
154
|
+
'btn btn-primary',
|
|
155
|
+
(this.isUploading || uploadPolicyState.pending) && 'btn-disabled',
|
|
156
|
+
)}
|
|
157
|
+
onClick={() => {
|
|
158
|
+
if (this.isUploading || uploadPolicyState.pending) return;
|
|
159
|
+
this._applyInputPolicy(uploadPolicyState);
|
|
160
|
+
this.fileInputRef?.click();
|
|
161
|
+
}}
|
|
162
|
+
>
|
|
163
|
+
{this._getUploadButtonText(items.length, uploadPolicyState.multiple)}
|
|
164
|
+
</button>
|
|
165
|
+
)}
|
|
152
166
|
{this.isUploading && (
|
|
153
167
|
<span class="inline-flex items-center gap-2 text-sm text-base-content/70">
|
|
154
168
|
<span class="loading loading-spinner loading-sm text-primary"></span>
|
|
@@ -275,14 +289,51 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
275
289
|
);
|
|
276
290
|
}
|
|
277
291
|
|
|
278
|
-
private _getUploadButtonText(
|
|
279
|
-
|
|
280
|
-
|
|
292
|
+
private _getUploadButtonText(
|
|
293
|
+
itemCount: number,
|
|
294
|
+
multiple = this._getEffectiveMultiple(this.currentOptions),
|
|
295
|
+
) {
|
|
296
|
+
if (multiple) {
|
|
281
297
|
return itemCount > 0 ? this.scope.locale.AddImage() : this.scope.locale.SelectImage();
|
|
282
298
|
}
|
|
283
299
|
return itemCount > 0 ? this.scope.locale.ReplaceImage() : this.scope.locale.SelectImage();
|
|
284
300
|
}
|
|
285
301
|
|
|
302
|
+
private _getUploadPolicyQuery(options?: IResourceFormFieldImageOptions) {
|
|
303
|
+
return this.$$modelImage.getUploadPolicy(options?.imageScene as string | undefined);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private _getUploadPolicyState(options?: IResourceFormFieldImageOptions): IUploadPolicyState {
|
|
307
|
+
const query = this._getUploadPolicyQuery(options);
|
|
308
|
+
const policy = query?.data;
|
|
309
|
+
return {
|
|
310
|
+
acceptAttr: this._getAcceptAttr(options, policy),
|
|
311
|
+
multiple: this._getEffectiveMultiple(options, policy),
|
|
312
|
+
pending: query ? query.data === undefined && !!(query.isPending || query.isFetching) : false,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private _getCachedUploadPolicy(options?: IResourceFormFieldImageOptions) {
|
|
317
|
+
return this._getUploadPolicyQuery(options)?.data;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private async _waitForUploadPolicy(options?: IResourceFormFieldImageOptions) {
|
|
321
|
+
await $QueryEnsureLoaded(() => this._getUploadPolicyQuery(options));
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private _getEffectiveMultiple(
|
|
325
|
+
options?: IResourceFormFieldImageOptions,
|
|
326
|
+
policy = this._getCachedUploadPolicy(options),
|
|
327
|
+
) {
|
|
328
|
+
return !!(options?.multiple ?? policy?.multiple);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private _applyInputPolicy(uploadPolicyState: IUploadPolicyState) {
|
|
332
|
+
if (!this.fileInputRef) return;
|
|
333
|
+
this.fileInputRef.accept = uploadPolicyState.acceptAttr;
|
|
334
|
+
this.fileInputRef.multiple = uploadPolicyState.multiple;
|
|
335
|
+
}
|
|
336
|
+
|
|
286
337
|
private async _handleFileChange(event: Event, disableNotifyChanged?: boolean) {
|
|
287
338
|
const input = event.target as HTMLInputElement;
|
|
288
339
|
const files = Array.from(input.files ?? []);
|
|
@@ -290,20 +341,21 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
290
341
|
if (files.length === 0) return;
|
|
291
342
|
this.errorMessage = undefined;
|
|
292
343
|
const options = this.currentOptions ?? {};
|
|
293
|
-
const multiple = !!options.multiple;
|
|
294
|
-
const currentIds = this._normalizeValueToImageIds(this.currentValue, multiple);
|
|
295
|
-
const filesToHandle = options.multiple ? files : files.slice(0, 1);
|
|
296
|
-
const maxCount = this._getMaxCount(options);
|
|
297
|
-
const nextCountCandidate = options.multiple
|
|
298
|
-
? currentIds.length + filesToHandle.length
|
|
299
|
-
: filesToHandle.length;
|
|
300
|
-
if (nextCountCandidate > maxCount) {
|
|
301
|
-
this.errorMessage = this.scope.locale.TooManyImages(maxCount);
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
344
|
const uploadTarget = this._resolveUploadTarget();
|
|
305
345
|
this.isUploading = true;
|
|
306
346
|
try {
|
|
347
|
+
await this._waitForUploadPolicy(options);
|
|
348
|
+
const multiple = this._getEffectiveMultiple(options);
|
|
349
|
+
const currentIds = this._normalizeValueToImageIds(this.currentValue, multiple);
|
|
350
|
+
const filesToHandle = multiple ? files : files.slice(0, 1);
|
|
351
|
+
const maxCount = this._getMaxCount(options);
|
|
352
|
+
const nextCountCandidate = multiple
|
|
353
|
+
? currentIds.length + filesToHandle.length
|
|
354
|
+
: filesToHandle.length;
|
|
355
|
+
if (nextCountCandidate > maxCount) {
|
|
356
|
+
this.errorMessage = this.scope.locale.TooManyImages(maxCount);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
307
359
|
const uploadedItems: IImagePreviewItem[] = [];
|
|
308
360
|
for (const file of filesToHandle) {
|
|
309
361
|
const validationMessage = this._validateFile(file, options);
|
|
@@ -333,7 +385,7 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
333
385
|
uploadedItems.push(item);
|
|
334
386
|
}
|
|
335
387
|
if (uploadedItems.length === 0) return;
|
|
336
|
-
const nextIds =
|
|
388
|
+
const nextIds = multiple
|
|
337
389
|
? [...currentIds, ...uploadedItems.map(item => item.id)]
|
|
338
390
|
: [uploadedItems[uploadedItems.length - 1].id];
|
|
339
391
|
this._setFieldValue(nextIds, disableNotifyChanged, multiple);
|
|
@@ -356,7 +408,7 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
356
408
|
}
|
|
357
409
|
|
|
358
410
|
private _removeItem(imageId: TableIdentity, disableNotifyChanged?: boolean) {
|
|
359
|
-
const multiple =
|
|
411
|
+
const multiple = this._getEffectiveMultiple(this.currentOptions);
|
|
360
412
|
const currentIds = this._normalizeValueToImageIds(this.currentValue, multiple);
|
|
361
413
|
const nextIds = currentIds.filter(item => String(item) !== String(imageId));
|
|
362
414
|
delete this.uploadedPreviewMap[String(imageId)];
|
|
@@ -371,12 +423,12 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
371
423
|
) {
|
|
372
424
|
const nextValue = multiple ? imageIds : (imageIds[0] ?? '');
|
|
373
425
|
this.currentValue = nextValue as any;
|
|
374
|
-
this._syncRelationField(imageIds);
|
|
426
|
+
this._syncRelationField(imageIds, multiple);
|
|
375
427
|
this.$$formField?.setValue(nextValue, disableNotifyChanged);
|
|
376
428
|
this.$$formField?.handleBlur();
|
|
377
429
|
}
|
|
378
430
|
|
|
379
|
-
private _syncRelationField(imageIds: TableIdentity[]) {
|
|
431
|
+
private _syncRelationField(imageIds: TableIdentity[], multiple: boolean) {
|
|
380
432
|
const relationName = this._getRelationName();
|
|
381
433
|
if (!relationName) return;
|
|
382
434
|
const relationMap = this._getRelationPreviewMap();
|
|
@@ -384,14 +436,14 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
384
436
|
const key = String(imageId);
|
|
385
437
|
return this.uploadedPreviewMap[key] ?? relationMap[key] ?? { id: imageId };
|
|
386
438
|
});
|
|
387
|
-
const relationValue =
|
|
388
|
-
? relationItems
|
|
389
|
-
: (relationItems[0] ?? undefined);
|
|
439
|
+
const relationValue = multiple ? relationItems : (relationItems[0] ?? undefined);
|
|
390
440
|
this.$$renderContext.$$form.setFieldValue(relationName as never, relationValue, true);
|
|
391
441
|
}
|
|
392
442
|
|
|
393
|
-
private _getPreviewItems(
|
|
394
|
-
|
|
443
|
+
private _getPreviewItems(
|
|
444
|
+
value: unknown,
|
|
445
|
+
multiple = this._getEffectiveMultiple(this.currentOptions),
|
|
446
|
+
) {
|
|
395
447
|
const imageIds = this._normalizeValueToImageIds(value, multiple);
|
|
396
448
|
const relationMap = this._getRelationPreviewMap();
|
|
397
449
|
if (imageIds.length === 0) {
|
|
@@ -443,15 +495,21 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
443
495
|
}
|
|
444
496
|
|
|
445
497
|
private _getMaxCount(options: IResourceFormFieldImageOptions) {
|
|
446
|
-
if (!options
|
|
498
|
+
if (!this._getEffectiveMultiple(options)) return 1;
|
|
447
499
|
return Math.max(options.maxCount ?? 1, 1);
|
|
448
500
|
}
|
|
449
501
|
|
|
450
|
-
private _getAcceptAttr(
|
|
502
|
+
private _getAcceptAttr(
|
|
503
|
+
options?: IResourceFormFieldImageOptions,
|
|
504
|
+
policy = this._getCachedUploadPolicy(options),
|
|
505
|
+
) {
|
|
451
506
|
if (!options) return 'image/*';
|
|
452
507
|
if (typeof options.accept === 'string') return options.accept;
|
|
453
508
|
if (options.accept?.length) return options.accept.join(',');
|
|
454
|
-
const parts = [
|
|
509
|
+
const parts = [
|
|
510
|
+
...(options.mimeTypes ?? policy?.mimeTypes ?? []),
|
|
511
|
+
...(options.extensions ?? policy?.extensions ?? []),
|
|
512
|
+
];
|
|
455
513
|
return parts.length > 0 ? parts.join(',') : 'image/*';
|
|
456
514
|
}
|
|
457
515
|
|
|
@@ -460,8 +518,9 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
460
518
|
if (acceptTokens.length > 0 && !this._matchesAccept(file, acceptTokens)) {
|
|
461
519
|
return this.scope.locale.InvalidImageType();
|
|
462
520
|
}
|
|
463
|
-
|
|
464
|
-
|
|
521
|
+
const maxSize = options.maxSize ?? this._getCachedUploadPolicy(options)?.maxSize;
|
|
522
|
+
if (typeof maxSize === 'number' && file.size > maxSize) {
|
|
523
|
+
return this.scope.locale.ImageTooLarge(this._formatBytes(maxSize));
|
|
465
524
|
}
|
|
466
525
|
if (options.minSize && file.size < options.minSize) {
|
|
467
526
|
return this.scope.locale.ImageTooSmall(this._formatBytes(options.minSize));
|
|
@@ -475,7 +534,12 @@ export class ControllerFormFieldImage extends BeanControllerBase {
|
|
|
475
534
|
? options.accept
|
|
476
535
|
: options.accept.split(',')
|
|
477
536
|
: [];
|
|
478
|
-
|
|
537
|
+
const policy = this._getCachedUploadPolicy(options);
|
|
538
|
+
return [
|
|
539
|
+
...accept,
|
|
540
|
+
...(options.mimeTypes ?? policy?.mimeTypes ?? []),
|
|
541
|
+
...(options.extensions ?? policy?.extensions ?? []),
|
|
542
|
+
]
|
|
479
543
|
.map(item => item.trim().toLowerCase())
|
|
480
544
|
.filter(item => !!item);
|
|
481
545
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { IDecoratorModelOptions } from 'zova-module-a-model';
|
|
2
|
+
|
|
3
|
+
import { BeanModelBase, Model } from 'zova-module-a-model';
|
|
4
|
+
|
|
5
|
+
import type { ApiApiImagegetUploadPolicyResponseBody } from '../api/image.js';
|
|
6
|
+
|
|
7
|
+
export interface IModelOptionsImage extends IDecoratorModelOptions {}
|
|
8
|
+
|
|
9
|
+
@Model<IModelOptionsImage>()
|
|
10
|
+
export class ModelImage extends BeanModelBase {
|
|
11
|
+
getUploadPolicy(imageScene?: string) {
|
|
12
|
+
if (!imageScene) return undefined;
|
|
13
|
+
return this.$useStateData<ApiApiImagegetUploadPolicyResponseBody>({
|
|
14
|
+
queryKey: ['uploadPolicy', 'image', imageScene],
|
|
15
|
+
queryFn: async () => {
|
|
16
|
+
return this.scope.api.image.getUploadPolicy({ imageScene });
|
|
17
|
+
},
|
|
18
|
+
meta: {
|
|
19
|
+
disableSuspenseOnInit: true,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockPage/controller.tsx
CHANGED
|
@@ -14,7 +14,7 @@ import { VNode } from 'vue';
|
|
|
14
14
|
import { BeanControllerBase, deepEqual } from 'zova';
|
|
15
15
|
import { ZovaJsx } from 'zova-jsx';
|
|
16
16
|
import { Controller } from 'zova-module-a-bean';
|
|
17
|
-
import { $
|
|
17
|
+
import { $QueriesEnsureLoaded } from 'zova-module-a-model';
|
|
18
18
|
import { BeanControllerTableBase } from 'zova-module-a-table';
|
|
19
19
|
import { ModelResource } from 'zova-module-rest-resource';
|
|
20
20
|
|
|
@@ -38,7 +38,9 @@ export class ControllerBlockPage<TData extends {} = {}> extends BeanControllerBa
|
|
|
38
38
|
|
|
39
39
|
static $componentOptions: IComponentOptions = { inheritAttrs: false, deepExtendDefault: true };
|
|
40
40
|
|
|
41
|
-
tableRef: BeanControllerTableBase<TData
|
|
41
|
+
tableRef: BeanControllerTableBase<TData> | undefined;
|
|
42
|
+
private _tableMetaRefreshPending = false;
|
|
43
|
+
private _tableMetaRefreshTask: Promise<void> | undefined;
|
|
42
44
|
|
|
43
45
|
jsxZova: ZovaJsx;
|
|
44
46
|
jsxCelScope: IPageScope;
|
|
@@ -65,7 +67,7 @@ export class ControllerBlockPage<TData extends {} = {}> extends BeanControllerBa
|
|
|
65
67
|
return Object.assign({}, this.queryFilterData, this.queryPaged);
|
|
66
68
|
});
|
|
67
69
|
// load schema/data
|
|
68
|
-
await $
|
|
70
|
+
await $QueriesEnsureLoaded(
|
|
69
71
|
() => this.$$modelResource.apiSchemasSelect.sdk,
|
|
70
72
|
() => this.queryData,
|
|
71
73
|
);
|
|
@@ -74,7 +76,7 @@ export class ControllerBlockPage<TData extends {} = {}> extends BeanControllerBa
|
|
|
74
76
|
() => this.permissions,
|
|
75
77
|
async (newValue, oldValue) => {
|
|
76
78
|
if (deepEqual(newValue, oldValue)) return;
|
|
77
|
-
await this.
|
|
79
|
+
await this._requestTableMetaRefresh();
|
|
78
80
|
},
|
|
79
81
|
);
|
|
80
82
|
}
|
|
@@ -123,6 +125,44 @@ export class ControllerBlockPage<TData extends {} = {}> extends BeanControllerBa
|
|
|
123
125
|
this.queryFilterData = data;
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
public setTableRef(tableRef: BeanControllerTableBase<TData> | undefined) {
|
|
129
|
+
this.tableRef = tableRef;
|
|
130
|
+
if (!tableRef || !this._tableMetaRefreshPending) return;
|
|
131
|
+
this._scheduleTableMetaRefresh();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private _scheduleTableMetaRefresh() {
|
|
135
|
+
void this._flushTableMetaRefresh().catch(err => {
|
|
136
|
+
this.$errorHandler(err, 'ControllerBlockPage.setTableRef');
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private async _requestTableMetaRefresh() {
|
|
141
|
+
this._tableMetaRefreshPending = true;
|
|
142
|
+
await this._flushTableMetaRefresh();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private async _flushTableMetaRefresh() {
|
|
146
|
+
if (this._tableMetaRefreshTask) return await this._tableMetaRefreshTask;
|
|
147
|
+
const task = (async () => {
|
|
148
|
+
while (this._tableMetaRefreshPending) {
|
|
149
|
+
const tableRef = this.tableRef;
|
|
150
|
+
if (!tableRef) return;
|
|
151
|
+
this._tableMetaRefreshPending = false;
|
|
152
|
+
await tableRef.refreshMeta();
|
|
153
|
+
}
|
|
154
|
+
})();
|
|
155
|
+
this._tableMetaRefreshTask = task;
|
|
156
|
+
try {
|
|
157
|
+
await task;
|
|
158
|
+
} finally {
|
|
159
|
+
this._tableMetaRefreshTask = undefined;
|
|
160
|
+
if (this._tableMetaRefreshPending && this.tableRef) {
|
|
161
|
+
this._scheduleTableMetaRefresh();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
126
166
|
private _prepareJsx() {
|
|
127
167
|
const jsxCelEnv = celEnvBase.clone();
|
|
128
168
|
this.jsxZova = this.bean._newBeanSimple(ZovaJsx, false, undefined, jsxCelEnv);
|
package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockTable/controller.tsx
CHANGED
|
@@ -3,7 +3,8 @@ import type { IJsxRenderContextPage, IResourceBlockOptionsBase } from 'zova-modu
|
|
|
3
3
|
|
|
4
4
|
import { BeanControllerBase, Use } from 'zova';
|
|
5
5
|
import { Controller } from 'zova-module-a-bean';
|
|
6
|
-
import { BeanControllerTableBase
|
|
6
|
+
import { BeanControllerTableBase } from 'zova-module-a-table';
|
|
7
|
+
import { ZTable } from 'zova-module-basic-table';
|
|
7
8
|
|
|
8
9
|
declare module 'zova-module-a-openapi' {
|
|
9
10
|
export interface IResourceBlockRecord {
|
|
@@ -15,7 +16,10 @@ export interface ControllerBlockTableProps extends IResourceBlockOptionsBase {}
|
|
|
15
16
|
|
|
16
17
|
@Controller()
|
|
17
18
|
export class ControllerBlockTable<TData extends {} = {}> extends BeanControllerBase {
|
|
18
|
-
static $propsDefault = {
|
|
19
|
+
static $propsDefault = {
|
|
20
|
+
class: 'overflow-x-auto rounded-box border border-base-content/15 bg-base-100',
|
|
21
|
+
};
|
|
22
|
+
|
|
19
23
|
static $componentOptions: IComponentOptions = { inheritAttrs: false, deepExtendDefault: true };
|
|
20
24
|
|
|
21
25
|
tableRef: BeanControllerTableBase<TData>;
|
|
@@ -32,16 +36,17 @@ export class ControllerBlockTable<TData extends {} = {}> extends BeanControllerB
|
|
|
32
36
|
protected render() {
|
|
33
37
|
const { $$page } = this.$$renderContext;
|
|
34
38
|
return (
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
<div class={this.$props.class}>
|
|
40
|
+
<ZTable<TData>
|
|
41
|
+
tableRef={ref => {
|
|
42
|
+
this.tableRef = ref;
|
|
43
|
+
$$page.setTableRef(ref as unknown as BeanControllerTableBase<{}> | undefined);
|
|
44
|
+
}}
|
|
45
|
+
data={$$page.data as unknown as TData[]}
|
|
46
|
+
schema={$$page.schemaRow}
|
|
47
|
+
tableScope={$$page.jsxCelScope}
|
|
48
|
+
></ZTable>
|
|
49
|
+
</div>
|
|
45
50
|
);
|
|
46
51
|
}
|
|
47
52
|
}
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
formMetaFromFormScene,
|
|
23
23
|
TypeFormOnSubmitData,
|
|
24
24
|
} from 'zova-module-a-form';
|
|
25
|
-
import { $
|
|
25
|
+
import { $QueriesEnsureLoaded } from 'zova-module-a-model';
|
|
26
26
|
import { ModelResource } from 'zova-module-rest-resource';
|
|
27
27
|
|
|
28
28
|
declare module 'zova-module-a-openapi' {
|
|
@@ -81,7 +81,7 @@ export class ControllerBlockPageEntry<TData extends {} = {}> extends BeanControl
|
|
|
81
81
|
// jsx
|
|
82
82
|
this._prepareJsx();
|
|
83
83
|
// load schema/data
|
|
84
|
-
await $
|
|
84
|
+
await $QueriesEnsureLoaded(
|
|
85
85
|
() => this.$$modelResource.getFormApiSchemas(this.formMeta)?.sdk,
|
|
86
86
|
() => this.queryData,
|
|
87
87
|
);
|
|
@@ -6,7 +6,7 @@ import { classes } from 'typestyle';
|
|
|
6
6
|
import { BeanControllerBase, Use } from 'zova';
|
|
7
7
|
import { Controller } from 'zova-module-a-bean';
|
|
8
8
|
import { ZFormField, ZFormFieldPreset } from 'zova-module-a-form';
|
|
9
|
-
import { $
|
|
9
|
+
import { $QueryEnsureLoaded } from 'zova-module-a-model';
|
|
10
10
|
import { ZSelect, ZSelectProps } from 'zova-module-basic-select';
|
|
11
11
|
import { ModelResource } from 'zova-module-rest-resource';
|
|
12
12
|
|
|
@@ -52,7 +52,7 @@ export class ControllerFormFieldResourcePicker extends BeanControllerBase {
|
|
|
52
52
|
this.resource,
|
|
53
53
|
);
|
|
54
54
|
// load data
|
|
55
|
-
await $
|
|
55
|
+
await $QueryEnsureLoaded(() => this.queryData);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
get resource() {
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
BeanControllerTableBase,
|
|
3
|
+
ControllerTableProps as ControllerTablePropsSuper,
|
|
4
|
+
} from 'zova-module-a-table';
|
|
2
5
|
|
|
3
6
|
import { BeanControllerBase } from 'zova';
|
|
4
7
|
import { Controller } from 'zova-module-a-bean';
|
|
5
8
|
|
|
6
9
|
export interface ControllerTableProps<
|
|
7
10
|
TData extends {} = {},
|
|
8
|
-
> extends ControllerTablePropsSuper<TData> {
|
|
11
|
+
> extends ControllerTablePropsSuper<TData> {
|
|
12
|
+
tableRef?: (ref: BeanControllerTableBase<TData>) => void;
|
|
13
|
+
}
|
|
9
14
|
|
|
10
15
|
@Controller()
|
|
11
16
|
export class ControllerTable extends BeanControllerBase {
|
|
@@ -9,6 +9,9 @@ export class RenderTable<TData extends {} = {}> extends BeanRenderBase {
|
|
|
9
9
|
return (
|
|
10
10
|
<ZTable
|
|
11
11
|
{...this.$props}
|
|
12
|
+
controllerRef={ref => {
|
|
13
|
+
this.$props?.tableRef?.(ref);
|
|
14
|
+
}}
|
|
12
15
|
slotDefault={$$table => {
|
|
13
16
|
return this._renderTable($$table);
|
|
14
17
|
}}
|
|
@@ -19,42 +22,40 @@ export class RenderTable<TData extends {} = {}> extends BeanRenderBase {
|
|
|
19
22
|
public _renderTable($$table: ControllerTable<TData>) {
|
|
20
23
|
const table = $$table.table;
|
|
21
24
|
return (
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
{table.getFlatHeaders().map(header => {
|
|
27
|
-
return (
|
|
28
|
-
<th key={header.id}>
|
|
29
|
-
<FlexRender
|
|
30
|
-
render={header.column.columnDef.header}
|
|
31
|
-
props={header.getContext()}
|
|
32
|
-
></FlexRender>
|
|
33
|
-
</th>
|
|
34
|
-
);
|
|
35
|
-
})}
|
|
36
|
-
</tr>
|
|
37
|
-
</thead>
|
|
38
|
-
<tbody>
|
|
39
|
-
{table.getRowModel().rows.map(row => {
|
|
25
|
+
<table class="table">
|
|
26
|
+
<thead>
|
|
27
|
+
<tr>
|
|
28
|
+
{table.getFlatHeaders().map(header => {
|
|
40
29
|
return (
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
props={cell.getContext()}
|
|
48
|
-
></FlexRender>
|
|
49
|
-
</td>
|
|
50
|
-
);
|
|
51
|
-
})}
|
|
52
|
-
</tr>
|
|
30
|
+
<th key={header.id}>
|
|
31
|
+
<FlexRender
|
|
32
|
+
render={header.column.columnDef.header}
|
|
33
|
+
props={header.getContext()}
|
|
34
|
+
></FlexRender>
|
|
35
|
+
</th>
|
|
53
36
|
);
|
|
54
37
|
})}
|
|
55
|
-
</
|
|
56
|
-
</
|
|
57
|
-
|
|
38
|
+
</tr>
|
|
39
|
+
</thead>
|
|
40
|
+
<tbody>
|
|
41
|
+
{table.getRowModel().rows.map(row => {
|
|
42
|
+
return (
|
|
43
|
+
<tr key={row.id}>
|
|
44
|
+
{row.getVisibleCells().map(cell => {
|
|
45
|
+
return (
|
|
46
|
+
<td key={cell.id}>
|
|
47
|
+
<FlexRender
|
|
48
|
+
render={cell.column.columnDef.cell}
|
|
49
|
+
props={cell.getContext()}
|
|
50
|
+
></FlexRender>
|
|
51
|
+
</td>
|
|
52
|
+
);
|
|
53
|
+
})}
|
|
54
|
+
</tr>
|
|
55
|
+
);
|
|
56
|
+
})}
|
|
57
|
+
</tbody>
|
|
58
|
+
</table>
|
|
58
59
|
);
|
|
59
60
|
}
|
|
60
61
|
}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"zova-module-basic-currency": "^5.1.15",
|
|
16
16
|
"zova-module-basic-date": "^5.0.6",
|
|
17
17
|
"zova-module-basic-details": "^5.0.0",
|
|
18
|
+
"zova-module-basic-file": "^5.0.0",
|
|
18
19
|
"zova-module-basic-form": "^5.0.7",
|
|
19
20
|
"zova-module-basic-image": "^5.0.0",
|
|
20
21
|
"zova-module-basic-input": "^5.0.7",
|