Added initial layout for DHCP server config

This commit is contained in:
Ildar Kamalov
2018-12-12 18:12:51 +03:00
committed by Eugene Bujak
parent 390883126c
commit dd21f497e3
13 changed files with 514 additions and 10 deletions

View File

@@ -0,0 +1,134 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { Field, reduxForm } from 'redux-form';
import { R_IPV4 } from '../../../helpers/constants';
const required = (value) => {
if (value) {
return false;
}
return 'Required field';
};
const ipv4 = (value) => {
if (value && !new RegExp(R_IPV4).test(value)) {
return 'Invalid IPv4 format';
}
return false;
};
const renderField = ({
input, className, placeholder, type, disabled, meta: { touched, error },
}) => (
<Fragment>
<input
{...input}
placeholder={placeholder}
type={type}
className={className}
disabled={disabled}
/>
{!disabled && touched && (error && <span className="form__message form__message--error">{error}</span>)}
</Fragment>
);
const Form = (props) => {
const {
handleSubmit, pristine, submitting, enabled,
} = props;
return (
<form onSubmit={handleSubmit}>
<div className="row">
<div className="col-lg-6">
<div className="form__group form__group--dhcp">
<label>Gateway IP</label>
<Field
name="gateway_ip"
component={renderField}
type="text"
className="form-control"
placeholder="Gateway IP"
validate={[ipv4, required]}
disabled={!enabled}
/>
</div>
<div className="form__group form__group--dhcp">
<label>Subnet mask</label>
<Field
name="subnet_mask"
component={renderField}
type="text"
className="form-control"
placeholder="Subnet mask"
validate={[ipv4, required]}
disabled={!enabled}
/>
</div>
</div>
<div className="col-lg-6">
<div className="form__group form__group--dhcp">
<div className="row">
<div className="col-12">
<label>Range of IP addresses</label>
</div>
<div className="col">
<Field
name="range_start"
component={renderField}
type="text"
className="form-control"
placeholder="Range start"
validate={[ipv4, required]}
disabled={!enabled}
/>
</div>
<div className="col">
<Field
name="range_end"
component={renderField}
type="text"
className="form-control"
placeholder="Range end"
validate={[ipv4, required]}
disabled={!enabled}
/>
</div>
</div>
</div>
<div className="form__group form__group--dhcp">
<label>DHCP lease time (in seconds)</label>
<Field
name="lease_duration"
component={renderField}
type="number"
className="form-control"
placeholder="Lease duration"
validate={[required]}
disabled={!enabled}
/>
</div>
</div>
</div>
<button
type="submit"
className="btn btn-success btn-standart"
disabled={pristine || submitting || !enabled}
>
Save config
</button>
</form>
);
};
Form.propTypes = {
handleSubmit: PropTypes.func,
pristine: PropTypes.bool,
submitting: PropTypes.bool,
enabled: PropTypes.bool,
};
export default reduxForm({
form: 'dhcpForm',
})(Form);

View File

@@ -0,0 +1,36 @@
import React from 'react';
import PropTypes from 'prop-types';
import ReactTable from 'react-table';
import { withNamespaces } from 'react-i18next';
const columns = [{
Header: 'MAC',
accessor: 'mac',
}, {
Header: 'IP',
accessor: 'ip',
}, {
Header: 'Hostname',
accessor: 'hostname',
}, {
Header: 'Expires',
accessor: 'expires',
}];
const Leases = props => (
<ReactTable
data={props.leases}
columns={columns}
showPagination={false}
noDataText={ props.t('dhcp_leases_not_found') }
minRows={6}
className="-striped -highlight card-table-overflow"
/>
);
Leases.propTypes = {
leases: PropTypes.array,
t: PropTypes.func,
};
export default withNamespaces()(Leases);

View File

