+ client: add fastest_addr setting

Squashed commit of the following:

commit e47fae25f7bac950bfb452fc8f18b9c0865b08ba
Merge: a23285ec e2ddc82d
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Wed Apr 22 19:16:01 2020 +0300

    Merge remote-tracking branch 'origin/master' into 715

commit a23285ec3ace78fe4ce19122a51ecf3e6cdd942c
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed Apr 22 18:30:30 2020 +0300

    Review changes

commit f80d62a0d2038ff9d070ae9e9c77c33b92232d9c
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Tue Apr 21 16:37:42 2020 +0300

    + client: Add fastest addr option

commit 9e713df80c5bf113c98794c0a20915c756a76938
Merge: e3bf4037 9b7c1181
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Tue Apr 21 16:02:03 2020 +0300

    Merge remote-tracking branch 'origin/master' into 715-fastest-addr

commit e3bf4037f49198e42bde55305d6f9077341b556a
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Tue Apr 21 15:40:49 2020 +0300

    minor

commit d6e6a823c5e51acc061b2850d362772efcb827e1
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Apr 17 17:56:24 2020 +0300

    * API changes

    . removed POST /set_upstreams_config
    . removed fields from GET /status: bootstrap_dns, upstream_dns, all_servers
    . added new fields to /dns_config and /dns_info

commit 237a452d09cc48ff8f00e81c7fd35e7828bea835
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Apr 17 16:43:13 2020 +0300

    * API: /dns_info, /dns_config: add "parallel_requests" instead of "all_servers" from /set_upstreams_config

commit 9976723b9725ed19e0cce152d1d1198b13c4acc1
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Mon Mar 23 10:28:25 2020 +0300

    openapi

commit 6f8ea16c6332606f29095b0094d71e8a91798f82
Merge: 36e4d4e8 c8285c41
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Mar 20 19:18:48 2020 +0300

    Merge remote-tracking branch 'origin/master' into 715-fastest-addr

commit 36e4d4e82cadeaba5a11313f0d69d66a0924c342
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Mar 20 18:13:43 2020 +0300

    + DNS: add fastest_addr setting
This commit is contained in:
Artem Baskal 2020-04-22 19:32:07 +03:00
parent e2ddc82d70
commit 0ffc0965dc
13 changed files with 233 additions and 296 deletions

View file

