Skip to content

Commit 34f8a1f

Browse files
authored
[elsa] feat: modify interaction method for start node inputParams (#320)
1 parent d31703c commit 34f8a1f

File tree

5 files changed

+344
-48
lines changed

5 files changed

+344
-48
lines changed

framework/elsa/fit-elsa-react/src/App.jsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {Button} from 'antd';
1111
import {CodeDrawer} from '@/components/common/code/CodeDrawer.jsx';
1212
import 'antd/dist/antd.css';
1313
import {createGraphOperator} from '@/data/GraphOperator.js';
14+
import {v4 as uuidv4} from 'uuid';
1415

1516
function App({i18n}) {
1617
const [open, setOpen] = useState(false);
@@ -119,6 +120,42 @@ function App({i18n}) {
119120
},
120121
]);
121122
});
123+
agent.onAddInputParam(({ onAdd, existParam }) => {
124+
const mockParam = {
125+
id: 'input_' + uuidv4(),
126+
name: 'userAge',
127+
type: 'Boolean',
128+
value: '',
129+
displayName: 'test',
130+
isRequired: true,
131+
isVisible: true,
132+
disableModifiable: false,
133+
appearance: {},
134+
};
135+
136+
// 直接调用回调,模拟弹窗“确认”后的行为
137+
onAdd(mockParam);
138+
console.log(existParam);
139+
});
140+
141+
agent.onEditInputParam(({id, onEdit, selectedParam }) => {
142+
const mockParam = {
143+
id: id,
144+
name: 'userAge',
145+
type: 'String',
146+
value: '',
147+
displayName: 'test',
148+
isRequired: true,
149+
isVisible: true,
150+
disableModifiable: false,
151+
appearance: {},
152+
};
153+
154+
// 直接调用回调,模拟弹窗“确认”后的行为
155+
onEdit(mockParam);
156+
157+
console.log(selectedParam);
158+
});
122159
agent.listen('GENERATE_AI_PROMPT', (event) => {
123160
event.applyPrompt('123');
124161
});

framework/elsa/fit-elsa-react/src/components/start/StartFormWrapper.jsx

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

7-
import {useState} from 'react';
8-
import {Button, Collapse, Popover} from 'antd';
9-
import {PlusOutlined, QuestionCircleOutlined} from '@ant-design/icons';
7+
import React, {useEffect, useState} from 'react';
8+
import {Button, Collapse, Popover, Form} from 'antd';
9+
import {DeleteOutlined, EditOutlined, PlusOutlined, QuestionCircleOutlined} from '@ant-design/icons';
1010
import {StartInputForm} from './StartInputForm.jsx';
1111
import './style.css';
1212
import {useConfigContext, useDispatch, useShapeContext} from '@/components/DefaultRoot.jsx';
@@ -16,7 +16,6 @@ import PropTypes from 'prop-types';
1616
import {Trans, useTranslation} from 'react-i18next';
1717
import {AppConfiguration} from '@/components/start/AppConfiguration.jsx';
1818
import {JadeCollapse} from '@/components/common/JadeCollapse.jsx';
19-
import IconTrashBin from '../asserts/icon-delete-trash-bin.svg?react'; // 导入背景图片
2019

2120
const {Panel} = Collapse;
2221

@@ -51,6 +50,25 @@ export default function StartFormWrapper({data, shapeStatus}) {
5150
return isConfig ? items.map(item => item.id) : [];
5251
});
5352

