skyline/src/components/FormItem/NetworkSelect/index.jsx
zhuyue 8009bc8c41 fix: Fix for newtork config show
fix for network config show

Change-Id: I5448aca49a972c651e262130e0033158abe9d6ba
2021-09-01 03:46:22 +00:00

363 lines
8.8 KiB
JavaScript

// Copyright 2021 99cloud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from 'react';
import { Row, Col, Form, Tooltip, Input } from 'antd';
import Select from 'components/FormItem/Select';
import PropTypes from 'prop-types';
import { ipValidate } from 'utils/validate';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { ipTypeOptions } from 'resources/network';
// import { getIpInitValue } from 'resources/instance';
import styles from './index.less';
const { isIPv4, isIpv6, isIpInRangeAll } = ipValidate;
export default class NetworkSelect extends React.Component {
static propTypes = {
// eslint-disable-next-line react/no-unused-prop-types
networks: PropTypes.array,
// eslint-disable-next-line react/no-unused-prop-types
subnets: PropTypes.array,
value: PropTypes.object,
ipType: PropTypes.number,
name: PropTypes.string,
optionsByIndex: PropTypes.bool,
index: PropTypes.number,
};
static defaultProps = {
networks: [],
subnets: [],
value: {},
ipType: 0,
name: 'network',
optionsByIndex: false,
index: 0,
};
constructor(props) {
super(props);
const { value } = props;
const { network, subnet, ip, ipType } = value;
this.state = {
network: network || null,
subnet: subnet || null,
ip: ip || '0.0.0.0',
ipType: ipType || 0,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
if (
nextProps.networks !== prevState.networks ||
nextProps.subnets !== prevState.subnets
) {
const { networks, subnets } = nextProps;
return {
networks,
subnets,
};
}
return null;
}
componentDidMount() {
this.checkNetwork();
}
onChange = () => {
this.checkNetwork(() => {
const { onChange } = this.props;
const { network, subnet, ip, ipType, validateStatus, errorMsg } =
this.state;
const networkOptions = this.getNetworkOptions();
const subnetOptions = this.getSubnetOptions();
const networkOption = networkOptions.find((it) => it.value === network);
const subnetOption = subnetOptions.find((it) => it.value === subnet);
const ipTypeOption = ipTypeOptions.find((it) => it.value === ipType);
if (onChange) {
onChange({
network,
subnet,
ip,
ipType,
networkOption,
subnetOption,
ipTypeOption,
validateStatus,
errorMsg,
});
}
});
};
onNetworkChange = (value) => {
const { subnets } = this.state;
const subs = subnets.filter((it) => it.network_id === value);
const subnet = subs.length ? subs[0].id : null;
this.setState(
{
network: value,
subnet,
ipType: 0,
// defaultIp: this.getIpInitValue(subnet),
ip: undefined,
},
this.onChange
);
};
onSubnetChange = (value) => {
this.setState(
{
subnet: value,
// defaultIp: this.getIpInitValue(value),
ip: undefined,
},
this.onChange
);
};
// getIpInitValue = (subnet) => {
// const { subnets } = this.state;
// const subnetItem = subnets.find(it => it.id === subnet);
// return getIpInitValue(subnetItem);
// }
onTypeChange = (value) => {
this.setState(
{
ipType: value,
},
this.onChange
);
};
onIPChange = (e) => {
const { value } = e.currentTarget;
this.setState(
{
ip: value,
},
this.onChange
);
};
checkNetwork = (callback) => {
const { network, subnets, subnet, ip, ipType } = this.state;
const item = subnets.find((it) => it.id === subnet);
const { allocation_pools: pools } = item || {};
if (!network) {
this.setState(
{
errorMsg: t('Pleasse select a network!'),
validateStatus: 'error',
},
callback
);
return;
}
// if (!subnet) {
// this.setState({
// errorMsg: t('Pleasse select a subnet!'),
// validateStatus: 'error',
// }, callback);
// return;
// }
if (ipType === 1 && !isIPv4(ip) && !isIpv6(ip)) {
this.setState(
{
errorMsg: t('Pleasse input a valid ip!'),
validateStatus: 'error',
},
callback
);
return;
}
if (pools && ipType === 1) {
const okPool = pools.find((pool) =>
isIpInRangeAll(ip, pool.start, pool.end)
);
if (!okPool) {
this.setState(
{
errorMsg: t('The ip is not within the allocated pool!'),
validateStatus: 'error',
},
callback
);
return;
}
}
this.setState(
{
errorMsg: undefined,
validateStatus: 'success',
},
callback
);
};
getNetworkOptions = () => {
const { networks } = this.state;
const { optionsByIndex, index } = this.props;
let datas = [...networks];
if (optionsByIndex && index < networks.length) {
datas = [networks[index]];
}
return datas.map((it) => ({
label: it.name,
value: it.id,
}));
};
getSubnetOptions = () => {
const { network, subnets } = this.state;
if (!network) {
return [];
}
return subnets
.filter((it) => it.network_id === network)
.map((it) => ({
label: (
<div>
<span>{it.name}</span>
<span className={styles.subnet_options_cidr}>{it.cidr}</span>
</div>
),
name: it.name,
value: it.id,
}));
};
renderNetwork() {
const { network } = this.state;
return (
<Col span={6}>
<Select
options={this.getNetworkOptions()}
value={network}
onChange={this.onNetworkChange}
placeholder={t('please select network')}
/>
</Col>
);
}
renderSubnet() {
const { network, subnet, ipType } = this.state;
if (!network || !ipType) {
return null;
}
return (
<Col span={6}>
<Select
options={this.getSubnetOptions()}
value={subnet}
placeholder={t('please select subnet')}
onChange={this.onSubnetChange}
/>
</Col>
);
}
renderIpType() {
const { network, ipType } = this.state;
if (!network) {
return null;
}
return (
<Col span={6}>
<Select
value={ipType}
options={ipTypeOptions}
onChange={this.onTypeChange}
/>
</Col>
);
}
renderIp() {
const { subnet, subnets, ipType, ip } = this.state;
if (!subnet) {
return null;
}
const item = subnets.find((it) => it.id === subnet);
if (!item) {
return null;
}
const { allocation_pools: pools } = item;
const details = pools.map((pool, index) => (
<span key={`pool.start.${index}`} style={{ marginRight: 10 }}>
{pool.start}--{pool.end}
</span>
));
const detailsDiv = pools.map((pool, index) => (
<div key={`pool.start.${index}`}>
{pool.start}--{pool.end}
</div>
));
if (ipType === 0) {
const tips = (
<span>
<span className={styles.label}>{t('Allocation Pools')}: </span>
<span className={styles.content}>{details}</span>
</span>
);
return <Col span={12}>{tips}</Col>;
}
const tips = (
<span>
<span className={styles.label}>{t('Allocation Pools')}: </span>
<span className={styles.content}>{detailsDiv}</span>
<span className={styles.content}>
{t(
'Please make sure this IP address be available to avoid creating VM failure.'
)}
</span>
</span>
);
return (
<Col span={6}>
<Input defaultValue={ip} onChange={this.onIPChange} />
<Tooltip title={tips} color="white">
<QuestionCircleOutlined />
</Tooltip>
</Col>
);
}
render() {
const { validateStatus, errorMsg } = this.state;
const { name } = this.props;
return (
<Form.Item
className={styles['network-select']}
name={name}
validateStatus={validateStatus}
help={errorMsg}
>
<Row gutter={24}>
{this.renderNetwork()}
{this.renderIpType()}
{this.renderSubnet()}
{this.renderIp()}
</Row>
</Form.Item>
);
}
}