add step of creating new cluster

This commit is contained in:
silenceqi 2021-08-27 10:52:25 +08:00
parent 77fc87c3dc
commit 62a61ec2de
18 changed files with 517 additions and 108 deletions

View File

@ -1,7 +1,7 @@
elasticsearch: elasticsearch:
- name: default - name: default
enabled: true enabled: true
endpoint: https://192.168.3.98:9200 endpoint: http://127.0.0.1:9200
basic_auth: basic_auth:
username: elastic username: elastic
password: ZBdkVQUUdF1Sir4X4BGB password: ZBdkVQUUdF1Sir4X4BGB
@ -29,6 +29,7 @@ elastic:
init_template: true init_template: true
template_name: ".infini-search-center" template_name: ".infini-search-center"
index_prefix: ".infini-search-center_" index_prefix: ".infini-search-center_"
# load_remote_elasticsearch_configs: true
search-center: search-center:
ui_path: .public ui_path: .public

View File

@ -442,6 +442,12 @@ export default [
name: 'cluster', name: 'cluster',
component: './System/Cluster/Index', component: './System/Cluster/Index',
}, },
{
path: '/system/cluster/regist',
name: 'registCluster',
component: './System/Cluster/Step',
hideInMenu: true
},
{ {
path: '/system/cluster/edit', path: '/system/cluster/edit',
name: 'editCluster', name: 'editCluster',

View File

@ -29,6 +29,8 @@ import { IndexPatternCreationOption } from '../../types';
import { CreateButton } from '../../create_button'; import { CreateButton } from '../../create_button';
import { Illustration } from './assets/index_pattern_illustration'; import { Illustration } from './assets/index_pattern_illustration';
import { ManagementAppMountParams } from '../../../../../management/public'; import { ManagementAppMountParams } from '../../../../../management/public';
import Link from 'umi/link';
import Exception from '@/components/Exception';
interface Props { interface Props {
canSave: boolean; canSave: boolean;
@ -53,9 +55,9 @@ export const EmptyIndexPatternPrompt = ({
horizontalPosition="center" horizontalPosition="center"
> >
<EuiFlexGroup gutterSize="xl" alignItems="center" direction="rowReverse" wrap> <EuiFlexGroup gutterSize="xl" alignItems="center" direction="rowReverse" wrap>
<EuiFlexItem grow={1} className="inpEmptyIndexPatternPrompt__illustration"> {/* <EuiFlexItem grow={1} className="inpEmptyIndexPatternPrompt__illustration">
<Illustration /> <Illustration />
</EuiFlexItem> </EuiFlexItem> */}
<EuiFlexItem grow={2} className="inpEmptyIndexPatternPrompt__text"> <EuiFlexItem grow={2} className="inpEmptyIndexPatternPrompt__text">
<EuiText grow={false}> <EuiText grow={false}>
<h2> <h2>

View File

@ -123,6 +123,7 @@ export default {
'menu.system': 'SYSTEM', 'menu.system': 'SYSTEM',
'menu.system.cluster': 'CLUSTERS', 'menu.system.cluster': 'CLUSTERS',
'menu.system.registCluster': 'REGIST CLUSTER',
'menu.system.editCluster': 'EDIT CLUSTER', 'menu.system.editCluster': 'EDIT CLUSTER',
'menu.system.settings': 'SETTINGS', 'menu.system.settings': 'SETTINGS',
'menu.system.settings.global': 'GLOBAL', 'menu.system.settings.global': 'GLOBAL',

View File

@ -130,7 +130,8 @@ export default {
'menu.system': '系统管理', 'menu.system': '系统管理',
'menu.system.cluster': '集群管理', 'menu.system.cluster': '集群管理',
'menu.system.editCluster': '集群编辑', 'menu.system.registCluster': '集群注册',
'menu.system.editCluster': '集群修改',
'menu.system.settings': '系统设置', 'menu.system.settings': '系统设置',
'menu.system.settings.global': '全局设置', 'menu.system.settings.global': '全局设置',
'menu.system.settings.gateway': '网关设置', 'menu.system.settings.gateway': '网关设置',

View File

@ -146,7 +146,7 @@ const vstyle = {
const MonitorDatePicker = ({timeRange, commonlyUsedRanges, onChange, isLoading}) => { const MonitorDatePicker = ({timeRange, commonlyUsedRanges, onChange, isLoading}) => {
// const [recentlyUsedRanges, setRecentlyUsedRanges] = useState([]); // const [recentlyUsedRanges, setRecentlyUsedRanges] = useState([]);
const [isPaused, setIsPaused] = useState(true); const [isPaused, setIsPaused] = useState(true);
const [refreshInterval, setRefreshInterval] = useState(); const [refreshInterval, setRefreshInterval] = useState(10000);
const onTimeChange = ({ start, end }) => { const onTimeChange = ({ start, end }) => {
onChange({ onChange({

View File

@ -164,8 +164,8 @@ const filterManager = new FilterManager();
const storage = new Storage(localStorage); const storage = new Storage(localStorage);
const queryStringManager = new QueryStringManager(storage); const queryStringManager = new QueryStringManager(storage);
const timefilterConfig = { const timefilterConfig = {
timeDefaults: { from: 'now-15m', to: 'now' }, timeDefaults: { from: 'now-1y', to: 'now' },
refreshIntervalDefaults: { pause: false, value: 0 }, refreshIntervalDefaults: { pause: true, value: 10000 },
}; };
const timeHistory = new TimeHistory(storage); const timeHistory = new TimeHistory(storage);
const timefilter = new Timefilter(timefilterConfig, timeHistory); const timefilter = new Timefilter(timefilterConfig, timeHistory);

View File

@ -53,7 +53,7 @@ class ClusterForm extends React.Component{
//console.log(values); //console.log(values);
let newVals = { let newVals = {
name: values.name, name: values.name,
endpoint: values.endpoint, host: values.host,
basic_auth: { basic_auth: {
username: values.username, username: values.username,
password: values.password, password: values.password,
@ -61,7 +61,8 @@ class ClusterForm extends React.Component{
description: values.description, description: values.description,
enabled: values.enabled, enabled: values.enabled,
monitored: values.monitored, monitored: values.monitored,
order: values.order, schema: values.isTLS === true ? 'https': 'http',
// order: values.order,
} }
if(clusterConfig.editMode === 'NEW') { if(clusterConfig.editMode === 'NEW') {
dispatch({ dispatch({
@ -125,7 +126,6 @@ class ClusterForm extends React.Component{
router.push('/system/cluster'); router.push('/system/cluster');
}}>返回</Button>]} }}>返回</Button>]}
> >
{/* <NewCluster/> */}
<Form {...formItemLayout}> <Form {...formItemLayout}>
<Form.Item label="集群名称"> <Form.Item label="集群名称">
{getFieldDecorator('name', { {getFieldDecorator('name', {
@ -138,20 +138,31 @@ class ClusterForm extends React.Component{
], ],
})(<Input autoComplete='off' placeholder="cluster-name" />)} })(<Input autoComplete='off' placeholder="cluster-name" />)}
</Form.Item> </Form.Item>
<Form.Item label="集群 URL"> <Form.Item label="集群地址">
{getFieldDecorator('endpoint', { {getFieldDecorator('host', {
initialValue: editValue.endpoint, initialValue: editValue.host,
rules: [ rules: [
{ {
type: 'url', //https://github.com/yiminghe/async-validator#type type: 'string',
message: 'The input is not valid url!', pattern: /^[\w\.]+\:\d+$/, //(https?:\/\/)?
message: '请输入域名或 IP 地址和端口号',
}, },
{ {
required: true, required: true,
message: 'Please input cluster name!', message: '请输入域名或 IP 地址和端口号!',
}, },
], ],
})(<Input placeholder="http://127.0.0.1:9200" />)} })(<Input placeholder="127.0.0.1:9200" />)}
</Form.Item>
<Form.Item label="TLS">
{getFieldDecorator('isTLS', {
initialValue: editValue?.schema === "https",
})(
<Switch
defaultChecked={editValue?.schema === "https"}
checkedChildren={<Icon type="check" />}
unCheckedChildren={<Icon type="close" />}
/>)}
</Form.Item> </Form.Item>
<Form.Item label="是否需要身份验证"> <Form.Item label="是否需要身份验证">
<Switch <Switch
@ -177,22 +188,17 @@ class ClusterForm extends React.Component{
})(<Input.Password />)} })(<Input.Password />)}
</Form.Item> </Form.Item>
</div>):''} </div>):''}
{/* <Form.Item label="Elasticsearch "> {/* <Form.Item label="">
{getFieldDecorator('version', {
initialValue: editValue.version || '',
})(<Input readOnly={true} />)}
</Form.Item> */}
<Form.Item label="排序权重">
{getFieldDecorator('order', { {getFieldDecorator('order', {
initialValue: editValue.order || 0, initialValue: editValue.order || 0,
})(<InputNumber />)} })(<InputNumber />)}
</Form.Item> </Form.Item> */}
<Form.Item label="描述"> <Form.Item label="描述">
{getFieldDecorator('description', { {getFieldDecorator('description', {
initialValue: editValue.description, initialValue: editValue.description,
})(<Input.TextArea placeholder="集群应用描述" />)} })(<Input.TextArea placeholder="集群应用描述" />)}
</Form.Item> </Form.Item>
<Form.Item label="是否启用"> {/* <Form.Item label="">
{getFieldDecorator('enabled', { {getFieldDecorator('enabled', {
valuePropName: 'checked', valuePropName: 'checked',
initialValue: typeof editValue.enabled === 'undefined' ? true: editValue.enabled, initialValue: typeof editValue.enabled === 'undefined' ? true: editValue.enabled,
@ -200,7 +206,7 @@ class ClusterForm extends React.Component{
checkedChildren={<Icon type="check" />} checkedChildren={<Icon type="check" />}
unCheckedChildren={<Icon type="close" />} unCheckedChildren={<Icon type="close" />}
/>)} />)}
</Form.Item> </Form.Item> */}
<Form.Item label="启用监控"> <Form.Item label="启用监控">
{getFieldDecorator('monitored', { {getFieldDecorator('monitored', {
valuePropName: 'checked', valuePropName: 'checked',
@ -214,9 +220,6 @@ class ClusterForm extends React.Component{
<Button type="primary" onClick={this.handleSubmit}> <Button type="primary" onClick={this.handleSubmit}>
{editMode === 'NEW' ? '注册': '保存'} {editMode === 'NEW' ? '注册': '保存'}
</Button> </Button>
{/* <Button style={{marginLeft:20}}>
测试连接
</Button> */}
</Form.Item> </Form.Item>
</Form> </Form>
</Card> </Card>

View File

@ -40,14 +40,14 @@ class Index extends React.Component {
} }
}, { }, {
title: '部署环境', title: '部署环境',
dataIndex: 'business_department', dataIndex: 'deploy_env',
key: 'business_department', key: 'deploy_env',
render: ()=>{ render: ()=>{
return 'PROD' return 'PROD'
} }
},{ },{
title: '程序版本', title: '程序版本',
dataIndex: 'status.version', dataIndex: 'version',
key: 'elasticsearch_version', key: 'elasticsearch_version',
// render: (data)=>{ // render: (data)=>{
// return // return
@ -212,7 +212,7 @@ class Index extends React.Component {
onChange={this.handleEnabledChange} onChange={this.handleEnabledChange}
defaultChecked defaultChecked
/></span> /></span>
<Link to='/system/cluster/edit' onClick={this.handleNewClick}> <Button type="primary" icon="plus">新建集群</Button></Link> <Link to='/system/cluster/regist' onClick={this.handleNewClick}> <Button type="primary" icon="plus">注册集群</Button></Link>
</div> </div>
</div> </div>
<Table <Table

View File

@ -1,7 +1,9 @@
import { Steps, Button, message } from 'antd'; import { Steps, Button, message, Spin, Card } from 'antd';
import {connect} from "dva"; import {connect} from "dva";
import { useState, useRef } from 'react'; import { useState, useRef } from 'react';
import InitialStep from './steps/initial_step'; import {InitialStep, ExtraStep, ResultStep} from './steps';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import styles from './step.less';
const { Step } = Steps; const { Step } = Steps;
@ -10,7 +12,7 @@ const steps = [
title: '初始化', title: '初始化',
}, },
{ {
title: '连接', title: '信息确认',
content: 'Second-content', content: 'Second-content',
}, },
{ {
@ -22,24 +24,100 @@ const steps = [
const ClusterStep = ({ const ClusterStep = ({
current, current,
changeStep, changeStep,
dispatch,
history,
}) => { }) => {
const initalFormRef = useRef(); const formRef = useRef();
const [clusterConfig, setClusterConfig] = useState({})
const [isLoading, setIsLoading] = useState(false);
// const [clusterInfo, setClusterInfo] = useState({});
const handleConnect = async ()=>{
const result = await formRef.current.validateFields((errors, values) => {
if(errors){
return false;
}
return values;
}).catch((err)=>{
return false;
});
if(!result){
return false
}
setIsLoading(true)
const res = await dispatch({
type: 'clusterConfig/doTryConnect',
payload: {
basic_auth:{
username: result.username,
password: result.password,
},
host: result.host,
schema: result.isTLS === true ? 'https': 'http',
},
});
if(res && !res.error){
setClusterConfig({
...result,
...res,
});
return true;
}else{
setIsLoading(false)
return false;
}
}
const handleCommit = async ()=>{
const result = await formRef.current.validateFields((errors, values) => {
if(errors){
return false;
}
// console.log(values);
return values
});
if(!result){
return fasle;
}
const newVals = {
name: result.name,
version: clusterConfig.version,
host: clusterConfig.host,
basic_auth: {
username: clusterConfig.username || '',
password: clusterConfig.password || '',
},
description: result.description,
enabled: true,
monitored: result.monitored,
schema: clusterConfig.isTLS ? 'https': 'http'
}
setIsLoading(true);
const res = await dispatch({
type: 'clusterConfig/addCluster',
payload: newVals,
});
if(res && !res.error){
return true;
}else{
setIsLoading(false)
return false;
}
}
const next = async () => { const next = async () => {
let result let result
if(current === 0){ if(current === 0){
result = await initalFormRef.current.validateFields((errors, values) => { result = await handleConnect();
if(errors){ }else if(current === 1){
return false; result = await handleCommit();
}
console.log(values)
}).catch((err)=>{
return false;
})
} }
if(!result){ if(!result){
return return
} }
setIsLoading(false)
changeStep(current + 1) changeStep(current + 1)
}; };
@ -47,48 +125,97 @@ const ClusterStep = ({
changeStep(current - 1) changeStep(current - 1)
}; };
const oneMoreClick = ()=>{
setClusterConfig({});
changeStep(0);
}
const goToClusterList = ()=>{
history.push('/system/cluster');
}
const renderContent = (current)=>{ const renderContent = (current)=>{
if(current===0){ if(current===0){
return <InitialStep ref={initalFormRef} /> return <InitialStep ref={formRef} initialValue={clusterConfig} />
}else if(current === 1){ }else if(current === 1){
return <></> return <ExtraStep initialValue={clusterConfig} ref={formRef}/>
}else{ }else if(current === 2){
return null return <ResultStep clusterConfig={clusterConfig} oneMoreClick={oneMoreClick}
goToClusterList={goToClusterList}
/>
} }
} }
return (
<> const content = (
<Steps current={current}> <div className={styles.pageHeaderContent}>
{steps.map(item => ( <p>
<Step key={item.title} title={item.title} /> 输入集群地址和身份验证信息分步创建集群
))} </p>
</Steps> <div className={styles.contentLink}>
<div className="steps-content">{renderContent(current)}</div> <a>
<div className="steps-action" style={{textAlign:'center'}}> <img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/MjEImQtenlyueSmVEfUD.svg" />{' '}
{current < steps.length - 1 && ( 快速开始
<Button type="primary" onClick={() => next()}> </a>
下一步 <a>
</Button> <img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/NbuDUAuBlIApFuDvWiND.svg" />{' '}
)} 产品简介
{current === steps.length - 1 && ( </a>
<Button type="primary" onClick={() => message.success('Processing complete!')}> <a>
完成 <img alt="" src="https://gw.alipayobjects.com/zos/rmsportal/ohOEPSYdDTNnyMbGuyLb.svg" />{' '}
</Button> 产品文档
)} </a>
{current > 0 && (
<Button style={{ margin: '0 8px' }} onClick={() => prev()}>
上一步
</Button>
)}
</div> </div>
</> </div>
);
const extraContent = (
<div className={styles.extraImg}>
<img
alt="这是一个标题"
src="https://gw.alipayobjects.com/zos/rmsportal/RzwpdLnhmvDJToTdfDPe.png"
/>
</div>
);
return (
<PageHeaderWrapper title="集群注册" content={content} extraContent={extraContent}>
<Card>
<Spin spinning={isLoading}>
<div style={{maxWidth:720, margin:'0 auto'}}>
<Steps current={current} style={{marginBottom:24}}>
{steps.map(item => (
<Step key={item.title} title={item.title} />
))}
</Steps>
<div className="steps-content">{renderContent(current)}</div>
<div className="steps-action" style={{textAlign:'center'}}>
{current === 1 && (
<Button style={{ margin: '0 8px' }} onClick={() => prev()}>
上一步
</Button>
)}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => next()}>
下一步
</Button>
)}
</div>
</div>
</Spin>
</Card>
</PageHeaderWrapper>
); );
}; };
const NewCluster = ()=>{ const NewCluster = (props)=>{
const {dispatch, history} = props;
const [current, setCurrent] = useState(0); const [current, setCurrent] = useState(0);
return <ClusterStep current={current} changeStep={setCurrent} /> return <ClusterStep current={current} changeStep={setCurrent}
history={history}
dispatch={dispatch} />
} }
export default connect(({ export default connect(({

View File

@ -1,4 +1,5 @@
import {createClusterConfig, searchClusterConfig, updateClusterConfig,deleteClusterConfig, getClusterStatus} from "@/services/cluster"; import {createClusterConfig, searchClusterConfig, updateClusterConfig,deleteClusterConfig,
getClusterStatus, tryConnect} from "@/services/cluster";
import {message} from "antd"; import {message} from "antd";
import {formatESSearchResult} from '@/lib/elasticsearch/util'; import {formatESSearchResult} from '@/lib/elasticsearch/util';
@ -45,6 +46,9 @@ export default {
return false; return false;
} }
let {data, total} = yield select(state => state.clusterConfig); let {data, total} = yield select(state => state.clusterConfig);
if(!data){
return
}
data.unshift({ data.unshift({
...res._source, ...res._source,
id: res._id, id: res._id,
@ -147,6 +151,21 @@ export default {
} }
}) })
return res; return res;
},
*doTryConnect({payload}, {call, put, select}) {
let res = yield call(tryConnect, payload)
if(res.error){
message.error(res.error)
return false;
}
yield put({
type: 'saveData',
payload: {
tempClusterInfo: res,
}
})
return res;
} }
}, },
reducers:{ reducers:{

View File

@ -0,0 +1,26 @@
.extraImg {
margin-top: -60px;
text-align: center;
width: 195px;
img {
width: 100%;
}
}
.pageHeaderContent {
position: relative;
}
.contentLink {
margin-top: 16px;
a {
margin-right: 32px;
img {
width: 24px;
}
}
img {
vertical-align: middle;
margin-right: 8px;
}
}

View File

@ -0,0 +1,88 @@
import {Form, Input, Switch, Icon, InputNumber, Divider, Descriptions} from 'antd';
@Form.create()
export class ExtraStep extends React.Component {
state = {
}
render(){
const {form:{getFieldDecorator}, initialValue} = this.props;
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
};
return (
<>
<Descriptions column={2} size="small" bordered>
<Descriptions.Item label="集群版本" >
{initialValue?.version}
</Descriptions.Item>
<Descriptions.Item label="健康状态" >
{initialValue?.status}
</Descriptions.Item>
<Descriptions.Item label="节点数" >
{initialValue?.number_of_nodes}
</Descriptions.Item>
<Descriptions.Item label="数据节点数" >
{initialValue?.number_of_data_nodes}
</Descriptions.Item>
<Descriptions.Item label="分片数" >
{initialValue?.active_shards}
</Descriptions.Item>
</Descriptions>
<Divider/>
<Form {...formItemLayout} style={{marginTop:15}} form={this.props.formRef}>
<Form.Item label="集群名称" >
{getFieldDecorator('name', {
initialValue: initialValue?.cluster_name || '',
rules: [
{
required: true,
message: 'Please input cluster name!',
},
],
})(<Input autoComplete='off' placeholder="cluster-name" />)}
</Form.Item>
{/* <Form.Item label="Elasticsearch ">
{getFieldDecorator('version', {
initialValue: initialValue?.version || '',
})(<Input readOnly={true} />)}
</Form.Item> */}
{/* <Form.Item label="">
{getFieldDecorator('order', {
initialValue: 0,
})(<InputNumber />)}
</Form.Item> */}
<Form.Item label="描述">
{getFieldDecorator('description', {
initialValue: '',
})(<Input.TextArea placeholder="集群应用描述" />)}
</Form.Item>
{/* <Form.Item label="">
{getFieldDecorator('enabled', {
valuePropName: 'checked',
initialValue: true,
})(<Switch
checkedChildren={<Icon type="check" />}
unCheckedChildren={<Icon type="close" />}
/>)}
</Form.Item> */}
<Form.Item label="启用监控">
{getFieldDecorator('monitored', {
valuePropName: 'checked',
initialValue: true,
})(<Switch
checkedChildren={<Icon type="check" />}
unCheckedChildren={<Icon type="close" />}
/>)}
</Form.Item>
</Form>
</>
)
}
}

View File

@ -0,0 +1,3 @@
export * from './initial_step';
export * from './extra_step';
export * from './result_step';

View File

@ -1,10 +1,12 @@
import {Form, Input, Switch, Icon} from 'antd'; import {Form, Input, Switch, Icon} from 'antd';
import {useState} from 'react';
@Form.create() @Form.create()
class InitialStep extends React.Component { export class InitialStep extends React.Component {
state = { constructor(props){
needAuth: false, super(props);
this.state = {
needAuth: props.initialValue?.username !== undefined,
}
} }
handleAuthChange = (val) => { handleAuthChange = (val) => {
this.setState({ this.setState({
@ -12,7 +14,7 @@ class InitialStep extends React.Component {
}) })
} }
render(){ render(){
const {form:{getFieldDecorator}} = this.props; const {form:{getFieldDecorator}, initialValue} = this.props;
const formItemLayout = { const formItemLayout = {
labelCol: { labelCol: {
xs: { span: 24 }, xs: { span: 24 },
@ -24,34 +26,33 @@ class InitialStep extends React.Component {
}, },
}; };
return ( return (
<Form {...formItemLayout} style={{marginTop:15}} form={this.props.formRef}> <Form {...formItemLayout} form={this.props.formRef}>
<Form.Item label="集群名称" > <Form.Item label="集群地址">
{getFieldDecorator('name', { {getFieldDecorator('host', {
initialValue: '', initialValue: initialValue?.host || '',
rules: [ rules: [
{ {
required: true, type: 'string',
message: 'Please input cluster name!', pattern: /^[\w\.]+\:\d+$/, //(https?:\/\/)?
}, message: '请输入域名或 IP 地址和端口号',
],
})(<Input autoComplete='off' placeholder="cluster-name" />)}
</Form.Item>
<Form.Item label="集群 URL">
{getFieldDecorator('endpoint', {
initialValue: '',
rules: [
{
type: 'url',
message: 'The input is not valid url!',
}, },
{ {
required: true, required: true,
message: 'Please input cluster endpoint!', message: '请输入集群地址!',
}, },
], ],
})(<Input placeholder="http://127.0.0.1:9200" />)} })(<Input placeholder="127.0.0.1:9200" />)}
</Form.Item> </Form.Item>
<Form.Item label="是否需要身份验证"> <Form.Item label="TLS">
{getFieldDecorator('isTLS', {
initialValue: initialValue?.isTLS || false,
})(
<Switch
checkedChildren={<Icon type="check" />}
unCheckedChildren={<Icon type="close" />}
/>)}
</Form.Item>
<Form.Item label="身份验证">
<Switch <Switch
defaultChecked={this.state.needAuth} defaultChecked={this.state.needAuth}
onChange={this.handleAuthChange} onChange={this.handleAuthChange}
@ -62,7 +63,7 @@ class InitialStep extends React.Component {
{this.state.needAuth === true ? (<div> {this.state.needAuth === true ? (<div>
<Form.Item label="用户名"> <Form.Item label="用户名">
{getFieldDecorator('username', { {getFieldDecorator('username', {
initialValue: '', initialValue: initialValue?.username || '',
rules: [ rules: [
{ {
required: true, required: true,
@ -73,7 +74,7 @@ class InitialStep extends React.Component {
</Form.Item> </Form.Item>
<Form.Item label="密码" hasFeedback> <Form.Item label="密码" hasFeedback>
{getFieldDecorator('password', { {getFieldDecorator('password', {
initialValue: '', initialValue: initialValue?.password || '',
rules: [ rules: [
{ {
required: true, required: true,
@ -86,6 +87,4 @@ class InitialStep extends React.Component {
</Form> </Form>
) )
} }
} }
export default InitialStep;

View File

@ -0,0 +1,63 @@
import Result from '@/components/Result';
import React, { Fragment } from 'react';
import { Button, Row, Col } from 'antd';
import styles from './styles.less';
export const ResultStep = (props)=>{
const {clusterConfig, oneMoreClick, goToClusterList} = props;
const information = (
<div className={styles.information}>
<Row>
<Col xs={24} sm={8} className={styles.label}>
集群名称
</Col>
<Col xs={24} sm={16}>
{clusterConfig?.cluster_name}
</Col>
</Row>
<Row>
<Col xs={24} sm={8} className={styles.label}>
集群版本
</Col>
<Col xs={24} sm={16}>
{clusterConfig?.version}
</Col>
</Row>
<Row>
<Col xs={24} sm={8} className={styles.label}>
集群地址
</Col>
<Col xs={24} sm={16}>
{clusterConfig?.host}
</Col>
</Row>
<Row>
<Col xs={24} sm={8} className={styles.label}>
TLS
</Col>
<Col xs={24} sm={16}>
{clusterConfig?.isTLS ? '是': '否'}
</Col>
</Row>
</div>
);
const actions = (
<Fragment>
<Button type="primary" onClick={oneMoreClick}>
再创建一个集群
</Button>
<Button onClick={goToClusterList}>查看集群列表</Button>
</Fragment>
);
return (
<Result
type="success"
title="创建成功"
description=""
extra={information}
actions={actions}
className={styles.result}
/>
);
}

View File

@ -0,0 +1,62 @@
@import '~antd/lib/style/themes/default.less';
.result {
margin: 0 auto;
max-width: 560px;
padding: 24px 0 8px;
}
.desc {
padding: 0 56px;
// color: @text-color-secondary;
h3 {
font-size: 16px;
margin: 0 0 12px 0;
// color: @text-color-secondary;
line-height: 32px;
}
h4 {
margin: 0 0 4px 0;
// color: @text-color-secondary;
font-size: 14px;
line-height: 22px;
}
p {
margin-top: 0;
margin-bottom: 12px;
line-height: 22px;
}
}
@media screen and (max-width: @screen-md) {
.desc {
padding: 0;
}
}
.information {
line-height: 22px;
:global {
.ant-row:not(:last-child) {
margin-bottom: 24px;
}
}
.label {
// color: @heading-color;
text-align: right;
padding-right: 8px;
@media screen and (max-width: @screen-sm) {
text-align: left;
}
}
}
.money {
font-family: 'Helvetica Neue', sans-serif;
font-weight: 500;
font-size: 20px;
line-height: 14px;
}
.uppercase {
font-size: 12px;
}

View File

@ -16,7 +16,7 @@ export async function getClusterMetrics(params) {
} }
export async function createClusterConfig(params) { export async function createClusterConfig(params) {
return request(`/elasticsearch`, { return request(`/elasticsearch/`, {
method: 'POST', method: 'POST',
body: params, body: params,
}); });
@ -57,4 +57,12 @@ export async function getClusterStatus(params) {
return request(url, { return request(url, {
method: 'GET', method: 'GET',
}); });
}
export async function tryConnect(params) {
let url = `/elasticsearch/try_connect`;
return request(url, {
method: 'POST',
body: params,
});
} }