@nocobase/client-v2 2.2.0-alpha.1 → 2.2.0-alpha.11
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/APIClient.d.ts +1 -3
- package/es/BaseApplication.d.ts +3 -0
- package/es/PluginSettingsManager.d.ts +33 -0
- package/es/RouteRepository.d.ts +29 -6
- package/es/RouterManager.d.ts +15 -0
- package/es/authRedirect.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterface.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +1 -0
- package/es/components/category-tabs/SortableCategoryTabs.d.ts +55 -0
- package/es/components/category-tabs/index.d.ts +9 -0
- package/es/components/form/JsonTextArea.d.ts +2 -1
- package/es/components/form/ScanInput/useCodeScanner.d.ts +3 -2
- package/es/components/form/TypedVariableInput.d.ts +31 -5
- package/es/components/form/VariableJsonTextArea.d.ts +19 -0
- package/es/components/form/filter/CollectionFilter.d.ts +2 -0
- package/es/components/form/filter/CollectionFilterItem.d.ts +11 -1
- package/es/components/form/filter/CollectionFilterPanel.d.ts +2 -0
- package/es/components/form/filter/index.d.ts +2 -0
- package/es/components/form/filter/useFilterActionProps.d.ts +2 -0
- package/es/components/form/index.d.ts +1 -0
- package/es/components/index.d.ts +2 -0
- package/es/entry-actions/EntryActionManager.d.ts +24 -0
- package/es/entry-actions/index.d.ts +9 -0
- package/es/flow/actions/afterSuccess.d.ts +8 -1
- package/es/flow/actions/index.d.ts +2 -2
- package/es/flow/actions/linkageRules.d.ts +2 -0
- package/es/flow/admin-shell/BaseLayoutModel.d.ts +6 -0
- package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +7 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +2 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.d.ts +2 -1
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +3 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.d.ts +3 -2
- package/es/flow/admin-shell/admin-layout/AdminLayoutSlotModels.d.ts +5 -0
- package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +2 -1
- package/es/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.d.ts +24 -0
- package/es/flow/admin-shell/admin-layout/index.d.ts +1 -0
- package/es/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.d.ts +6 -0
- package/es/flow/admin-shell/admin-layout/useApplications.d.ts +7 -2
- package/es/flow/components/FieldAssignExactDatePicker.d.ts +1 -0
- package/es/flow/components/FieldAssignRulesEditor.d.ts +3 -1
- package/es/flow/components/FieldAssignValueInput.d.ts +9 -0
- package/es/flow/components/FlowRoute.d.ts +2 -2
- package/es/flow/components/RunJSValueEditor.d.ts +1 -0
- package/es/flow/components/filter/FilterGroup.d.ts +1 -0
- package/es/flow/components/filter/VariableFilterItem.d.ts +6 -1
- package/es/flow/index.d.ts +1 -0
- package/es/flow/internal/registerDeviceTypeContext.d.ts +10 -0
- package/es/flow/models/base/ActionModelCore.d.ts +2 -0
- package/es/flow/models/base/BlockGridModel.d.ts +3 -0
- package/es/flow/models/base/GridModel.d.ts +1 -1
- package/es/flow/models/base/PageModel/PageModel.d.ts +12 -0
- package/es/flow/models/base/PageModel/PageModelTabBar.d.ts +22 -0
- package/es/flow/models/base/PageModel/PageTabModel.d.ts +12 -0
- package/es/flow/models/blocks/filter-form/FilterFormBlockModel.d.ts +5 -0
- package/es/flow/models/blocks/form/FormBlockModel.d.ts +4 -0
- package/es/flow/models/blocks/form/QuickEditFormModel.d.ts +17 -2
- package/es/flow/models/blocks/form/submitHandler.d.ts +1 -1
- package/es/flow/models/blocks/form/value-runtime/rules.d.ts +21 -0
- package/es/flow/models/blocks/form/value-runtime/runtime.d.ts +30 -0
- package/es/flow/models/blocks/form/value-runtime/types.d.ts +2 -2
- package/es/flow/models/blocks/js-block/JSBlock.d.ts +1 -0
- package/es/flow/models/blocks/table/TableActionsColumnModel.d.ts +1 -0
- package/es/flow/models/blocks/table/TableBlockModel.d.ts +1 -0
- package/es/flow/models/blocks/table/TableColumnModel.d.ts +1 -0
- package/es/flow/models/blocks/table/dragSort/dragSortHooks.d.ts +1 -1
- package/es/flow/models/blocks/table/dragSort/dragSortSettings.d.ts +2 -1
- package/es/flow/models/blocks/table/dragSort/dragSortUtils.d.ts +6 -4
- package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +2 -0
- package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.d.ts +6 -0
- package/es/flow/models/fields/DateTimeFieldModel/dateLimit.d.ts +15 -7
- package/es/flow/resolveViewParamsToViewList.d.ts +1 -1
- package/es/flow/routeTransientInputArgs.d.ts +14 -0
- package/es/flow/utils/dataScopeRowSnapshot.d.ts +59 -0
- package/es/flow/utils/dateTimeDisplayProps.d.ts +49 -0
- package/es/flow/utils/formValueDeps.d.ts +32 -0
- package/es/flow-compat/FieldValidation.d.ts +2 -1
- package/es/flow-compat/fieldValidationConstants.d.ts +1 -1
- package/es/flow-compat/routeTypes.d.ts +1 -0
- package/es/index.d.ts +8 -1
- package/es/index.mjs +367 -181
- package/es/utils/getRouteRuntimeVersion.d.ts +23 -0
- package/es/utils/index.d.ts +1 -0
- package/es/utils/markdownSanitize.d.ts +11 -0
- package/lib/index.js +367 -181
- package/lib/locale/languageCodes.js +3 -1
- package/package.json +9 -7
- package/src/APIClient.ts +1 -10
- package/src/Application.tsx +4 -0
- package/src/BaseApplication.tsx +13 -6
- package/src/PluginSettingsManager.ts +53 -0
- package/src/RouteRepository.ts +151 -24
- package/src/RouterManager.tsx +142 -1
- package/src/__tests__/PluginSettingsManager.test.ts +13 -0
- package/src/__tests__/RouteRepository.test.ts +239 -0
- package/src/__tests__/RouterManager.test.ts +125 -0
- package/src/__tests__/app.test.tsx +73 -0
- package/src/__tests__/authRedirect.test.ts +17 -0
- package/src/__tests__/browserChecker.test.ts +61 -0
- package/src/__tests__/exports.test.ts +16 -0
- package/src/__tests__/getRouteRuntimeVersion.test.ts +68 -0
- package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +234 -2
- package/src/__tests__/plugin-manager.test.tsx +44 -2
- package/src/__tests__/settings-center.test.tsx +40 -1
- package/src/authRedirect.ts +38 -0
- package/src/collection-field-interface/CollectionFieldInterface.ts +1 -0
- package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +1 -0
- package/src/collection-manager/field-configure.ts +1 -1
- package/src/collection-manager/field-validation.ts +1 -1
- package/src/collection-manager/interfaces/id.ts +1 -1
- package/src/collection-manager/interfaces/m2m.tsx +2 -2
- package/src/collection-manager/interfaces/m2o.tsx +2 -2
- package/src/collection-manager/interfaces/nanoid.ts +1 -1
- package/src/collection-manager/interfaces/o2m.tsx +2 -2
- package/src/collection-manager/interfaces/obo.tsx +2 -2
- package/src/collection-manager/interfaces/oho.tsx +2 -2
- package/src/collection-manager/interfaces/properties/index.ts +2 -2
- package/src/collection-manager/interfaces/uuid.ts +1 -1
- package/src/components/AppComponents.tsx +19 -3
- package/src/components/README.md +7 -1
- package/src/components/README.zh-CN.md +6 -1
- package/src/components/category-tabs/SortableCategoryTabs.tsx +210 -0
- package/src/components/category-tabs/index.ts +10 -0
- package/src/components/form/JsonTextArea.tsx +25 -11
- package/src/components/form/ScanInput/CodeScanner.tsx +79 -35
- package/src/components/form/ScanInput/__tests__/CodeScanner.test.tsx +101 -0
- package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +284 -11
- package/src/components/form/ScanInput/useCodeScanner.ts +332 -24
- package/src/components/form/TypedVariableInput.tsx +452 -101
- package/src/components/form/VariableJsonTextArea.tsx +175 -0
- package/src/components/form/__tests__/JsonTextArea.test.tsx +43 -0
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +364 -12
- package/src/components/form/__tests__/VariableJsonTextArea.test.tsx +86 -0
- package/src/components/form/filter/CollectionFilter.tsx +4 -0
- package/src/components/form/filter/CollectionFilterItem.tsx +32 -7
- package/src/components/form/filter/CollectionFilterPanel.tsx +4 -0
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +38 -0
- package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +95 -0
- package/src/components/form/filter/index.ts +2 -0
- package/src/components/form/filter/useFilterActionProps.ts +37 -6
- package/src/components/form/index.tsx +1 -0
- package/src/components/index.ts +2 -0
- package/src/entry-actions/EntryActionManager.ts +76 -0
- package/src/entry-actions/index.ts +10 -0
- package/src/flow/FlowPage.tsx +38 -3
- package/src/flow/__tests__/FlowPage.test.tsx +201 -27
- package/src/flow/__tests__/FlowRoute.test.tsx +1181 -80
- package/src/flow/__tests__/PluginFlowEngine.test.ts +58 -0
- package/src/flow/__tests__/getKey.test.ts +7 -0
- package/src/flow/__tests__/resolveViewParamsToViewList.test.ts +34 -0
- package/src/flow/actions/__tests__/actionLinkageRules.forkProps.test.ts +115 -0
- package/src/flow/actions/__tests__/afterSuccess.test.ts +73 -0
- package/src/flow/actions/__tests__/dataScopeFilter.test.ts +120 -0
- package/src/flow/actions/__tests__/dataScopeFormValueClear.test.ts +1124 -0
- package/src/flow/actions/__tests__/fieldLinkageRules.scopeDepth.test.ts +150 -1
- package/src/flow/actions/__tests__/linkageAssignField.legacy.test.ts +135 -0
- package/src/flow/actions/__tests__/linkageRules.hiddenSync.restore.test.ts +19 -5
- package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +92 -0
- package/src/flow/actions/__tests__/linkageRules.tab.test.ts +171 -0
- package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +7 -3
- package/src/flow/actions/__tests__/openView.defineProps.route.test.tsx +164 -0
- package/src/flow/actions/__tests__/subFormFieldLinkageRules.inputArgs.test.ts +2 -2
- package/src/flow/actions/afterSuccess.tsx +142 -3
- package/src/flow/actions/customVariable.tsx +1 -2
- package/src/flow/actions/dataScopeFilter.ts +20 -1
- package/src/flow/actions/dateTimeFormat.tsx +42 -28
- package/src/flow/actions/index.ts +3 -1
- package/src/flow/actions/linkageRules.tsx +209 -47
- package/src/flow/actions/linkageRulesFormValueRefresh.ts +22 -130
- package/src/flow/actions/linkageRulesRefresh.tsx +2 -6
- package/src/flow/actions/openView.tsx +59 -5
- package/src/flow/actions/runjs.tsx +2 -14
- package/src/flow/actions/validation.tsx +62 -30
- package/src/flow/admin-shell/BaseLayoutModel.tsx +149 -3
- package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +187 -42
- package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +1020 -110
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +74 -14
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.test.tsx +486 -0
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +64 -8
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.ts +5 -3
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +61 -9
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +71 -8
- package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +1 -1
- package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +23 -9
- package/src/flow/admin-shell/admin-layout/AppListRender.tsx +13 -2
- package/src/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.tsx +289 -0
- package/src/flow/admin-shell/admin-layout/HelpLite.tsx +1 -3
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +435 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +99 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +518 -2
- package/src/flow/admin-shell/admin-layout/__tests__/TopbarActionsBar.test.tsx +214 -2
- package/src/flow/admin-shell/admin-layout/index.ts +1 -0
- package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.test.ts +20 -0
- package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.ts +33 -5
- package/src/flow/admin-shell/admin-layout/useApplications.tsx +81 -12
- package/src/flow/common/Markdown/Display.tsx +14 -3
- package/src/flow/common/Markdown/Edit.tsx +19 -7
- package/src/flow/common/Markdown/style.ts +4 -0
- package/src/flow/components/BlockItemCard.tsx +2 -2
- package/src/flow/components/DefaultValue.tsx +1 -2
- package/src/flow/components/DynamicFlowsIcon.tsx +447 -126
- package/src/flow/components/FieldAssignExactDatePicker.tsx +25 -11
- package/src/flow/components/FieldAssignRulesEditor.tsx +128 -21
- package/src/flow/components/FieldAssignValueInput.tsx +91 -20
- package/src/flow/components/FlowRoute.tsx +256 -53
- package/src/flow/components/RunJSValueEditor.tsx +9 -1
- package/src/flow/components/__tests__/DynamicFlowsIcon.test.tsx +148 -2
- package/src/flow/components/__tests__/FieldAssignRulesEditor.test.tsx +508 -4
- package/src/flow/components/__tests__/FieldAssignValueInput.context.test.tsx +216 -0
- package/src/flow/components/__tests__/fieldAssignOptions.test.ts +151 -3
- package/src/flow/components/code-editor/__tests__/useCodeRunner.test.tsx +2 -17
- package/src/flow/components/code-editor/hooks/useCodeRunner.ts +2 -14
- package/src/flow/components/code-editor/runjsDiagnostics.ts +8 -45
- package/src/flow/components/fieldAssignOptions.ts +155 -27
- package/src/flow/components/filter/FilterGroup.tsx +33 -5
- package/src/flow/components/filter/VariableFilterItem.tsx +158 -10
- package/src/flow/components/filter/__tests__/FilterGroup.test.tsx +45 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.leftMetaTree.test.tsx +9 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +70 -1
- package/src/flow/flows/editMarkdownFlow.tsx +1 -1
- package/src/flow/getViewDiffAndUpdateHidden.tsx +1 -0
- package/src/flow/index.ts +4 -1
- package/src/flow/internal/components/Markdown/util.ts +2 -1
- package/src/flow/internal/registerDeviceTypeContext.ts +39 -0
- package/src/flow/internal/utils/operatorSchemaHelper.ts +15 -1
- package/src/flow/models/actions/JSActionModel.tsx +2 -7
- package/src/flow/models/actions/JSCollectionActionModel.tsx +2 -7
- package/src/flow/models/actions/JSItemActionModel.tsx +2 -7
- package/src/flow/models/actions/JSRecordActionModel.tsx +2 -7
- package/src/flow/models/base/ActionModel.tsx +21 -8
- package/src/flow/models/base/ActionModelCore.tsx +11 -4
- package/src/flow/models/base/BlockGridModel.tsx +26 -0
- package/src/flow/models/base/CollectionBlockModel.tsx +6 -2
- package/src/flow/models/base/GridModel.tsx +38 -7
- package/src/flow/models/base/PageModel/PageModel.tsx +387 -50
- package/src/flow/models/base/PageModel/PageModelTabBar.tsx +114 -0
- package/src/flow/models/base/PageModel/PageTabModel.tsx +249 -18
- package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +817 -13
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.module-isolation.test.tsx +130 -0
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.test.tsx +118 -0
- package/src/flow/models/base/PageModel/__tests__/PageTabModel.test.ts +1075 -7
- package/src/flow/models/base/__tests__/ActionModel.test.ts +83 -0
- package/src/flow/models/base/__tests__/ActionModelCore.render.test.tsx +37 -0
- package/src/flow/models/base/__tests__/BlockGridModel.selectSceneActivation.test.ts +124 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.addAppends.test.ts +41 -0
- package/src/flow/models/base/__tests__/GridModel.dragSnapshotContainer.test.ts +239 -1
- package/src/flow/models/base/__tests__/transformRowsToSingleColumn.test.ts +48 -0
- package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +59 -6
- package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +27 -12
- package/src/flow/models/blocks/filter-form/FilterFormJSActionModel.tsx +2 -7
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +36 -0
- package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +143 -4
- package/src/flow/models/blocks/filter-form/fields/FilterFormCustomFieldModel.tsx +1 -1
- package/src/flow/models/blocks/filter-manager/flow-actions/__tests__/customizeFilterRender.test.tsx +56 -1
- package/src/flow/models/blocks/form/EditFormModel.tsx +1 -0
- package/src/flow/models/blocks/form/FormActionModel.tsx +1 -1
- package/src/flow/models/blocks/form/FormBlockModel.tsx +7 -0
- package/src/flow/models/blocks/form/JSFormActionModel.tsx +2 -7
- package/src/flow/models/blocks/form/QuickEditFormModel.tsx +189 -36
- package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +17 -0
- package/src/flow/models/blocks/form/__tests__/QuickEditFormModel.quickEdit.test.ts +350 -2
- package/src/flow/models/blocks/form/__tests__/submitHandler.test.ts +54 -1
- package/src/flow/models/blocks/form/submitHandler.ts +17 -3
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +940 -75
- package/src/flow/models/blocks/form/value-runtime/rules.ts +445 -13
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +348 -13
- package/src/flow/models/blocks/form/value-runtime/types.ts +2 -2
- package/src/flow/models/blocks/js-block/JSBlock.tsx +225 -9
- package/src/flow/models/blocks/js-block/__tests__/JSBlockModel.test.tsx +150 -0
- package/src/flow/models/blocks/table/JSColumnModel.tsx +1 -9
- package/src/flow/models/blocks/table/TableActionsColumnModel.tsx +38 -14
- package/src/flow/models/blocks/table/TableBlockModel.tsx +42 -19
- package/src/flow/models/blocks/table/TableColumnModel.tsx +72 -6
- package/src/flow/models/blocks/table/__tests__/TableActionsColumnModel.test.tsx +111 -1
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.dragSort.test.ts +127 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.mobileSettingsButtons.test.tsx +78 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.quickEditRefresh.test.ts +12 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.rowSelection.test.tsx +1 -0
- package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +243 -1
- package/src/flow/models/blocks/table/dragSort/dragSortHooks.tsx +28 -17
- package/src/flow/models/blocks/table/dragSort/dragSortSettings.ts +13 -6
- package/src/flow/models/blocks/table/dragSort/dragSortUtils.ts +15 -2
- package/src/flow/models/fields/AssociationFieldModel/AssociationFieldModel.tsx +1 -1
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +31 -7
- package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +61 -17
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.tsx +141 -19
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +13 -1
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableColumnModel.rowRecord.test.ts +197 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableFieldModel.reset.test.ts +180 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -4
- package/src/flow/models/fields/AssociationFieldModel/__tests__/AssociationFieldModel.updateAssociation.test.ts +72 -0
- package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +23 -0
- package/src/flow/models/fields/ClickableFieldModel.tsx +5 -0
- package/src/flow/models/fields/DateTimeFieldModel/__tests__/DateTimeNoTzFieldModel.dateLimit.test.tsx +149 -0
- package/src/flow/models/fields/DateTimeFieldModel/dateLimit.ts +149 -113
- package/src/flow/models/fields/DisplayDateTimeFieldModel.tsx +29 -1
- package/src/flow/models/fields/InputFieldModel.tsx +40 -2
- package/src/flow/models/fields/JSEditableFieldModel.tsx +2 -11
- package/src/flow/models/fields/JSFieldModel.tsx +2 -7
- package/src/flow/models/fields/JSItemModel.tsx +2 -14
- package/src/flow/models/fields/SelectFieldModel.tsx +6 -4
- package/src/flow/models/fields/TextareaFieldModel.tsx +72 -3
- package/src/flow/models/fields/VariableFieldFormModel.tsx +3 -3
- package/src/flow/models/fields/__tests__/DisplayDateTimeFieldModel.test.tsx +96 -0
- package/src/flow/models/fields/__tests__/InputFieldModel.test.tsx +117 -1
- package/src/flow/models/fields/__tests__/SelectFieldModel.test.tsx +43 -0
- package/src/flow/models/fields/__tests__/TextareaFieldModel.test.tsx +131 -0
- package/src/flow/models/fields/__tests__/VariableFieldFormModel.test.tsx +51 -0
- package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +20 -10
- package/src/flow/models/fields/mobile-components/MobileSelect.tsx +24 -12
- package/src/flow/models/topbar/TopbarActionModel.tsx +168 -10
- package/src/flow/resolveViewParamsToViewList.tsx +11 -3
- package/src/flow/routeTransientInputArgs.ts +27 -0
- package/src/flow/utils/__tests__/dateTimeFormat.test.ts +300 -0
- package/src/flow/utils/dataScopeFormValueClear.ts +219 -81
- package/src/flow/utils/dataScopeRowSnapshot.ts +616 -0
- package/src/flow/utils/dateTimeDisplayProps.ts +135 -0
- package/src/flow/utils/formValueDeps.ts +170 -0
- package/src/flow-compat/FieldValidation.tsx +122 -60
- package/src/flow-compat/Popover.tsx +43 -4
- package/src/flow-compat/__tests__/Popover.test.tsx +34 -0
- package/src/flow-compat/fieldValidationConstants.ts +1 -1
- package/src/flow-compat/routeTypes.ts +1 -0
- package/src/index.ts +14 -1
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +41 -1
- package/src/locale/languageCodes.ts +3 -1
- package/src/nocobase-buildin-plugin/index.tsx +63 -15
- package/src/settings-center/AdminSettingsLayout.tsx +10 -2
- package/src/settings-center/SystemSettingsPage.tsx +1 -2
- package/src/settings-center/plugin-manager/PluginCard.tsx +2 -2
- package/src/settings-center/plugin-manager/index.tsx +3 -0
- package/src/settings-center/utils.tsx +0 -6
- package/src/utils/getRouteRuntimeVersion.ts +185 -0
- package/src/utils/index.tsx +1 -0
- package/src/utils/markdownSanitize.ts +88 -0
|
@@ -140,4 +140,49 @@ describe('FilterGroup closeIcon', () => {
|
|
|
140
140
|
expect(onChange).toHaveBeenCalledTimes(1);
|
|
141
141
|
expect(value.items[0].items).toHaveLength(1);
|
|
142
142
|
});
|
|
143
|
+
|
|
144
|
+
it('disables close and add actions when the filter group is disabled', () => {
|
|
145
|
+
const value = {
|
|
146
|
+
logic: '$and',
|
|
147
|
+
items: [
|
|
148
|
+
{
|
|
149
|
+
path: 'name',
|
|
150
|
+
operator: 'eq',
|
|
151
|
+
value: 'test',
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
const onRemove = vi.fn();
|
|
156
|
+
const onChange = vi.fn();
|
|
157
|
+
|
|
158
|
+
renderWithProviders(
|
|
159
|
+
<FilterGroup
|
|
160
|
+
value={value}
|
|
161
|
+
FilterItem={DummyFilterItem}
|
|
162
|
+
showBorder
|
|
163
|
+
onRemove={onRemove}
|
|
164
|
+
onChange={onChange}
|
|
165
|
+
disabled
|
|
166
|
+
/>,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const closeButtons = screen
|
|
170
|
+
.getAllByLabelText('icon-close')
|
|
171
|
+
.map((element) => element.closest('button'))
|
|
172
|
+
.filter(Boolean) as HTMLButtonElement[];
|
|
173
|
+
expect(closeButtons).toHaveLength(2);
|
|
174
|
+
expect(closeButtons[0]).toBeDisabled();
|
|
175
|
+
expect(closeButtons[1]).toBeDisabled();
|
|
176
|
+
expect(screen.getByText('Add condition').closest('button')).toBeDisabled();
|
|
177
|
+
expect(screen.getByText('Add condition group').closest('button')).toBeDisabled();
|
|
178
|
+
|
|
179
|
+
fireEvent.click(closeButtons[0]);
|
|
180
|
+
fireEvent.click(closeButtons[1]);
|
|
181
|
+
fireEvent.click(screen.getByText('Add condition').closest('button') as HTMLButtonElement);
|
|
182
|
+
fireEvent.click(screen.getByText('Add condition group').closest('button') as HTMLButtonElement);
|
|
183
|
+
|
|
184
|
+
expect(onRemove).not.toHaveBeenCalled();
|
|
185
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
186
|
+
expect(value.items).toHaveLength(1);
|
|
187
|
+
});
|
|
143
188
|
});
|
|
@@ -193,4 +193,13 @@ describe('VariableFilterItem with leftMetaTree', () => {
|
|
|
193
193
|
fireEvent.click(screen.getByTestId('variable-input'));
|
|
194
194
|
expect(value.path).toBe('title');
|
|
195
195
|
});
|
|
196
|
+
|
|
197
|
+
it('restores the saved left meta so the operator select shows its label on reopen', async () => {
|
|
198
|
+
const value = { path: 'title', operator: '$eq', value: 'x' } as any;
|
|
199
|
+
const model = createModelWithCollection();
|
|
200
|
+
|
|
201
|
+
render(<VariableFilterItem value={value} model={model} rightAsVariable={false} />);
|
|
202
|
+
|
|
203
|
+
expect(await screen.findByText('Equals')).toBeInTheDocument();
|
|
204
|
+
});
|
|
196
205
|
});
|
|
@@ -11,7 +11,7 @@ import React from 'react';
|
|
|
11
11
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
12
12
|
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
13
13
|
import { VariableFilterItem, VariableFilterItemValue } from '../VariableFilterItem';
|
|
14
|
-
import { FlowEngine, FlowModel } from '@nocobase/flow-engine';
|
|
14
|
+
import { FlowEngine, FlowModel, type Converters, type MetaTreeNode } from '@nocobase/flow-engine';
|
|
15
15
|
import { observable } from '@formily/reactive';
|
|
16
16
|
import { createMockFlowApp, TestCollectionFieldInterface } from '../../../__tests__/helpers/mockFlowApp';
|
|
17
17
|
|
|
@@ -158,6 +158,75 @@ describe('VariableFilterItem', () => {
|
|
|
158
158
|
expect(value.value).toBe('abc');
|
|
159
159
|
});
|
|
160
160
|
|
|
161
|
+
it('passes disabled through to the left selector, operator select, and right variable input', async () => {
|
|
162
|
+
const value: VariableFilterItemValue = { path: '', operator: '', value: '' };
|
|
163
|
+
const model = CreateModel();
|
|
164
|
+
|
|
165
|
+
render(<VariableFilterItem value={value} model={model} rightAsVariable disabled />);
|
|
166
|
+
|
|
167
|
+
const leftVariableInputProps = (globalThis as any).__LAST_VARIABLE_INPUT_PROPS__;
|
|
168
|
+
expect(leftVariableInputProps.disabled).toBe(true);
|
|
169
|
+
|
|
170
|
+
fireEvent.click(screen.getAllByTestId('variable-input')[0]);
|
|
171
|
+
|
|
172
|
+
const variableInputs = screen.getAllByTestId('variable-input');
|
|
173
|
+
expect(variableInputs.length).toBeGreaterThanOrEqual(2);
|
|
174
|
+
const rightVariableInputProps = (globalThis as any).__LAST_VARIABLE_INPUT_PROPS__;
|
|
175
|
+
expect(rightVariableInputProps.disabled).toBe(true);
|
|
176
|
+
|
|
177
|
+
const operatorSelect = document.body.querySelector('.ant-select') as HTMLDivElement | null;
|
|
178
|
+
expect(operatorSelect).not.toBeNull();
|
|
179
|
+
expect(operatorSelect).toHaveClass('ant-select-disabled');
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('composes custom right variable converters with constant, null, and core fallbacks', () => {
|
|
183
|
+
const value: VariableFilterItemValue = {
|
|
184
|
+
path: 'name',
|
|
185
|
+
operator: '$eq',
|
|
186
|
+
value: '{{$context.data.id}}',
|
|
187
|
+
};
|
|
188
|
+
const model = CreateModel();
|
|
189
|
+
const rightVariableConverters: Pick<Converters, 'resolvePathFromValue' | 'resolveValueFromPath'> = {
|
|
190
|
+
resolvePathFromValue: (input) => (input === '{{$context.data.id}}' ? ['$context', 'data', 'id'] : undefined),
|
|
191
|
+
resolveValueFromPath: (metaTreeNode) =>
|
|
192
|
+
metaTreeNode.paths?.[0] === '$context' ? `{{${metaTreeNode.paths.join('.')}}}` : undefined,
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
render(
|
|
196
|
+
<VariableFilterItem
|
|
197
|
+
value={value}
|
|
198
|
+
model={model}
|
|
199
|
+
rightAsVariable
|
|
200
|
+
rightVariableConverters={rightVariableConverters}
|
|
201
|
+
/>,
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const variableInputProps = (
|
|
205
|
+
globalThis as {
|
|
206
|
+
__LAST_VARIABLE_INPUT_PROPS__?: {
|
|
207
|
+
converters?: Converters;
|
|
208
|
+
value?: unknown;
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
).__LAST_VARIABLE_INPUT_PROPS__;
|
|
212
|
+
const converters = variableInputProps?.converters;
|
|
213
|
+
const constantNode: MetaTreeNode = { name: 'constant', title: 'Constant', type: 'string', paths: ['constant'] };
|
|
214
|
+
const nullNode: MetaTreeNode = { name: 'null', title: 'Null', type: 'object', paths: ['null'] };
|
|
215
|
+
const workflowNode: MetaTreeNode = {
|
|
216
|
+
name: 'id',
|
|
217
|
+
title: 'ID',
|
|
218
|
+
type: 'number',
|
|
219
|
+
paths: ['$context', 'data', 'id'],
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
expect(variableInputProps?.value).toBe('{{$context.data.id}}');
|
|
223
|
+
expect(converters?.resolvePathFromValue?.('{{$context.data.id}}')).toEqual(['$context', 'data', 'id']);
|
|
224
|
+
expect(converters?.resolvePathFromValue?.('{{ ctx.$context.data.id }}')).toEqual(['$context', 'data', 'id']);
|
|
225
|
+
expect(converters?.resolveValueFromPath?.(constantNode)).toBe('');
|
|
226
|
+
expect(converters?.resolveValueFromPath?.(nullNode)).toBeNull();
|
|
227
|
+
expect(converters?.resolveValueFromPath?.(workflowNode)).toBe('{{$context.data.id}}');
|
|
228
|
+
});
|
|
229
|
+
|
|
161
230
|
it('uses scoped context dataSourceManager when app dataSourceManager has no field interface manager', async () => {
|
|
162
231
|
const value = observable({ path: '', operator: '', value: '' }) as any;
|
|
163
232
|
const model = CreateModel();
|
|
@@ -70,7 +70,7 @@ export const editMarkdownFlow = defineFlow<FlowModel>({
|
|
|
70
70
|
{t('References')}:
|
|
71
71
|
</span>
|
|
72
72
|
<a
|
|
73
|
-
href={`https://
|
|
73
|
+
href={`https://docs.nocobase.com/interface-builder/blocks/other-blocks/markdown`}
|
|
74
74
|
target="_blank"
|
|
75
75
|
rel="noreferrer"
|
|
76
76
|
>
|
package/src/flow/index.ts
CHANGED
|
@@ -22,12 +22,14 @@ import { Markdown } from './common/Markdown/Markdown';
|
|
|
22
22
|
import { LiquidEngine } from './common/Liquid';
|
|
23
23
|
import type { PreviewRunJSResult } from './components/code-editor/runjsDiagnostics';
|
|
24
24
|
import { TextAreaWithContextSelector } from './components/TextAreaWithContextSelector';
|
|
25
|
+
import { registerDeviceTypeContext } from './internal/registerDeviceTypeContext';
|
|
25
26
|
|
|
26
27
|
export class PluginFlowEngine<TApp extends BaseApplication<any> = BaseApplication<any>> extends Plugin<
|
|
27
28
|
PluginOptions<any>,
|
|
28
29
|
TApp
|
|
29
30
|
> {
|
|
30
31
|
async load() {
|
|
32
|
+
registerDeviceTypeContext(this.flowEngine);
|
|
31
33
|
this.app.addComponents({ FlowRoute });
|
|
32
34
|
this.app.flowEngine.setModelRepository(new FlowModelRepository(this.app));
|
|
33
35
|
const filteredModels = Object.fromEntries(
|
|
@@ -49,7 +51,7 @@ export class PluginFlowEngine<TApp extends BaseApplication<any> = BaseApplicatio
|
|
|
49
51
|
key: 'dynamic-flows-editor',
|
|
50
52
|
component: DynamicFlowsIcon,
|
|
51
53
|
visible(model) {
|
|
52
|
-
return model.getEvents().size > 0;
|
|
54
|
+
return model.getEvents().size > 0 || model.flowEngine.flowSettings.hasDynamicFlowSourceProvider(model);
|
|
53
55
|
},
|
|
54
56
|
sort: 0,
|
|
55
57
|
});
|
|
@@ -98,6 +100,7 @@ export * from './FlowPage';
|
|
|
98
100
|
export * from './models';
|
|
99
101
|
export * from './utils';
|
|
100
102
|
export * from './actions';
|
|
103
|
+
export { FieldAssignValueInput } from './components/FieldAssignValueInput';
|
|
101
104
|
export * from './system-settings';
|
|
102
105
|
export * from './admin-shell/admin-layout';
|
|
103
106
|
export * from './admin-shell/BaseLayoutModel';
|
|
@@ -9,13 +9,14 @@
|
|
|
9
9
|
|
|
10
10
|
import _ from 'lodash';
|
|
11
11
|
import { useEffect, useState } from 'react';
|
|
12
|
+
import { stripMarkdownIframes } from '../../../../utils/markdownSanitize';
|
|
12
13
|
|
|
13
14
|
export const parseMarkdown = _.memoize(async (text: string) => {
|
|
14
15
|
if (!text) {
|
|
15
16
|
return text;
|
|
16
17
|
}
|
|
17
18
|
const m = await import('./md');
|
|
18
|
-
return m.default.render(text);
|
|
19
|
+
return stripMarkdownIframes(m.default.render(text));
|
|
19
20
|
});
|
|
20
21
|
|
|
21
22
|
export function useParseMarkdown(text: string) {
|
|
@@ -0,0 +1,39 @@
|
|
|
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 type { FlowEngine } from '@nocobase/flow-engine';
|
|
11
|
+
import { deviceType } from 'react-device-detect';
|
|
12
|
+
|
|
13
|
+
export const registerDeviceTypeContext = (flowEngine: FlowEngine) => {
|
|
14
|
+
flowEngine.context.defineProperty('deviceType', {
|
|
15
|
+
get: () => (deviceType === 'browser' ? 'computer' : deviceType),
|
|
16
|
+
cache: false,
|
|
17
|
+
meta: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
title: flowEngine.translate('Current device type'),
|
|
20
|
+
interface: 'select',
|
|
21
|
+
uiSchema: {
|
|
22
|
+
enum: [
|
|
23
|
+
{ label: flowEngine.translate('Computer'), value: 'computer' },
|
|
24
|
+
{ label: flowEngine.translate('Mobile'), value: 'mobile' },
|
|
25
|
+
{ label: flowEngine.translate('Tablet'), value: 'tablet' },
|
|
26
|
+
{ label: flowEngine.translate('SmartTv'), value: 'smarttv' },
|
|
27
|
+
{ label: flowEngine.translate('Console'), value: 'console' },
|
|
28
|
+
{ label: flowEngine.translate('Wearable'), value: 'wearable' },
|
|
29
|
+
{ label: flowEngine.translate('Embedded'), value: 'embedded' },
|
|
30
|
+
],
|
|
31
|
+
'x-component': 'Select',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
info: {
|
|
35
|
+
description: 'Current device type (computer/mobile/tablet/...).',
|
|
36
|
+
detail: 'string',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
};
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import React, { type ComponentType, type CSSProperties, type ReactNode } from 'react';
|
|
11
11
|
import { DateFilterDynamicComponent } from '../../models/blocks/filter-form/fields/date-time/components/DateFilterDynamicComponent';
|
|
12
|
+
import { translateOptions } from './enumOptionsUtils';
|
|
12
13
|
|
|
13
14
|
type OperatorMeta = {
|
|
14
15
|
value?: string;
|
|
@@ -26,6 +27,7 @@ type OperatorComponentFieldModel = {
|
|
|
26
27
|
props?: Record<string, unknown>;
|
|
27
28
|
render?: () => ReactNode;
|
|
28
29
|
__originalRender?: () => ReactNode;
|
|
30
|
+
translate?: (text: string) => string;
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
type OperatorComponentRenderOptions = {
|
|
@@ -93,6 +95,17 @@ export function restoreOperatorComponentRender(fieldModel?: unknown) {
|
|
|
93
95
|
return true;
|
|
94
96
|
}
|
|
95
97
|
|
|
98
|
+
function translateComponentOptions(props: Record<string, unknown>, translate: ((text: string) => string) | undefined) {
|
|
99
|
+
if (!Array.isArray(props.options) || typeof translate !== 'function') {
|
|
100
|
+
return props;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
...props,
|
|
105
|
+
options: translateOptions(props.options, translate),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
96
109
|
export function applyOperatorComponentRender({
|
|
97
110
|
app,
|
|
98
111
|
fieldModel,
|
|
@@ -118,8 +131,9 @@ export function applyOperatorComponentRender({
|
|
|
118
131
|
mutableFieldModel.render = () => {
|
|
119
132
|
const fieldProps = mutableFieldModel.props || {};
|
|
120
133
|
const fieldStyle = pickOperatorStyle(fieldProps.style);
|
|
121
|
-
const
|
|
134
|
+
const mergedProps =
|
|
122
135
|
propsPriority === 'operator' ? { ...fieldProps, ...operatorProps } : { ...operatorProps, ...fieldProps };
|
|
136
|
+
const componentProps = translateComponentOptions(mergedProps, mutableFieldModel.translate);
|
|
123
137
|
const componentStyle =
|
|
124
138
|
propsPriority === 'operator' ? { ...fieldStyle, ...operatorStyle } : { ...operatorStyle, ...fieldStyle };
|
|
125
139
|
const mergedStyle = { ...(style || {}), ...componentStyle };
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { tExpr } from '@nocobase/flow-engine';
|
|
11
11
|
import type { ButtonProps } from 'antd/es/button';
|
|
12
12
|
import { CodeEditor } from '../../components/code-editor';
|
|
13
13
|
import { ActionModel } from '../base';
|
|
@@ -72,12 +72,7 @@ ctx.message.info('Hello JS action.');
|
|
|
72
72
|
},
|
|
73
73
|
async handler(ctx, params) {
|
|
74
74
|
const { code, version } = resolveRunJsParams(ctx, params);
|
|
75
|
-
|
|
76
|
-
await ctx.runjs(
|
|
77
|
-
code,
|
|
78
|
-
{ window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator },
|
|
79
|
-
{ version },
|
|
80
|
-
);
|
|
75
|
+
await ctx.runjs(code, undefined, { version });
|
|
81
76
|
},
|
|
82
77
|
},
|
|
83
78
|
},
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { tExpr } from '@nocobase/flow-engine';
|
|
11
11
|
import type { ButtonProps } from 'antd/es/button';
|
|
12
12
|
import { CodeEditor } from '../../components/code-editor';
|
|
13
13
|
import { ActionModel, ActionSceneEnum } from '../base';
|
|
@@ -78,12 +78,7 @@ if (!rows.length) {
|
|
|
78
78
|
},
|
|
79
79
|
async handler(ctx, params) {
|
|
80
80
|
const { code, version } = resolveRunJsParams(ctx, params);
|
|
81
|
-
|
|
82
|
-
await ctx.runjs(
|
|
83
|
-
code,
|
|
84
|
-
{ window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator },
|
|
85
|
-
{ version },
|
|
86
|
-
);
|
|
81
|
+
await ctx.runjs(code, undefined, { version });
|
|
87
82
|
},
|
|
88
83
|
},
|
|
89
84
|
},
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { ElementProxy,
|
|
10
|
+
import { ElementProxy, tExpr } from '@nocobase/flow-engine';
|
|
11
11
|
import React from 'react';
|
|
12
12
|
import { CodeEditor } from '../../components/code-editor';
|
|
13
13
|
import { ActionModel, ActionSceneEnum, CollectionActionGroupModel, RecordActionGroupModel } from '../base';
|
|
@@ -137,12 +137,7 @@ JSItemActionModel.registerFlow({
|
|
|
137
137
|
ctx.defineProperty('element', {
|
|
138
138
|
get: () => new ElementProxy(element),
|
|
139
139
|
});
|
|
140
|
-
|
|
141
|
-
await ctx.runjs(
|
|
142
|
-
code,
|
|
143
|
-
{ window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator },
|
|
144
|
-
{ version },
|
|
145
|
-
);
|
|
140
|
+
await ctx.runjs(code, undefined, { version });
|
|
146
141
|
});
|
|
147
142
|
},
|
|
148
143
|
},
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { tExpr } from '@nocobase/flow-engine';
|
|
11
11
|
import type { ButtonProps } from 'antd/es/button';
|
|
12
12
|
import { CodeEditor } from '../../components/code-editor';
|
|
13
13
|
import { ActionSceneEnum, RecordActionModel } from '../base';
|
|
@@ -78,12 +78,7 @@ if (!ctx.record) {
|
|
|
78
78
|
},
|
|
79
79
|
async handler(ctx, params) {
|
|
80
80
|
const { code, version } = resolveRunJsParams(ctx, params);
|
|
81
|
-
|
|
82
|
-
await ctx.runjs(
|
|
83
|
-
code,
|
|
84
|
-
{ window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator },
|
|
85
|
-
{ version },
|
|
86
|
-
);
|
|
81
|
+
await ctx.runjs(code, undefined, { version });
|
|
87
82
|
},
|
|
88
83
|
},
|
|
89
84
|
},
|
|
@@ -18,6 +18,17 @@ import { commonConditionHandler, ConditionBuilder } from '../../components/Condi
|
|
|
18
18
|
export { ActionModel, ActionSceneEnum, ActionWithoutPermission, type ActionSceneType } from './ActionModelCore';
|
|
19
19
|
import { ActionModel } from './ActionModelCore';
|
|
20
20
|
|
|
21
|
+
function getMobileDefaultProps(ctx) {
|
|
22
|
+
const defaultProps = ctx.model.defaultProps || {};
|
|
23
|
+
if (ctx.isMobileLayout && defaultProps.icon && ctx.model.enableEditIconOnly !== false) {
|
|
24
|
+
return {
|
|
25
|
+
...defaultProps,
|
|
26
|
+
iconOnly: true,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return defaultProps;
|
|
30
|
+
}
|
|
31
|
+
|
|
21
32
|
ActionModel.registerFlow({
|
|
22
33
|
key: 'buttonSettings',
|
|
23
34
|
title: tExpr('Button settings'),
|
|
@@ -32,6 +43,7 @@ ActionModel.registerFlow({
|
|
|
32
43
|
'x-decorator': 'FormItem',
|
|
33
44
|
'x-component': 'Input',
|
|
34
45
|
title: tExpr('Button title'),
|
|
46
|
+
description: ctx.model.getTitleFieldDescription?.(),
|
|
35
47
|
}
|
|
36
48
|
: undefined,
|
|
37
49
|
tooltip: ctx.model.enableEditTooltip
|
|
@@ -48,13 +60,14 @@ ActionModel.registerFlow({
|
|
|
48
60
|
title: tExpr('Button icon'),
|
|
49
61
|
}
|
|
50
62
|
: undefined,
|
|
51
|
-
iconOnly:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
iconOnly:
|
|
64
|
+
ctx.model.enableEditIcon && ctx.model.enableEditIconOnly !== false
|
|
65
|
+
? {
|
|
66
|
+
'x-decorator': 'FormItem',
|
|
67
|
+
'x-component': 'Switch',
|
|
68
|
+
title: tExpr('Icon only'),
|
|
69
|
+
}
|
|
70
|
+
: undefined,
|
|
58
71
|
type: ctx.model.enableEditType
|
|
59
72
|
? {
|
|
60
73
|
'x-decorator': 'FormItem',
|
|
@@ -80,7 +93,7 @@ ActionModel.registerFlow({
|
|
|
80
93
|
};
|
|
81
94
|
},
|
|
82
95
|
defaultParams(ctx) {
|
|
83
|
-
const defaultProps = ctx
|
|
96
|
+
const defaultProps = getMobileDefaultProps(ctx);
|
|
84
97
|
if (!ctx.model.enableEditColor) {
|
|
85
98
|
return defaultProps;
|
|
86
99
|
}
|
|
@@ -25,7 +25,7 @@ export function ActionWithoutPermission(props) {
|
|
|
25
25
|
const dataSourcePrefix = `${t(dataSource.displayName || dataSource.key)} > `;
|
|
26
26
|
const collectionPrefix = collection ? `${t(collection.title) || collection.name || collection.tableName} ` : '';
|
|
27
27
|
return `${dataSourcePrefix}${collectionPrefix}`;
|
|
28
|
-
}, []);
|
|
28
|
+
}, [collection, dataSource.displayName, dataSource.key, t]);
|
|
29
29
|
const { actionName } = props?.forbidden || model.forbidden;
|
|
30
30
|
const messageValue = useMemo(() => {
|
|
31
31
|
return t(
|
|
@@ -62,6 +62,7 @@ export class ActionModel<T extends DefaultStructure = DefaultStructure> extends
|
|
|
62
62
|
enableEditTooltip = true;
|
|
63
63
|
enableEditTitle = true;
|
|
64
64
|
enableEditIcon = true;
|
|
65
|
+
enableEditIconOnly = true;
|
|
65
66
|
enableEditType = true;
|
|
66
67
|
enableEditDanger = true;
|
|
67
68
|
enableEditColor = false;
|
|
@@ -136,6 +137,10 @@ export class ActionModel<T extends DefaultStructure = DefaultStructure> extends
|
|
|
136
137
|
return this.props.title;
|
|
137
138
|
}
|
|
138
139
|
|
|
140
|
+
getTitleFieldDescription() {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
139
144
|
getIcon() {
|
|
140
145
|
return this.props.icon;
|
|
141
146
|
}
|
|
@@ -143,10 +148,11 @@ export class ActionModel<T extends DefaultStructure = DefaultStructure> extends
|
|
|
143
148
|
renderButton() {
|
|
144
149
|
const { iconOnly, ...props } = this.props;
|
|
145
150
|
const icon = this.getIcon() ? <Icon type={this.getIcon() as any} /> : undefined;
|
|
151
|
+
const titleContent = iconOnly && icon ? null : props.children || this.getTitle();
|
|
146
152
|
|
|
147
153
|
return (
|
|
148
154
|
<Button {...props} onClick={this.onClick.bind(this)} icon={icon}>
|
|
149
|
-
{
|
|
155
|
+
{titleContent}
|
|
150
156
|
</Button>
|
|
151
157
|
);
|
|
152
158
|
}
|
|
@@ -162,11 +168,12 @@ export class ActionModel<T extends DefaultStructure = DefaultStructure> extends
|
|
|
162
168
|
renderHiddenInConfig(): React.ReactNode | undefined {
|
|
163
169
|
const { iconOnly, ...props } = this.props;
|
|
164
170
|
const icon = this.getIcon() ? <Icon type={this.getIcon() as any} /> : undefined;
|
|
171
|
+
const titleContent = iconOnly && icon ? null : props.children || this.getTitle();
|
|
165
172
|
if (this.forbidden) {
|
|
166
173
|
return (
|
|
167
174
|
<ActionWithoutPermission>
|
|
168
175
|
<Button {...props} onClick={this.onClick.bind(this)} icon={icon} style={{ opacity: '0.3' }}>
|
|
169
|
-
{
|
|
176
|
+
{titleContent}
|
|
170
177
|
</Button>
|
|
171
178
|
</ActionWithoutPermission>
|
|
172
179
|
);
|
|
@@ -174,7 +181,7 @@ export class ActionModel<T extends DefaultStructure = DefaultStructure> extends
|
|
|
174
181
|
return (
|
|
175
182
|
<Tooltip title={this.context.t('The button is hidden and only visible when the UI Editor is active')}>
|
|
176
183
|
<Button {...props} onClick={this.onClick.bind(this)} icon={icon} style={{ opacity: '0.3' }}>
|
|
177
|
-
{
|
|
184
|
+
{titleContent}
|
|
178
185
|
</Button>
|
|
179
186
|
</Tooltip>
|
|
180
187
|
);
|
|
@@ -14,8 +14,10 @@ import {
|
|
|
14
14
|
FlowSettingsButton,
|
|
15
15
|
buildSubModelGroups,
|
|
16
16
|
buildSubModelItems,
|
|
17
|
+
type FlowModel,
|
|
17
18
|
type SubModelItem,
|
|
18
19
|
type SubModelItemsType,
|
|
20
|
+
VIEW_ACTIVATED_EVENT,
|
|
19
21
|
} from '@nocobase/flow-engine';
|
|
20
22
|
import React from 'react';
|
|
21
23
|
import { FilterManager } from '../blocks/filter-manager/FilterManager';
|
|
@@ -24,6 +26,8 @@ import { GridModel } from './GridModel';
|
|
|
24
26
|
const SELECT_SCENE_ALLOWED_OTHER_BLOCK_MODELS = ['JSBlockModel', 'IframeBlockModel', 'MarkdownBlockModel'] as const;
|
|
25
27
|
|
|
26
28
|
export class BlockGridModel extends GridModel {
|
|
29
|
+
private viewActivatedListener?: () => void;
|
|
30
|
+
|
|
27
31
|
dragOverlayConfig: DragOverlayConfig = {
|
|
28
32
|
// 列内插入
|
|
29
33
|
columnInsert: {
|
|
@@ -50,6 +54,28 @@ export class BlockGridModel extends GridModel {
|
|
|
50
54
|
});
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
onMount() {
|
|
58
|
+
super.onMount();
|
|
59
|
+
if (this.context.view?.inputArgs?.scene !== 'select' || this.viewActivatedListener) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.viewActivatedListener = () => {
|
|
64
|
+
this.mapSubModels('items', (item) => {
|
|
65
|
+
(item as FlowModel & { onActive?: () => void }).onActive?.();
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
this.flowEngine.emitter.on(VIEW_ACTIVATED_EVENT, this.viewActivatedListener);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
protected onUnmount() {
|
|
72
|
+
if (this.viewActivatedListener) {
|
|
73
|
+
this.flowEngine.emitter.off(VIEW_ACTIVATED_EVENT, this.viewActivatedListener);
|
|
74
|
+
this.viewActivatedListener = undefined;
|
|
75
|
+
}
|
|
76
|
+
super.onUnmount();
|
|
77
|
+
}
|
|
78
|
+
|
|
53
79
|
get subModelBaseClasses() {
|
|
54
80
|
const inputArgs = this.context.view?.inputArgs ?? {};
|
|
55
81
|
if (inputArgs.collectionName && !inputArgs.filterByTk) {
|
|
@@ -569,9 +569,13 @@ export class CollectionBlockModel<T = DefaultStructure> extends DataBlockModel<T
|
|
|
569
569
|
}
|
|
570
570
|
if (fieldPath.includes('.')) {
|
|
571
571
|
// 关系数据
|
|
572
|
+
const collection = this.collection;
|
|
573
|
+
if (!collection) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
572
576
|
const [field1, field2] = fieldPath.split('.');
|
|
573
577
|
const associationField = this.context.dataSourceManager.getCollectionField(
|
|
574
|
-
`${
|
|
578
|
+
`${collection.dataSourceKey}.${collection.name}.${field1}`,
|
|
575
579
|
) as CollectionField;
|
|
576
580
|
if (!associationField) {
|
|
577
581
|
return;
|
|
@@ -583,7 +587,7 @@ export class CollectionBlockModel<T = DefaultStructure> extends DataBlockModel<T
|
|
|
583
587
|
}
|
|
584
588
|
|
|
585
589
|
const collectionField = this.context.dataSourceManager.getCollectionField(
|
|
586
|
-
`${
|
|
590
|
+
`${collection.dataSourceKey}.${targetCollectionName}.${field2}`,
|
|
587
591
|
) as CollectionField;
|
|
588
592
|
|
|
589
593
|
if (collectionField && collectionField.isAssociationField()) {
|
|
@@ -75,6 +75,12 @@ interface DragState {
|
|
|
75
75
|
generatedIds: Map<string, string>;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
const MOBILE_GRID_DISABLED_DROP_SLOT_TYPES = new Set<LayoutSlot['type']>(['column-edge', 'item-edge', 'empty-column']);
|
|
79
|
+
|
|
80
|
+
const filterMobileGridDragSlots = (slots: LayoutSlot[]) => {
|
|
81
|
+
return slots.filter((slot) => !MOBILE_GRID_DISABLED_DROP_SLOT_TYPES.has(slot.type));
|
|
82
|
+
};
|
|
83
|
+
|
|
78
84
|
const getClientPoint = (event: any): { x: number; y: number } | null => {
|
|
79
85
|
if (!event) {
|
|
80
86
|
return null;
|
|
@@ -625,7 +631,7 @@ export class GridModel<T extends { subModels: { items: FlowModel[] } } = Default
|
|
|
625
631
|
return;
|
|
626
632
|
}
|
|
627
633
|
const snapshot = buildLayoutSnapshot({ container: this.getDragContainer() });
|
|
628
|
-
this.dragState.slots = snapshot.slots;
|
|
634
|
+
this.dragState.slots = this.context.isMobileLayout ? filterMobileGridDragSlots(snapshot.slots) : snapshot.slots;
|
|
629
635
|
this.dragState.containerRect = snapshot.containerRect;
|
|
630
636
|
}
|
|
631
637
|
|
|
@@ -1135,7 +1141,7 @@ GridModel.registerFlow({
|
|
|
1135
1141
|
/**
|
|
1136
1142
|
* 将多列栅格 rows 转换为移动端单列 rows。
|
|
1137
1143
|
* 遍历原 rows 的行与列顺序,把每个原列(过滤空白列后)变成一个新行(仅一列)。
|
|
1138
|
-
* 行 key
|
|
1144
|
+
* 行 key 使用原 rowId 与 columnIndex 生成,避免每次渲染产生随机 key 导致移动端滚动位置丢失。
|
|
1139
1145
|
* @param rows 原始多列 rows
|
|
1140
1146
|
* @returns 单列 rows
|
|
1141
1147
|
*/
|
|
@@ -1145,13 +1151,38 @@ export function transformRowsToSingleColumn(
|
|
|
1145
1151
|
): Record<string, string[][]> {
|
|
1146
1152
|
const emptyColumnUid = options?.emptyColumnUid ?? EMPTY_COLUMN_UID;
|
|
1147
1153
|
const singleColumnRows: Record<string, string[][]> = {};
|
|
1154
|
+
|
|
1155
|
+
const getAvailableRowId = (baseRowId: string) => {
|
|
1156
|
+
if (!singleColumnRows[baseRowId]) {
|
|
1157
|
+
return baseRowId;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
let duplicateIndex = 1;
|
|
1161
|
+
let rowId = `${baseRowId}:duplicate:${duplicateIndex}`;
|
|
1162
|
+
while (singleColumnRows[rowId]) {
|
|
1163
|
+
duplicateIndex += 1;
|
|
1164
|
+
rowId = `${baseRowId}:duplicate:${duplicateIndex}`;
|
|
1165
|
+
}
|
|
1166
|
+
return rowId;
|
|
1167
|
+
};
|
|
1168
|
+
|
|
1148
1169
|
Object.keys(rows).forEach((rowId) => {
|
|
1149
1170
|
const columns = rows[rowId];
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
}
|
|
1171
|
+
const effectiveColumns = columns
|
|
1172
|
+
.map((column, columnIndex) => ({
|
|
1173
|
+
columnIndex,
|
|
1174
|
+
items: column.filter((id) => id !== emptyColumnUid),
|
|
1175
|
+
}))
|
|
1176
|
+
.filter((column) => column.items.length > 0);
|
|
1177
|
+
|
|
1178
|
+
if (effectiveColumns.length === 1 && effectiveColumns[0].columnIndex === 0) {
|
|
1179
|
+
singleColumnRows[getAvailableRowId(rowId)] = [effectiveColumns[0].items];
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
effectiveColumns.forEach((column) => {
|
|
1184
|
+
const generatedRowId = `mobile:${encodeURIComponent(rowId)}:${column.columnIndex}`;
|
|
1185
|
+
singleColumnRows[getAvailableRowId(generatedRowId)] = [column.items];
|
|
1155
1186
|
});
|
|
1156
1187
|
});
|
|
1157
1188
|
return singleColumnRows;
|