Skip to content

Commit a763d44

Browse files
committed
Merge branch '3.5.x'
2 parents e74cf70 + 02a2938 commit a763d44

File tree

14 files changed

+1133
-979
lines changed

14 files changed

+1133
-979
lines changed

framework/elsa/fit-elsa-react/src/components/DefaultRoot.jsx

Lines changed: 156 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
* Licensed under the MIT License. See License.txt in the project root for license information.
55
*--------------------------------------------------------------------------------------------*/
66

7-
import React, {createContext, forwardRef, useContext, useEffect, useImperativeHandle, useReducer, useRef} from 'react';
7+
import React, {createContext, forwardRef, useContext, useEffect, useImperativeHandle, useReducer, useRef, useState} from 'react';
8+
import {createPortal} from 'react-dom';
89
import './contentStyle.css';
9-
import {ConfigProvider, Form} from 'antd';
10+
import {Form} from 'antd';
11+
import {CloseOutlined} from '@ant-design/icons';
1012
import {useUpdateEffect} from '@/components/common/UseUpdateEffect.jsx';
1113
import {EVENT_TYPE} from '@fit-elsa/elsa-core';
1214
import PropTypes from 'prop-types';
@@ -26,117 +28,180 @@ const FormContext = createContext(null);
2628
* @return {JSX.Element}
2729
* @constructor
2830
*/
29-
export const DefaultRoot = forwardRef(function ({shape, component, shapeStatus, borderPadding}, ref) {
30-
const [data, dispatch] = useReducer(component.reducers, component.getJadeConfig());
31-
const id = "react-root-" + shape.id;
32-
const [form] = Form.useForm();
33-
const domRef = useRef();
31+
export const DefaultRoot = forwardRef(function (
32+
{shape, component, shapeStatus, borderPadding},
33+
ref,
34+
) {
35+
const [data, dispatch] = useReducer(
36+
component.reducers,
37+
component.getJadeConfig(),
38+
);
39+
const id = 'react-root-' + shape.id;
40+
const [form] = Form.useForm();
41+
const domRef = useRef();
42+
const [open, setOpen] = useState(false);
3443

35-
// 对外暴露方法.
36-
useImperativeHandle(ref, () => {
37-
return {
38-
getData: () => {
39-
return data;
40-
},
41-
dispatch: (action) => {
42-
dispatch(action);
43-
}
44-
}
45-
});
46-
47-
/**
48-
* 校验当前节点的form输入是否合法.
49-
*
50-
* @return Promise 校验结果
51-
*/
52-
shape.validateForm = () => {
53-
return form.validateFields();
44+
// 对外暴露方法.
45+
useImperativeHandle(ref, () => {
46+
return {
47+
getData: () => {
48+
return data;
49+
},
50+
dispatch: (action) => {
51+
dispatch(action);
52+
},
5453
};
54+
});
5555

56-
// 相当于 componentDidMount
57-
useEffect(() => {
58-
shape.observe();
59-
shape.page.addEventListener(EVENT_TYPE.FOCUSED_SHAPES_CHANGE, onFocusedShapeChange);
60-
shape.page.triggerEvent({type: "shape_rendered", value: {id: shape.id}});
61-
return () => {
62-
shape.page.removeEventListener(EVENT_TYPE.FOCUSED_SHAPES_CHANGE, onFocusedShapeChange);
63-
};
64-
}, []);
56+
/**
57+
* 校验当前节点的form输入是否合法.
58+
*
59+
* @return Promise 校验结果
60+
*/
61+
shape.validateForm = () => {
62+
return form.validateFields();
63+
};
6564

66-
const onFocusedShapeChange = () => {
67-
if (!domRef.current) {
68-
return;
69-
}
70-
const focusedShapes = shape.page.getFocusedShapes();
71-
if (focusedShapes.includes(shape)) {
72-
domRef.current.style.pointerEvents = focusedShapes.length > 1 ? "none" : "auto";
73-
} else {
74-
domRef.current.style.pointerEvents = "auto";
75-
}
65+
// 相当于 componentDidMount
66+
useEffect(() => {
67+
shape.observe();
68+
shape.page.addEventListener(
69+
EVENT_TYPE.FOCUSED_SHAPES_CHANGE,
70+
onFocusedShapeChange,
71+
);
72+
shape.page.triggerEvent({
73+
type: 'shape_rendered',
74+
value: {id: shape.id},
75+
});
76+
return () => {
77+
shape.page.removeEventListener(
78+
EVENT_TYPE.FOCUSED_SHAPES_CHANGE,
79+
onFocusedShapeChange,
80+
);
7681
};
82+
}, []);
7783

78-
// 第一次进来不会触发,第一次发生变化时才触发.
79-
useUpdateEffect(() => {
80-
if (data.jadeNodeConfigChangeIgnored) {
81-
return;
82-
}
83-
if (shape.hasError) {
84-
shape.validateForm().then(shape.offError);
85-
}
86-
shape.graph.dirtied(null, {action: SYSTEM_ACTION.JADE_NODE_CONFIG_CHANGE, shape: shape.id});
87-
}, [data]);
84+
const onFocusedShapeChange = () => {
85+
if (!domRef.current) {
86+
return;
87+
}
88+
const focusedShapes = shape.page.getFocusedShapes();
89+
if (focusedShapes.includes(shape)) {
90+
domRef.current.style.pointerEvents = focusedShapes.length > 1 ? 'none' : 'auto';
91+
} else {
92+
domRef.current.style.pointerEvents = 'auto';
93+
}
94+
setOpen(shape.page.onConfigShape === shape.id);
95+
};
8896

89-
// 当前是评估页面,并且runnable为false时,才出现遮盖层
90-
return (<>
91-
{shape.enableMask && <div className='jade-cover-level' style={{
97+
// 第一次进来不会触发,第一次发生变化时才触发.
98+
useUpdateEffect(() => {
99+
if (data.jadeNodeConfigChangeIgnored) {
100+
return;
101+
}
102+
if (shape.hasError) {
103+
shape.validateForm().then(shape.offError);
104+
}
105+
shape.graph.dirtied(null, {
106+
action: SYSTEM_ACTION.JADE_NODE_CONFIG_CHANGE,
107+
shape: shape.id,
108+
});
109+
}, [data]);
110+
111+
// 当前是评估页面,并且runnable为false时,才出现遮盖层
112+
return (
113+
<>
114+
{shape.enableMask && (
115+
<div
116+
className="jade-cover-level"
117+
style={{
92118
margin: -borderPadding,
93119
width: `calc(100% + ${2 * borderPadding}px)`,
94120
height: `calc(100% + ${2 * borderPadding}px)`,
95-
}}/>}
96-
<div id={id} style={{display: 'block'}} ref={domRef}>
97-
<Form form={form}
98-
name={`form-${shape.id}`}
99-
layout='vertical' // 设置全局的垂直布局
100-
className={'jade-form'}
101-
>
102-
<DispatchContext.Provider value={dispatch}>
103-
{shape.drawer.getHeaderComponent(data, shapeStatus)}
104-
<FormContext.Provider value={form}>
105-
<ShapeContext.Provider value={shape}>
106-
<DataContext.Provider value={data}>
107-
<div
108-
className='react-node-content'
109-
style={{borderRadius: `${shape.borderRadius}px`}}>
110-
{component.getReactComponents(shapeStatus, data)}
111-
</div>
112-
</DataContext.Provider>
113-
</ShapeContext.Provider>
114-
</FormContext.Provider>
115-
{shape.drawer.getFooterComponent()}
116-
</DispatchContext.Provider>
117-
</Form>
118-
</div>
119-
</>);
121+
}}
122+
/>
123+
)}
124+
<div id={id} style={{display: 'block'}} ref={domRef}>
125+
<Form
126+
form={form}
127+
name={`form-${shape.id}`}
128+
layout="vertical" // 设置全局的垂直布局
129+
className={'jade-form'}
130+
>
131+
<DispatchContext.Provider value={dispatch}>
132+
{shape.drawer.getHeaderComponent(data, shapeStatus)}
133+
<FormContext.Provider value={form}>
134+
<ShapeContext.Provider value={shape}>
135+
<DataContext.Provider value={data}>
136+
<div
137+
className="react-node-content"
138+
style={{borderRadius: `${shape.borderRadius}px`}}
139+
>
140+
{component.getReactComponents(shapeStatus, data, false)}
141+
</div>
142+
</DataContext.Provider>
143+
</ShapeContext.Provider>
144+
</FormContext.Provider>
145+
{shape.drawer.getFooterComponent()}
146+
</DispatchContext.Provider>
147+
</Form>
148+
</div>
149+
{createPortal(
150+
<div className={`jade-form-drawer ${open ? '' : 'hidden'}`}>
151+
<Form
152+
form={form}
153+
name={`outside-form-${shape.id}`}
154+
layout="vertical" // 设置全局的垂直布局
155+
className={'jade-form'}
156+
>
157+
<DispatchContext.Provider value={dispatch}>
158+
<div className="sticky-header">
159+
{shape.drawer.getHeaderComponent(data, shapeStatus)}
160+
<div className="jade-form-drawer-close" onClick={() => {
161+
shape.page.onConfigShape = undefined;
162+
setOpen(false);
163+
}}>
164+
<CloseOutlined style={{fontSize: '12px'}}/>
165+
</div>
166+
</div>
167+
<div className="jade-form-drawer-content">
168+
<FormContext.Provider value={form}>
169+
<ShapeContext.Provider value={shape}>
170+
<DataContext.Provider value={data}>
171+
<div className="react-node-content">
172+
{component.getReactComponents(shapeStatus, data, true)}
173+
</div>
174+
</DataContext.Provider>
175+
</ShapeContext.Provider>
176+
</FormContext.Provider>
177+
</div>
178+
</DispatchContext.Provider>
179+
</Form>
180+
</div>,
181+
document.getElementById('elsa-graph'),
182+
)}
183+
</>
184+
);
120185
});
121186

122187
DefaultRoot.propTypes = {
123-
shape: PropTypes.object,
124-
component: PropTypes.object,
125-
shapeStatus: PropTypes.object
188+
shape: PropTypes.object,
189+
component: PropTypes.object,
190+
shapeStatus: PropTypes.object,
126191
};
127192

128193
export function useDataContext() {
129-
return useContext(DataContext);
194+
return useContext(DataContext);
130195
}
131196

132197
export function useShapeContext() {
133-
return useContext(ShapeContext);
198+
return useContext(ShapeContext);
134199
}
135200

136201
export function useDispatch() {
137-
return useContext(DispatchContext);
202+
return useContext(DispatchContext);
138203
}
139204

140205
export function useFormContext() {
141-
return useContext(FormContext);
142-
}
206+
return useContext(FormContext);
207+
}

framework/elsa/fit-elsa-react/src/components/base/jadeNode.jsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export const jadeNode = (id, x, y, width, height, parent, drawer) => {
7676
self.referenceDisabled = false;
7777
self.statusManager = statusManager(self);
7878
self.isActiveInFlow = false;
79+
self.allowConfig = true;
7980

8081
overrideMethods(self);
8182
referenceDecorate(self);
@@ -488,5 +489,17 @@ export const jadeNode = (id, x, y, width, height, parent, drawer) => {
488489
self.invalidateAlone();
489490
};
490491

492+
/**
493+
* @override
494+
*/
495+
const select = self.select;
496+
self.select = (xVal, yVal) => {
497+
select.apply(self, [xVal, yVal]);
498+
const focusedShapes = self.page.getFocusedShapes();
499+
if (focusedShapes.length === 1 && focusedShapes.includes(self)) {
500+
self.page.onConfigShape = self.allowConfig ? self.id : undefined;
501+
}
502+
};
503+
491504
return self;
492505
};

framework/elsa/fit-elsa-react/src/components/common/style.css

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,4 +687,40 @@
687687

688688
.intelligent-form-right-select .ant-select-selector{
689689
border-radius: 0 8px 8px 0 !important;
690-
}
690+
}
691+
.jade-form-drawer {
692+
position: absolute;
693+
top: 100px;
694+
right: 30px;
695+
width: 360px;
696+
height: calc(100% - 110px);
697+
background-color: #ffffff;
698+
z-index: 999;
699+
padding: 0;
700+
box-sizing: border-box;
701+
border: 1px solid rgb(230, 230, 230);
702+
border-radius: 12px;
703+
overflow: auto;
704+
}
705+
.jade-form-drawer-content {
706+
padding: 0 16px 16px 16px;
707+
}
708+
.jade-form-drawer .jade-form-drawer-close {
709+
position: absolute;
710+
top: 16px;
711+
right: 25px;
712+
cursor: pointer;
713+
}
714+
.jade-form-drawer .jade-menus {
715+
margin-right: 50px;
716+
}
717+
.jade-form-drawer.hidden {
718+
display: none;
719+
}
720+
.sticky-header {
721+
padding: 16px 16px 0 16px;
722+
position: sticky;
723+
top: 0;
724+
z-index: 1000;
725+
background-color: white;
726+
}

0 commit comments

Comments
 (0)