Unverified Commit 5a2df799 authored by aiwenmo's avatar aiwenmo Committed by GitHub

[Optimization-627][web] Optimization page Form

[Optimization-627][web] Optimization page Form  
parents 610bfed2 bad99308
...@@ -60,7 +60,7 @@ const AlertGroupForm: React.FC<AlertGroupFormProps> = (props) => { ...@@ -60,7 +60,7 @@ const AlertGroupForm: React.FC<AlertGroupFormProps> = (props) => {
<> <>
<Form.Item <Form.Item
name="name" name="name"
label="标识" label="名称"
rules={[{required: true, message: '请输入名称!'}]}> rules={[{required: true, message: '请输入名称!'}]}>
<Input placeholder="请输入唯一英文标识"/> <Input placeholder="请输入唯一英文标识"/>
</Form.Item> </Form.Item>
......
...@@ -38,7 +38,7 @@ const ClusterForm: React.FC<ClusterFormProps> = (props) => { ...@@ -38,7 +38,7 @@ const ClusterForm: React.FC<ClusterFormProps> = (props) => {
const submitForm = async () => { const submitForm = async () => {
const fieldsValue = await form.validateFields(); const fieldsValue = await form.validateFields();
fieldsValue.id= formVals.id; fieldsValue.id = formVals.id;
setFormVals(fieldsValue); setFormVals(fieldsValue);
handleSubmit(fieldsValue); handleSubmit(fieldsValue);
}; };
...@@ -48,14 +48,14 @@ const ClusterForm: React.FC<ClusterFormProps> = (props) => { ...@@ -48,14 +48,14 @@ const ClusterForm: React.FC<ClusterFormProps> = (props) => {
<> <>
<Form.Item <Form.Item
name="name" name="name"
label="标识" label="名称"
rules={[{required: true, message: '请输入名称!'}]}> rules={[{required: true, message: '请输入名称!'}]}>
<Input placeholder="请输入唯一英文标识"/> <Input placeholder="请输入唯一英文标识"/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="alias" name="alias"
label="名称" label="别名"
> >
<Input placeholder="请输入名称"/> <Input placeholder="请输入名称"/>
</Form.Item> </Form.Item>
...@@ -75,6 +75,29 @@ const ClusterForm: React.FC<ClusterFormProps> = (props) => { ...@@ -75,6 +75,29 @@ const ClusterForm: React.FC<ClusterFormProps> = (props) => {
<Form.Item <Form.Item
name="hosts" name="hosts"
label="JobManager HA 地址" label="JobManager HA 地址"
validateTrigger={['onChange']}
rules={[
{
required: true,
validator(_, hostsValue) {
let hostArray = [];
if (hostsValue.trim().length === 0) {
return Promise.reject(new Error('请输入 JobManager HA 地址!'));
} else {
hostArray = hostsValue.split(',')
for (let i = 0; i < hostArray.length; i++) {
if (hostArray[i].includes('/')) {
return Promise.reject(new Error('不符合规则! 不能包含/'));
}
if (parseInt(hostArray[i].split(':')[1]) >= 65535) {
return Promise.reject(new Error('不符合规则! 端口号区间[0-65535]'));
}
}
return Promise.resolve();
}
},
},
]}
> >
<Input.TextArea <Input.TextArea
placeholder="添加 Flink 集群的 JobManager 的 RestApi 地址。当 HA 模式时,地址间用英文逗号分隔,例如:192.168.123.101:8081,192.168.123.102:8081,192.168.123.103:8081" placeholder="添加 Flink 集群的 JobManager 的 RestApi 地址。当 HA 模式时,地址间用英文逗号分隔,例如:192.168.123.101:8081,192.168.123.102:8081,192.168.123.103:8081"
...@@ -114,7 +137,7 @@ const ClusterForm: React.FC<ClusterFormProps> = (props) => { ...@@ -114,7 +137,7 @@ const ClusterForm: React.FC<ClusterFormProps> = (props) => {
width={640} width={640}
bodyStyle={{padding: '32px 40px 48px'}} bodyStyle={{padding: '32px 40px 48px'}}
destroyOnClose destroyOnClose
title={formVals.id?"修改集群":"创建集群"} title={formVals.id ? "修改集群" : "创建集群"}
visible={modalVisible} visible={modalVisible}
footer={renderFooter()} footer={renderFooter()}
onCancel={() => handleModalVisible()} onCancel={() => handleModalVisible()}
......
import React from 'react';
import { Modal } from 'antd';
type CreateFormProps = {
modalVisible: boolean;
onCancel: () => void;
};
const CreateForm: React.FC<CreateFormProps> = (props) => {
const { modalVisible, onCancel } = props;
return (
<Modal
destroyOnClose
title="添加 Flink 集群"
visible={modalVisible}
onCancel={() => onCancel()}
footer={null}
>
{props.children}
</Modal>
);
};
export default CreateForm;
import React, {useEffect, useState} from 'react';
import {Form, Button, Input, Modal, Select} from 'antd';
import Switch from "antd/es/switch";
import TextArea from "antd/es/input/TextArea";
import {ClusterTableListItem} from "@/pages/Cluster/data";
import {RUN_MODE} from "@/components/Studio/conf";
export type UpdateFormProps = {
onCancel: (flag?: boolean, formVals?: Partial<ClusterTableListItem>) => void;
onSubmit: (values: Partial<ClusterTableListItem>) => void;
updateModalVisible: boolean;
values: Partial<ClusterTableListItem>;
};
const Option = Select.Option;
const formLayout = {
labelCol: {span: 7},
wrapperCol: {span: 13},
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const [formVals, setFormVals] = useState<Partial<ClusterTableListItem>>({
id: props.values.id,
name: props.values.name,
alias: props.values.alias,
type: props.values.type,
hosts: props.values.hosts,
note: props.values.note,
enabled: props.values.enabled,
});
const [form] = Form.useForm();
const {
onSubmit: handleUpdate,
onCancel: handleUpdateModalVisible,
updateModalVisible,
values,
} = props;
const submitForm = async () => {
const fieldsValue = await form.validateFields();
setFormVals({...formVals, ...fieldsValue});
handleUpdate({...formVals, ...fieldsValue});
};
const renderContent = (formVals) => {
return (
<>
<Form.Item
name="name"
label="名称"
rules={[{required: true, message: '请输入名称!'}]}>
<Input placeholder="请输入"/>
</Form.Item>
<Form.Item
name="alias"
label="别名"
>
<Input placeholder="请输入"/>
</Form.Item>
<Form.Item
name="type"
label="类型"
>
<Select defaultValue={RUN_MODE.YARN_SESSION} allowClear>
<Option value={RUN_MODE.STANDALONE}>Standalone</Option>
<Option value={RUN_MODE.YARN_SESSION}>Yarn Session</Option>
<Option value={RUN_MODE.YARN_PER_JOB}>Yarn Per-Job</Option>
<Option value={RUN_MODE.YARN_APPLICATION}>Yarn Application</Option>
<Option value={RUN_MODE.KUBERNETES_SESSION}>Kubernetes Session</Option>
<Option value={RUN_MODE.KUBERNETES_APPLICATION}>Kubernetes Application</Option>
</Select>
</Form.Item>
<Form.Item
name="hosts"
label="JobManager HA 地址"
>
<TextArea
placeholder="添加 Flink 集群的 JobManager 的 RestApi 地址。当 HA 模式时,地址间用英文逗号分隔,例如:192.168.123.101:8081,192.168.123.102:8081,192.168.123.103:8081"
allowClear
autoSize={{minRows: 3, maxRows: 10}}/>
</Form.Item>
<Form.Item
name="note"
label="注释"
>
<TextArea
placeholder="请输入"
allowClear
autoSize={{minRows: 3, maxRows: 10}}/>
</Form.Item>
<Form.Item
name="enabled"
label="是否启用"
rules={[{required: true, message: '请输入是否启用!'}]}>
<Switch checkedChildren="启用" unCheckedChildren="禁用"
defaultChecked={formVals.enabled}/>
</Form.Item>
</>
);
};
const renderFooter = () => {
return (
<>
<Button onClick={() => handleUpdateModalVisible(false, values)}>取消</Button>
<Button type="primary" onClick={() => submitForm()}>
完成
</Button>
</>
);
};
return (
<Modal
width={640}
bodyStyle={{padding: '32px 40px 48px'}}
destroyOnClose
title="编辑集群"
visible={updateModalVisible}
footer={renderFooter()}
onCancel={() => handleUpdateModalVisible()}
>
<Form
{...formLayout}
form={form}
initialValues={{
id: formVals.id,
name: formVals.name,
alias: formVals.alias,
type: formVals.type,
hosts: formVals.hosts,
note: formVals.note,
enabled: formVals.enabled,
}}
>
{renderContent(formVals)}
</Form>
</Modal>
);
};
export default UpdateForm;
...@@ -5,8 +5,6 @@ import {FooterToolbar, PageContainer} from '@ant-design/pro-layout'; ...@@ -5,8 +5,6 @@ import {FooterToolbar, PageContainer} from '@ant-design/pro-layout';
import type {ActionType, ProColumns} from '@ant-design/pro-table'; import type {ActionType, ProColumns} from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import ProDescriptions from '@ant-design/pro-descriptions'; import ProDescriptions from '@ant-design/pro-descriptions';
import CreateForm from './components/CreateForm';
import UpdateForm from './components/UpdateForm';
import type {ClusterTableListItem} from './data.d'; import type {ClusterTableListItem} from './data.d';
import Dropdown from "antd/es/dropdown/dropdown"; import Dropdown from "antd/es/dropdown/dropdown";
...@@ -21,13 +19,14 @@ import { ...@@ -21,13 +19,14 @@ import {
} from "@/components/Common/crud"; } from "@/components/Common/crud";
import {showCluster, showSessionCluster} from "@/components/Studio/StudioEvent/DDL"; import {showCluster, showSessionCluster} from "@/components/Studio/StudioEvent/DDL";
import {RUN_MODE} from "@/components/Studio/conf"; import {RUN_MODE} from "@/components/Studio/conf";
import ClusterForm from "@/pages/Cluster/components/ClusterForm";
const TextArea = Input.TextArea; const TextArea = Input.TextArea;
const url = '/api/cluster'; const url = '/api/cluster';
const ClusterTableList: React.FC<{}> = (props: any) => { const ClusterTableList: React.FC<{}> = (props: any) => {
const {dispatch} = props; const {dispatch} = props;
const [createModalVisible, handleModalVisible] = useState<boolean>(false); const [modalVisible, handleModalVisible] = useState<boolean>(false);
const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false); const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
const [formValues, setFormValues] = useState({}); const [formValues, setFormValues] = useState({});
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
...@@ -303,6 +302,7 @@ const ClusterTableList: React.FC<{}> = (props: any) => { ...@@ -303,6 +302,7 @@ const ClusterTableList: React.FC<{}> = (props: any) => {
{ {
title: '操作', title: '操作',
dataIndex: 'option', dataIndex: 'option',
tooltip: 'FLinkWebUI连接 当集群状态为`可用`时! 支持 SESSION | STANDALONE',
valueType: 'option', valueType: 'option',
render: (_, record) => [ render: (_, record) => [
<a <a
...@@ -313,13 +313,18 @@ const ClusterTableList: React.FC<{}> = (props: any) => { ...@@ -313,13 +313,18 @@ const ClusterTableList: React.FC<{}> = (props: any) => {
> >
配置 配置
</a>, </a>,
<Button type="link"
href={`http://${record.jobManagerHost}/#/overview`}
target="_blank"
>
FlinkWebUI
</Button>,
<MoreBtn key="more" item={record}/>, <MoreBtn key="more" item={record}/>,
((record.status && (record.type === RUN_MODE.YARN_SESSION || record.type === RUN_MODE.STANDALONE )) ?
<>
<Button type="link" title={`http://${record.jobManagerHost}/#/overview`}
href={`http://${record.jobManagerHost}/#/overview`}
target="_blank"
>
FlinkWebUI
</Button>
</>
: undefined
),
], ],
}, },
]; ];
...@@ -356,7 +361,7 @@ const ClusterTableList: React.FC<{}> = (props: any) => { ...@@ -356,7 +361,7 @@ const ClusterTableList: React.FC<{}> = (props: any) => {
<div> <div>
已选择 <a style={{fontWeight: 600}}>{selectedRowsState.length}</a>&nbsp;&nbsp; 已选择 <a style={{fontWeight: 600}}>{selectedRowsState.length}</a>&nbsp;&nbsp;
<span> <span>
被禁用的集群共 {selectedRowsState.length - selectedRowsState.reduce((pre, item) => pre + (item.enabled ? 1 : 0), 0)} 被禁用的集群共 {selectedRowsState.length - selectedRowsState.reduce((pre, item) => pre + (item.enabled ? 1 : 0), 0)}
</span> </span>
</div> </div>
} }
...@@ -410,26 +415,26 @@ const ClusterTableList: React.FC<{}> = (props: any) => { ...@@ -410,26 +415,26 @@ const ClusterTableList: React.FC<{}> = (props: any) => {
>批量禁用</Button> >批量禁用</Button>
</FooterToolbar> </FooterToolbar>
)} )}
<CreateForm onCancel={() => handleModalVisible(false)} modalVisible={createModalVisible}> <ClusterForm
<ProTable<ClusterTableListItem, ClusterTableListItem>
onSubmit={async (value) => { onSubmit={async (value) => {
const success = await handleAddOrUpdate(url, value); const success = await handleAddOrUpdate(url, value);
if (success) { if (success) {
handleModalVisible(false); handleModalVisible(false);
if (actionRef.current) { setFormValues({});
actionRef.current.reload(); if (actionRef.current) {
actionRef.current.reload();
}
showCluster(dispatch);
showSessionCluster(dispatch);
} }
showCluster(dispatch); }}
showSessionCluster(dispatch); onCancel={() => handleModalVisible(false)}
} modalVisible={modalVisible}
}} values={{}}
rowKey="id" >
type="form" </ClusterForm>
columns={columns}
/>
</CreateForm>
{formValues && Object.keys(formValues).length ? ( {formValues && Object.keys(formValues).length ? (
<UpdateForm <ClusterForm
onSubmit={async (value) => { onSubmit={async (value) => {
const success = await handleAddOrUpdate(url, value); const success = await handleAddOrUpdate(url, value);
if (success) { if (success) {
...@@ -446,10 +451,10 @@ const ClusterTableList: React.FC<{}> = (props: any) => { ...@@ -446,10 +451,10 @@ const ClusterTableList: React.FC<{}> = (props: any) => {
handleUpdateModalVisible(false); handleUpdateModalVisible(false);
setFormValues({}); setFormValues({});
}} }}
updateModalVisible={updateModalVisible} modalVisible={updateModalVisible}
values={formValues} values={formValues}
/> />
) : null} ) : undefined}
<Drawer <Drawer
width={600} width={600}
......
...@@ -225,13 +225,13 @@ const ClusterConfigurationForm: React.FC<ClusterConfigurationFormProps> = (props ...@@ -225,13 +225,13 @@ const ClusterConfigurationForm: React.FC<ClusterConfigurationFormProps> = (props
<Divider>基本配置</Divider> <Divider>基本配置</Divider>
<Form.Item <Form.Item
name="name" name="name"
label="标识" label="名称"
rules={[{required: true, message: '请输入名称!'}]}> rules={[{required: true, message: '请输入名称!'}]}>
<Input placeholder="请输入唯一英文标识"/> <Input placeholder="请输入唯一英文标识"/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="alias" name="alias"
label="名称" label="别名"
> >
<Input placeholder="请输入名称"/> <Input placeholder="请输入名称"/>
</Form.Item> </Form.Item>
......
...@@ -79,13 +79,13 @@ const JarForm: React.FC<JarFormProps> = (props) => { ...@@ -79,13 +79,13 @@ const JarForm: React.FC<JarFormProps> = (props) => {
<Divider>基本配置</Divider> <Divider>基本配置</Divider>
<Form.Item <Form.Item
name="name" name="name"
label="标识" label="名称"
rules={[{required: true, message: '请输入名称!'}]}> rules={[{required: true, message: '请输入名称!'}]}>
<Input placeholder="请输入唯一英文标识"/> <Input placeholder="请输入唯一英文标识"/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="alias" name="alias"
label="名称" label="别名"
> >
<Input placeholder="请输入名称"/> <Input placeholder="请输入名称"/>
</Form.Item> </Form.Item>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment