+ client: Allow `Fastest IP address` and `Parallel requests` to toggle each other: Merge pull request #619 in DNS/adguard-home from feature/1678 to master

Close #1678

Squashed commit of the following:

commit 9251ed0f1b58426104d1b9bdaa4b7af5f92be83e
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Thu May 21 18:25:18 2020 +0300

    + client: Allow `Fastest IP address` and `Parallel requests` to toggle each other
This commit is contained in:
Artem Baskal 2020-05-25 19:41:04 +03:00
parent 2f5073b720
commit 383507bc0c
6 changed files with 137 additions and 114 deletions

View File

@ -456,7 +456,7 @@
"disable_ipv6": "Disable IPv6",
"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",
"fastest_addr_desc": "Query all DNS servers and return the fastest IP address among all responses. This will slow down the DNS queries as we have to wait for responses from all DNS servers, but improve the overall connectivity.",
"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_result": "As a result all DNS requests from your system will be processed by AdGuard Home by default.",
@ -490,4 +490,4 @@
"list_updated_plural": "{{count}} lists updated",
"dnssec_enable": "Enable DNSSEC",
"dnssec_enable_desc": "Set DNSSEC flag in the outcoming DNS queries and check the result (DNSSEC-enabled resolver is required)"
}
}

View File

@ -19,18 +19,18 @@ const Form = (props) => {
return (
<form onSubmit={handleSubmit}>
<div className="modal-body">
<div className="form__group">
<Field
id="name"
name="name"
type="text"
component={renderInputField}
className="form-control"
placeholder={t('enter_name_hint')}
validate={[required]}
normalizeOnBlur={(data) => data.trim()}
/>
</div>
<div className="form__group">
<Field
id="name"
name="name"
type="text"
component={renderInputField}
className="form-control"
placeholder={t('enter_name_hint')}
validate={[required]}
normalizeOnBlur={(data) => data.trim()}
/>
</div>
<div className="form__group">
<Field
id="url"

View File

@ -5,11 +5,13 @@ import { Field, reduxForm, formValueSelector } from 'redux-form';
import { Trans, withTranslation } from 'react-i18next';
import flow from 'lodash/flow';
import classnames from 'classnames';
import { nanoid } from 'nanoid';
import Examples from './Examples';
import { renderSelectField } from '../../../../helpers/form';
import { renderRadioField } from '../../../../helpers/form';
import { DNS_REQUEST_OPTIONS } from '../../../../helpers/constants';
const getInputFields = (parallel_requests_selected, fastest_addr_selected) => [{
const getInputFields = () => [{
// eslint-disable-next-line react/display-name
getTitle: () => <label className="form__label" htmlFor="upstream_dns">
<Trans>upstream_dns</Trans>
@ -21,20 +23,20 @@ const getInputFields = (parallel_requests_selected, fastest_addr_selected) => [{
placeholder: 'upstream_dns',
},
{
name: 'parallel_requests',
placeholder: 'parallel_requests',
component: renderSelectField,
type: 'checkbox',
name: 'dnsRequestOption',
type: 'radio',
value: DNS_REQUEST_OPTIONS.PARALLEL_REQUESTS,
component: renderRadioField,
subtitle: 'upstream_parallel',
disabled: fastest_addr_selected,
placeholder: 'parallel_requests',
},
{
name: 'fastest_addr',
placeholder: 'fastest_addr',
component: renderSelectField,
type: 'checkbox',
name: 'dnsRequestOption',
type: 'radio',
value: DNS_REQUEST_OPTIONS.FASTEST_ADDR,
component: renderRadioField,
subtitle: 'fastest_addr_desc',
disabled: parallel_requests_selected,
placeholder: 'fastest_addr',
}];
let Form = (props) => {
@ -46,8 +48,6 @@ let Form = (props) => {
invalid,
processingSetConfig,
processingTestUpstream,
fastest_addr,
parallel_requests,
upstream_dns,
bootstrap_dns,
} = props;
@ -57,78 +57,77 @@ let Form = (props) => {
'btn btn-primary btn-standard mr-2 btn-loading': processingTestUpstream,
});
const INPUT_FIELDS = getInputFields(parallel_requests, fastest_addr);
const INPUT_FIELDS = getInputFields();
return (
<form onSubmit={handleSubmit}>
<div className="row">
{INPUT_FIELDS.map(({
name, component, type, className, placeholder, getTitle, subtitle, disabled,
}) => <div className="col-12 mb-4" key={name}>
{typeof getTitle === 'function' && getTitle()}
<Field
id={name}
name={name}
component={component}
type={type}
className={className}
placeholder={t(placeholder)}
subtitle={t(subtitle)}
disabled={processingSetConfig || processingTestUpstream || disabled}
/>
</div>)}
<div className="col-12">
<Examples />
<hr />
</div>
<div className="col-12 mb-4">
<label
className="form__label form__label--with-desc"
htmlFor="bootstrap_dns"
>
<Trans>bootstrap_dns</Trans>
</label>
<div className="form__desc form__desc--top">
<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 font-monospace"
placeholder={t('bootstrap_dns')}
disabled={processingSetConfig}
/>
</div>
return <form onSubmit={handleSubmit}>
<div className="row">
{INPUT_FIELDS.map(({
name, component, type, className, placeholder, getTitle, subtitle, disabled, value,
}) => <div className="col-12 mb-4" key={nanoid()}>
{typeof getTitle === 'function' && getTitle()}
<Field
id={name}
value={value}
name={name}
component={component}
type={type}
className={className}
placeholder={t(placeholder)}
subtitle={t(subtitle)}
disabled={processingSetConfig || processingTestUpstream || disabled}
/>
</div>)}
<div className="col-12">
<Examples />
<hr />
</div>
<div className="card-actions">
<div className="btn-list">
<button
type="button"
className={testButtonClass}
onClick={() => testUpstream({
upstream_dns,
bootstrap_dns,
})
}
disabled={!upstream_dns || processingTestUpstream}
>
<Trans>test_upstream_btn</Trans>
</button>
<button
type="submit"
className="btn btn-success btn-standard"
disabled={
submitting || invalid || processingSetConfig || processingTestUpstream
}
>
<Trans>apply_btn</Trans>
</button>
<div className="col-12 mb-4">
<label
className="form__label form__label--with-desc"
htmlFor="bootstrap_dns"
>
<Trans>bootstrap_dns</Trans>
</label>
<div className="form__desc form__desc--top">
<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 font-monospace"
placeholder={t('bootstrap_dns')}
disabled={processingSetConfig}
/>
</div>
</form>
);
</div>
<div className="card-actions">
<div className="btn-list">
<button
type="button"
className={testButtonClass}
onClick={() => testUpstream({
upstream_dns,
bootstrap_dns,
})
}
disabled={!upstream_dns || processingTestUpstream}
>
<Trans>test_upstream_btn</Trans>
</button>
<button
type="submit"
className="btn btn-success btn-standard"
disabled={
submitting || invalid || processingSetConfig || processingTestUpstream
}
>
<Trans>apply_btn</Trans>
</button>
</div>
</div>
</form>;
};
Form.propTypes = {
@ -139,8 +138,6 @@ Form.propTypes = {
initialValues: PropTypes.object,
upstream_dns: PropTypes.string,
bootstrap_dns: PropTypes.string,
fastest_addr: PropTypes.bool,
parallel_requests: PropTypes.bool,
processingTestUpstream: PropTypes.bool,
processingSetConfig: PropTypes.bool,
t: PropTypes.func,
@ -151,14 +148,10 @@ const selector = formValueSelector('upstreamForm');
Form = connect((state) => {
const upstream_dns = selector(state, 'upstream_dns');
const bootstrap_dns = selector(state, 'bootstrap_dns');
const fastest_addr = selector(state, 'fastest_addr');
const parallel_requests = selector(state, 'parallel_requests');
return {
upstream_dns,
bootstrap_dns,
fastest_addr,
parallel_requests,
};
})(Form);

View File

@ -1,13 +1,27 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withTranslation } from 'react-i18next';
import cn from 'classnames';
import Form from './Form';
import Card from '../../../ui/Card';
import { DNS_REQUEST_OPTIONS } from '../../../../helpers/constants';
class Upstream extends Component {
handleSubmit = (values) => {
this.props.setDnsConfig(values);
handleSubmit = ({ bootstrap_dns, upstream_dns, dnsRequestOption }) => {
const disabledOption = dnsRequestOption === DNS_REQUEST_OPTIONS.PARALLEL_REQUESTS
? DNS_REQUEST_OPTIONS.FASTEST_ADDR
: DNS_REQUEST_OPTIONS.PARALLEL_REQUESTS;
const formattedValues = {
bootstrap_dns,
upstream_dns,
[dnsRequestOption]: true,
[disabledOption]: false,
};
this.props.setDnsConfig(formattedValues);
};
handleTest = (values) => {
@ -27,6 +41,11 @@ class Upstream extends Component {
},
} = this.props;
const dnsRequestOption = cn({
parallel_requests,
fastest_addr,
});
return (
<Card
title={t('upstream_dns')}
@ -39,8 +58,7 @@ class Upstream extends Component {
initialValues={{
upstream_dns,
bootstrap_dns,
fastest_addr,
parallel_requests,
dnsRequestOption,
}}
testUpstream={this.handleTest}
onSubmit={this.handleSubmit}

View File

@ -374,3 +374,8 @@ export const ACTION = {
block: 'block',
unblock: 'unblock',
};
export const DNS_REQUEST_OPTIONS = {
PARALLEL_REQUESTS: 'parallel_requests',
FASTEST_ADDR: 'fastest_addr',
};

View File

@ -119,11 +119,19 @@ renderGroupField.propTypes = {
};
export const renderRadioField = ({
input, placeholder, disabled, meta: { touched, error },
input,
placeholder,
subtitle,
disabled,
meta: { touched, error },
}) => <Fragment>
<label className="custom-control custom-radio custom-control-inline">
<label className="custom-control custom-radio">
<input {...input} type="radio" className="custom-control-input" disabled={disabled} />
<span className="custom-control-label">{placeholder}</span>
{subtitle && <span
className="checkbox__label-subtitle"
dangerouslySetInnerHTML={{ __html: subtitle }}
/>}
</label>
{!disabled
&& touched
@ -133,6 +141,7 @@ export const renderRadioField = ({
renderRadioField.propTypes = {
input: PropTypes.object.isRequired,
placeholder: PropTypes.string,
subtitle: PropTypes.string,
disabled: PropTypes.bool,
meta: PropTypes.shape({
touched: PropTypes.bool,
@ -155,12 +164,10 @@ export const renderSelectField = ({
<span className="checkbox__label">
<span className="checkbox__label-text checkbox__label-text--long">
<span className="checkbox__label-title">{placeholder}</span>
{subtitle && (
<span
className="checkbox__label-subtitle"
dangerouslySetInnerHTML={{ __html: subtitle }}
/>
)}
{subtitle && <span
className="checkbox__label-subtitle"
dangerouslySetInnerHTML={{ __html: subtitle }}
/>}
</span>
</span>
</label>