|
|
|
@@ -5,22 +5,25 @@ import { to } from '@/utils/promise'; |
|
|
|
import { Button, Drawer, Form, Input, Select } from 'antd'; |
|
|
|
import { pick } from 'lodash'; |
|
|
|
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; |
|
|
|
import PropsLabel from '../components/PropsLabel'; |
|
|
|
import ResourceSelectorModal, { ResourceSelectorType } from '../components/ResourceSelectorModal'; |
|
|
|
import Styles from './editPipeline.less'; |
|
|
|
import { createMenuItems } from './utils'; |
|
|
|
const { TextArea } = Input; |
|
|
|
|
|
|
|
const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
const [form] = Form.useForm(); |
|
|
|
|
|
|
|
const [stagingItem, setStagingItem] = useState({}); |
|
|
|
const [open, setOpen] = useState(false); |
|
|
|
const [selectedModel, setSelectedModel] = useState(undefined); |
|
|
|
const [selectedDataset, setSelectedDataset] = useState(undefined); |
|
|
|
const [resourceStandardList, setResourceStandardList] = useState([]); |
|
|
|
|
|
|
|
const [selectedModel, setSelectedModel] = useState(undefined); // 选择的模型,为了再次打开时恢复原来的选择 |
|
|
|
const [selectedDataset, setSelectedDataset] = useState(undefined); // 选择的数据集,为了再次打开时恢复原来的选择 |
|
|
|
const [resourceStandardList, setResourceStandardList] = useState([]); // 资源规模列表 |
|
|
|
const [items, setItems] = useState([]); |
|
|
|
useEffect(() => { |
|
|
|
getComputingResource(); |
|
|
|
}, []); |
|
|
|
|
|
|
|
// 获取资源规格列表数据 |
|
|
|
const getComputingResource = async () => { |
|
|
|
const params = { |
|
|
|
page: 0, |
|
|
|
@@ -35,49 +38,22 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
|
|
|
|
const afterOpenChange = () => { |
|
|
|
if (!open) { |
|
|
|
console.log(stagingItem, form.getFieldsValue()); |
|
|
|
// 禁止校验 guard-for-in |
|
|
|
/* eslint-disable */ |
|
|
|
for (let i in form.getFieldsValue()) { |
|
|
|
for (let j in stagingItem.in_parameters) { |
|
|
|
if (i == j) { |
|
|
|
console.log(j, i); |
|
|
|
stagingItem.in_parameters[j].value = form.getFieldsValue()[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
for (let p in stagingItem.out_parameters) { |
|
|
|
if (i == p) { |
|
|
|
stagingItem.out_parameters[p].value = form.getFieldsValue()[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
for (let k in stagingItem.control_strategy) { |
|
|
|
if (i == k) { |
|
|
|
stagingItem.control_strategy[k].value = form.getFieldsValue()[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
/* eslint-enable */ |
|
|
|
// setStagingItem({...stagingItem,}) |
|
|
|
console.log(stagingItem.control_strategy); |
|
|
|
// console.log('zzzz', stagingItem, form.getFieldsValue()); |
|
|
|
const control_strategy = form.getFieldValue('control_strategy'); |
|
|
|
const in_parameters = form.getFieldValue('in_parameters'); |
|
|
|
const out_parameters = form.getFieldValue('out_parameters'); |
|
|
|
onParentChange({ |
|
|
|
...stagingItem, |
|
|
|
control_strategy: JSON.stringify(stagingItem.control_strategy), |
|
|
|
in_parameters: JSON.stringify(stagingItem.in_parameters), |
|
|
|
out_parameters: JSON.stringify(stagingItem.out_parameters), |
|
|
|
...form.getFieldsValue(), |
|
|
|
control_strategy: JSON.stringify(control_strategy), |
|
|
|
in_parameters: JSON.stringify(in_parameters), |
|
|
|
out_parameters: JSON.stringify(out_parameters), |
|
|
|
}); |
|
|
|
// onParentChange({...stagingItem,...form.getFieldsValue()}) |
|
|
|
} |
|
|
|
}; |
|
|
|
const onClose = () => { |
|
|
|
setOpen(false); |
|
|
|
}; |
|
|
|
const onFinish = (values) => { |
|
|
|
console.log('Success:', values); |
|
|
|
}; |
|
|
|
const onFinishFailed = (errorInfo) => { |
|
|
|
console.log('Failed:', errorInfo); |
|
|
|
}; |
|
|
|
useImperativeHandle(ref, () => ({ |
|
|
|
getFieldsValue: async () => { |
|
|
|
const [propsRes, propsError] = await to(form.validateFields()); |
|
|
|
@@ -88,30 +64,27 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
return Promise.reject(propsError); |
|
|
|
} |
|
|
|
}, |
|
|
|
showDrawer(e) { |
|
|
|
showDrawer(e, params, parentNodes) { |
|
|
|
if (e.item && e.item.getModel()) { |
|
|
|
// console.log(e.item.getModel().in_parameters); |
|
|
|
form.resetFields(); |
|
|
|
form.setFieldsValue({ |
|
|
|
...e.item.getModel(), |
|
|
|
in_parameters: JSON.parse(e.item.getModel().in_parameters), |
|
|
|
out_parameters: JSON.parse(e.item.getModel().out_parameters), |
|
|
|
control_strategy: JSON.parse(e.item.getModel().control_strategy), |
|
|
|
}); |
|
|
|
const model = e.item.getModel(); |
|
|
|
const nodeData = { |
|
|
|
...model, |
|
|
|
in_parameters: JSON.parse(model.in_parameters), |
|
|
|
out_parameters: JSON.parse(model.out_parameters), |
|
|
|
control_strategy: JSON.parse(model.control_strategy), |
|
|
|
}; |
|
|
|
setStagingItem({ |
|
|
|
...e.item.getModel(), |
|
|
|
in_parameters: JSON.parse(e.item.getModel().in_parameters), |
|
|
|
out_parameters: JSON.parse(e.item.getModel().out_parameters), |
|
|
|
control_strategy: JSON.parse(e.item.getModel().control_strategy), |
|
|
|
...nodeData, |
|
|
|
}); |
|
|
|
form.setFieldsValue({ |
|
|
|
...nodeData, |
|
|
|
}); |
|
|
|
// form.setFieldsValue({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters)}) |
|
|
|
// setStagingItem({...e.item.getModel(),in_parameters:JSON.parse(e.item.getModel().in_parameters),out_parameters:JSON.parse(e.item.getModel().out_parameters)}) |
|
|
|
// setTimeout(() => { |
|
|
|
// console.log(stagingItem); |
|
|
|
// }, (500)); |
|
|
|
setSelectedModel(undefined); |
|
|
|
setSelectedDataset(undefined); |
|
|
|
setOpen(true); |
|
|
|
|
|
|
|
setItems(createMenuItems(params, parentNodes)); |
|
|
|
} |
|
|
|
}, |
|
|
|
propClose: async () => { |
|
|
|
@@ -119,16 +92,12 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
const [openRes, propsError] = await to(setOpen(false)); |
|
|
|
console.log(setOpen(false)); |
|
|
|
}, |
|
|
|
// propClose() { |
|
|
|
|
|
|
|
// setOpen(false); |
|
|
|
// }, |
|
|
|
})); |
|
|
|
|
|
|
|
// 选择数据集、模型 |
|
|
|
const selectResource = (name, item) => { |
|
|
|
let type; |
|
|
|
let resource = undefined; |
|
|
|
let resource; |
|
|
|
switch (item.item_type) { |
|
|
|
case 'dataset': |
|
|
|
type = ResourceSelectorType.Dataset; |
|
|
|
@@ -154,7 +123,7 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
} else { |
|
|
|
const jsonObj = pick(res, ['id', 'version', 'path']); |
|
|
|
const value = JSON.stringify(jsonObj); |
|
|
|
form.setFieldValue(name, value); |
|
|
|
form.setFieldValue(name, { ...item, value }); |
|
|
|
} |
|
|
|
|
|
|
|
if (type === ResourceSelectorType.Dataset) { |
|
|
|
@@ -187,16 +156,26 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 筛选资源规格 |
|
|
|
const filterResourceStandard = (input, { computing_resource = '' }) => { |
|
|
|
return computing_resource.toLocaleLowerCase().includes(input.toLocaleLowerCase()); |
|
|
|
}; |
|
|
|
|
|
|
|
// 控制策略 |
|
|
|
const controlStrategy = stagingItem.control_strategy; |
|
|
|
const controlStrategyList = Object.entries(stagingItem.control_strategy ?? {}).map( |
|
|
|
([key, value]) => ({ key, value }), |
|
|
|
); |
|
|
|
|
|
|
|
// 输入参数 |
|
|
|
const inParameters = stagingItem.in_parameters; |
|
|
|
const inParametersList = Object.entries(stagingItem.in_parameters ?? {}).map(([key, value]) => ({ |
|
|
|
key, |
|
|
|
value, |
|
|
|
})); |
|
|
|
|
|
|
|
// 输出参数 |
|
|
|
const outParameters = stagingItem.out_parameters; |
|
|
|
const outParametersList = Object.entries(stagingItem.out_parameters ?? {}).map( |
|
|
|
([key, value]) => ({ key, value }), |
|
|
|
); |
|
|
|
|
|
|
|
return ( |
|
|
|
<> |
|
|
|
@@ -209,15 +188,15 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
onClose={onClose} |
|
|
|
afterOpenChange={afterOpenChange} |
|
|
|
open={open} |
|
|
|
width={420} |
|
|
|
width={520} |
|
|
|
className={Styles.editPipelineProps} |
|
|
|
> |
|
|
|
<Form |
|
|
|
name="form" |
|
|
|
form={form} |
|
|
|
// layout="vertical" |
|
|
|
layout="vertical" |
|
|
|
labelCol={{ |
|
|
|
span: 16, |
|
|
|
span: 24, |
|
|
|
}} |
|
|
|
wrapperCol={{ |
|
|
|
span: 24, |
|
|
|
@@ -225,11 +204,6 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
style={{ |
|
|
|
maxWidth: 600, |
|
|
|
}} |
|
|
|
initialValues={{ |
|
|
|
remember: true, |
|
|
|
}} |
|
|
|
onFinish={onFinish} |
|
|
|
onFinishFailed={onFinishFailed} |
|
|
|
autoComplete="off" |
|
|
|
> |
|
|
|
<div className={Styles.editPipelinePropsContent}> |
|
|
|
@@ -250,7 +224,7 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
}, |
|
|
|
]} |
|
|
|
> |
|
|
|
<Input /> |
|
|
|
<Input placeholder="请输入任务名称" allowClear /> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item |
|
|
|
label="任务ID" |
|
|
|
@@ -275,7 +249,7 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
<Form.Item label="镜像" required> |
|
|
|
<div className={Styles['ref-row']}> |
|
|
|
<Form.Item name="image" noStyle rules={[{ required: true, message: '请输入镜像' }]}> |
|
|
|
<Input placeholder="请输入镜像" allowClear /> |
|
|
|
<Input placeholder="请输入或选择镜像" allowClear /> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item noStyle> |
|
|
|
<Button |
|
|
|
@@ -289,12 +263,33 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
</Form.Item> |
|
|
|
</div> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item label="工作目录" name="working_directory"> |
|
|
|
<Input /> |
|
|
|
<Form.Item |
|
|
|
name="working_directory" |
|
|
|
label={ |
|
|
|
<PropsLabel |
|
|
|
menuItems={items} |
|
|
|
title="工作目录" |
|
|
|
onClick={(value) => { |
|
|
|
form.setFieldValue('working_directory', value); |
|
|
|
}} |
|
|
|
/> |
|
|
|
} |
|
|
|
> |
|
|
|
<Input placeholder="请输入工作目录" allowClear /> |
|
|
|
</Form.Item> |
|
|
|
|
|
|
|
<Form.Item label="启动命令" name="command"> |
|
|
|
<TextArea /> |
|
|
|
<Form.Item |
|
|
|
name="command" |
|
|
|
label={ |
|
|
|
<PropsLabel |
|
|
|
menuItems={items} |
|
|
|
title="工作目录" |
|
|
|
onClick={(value) => { |
|
|
|
form.setFieldValue('command', value); |
|
|
|
}} |
|
|
|
/> |
|
|
|
} |
|
|
|
> |
|
|
|
<TextArea placeholder="请输入启动命令" allowClear /> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item |
|
|
|
label="资源规格" |
|
|
|
@@ -317,19 +312,63 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
}} |
|
|
|
/> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item label="挂载路径" name="mount_path"> |
|
|
|
<Input /> |
|
|
|
<Form.Item |
|
|
|
name="mount_path" |
|
|
|
label={ |
|
|
|
<PropsLabel |
|
|
|
menuItems={items} |
|
|
|
title="挂载路径" |
|
|
|
onClick={(value) => { |
|
|
|
form.setFieldValue('mount_path', value); |
|
|
|
}} |
|
|
|
/> |
|
|
|
} |
|
|
|
> |
|
|
|
<Input placeholder="请输入挂载路径" allowClear /> |
|
|
|
</Form.Item> |
|
|
|
<Form.Item label="环境变量" name="env_variables"> |
|
|
|
<TextArea /> |
|
|
|
<Form.Item |
|
|
|
name="env_variables" |
|
|
|
label={ |
|
|
|
<PropsLabel |
|
|
|
menuItems={items} |
|
|
|
title="环境变量" |
|
|
|
onClick={(value) => { |
|
|
|
form.setFieldValue('env_variables', value); |
|
|
|
}} |
|
|
|
/> |
|
|
|
} |
|
|
|
> |
|
|
|
<TextArea placeholder="请输入环境变量" allowClear /> |
|
|
|
</Form.Item> |
|
|
|
{controlStrategy && Object.keys(controlStrategy).length > 0 |
|
|
|
? Object.keys(controlStrategy).map((item) => ( |
|
|
|
<Form.Item key={item} label={controlStrategy[item].label} name={item}> |
|
|
|
<Input /> |
|
|
|
</Form.Item> |
|
|
|
)) |
|
|
|
: ''} |
|
|
|
{controlStrategyList.map((item) => ( |
|
|
|
<Form.Item |
|
|
|
key={item.key} |
|
|
|
name={['control_strategy', item.key]} |
|
|
|
label={ |
|
|
|
<PropsLabel |
|
|
|
menuItems={items} |
|
|
|
title={item.value.label} |
|
|
|
onClick={(value) => { |
|
|
|
form.setFieldValue(['control_strategy', item.key], { |
|
|
|
...item.value, |
|
|
|
value, |
|
|
|
}); |
|
|
|
}} |
|
|
|
/> |
|
|
|
} |
|
|
|
getValueProps={(e) => { |
|
|
|
return { value: e.value }; |
|
|
|
}} |
|
|
|
getValueFromEvent={(e) => { |
|
|
|
return { |
|
|
|
...item.value, |
|
|
|
value: e.target.value, |
|
|
|
}; |
|
|
|
}} |
|
|
|
> |
|
|
|
<Input placeholder={item.value.label} allowClear /> |
|
|
|
</Form.Item> |
|
|
|
))} |
|
|
|
<div className={Styles.editPipelinePropsContent}> |
|
|
|
<img |
|
|
|
style={{ width: '15px', marginRight: '10px' }} |
|
|
|
@@ -338,37 +377,55 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
/> |
|
|
|
输入参数 |
|
|
|
</div> |
|
|
|
{inParameters && Object.keys(inParameters).length > 0 |
|
|
|
? Object.keys(inParameters).map((item) => ( |
|
|
|
{inParametersList.map((item) => ( |
|
|
|
<Form.Item |
|
|
|
key={item.key} |
|
|
|
label={ |
|
|
|
<PropsLabel |
|
|
|
menuItems={items} |
|
|
|
title={item.value.label + '(' + item.key + ')'} |
|
|
|
onClick={(value) => { |
|
|
|
form.setFieldValue(['in_parameters', item.key], { |
|
|
|
...item.value, |
|
|
|
value, |
|
|
|
}); |
|
|
|
}} |
|
|
|
/> |
|
|
|
} |
|
|
|
required={item.value.require ? true : false} |
|
|
|
> |
|
|
|
<div className={Styles['ref-row']}> |
|
|
|
<Form.Item |
|
|
|
key={item} |
|
|
|
label={inParameters[item].label + '(' + item + ')'} |
|
|
|
required={inParameters[item].require ? true : false} |
|
|
|
name={['in_parameters', item.key]} |
|
|
|
noStyle |
|
|
|
rules={[{ required: item.value.require ? true : false }]} |
|
|
|
getValueProps={(e) => { |
|
|
|
return { value: e.value }; |
|
|
|
}} |
|
|
|
getValueFromEvent={(e) => { |
|
|
|
return { |
|
|
|
...item.value, |
|
|
|
value: e.target.value, |
|
|
|
}; |
|
|
|
}} |
|
|
|
> |
|
|
|
<div className={Styles['ref-row']}> |
|
|
|
<Form.Item |
|
|
|
name={item} |
|
|
|
noStyle |
|
|
|
rules={[{ required: inParameters[item].require ? true : false }]} |
|
|
|
> |
|
|
|
<Input /> |
|
|
|
</Form.Item> |
|
|
|
{inParameters[item].type === 'ref' && ( |
|
|
|
<Form.Item noStyle> |
|
|
|
<Button |
|
|
|
type="link" |
|
|
|
icon={getSelectBtnIcon(inParameters[item])} |
|
|
|
onClick={() => selectResource(item, inParameters[item])} |
|
|
|
className={Styles['select-button']} |
|
|
|
> |
|
|
|
{inParameters[item].label} |
|
|
|
</Button> |
|
|
|
</Form.Item> |
|
|
|
)} |
|
|
|
</div> |
|
|
|
<Input placeholder={item.value.label} allowClear /> |
|
|
|
</Form.Item> |
|
|
|
)) |
|
|
|
: ''} |
|
|
|
{item.value.type === 'ref' && ( |
|
|
|
<Form.Item noStyle> |
|
|
|
<Button |
|
|
|
type="link" |
|
|
|
icon={getSelectBtnIcon(item.value)} |
|
|
|
onClick={() => selectResource(['in_parameters', item.key], item.value)} |
|
|
|
className={Styles['select-button']} |
|
|
|
> |
|
|
|
{item.value.label} |
|
|
|
</Button> |
|
|
|
</Form.Item> |
|
|
|
)} |
|
|
|
</div> |
|
|
|
</Form.Item> |
|
|
|
))} |
|
|
|
<div className={Styles.editPipelinePropsContent}> |
|
|
|
<img |
|
|
|
style={{ width: '15px', marginRight: '10px' }} |
|
|
|
@@ -377,18 +434,36 @@ const Props = forwardRef(({ onParentChange }, ref) => { |
|
|
|
/> |
|
|
|
输出参数 |
|
|
|
</div> |
|
|
|
{outParameters && Object.keys(outParameters).length > 0 |
|
|
|
? Object.keys(outParameters).map((item) => ( |
|
|
|
<Form.Item |
|
|
|
key={item} |
|
|
|
label={outParameters[item].label + '(' + item + ')'} |
|
|
|
rules={[{ required: outParameters[item].require ? true : false }]} |
|
|
|
name={item} |
|
|
|
> |
|
|
|
<Input /> |
|
|
|
</Form.Item> |
|
|
|
)) |
|
|
|
: ''} |
|
|
|
{outParametersList.map((item) => ( |
|
|
|
<Form.Item |
|
|
|
key={item.key} |
|
|
|
name={['out_parameters', item.key]} |
|
|
|
label={ |
|
|
|
<PropsLabel |
|
|
|
menuItems={items} |
|
|
|
title={item.value.label + '(' + item.key + ')'} |
|
|
|
onClick={(value) => { |
|
|
|
form.setFieldValue(['out_parameters', item.key], { |
|
|
|
...item.value, |
|
|
|
value, |
|
|
|
}); |
|
|
|
}} |
|
|
|
/> |
|
|
|
} |
|
|
|
rules={[{ required: item.value.require ? true : false }]} |
|
|
|
getValueProps={(e) => { |
|
|
|
return { value: e.value }; |
|
|
|
}} |
|
|
|
getValueFromEvent={(e) => { |
|
|
|
return { |
|
|
|
...item.value, |
|
|
|
value: e.target.value, |
|
|
|
}; |
|
|
|
}} |
|
|
|
> |
|
|
|
<Input placeholder={item.value.label} allowClear /> |
|
|
|
</Form.Item> |
|
|
|
))} |
|
|
|
</Form> |
|
|
|
</Drawer> |
|
|
|
</> |
|
|
|
|