+ client: Refactor DHCP settings

This commit is contained in:
Artem Baskal
2020-08-19 18:23:05 +03:00
committed by Simon Zolin
parent c9f58ce4a7
commit 1d35d73fc5
49 changed files with 2953 additions and 1660 deletions

View File

@@ -1,22 +1,27 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Field, reduxForm } from 'redux-form';
import { Trans, withTranslation } from 'react-i18next';
import flow from 'lodash/flow';
import { Trans, useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { renderInputField } from '../../../../helpers/form';
import { validateIpv4, validateMac, validateRequiredValue } from '../../../../helpers/validators';
import { FORM_NAME } from '../../../../helpers/constants';
import { toggleLeaseModal } from '../../../../actions';
const Form = (props) => {
const {
t,
handleSubmit,
reset,
pristine,
submitting,
toggleLeaseModal,
processingAdding,
} = props;
const Form = ({
handleSubmit,
reset,
pristine,
submitting,
processingAdding,
}) => {
const { t } = useTranslation();
const dispatch = useDispatch();
const onClick = () => {
reset();
dispatch(toggleLeaseModal());
};
return (
<form onSubmit={handleSubmit}>
@@ -61,10 +66,7 @@ const Form = (props) => {
type="button"
className="btn btn-secondary btn-standard"
disabled={submitting}
onClick={() => {
reset();
toggleLeaseModal();
}}
onClick={onClick}
>
<Trans>cancel_btn</Trans>
</button>
@@ -86,12 +88,7 @@ Form.propTypes = {
handleSubmit: PropTypes.func.isRequired,
reset: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired,
toggleLeaseModal: PropTypes.func.isRequired,
processingAdding: PropTypes.bool.isRequired,
t: PropTypes.func.isRequired,
};
export default flow([
withTranslation(),
reduxForm({ form: FORM_NAME.LEASE }),
])(Form);
export default reduxForm({ form: FORM_NAME.LEASE })(Form);

View File

@@ -2,36 +2,37 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Trans, withTranslation } from 'react-i18next';
import ReactModal from 'react-modal';
import { useDispatch } from 'react-redux';
import Form from './Form';
import { toggleLeaseModal } from '../../../../actions';
const Modal = (props) => {
const {
isModalOpen,
handleSubmit,
toggleLeaseModal,
processingAdding,
} = props;
const Modal = ({
isModalOpen,
handleSubmit,
processingAdding,
}) => {
const dispatch = useDispatch();
const toggleModal = () => dispatch(toggleLeaseModal());
return (
<ReactModal
className="Modal__Bootstrap modal-dialog modal-dialog-centered modal-dialog--clients"
closeTimeoutMS={0}
isOpen={isModalOpen}
onRequestClose={() => toggleLeaseModal()}
onRequestClose={toggleModal}
>
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">
<Trans>dhcp_new_static_lease</Trans>
</h4>
<button type="button" className="close" onClick={() => toggleLeaseModal()}>
<button type="button" className="close" onClick={toggleModal}>
<span className="sr-only">Close</span>
</button>
</div>
<Form
onSubmit={handleSubmit}
toggleLeaseModal={toggleLeaseModal}
processingAdding={processingAdding}
/>
</div>
@@ -42,7 +43,6 @@ const Modal = (props) => {
Modal.propTypes = {
isModalOpen: PropTypes.bool.isRequired,
handleSubmit: PropTypes.func.isRequired,
toggleLeaseModal: PropTypes.func.isRequired,
processingAdding: PropTypes.bool.isRequired,
};

View File

@@ -1,115 +1,116 @@
import React, { Component, Fragment } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import ReactTable from 'react-table';
import { Trans, withTranslation } from 'react-i18next';
import { Trans, useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { LEASES_TABLE_DEFAULT_PAGE_SIZE } from '../../../../helpers/constants';
import { sortIp } from '../../../../helpers/helpers';
import Modal from './Modal';
import { addStaticLease, removeStaticLease } from '../../../../actions';
class StaticLeases extends Component {
cellWrap = ({ value }) => (
<div className="logs__row o-hidden">
const cellWrap = ({ value }) => (
<div className="logs__row o-hidden">
<span className="logs__text" title={value}>
{value}
</span>
</div>
);
</div>
);
handleSubmit = (data) => {
this.props.addStaticLease(data);
const StaticLeases = ({
isModalOpen,
processingAdding,
processingDeleting,
staticLeases,
}) => {
const [t] = useTranslation();
const dispatch = useDispatch();
const handleSubmit = (data) => {
dispatch(addStaticLease(data));
};
handleDelete = (ip, mac, hostname = '') => {
const handleDelete = (ip, mac, hostname = '') => {
const name = hostname || ip;
// eslint-disable-next-line no-alert
if (window.confirm(this.props.t('delete_confirm', { key: name }))) {
this.props.removeStaticLease({ ip, mac, hostname });
if (window.confirm(t('delete_confirm', { key: name }))) {
dispatch(removeStaticLease({
ip,
mac,
hostname,
}));
}
};
render() {
const {
isModalOpen,
toggleLeaseModal,
processingAdding,
processingDeleting,
staticLeases,
t,
} = this.props;
return (
<Fragment>
<ReactTable
data={staticLeases || []}
columns={[
{
Header: 'MAC',
accessor: 'mac',
Cell: this.cellWrap,
},
{
Header: 'IP',
accessor: 'ip',
sortMethod: sortIp,
Cell: this.cellWrap,
},
{
Header: <Trans>dhcp_table_hostname</Trans>,
accessor: 'hostname',
Cell: this.cellWrap,
},
{
Header: <Trans>actions_table_header</Trans>,
accessor: 'actions',
maxWidth: 150,
Cell: (row) => {
const { ip, mac, hostname } = row.original;
return (
<>
<ReactTable
data={staticLeases || []}
columns={[
{
Header: 'MAC',
accessor: 'mac',
Cell: cellWrap,
},
{
Header: 'IP',
accessor: 'ip',
sortMethod: sortIp,
Cell: cellWrap,
},
{
Header: <Trans>dhcp_table_hostname</Trans>,
accessor: 'hostname',
Cell: cellWrap,
},
{
Header: <Trans>actions_table_header</Trans>,
accessor: 'actions',
maxWidth: 150,
// eslint-disable-next-line react/display-name
Cell: (row) => {
const { ip, mac, hostname } = row.original;
return (
<div className="logs__row logs__row--center">
<button
type="button"
className="btn btn-icon btn-icon--green btn-outline-secondary btn-sm"
title={t('delete_table_action')}
disabled={processingDeleting}
onClick={() => this.handleDelete(ip, mac, hostname)
}
>
<svg className="icons">
<use xlinkHref="#delete"/>
</svg>
</button>
</div>
);
},
return <div className="logs__row logs__row--center">
<button
type="button"
className="btn btn-icon btn-icon--green btn-outline-secondary btn-sm"
title={t('delete_table_action')}
disabled={processingDeleting}
onClick={() => handleDelete(ip, mac, hostname)}
>
<svg className="icons">
<use xlinkHref="#delete" />
</svg>
</button>
</div>;
},
]}
pageSize={LEASES_TABLE_DEFAULT_PAGE_SIZE}
showPageSizeOptions={false}
showPagination={staticLeases.length > LEASES_TABLE_DEFAULT_PAGE_SIZE}
noDataText={t('dhcp_static_leases_not_found')}
className="-striped -highlight card-table-overflow"
minRows={6}
/>
<Modal
isModalOpen={isModalOpen}
toggleLeaseModal={toggleLeaseModal}
handleSubmit={this.handleSubmit}
processingAdding={processingAdding}
/>
</Fragment>
);
}
}
},
]}
pageSize={LEASES_TABLE_DEFAULT_PAGE_SIZE}
showPageSizeOptions={false}
showPagination={staticLeases.length > LEASES_TABLE_DEFAULT_PAGE_SIZE}
noDataText={t('dhcp_static_leases_not_found')}
className="-striped -highlight card-table-overflow"
minRows={6}
/>
<Modal
isModalOpen={isModalOpen}
handleSubmit={handleSubmit}
processingAdding={processingAdding}
/>
</>
);
};
StaticLeases.propTypes = {
staticLeases: PropTypes.array.isRequired,
isModalOpen: PropTypes.bool.isRequired,
toggleLeaseModal: PropTypes.func.isRequired,
removeStaticLease: PropTypes.func.isRequired,
addStaticLease: PropTypes.func.isRequired,
processingAdding: PropTypes.bool.isRequired,
processingDeleting: PropTypes.bool.isRequired,
t: PropTypes.func.isRequired,
};
export default withTranslation()(StaticLeases);
cellWrap.propTypes = {
value: PropTypes.string.isRequired,
};
export default StaticLeases;