53+
useEffect(() => {
54+
items.map(item => {
55+
shape.page.registerObservable({
56+
nodeId: shape.id,
57+
observableId: item.id,
58+
value: item.name,
59+
type: item.type,
60+
parentId: undefined,
61+
});
62+
})
63+
64+
// 组件unmount时,删除observable.
65+
return () => {
66+
items.map(item => {
67+
shape.page.removeObservable(shape.id, item.id);
68+
})
69+
};
70+
}, []);
71+
5472
// 添加新元素到 items 数组中,并将其 key 添加到当前展开的面板数组中
5573
const addItem = () => {
5674
// 开始节点入参最大数量为20
@@ -68,27 +86,37 @@ export default function StartFormWrapper({data, shapeStatus}) {
6886
?.config
6987
?.find(configItem => configItem.hasOwnProperty('allowAdd')); // 查找具有 "allowAdd" 属性的对象
7088
if (configObject ? configObject.allowAdd : false) {
89+
const inputParams = data.find(item => item.name === 'input')?.value;
7190
return (<>
7291
<Button disabled={shapeStatus.disabled}
7392
type="text"
7493
className="icon-button jade-start-add-icon"
75-
onClick={addItem}>
94+
onClick={(event) => {
95+
triggerAddInput(event, inputParams);
96+
}}>
7697
<PlusOutlined/>
7798
</Button>
7899
</>);
79100
}
80101
return null;
81102
};
82103

83-
const renderDeleteIcon = (item) => {
104+
const renderIcons = (item) => {
84105
if (!item.disableModifiable) {
85106
return (<>
107+
<Button
108+
disabled={shape.status.disabled}
109+
type="text"
110+
className="icon-button start-node-edit-icon-button"
111+
onClick={(event) =>triggerEditInput(event, item.id, item)}>
112+
<EditOutlined/>
113+
</Button>
86114
<Button
87115
disabled={shapeStatus.disabled}
88116
type="text"
89117
className="icon-button start-node-delete-icon-button"
90118
onClick={() => handleDelete(item.id)}>
91-
<IconTrashBin/>
119+
<DeleteOutlined/>
92120
</Button>
93121
</>);
94122
}
@@ -99,6 +127,7 @@ export default function StartFormWrapper({data, shapeStatus}) {
99127
const updatedOpenItems = openItems.filter((key) => key !== itemId);
100128
setOpenItems(updatedOpenItems);
101129
dispatch({actionType: 'deleteInputParam', id: itemId});
130+
shape.page.removeObservable(shape.id, itemId)
102131
};
103132

104133
const content = (<div className={'jade-font-size'} style={{lineHeight: '1.2'}}>
@@ -128,50 +157,117 @@ export default function StartFormWrapper({data, shapeStatus}) {
128157
dispatch({actionType: 'changeMemorySwitch', value: e});
129158
};
130159

160+
/**
161+
* 添加增加开始节点自定义参数的回调函数
162+
*
163+
* @param event 事件
164+
*/
165+
const triggerAddInput = (event, existParam) => {
166+
event.preventDefault();
167+
shape.page.triggerEvent({
168+
type: 'ADD_START_INPUT',
169+
value: {
170+
existParam: items,
171+
onAdd: (param) => {
172+
dispatch({
173+
actionType: 'addParam',
174+
value: param,
175+
});
176+
shape.page.registerObservable({
177+
nodeId: shape.id,
178+
observableId: param.id,
179+
value: param.name,
180+
type: param.type,
181+
parentId: undefined
182+
});
183+
184+
if (isConfig) {
185+
setOpenItems(prev => [...prev, param.id]);
186+
}
187+
},
188+
},
189+
});
190+
event.stopPropagation();
191+
};
192+
193+
/**
194+
* 添加修改开始节点自定义参数的回调函数
195+
*
196+
* @param event 事件
197+
*/
198+
const triggerEditInput = (event, id, selectedParam) => {
199+
event.preventDefault();
200+
shape.page.triggerEvent({
201+
type: 'EDIT_START_INPUT',
202+
value: {
203+
id: id,
204+
selectedParam: selectedParam,
205+
onEdit: (param) => {
206+
dispatch({
207+
actionType: 'editParam',
208+
value: param,
209+
id: id,
210+
});
211+
shape.emit(id, {type: param.type, value: param.name});
212+
},
213+
},
214+
});
215+
event.stopPropagation();
216+
};
217+
218+
131219
return (<>
132220
<div>
133-
<div style={{
134-
display: 'flex',
135-
alignItems: 'center',
136-
marginBottom: '8px',
137-
paddingLeft: '8px',
138-
paddingRight: '4px',
139-
height: '32px',
140-
}}>
141-
<div className="jade-panel-header-font">{t('input')}</div>
142-
<Popover
143-
content={content}
144-
align={{offset: [0, 3]}}
145-
overlayClassName={'jade-custom-popover'}
146-
>
147-
<QuestionCircleOutlined className="jade-panel-header-popover-content"/>
148-
</Popover>
149-
{renderAddInputIcon()}
150-
</div>
151221
<JadeCollapse
152-
activeKey={openItems}
153-
onChange={(keys) => setOpenItems(keys)}
154-
style={{backgroundColor: 'transparent'}}>
155-
{
156-
items.map((item) => (
157-
<Panel
158-
key={item.id}
159-
header={
160-
<div className="panel-header">
161-
<span className="jade-panel-header-font">{item.name}</span> {/* 显示Name值的元素 */}
162-
{renderDeleteIcon(item)}
163-
</div>
164-
}
165-
className="jade-panel"
166-
style={{marginBottom: 8, borderRadius: '8px', width: '100%'}}
167-
forceRender
222+
defaultActiveKey={["startInput"]}
223+
>
224+
<Panel
225+
key={"startInput"}
226+
header={
227+
<div style={{
228+
display: 'flex',
229+
alignItems: 'center',
230+
paddingRight: '4px',
231+
height: '32px',
232+
}}>
233+
<div className="jade-panel-header-font">{t('input')}</div>
234+
<Popover
235+
content={content}
236+
align={{offset: [0, 3]}}
237+
overlayClassName={'jade-custom-popover'}
168238
>
169-
<div className={'jade-custom-panel-content'}>
170-
<StartInputForm item={item} items={items}/>
171-
</div>
172-
</Panel>
173-
))
239+
<QuestionCircleOutlined className="jade-panel-header-popover-content"/>
240+
</Popover>
241+
{renderAddInputIcon()}
242+
</div>
174243
}
244+
className='jade-panel'
245+
>
246+
{items.map((item) => (
247+
<Form.Item
248+
className='jade-input-item'
249+
name={`input-${item.id}`}
250+
key={item.id}
251+
>
252+
<div className="param-item">
253+
<div className="param-row">
254+
<div className="param-left">
255+
<div className="param-name">{item.name}</div>
256+
<div className="param-display-name">{item.displayName}</div>
257+
</div>
258+
<div className="param-right">
259+
<div className="param-type-wrapper">
260+
<div className="param-type">{item.type}</div>
261+
</div>
262+
<div className="param-icons">
263+
{renderIcons(item)}
264+
</div>
265+
</div>
266+
</div>
267+
</div>
268+
</Form.Item>
269+
))}
270+
</Panel>
175271
</JadeCollapse>
176272

177273
<MultiConversation className="jade-multi-conversation"

framework/elsa/fit-elsa-react/src/components/start/startComponent.jsx

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ export const startComponent = (jadeConfig) => {
2525
name: 'Question',
2626
type: 'String',
2727
from: 'Input',
28-
description: '这是用户输入的问题',
2928
value: '',
3029
disableModifiable: true,
3130
isRequired: true,
@@ -101,6 +100,58 @@ export const startComponent = (jadeConfig) => {
101100
})
102101
};
103102

103+
const addParam = () => {
104+
let param = action.value;
105+
return data.map(item => {
106+
if (item.name === "input") {
107+
return {
108+
...item,
109+
value: [
110+
...item.value,
111+
{
112+
id: param.id,
113+
name: param.name,
114+
type: param.type,
115+
from: "Input",
116+
description: param.description,
117+
value: param.value,
118+
disableModifiable: param.disableModifiable,
119+
isRequired: param.isRequired,
120+
isVisible: param.isVisible,
121+
displayName: param.displayName,
122+
appearance: param.appearance,
123+
}
124+
]
125+
}
126+
} else {
127+
return item;
128+
}
129+
})
130+
};
131+
132+
const updateInputParamById = () => {
133+
const param = action.value;
134+
return data.map(item => {
135+
if (item.name === "input") {
136+
return {
137+
...item,
138+
value: item.value.map(p => {
139+
if (p.id === action.id) {
140+
return {
141+
...p,
142+
...param,
143+
};
144+
} else {
145+
return p;
146+
}
147+
})
148+
};
149+
} else {
150+
return item;
151+
}
152+
});
153+
};
154+
104155
const changeInputParam = () => {
105156
return data.map(item => {
106157
if (item.name === "input") {
@@ -196,6 +247,12 @@ export const startComponent = (jadeConfig) => {
196247
case 'changeInputParam': {
197248
return changeInputParam();
198249
}
250+
case 'addParam': {
251+
return addParam()
252+
}
253+
case 'editParam': {
254+
return updateInputParamById();
255+
}
199256
case 'changeMemory': {
200257
return changeMemory();
201258
}

0 commit comments

Comments
 (0)