@@ -0,0 +1,93 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Trans, withNamespaces } from 'react-i18next';
import Form from './Form';
import Leases from './Leases';
import Card from '../../ui/Card';
class Dhcp extends Component {
handleFormSubmit = (values) => {
this.props.setDhcpConfig(values);
};
handleRefresh = () => {
this.props.findActiveDhcp();
}
getToggleDhcpButton = () => {
const { enabled } = this.props.dhcp.config;
const buttonText = enabled ? 'dhcp_disable' : 'dhcp_enable';
const buttonClass = enabled ? 'btn-gray' : 'btn-success';
return (
<button type="button" className={`btn btn-standart mr-2 ${buttonClass}`} onClick={() => this.props.toggleDhcp(enabled)}>
<Trans>{buttonText}</Trans>
</button>
);
}
render() {
const { t, dhcp } = this.props;
const statusButtonClass = classnames({
'btn btn-primary btn-standart': true,
'btn btn-primary btn-standart btn-loading': dhcp.processingStatus,
});
return (
<Fragment>
{!dhcp.processing &&
<Card title={ t('dhcp_title') } subtitle={ t('dhcp_description') } bodyType="card-body box-body--settings">
<div className="row">
<div className="col">
<div className="card-actions mt-0 mb-3">
{this.getToggleDhcpButton()}
<button
className={statusButtonClass}
type="button"
onClick={this.handleRefresh}
>
<Trans>refresh_status</Trans>
</button>
</div>
{dhcp.active && !dhcp.active.found &&
<div className="text-secondary">
<Trans>dhcp_not_found</Trans>
</div>
}
<hr/>
<Form
onSubmit={this.handleFormSubmit}
initialValues={dhcp.config}
enabled={dhcp.config.enabled}
/>
</div>
</div>
</Card>
}
{!dhcp.processing && dhcp.config.enabled &&
<Card title={ t('dhcp_leases') } bodyType="card-body box-body--settings">
<div className="row">
<div className="col">
<Leases leases={dhcp.leases} />
</div>
</div>
</Card>
}
</Fragment>
);
}
}
Dhcp.propTypes = {
dhcp: PropTypes.object,
toggleDhcp: PropTypes.func,
getDhcpStatus: PropTypes.func,
setDhcpConfig: PropTypes.func,
findActiveDhcp: PropTypes.func,
handleSubmit: PropTypes.func,
t: PropTypes.func,
};
export default withNamespaces()(Dhcp);

View File

@@ -1,4 +1,5 @@
.form__group {
position: relative;
margin-bottom: 15px;
}
@@ -6,6 +7,10 @@
margin-bottom: 0;
}
.form__group--dhcp:last-child {
margin-bottom: 15px;
}
.btn-standart {
padding-left: 20px;
padding-right: 20px;
@@ -18,3 +23,11 @@
.form-control--textarea-large {
min-height: 240px;
}
.form__message {
font-size: 11px;
}
.form__message--error {
color: #cd201f;
}

View File

@@ -2,6 +2,7 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { withNamespaces, Trans } from 'react-i18next';
import Upstream from './Upstream';
import Dhcp from './Dhcp';
import Checkbox from '../ui/Checkbox';
import Loading from '../ui/Loading';
import PageTitle from '../ui/PageTitle';
@@ -34,6 +35,7 @@ class Settings extends Component {
componentDidMount() {
this.props.initSettings(this.settings);
this.props.getDhcpStatus();
}
handleUpstreamChange = (value) => {
@@ -92,6 +94,13 @@ class Settings extends Component {
handleUpstreamSubmit={this.handleUpstreamSubmit}
handleUpstreamTest={this.handleUpstreamTest}
/>
<Dhcp
dhcp={this.props.dhcp}
toggleDhcp={this.props.toggleDhcp}
getDhcpStatus={this.props.getDhcpStatus}
findActiveDhcp={this.props.findActiveDhcp}
setDhcpConfig={this.props.setDhcpConfig}
/>
</div>
</div>
</div>