diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 73f5db5b..baa0d353 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "You can specify DNS upstream <0>for the specific domain(s)", "upstream_parallel": "Use parallel requests to speed up resolving by simultaneously querying all upstream servers", "parallel_requests": "Parallel requests", + "load_balancing": "Load-balancing", + "load_balancing_desc": "Query one server at a time. AdGuard Home will use the weighted random algorithm to pick the server so that the fastest server will be used more often.", "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.", "check_dhcp_servers": "Check for DHCP servers", diff --git a/client/src/components/Filters/Check/index.js b/client/src/components/Filters/Check/index.js index 463bb4a5..a15b62aa 100644 --- a/client/src/components/Filters/Check/index.js +++ b/client/src/components/Filters/Check/index.js @@ -7,6 +7,7 @@ import Card from '../../ui/Card'; import { renderInputField } from '../../../helpers/form'; import Info from './Info'; +import { FORM_NAME } from '../../../helpers/constants'; const Check = (props) => { const { @@ -60,7 +61,7 @@ const Check = (props) => { {check.hostname && ( -
+
{ const { @@ -19,18 +20,18 @@ const Form = (props) => { return (
-
- data.trim()} - /> -
+
+ data.trim()} + /> +
{ const { @@ -104,7 +105,7 @@ Form.propTypes = { export default flow([ withTranslation(), reduxForm({ - form: 'rewritesForm', + form: FORM_NAME.REWRITES, enableReinitialize: true, }), ])(Form); diff --git a/client/src/components/Filters/Services/Form.js b/client/src/components/Filters/Services/Form.js index 1b2b499a..4aed810d 100644 --- a/client/src/components/Filters/Services/Form.js +++ b/client/src/components/Filters/Services/Form.js @@ -6,7 +6,7 @@ import flow from 'lodash/flow'; import { toggleAllServices } from '../../../helpers/helpers'; import { renderServiceField } from '../../../helpers/form'; -import { SERVICES } from '../../../helpers/constants'; +import { FORM_NAME, SERVICES } from '../../../helpers/constants'; const Form = (props) => { const { @@ -84,7 +84,7 @@ Form.propTypes = { export default flow([ withTranslation(), reduxForm({ - form: 'servicesForm', + form: FORM_NAME.SERVICES, enableReinitialize: true, }), ])(Form); diff --git a/client/src/components/Logs/Filters/Form.js b/client/src/components/Logs/Filters/Form.js index 307694cb..9a10442f 100644 --- a/client/src/components/Logs/Filters/Form.js +++ b/client/src/components/Logs/Filters/Form.js @@ -5,7 +5,7 @@ import { withTranslation } from 'react-i18next'; import flow from 'lodash/flow'; import { renderInputField } from '../../../helpers/form'; -import { RESPONSE_FILTER } from '../../../helpers/constants'; +import { FORM_NAME, RESPONSE_FILTER } from '../../../helpers/constants'; import Tooltip from '../../ui/Tooltip'; const renderFilterField = ({ @@ -124,6 +124,6 @@ Form.propTypes = { export default flow([ withTranslation(), reduxForm({ - form: 'logsFilterForm', + form: FORM_NAME.LOGS_FILTER, }), ])(Form); diff --git a/client/src/components/Settings/Clients/Form.js b/client/src/components/Settings/Clients/Form.js index 5ac8faf8..5b2a49c4 100644 --- a/client/src/components/Settings/Clients/Form.js +++ b/client/src/components/Settings/Clients/Form.js @@ -20,7 +20,7 @@ import { renderSelectField, renderServiceField, } from '../../../helpers/form'; -import { SERVICES } from '../../../helpers/constants'; +import { FORM_NAME, SERVICES } from '../../../helpers/constants'; import './Service.css'; const settingsCheckboxes = [ @@ -338,7 +338,7 @@ Form.propTypes = { tagsOptions: PropTypes.array.isRequired, }; -const selector = formValueSelector('clientForm'); +const selector = formValueSelector(FORM_NAME.CLIENT); Form = connect((state) => { const useGlobalSettings = selector(state, 'use_global_settings'); @@ -352,7 +352,7 @@ Form = connect((state) => { export default flow([ withTranslation(), reduxForm({ - form: 'clientForm', + form: FORM_NAME.CLIENT, enableReinitialize: true, validate, }), diff --git a/client/src/components/Settings/Dhcp/Form.js b/client/src/components/Settings/Dhcp/Form.js index b319b495..6e0a134f 100644 --- a/client/src/components/Settings/Dhcp/Form.js +++ b/client/src/components/Settings/Dhcp/Form.js @@ -8,6 +8,7 @@ import flow from 'lodash/flow'; import { renderInputField, required, ipv4, isPositive, toNumber, } from '../../../helpers/form'; +import { FORM_NAME } from '../../../helpers/constants'; const renderInterfaces = ((interfaces) => ( Object.keys(interfaces).map((item) => { @@ -221,7 +222,7 @@ Form.propTypes = { change: PropTypes.func.isRequired, }; -const selector = formValueSelector('dhcpForm'); +const selector = formValueSelector(FORM_NAME.DHCP); Form = connect((state) => { const interfaceValue = selector(state, 'interface_name'); @@ -232,5 +233,5 @@ Form = connect((state) => { export default flow([ withTranslation(), - reduxForm({ form: 'dhcpForm' }), + reduxForm({ form: FORM_NAME.DHCP }), ])(Form); diff --git a/client/src/components/Settings/Dhcp/StaticLeases/Form.js b/client/src/components/Settings/Dhcp/StaticLeases/Form.js index b2924d78..9cbbb0a2 100644 --- a/client/src/components/Settings/Dhcp/StaticLeases/Form.js +++ b/client/src/components/Settings/Dhcp/StaticLeases/Form.js @@ -7,6 +7,7 @@ import flow from 'lodash/flow'; import { renderInputField, ipv4, mac, required, } from '../../../../helpers/form'; +import { FORM_NAME } from '../../../../helpers/constants'; const Form = (props) => { const { @@ -94,5 +95,5 @@ Form.propTypes = { export default flow([ withTranslation(), - reduxForm({ form: 'leaseForm' }), + reduxForm({ form: FORM_NAME.LEASE }), ])(Form); diff --git a/client/src/components/Settings/Dns/Access/Form.js b/client/src/components/Settings/Dns/Access/Form.js index 7cdec77a..bd7ca897 100644 --- a/client/src/components/Settings/Dns/Access/Form.js +++ b/client/src/components/Settings/Dns/Access/Form.js @@ -5,6 +5,7 @@ import { Trans, withTranslation } from 'react-i18next'; import flow from 'lodash/flow'; import { renderTextareaField } from '../../../../helpers/form'; import { normalizeMultiline } from '../../../../helpers/helpers'; +import { FORM_NAME } from '../../../../helpers/constants'; const fields = [ { @@ -84,4 +85,4 @@ Form.propTypes = { textarea: PropTypes.bool, }; -export default flow([withTranslation(), reduxForm({ form: 'accessForm' })])(Form); +export default flow([withTranslation(), reduxForm({ form: FORM_NAME.ACCESS })])(Form); diff --git a/client/src/components/Settings/Dns/Config/Form.js b/client/src/components/Settings/Dns/Config/Form.js index e24655e3..a137130e 100644 --- a/client/src/components/Settings/Dns/Config/Form.js +++ b/client/src/components/Settings/Dns/Config/Form.js @@ -15,7 +15,7 @@ import { biggerOrEqualZero, toNumber, } from '../../../../helpers/form'; -import { BLOCKING_MODES } from '../../../../helpers/constants'; +import { BLOCKING_MODES, FORM_NAME } from '../../../../helpers/constants'; const checkboxes = [{ name: 'edns_cs_enabled', @@ -60,91 +60,91 @@ const getFields = (processing, t) => Object.values(BLOCKING_MODES) let Form = ({ handleSubmit, submitting, invalid, processing, blockingMode, t, }) => -
-
-
- -
- rate_limit_desc -
- +
+
+
+ +
+ rate_limit_desc +
+ +
+
+ {checkboxes.map(({ name, placeholder, subtitle }) =>
+
+ +
+
)} +
+
+ +
+ {Object.values(BLOCKING_MODES) + .map((mode) => ( +
  • + {`blocking_mode_${mode}`} +
  • + ))} +
    +
    + {getFields(processing, t)}
    - {checkboxes.map(({ name, placeholder, subtitle }) =>
    +
    + {blockingMode === BLOCKING_MODES.custom_ip && ( + + {customIps.map(({ + description, + name, + validateIp, + }) =>
    + +
    + {description} +
    )} -
    -
    - -
    - {Object.values(BLOCKING_MODES) - .map((mode) => ( -
  • - {`blocking_mode_${mode}`} -
  • - ))} -
    -
    - {getFields(processing, t)} -
    -
    -
    - {blockingMode === BLOCKING_MODES.custom_ip && ( - - {customIps.map(({ - description, - name, - validateIp, - }) =>
    -
    - -
    - {description} -
    - -
    -
    )} -
    - )} -
    - - ; + + )} +
    + +; Form.propTypes = { blockingMode: PropTypes.string.isRequired, @@ -155,7 +155,7 @@ Form.propTypes = { t: PropTypes.func.isRequired, }; -const selector = formValueSelector('blockingModeForm'); +const selector = formValueSelector(FORM_NAME.BLOCKING_MODE); Form = connect((state) => { const blockingMode = selector(state, 'blocking_mode'); @@ -166,7 +166,5 @@ Form = connect((state) => { export default flow([ withTranslation(), - reduxForm({ - form: 'blockingModeForm', - }), + reduxForm({ form: FORM_NAME.BLOCKING_MODE }), ])(Form); diff --git a/client/src/components/Settings/Dns/Upstream/Form.js b/client/src/components/Settings/Dns/Upstream/Form.js index ec110d6d..99ae9a95 100644 --- a/client/src/components/Settings/Dns/Upstream/Form.js +++ b/client/src/components/Settings/Dns/Upstream/Form.js @@ -1,14 +1,14 @@ import React from 'react'; -import { connect } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import PropTypes from 'prop-types'; -import { Field, reduxForm, formValueSelector } from 'redux-form'; -import { Trans, withTranslation } from 'react-i18next'; -import flow from 'lodash/flow'; +import { Field, reduxForm } from 'redux-form'; +import { Trans, useTranslation } from 'react-i18next'; import classnames from 'classnames'; import Examples from './Examples'; import { renderRadioField } from '../../../../helpers/form'; -import { DNS_REQUEST_OPTIONS } from '../../../../helpers/constants'; +import { DNS_REQUEST_OPTIONS, FORM_NAME } from '../../../../helpers/constants'; +import { testUpstream } from '../../../../actions'; const getInputFields = () => [{ // eslint-disable-next-line react/display-name @@ -22,15 +22,23 @@ const getInputFields = () => [{ placeholder: 'upstream_dns', }, { - name: 'dnsRequestOption', + name: 'upstream_mode', type: 'radio', - value: DNS_REQUEST_OPTIONS.PARALLEL_REQUESTS, + value: DNS_REQUEST_OPTIONS.LOAD_BALANCING, + component: renderRadioField, + subtitle: 'load_balancing_desc', + placeholder: 'load_balancing', +}, +{ + name: 'upstream_mode', + type: 'radio', + value: DNS_REQUEST_OPTIONS.PARALLEL, component: renderRadioField, subtitle: 'upstream_parallel', placeholder: 'parallel_requests', }, { - name: 'dnsRequestOption', + name: 'upstream_mode', type: 'radio', value: DNS_REQUEST_OPTIONS.FASTEST_ADDR, component: renderRadioField, @@ -38,22 +46,22 @@ const getInputFields = () => [{ placeholder: 'fastest_addr', }]; -let Form = (props) => { - const { - t, - handleSubmit, - testUpstream, - submitting, - invalid, - processingSetConfig, - processingTestUpstream, +const Form = ({ + submitting, invalid, processingSetConfig, processingTestUpstream, handleSubmit, +}) => { + const dispatch = useDispatch(); + const [t] = useTranslation(); + const upstream_dns = useSelector((store) => store.form[FORM_NAME.UPSTREAM].values.upstream_dns); + const bootstrap_dns = useSelector((store) => store.form[FORM_NAME.UPSTREAM] + .values.bootstrap_dns); + + const handleUpstreamTest = () => dispatch(testUpstream({ upstream_dns, bootstrap_dns, - } = props; + })); - const testButtonClass = classnames({ - 'btn btn-primary btn-standard mr-2': true, - 'btn btn-primary btn-standard mr-2 btn-loading': processingTestUpstream, + const testButtonClass = classnames('btn btn-primary btn-standard mr-2', { + 'btn-loading': processingTestUpstream, }); const INPUT_FIELDS = getInputFields(); @@ -106,11 +114,7 @@ let Form = (props) => {