@nocobase/client-v2 2.1.0-alpha.40 → 2.1.0-alpha.46
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/es/Application.d.ts +7 -0
- package/es/BaseApplication.d.ts +13 -0
- package/es/RouterManager.d.ts +1 -0
- package/es/authRedirect.d.ts +12 -0
- package/es/collection-field-interface/CollectionFieldInterface.d.ts +51 -15
- package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +82 -3
- package/es/collection-manager/field-configure.d.ts +80 -0
- package/es/collection-manager/field-validation.d.ts +43 -0
- package/es/collection-manager/filter-operators/index.d.ts +46 -0
- package/es/collection-manager/filter-operators/operators.d.ts +30 -0
- package/es/collection-manager/interfaces/checkbox.d.ts +1 -41
- package/es/collection-manager/interfaces/checkboxGroup.d.ts +12 -44
- package/es/collection-manager/interfaces/collection.d.ts +12 -51
- package/es/collection-manager/interfaces/color.d.ts +1 -16
- package/es/collection-manager/interfaces/createdAt.d.ts +1 -44
- package/es/collection-manager/interfaces/createdBy.d.ts +0 -4
- package/es/collection-manager/interfaces/dateOnly.d.ts +7 -44
- package/es/collection-manager/interfaces/datetime.d.ts +1 -44
- package/es/collection-manager/interfaces/datetimeNoTz.d.ts +1 -44
- package/es/collection-manager/interfaces/email.d.ts +1 -29
- package/es/collection-manager/interfaces/id.d.ts +1 -16
- package/es/collection-manager/interfaces/index.d.ts +2 -3
- package/es/collection-manager/interfaces/input.d.ts +1 -102
- package/es/collection-manager/interfaces/integer.d.ts +1 -95
- package/es/collection-manager/interfaces/json.d.ts +16 -7
- package/es/collection-manager/interfaces/m2m.d.ts +11 -19
- package/es/collection-manager/interfaces/m2o.d.ts +11 -19
- package/es/collection-manager/interfaces/markdown.d.ts +1 -63
- package/es/collection-manager/interfaces/multipleSelect.d.ts +12 -44
- package/es/collection-manager/interfaces/nanoid.d.ts +1 -34
- package/es/collection-manager/interfaces/number.d.ts +1 -87
- package/es/collection-manager/interfaces/o2m.d.ts +12 -24
- package/es/collection-manager/interfaces/obo.d.ts +207 -0
- package/es/collection-manager/interfaces/oho.d.ts +207 -0
- package/es/collection-manager/interfaces/password.d.ts +1 -56
- package/es/collection-manager/interfaces/percent.d.ts +1 -84
- package/es/collection-manager/interfaces/phone.d.ts +1 -25
- package/es/collection-manager/interfaces/properties/index.d.ts +0 -28
- package/es/collection-manager/interfaces/radioGroup.d.ts +1 -29
- package/es/collection-manager/interfaces/richText.d.ts +1 -63
- package/es/collection-manager/interfaces/select.d.ts +12 -44
- package/es/collection-manager/interfaces/snowflake-id.d.ts +1 -34
- package/es/collection-manager/interfaces/tableoid.d.ts +1 -10
- package/es/collection-manager/interfaces/textarea.d.ts +1 -51
- package/es/collection-manager/interfaces/time.d.ts +1 -16
- package/es/collection-manager/interfaces/types.d.ts +3 -12
- package/es/collection-manager/interfaces/unixTimestamp.d.ts +1 -44
- package/es/collection-manager/interfaces/updatedAt.d.ts +1 -44
- package/es/collection-manager/interfaces/updatedBy.d.ts +0 -4
- package/es/collection-manager/interfaces/url.d.ts +1 -20
- package/es/collection-manager/interfaces/uuid.d.ts +1 -34
- package/es/collection-manager/template-fields.d.ts +53 -0
- package/es/components/KeepAlive.d.ts +22 -0
- package/es/components/RouterBridge.d.ts +9 -0
- package/es/components/form/DialogFormLayout.d.ts +5 -29
- package/es/components/form/TypedVariableInput.d.ts +75 -0
- package/es/components/form/VariableInput.d.ts +53 -2
- package/es/components/form/filter/CollectionFilter.d.ts +49 -0
- package/es/components/form/filter/CollectionFilterItem.d.ts +49 -0
- package/es/components/form/filter/DateFilterDynamicComponent.d.ts +57 -0
- package/es/components/form/filter/FilterValueInput.d.ts +29 -0
- package/es/components/form/filter/index.d.ts +11 -0
- package/es/components/form/filter/useFilterActionProps.d.ts +96 -0
- package/es/components/form/index.d.ts +2 -0
- package/es/data-source/ExtendCollectionsProvider.d.ts +50 -0
- package/es/data-source/index.d.ts +9 -0
- package/es/flow/FlowPage.d.ts +2 -1
- package/es/flow/admin-shell/AdminLayoutRouteCoordinator.d.ts +8 -40
- package/es/flow/admin-shell/BaseLayoutModel.d.ts +89 -0
- package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +74 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +12 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +1 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutModel.d.ts +7 -92
- package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +11 -0
- package/es/flow/admin-shell/admin-layout/index.d.ts +3 -0
- package/es/flow/admin-shell/admin-layout/useApplications.d.ts +3 -2
- package/es/flow/admin-shell/useAdminLayoutRoutePage.d.ts +2 -2
- package/es/flow/admin-shell/useLayoutRoutePage.d.ts +23 -0
- package/es/flow/components/ConditionBuilder.d.ts +1 -0
- package/es/flow/components/FieldAssignRulesEditor.d.ts +3 -1
- package/es/flow/components/FieldAssignValueInput.d.ts +1 -0
- package/es/flow/components/FlowRoute.d.ts +10 -1
- package/es/flow/components/fieldAssignOptions.d.ts +10 -0
- package/es/flow/components/filter/LinkageFilterItem.d.ts +1 -0
- package/es/flow/components/filter/VariableFilterItem.d.ts +1 -0
- package/es/flow/components/filter/index.d.ts +2 -0
- package/es/flow/components/filter/metaTreeAssociationDepth.d.ts +13 -0
- package/es/flow/components/filter/useFilterOptions.d.ts +66 -0
- package/es/flow/index.d.ts +4 -0
- package/es/flow/models/base/AssociationFieldGroupModel.d.ts +2 -33
- package/es/flow/models/base/PageModel/PageModel.d.ts +3 -1
- package/es/flow/models/blocks/assign-form/assignFieldValuesFlow.d.ts +92 -0
- package/es/flow/models/blocks/assign-form/index.d.ts +1 -0
- package/es/flow/models/blocks/form/FormActionGroupModel.d.ts +1 -0
- package/es/flow/models/blocks/form/FormActionModel.d.ts +9 -2
- package/es/flow/models/blocks/table/TableBlockModel.d.ts +10 -0
- package/es/flow/models/blocks/table/TableColumnModel.d.ts +2 -0
- package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.d.ts +1 -1
- package/es/flow-compat/passwordUtils.d.ts +1 -1
- package/es/index.d.ts +6 -0
- package/es/index.mjs +552 -459
- package/es/layout-manager/LayoutContentRoute.d.ts +14 -0
- package/es/layout-manager/LayoutManager.d.ts +22 -0
- package/es/layout-manager/LayoutRoute.d.ts +14 -0
- package/es/layout-manager/index.d.ts +13 -0
- package/es/layout-manager/types.d.ts +20 -0
- package/es/layout-manager/utils.d.ts +14 -0
- package/es/nocobase-buildin-plugin/index.d.ts +3 -10
- package/es/settings-center/index.d.ts +1 -1
- package/es/settings-center/plugin-manager/BulkEnableButton.d.ts +15 -0
- package/es/settings-center/plugin-manager/PluginCard.d.ts +15 -0
- package/es/settings-center/plugin-manager/PluginDetail.d.ts +16 -0
- package/es/settings-center/{PluginManagerPage.d.ts → plugin-manager/index.d.ts} +1 -7
- package/es/settings-center/plugin-manager/types.d.ts +34 -0
- package/lib/index.js +552 -459
- package/package.json +8 -7
- package/src/Application.tsx +51 -12
- package/src/BaseApplication.tsx +32 -0
- package/src/PluginSettingsManager.ts +1 -1
- package/src/RouterManager.tsx +17 -1
- package/src/__tests__/PluginSettingsManager.test.ts +41 -2
- package/src/__tests__/app.test.tsx +17 -1
- package/src/__tests__/globalDeps.test.ts +1 -0
- package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +50 -2
- package/src/__tests__/plugin-manager.test.tsx +177 -0
- package/src/__tests__/settings-center.test.tsx +24 -2
- package/src/authRedirect.ts +43 -0
- package/src/collection-field-interface/CollectionFieldInterface.ts +71 -77
- package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +201 -4
- package/src/collection-manager/field-configure.ts +548 -0
- package/src/collection-manager/field-validation.ts +195 -0
- package/src/collection-manager/filter-operators/index.ts +176 -0
- package/src/collection-manager/{interfaces/properties → filter-operators}/operators.ts +24 -13
- package/src/collection-manager/interfaces/checkbox.ts +2 -9
- package/src/collection-manager/interfaces/checkboxGroup.ts +2 -10
- package/src/collection-manager/interfaces/collection.ts +2 -15
- package/src/collection-manager/interfaces/color.ts +2 -2
- package/src/collection-manager/interfaces/createdAt.ts +2 -2
- package/src/collection-manager/interfaces/createdBy.ts +1 -12
- package/src/collection-manager/interfaces/dateOnly.ts +8 -2
- package/src/collection-manager/interfaces/datetime.ts +2 -2
- package/src/collection-manager/interfaces/datetimeNoTz.ts +2 -2
- package/src/collection-manager/interfaces/email.ts +2 -9
- package/src/collection-manager/interfaces/id.ts +1 -2
- package/src/collection-manager/interfaces/index.ts +2 -3
- package/src/collection-manager/interfaces/input.ts +2 -133
- package/src/collection-manager/interfaces/integer.ts +2 -71
- package/src/collection-manager/interfaces/json.tsx +17 -11
- package/src/collection-manager/interfaces/m2m.tsx +0 -21
- package/src/collection-manager/interfaces/m2o.tsx +0 -22
- package/src/collection-manager/interfaces/markdown.ts +2 -51
- package/src/collection-manager/interfaces/multipleSelect.ts +2 -14
- package/src/collection-manager/interfaces/nanoid.ts +2 -2
- package/src/collection-manager/interfaces/number.ts +2 -85
- package/src/collection-manager/interfaces/o2m.tsx +1 -22
- package/src/collection-manager/interfaces/obo.tsx +145 -0
- package/src/collection-manager/interfaces/oho.tsx +145 -0
- package/src/collection-manager/interfaces/password.ts +2 -44
- package/src/collection-manager/interfaces/percent.ts +2 -74
- package/src/collection-manager/interfaces/phone.ts +2 -2
- package/src/collection-manager/interfaces/properties/index.ts +0 -133
- package/src/collection-manager/interfaces/radioGroup.ts +2 -2
- package/src/collection-manager/interfaces/richText.ts +2 -51
- package/src/collection-manager/interfaces/select.ts +2 -14
- package/src/collection-manager/interfaces/snowflake-id.ts +2 -2
- package/src/collection-manager/interfaces/tableoid.ts +1 -2
- package/src/collection-manager/interfaces/textarea.ts +2 -51
- package/src/collection-manager/interfaces/time.ts +2 -2
- package/src/collection-manager/interfaces/types.ts +4 -12
- package/src/collection-manager/interfaces/unixTimestamp.tsx +2 -2
- package/src/collection-manager/interfaces/updatedAt.ts +2 -2
- package/src/collection-manager/interfaces/updatedBy.ts +1 -12
- package/src/collection-manager/interfaces/url.ts +2 -4
- package/src/collection-manager/interfaces/uuid.ts +2 -2
- package/src/collection-manager/template-fields.ts +109 -0
- package/src/components/KeepAlive.tsx +131 -0
- package/src/components/README.md +138 -6
- package/src/components/README.zh-CN.md +138 -7
- package/src/components/RouterBridge.tsx +28 -4
- package/src/components/__tests__/KeepAlive.test.tsx +63 -0
- package/src/components/__tests__/RouterBridge.test.tsx +27 -0
- package/src/components/form/DialogFormLayout.tsx +5 -29
- package/src/components/form/TypedVariableInput.tsx +441 -0
- package/src/components/form/VariableInput.tsx +101 -28
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +152 -0
- package/src/components/form/__tests__/VariableInput.test.ts +85 -0
- package/src/components/form/filter/CollectionFilter.tsx +111 -0
- package/src/components/form/filter/CollectionFilterItem.tsx +184 -0
- package/src/components/form/filter/DateFilterDynamicComponent.tsx +283 -0
- package/src/components/form/filter/FilterValueInput.tsx +198 -0
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +247 -0
- package/src/components/form/filter/__tests__/DateFilterDynamicComponent.test.tsx +148 -0
- package/src/components/form/filter/__tests__/FilterValueInput.test.tsx +243 -0
- package/src/components/form/filter/__tests__/compileFilterGroup.test.ts +146 -0
- package/src/components/form/filter/index.ts +13 -0
- package/src/components/form/filter/useFilterActionProps.ts +203 -0
- package/src/components/form/index.tsx +2 -0
- package/src/data-source/ExtendCollectionsProvider.tsx +144 -0
- package/src/data-source/__tests__/ExtendCollectionsProvider.test.tsx +264 -0
- package/src/data-source/index.ts +10 -0
- package/src/flow/FlowPage.tsx +35 -7
- package/src/flow/__tests__/FlowPage.test.tsx +79 -0
- package/src/flow/__tests__/FlowRoute.test.tsx +537 -3
- package/src/flow/actions/__tests__/linkageRules.hiddenSync.restore.test.ts +100 -0
- package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +191 -0
- package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +23 -1
- package/src/flow/actions/__tests__/openView.subModelKey.test.tsx +33 -0
- package/src/flow/actions/aclCheck.tsx +4 -0
- package/src/flow/actions/aclCheckRefresh.tsx +4 -0
- package/src/flow/actions/dataScope.tsx +8 -1
- package/src/flow/actions/dateTimeFormat.tsx +12 -8
- package/src/flow/actions/linkageRules.tsx +127 -2
- package/src/flow/actions/linkageRulesRefresh.tsx +2 -3
- package/src/flow/actions/openView.tsx +28 -4
- package/src/flow/actions/setTargetDataScope.tsx +1 -1
- package/src/flow/admin-shell/AdminLayoutRouteCoordinator.ts +11 -329
- package/src/flow/admin-shell/BaseLayoutModel.tsx +455 -0
- package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +502 -0
- package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +547 -3
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +35 -7
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +160 -0
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +15 -13
- package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +28 -201
- package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +11 -2
- package/src/flow/admin-shell/admin-layout/AppListRender.tsx +139 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +76 -27
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +149 -27
- package/src/flow/admin-shell/admin-layout/index.ts +3 -0
- package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.test.ts +11 -0
- package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.ts +2 -4
- package/src/flow/admin-shell/admin-layout/useApplications.tsx +34 -1
- package/src/flow/admin-shell/useAdminLayoutRoutePage.ts +10 -26
- package/src/flow/admin-shell/useLayoutRoutePage.ts +61 -0
- package/src/flow/common/Markdown/Edit.tsx +32 -4
- package/src/flow/components/AdminLayout.tsx +4 -154
- package/src/flow/components/ConditionBuilder.tsx +12 -2
- package/src/flow/components/FieldAssignRulesEditor.tsx +37 -46
- package/src/flow/components/FieldAssignValueInput.tsx +8 -4
- package/src/flow/components/FlowRoute.tsx +105 -15
- package/src/flow/components/__tests__/FieldAssignRulesEditor.test.tsx +112 -1
- package/src/flow/components/__tests__/fieldAssignOptions.test.ts +71 -1
- package/src/flow/components/code-editor/__tests__/runjsCompletions.test.ts +272 -27
- package/src/flow/components/code-editor/runjsCompletions.ts +490 -9
- package/src/flow/components/fieldAssignOptions.ts +23 -6
- package/src/flow/components/filter/LinkageFilterItem.tsx +22 -9
- package/src/flow/components/filter/VariableFilterItem.tsx +27 -9
- package/src/flow/components/filter/__tests__/fieldsToOptions.test.ts +48 -0
- package/src/flow/components/filter/__tests__/metaTreeAssociationDepth.test.ts +60 -0
- package/src/flow/components/filter/fieldsToOptions.ts +9 -4
- package/src/flow/components/filter/index.ts +3 -0
- package/src/flow/components/filter/metaTreeAssociationDepth.ts +69 -0
- package/src/flow/components/filter/useFilterOptions.ts +102 -0
- package/src/flow/index.ts +4 -0
- package/src/flow/models/actions/FilterActionModel.tsx +15 -3
- package/src/flow/models/actions/UpdateRecordActionModel.tsx +14 -95
- package/src/flow/models/actions/UpdateRecordActionUtils.ts +4 -7
- package/src/flow/models/actions/__tests__/AssignFormRefill.test.ts +116 -1
- package/src/flow/models/base/ActionModel.tsx +8 -1
- package/src/flow/models/base/AssociationFieldGroupModel.tsx +20 -3
- package/src/flow/models/base/GridModel.tsx +1 -1
- package/src/flow/models/base/PageModel/ChildPageModel.tsx +5 -1
- package/src/flow/models/base/PageModel/PageModel.tsx +51 -18
- package/src/flow/models/base/PageModel/RootPageModel.tsx +6 -13
- package/src/flow/models/base/PageModel/__tests__/ChildPageModel.test.ts +12 -0
- package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +102 -1
- package/src/flow/models/base/RouteModel.tsx +1 -1
- package/src/flow/models/base/__tests__/AssociationFieldGroupModel.test.ts +86 -0
- package/src/flow/models/base/__tests__/GridModel.render.test.tsx +53 -0
- package/src/flow/models/blocks/assign-form/AssignFormGridModel.tsx +12 -3
- package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +77 -6
- package/src/flow/models/blocks/assign-form/__tests__/assignFieldValuesFlow.editor.test.tsx +216 -0
- package/src/flow/models/blocks/assign-form/assignFieldValuesFlow.tsx +308 -0
- package/src/flow/models/blocks/assign-form/index.ts +1 -0
- package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +1 -1
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +6 -1
- package/src/flow/models/blocks/filter-manager/flow-actions/connectFields.tsx +48 -6
- package/src/flow/models/blocks/form/FormActionGroupModel.tsx +14 -0
- package/src/flow/models/blocks/form/FormActionModel.tsx +30 -3
- package/src/flow/models/blocks/form/FormAssociationItemModel.tsx +9 -0
- package/src/flow/models/blocks/form/FormItemModel.tsx +17 -1
- package/src/flow/models/blocks/form/__tests__/FormActionGroupModel.test.ts +46 -0
- package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +17 -0
- package/src/flow/models/blocks/form/__tests__/FormItemModel.defineChildren.test.ts +27 -2
- package/src/flow/models/blocks/form/__tests__/submitHandler.test.ts +71 -0
- package/src/flow/models/blocks/form/submitHandler.ts +8 -1
- package/src/flow/models/blocks/form/submitValues.ts +4 -1
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +29 -0
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +5 -1
- package/src/flow/models/blocks/table/TableBlockModel.tsx +118 -16
- package/src/flow/models/blocks/table/TableColumnModel.tsx +15 -5
- package/src/flow/models/blocks/table/TableCustomColumnModel.tsx +2 -2
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.rowSelection.test.tsx +114 -0
- package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +18 -0
- package/src/flow/models/fields/AssociationFieldModel/SubFormFieldModel.tsx +7 -1
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.tsx +6 -7
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +1 -1
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -5
- package/src/flow/models/fields/ClickableFieldModel.tsx +9 -1
- package/src/flow/models/fields/CollectionSelectorFieldModel.tsx +8 -2
- package/src/flow/models/fields/DisplayEnumFieldModel.tsx +8 -2
- package/src/flow/models/fields/DisplayTimeFieldModel.tsx +1 -1
- package/src/flow/models/fields/TimeFieldModel.tsx +1 -1
- package/src/flow/models/fields/__tests__/TimeFieldModel.test.tsx +61 -0
- package/src/flow/models/fields/mobile-components/MobileDatePicker.tsx +19 -3
- package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +5 -3
- package/src/flow/models/fields/mobile-components/__tests__/MobileDatePicker.test.tsx +94 -0
- package/src/flow/models/fields/mobile-components/__tests__/MobileSelect.test.tsx +70 -0
- package/src/flow/models/topbar/TopbarActionModel.tsx +1 -1
- package/src/flow/utils/__tests__/dateTimeFormat.test.ts +91 -0
- package/src/index.ts +6 -0
- package/src/layout-manager/LayoutContentRoute.tsx +90 -0
- package/src/layout-manager/LayoutManager.tsx +185 -0
- package/src/layout-manager/LayoutRoute.tsx +138 -0
- package/src/layout-manager/__tests__/LayoutManager.test.tsx +335 -0
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +473 -0
- package/src/layout-manager/index.ts +14 -0
- package/src/layout-manager/types.ts +22 -0
- package/src/layout-manager/utils.ts +37 -0
- package/src/nocobase-buildin-plugin/index.tsx +69 -67
- package/src/nocobase-buildin-plugin/plugins/LocalePlugin.ts +1 -0
- package/src/settings-center/index.ts +1 -1
- package/src/settings-center/plugin-manager/BulkEnableButton.tsx +111 -0
- package/src/settings-center/plugin-manager/PluginCard.tsx +270 -0
- package/src/settings-center/plugin-manager/PluginDetail.tsx +195 -0
- package/src/settings-center/plugin-manager/index.tsx +254 -0
- package/src/settings-center/plugin-manager/types.ts +35 -0
- package/src/settings-center/utils.tsx +8 -1
- package/src/theme/__tests__/globalStyles.test.ts +24 -0
- package/src/theme/globalStyles.ts +10 -0
- package/src/utils/globalDeps.ts +2 -0
- package/es/collection-manager/interfaces/linkTo.d.ts +0 -90
- package/es/collection-manager/interfaces/o2o.d.ts +0 -621
- package/es/collection-manager/interfaces/properties/operators.d.ts +0 -294
- package/es/collection-manager/interfaces/subTable.d.ts +0 -172
- package/src/collection-manager/interfaces/linkTo.ts +0 -120
- package/src/collection-manager/interfaces/o2o.tsx +0 -561
- package/src/collection-manager/interfaces/subTable.ts +0 -218
- package/src/settings-center/PluginManagerPage.tsx +0 -162
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
FlowModelRenderer,
|
|
12
|
+
resolveRunJSObjectValues,
|
|
13
|
+
tExpr,
|
|
14
|
+
type FlowModelContext,
|
|
15
|
+
useFlowEngine,
|
|
16
|
+
useFlowSettingsContext,
|
|
17
|
+
} from '@nocobase/flow-engine';
|
|
18
|
+
import React, { useEffect } from 'react';
|
|
19
|
+
import { CollectionActionModel } from '../../base/CollectionActionModel';
|
|
20
|
+
import { RecordActionModel } from '../../base/RecordActionModel';
|
|
21
|
+
import { AssignFormModel } from './AssignFormModel';
|
|
22
|
+
|
|
23
|
+
export const ASSIGN_FIELD_VALUES_STEP_KEY = 'assignFieldValues';
|
|
24
|
+
|
|
25
|
+
type AssignedValues = Record<string, unknown>;
|
|
26
|
+
|
|
27
|
+
type AssignFieldValuesCollection = {
|
|
28
|
+
dataSourceKey?: string;
|
|
29
|
+
name?: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type AssignFieldValuesContext = FlowModelContext & {
|
|
33
|
+
collection?: AssignFieldValuesCollection;
|
|
34
|
+
flowSettingsEnabled?: boolean;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type AssignFieldValuesModel = {
|
|
38
|
+
uid: string;
|
|
39
|
+
assignFormUid?: string;
|
|
40
|
+
context?: AssignFieldValuesContext;
|
|
41
|
+
subModels?: {
|
|
42
|
+
assignForm?: AssignFormModel;
|
|
43
|
+
};
|
|
44
|
+
getStepParams?: (flowKey: string, stepKey: string) => { assignedValues?: AssignedValues } | undefined;
|
|
45
|
+
setStepParams?: (flowKey: string, stepKey: string, params: { assignedValues: AssignedValues }) => void;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
type AssignFieldValuesStepOptions = {
|
|
49
|
+
settingsFlowKey: string;
|
|
50
|
+
title?: string;
|
|
51
|
+
tipComponent?: React.ComponentType;
|
|
52
|
+
validateBeforeSave?: boolean;
|
|
53
|
+
clearRecordContext?: boolean;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function getContextCollection(ctx: AssignFieldValuesContext | undefined): AssignFieldValuesCollection | undefined {
|
|
57
|
+
const collection = ctx?.collection;
|
|
58
|
+
return collection && typeof collection === 'object' ? collection : undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function getResourceInit(ctx: AssignFieldValuesContext): { dataSourceKey: string; collectionName: string } | undefined {
|
|
62
|
+
const collection = getContextCollection(ctx);
|
|
63
|
+
const dsKey = collection?.dataSourceKey;
|
|
64
|
+
const collName = collection?.name;
|
|
65
|
+
return dsKey && collName ? { dataSourceKey: dsKey, collectionName: collName } : undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function resolveInitFromFlowSettings(
|
|
69
|
+
blockModel: unknown,
|
|
70
|
+
actionContext: AssignFieldValuesContext | undefined,
|
|
71
|
+
): { dataSourceKey: string; collectionName: string } | undefined {
|
|
72
|
+
const maybeBlockCollection = (blockModel as { collection?: { dataSourceKey?: string; name?: string } } | undefined)
|
|
73
|
+
?.collection;
|
|
74
|
+
const collection = maybeBlockCollection || getContextCollection(actionContext);
|
|
75
|
+
const dsKey = collection?.dataSourceKey;
|
|
76
|
+
const collName = collection?.name;
|
|
77
|
+
return dsKey && collName ? { dataSourceKey: dsKey, collectionName: collName } : undefined;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isValidResourceInit(init: unknown): init is {
|
|
81
|
+
dataSourceKey: string;
|
|
82
|
+
collectionName: string;
|
|
83
|
+
} {
|
|
84
|
+
if (!init || typeof init !== 'object') return false;
|
|
85
|
+
const obj = init as { dataSourceKey?: unknown; collectionName?: unknown };
|
|
86
|
+
return (
|
|
87
|
+
typeof obj.dataSourceKey === 'string' &&
|
|
88
|
+
!!obj.dataSourceKey &&
|
|
89
|
+
typeof obj.collectionName === 'string' &&
|
|
90
|
+
!!obj.collectionName
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
type LocalCacheContext = {
|
|
95
|
+
_observableCache?: Record<string, unknown>;
|
|
96
|
+
_cache?: Record<string, unknown>;
|
|
97
|
+
_pending?: Record<string, unknown>;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
function toLocalCacheContext(context: unknown): LocalCacheContext | undefined {
|
|
101
|
+
return context && typeof context === 'object' ? (context as LocalCacheContext) : undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function clearOwnContextCache(context: unknown, key: string) {
|
|
105
|
+
const localContext = toLocalCacheContext(context);
|
|
106
|
+
if (!localContext) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
delete localContext._observableCache?.[key];
|
|
110
|
+
delete localContext._cache?.[key];
|
|
111
|
+
delete localContext._pending?.[key];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function clearResourceContextCache(model: { context?: unknown } | undefined) {
|
|
115
|
+
clearOwnContextCache(model?.context, 'dataSource');
|
|
116
|
+
clearOwnContextCache(model?.context, 'collection');
|
|
117
|
+
clearOwnContextCache(model?.context, 'resource');
|
|
118
|
+
clearOwnContextCache(model?.context, 'association');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function resolveAssignFormModel(ctx: {
|
|
122
|
+
model: AssignFieldValuesModel;
|
|
123
|
+
engine: {
|
|
124
|
+
getModel?: (uid: string, fromRoot?: boolean) => AssignFormModel | undefined;
|
|
125
|
+
findModelByParentId?: (parentId: string, subKey: string) => AssignFormModel | undefined | null;
|
|
126
|
+
};
|
|
127
|
+
}) {
|
|
128
|
+
if (ctx.model.assignFormUid) {
|
|
129
|
+
const form = ctx.engine.getModel?.(ctx.model.assignFormUid, true);
|
|
130
|
+
if (form) {
|
|
131
|
+
return form;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const localForm = ctx.model.subModels?.assignForm;
|
|
136
|
+
if (localForm) {
|
|
137
|
+
return localForm;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return ctx.engine.findModelByParentId?.(ctx.model.uid, 'assignForm') || undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function createAssignFormSubModelOptions(ctx: AssignFieldValuesContext) {
|
|
144
|
+
return {
|
|
145
|
+
async: true,
|
|
146
|
+
use: 'AssignFormModel',
|
|
147
|
+
stepParams: { resourceSettings: { init: getResourceInit(ctx) } },
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function getAssignFieldValuesDefaultParams(
|
|
152
|
+
ctx: {
|
|
153
|
+
model: Pick<AssignFieldValuesModel, 'getStepParams'>;
|
|
154
|
+
},
|
|
155
|
+
settingsFlowKey: string,
|
|
156
|
+
): { assignedValues: AssignedValues } {
|
|
157
|
+
const step = ctx.model.getStepParams?.(settingsFlowKey, ASSIGN_FIELD_VALUES_STEP_KEY) || {};
|
|
158
|
+
return { assignedValues: step?.assignedValues || {} };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export async function resolveAssignFieldValues(
|
|
162
|
+
ctx: {
|
|
163
|
+
message?: { error?: (message: string) => void };
|
|
164
|
+
t?: (message: string) => string;
|
|
165
|
+
},
|
|
166
|
+
rawAssignedValues: unknown,
|
|
167
|
+
logName = 'AssignFieldValues',
|
|
168
|
+
): Promise<AssignedValues | null> {
|
|
169
|
+
try {
|
|
170
|
+
return await resolveRunJSObjectValues(ctx, rawAssignedValues);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error(`[${logName}] RunJS execution failed`, error);
|
|
173
|
+
ctx.message?.error?.(ctx.t?.('RunJS execution failed') || 'RunJS execution failed');
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function mergeAssignFieldValues<T extends Record<string, unknown>>(
|
|
179
|
+
values: T,
|
|
180
|
+
assignedValues?: AssignedValues | null,
|
|
181
|
+
): T {
|
|
182
|
+
if (!assignedValues || typeof assignedValues !== 'object' || !Object.keys(assignedValues).length) {
|
|
183
|
+
return values;
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
...values,
|
|
187
|
+
...assignedValues,
|
|
188
|
+
} as T;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function AssignFieldsEditor(props: { settingsFlowKey: string; clearRecordContext?: boolean }) {
|
|
192
|
+
const { model, blockModel } = useFlowSettingsContext();
|
|
193
|
+
const action = model as AssignFieldValuesModel;
|
|
194
|
+
const engine = useFlowEngine();
|
|
195
|
+
const [formModel, setFormModel] = React.useState<AssignFormModel | null>(null);
|
|
196
|
+
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
let cancelled = false;
|
|
199
|
+
const loadAssignForm = async () => {
|
|
200
|
+
const init = resolveInitFromFlowSettings(blockModel, action?.context);
|
|
201
|
+
const loaded = (await engine.loadOrCreateModel(
|
|
202
|
+
init
|
|
203
|
+
? {
|
|
204
|
+
parentId: action.uid,
|
|
205
|
+
subKey: 'assignForm',
|
|
206
|
+
use: 'AssignFormModel',
|
|
207
|
+
stepParams: { resourceSettings: { init } },
|
|
208
|
+
}
|
|
209
|
+
: {
|
|
210
|
+
parentId: action.uid,
|
|
211
|
+
subKey: 'assignForm',
|
|
212
|
+
use: 'AssignFormModel',
|
|
213
|
+
},
|
|
214
|
+
{ skipSave: !model.context.flowSettingsEnabled },
|
|
215
|
+
)) as AssignFormModel;
|
|
216
|
+
if (cancelled) return;
|
|
217
|
+
|
|
218
|
+
if (isValidResourceInit(init)) {
|
|
219
|
+
const existingInit = loaded.getStepParams?.('resourceSettings', 'init');
|
|
220
|
+
// Ensure `resourceSettings.init` is available before first render to avoid cached undefined `collection`
|
|
221
|
+
if (
|
|
222
|
+
!isValidResourceInit(existingInit) ||
|
|
223
|
+
existingInit.dataSourceKey !== init.dataSourceKey ||
|
|
224
|
+
existingInit.collectionName !== init.collectionName
|
|
225
|
+
) {
|
|
226
|
+
loaded.setStepParams?.('resourceSettings', 'init', init);
|
|
227
|
+
}
|
|
228
|
+
clearResourceContextCache(loaded);
|
|
229
|
+
clearResourceContextCache(loaded.subModels?.grid);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const prev = action.getStepParams?.(props.settingsFlowKey, ASSIGN_FIELD_VALUES_STEP_KEY) || {};
|
|
233
|
+
loaded.setInitialAssignedValues(prev?.assignedValues || {});
|
|
234
|
+
|
|
235
|
+
const isBulkCollectionAction = model instanceof CollectionActionModel && !(model instanceof RecordActionModel);
|
|
236
|
+
const isBulk = props.clearRecordContext || isBulkCollectionAction;
|
|
237
|
+
if (isBulk && loaded.context?.defineProperty) {
|
|
238
|
+
loaded.context.defineProperty('record', { get: () => undefined, cache: false });
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
setFormModel(loaded);
|
|
242
|
+
action.assignFormUid = loaded?.uid || action.assignFormUid;
|
|
243
|
+
};
|
|
244
|
+
loadAssignForm();
|
|
245
|
+
return () => {
|
|
246
|
+
cancelled = true;
|
|
247
|
+
};
|
|
248
|
+
}, [
|
|
249
|
+
action,
|
|
250
|
+
blockModel,
|
|
251
|
+
engine,
|
|
252
|
+
model,
|
|
253
|
+
model.context.flowSettingsEnabled,
|
|
254
|
+
props.clearRecordContext,
|
|
255
|
+
props.settingsFlowKey,
|
|
256
|
+
]);
|
|
257
|
+
|
|
258
|
+
return formModel ? <FlowModelRenderer model={formModel} showFlowSettings={false} /> : null;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function createAssignFieldValuesStep(options: AssignFieldValuesStepOptions) {
|
|
262
|
+
return {
|
|
263
|
+
title: options.title || tExpr('Assign field values'),
|
|
264
|
+
uiSchema() {
|
|
265
|
+
return {
|
|
266
|
+
tip: options.tipComponent
|
|
267
|
+
? {
|
|
268
|
+
'x-decorator': 'FormItem',
|
|
269
|
+
'x-component': options.tipComponent,
|
|
270
|
+
}
|
|
271
|
+
: undefined,
|
|
272
|
+
editor: {
|
|
273
|
+
'x-decorator': 'FormItem',
|
|
274
|
+
'x-component': () => (
|
|
275
|
+
<AssignFieldsEditor
|
|
276
|
+
settingsFlowKey={options.settingsFlowKey}
|
|
277
|
+
clearRecordContext={options.clearRecordContext}
|
|
278
|
+
/>
|
|
279
|
+
),
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
},
|
|
283
|
+
async beforeParamsSave(
|
|
284
|
+
ctx: {
|
|
285
|
+
model: AssignFieldValuesModel;
|
|
286
|
+
engine: {
|
|
287
|
+
getModel?: (uid: string, fromRoot?: boolean) => AssignFormModel | undefined;
|
|
288
|
+
findModelByParentId?: (parentId: string, subKey: string) => AssignFormModel | undefined | null;
|
|
289
|
+
};
|
|
290
|
+
},
|
|
291
|
+
params?: { assignedValues?: AssignedValues },
|
|
292
|
+
previousParams?: { assignedValues?: AssignedValues },
|
|
293
|
+
) {
|
|
294
|
+
const form = resolveAssignFormModel(ctx);
|
|
295
|
+
if (!form) {
|
|
296
|
+
const assignedValues = params?.assignedValues || previousParams?.assignedValues || {};
|
|
297
|
+
ctx.model.setStepParams?.(options.settingsFlowKey, ASSIGN_FIELD_VALUES_STEP_KEY, { assignedValues });
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (options.validateBeforeSave) {
|
|
301
|
+
await form.form?.validateFields?.();
|
|
302
|
+
}
|
|
303
|
+
const assignedValues = form.getAssignedValues?.() || {};
|
|
304
|
+
ctx.model.setStepParams?.(options.settingsFlowKey, ASSIGN_FIELD_VALUES_STEP_KEY, { assignedValues });
|
|
305
|
+
},
|
|
306
|
+
handler() {},
|
|
307
|
+
};
|
|
308
|
+
}
|
|
@@ -51,7 +51,7 @@ const getTargetFilterableFields = (field: any, collection?: Collection, model?:
|
|
|
51
51
|
return (targetCollection.getFields() || []).filter((childField: any) => childField?.filterable);
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
const MAX_ASSOCIATION_DEPTH =
|
|
54
|
+
const MAX_ASSOCIATION_DEPTH = 2;
|
|
55
55
|
|
|
56
56
|
const normalizeAssociationDefaultFilterValue = (value: any, fieldModel: any) => {
|
|
57
57
|
const collectionField = fieldModel?.context?.collectionField;
|
package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts
CHANGED
|
@@ -136,9 +136,13 @@ describe('FilterFormItemModel defineChildren association fields', () => {
|
|
|
136
136
|
);
|
|
137
137
|
const managerGroups = await managerAssociation.children();
|
|
138
138
|
const managerFieldsGroup = managerGroups.find((group: any) => group.key === 'department.manager-fields');
|
|
139
|
+
const managerAssociationGroup = managerGroups.find(
|
|
140
|
+
(group: any) => group.key === 'department.manager-relation-fields',
|
|
141
|
+
);
|
|
139
142
|
|
|
140
143
|
const managerFieldKeys = (managerFieldsGroup?.children || []).map((item: any) => item.key);
|
|
141
144
|
expect(managerFieldKeys).toContain('department.manager.name');
|
|
145
|
+
expect(managerAssociationGroup).toBeUndefined();
|
|
142
146
|
|
|
143
147
|
const targetItem = managerFieldsGroup?.children?.find((item: any) => item.key === 'department.manager.name');
|
|
144
148
|
const createOptions = await targetItem.createModelOptions();
|
|
@@ -200,7 +204,8 @@ describe('FilterFormItemModel defineChildren association fields', () => {
|
|
|
200
204
|
});
|
|
201
205
|
|
|
202
206
|
const ds = engine.dataSourceManager.getDataSource('main');
|
|
203
|
-
ds
|
|
207
|
+
expect(ds).toBeTruthy();
|
|
208
|
+
ds?.addCollection({
|
|
204
209
|
name: 'users',
|
|
205
210
|
filterTargetKey: 'id',
|
|
206
211
|
fields: [{ name: 'id', type: 'integer', interface: 'number', filterable: { operators: [] } }],
|
|
@@ -40,7 +40,20 @@ export const connectFields = defineAction({
|
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
// 构建级联选项数据结构
|
|
43
|
-
const
|
|
43
|
+
const MAX_ASSOCIATION_FIELD_DEPTH = 2;
|
|
44
|
+
|
|
45
|
+
const isAssociationField = (field: any) => {
|
|
46
|
+
return Boolean(field?.target || field?.targetCollection);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const buildCascaderOptions = (
|
|
50
|
+
ctx,
|
|
51
|
+
fields: any[],
|
|
52
|
+
prefix = '',
|
|
53
|
+
selectedPaths: string[] = [],
|
|
54
|
+
labelPrefix = '',
|
|
55
|
+
associationDepth = 0,
|
|
56
|
+
) => {
|
|
44
57
|
const selectedPathsArray = selectedPaths.filter(Boolean);
|
|
45
58
|
|
|
46
59
|
return fields
|
|
@@ -48,7 +61,13 @@ const buildCascaderOptions = (ctx, fields: any[], prefix = '', selectedPaths: st
|
|
|
48
61
|
const currentPath = prefix ? `${prefix}.${field.name}` : field.name;
|
|
49
62
|
const label = field.title || field.name;
|
|
50
63
|
const fullLabel = labelPrefix ? `${labelPrefix} / ${label}` : label;
|
|
51
|
-
const
|
|
64
|
+
const isAssociation = isAssociationField(field);
|
|
65
|
+
const nextAssociationDepth = associationDepth + (isAssociation ? 1 : 0);
|
|
66
|
+
if (isAssociation && nextAssociationDepth > MAX_ASSOCIATION_FIELD_DEPTH) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const isLeaf = !isAssociation;
|
|
52
71
|
|
|
53
72
|
const option: any = {
|
|
54
73
|
label,
|
|
@@ -59,6 +78,7 @@ const buildCascaderOptions = (ctx, fields: any[], prefix = '', selectedPaths: st
|
|
|
59
78
|
field,
|
|
60
79
|
fullPath: currentPath,
|
|
61
80
|
fullLabel,
|
|
81
|
+
associationDepth: nextAssociationDepth,
|
|
62
82
|
},
|
|
63
83
|
};
|
|
64
84
|
|
|
@@ -68,18 +88,33 @@ const buildCascaderOptions = (ctx, fields: any[], prefix = '', selectedPaths: st
|
|
|
68
88
|
|
|
69
89
|
if (shouldLoadChildren) {
|
|
70
90
|
if (field.filterable?.children?.length) {
|
|
71
|
-
option.children = buildCascaderOptions(
|
|
91
|
+
option.children = buildCascaderOptions(
|
|
92
|
+
ctx,
|
|
93
|
+
field.filterable.children,
|
|
94
|
+
currentPath,
|
|
95
|
+
selectedPaths,
|
|
96
|
+
fullLabel,
|
|
97
|
+
nextAssociationDepth,
|
|
98
|
+
);
|
|
72
99
|
} else {
|
|
73
100
|
const targetCollection = field.targetCollection;
|
|
74
101
|
if (targetCollection) {
|
|
75
102
|
const targetFields = targetCollection.getFields?.() || [];
|
|
76
|
-
option.children = buildCascaderOptions(
|
|
103
|
+
option.children = buildCascaderOptions(
|
|
104
|
+
ctx,
|
|
105
|
+
targetFields,
|
|
106
|
+
currentPath,
|
|
107
|
+
selectedPaths,
|
|
108
|
+
fullLabel,
|
|
109
|
+
nextAssociationDepth,
|
|
110
|
+
);
|
|
77
111
|
}
|
|
78
112
|
}
|
|
79
113
|
}
|
|
80
114
|
|
|
81
115
|
return option;
|
|
82
116
|
})
|
|
117
|
+
.filter(Boolean)
|
|
83
118
|
.sort((a, b) => {
|
|
84
119
|
// isLeaf 为 true 的节点排在前面
|
|
85
120
|
if (a.isLeaf && !b.isLeaf) return -1;
|
|
@@ -259,7 +294,7 @@ function ConnectFields(
|
|
|
259
294
|
<li>{ctx.t('Available "target blocks" are all data blocks on the current page')}</li>
|
|
260
295
|
<li>
|
|
261
296
|
{ctx.t(
|
|
262
|
-
'Support filtering multiple blocks simultaneously, support
|
|
297
|
+
'Support filtering multiple blocks simultaneously, support selection of relationship fields up to two levels (e.g.: User/Department/Name)',
|
|
263
298
|
)}
|
|
264
299
|
</li>
|
|
265
300
|
</ul>
|
|
@@ -469,7 +504,14 @@ function CascaderWrapper(
|
|
|
469
504
|
return;
|
|
470
505
|
}
|
|
471
506
|
|
|
472
|
-
target.children = buildCascaderOptions(
|
|
507
|
+
target.children = buildCascaderOptions(
|
|
508
|
+
ctx,
|
|
509
|
+
childFields,
|
|
510
|
+
fullPath,
|
|
511
|
+
[],
|
|
512
|
+
meta.fullLabel || target.label,
|
|
513
|
+
meta.associationDepth || 0,
|
|
514
|
+
);
|
|
473
515
|
setOptions((prev) => [...prev]);
|
|
474
516
|
};
|
|
475
517
|
|
|
@@ -12,4 +12,18 @@ import { FormActionModel } from './FormActionModel';
|
|
|
12
12
|
|
|
13
13
|
export class FormActionGroupModel extends ActionGroupModel {
|
|
14
14
|
static baseClass = FormActionModel;
|
|
15
|
+
|
|
16
|
+
static async defineChildren(ctx) {
|
|
17
|
+
const allowedModelNames = ctx.allowedFormActionModelNames;
|
|
18
|
+
|
|
19
|
+
if (!Array.isArray(allowedModelNames) || allowedModelNames.length === 0) {
|
|
20
|
+
return super.defineChildren(ctx);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
await Promise.all(allowedModelNames.map((name) => ctx.engine?.getModelClassAsync?.(name)));
|
|
24
|
+
|
|
25
|
+
const items = await super.defineChildren(ctx);
|
|
26
|
+
const allowedSet = new Set(allowedModelNames);
|
|
27
|
+
return items.filter((item) => allowedSet.has(item.useModel || item.key));
|
|
28
|
+
}
|
|
15
29
|
}
|
|
@@ -7,15 +7,27 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { tExpr } from '@nocobase/flow-engine';
|
|
10
|
+
import { DefaultStructure, FlowExitAllException, tExpr } from '@nocobase/flow-engine';
|
|
11
11
|
import { ButtonProps } from 'antd';
|
|
12
12
|
import { AxiosRequestConfig } from 'axios';
|
|
13
13
|
import { ActionModel } from '../../base/ActionModelCore';
|
|
14
|
+
import { AssignFormModel } from '../assign-form/AssignFormModel';
|
|
15
|
+
import {
|
|
16
|
+
createAssignFieldValuesStep,
|
|
17
|
+
createAssignFormSubModelOptions,
|
|
18
|
+
getAssignFieldValuesDefaultParams,
|
|
19
|
+
} from '../assign-form/assignFieldValuesFlow';
|
|
14
20
|
import { shouldSkipSubmitValidation, validateSubmitForm } from './submitValues';
|
|
15
21
|
|
|
16
|
-
export class FormActionModel extends ActionModel {}
|
|
22
|
+
export class FormActionModel<T extends DefaultStructure = DefaultStructure> extends ActionModel<T> {}
|
|
23
|
+
|
|
24
|
+
export class FormSubmitActionModel extends FormActionModel<{
|
|
25
|
+
subModels: {
|
|
26
|
+
assignForm: AssignFormModel;
|
|
27
|
+
};
|
|
28
|
+
}> {
|
|
29
|
+
assignFormUid?: string;
|
|
17
30
|
|
|
18
|
-
export class FormSubmitActionModel extends FormActionModel {
|
|
19
31
|
defaultProps: ButtonProps = {
|
|
20
32
|
title: tExpr('Submit'),
|
|
21
33
|
type: 'primary',
|
|
@@ -35,6 +47,11 @@ export class FormSubmitActionModel extends FormActionModel {
|
|
|
35
47
|
|
|
36
48
|
FormSubmitActionModel.define({
|
|
37
49
|
label: tExpr('Submit'),
|
|
50
|
+
createModelOptions: (ctx) => ({
|
|
51
|
+
subModels: {
|
|
52
|
+
assignForm: createAssignFormSubModelOptions(ctx),
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
38
55
|
});
|
|
39
56
|
|
|
40
57
|
FormSubmitActionModel.registerFlow({
|
|
@@ -82,7 +99,14 @@ FormSubmitActionModel.registerFlow({
|
|
|
82
99
|
},
|
|
83
100
|
handler() {},
|
|
84
101
|
},
|
|
102
|
+
assignFieldValues: createAssignFieldValuesStep({
|
|
103
|
+
settingsFlowKey: 'submitSettings',
|
|
104
|
+
title: tExpr('Assign field values'),
|
|
105
|
+
}),
|
|
85
106
|
saveResource: {
|
|
107
|
+
async defaultParams(ctx) {
|
|
108
|
+
return getAssignFieldValuesDefaultParams(ctx, 'submitSettings');
|
|
109
|
+
},
|
|
86
110
|
async handler(ctx, params) {
|
|
87
111
|
if (!ctx?.resource) {
|
|
88
112
|
throw new Error('Resource is not initialized');
|
|
@@ -96,6 +120,9 @@ FormSubmitActionModel.registerFlow({
|
|
|
96
120
|
await submitHandler(ctx, params);
|
|
97
121
|
} catch (error) {
|
|
98
122
|
ctx.model.setProps('loading', false);
|
|
123
|
+
if (error instanceof FlowExitAllException) {
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
99
126
|
// 显示保存失败提示
|
|
100
127
|
ctx.message.error(ctx.t('Save failed'));
|
|
101
128
|
console.error('Form submission error:', error);
|
|
@@ -22,6 +22,8 @@ import { FieldModel } from '../../base/FieldModel';
|
|
|
22
22
|
import { rebuildFieldSubModel } from '../../../internal/utils/rebuildFieldSubModel';
|
|
23
23
|
import { useJsonTemplateResolver } from '../../../utils/useJsonTemplateResolver';
|
|
24
24
|
|
|
25
|
+
const MAX_FORM_ASSOCIATION_FIELD_DEPTH = 2;
|
|
26
|
+
|
|
25
27
|
function mergeArrays(a, b) {
|
|
26
28
|
if (!b) {
|
|
27
29
|
return a;
|
|
@@ -84,10 +86,17 @@ const AssociationItem = (props) => {
|
|
|
84
86
|
export class FormAssociationItemModel extends DisplayItemModel {
|
|
85
87
|
static defineChildren(ctx: FlowModelContext) {
|
|
86
88
|
const collection = ctx.collection as Collection;
|
|
89
|
+
const associationDepth = ctx.prefixFieldPath ? ctx.prefixFieldPath.split('.').filter(Boolean).length : 0;
|
|
87
90
|
|
|
88
91
|
return collection
|
|
89
92
|
.getFields()
|
|
90
93
|
.map((field) => {
|
|
94
|
+
if (
|
|
95
|
+
associationDepth >= MAX_FORM_ASSOCIATION_FIELD_DEPTH &&
|
|
96
|
+
(field.isAssociationField?.() || field.target || field.targetCollection)
|
|
97
|
+
) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
91
100
|
const binding = this.getDefaultBindingByField(ctx, field, { fallbackToTargetTitleField: true });
|
|
92
101
|
if (!binding) return null;
|
|
93
102
|
const fieldModel = binding.modelName;
|
|
@@ -42,12 +42,21 @@ const interfacesOfUnsupportedDefaultValue = [
|
|
|
42
42
|
'formula',
|
|
43
43
|
];
|
|
44
44
|
|
|
45
|
+
const MAX_FORM_ASSOCIATION_FIELD_DEPTH = 2;
|
|
46
|
+
|
|
45
47
|
export class FormItemModel<T extends DefaultStructure = DefaultStructure> extends EditableItemModel<T> {
|
|
46
48
|
static defineChildren(ctx: FlowModelContext) {
|
|
47
49
|
const collection = ctx.collection as Collection;
|
|
50
|
+
const associationDepth = ctx.prefixFieldPath ? ctx.prefixFieldPath.split('.').filter(Boolean).length : 0;
|
|
48
51
|
return collection
|
|
49
52
|
.getFields()
|
|
50
53
|
.map((field) => {
|
|
54
|
+
if (
|
|
55
|
+
associationDepth >= MAX_FORM_ASSOCIATION_FIELD_DEPTH &&
|
|
56
|
+
(field.isAssociationField?.() || field.target || field.targetCollection)
|
|
57
|
+
) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
51
60
|
const binding = this.getDefaultBindingByField(ctx, field);
|
|
52
61
|
if (!binding) {
|
|
53
62
|
return;
|
|
@@ -138,6 +147,10 @@ export class FormItemModel<T extends DefaultStructure = DefaultStructure> extend
|
|
|
138
147
|
});
|
|
139
148
|
}
|
|
140
149
|
}
|
|
150
|
+
fork.context.defineProperty('fieldPathArray', {
|
|
151
|
+
get: () => this.context.fieldPathArray,
|
|
152
|
+
cache: false,
|
|
153
|
+
});
|
|
141
154
|
if (isHiddenReservedValuePreview) {
|
|
142
155
|
fork.setProps({ hidden: false });
|
|
143
156
|
}
|
|
@@ -151,7 +164,10 @@ export class FormItemModel<T extends DefaultStructure = DefaultStructure> extend
|
|
|
151
164
|
: { hidden, ...mergedPropsWithoutInitial };
|
|
152
165
|
const fieldPath = buildDynamicNamePath(this.props.name, idx);
|
|
153
166
|
this.context.defineProperty('fieldPathArray', {
|
|
154
|
-
|
|
167
|
+
get: () => {
|
|
168
|
+
return [...parentFieldPathArray, ..._.castArray(fieldPath)];
|
|
169
|
+
},
|
|
170
|
+
cache: false,
|
|
155
171
|
});
|
|
156
172
|
const record = this.context.item?.value || this.context.record;
|
|
157
173
|
const content = (
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { FlowEngine } from '@nocobase/flow-engine';
|
|
11
|
+
import { describe, expect, it } from 'vitest';
|
|
12
|
+
import { FormActionGroupModel, FormActionModel } from '../../../..';
|
|
13
|
+
|
|
14
|
+
describe('FormActionGroupModel', () => {
|
|
15
|
+
it('filters addable form actions by allowedFormActionModelNames', async () => {
|
|
16
|
+
class AllowedFormActionModel extends FormActionModel {}
|
|
17
|
+
class HiddenFormActionModel extends FormActionModel {}
|
|
18
|
+
|
|
19
|
+
AllowedFormActionModel.define({
|
|
20
|
+
label: 'Allowed action',
|
|
21
|
+
sort: 10,
|
|
22
|
+
});
|
|
23
|
+
HiddenFormActionModel.define({
|
|
24
|
+
label: 'Hidden action',
|
|
25
|
+
sort: 20,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const engine = new FlowEngine();
|
|
29
|
+
engine.registerModels({
|
|
30
|
+
FormActionModel,
|
|
31
|
+
HiddenFormActionModel,
|
|
32
|
+
});
|
|
33
|
+
engine.registerModelLoaders({
|
|
34
|
+
AllowedFormActionModel: {
|
|
35
|
+
loader: async () => ({ AllowedFormActionModel }),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const items = await FormActionGroupModel.defineChildren({
|
|
40
|
+
engine,
|
|
41
|
+
allowedFormActionModelNames: ['AllowedFormActionModel'],
|
|
42
|
+
} as any);
|
|
43
|
+
|
|
44
|
+
expect(items.map((item: any) => item.useModel)).toEqual(['AllowedFormActionModel']);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -221,6 +221,23 @@ describe('FlowModel core behaviors (collected)', () => {
|
|
|
221
221
|
expect(i1).toEqual({ ping: 1 });
|
|
222
222
|
});
|
|
223
223
|
|
|
224
|
+
it('unchanged stepParams do not trigger a beforeRender rerun', async () => {
|
|
225
|
+
vi.useFakeTimers();
|
|
226
|
+
const spy = vi.fn().mockResolvedValue([]);
|
|
227
|
+
(engine as any).executor.dispatchEvent = spy;
|
|
228
|
+
const model = engine.createModel<FlowModel>({
|
|
229
|
+
use: 'FlowModel',
|
|
230
|
+
uid: 'm-flow-3-noop',
|
|
231
|
+
stepParams: { anyFlow: { anyStep: { x: 1 } } },
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
await model.dispatchEvent('beforeRender', { ping: 1 });
|
|
235
|
+
model.setStepParams('anyFlow', 'anyStep', { x: 1 });
|
|
236
|
+
await vi.advanceTimersByTimeAsync(150);
|
|
237
|
+
|
|
238
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
239
|
+
});
|
|
240
|
+
|
|
224
241
|
it('applyFlow delegates to executor.runFlow', async () => {
|
|
225
242
|
const spyRun = vi.fn().mockResolvedValue('ok');
|
|
226
243
|
(engine as any).executor.runFlow = spyRun;
|