Pull request #730: + client: Add Hot Module Replacement
Merge in DNS/adguard-home from feature/hmr to master
Squashed commit of the following:
commit 952ed1955c2a7a32446d99489f137f02eb47c99e
Merge: 83484931 de92c852
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Thu Aug 13 11:02:10 2020 +0300
Merge branch 'master' into feature/hmr
commit 8348493105d7d63d8b0836a5c272df2b17a6b142
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Wed Aug 5 15:07:31 2020 +0300
Remove empty prop types, remove Services empty container
commit b2fe4a30b79d91e482318ee5deea8e49c7038f7e
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Wed Aug 5 13:56:35 2020 +0300
Move constants
commit f8be4c18c35193ad77bf5e25f311ad834c1d6870
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Wed Aug 5 13:19:02 2020 +0300
Fix Setup bug, update webpack.dev
commit 1d9cc4ddf8af2c979eb707a7f0fc06744eec186c
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Wed Aug 5 12:10:38 2020 +0300
Review changes
commit a1edb21358def21ed1808b081ffc2f0b6755e3da
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Wed Aug 5 11:46:58 2020 +0300
Remove lazy loading, fix updated components
commit 0aa2cf55f8d4206ac9e2f99fc1b990ed8a9c7825
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Tue Aug 4 20:32:19 2020 +0300
Refactor App component, add lazy loading
commit 3c2ba4772a91ff7b06641dba6c6bf3fdcd2fdf7f
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Tue Aug 4 17:12:41 2020 +0300
Simplify App hot loading boilerplate, setup lazy loading, update Header
commit 8df3221f315372b066f2ac0c9a1687f1677b8415
Author: ArtemBaskal <a.baskal@adguard.com>
Date: Tue Aug 4 15:16:06 2020 +0300
+ client: Add Hot Module Replacement
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { Trans, withTranslation } from 'react-i18next';
|
||||
@@ -34,13 +34,14 @@ class Dhcp extends Component {
|
||||
} = this.props.dhcp;
|
||||
const otherDhcpFound = check?.otherServer
|
||||
&& check.otherServer.found === DHCP_STATUS_RESPONSE.YES;
|
||||
const filledConfig = Object.keys(config).every((key) => {
|
||||
if (key === 'enabled' || key === 'icmp_timeout_msec') {
|
||||
return true;
|
||||
}
|
||||
const filledConfig = Object.keys(config)
|
||||
.every((key) => {
|
||||
if (key === 'enabled' || key === 'icmp_timeout_msec') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return config[key];
|
||||
});
|
||||
return config[key];
|
||||
});
|
||||
|
||||
if (config.enabled) {
|
||||
return (
|
||||
@@ -114,40 +115,35 @@ class Dhcp extends Component {
|
||||
|
||||
getStaticIpWarning = (t, check, interfaceName) => {
|
||||
if (check.staticIP.static === DHCP_STATUS_RESPONSE.ERROR) {
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="text-danger mb-2">
|
||||
<Trans>dhcp_static_ip_error</Trans>
|
||||
<div className="mt-2 mb-2">
|
||||
<Accordion label={t('error_details')}>
|
||||
<span>{check.staticIP.error}</span>
|
||||
</Accordion>
|
||||
</div>
|
||||
return <>
|
||||
<div className="text-danger mb-2">
|
||||
<Trans>dhcp_static_ip_error</Trans>
|
||||
<div className="mt-2 mb-2">
|
||||
<Accordion label={t('error_details')}>
|
||||
<span>{check.staticIP.error}</span>
|
||||
</Accordion>
|
||||
</div>
|
||||
<hr className="mt-4 mb-4" />
|
||||
</Fragment>
|
||||
);
|
||||
} if (
|
||||
check.staticIP.static === DHCP_STATUS_RESPONSE.NO
|
||||
</div>
|
||||
<hr className="mt-4 mb-4" />
|
||||
</>;
|
||||
}
|
||||
if (check.staticIP.static === DHCP_STATUS_RESPONSE.NO
|
||||
&& check.staticIP.ip
|
||||
&& interfaceName
|
||||
) {
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="text-secondary mb-2">
|
||||
<Trans
|
||||
components={[<strong key="0">example</strong>]}
|
||||
values={{
|
||||
interfaceName,
|
||||
ipAddress: check.staticIP.ip,
|
||||
}}
|
||||
>
|
||||
dhcp_dynamic_ip_found
|
||||
</Trans>
|
||||
</div>
|
||||
<hr className="mt-4 mb-4" />
|
||||
</Fragment>
|
||||
);
|
||||
&& interfaceName) {
|
||||
return <>
|
||||
<div className="text-secondary mb-2">
|
||||
<Trans
|
||||
components={[<strong key="0">example</strong>]}
|
||||
values={{
|
||||
interfaceName,
|
||||
ipAddress: check.staticIP.ip,
|
||||
}}
|
||||
>
|
||||
dhcp_dynamic_ip_found
|
||||
</Trans>
|
||||
</div>
|
||||
<hr className="mt-4 mb-4" />
|
||||
</>;
|
||||
}
|
||||
|
||||
return '';
|
||||
@@ -163,104 +159,101 @@ class Dhcp extends Component {
|
||||
removeStaticLease,
|
||||
toggleLeaseModal,
|
||||
} = this.props;
|
||||
|
||||
const statusButtonClass = classnames({
|
||||
'btn btn-primary btn-standard': true,
|
||||
'btn btn-primary btn-standard btn-loading': dhcp.processingStatus,
|
||||
});
|
||||
const { enabled, interface_name, ...values } = dhcp.config;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<PageTitle title={t('dhcp_settings')} />
|
||||
{(dhcp.processing || dhcp.processingInterfaces) && <Loading />}
|
||||
{!dhcp.processing && !dhcp.processingInterfaces && (
|
||||
<Fragment>
|
||||
<Card
|
||||
title={t('dhcp_title')}
|
||||
subtitle={t('dhcp_description')}
|
||||
bodyType="card-body box-body--settings"
|
||||
>
|
||||
<div className="dhcp">
|
||||
<Fragment>
|
||||
<Form
|
||||
onSubmit={this.handleFormSubmit}
|
||||
initialValues={{
|
||||
interface_name,
|
||||
...values,
|
||||
}}
|
||||
interfaces={dhcp.interfaces}
|
||||
processingConfig={dhcp.processingConfig}
|
||||
processingInterfaces={dhcp.processingInterfaces}
|
||||
enabled={enabled}
|
||||
resetDhcp={resetDhcp}
|
||||
/>
|
||||
<hr />
|
||||
<div className="card-actions mb-3">
|
||||
{this.getToggleDhcpButton()}
|
||||
<button
|
||||
type="button"
|
||||
className={statusButtonClass}
|
||||
onClick={() => findActiveDhcp(interface_name)}
|
||||
disabled={
|
||||
enabled || !interface_name || dhcp.processingConfig
|
||||
}
|
||||
>
|
||||
<Trans>check_dhcp_servers</Trans>
|
||||
</button>
|
||||
</div>
|
||||
{!enabled && dhcp.check && (
|
||||
<Fragment>
|
||||
{this.getStaticIpWarning(t, dhcp.check, interface_name)}
|
||||
{this.getActiveDhcpMessage(t, dhcp.check)}
|
||||
{this.getDhcpWarning(dhcp.check)}
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
return <>
|
||||
<PageTitle title={t('dhcp_settings')} />
|
||||
{(dhcp.processing || dhcp.processingInterfaces) && <Loading />}
|
||||
{!dhcp.processing && !dhcp.processingInterfaces && <>
|
||||
<Card
|
||||
title={t('dhcp_title')}
|
||||
subtitle={t('dhcp_description')}
|
||||
bodyType="card-body box-body--settings"
|
||||
>
|
||||
<div className="dhcp">
|
||||
<>
|
||||
<Form
|
||||
onSubmit={this.handleFormSubmit}
|
||||
initialValues={{
|
||||
interface_name,
|
||||
...values,
|
||||
}}
|
||||
interfaces={dhcp.interfaces}
|
||||
processingConfig={dhcp.processingConfig}
|
||||
processingInterfaces={dhcp.processingInterfaces}
|
||||
enabled={enabled}
|
||||
resetDhcp={resetDhcp}
|
||||
/>
|
||||
<hr />
|
||||
<div className="card-actions mb-3">
|
||||
{this.getToggleDhcpButton()}
|
||||
<button
|
||||
type="button"
|
||||
className={statusButtonClass}
|
||||
onClick={() => findActiveDhcp(interface_name)}
|
||||
disabled={
|
||||
enabled || !interface_name || dhcp.processingConfig
|
||||
}
|
||||
>
|
||||
<Trans>check_dhcp_servers</Trans>
|
||||
</button>
|
||||
</div>
|
||||
</Card>
|
||||
{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>
|
||||
)}
|
||||
<Card
|
||||
title={t('dhcp_static_leases')}
|
||||
bodyType="card-body box-body--settings"
|
||||
>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<StaticLeases
|
||||
staticLeases={dhcp.staticLeases}
|
||||
isModalOpen={dhcp.isModalOpen}
|
||||
addStaticLease={addStaticLease}
|
||||
removeStaticLease={removeStaticLease}
|
||||
toggleLeaseModal={toggleLeaseModal}
|
||||
processingAdding={dhcp.processingAdding}
|
||||
processingDeleting={dhcp.processingDeleting}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-success btn-standard mt-3"
|
||||
onClick={() => toggleLeaseModal()}
|
||||
>
|
||||
<Trans>dhcp_add_static_lease</Trans>
|
||||
</button>
|
||||
</div>
|
||||
{!enabled && dhcp.check && (
|
||||
<>
|
||||
{this.getStaticIpWarning(t, dhcp.check, interface_name)}
|
||||
{this.getActiveDhcpMessage(t, dhcp.check)}
|
||||
{this.getDhcpWarning(dhcp.check)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
</Card>
|
||||
{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>
|
||||
</Card>
|
||||
</Fragment>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
<Card
|
||||
title={t('dhcp_static_leases')}
|
||||
bodyType="card-body box-body--settings"
|
||||
>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<StaticLeases
|
||||
staticLeases={dhcp.staticLeases}
|
||||
isModalOpen={dhcp.isModalOpen}
|
||||
addStaticLease={addStaticLease}
|
||||
removeStaticLease={removeStaticLease}
|
||||
toggleLeaseModal={toggleLeaseModal}
|
||||
processingAdding={dhcp.processingAdding}
|
||||
processingDeleting={dhcp.processingDeleting}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-success btn-standard mt-3"
|
||||
onClick={() => toggleLeaseModal()}
|
||||
>
|
||||
<Trans>dhcp_add_static_lease</Trans>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</>}
|
||||
</>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,36 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
import Form from './Form';
|
||||
import Card from '../../../ui/Card';
|
||||
import { setAccessList } from '../../../../actions/access';
|
||||
|
||||
class Access extends Component {
|
||||
handleFormSubmit = (values) => {
|
||||
this.props.setAccessList(values);
|
||||
const Access = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
processing,
|
||||
processingSet,
|
||||
...values
|
||||
} = useSelector((state) => state.access, shallowEqual);
|
||||
|
||||
const handleFormSubmit = (values) => {
|
||||
dispatch(setAccessList(values));
|
||||
};
|
||||
|
||||
render() {
|
||||
const { t, access } = this.props;
|
||||
|
||||
const { processing, processingSet, ...values } = access;
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={t('access_title')}
|
||||
subtitle={t('access_desc')}
|
||||
bodyType="card-body box-body--settings"
|
||||
>
|
||||
<Form
|
||||
initialValues={values}
|
||||
onSubmit={this.handleFormSubmit}
|
||||
processingSet={processingSet}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Access.propTypes = {
|
||||
access: PropTypes.object.isRequired,
|
||||
setAccessList: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired,
|
||||
return (
|
||||
<Card
|
||||
title={t('access_title')}
|
||||
subtitle={t('access_desc')}
|
||||
bodyType="card-body box-body--settings"
|
||||
>
|
||||
<Form
|
||||
initialValues={values}
|
||||
onSubmit={handleFormSubmit}
|
||||
processingSet={processingSet}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation()(Access);
|
||||
export default Access;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { Field, reduxForm, formValueSelector } from 'redux-form';
|
||||
import { Trans, withTranslation } from 'react-i18next';
|
||||
import flow from 'lodash/flow';
|
||||
import { shallowEqual, useSelector } from 'react-redux';
|
||||
import { Field, reduxForm } from 'redux-form';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import {
|
||||
renderInputField,
|
||||
renderRadioField,
|
||||
@@ -18,32 +17,36 @@ import {
|
||||
} from '../../../../helpers/validators';
|
||||
import { BLOCKING_MODES, FORM_NAME } from '../../../../helpers/constants';
|
||||
|
||||
const checkboxes = [{
|
||||
name: 'edns_cs_enabled',
|
||||
placeholder: 'edns_enable',
|
||||
subtitle: 'edns_cs_desc',
|
||||
},
|
||||
{
|
||||
name: 'dnssec_enabled',
|
||||
placeholder: 'dnssec_enable',
|
||||
subtitle: 'dnssec_enable_desc',
|
||||
},
|
||||
{
|
||||
name: 'disable_ipv6',
|
||||
placeholder: 'disable_ipv6',
|
||||
subtitle: 'disable_ipv6_desc',
|
||||
}];
|
||||
const checkboxes = [
|
||||
{
|
||||
name: 'edns_cs_enabled',
|
||||
placeholder: 'edns_enable',
|
||||
subtitle: 'edns_cs_desc',
|
||||
},
|
||||
{
|
||||
name: 'dnssec_enabled',
|
||||
placeholder: 'dnssec_enable',
|
||||
subtitle: 'dnssec_enable_desc',
|
||||
},
|
||||
{
|
||||
name: 'disable_ipv6',
|
||||
placeholder: 'disable_ipv6',
|
||||
subtitle: 'disable_ipv6_desc',
|
||||
},
|
||||
];
|
||||
|
||||
const customIps = [{
|
||||
description: 'blocking_ipv4_desc',
|
||||
name: 'blocking_ipv4',
|
||||
validateIp: validateIpv4,
|
||||
},
|
||||
{
|
||||
description: 'blocking_ipv6_desc',
|
||||
name: 'blocking_ipv6',
|
||||
validateIp: validateIpv6,
|
||||
}];
|
||||
const customIps = [
|
||||
{
|
||||
description: 'blocking_ipv4_desc',
|
||||
name: 'blocking_ipv4',
|
||||
validateIp: validateIpv4,
|
||||
},
|
||||
{
|
||||
description: 'blocking_ipv6_desc',
|
||||
name: 'blocking_ipv6',
|
||||
validateIp: validateIpv6,
|
||||
},
|
||||
];
|
||||
|
||||
const getFields = (processing, t) => Object.values(BLOCKING_MODES)
|
||||
.map((mode) => (
|
||||
@@ -58,114 +61,107 @@ const getFields = (processing, t) => Object.values(BLOCKING_MODES)
|
||||
/>
|
||||
));
|
||||
|
||||
let Form = ({
|
||||
handleSubmit, submitting, invalid, processing, blockingMode, t,
|
||||
}) => <form onSubmit={handleSubmit}>
|
||||
<div className="row">
|
||||
<div className="col-12 col-sm-6">
|
||||
<div className="form__group form__group--settings">
|
||||
<label htmlFor="ratelimit"
|
||||
className="form__label form__label--with-desc">
|
||||
<Trans>rate_limit</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
<Trans>rate_limit_desc</Trans>
|
||||
</div>
|
||||
<Field
|
||||
name="ratelimit"
|
||||
type="number"
|
||||
component={renderInputField}
|
||||
className="form-control"
|
||||
placeholder={t('form_enter_rate_limit')}
|
||||
normalize={toNumber}
|
||||
validate={[validateRequiredValue, validateBiggerOrEqualZeroValue]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{checkboxes.map(({ name, placeholder, subtitle }) => <div className="col-12" key={name}>
|
||||
<div className="form__group form__group--settings">
|
||||
<Field
|
||||
name={name}
|
||||
type="checkbox"
|
||||
component={renderSelectField}
|
||||
placeholder={t(placeholder)}
|
||||
disabled={processing}
|
||||
subtitle={t(subtitle)}
|
||||
/>
|
||||
</div>
|
||||
</div>)}
|
||||
<div className="col-12">
|
||||
<div className="form__group form__group--settings mb-4">
|
||||
<label className="form__label form__label--with-desc">
|
||||
<Trans>blocking_mode</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
{Object.values(BLOCKING_MODES)
|
||||
.map((mode) => (
|
||||
<li key={mode}>
|
||||
<Trans>{`blocking_mode_${mode}`}</Trans>
|
||||
</li>
|
||||
))}
|
||||
</div>
|
||||
<div className="custom-controls-stacked">
|
||||
{getFields(processing, t)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{blockingMode === BLOCKING_MODES.custom_ip && (
|
||||
<Fragment>
|
||||
{customIps.map(({
|
||||
description,
|
||||
name,
|
||||
validateIp,
|
||||
}) => <div className="col-12 col-sm-6" key={name}>
|
||||
<div className="form__group form__group--settings">
|
||||
<label className="form__label form__label--with-desc"
|
||||
htmlFor={name}><Trans>{name}</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
<Trans>{description}</Trans>
|
||||
</div>
|
||||
<Field
|
||||
name={name}
|
||||
component={renderInputField}
|
||||
className="form-control"
|
||||
placeholder={t('form_enter_ip')}
|
||||
validate={[validateIp, validateRequiredValue]}
|
||||
/>
|
||||
const Form = ({
|
||||
handleSubmit, submitting, invalid, processing,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
blocking_mode,
|
||||
} = useSelector((state) => state.form[FORM_NAME.BLOCKING_MODE].values ?? {}, shallowEqual);
|
||||
|
||||
return <form onSubmit={handleSubmit}>
|
||||
<div className="row">
|
||||
<div className="col-12 col-sm-6">
|
||||
<div className="form__group form__group--settings">
|
||||
<label htmlFor="ratelimit"
|
||||
className="form__label form__label--with-desc">
|
||||
<Trans>rate_limit</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
<Trans>rate_limit_desc</Trans>
|
||||
</div>
|
||||
</div>)}
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-success btn-standard btn-large"
|
||||
disabled={submitting || invalid || processing}
|
||||
>
|
||||
<Trans>save_btn</Trans>
|
||||
</button>
|
||||
</form>;
|
||||
<Field
|
||||
name="ratelimit"
|
||||
type="number"
|
||||
component={renderInputField}
|
||||
className="form-control"
|
||||
placeholder={t('form_enter_rate_limit')}
|
||||
normalize={toNumber}
|
||||
validate={[validateRequiredValue, validateBiggerOrEqualZeroValue]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{checkboxes.map(({ name, placeholder, subtitle }) => <div className="col-12" key={name}>
|
||||
<div className="form__group form__group--settings">
|
||||
<Field
|
||||
name={name}
|
||||
type="checkbox"
|
||||
component={renderSelectField}
|
||||
placeholder={t(placeholder)}
|
||||
disabled={processing}
|
||||
subtitle={t(subtitle)}
|
||||
/>
|
||||
</div>
|
||||
</div>)}
|
||||
<div className="col-12">
|
||||
<div className="form__group form__group--settings mb-4">
|
||||
<label className="form__label form__label--with-desc">
|
||||
<Trans>blocking_mode</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
{Object.values(BLOCKING_MODES)
|
||||
.map((mode) => (
|
||||
<li key={mode}>
|
||||
<Trans>{`blocking_mode_${mode}`}</Trans>
|
||||
</li>
|
||||
))}
|
||||
</div>
|
||||
<div className="custom-controls-stacked">
|
||||
{getFields(processing, t)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{blocking_mode === BLOCKING_MODES.custom_ip && (
|
||||
<>
|
||||
{customIps.map(({
|
||||
description,
|
||||
name,
|
||||
validateIp,
|
||||
}) => <div className="col-12 col-sm-6" key={name}>
|
||||
<div className="form__group form__group--settings">
|
||||
<label className="form__label form__label--with-desc"
|
||||
htmlFor={name}><Trans>{name}</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
<Trans>{description}</Trans>
|
||||
</div>
|
||||
<Field
|
||||
name={name}
|
||||
component={renderInputField}
|
||||
className="form-control"
|
||||
placeholder={t('form_enter_ip')}
|
||||
validate={[validateIp, validateRequiredValue]}
|
||||
/>
|
||||
</div>
|
||||
</div>)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-success btn-standard btn-large"
|
||||
disabled={submitting || invalid || processing}
|
||||
>
|
||||
<Trans>save_btn</Trans>
|
||||
</button>
|
||||
</form>;
|
||||
};
|
||||
|
||||
Form.propTypes = {
|
||||
blockingMode: PropTypes.string.isRequired,
|
||||
handleSubmit: PropTypes.func.isRequired,
|
||||
submitting: PropTypes.bool.isRequired,
|
||||
invalid: PropTypes.bool.isRequired,
|
||||
processing: PropTypes.bool.isRequired,
|
||||
t: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const selector = formValueSelector(FORM_NAME.BLOCKING_MODE);
|
||||
|
||||
Form = connect((state) => {
|
||||
const blockingMode = selector(state, 'blocking_mode');
|
||||
return {
|
||||
blockingMode,
|
||||
};
|
||||
})(Form);
|
||||
|
||||
export default flow([
|
||||
withTranslation(),
|
||||
reduxForm({ form: FORM_NAME.BLOCKING_MODE }),
|
||||
])(Form);
|
||||
export default reduxForm({ form: FORM_NAME.BLOCKING_MODE })(Form);
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
import Card from '../../../ui/Card';
|
||||
import Form from './Form';
|
||||
import { setDnsConfig } from '../../../../actions/dnsConfig';
|
||||
|
||||
const Config = ({ t, dnsConfig, setDnsConfig }) => {
|
||||
const handleFormSubmit = (values) => {
|
||||
setDnsConfig(values);
|
||||
};
|
||||
|
||||
const Config = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
blocking_mode,
|
||||
ratelimit,
|
||||
@@ -19,7 +17,11 @@ const Config = ({ t, dnsConfig, setDnsConfig }) => {
|
||||
dnssec_enabled,
|
||||
disable_ipv6,
|
||||
processingSetConfig,
|
||||
} = dnsConfig;
|
||||
} = useSelector((state) => state.dnsConfig, shallowEqual);
|
||||
|
||||
const handleFormSubmit = (values) => {
|
||||
dispatch(setDnsConfig(values));
|
||||
};
|
||||
|
||||
return (
|
||||
<Card
|
||||
@@ -46,10 +48,4 @@ const Config = ({ t, dnsConfig, setDnsConfig }) => {
|
||||
);
|
||||
};
|
||||
|
||||
Config.propTypes = {
|
||||
dnsConfig: PropTypes.object.isRequired,
|
||||
setDnsConfig: PropTypes.func.isRequired,
|
||||
t: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default withTranslation()(Config);
|
||||
export default Config;
|
||||
|
||||
@@ -1,29 +1,26 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { shallowEqual, useDispatch } from 'react-redux';
|
||||
import Form from './Form';
|
||||
import Card from '../../../ui/Card';
|
||||
import { setDnsConfig } from '../../../../actions/dnsConfig';
|
||||
|
||||
const Upstream = (props) => {
|
||||
const [t] = useTranslation();
|
||||
const Upstream = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
upstream_dns,
|
||||
bootstrap_dns,
|
||||
upstream_mode,
|
||||
processingSetConfig,
|
||||
} = ((state) => state.dnsConfig, shallowEqual);
|
||||
|
||||
const { processingTestUpstream } = ((state) => state.settings, shallowEqual);
|
||||
|
||||
const handleSubmit = (values) => {
|
||||
dispatch(setDnsConfig(values));
|
||||
};
|
||||
|
||||
const {
|
||||
processingTestUpstream,
|
||||
dnsConfig: {
|
||||
upstream_dns,
|
||||
bootstrap_dns,
|
||||
processingSetConfig,
|
||||
upstream_mode,
|
||||
},
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={t('upstream_dns')}
|
||||
@@ -48,9 +45,4 @@ const Upstream = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Upstream.propTypes = {
|
||||
processingTestUpstream: PropTypes.bool.isRequired,
|
||||
dnsConfig: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default Upstream;
|
||||
|
||||
@@ -1,67 +1,40 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import Upstream from './Upstream';
|
||||
import Access from './Access';
|
||||
import Config from './Config';
|
||||
import PageTitle from '../../ui/PageTitle';
|
||||
import Loading from '../../ui/Loading';
|
||||
import CacheConfig from './Cache';
|
||||
import { getDnsConfig } from '../../../actions/dnsConfig';
|
||||
import { getAccessList } from '../../../actions/access';
|
||||
|
||||
const Dns = (props) => {
|
||||
const Dns = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const processing = useSelector((state) => state.access.processing);
|
||||
const processingGetConfig = useSelector((state) => state.dnsConfig.processingGetConfig);
|
||||
|
||||
const isDataLoading = processing || processingGetConfig;
|
||||
|
||||
useEffect(() => {
|
||||
props.getAccessList();
|
||||
props.getDnsConfig();
|
||||
dispatch(getAccessList());
|
||||
dispatch(getDnsConfig());
|
||||
}, []);
|
||||
|
||||
const {
|
||||
settings,
|
||||
access,
|
||||
setAccessList,
|
||||
dnsConfig,
|
||||
setDnsConfig,
|
||||
} = props;
|
||||
|
||||
const isDataLoading = access.processing || dnsConfig.processingGetConfig;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={t('dns_settings')} />
|
||||
{isDataLoading
|
||||
? <Loading />
|
||||
: <>
|
||||
<Upstream
|
||||
processingTestUpstream={settings.processingTestUpstream}
|
||||
dnsConfig={dnsConfig}
|
||||
/>
|
||||
<Config
|
||||
dnsConfig={dnsConfig}
|
||||
setDnsConfig={setDnsConfig}
|
||||
/>
|
||||
<CacheConfig
|
||||
dnsConfig={dnsConfig}
|
||||
setDnsConfig={setDnsConfig}
|
||||
/>
|
||||
<Access
|
||||
access={access}
|
||||
setAccessList={setAccessList}
|
||||
/>
|
||||
</>}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Dns.propTypes = {
|
||||
settings: PropTypes.object.isRequired,
|
||||
getAccessList: PropTypes.func.isRequired,
|
||||
setAccessList: PropTypes.func.isRequired,
|
||||
access: PropTypes.object.isRequired,
|
||||
dnsConfig: PropTypes.object.isRequired,
|
||||
setDnsConfig: PropTypes.func.isRequired,
|
||||
getDnsConfig: PropTypes.func.isRequired,
|
||||
return <>
|
||||
<PageTitle title={t('dns_settings')} />
|
||||
{isDataLoading
|
||||
? <Loading />
|
||||
: <>
|
||||
<Upstream />
|
||||
<Config />
|
||||
<CacheConfig />
|
||||
<Access />
|
||||
</>}
|
||||
</>;
|
||||
};
|
||||
|
||||
export default Dns;
|
||||
|
||||
Reference in New Issue
Block a user