From b2970245d9416130b405c2e3e35789fd6e28a3a8 Mon Sep 17 00:00:00 2001 From: sealday Date: Tue, 4 Jun 2024 16:51:57 +0800 Subject: [PATCH] feat: new action.area (#1113) Reviewed-on: https://git.daoyoucloud.com/daoyoucloud/tachybase/pulls/1113 --- .../antd/action/Action.Area.style.ts | 8 + .../antd/action/Action.Area.tsx | 86 +++++++ .../schema-component/antd/action/Action.tsx | 2 + .../schema-component/antd/action/index.tsx | 1 + .../src/client/CanvasContent.tsx | 4 +- .../src/client/WorkflowCanvas.tsx | 24 +- .../src/client/WorkflowPane.tsx | 17 +- .../client/components/RadioWithTooltip.tsx | 7 +- .../src/client/nodes/calculation.tsx | 10 +- .../src/client/nodes/condition.tsx | 6 +- .../src/client/nodes/index.tsx | 214 +++++++++--------- .../src/client/nodes/update.tsx | 8 +- .../src/client/schemas/executions.tsx | 10 +- .../plugin-workflow/src/client/style.tsx | 12 + .../src/client/triggers/index.tsx | 23 +- 15 files changed, 277 insertions(+), 155 deletions(-) create mode 100644 packages/core/client/src/schema-component/antd/action/Action.Area.style.ts create mode 100644 packages/core/client/src/schema-component/antd/action/Action.Area.tsx diff --git a/packages/core/client/src/schema-component/antd/action/Action.Area.style.ts b/packages/core/client/src/schema-component/antd/action/Action.Area.style.ts new file mode 100644 index 000000000..a76f7b882 --- /dev/null +++ b/packages/core/client/src/schema-component/antd/action/Action.Area.style.ts @@ -0,0 +1,8 @@ +import { createStyles } from 'antd-style'; + +export const useStyles = createStyles(({ css, token }) => { + return css` + padding-top: ${token.paddingContentVerticalLG}px; + background-color: var(--colorBgDrawer); + `; +}); diff --git a/packages/core/client/src/schema-component/antd/action/Action.Area.tsx b/packages/core/client/src/schema-component/antd/action/Action.Area.tsx new file mode 100644 index 000000000..940a2015b --- /dev/null +++ b/packages/core/client/src/schema-component/antd/action/Action.Area.tsx @@ -0,0 +1,86 @@ +import React, { useContext, useEffect, useRef, useState } from 'react'; +import { observer, RecursionField, useField, useFieldSchema } from '@tachybase/schema'; + +import { createPortal } from 'react-dom'; + +import { useStyles } from './Action.Area.style'; +import { useActionContext } from './hooks'; +import { ComposedActionDrawer } from './types'; + +const ActionAreaContext = React.createContext({}); + +export const ActionAreaProvider = ({ children }: { children: React.ReactNode }) => { + const [component, setComponent] = useState(() => {}); + const [prevSetVisible, setPrevSetVisible] = useState(() => {}); + const ref = useRef(); + return ( + + {children} + + ); +}; + +export const useActionAreaStub = () => { + const { component } = useContext(ActionAreaContext); + return component; +}; + +export const ActionAreaStub = () => { + const { ref } = useContext(ActionAreaContext); + return
; +}; + +export const ActionAreaPlayer = ({ children }) => { + const { visible, setVisible } = useActionContext(); + const { prevSetVisible, setPrevSetVisible, ref } = useContext(ActionAreaContext); + useEffect(() => { + if (visible) { + setPrevSetVisible(() => { + prevSetVisible?.(false); + return setVisible; + }); + } + }, [visible]); + + return visible ? createPortal(children, ref.current) : null; +}; + +export const ActionArea: ComposedActionDrawer = observer( + (props) => { + const { footerNodeName = 'Action.Drawer.Footer' } = props; + const schema = useFieldSchema(); + const field = useField(); + const { styles } = useStyles(); + + const Current = () => ( +
+ { + return s['x-component'] !== footerNodeName; + }} + /> +
+ ); + + return ( + + + + ); + }, + { displayName: 'ActionArea' }, +); + +ActionArea.Footer = observer( + () => { + const field = useField(); + const schema = useFieldSchema(); + return ; + }, + { displayName: 'ActionArea.Footer' }, +); + +export default ActionArea; diff --git a/packages/core/client/src/schema-component/antd/action/Action.tsx b/packages/core/client/src/schema-component/antd/action/Action.tsx index ad5c93d0d..0263d06f0 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.tsx @@ -17,6 +17,7 @@ import { useLocalVariables, useVariables } from '../../../variables'; import { SortableItem } from '../../common'; import { useCompile, useComponent, useDesigner } from '../../hooks'; import { useProps } from '../../hooks/useProps'; +import { ActionArea } from './Action.Area'; import ActionContainer from './Action.Container'; import { ActionDesigner } from './Action.Designer'; import { ActionDrawer } from './Action.Drawer'; @@ -231,5 +232,6 @@ Action.Drawer = ActionDrawer; Action.Modal = ActionModal; Action.Container = ActionContainer; Action.Page = ActionPage; +Action.Area = ActionArea; export default Action; diff --git a/packages/core/client/src/schema-component/antd/action/index.tsx b/packages/core/client/src/schema-component/antd/action/index.tsx index 360304a15..4b3240fdf 100644 --- a/packages/core/client/src/schema-component/antd/action/index.tsx +++ b/packages/core/client/src/schema-component/antd/action/index.tsx @@ -7,3 +7,4 @@ export * from './hooks/useGetAriaLabelOfDrawer'; export * from './hooks/useGetAriaLabelOfModal'; export * from './hooks/useGetAriaLabelOfPopover'; export * from './Action.Designer'; +export * from './Action.Area'; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/CanvasContent.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/CanvasContent.tsx index b80834b42..0a899527e 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/CanvasContent.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/CanvasContent.tsx @@ -1,7 +1,7 @@ -import { Alert, Slider } from 'antd'; import React from 'react'; +import { css, cx } from '@tachybase/client'; -import { cx, css } from '@tachybase/client'; +import { Alert, Slider } from 'antd'; import { Branch } from './Branch'; import { useFlowContext } from './FlowContext'; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/WorkflowCanvas.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/WorkflowCanvas.tsx index f166bbe04..edc1b6777 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/WorkflowCanvas.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/WorkflowCanvas.tsx @@ -1,28 +1,31 @@ -import { DownOutlined, EllipsisOutlined, RightOutlined } from '@ant-design/icons'; +import React, { useEffect, useState } from 'react'; import { + ActionAreaProvider, + ActionAreaStub, ActionContextProvider, + cx, ResourceActionProvider, SchemaComponent, - cx, useApp, useDocumentTitle, useResourceActionContext, useResourceContext, } from '@tachybase/client'; import { str2moment } from '@tachybase/utils/client'; -import { App, Breadcrumb, Button, Dropdown, Result, Spin, Switch, message } from 'antd'; -import React, { useEffect, useState } from 'react'; + +import { DownOutlined, EllipsisOutlined, RightOutlined } from '@ant-design/icons'; +import { App, Breadcrumb, Button, Dropdown, message, Result, Spin, Switch } from 'antd'; import { useTranslation } from 'react-i18next'; import { Link, useNavigate } from 'react-router-dom'; import { CanvasContent } from './CanvasContent'; +import { ExecutionStatusColumn } from './components/ExecutionStatus'; import { ExecutionLink } from './ExecutionLink'; import { FlowContext, useFlowContext } from './FlowContext'; import { lang } from './locale'; import { executionSchema } from './schemas/executions'; import useStyles from './style'; -import { linkNodes, getWorkflowDetailPath } from './utils'; -import { ExecutionStatusColumn } from './components/ExecutionStatus'; +import { getWorkflowDetailPath, linkNodes } from './utils'; function ExecutionResourceProvider({ request, filter = {}, ...others }) { const { workflow } = useFlowContext(); @@ -236,7 +239,14 @@ export function WorkflowCanvas() { - + +
+ +
+ +
+
+
); } diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/WorkflowPane.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/WorkflowPane.tsx index 0c10424f8..2ea2b7c40 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/WorkflowPane.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/WorkflowPane.tsx @@ -1,15 +1,16 @@ -import { SchemaComponent, SchemaComponentContext, usePlugin, useRecord } from '@tachybase/client'; -import { Card } from 'antd'; import React, { useContext, useEffect } from 'react'; +import { SchemaComponent, SchemaComponentContext, usePlugin, useRecord } from '@tachybase/client'; +import { onFieldChange, useField, useFormEffects } from '@tachybase/schema'; + +import { Card } from 'antd'; + +import WorkflowPlugin, { RadioWithTooltip } from '.'; +import { ExecutionStatusColumn, ExecutionStatusSelect } from './components/ExecutionStatus'; +import OpenDrawer from './components/OpenDrawer'; import { ExecutionLink } from './ExecutionLink'; import { ExecutionResourceProvider } from './ExecutionResourceProvider'; -import { WorkflowLink } from './WorkflowLink'; -import OpenDrawer from './components/OpenDrawer'; import { workflowSchema } from './schemas/workflows'; -import { ExecutionStatusSelect, ExecutionStatusColumn } from './components/ExecutionStatus'; -import WorkflowPlugin, { RadioWithTooltip } from '.'; -import { onFieldChange } from '@tachybase/schema'; -import { useField, useFormEffects } from '@tachybase/schema'; +import { WorkflowLink } from './WorkflowLink'; function SyncOptionSelect(props) { const field = useField(); diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/components/RadioWithTooltip.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/components/RadioWithTooltip.tsx index c04c18342..f575a77eb 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/components/RadioWithTooltip.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/components/RadioWithTooltip.tsx @@ -1,7 +1,8 @@ -import { QuestionCircleOutlined } from '@ant-design/icons'; -import { css, useCompile } from '@tachybase/client'; -import { Radio, Space, Tooltip } from 'antd'; import React from 'react'; +import { css, useCompile } from '@tachybase/client'; + +import { QuestionCircleOutlined } from '@ant-design/icons'; +import { Radio, Space, Tooltip } from 'antd'; export interface RadioWithTooltipOption { value: any; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/calculation.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/calculation.tsx index 1e1ea84fc..cbfcf82aa 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/calculation.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/calculation.tsx @@ -1,12 +1,12 @@ import { SchemaInitializerItemType } from '@tachybase/client'; import { Evaluator, evaluators, getOptions } from '@tachybase/evaluators/client'; -import { RadioWithTooltip } from '../components/RadioWithTooltip'; -import { ValueBlock } from '../components/ValueBlock'; -import { renderEngineReference } from '../components/renderEngineReference'; -import { NAMESPACE, lang } from '../locale'; -import { BaseTypeSets, WorkflowVariableTextArea, defaultFieldNames } from '../variable'; import { Instruction } from '.'; +import { RadioWithTooltip } from '../components/RadioWithTooltip'; +import { renderEngineReference } from '../components/renderEngineReference'; +import { ValueBlock } from '../components/ValueBlock'; +import { lang, NAMESPACE } from '../locale'; +import { BaseTypeSets, defaultFieldNames, WorkflowVariableTextArea } from '../variable'; export default class extends Instruction { title = `{{t("Calculation", { ns: "${NAMESPACE}" })}}`; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/condition.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/condition.tsx index e29e18918..08d34f39b 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/condition.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/condition.tsx @@ -1,10 +1,12 @@ -import { CloseCircleOutlined } from '@ant-design/icons'; +import React from 'react'; import { css, cx, useCompile, Variable } from '@tachybase/client'; import { evaluators } from '@tachybase/evaluators/client'; import { Registry } from '@tachybase/utils/client'; + +import { CloseCircleOutlined } from '@ant-design/icons'; import { Button, Select } from 'antd'; -import React from 'react'; import { Trans, useTranslation } from 'react-i18next'; + import { Instruction, NodeDefaultView } from '.'; import { Branch } from '../Branch'; import { RadioWithTooltip, RadioWithTooltipOption } from '../components/RadioWithTooltip'; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/index.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/index.tsx index 764719763..5e34cff63 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/index.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/index.tsx @@ -327,6 +327,113 @@ export function NodeDefaultView(props) { } }, []); + const schema = { + type: 'void', + properties: { + ...(instruction.view ? { view: instruction.view } : {}), + button: { + type: 'void', + 'x-content': detailText, + 'x-component': Button, + 'x-component-props': { + type: 'link', + className: 'workflow-node-config-button', + }, + }, + [data.id]: { + type: 'void', + title: ( +
+ {data.title} + + + {data.key} + + +
+ ), + 'x-decorator': 'FormV2', + 'x-use-decorator-props': 'useFormProviderProps', + 'x-component': 'Action.Area', + properties: { + ...(instruction.description + ? { + description: { + type: 'void', + 'x-component': DrawerDescription, + 'x-component-props': { + label: lang('Node type'), + title: instruction.title, + description: instruction.description, + }, + }, + } + : {}), + fieldset: { + type: 'void', + 'x-component': 'fieldset', + 'x-component-props': { + className: css` + .ant-input, + .ant-select, + .ant-cascader-picker, + .ant-picker, + .ant-input-number, + .ant-input-affix-wrapper { + &.auto-width { + width: auto; + min-width: 6em; + } + } + `, + }, + properties: instruction.fieldset, + }, + actions: workflow.executed + ? null + : { + type: 'void', + 'x-component': 'Action.Drawer.Footer', + properties: { + cancel: { + title: '{{t("Cancel")}}', + 'x-component': 'Action', + 'x-component-props': { + useAction: '{{ cm.useCancelAction }}', + }, + }, + submit: { + title: '{{t("Submit")}}', + 'x-component': 'Action', + 'x-component-props': { + type: 'primary', + useAction: useUpdateAction, + }, + }, + }, + }, + }, + } as ISchema, + }, + }; + return (
- {data.title} - - - {data.key} - - -
- ), - 'x-decorator': 'FormV2', - 'x-use-decorator-props': 'useFormProviderProps', - 'x-component': 'Action.Drawer', - properties: { - ...(instruction.description - ? { - description: { - type: 'void', - 'x-component': DrawerDescription, - 'x-component-props': { - label: lang('Node type'), - title: instruction.title, - description: instruction.description, - }, - }, - } - : {}), - fieldset: { - type: 'void', - 'x-component': 'fieldset', - 'x-component-props': { - className: css` - .ant-input, - .ant-select, - .ant-cascader-picker, - .ant-picker, - .ant-input-number, - .ant-input-affix-wrapper { - &.auto-width { - width: auto; - min-width: 6em; - } - } - `, - }, - properties: instruction.fieldset, - }, - actions: workflow.executed - ? null - : { - type: 'void', - 'x-component': 'Action.Drawer.Footer', - properties: { - cancel: { - title: '{{t("Cancel")}}', - 'x-component': 'Action', - 'x-component-props': { - useAction: '{{ cm.useCancelAction }}', - }, - }, - submit: { - title: '{{t("Submit")}}', - 'x-component': 'Action', - 'x-component-props': { - type: 'primary', - useAction: useUpdateAction, - }, - }, - }, - }, - }, - } as ISchema, - }, - }} + schema={schema} /> diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/update.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/update.tsx index b99c64511..38a37e5fc 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/update.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/nodes/update.tsx @@ -1,16 +1,14 @@ -import { useField, useForm } from '@tachybase/schema'; import React from 'react'; - import { useCollectionDataSource, useCollectionManager_deprecated } from '@tachybase/client'; +import { useField, useForm } from '@tachybase/schema'; +import { Instruction } from '.'; import CollectionFieldset from '../components/CollectionFieldset'; import { FilterDynamicComponent } from '../components/FilterDynamicComponent'; - import { RadioWithTooltip } from '../components/RadioWithTooltip'; -import { NAMESPACE, lang } from '../locale'; +import { lang, NAMESPACE } from '../locale'; import { collection, filter, values } from '../schemas/collection'; import { isValidFilter } from '../utils'; -import { Instruction } from '.'; function IndividualHooksRadioWithTooltip({ onChange, ...props }) { const { getCollectionFields } = useCollectionManager_deprecated(); diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/schemas/executions.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/schemas/executions.tsx index 34ddf61f3..9e901527c 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/schemas/executions.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/schemas/executions.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { ISchema } from '@tachybase/schema'; -import { Link } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; -import { message } from 'antd'; - import { useActionContext, useRecord, useResourceActionContext, useResourceContext } from '@tachybase/client'; +import { ISchema } from '@tachybase/schema'; + +import { message } from 'antd'; +import { useTranslation } from 'react-i18next'; +import { Link } from 'react-router-dom'; import { ExecutionStatusOptions } from '../constants'; import { NAMESPACE } from '../locale'; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/style.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/style.tsx index 5717c0df4..5a14fb16e 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/style.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/style.tsx @@ -35,6 +35,18 @@ const useStyles = createStyles(({ css, token }) => { } } + .workflow-content { + display: flex; + height: 100%; + padding-bottom: 40px; + } + + .workflow-operator-area { + padding: 8px; + background-color: white; + width: 800px; + } + .workflow-canvas-wrapper { flex-grow: 1; overflow: hidden; diff --git a/packages/plugins/@tachybase/plugin-workflow/src/client/triggers/index.tsx b/packages/plugins/@tachybase/plugin-workflow/src/client/triggers/index.tsx index 5947de656..0ad758490 100644 --- a/packages/plugins/@tachybase/plugin-workflow/src/client/triggers/index.tsx +++ b/packages/plugins/@tachybase/plugin-workflow/src/client/triggers/index.tsx @@ -1,29 +1,28 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { Button, Input, Tag, message } from 'antd'; -import { cloneDeep } from 'lodash'; -import { InfoOutlined } from '@ant-design/icons'; -import { createForm } from '@tachybase/schema'; -import { ISchema, useForm } from '@tachybase/schema'; - import { ActionContextProvider, + css, + cx, FieldNames, FormProvider, SchemaComponent, SchemaInitializerItemType, - css, - cx, - useAPIClient, useActionContext, + useAPIClient, useCompile, usePlugin, useResourceActionContext, } from '@tachybase/client'; +import { createForm, ISchema, useForm } from '@tachybase/schema'; + +import { InfoOutlined } from '@ant-design/icons'; +import { Button, Input, message, Tag } from 'antd'; +import { cloneDeep } from 'lodash'; import WorkflowPlugin from '..'; -import { useFlowContext } from '../FlowContext'; import { DrawerDescription } from '../components/DrawerDescription'; -import { NAMESPACE, lang } from '../locale'; +import { useFlowContext } from '../FlowContext'; +import { lang, NAMESPACE } from '../locale'; import useStyles from '../style'; import { UseVariableOptions, VariableOption } from '../variable'; @@ -264,7 +263,7 @@ export const TriggerConfig = () => { drawer: { type: 'void', title: titleText, - 'x-component': 'Action.Drawer', + 'x-component': 'Action.Area', 'x-decorator': 'FormV2', 'x-use-decorator-props': 'useFormProviderProps', properties: {