@ -1,7 +1,8 @@
{ {
"client_settings": "Client settings", "client_settings": "Client settings",
"example_upstream_reserved": "you can specify DNS upstream <0>for a specific domain(s)</0>", "example_upstream_reserved": "You can specify DNS upstream <0>for the specific domain(s)</0>",
"upstream_parallel": "Use parallel queries to speed up resolving by simultaneously querying all upstream servers", "upstream_parallel": "Use parallel requests to speed up resolving by simultaneously querying all upstream servers",
"parallel_requests": "Parallel requests",
"bootstrap_dns": "Bootstrap DNS servers", "bootstrap_dns": "Bootstrap DNS servers",
"bootstrap_dns_desc": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.", "bootstrap_dns_desc": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.",
"check_dhcp_servers": "Check for DHCP servers", "check_dhcp_servers": "Check for DHCP servers",
@ -453,6 +454,8 @@
"example_rewrite_wildcard": "rewrite responses for all <0>example.org</0> subdomains.", "example_rewrite_wildcard": "rewrite responses for all <0>example.org</0> subdomains.",
"disable_ipv6": "Disable IPv6", "disable_ipv6": "Disable IPv6",
"disable_ipv6_desc": "If this feature is enabled, all DNS queries for IPv6 addresses (type AAAA) will be dropped.", "disable_ipv6_desc": "If this feature is enabled, all DNS queries for IPv6 addresses (type AAAA) will be dropped.",
"fastest_addr": "Fastest IP address",
"fastest_addr_desc": "Query all DNS servers and return the fastest IP address among all responses",
"autofix_warning_text": "If you click \"Fix\", AdGuard Home will configure your system to use AdGuard Home DNS server.", "autofix_warning_text": "If you click \"Fix\", AdGuard Home will configure your system to use AdGuard Home DNS server.",
"autofix_warning_list": "It will perform these tasks: <0>Deactivate system DNSStubListener</0> <0>Set DNS server address to 127.0.0.1</0> <0>Replace symbolic link target of /etc/resolv.conf with /run/systemd/resolve/resolv.conf</0> <0>Stop DNSStubListener (reload systemd-resolved service)</0>", "autofix_warning_list": "It will perform these tasks: <0>Deactivate system DNSStubListener</0> <0>Set DNS server address to 127.0.0.1</0> <0>Replace symbolic link target of /etc/resolv.conf with /run/systemd/resolve/resolv.conf</0> <0>Stop DNSStubListener (reload systemd-resolved service)</0>",
"autofix_warning_result": "As a result all DNS requests from your system will be processed by AdGuard Home by default.", "autofix_warning_result": "As a result all DNS requests from your system will be processed by AdGuard Home by default.",

View file

@ -2,6 +2,7 @@ import { createAction } from 'redux-actions';
import apiClient from '../api/Api'; import apiClient from '../api/Api';
import { addErrorToast, addSuccessToast } from './index'; import { addErrorToast, addSuccessToast } from './index';
import { normalizeTextarea } from '../helpers/helpers';
export const getDnsConfigRequest = createAction('GET_DNS_CONFIG_REQUEST'); export const getDnsConfigRequest = createAction('GET_DNS_CONFIG_REQUEST');
export const getDnsConfigFailure = createAction('GET_DNS_CONFIG_FAILURE'); export const getDnsConfigFailure = createAction('GET_DNS_CONFIG_FAILURE');
@ -25,8 +26,26 @@ export const setDnsConfigSuccess = createAction('SET_DNS_CONFIG_SUCCESS');
export const setDnsConfig = config => async (dispatch) => { export const setDnsConfig = config => async (dispatch) => {
dispatch(setDnsConfigRequest()); dispatch(setDnsConfigRequest());
try { try {
await apiClient.setDnsConfig(config); const data = { ...config };
dispatch(addSuccessToast('config_successfully_saved'));
let hasDnsSettings = false;
if (Object.prototype.hasOwnProperty.call(data, 'bootstrap_dns')) {
data.bootstrap_dns = normalizeTextarea(config.bootstrap_dns);
hasDnsSettings = true;
}
if (Object.prototype.hasOwnProperty.call(data, 'upstream_dns')) {
data.upstream_dns = normalizeTextarea(config.upstream_dns);
hasDnsSettings = true;
}
await apiClient.setDnsConfig(data);
if (hasDnsSettings) {
dispatch(addSuccessToast('updated_upstream_dns_toast'));
} else {
dispatch(addSuccessToast('config_successfully_saved'));
}
dispatch(setDnsConfigSuccess(config)); dispatch(setDnsConfigSuccess(config));
} catch (error) { } catch (error) {
dispatch(addErrorToast({ error })); dispatch(addErrorToast({ error }));

View file

@ -244,6 +244,7 @@ export const getDnsStatus = () => async (dispatch) => {
dispatch(dnsStatusFailure()); dispatch(dnsStatusFailure());
window.location.reload(true); window.location.reload(true);
}; };
const handleRequestSuccess = (response) => { const handleRequestSuccess = (response) => {
const dnsStatus = response.data; const dnsStatus = response.data;
const { running } = dnsStatus; const { running } = dnsStatus;
@ -265,42 +266,6 @@ export const getDnsStatus = () => async (dispatch) => {
} }
}; };
export const getDnsSettingsRequest = createAction('GET_DNS_SETTINGS_REQUEST');
export const getDnsSettingsFailure = createAction('GET_DNS_SETTINGS_FAILURE');
export const getDnsSettingsSuccess = createAction('GET_DNS_SETTINGS_SUCCESS');
export const getDnsSettings = () => async (dispatch) => {
dispatch(getDnsSettingsRequest());
try {
const dnsStatus = await apiClient.getGlobalStatus();
dispatch(getDnsSettingsSuccess(dnsStatus));
} catch (error) {
dispatch(addErrorToast({ error }));
dispatch(getDnsSettingsFailure());
}
};
export const handleUpstreamChange = createAction('HANDLE_UPSTREAM_CHANGE');
export const setUpstreamRequest = createAction('SET_UPSTREAM_REQUEST');
export const setUpstreamFailure = createAction('SET_UPSTREAM_FAILURE');
export const setUpstreamSuccess = createAction('SET_UPSTREAM_SUCCESS');
export const setUpstream = config => async (dispatch) => {
dispatch(setUpstreamRequest());
try {
const values = { ...config };
values.bootstrap_dns = normalizeTextarea(values.bootstrap_dns);
values.upstream_dns = normalizeTextarea(values.upstream_dns);
await apiClient.setUpstream(values);
dispatch(addSuccessToast('updated_upstream_dns_toast'));
dispatch(setUpstreamSuccess(config));
} catch (error) {
dispatch(addErrorToast({ error }));
dispatch(setUpstreamFailure());
}
};
export const testUpstreamRequest = createAction('TEST_UPSTREAM_REQUEST'); export const testUpstreamRequest = createAction('TEST_UPSTREAM_REQUEST');
export const testUpstreamFailure = createAction('TEST_UPSTREAM_FAILURE'); export const testUpstreamFailure = createAction('TEST_UPSTREAM_FAILURE');
export const testUpstreamSuccess = createAction('TEST_UPSTREAM_SUCCESS'); export const testUpstreamSuccess = createAction('TEST_UPSTREAM_SUCCESS');

View file

@ -32,7 +32,6 @@ class Api {
// Global methods // Global methods
GLOBAL_STATUS = { path: 'status', method: 'GET' }; GLOBAL_STATUS = { path: 'status', method: 'GET' };
GLOBAL_SET_UPSTREAM_DNS = { path: 'set_upstreams_config', method: 'POST' };
GLOBAL_TEST_UPSTREAM_DNS = { path: 'test_upstream_dns', method: 'POST' }; GLOBAL_TEST_UPSTREAM_DNS = { path: 'test_upstream_dns', method: 'POST' };
GLOBAL_VERSION = { path: 'version.json', method: 'POST' }; GLOBAL_VERSION = { path: 'version.json', method: 'POST' };
GLOBAL_UPDATE = { path: 'update', method: 'POST' }; GLOBAL_UPDATE = { path: 'update', method: 'POST' };
@ -42,15 +41,6 @@ class Api {
return this.makeRequest(path, method); return this.makeRequest(path, method);
} }
setUpstream(url) {
const { path, method } = this.GLOBAL_SET_UPSTREAM_DNS;
const config = {
data: url,
headers: { 'Content-Type': 'application/json' },
};
return this.makeRequest(path, method, config);
}
testUpstream(servers) { testUpstream(servers) {
const { path, method } = this.GLOBAL_TEST_UPSTREAM_DNS; const { path, method } = this.GLOBAL_TEST_UPSTREAM_DNS;
const config = { const config = {

View file

@ -17,26 +17,55 @@ import {
} from '../../../../helpers/form'; } from '../../../../helpers/form';
import { BLOCKING_MODES } from '../../../../helpers/constants'; import { BLOCKING_MODES } from '../../../../helpers/constants';
const getFields = (processing, t) => Object.values(BLOCKING_MODES).map(mode => ( const checkboxes = [{
<Field name: 'edns_cs_enabled',
key={mode} placeholder: 'edns_enable',
name="blocking_mode" subtitle: 'edns_cs_desc',
type="radio" },
component={renderRadioField} {
value={mode} name: 'dnssec_enabled',
placeholder={t(mode)} placeholder: 'dnssec_enable',
disabled={processing} subtitle: 'dnssec_enable_desc',
/> },
)); {
name: 'disable_ipv6',
placeholder: 'disable_ipv6',
subtitle: 'disable_ipv6_desc',
}];
const customIps = [{
description: 'blocking_ipv4_desc',
name: 'blocking_ipv4',
validateIp: ipv4,
},
{
description: 'blocking_ipv6_desc',
name: 'blocking_ipv6',
validateIp: ipv6,
}];
const getFields = (processing, t) => Object.values(BLOCKING_MODES)
.map(mode => (
<Field
key={mode}
name="blocking_mode"
type="radio"
component={renderRadioField}
value={mode}
placeholder={t(mode)}
disabled={processing}
/>
));
let Form = ({ let Form = ({
handleSubmit, submitting, invalid, processing, blockingMode, t, handleSubmit, submitting, invalid, processing, blockingMode, t,
}) => ( }) =>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="row"> <div className="row">
<div className="col-12 col-sm-6"> <div className="col-12 col-sm-6">
<div className="form__group form__group--settings"> <div className="form__group form__group--settings">
<label htmlFor="ratelimit" className="form__label form__label--with-desc"> <label htmlFor="ratelimit"
className="form__label form__label--with-desc">
<Trans>rate_limit</Trans> <Trans>rate_limit</Trans>
</label> </label>
<div className="form__desc form__desc--top"> <div className="form__desc form__desc--top">
@ -53,53 +82,31 @@ let Form = ({
/> />
</div> </div>
</div> </div>
<div className="col-12"> {checkboxes.map(({ name, placeholder, subtitle }) =>
<div className="form__group form__group--settings"> <div className="col-12" key={name}>
<Field <div className="form__group form__group--settings">
name="edns_cs_enabled" <Field
type="checkbox" name={name}
component={renderSelectField} type="checkbox"
placeholder={t('edns_enable')} component={renderSelectField}
disabled={processing} placeholder={t(placeholder)}
subtitle={t('edns_cs_desc')} disabled={processing}
/> subtitle={t(subtitle)}
</div> />
</div> </div>
<div className="col-12"> </div>)}
<div className="form__group form__group--settings">
<Field
name="dnssec_enabled"
type="checkbox"
component={renderSelectField}
placeholder={t('dnssec_enable')}
disabled={processing}
subtitle={t('dnssec_enable_desc')}
/>
</div>
</div>
<div className="col-12">
<div className="form__group form__group--settings">
<Field
name="disable_ipv6"
type="checkbox"
component={renderSelectField}
placeholder={t('disable_ipv6')}
disabled={processing}
subtitle={t('disable_ipv6_desc')}
/>
</div>
</div>
<div className="col-12"> <div className="col-12">
<div className="form__group form__group--settings mb-4"> <div className="form__group form__group--settings mb-4">
<label className="form__label form__label--with-desc"> <label className="form__label form__label--with-desc">
<Trans>blocking_mode</Trans> <Trans>blocking_mode</Trans>
</label> </label>
<div className="form__desc form__desc--top"> <div className="form__desc form__desc--top">
{Object.values(BLOCKING_MODES).map(mode => ( {Object.values(BLOCKING_MODES)
<li key={mode}> .map(mode => (
<Trans >{`blocking_mode_${mode}`}</Trans> <li key={mode}>
</li> <Trans>{`blocking_mode_${mode}`}</Trans>
))} </li>
))}
</div> </div>
<div className="custom-controls-stacked"> <div className="custom-controls-stacked">
{getFields(processing, t)} {getFields(processing, t)}
@ -108,40 +115,27 @@ let Form = ({
</div> </div>
{blockingMode === BLOCKING_MODES.custom_ip && ( {blockingMode === BLOCKING_MODES.custom_ip && (
<Fragment> <Fragment>
<div className="col-12 col-sm-6"> {customIps.map(({
description,
name,
validateIp,
}) => <div className="col-12 col-sm-6" key={name}>
<div className="form__group form__group--settings"> <div className="form__group form__group--settings">
<label htmlFor="blocking_ipv4" className="form__label form__label--with-desc"> <label className="form__label form__label--with-desc"
<Trans>blocking_ipv4</Trans> htmlFor={name}><Trans>{name}</Trans>
</label> </label>
<div className="form__desc form__desc--top"> <div className="form__desc form__desc--top">
<Trans>blocking_ipv4_desc</Trans> <Trans>{description}</Trans>
</div> </div>
<Field <Field
name="blocking_ipv4" name={name}
component={renderInputField} component={renderInputField}
className="form-control" className="form-control"
placeholder={t('form_enter_ip')} placeholder={t('form_enter_ip')}
validate={[ipv4, required]} validate={[validateIp, required]}
/> />
</div> </div>
</div> </div>)}
<div className="col-12 col-sm-6">
<div className="form__group form__group--settings">
<label htmlFor="ip_address" className="form__label form__label--with-desc">
<Trans>blocking_ipv6</Trans>
</label>
<div className="form__desc form__desc--top">
<Trans>blocking_ipv6_desc</Trans>
</div>
<Field
name="blocking_ipv6"
component={renderInputField}
className="form-control"
placeholder={t('form_enter_ip')}
validate={[ipv6, required]}
/>
</div>
</div>
</Fragment> </Fragment>
)} )}
</div> </div>
@ -152,8 +146,7 @@ let Form = ({
> >
<Trans>save_btn</Trans> <Trans>save_btn</Trans>
</button> </button>
</form> </form>;
);
Form.propTypes = { Form.propTypes = {
blockingMode: PropTypes.string.isRequired, blockingMode: PropTypes.string.isRequired,

View file

@ -6,21 +6,50 @@ import { Trans, withNamespaces } from 'react-i18next';
import flow from 'lodash/flow'; import flow from 'lodash/flow';
import classnames from 'classnames'; import classnames from 'classnames';
import { renderSelectField } from '../../../../helpers/form';
import Examples from './Examples'; import Examples from './Examples';
import { renderSelectField } from '../../../../helpers/form';
const getInputFields = (parallel_requests_selected, fastest_addr_selected) => [{
// eslint-disable-next-line react/display-name
getTitle: () => <label className="form__label" htmlFor="upstream_dns">
<Trans>upstream_dns</Trans>
</label>,
name: 'upstream_dns',
type: 'text',
component: 'textarea',
className: 'form-control form-control--textarea',
placeholder: 'upstream_dns',
},
{
name: 'parallel_requests',
placeholder: 'parallel_requests',
component: renderSelectField,
type: 'checkbox',
subtitle: 'upstream_parallel',
disabled: fastest_addr_selected,
},
{
name: 'fastest_addr',
placeholder: 'fastest_addr',
component: renderSelectField,
type: 'checkbox',
subtitle: 'fastest_addr_desc',
disabled: parallel_requests_selected,
}];
let Form = (props) => { let Form = (props) => {
const { const {
t, t,
handleSubmit, handleSubmit,
testUpstream, testUpstream,
upstreamDns,
bootstrapDns,
allServers,
submitting, submitting,
invalid, invalid,
processingSetUpstream, processingSetConfig,
processingTestUpstream, processingTestUpstream,
fastest_addr,
parallel_requests,
upstream_dns,
bootstrap_dns,
} = props; } = props;
const testButtonClass = classnames({ const testButtonClass = classnames({
@ -28,61 +57,49 @@ let Form = (props) => {
'btn btn-primary btn-standard mr-2 btn-loading': processingTestUpstream, 'btn btn-primary btn-standard mr-2 btn-loading': processingTestUpstream,
}); });
const INPUT_FIELDS = getInputFields(parallel_requests, fastest_addr);
return ( return (
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className="row"> <div className="row">
<div className="col-12"> {INPUT_FIELDS.map(({
<div className="form__group form__group--settings"> name, component, type, className, placeholder, getTitle, subtitle, disabled,
<label className="form__label" htmlFor="upstream_dns"> }) => <div className="col-12 mb-4" key={name}>
<Trans>upstream_dns</Trans> {typeof getTitle === 'function' && getTitle()}
</label> <Field
<Field id={name}
id="upstream_dns" name={name}
name="upstream_dns" component={component}
component="textarea" type={type}
type="text" className={className}
className="form-control form-control--textarea" placeholder={t(placeholder)}
placeholder={t('upstream_dns')} subtitle={t(subtitle)}
disabled={processingSetUpstream || processingTestUpstream} disabled={processingSetConfig || processingTestUpstream || disabled}
/> />
</div> </div>)}
</div>
<div className="col-12">
<div className="form__group form__group--settings">
<Field
name="all_servers"
type="checkbox"
component={renderSelectField}
placeholder={t('upstream_parallel')}
disabled={processingSetUpstream}
/>
</div>
</div>
<div className="col-12"> <div className="col-12">
<Examples /> <Examples />
<hr /> <hr />
</div> </div>
<div className="col-12"> <div className="col-12 mb-4">
<div className="form__group"> <label
<label className="form__label form__label--with-desc"
className="form__label form__label--with-desc" htmlFor="bootstrap_dns"
htmlFor="bootstrap_dns" >
> <Trans>bootstrap_dns</Trans>
<Trans>bootstrap_dns</Trans> </label>
</label> <div className="form__desc form__desc--top">
<div className="form__desc form__desc--top"> <Trans>bootstrap_dns_desc</Trans>
<Trans>bootstrap_dns_desc</Trans>
</div>
<Field
id="bootstrap_dns"
name="bootstrap_dns"
component="textarea"
type="text"
className="form-control form-control--textarea form-control--textarea-small"
placeholder={t('bootstrap_dns')}
disabled={processingSetUpstream}
/>
</div> </div>
<Field
id="bootstrap_dns"
name="bootstrap_dns"
component="textarea"
type="text"
className="form-control form-control--textarea form-control--textarea-small"
placeholder={t('bootstrap_dns')}
disabled={processingSetConfig}
/>
</div> </div>
</div> </div>
<div className="card-actions"> <div className="card-actions">
@ -92,12 +109,11 @@ let Form = (props) => {
className={testButtonClass} className={testButtonClass}
onClick={() => onClick={() =>
testUpstream({ testUpstream({
upstream_dns: upstreamDns, upstream_dns,
bootstrap_dns: bootstrapDns, bootstrap_dns,
all_servers: allServers,
}) })
} }
disabled={!upstreamDns || processingTestUpstream} disabled={!upstream_dns || processingTestUpstream}
> >
<Trans>test_upstream_btn</Trans> <Trans>test_upstream_btn</Trans>
</button> </button>
@ -105,7 +121,7 @@ let Form = (props) => {
type="submit" type="submit"
className="btn btn-success btn-standard" className="btn btn-success btn-standard"
disabled={ disabled={
submitting || invalid || processingSetUpstream || processingTestUpstream submitting || invalid || processingSetConfig || processingTestUpstream
} }
> >
<Trans>apply_btn</Trans> <Trans>apply_btn</Trans>
@ -122,24 +138,28 @@ Form.propTypes = {
submitting: PropTypes.bool, submitting: PropTypes.bool,
invalid: PropTypes.bool, invalid: PropTypes.bool,
initialValues: PropTypes.object, initialValues: PropTypes.object,
upstreamDns: PropTypes.string, upstream_dns: PropTypes.string,
bootstrapDns: PropTypes.string, bootstrap_dns: PropTypes.string,
allServers: PropTypes.bool, fastest_addr: PropTypes.bool,
parallel_requests: PropTypes.bool,
processingTestUpstream: PropTypes.bool, processingTestUpstream: PropTypes.bool,
processingSetUpstream: PropTypes.bool, processingSetConfig: PropTypes.bool,
t: PropTypes.func, t: PropTypes.func,
}; };
const selector = formValueSelector('upstreamForm'); const selector = formValueSelector('upstreamForm');
Form = connect((state) => { Form = connect((state) => {
const upstreamDns = selector(state, 'upstream_dns'); const upstream_dns = selector(state, 'upstream_dns');
const bootstrapDns = selector(state, 'bootstrap_dns'); const bootstrap_dns = selector(state, 'bootstrap_dns');
const allServers = selector(state, 'all_servers'); const fastest_addr = selector(state, 'fastest_addr');
const parallel_requests = selector(state, 'parallel_requests');
return { return {
upstreamDns, upstream_dns,
bootstrapDns, bootstrap_dns,
allServers, fastest_addr,
parallel_requests,
}; };
})(Form); })(Form);

View file

@ -7,7 +7,7 @@ import Card from '../../../ui/Card';
class Upstream extends Component { class Upstream extends Component {
handleSubmit = (values) => { handleSubmit = (values) => {
this.props.setUpstream(values); this.props.setDnsConfig(values);
}; };
handleTest = (values) => { handleTest = (values) => {
@ -17,11 +17,14 @@ class Upstream extends Component {
render() { render() {
const { const {
t, t,
upstreamDns: upstream_dns,
bootstrapDns: bootstrap_dns,
allServers: all_servers,
processingSetUpstream,
processingTestUpstream, processingTestUpstream,
dnsConfig: {
upstream_dns,
bootstrap_dns,
fastest_addr,
parallel_requests,
processingSetConfig,
},
} = this.props; } = this.props;
return ( return (
@ -36,12 +39,13 @@ class Upstream extends Component {
initialValues={{ initialValues={{
upstream_dns, upstream_dns,
bootstrap_dns, bootstrap_dns,
all_servers, fastest_addr,
parallel_requests,
}} }}
testUpstream={this.handleTest} testUpstream={this.handleTest}
onSubmit={this.handleSubmit} onSubmit={this.handleSubmit}
processingTestUpstream={processingTestUpstream} processingTestUpstream={processingTestUpstream}
processingSetUpstream={processingSetUpstream} processingSetConfig={processingSetConfig}
/> />
</div> </div>
</div> </div>
@ -51,14 +55,11 @@ class Upstream extends Component {
} }
Upstream.propTypes = { Upstream.propTypes = {
upstreamDns: PropTypes.string,
bootstrapDns: PropTypes.string,
allServers: PropTypes.bool,
setUpstream: PropTypes.func.isRequired,
testUpstream: PropTypes.func.isRequired, testUpstream: PropTypes.func.isRequired,
processingSetUpstream: PropTypes.bool.isRequired,
processingTestUpstream: PropTypes.bool.isRequired, processingTestUpstream: PropTypes.bool.isRequired,
t: PropTypes.func.isRequired, t: PropTypes.func.isRequired,
dnsConfig: PropTypes.object.isRequired,
setDnsConfig: PropTypes.func.isRequired,
}; };
export default withNamespaces()(Upstream); export default withNamespaces()(Upstream);

View file

@ -10,7 +10,6 @@ import Loading from '../../ui/Loading';
class Dns extends Component { class Dns extends Component {
componentDidMount() { componentDidMount() {
this.props.getDnsSettings();
this.props.getAccessList(); this.props.getAccessList();
this.props.getDnsConfig(); this.props.getDnsConfig();
} }
@ -18,59 +17,45 @@ class Dns extends Component {
render() { render() {
const { const {
t, t,
dashboard,
settings, settings,
access, access,
setAccessList, setAccessList,
testUpstream, testUpstream,
setUpstream,
dnsConfig, dnsConfig,
setDnsConfig, setDnsConfig,
} = this.props; } = this.props;
const isDataLoading = dashboard.processingDnsSettings const isDataLoading = access.processing || dnsConfig.processingGetConfig;
|| access.processing
|| dnsConfig.processingGetConfig;
const isDataReady = !dashboard.processingDnsSettings
&& !access.processing
&& !dnsConfig.processingGetConfig;
return ( return (
<Fragment> <Fragment>
<PageTitle title={t('dns_settings')} /> <PageTitle title={t('dns_settings')} />
{isDataLoading && <Loading />} {isDataLoading ?
{isDataReady && ( <Loading /> :
<Fragment> <Fragment>
<Config <Config
dnsConfig={dnsConfig} dnsConfig={dnsConfig}
setDnsConfig={setDnsConfig} setDnsConfig={setDnsConfig}
/> />
<Upstream <Upstream
upstreamDns={dashboard.upstreamDns}
bootstrapDns={dashboard.bootstrapDns}
allServers={dashboard.allServers}
processingTestUpstream={settings.processingTestUpstream} processingTestUpstream={settings.processingTestUpstream}
processingSetUpstream={settings.processingSetUpstream}
setUpstream={setUpstream}
testUpstream={testUpstream} testUpstream={testUpstream}
dnsConfig={dnsConfig}
setDnsConfig={setDnsConfig}
/> />
<Access access={access} setAccessList={setAccessList} /> <Access access={access} setAccessList={setAccessList} />
</Fragment> </Fragment>}
)}
</Fragment> </Fragment>
); );
} }
} }
Dns.propTypes = { Dns.propTypes = {
dashboard: PropTypes.object.isRequired,
settings: PropTypes.object.isRequired, settings: PropTypes.object.isRequired,
setUpstream: PropTypes.func.isRequired,
testUpstream: PropTypes.func.isRequired, testUpstream: PropTypes.func.isRequired,
getAccessList: PropTypes.func.isRequired, getAccessList: PropTypes.func.isRequired,
setAccessList: PropTypes.func.isRequired, setAccessList: PropTypes.func.isRequired,
access: PropTypes.object.isRequired, access: PropTypes.object.isRequired,
getDnsSettings: PropTypes.func.isRequired,
dnsConfig: PropTypes.object.isRequired, dnsConfig: PropTypes.object.isRequired,
setDnsConfig: PropTypes.func.isRequired, setDnsConfig: PropTypes.func.isRequired,
getDnsConfig: PropTypes.func.isRequired, getDnsConfig: PropTypes.func.isRequired,

View file

@ -83,6 +83,7 @@
.checkbox__input:disabled + .checkbox__label { .checkbox__input:disabled + .checkbox__label {
cursor: default; cursor: default;
color: var(--gray);
} }
.checkbox__input:disabled + .checkbox__label:before { .checkbox__input:disabled + .checkbox__label:before {

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { handleUpstreamChange, setUpstream, testUpstream, getDnsSettings } from '../actions'; import { testUpstream } from '../actions';
import { getAccessList, setAccessList } from '../actions/access'; import { getAccessList, setAccessList } from '../actions/access';
import { import {
getRewritesList, getRewritesList,
@ -25,8 +25,6 @@ const mapStateToProps = (state) => {
}; };
const mapDispatchToProps = { const mapDispatchToProps = {
handleUpstreamChange,
setUpstream,
testUpstream, testUpstream,
getAccessList, getAccessList,
setAccessList, setAccessList,
@ -34,7 +32,6 @@ const mapDispatchToProps = {
addRewrite, addRewrite,
deleteRewrite, deleteRewrite,
toggleRewritesModal, toggleRewritesModal,
getDnsSettings,
getDnsConfig, getDnsConfig,
setDnsConfig, setDnsConfig,
}; };

View file

@ -117,29 +117,30 @@ export const renderSelectField = ({
placeholder, placeholder,
subtitle, subtitle,
disabled, disabled,
onClick,
modifier = 'checkbox--form', modifier = 'checkbox--form',
meta: { touched, error }, meta: { touched, error },
}) => ( }) => (
<Fragment> <Fragment>
<label className={`checkbox ${modifier}`}> <label className={`checkbox ${modifier}`} onClick={onClick}>
<span className="checkbox__marker" /> <span className="checkbox__marker" />
<input {...input} type="checkbox" className="checkbox__input" disabled={disabled} /> <input {...input} type="checkbox" className="checkbox__input" disabled={disabled} />
<span className="checkbox__label"> <span className="checkbox__label">
<span className="checkbox__label-text checkbox__label-text--long"> <span className="checkbox__label-text checkbox__label-text--long">
<span className="checkbox__label-title">{placeholder}</span> <span className="checkbox__label-title">{placeholder}</span>
{subtitle && ( {subtitle && (
<span <span
className="checkbox__label-subtitle" className="checkbox__label-subtitle"
dangerouslySetInnerHTML={{ __html: subtitle }} dangerouslySetInnerHTML={{ __html: subtitle }}
/> />
)} )}
</span>
</span> </span>
</span> </label>
</label> {!disabled &&
{!disabled && touched &&
touched && (error && <span className="form__message form__message--error">{error}</span>)}
(error && <span className="form__message form__message--error">{error}</span>)} </Fragment>
</Fragment>
); );
export const renderServiceField = ({ export const renderServiceField = ({

View file

@ -15,6 +15,8 @@ const dnsConfig = handleActions(
const { const {
blocking_ipv4, blocking_ipv4,
blocking_ipv6, blocking_ipv6,
upstream_dns,
bootstrap_dns,
...values ...values
} = payload; } = payload;
@ -23,6 +25,8 @@ const dnsConfig = handleActions(
...values, ...values,
blocking_ipv4: blocking_ipv4 || DEFAULT_BLOCKING_IPV4, blocking_ipv4: blocking_ipv4 || DEFAULT_BLOCKING_IPV4,
blocking_ipv6: blocking_ipv6 || DEFAULT_BLOCKING_IPV6, blocking_ipv6: blocking_ipv6 || DEFAULT_BLOCKING_IPV6,
upstream_dns: (upstream_dns && upstream_dns.join('\n')) || '',
bootstrap_dns: (bootstrap_dns && bootstrap_dns.join('\n')) || '',
processingGetConfig: false, processingGetConfig: false,
}; };
}, },

View file

@ -35,14 +35,6 @@ const settings = handleActions(
const newSettingsList = { ...settingsList, [settingKey]: newSetting }; const newSettingsList = { ...settingsList, [settingKey]: newSetting };
return { ...state, settingsList: newSettingsList }; return { ...state, settingsList: newSettingsList };
}, },
[actions.setUpstreamRequest]: state => ({ ...state, processingSetUpstream: true }),
[actions.setUpstreamFailure]: state => ({ ...state, processingSetUpstream: false }),
[actions.setUpstreamSuccess]: (state, { payload }) => ({
...state,
...payload,
processingSetUpstream: false,
}),
[actions.testUpstreamRequest]: state => ({ ...state, processingTestUpstream: true }), [actions.testUpstreamRequest]: state => ({ ...state, processingTestUpstream: true }),
[actions.testUpstreamFailure]: state => ({ ...state, processingTestUpstream: false }), [actions.testUpstreamFailure]: state => ({ ...state, processingTestUpstream: false }),
[actions.testUpstreamSuccess]: state => ({ ...state, processingTestUpstream: false }), [actions.testUpstreamSuccess]: state => ({ ...state, processingTestUpstream: false }),
@ -50,7 +42,6 @@ const settings = handleActions(
{ {
processing: true, processing: true,
processingTestUpstream: false, processingTestUpstream: false,
processingSetUpstream: false,
processingDhcpStatus: false, processingDhcpStatus: false,
settingsList: {}, settingsList: {},
}, },
@ -67,12 +58,9 @@ const dashboard = handleActions(
version, version,
dns_port: dnsPort, dns_port: dnsPort,
dns_addresses: dnsAddresses, dns_addresses: dnsAddresses,
upstream_dns: upstreamDns,
bootstrap_dns: bootstrapDns,
all_servers: allServers,
protection_enabled: protectionEnabled, protection_enabled: protectionEnabled,
language,
http_port: httpPort, http_port: httpPort,
language,
} = payload; } = payload;
const newState = { const newState = {
...state, ...state,
@ -81,9 +69,6 @@ const dashboard = handleActions(
dnsVersion: version, dnsVersion: version,
dnsPort, dnsPort,
dnsAddresses, dnsAddresses,
upstreamDns: (upstreamDns && upstreamDns.join('\n')) || '',
bootstrapDns: (bootstrapDns && bootstrapDns.join('\n')) || '',
allServers,
protectionEnabled, protectionEnabled,
language, language,
httpPort, httpPort,
@ -138,11 +123,6 @@ const dashboard = handleActions(
return newState; return newState;
}, },
[actions.handleUpstreamChange]: (state, { payload }) => {
const { upstreamDns } = payload;
return { ...state, upstreamDns };
},
[actions.getLanguageSuccess]: (state, { payload }) => { [actions.getLanguageSuccess]: (state, { payload }) => {
const newState = { ...state, language: payload }; const newState = { ...state, language: payload };
return newState; return newState;
@ -159,24 +139,6 @@ const dashboard = handleActions(
return newState; return newState;
}, },
[actions.getDnsSettingsRequest]: state => ({ ...state, processingDnsSettings: true }),
[actions.getDnsSettingsFailure]: state => ({ ...state, processingDnsSettings: false }),
[actions.getDnsSettingsSuccess]: (state, { payload }) => {
const {
upstream_dns: upstreamDns,
bootstrap_dns: bootstrapDns,
all_servers: allServers,
} = payload;
return {
...state,
allServers,
upstreamDns: (upstreamDns && upstreamDns.join('\n')) || '',
bootstrapDns: (bootstrapDns && bootstrapDns.join('\n')) || '',
processingDnsSettings: false,
};
},
[actions.getProfileRequest]: state => ({ ...state, processingProfile: true }), [actions.getProfileRequest]: state => ({ ...state, processingProfile: true }),
[actions.getProfileFailure]: state => ({ ...state, processingProfile: false }), [actions.getProfileFailure]: state => ({ ...state, processingProfile: false }),
[actions.getProfileSuccess]: (state, { payload }) => ({ [actions.getProfileSuccess]: (state, { payload }) => ({
@ -191,11 +153,7 @@ const dashboard = handleActions(
processingVersion: true, processingVersion: true,
processingClients: true, processingClients: true,
processingUpdate: false, processingUpdate: false,
processingDnsSettings: true,
processingProfile: true, processingProfile: true,
upstreamDns: '',
bootstrapDns: '',
allServers: false,
protectionEnabled: false, protectionEnabled: false,
processingProtection: false, processingProtection: false,
httpPort: 80, httpPort: 80,