chore: Update AddFlowVariable component to remove unnecessary code in parameter management (#1948)

This commit is contained in:
Dreammy23 2024-09-03 17:32:20 +08:00 committed by GitHub
commit 7661de8602
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 185 additions and 102 deletions

View File

@ -1,78 +1,115 @@
import { apiInterceptors, getFlowNodes } from '@/client/api';
import { IFlowNode } from '@/types/flow';
import { FLOW_NODES_KEY } from '@/utils';
// import { IFlowNode } from '@/types/flow';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, Form, Input, Modal } from 'antd';
import React, { useEffect, useState } from 'react';
import { Button, Form, Input, Modal, Select, Space } from 'antd';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
type GroupType = { category: string; categoryLabel: string; nodes: IFlowNode[] };
// ype GroupType = { category: string; categoryLabel: string; nodes: IFlowNode[] };
type ValueType = 'str' | 'int' | 'float' | 'bool' | 'ref';
const { Option } = Select;
const DAG_PARAM_KEY = 'dbgpt.core.flow.params';
const DAG_PARAM_SCOPE = 'flow_priv';
const AddFlowVariable: React.FC = () => {
const { t } = useTranslation();
const [operators, setOperators] = useState<Array<IFlowNode>>([]);
const [resources, setResources] = useState<Array<IFlowNode>>([]);
const [operatorsGroup, setOperatorsGroup] = useState<GroupType[]>([]);
const [resourcesGroup, setResourcesGroup] = useState<GroupType[]>([]);
// const [operators, setOperators] = useState<Array<IFlowNode>>([]);
// const [resources, setResources] = useState<Array<IFlowNode>>([]);
// const [operatorsGroup, setOperatorsGroup] = useState<GroupType[]>([]);
// const [resourcesGroup, setResourcesGroup] = useState<GroupType[]>([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [form] = Form.useForm(); // const [form] = Form.useForm<IFlowUpdateParam>();
const showModal = () => {
setIsModalOpen(true);
};
useEffect(() => {
getNodes();
}, []);
// TODO: get keys
// useEffect(() => {
// getNodes();
// }, []);
async function getNodes() {
const [_, data] = await apiInterceptors(getFlowNodes());
if (data && data.length > 0) {
localStorage.setItem(FLOW_NODES_KEY, JSON.stringify(data));
const operatorNodes = data.filter(node => node.flow_type === 'operator');
const resourceNodes = data.filter(node => node.flow_type === 'resource');
setOperators(operatorNodes);
setResources(resourceNodes);
setOperatorsGroup(groupNodes(operatorNodes));
setResourcesGroup(groupNodes(resourceNodes));
}
}
// async function getNodes() {
// const [_, data] = await apiInterceptors(getFlowNodes());
// if (data && data.length > 0) {
// localStorage.setItem(FLOW_NODES_KEY, JSON.stringify(data));
// const operatorNodes = data.filter(node => node.flow_type === 'operator');
// const resourceNodes = data.filter(node => node.flow_type === 'resource');
// setOperators(operatorNodes);
// setResources(resourceNodes);
// setOperatorsGroup(groupNodes(operatorNodes));
// setResourcesGroup(groupNodes(resourceNodes));
// }
// }
function groupNodes(data: IFlowNode[]) {
const groups: GroupType[] = [];
const categoryMap: Record<string, { category: string; categoryLabel: string; nodes: IFlowNode[] }> = {};
data.forEach(item => {
const { category, category_label } = item;
if (!categoryMap[category]) {
categoryMap[category] = { category, categoryLabel: category_label, nodes: [] };
groups.push(categoryMap[category]);
}
categoryMap[category].nodes.push(item);
});
return groups;
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 20 },
},
};
const formItemLayoutWithOutLabel = {
wrapperCol: {
xs: { span: 24, offset: 0 },
sm: { span: 20, offset: 2 },
},
};
// function groupNodes(data: IFlowNode[]) {
// const groups: GroupType[] = [];
// const categoryMap: Record<string, { category: string; categoryLabel: string; nodes: IFlowNode[] }> = {};
// data.forEach(item => {
// const { category, category_label } = item;
// if (!categoryMap[category]) {
// categoryMap[category] = { category, categoryLabel: category_label, nodes: [] };
// groups.push(categoryMap[category]);
// }
// categoryMap[category].nodes.push(item);
// });
// return groups;
// }
const onFinish = (values: any) => {
console.log('Received values of form:', values);
};
function onNameChange(e: React.ChangeEvent<HTMLInputElement>, index: number) {
const name = e.target.value;
const result = name
?.split('_')
?.map(word => word.charAt(0).toUpperCase() + word.slice(1))
?.join(' ');
form.setFields([
{
name: ['parameters', index, 'label'],
value: result,
},
]);
// change value to ref
const type = form.getFieldValue(['parameters', index, 'value_type']);
if (type === 'ref') {
const parameters = form.getFieldValue('parameters');
const param = parameters?.[index];
if (param) {
const { name = '' } = param;
param.value = `${DAG_PARAM_KEY}:${name}@scope:${DAG_PARAM_SCOPE}`;
form.setFieldsValue({
parameters: [...parameters],
});
}
}
}
function onValueTypeChange(type: ValueType, index: number) {
if (type === 'ref') {
const parameters = form.getFieldValue('parameters');
const param = parameters?.[index];
if (param) {
const { name = '' } = param;
param.value = `${DAG_PARAM_KEY}:${name}@scope:${DAG_PARAM_SCOPE}`;
form.setFieldsValue({
parameters: [...parameters],
});
}
}
}
return (
<>
<Button
@ -83,64 +120,111 @@ const AddFlowVariable: React.FC = () => {
onClick={showModal}
/>
<Modal title={t('Add_Global_Variable_of_Flow')} open={isModalOpen} footer={null}>
<Form name='dynamic_form_item' {...formItemLayoutWithOutLabel} onFinish={onFinish} className='mt-8'>
<Form.List
name='names'
rules={[
{
validator: async (_, names) => {
if (!names || names.length < 2) {
return Promise.reject(new Error('At least 2 passengers'));
}
},
},
]}
>
{(fields, { add, remove }, { errors }) => (
<Modal
title={t('Add_Global_Variable_of_Flow')}
open={isModalOpen}
footer={null}
width={1000}
styles={{
body: {
maxHeight: '70vh',
overflow: 'scroll',
backgroundColor: 'rgba(0,0,0,0.02)',
padding: '0 8px',
borderRadius: 4,
},
}}
onClose={() => setIsModalOpen(false)}
>
<Form
name='dynamic_form_nest_item'
onFinish={onFinish}
form={form}
autoComplete='off'
layout='vertical'
className='mt-8'
initialValues={{ parameters: [{}] }}
>
<Form.List name='parameters'>
{(fields, { add, remove }) => (
<>
{fields.map((field, index) => (
<Form.Item
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
label={index === 0 ? 'Passengers' : ''}
required={false}
key={field.key}
>
{fields.map(({ key, name, ...restField }, index) => (
<Space key={key} style={{ display: 'flex', marginBottom: 8 }} align='baseline'>
<Form.Item
{...field}
validateTrigger={['onChange', 'onBlur']}
{...restField}
name={[name, 'name']}
label={`参数 ${index + 1} 名称`}
style={{ width: 140 }}
rules={[
{ required: true, message: 'Missing parameter name' },
{
required: true,
whitespace: true,
message: "Please input passenger's name or delete this field.",
pattern: /^[a-zA-Z0-9]+(_[a-zA-Z0-9]+)*$/,
message: '名称必须是字母、数字或下划线,并使用下划线分隔多个单词',
},
]}
noStyle
>
<Input placeholder='passenger name' style={{ width: '60%' }} />
<Input placeholder='Parameter Name' onChange={e => onNameChange(e, index)} />
</Form.Item>
{fields.length > 1 ? (
<MinusCircleOutlined className='dynamic-delete-button' onClick={() => remove(field.name)} />
) : null}
</Form.Item>
<Form.Item
{...restField}
name={[name, 'label']}
label='标题'
style={{ width: 130 }}
rules={[{ required: true, message: 'Missing parameter label' }]}
>
<Input placeholder='Parameter Label' />
</Form.Item>
<Form.Item
{...restField}
name={[name, 'value_type']}
label='类型'
style={{ width: 100 }}
rules={[{ required: true, message: 'Missing parameter type' }]}
>
<Select placeholder='Select' onChange={value => onValueTypeChange(value, index)}>
{['str', 'int', 'float', 'bool', 'ref'].map(type => (
<Option key={type} value={type}>
{type}
</Option>
))}
</Select>
</Form.Item>
<Form.Item
{...restField}
name={[name, 'value']}
label='值'
style={{ width: 320 }}
rules={[{ required: true, message: 'Missing parameter value' }]}
>
<Input placeholder='Parameter Value' />
</Form.Item>
<Form.Item {...restField} name={[name, 'description']} label='描述' style={{ width: 170 }}>
<Input placeholder='Parameter Description' />
</Form.Item>
<MinusCircleOutlined onClick={() => remove(name)} />
</Space>
))}
<Form.Item>
<Button type='dashed' onClick={() => add()} className='w-full' icon={<PlusOutlined />}>
Add field
<Button type='dashed' onClick={() => add()} block icon={<PlusOutlined />}>
{t('Add_Parameter')}
</Button>
<Form.ErrorList errors={errors} />
</Form.Item>
</>
)}
</Form.List>
<Form.Item wrapperCol={{ offset: 18, span: 8 }}>
<Button type='primary' htmlType='submit'>
Submit
</Button>
<Form.Item wrapperCol={{ offset: 20, span: 4 }}>
<Space>
<Button onClick={() => setIsModalOpen(false)}>{t('cancel')}</Button>
<Button type='primary' htmlType='submit'>
{t('verify')}
</Button>
</Space>
</Form.Item>
</Form>
</Modal>

View File

@ -43,7 +43,6 @@ export const ExportFlowModal: React.FC<Props> = ({
return (
<>
<Modal
centered
title={t('Export_Flow')}
open={isExportFlowModalOpen}
onCancel={() => setIsExportFlowModalOpen(false)}

View File

@ -61,7 +61,6 @@ export const ImportFlowModal: React.FC<Props> = ({ isImportModalOpen, setIsImpor
return (
<>
<Modal
centered
title={t('Import_Flow')}
open={isImportModalOpen}
onCancel={() => setIsImportFlowModalOpen(false)}

View File

@ -89,7 +89,6 @@ export const SaveFlowModal: React.FC<Props> = ({
return (
<>
<Modal
centered
title={t('flow_modal_title')}
open={isSaveFlowModalOpen}
onCancel={() => {
@ -142,7 +141,7 @@ export const SaveFlowModal: React.FC<Props> = ({
<TextArea rows={3} />
</Form.Item>
<Form.Item label='Editable' name='editable' initialValue={flowInfo?.editable} valuePropName='checked'>
<Form.Item label='Editable' name='editable' initialValue={flowInfo?.editable || true} valuePropName='checked'>
<Checkbox />
</Form.Item>

View File

@ -18,4 +18,5 @@ export const FlowEn = {
No: 'No',
Please_Add_Nodes_First: 'Please add nodes first',
Add_Global_Variable_of_Flow: 'Add global variable of flow',
Add_Parameter: 'Add Parameter',
};

View File

@ -18,4 +18,5 @@ export const FlowZn = {
No: '否',
Please_Add_Nodes_First: '请先添加节点',
Add_Global_Variable_of_Flow: '添加 Flow 全局变量',
Add_Parameter: '添加参数',
};