mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-11-23 13:35:38 +03:00
* client: installation wizard additional checks
This commit is contained in:
parent
9e68a522cb
commit
f76b7c3d94
8 changed files with 156 additions and 26 deletions
|
@ -257,5 +257,7 @@
|
|||
"reset_settings": "Reset settings",
|
||||
"update_announcement": "AdGuard Home {{version}} is now available! <0>Click here<\/0> for more info.",
|
||||
"setup_guide": "Setup guide",
|
||||
"dns_addresses": "DNS addresses"
|
||||
"dns_addresses": "DNS addresses",
|
||||
"down": "Down",
|
||||
"fix": "Fix"
|
||||
}
|
|
@ -44,3 +44,18 @@ export const setAllSettings = values => async (dispatch) => {
|
|||
dispatch(prevStep());
|
||||
}
|
||||
};
|
||||
|
||||
export const checkConfigRequest = createAction('CHECK_CONFIG_REQUEST');
|
||||
export const checkConfigFailure = createAction('CHECK_CONFIG_FAILURE');
|
||||
export const checkConfigSuccess = createAction('CHECK_CONFIG_SUCCESS');
|
||||
|
||||
export const checkConfig = values => async (dispatch) => {
|
||||
dispatch(checkConfigRequest());
|
||||
try {
|
||||
const check = await apiClient.checkConfig(values);
|
||||
dispatch(checkConfigSuccess(check));
|
||||
} catch (error) {
|
||||
dispatch(addErrorToast({ error }));
|
||||
dispatch(checkConfigFailure());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -350,6 +350,7 @@ export default class Api {
|
|||
// Installation
|
||||
INSTALL_GET_ADDRESSES = { path: 'install/get_addresses', method: 'GET' };
|
||||
INSTALL_CONFIGURE = { path: 'install/configure', method: 'POST' };
|
||||
INSTALL_CHECK_CONFIG = { path: 'install/check_config', method: 'POST' };
|
||||
|
||||
getDefaultAddresses() {
|
||||
const { path, method } = this.INSTALL_GET_ADDRESSES;
|
||||
|
@ -365,6 +366,15 @@ export default class Api {
|
|||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
checkConfig(config) {
|
||||
const { path, method } = this.INSTALL_CHECK_CONFIG;
|
||||
const parameters = {
|
||||
data: config,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
};
|
||||
return this.makeRequest(path, method, parameters);
|
||||
}
|
||||
|
||||
// DNS-over-HTTPS and DNS-over-TLS
|
||||
TLS_STATUS = { path: 'tls/status', method: 'GET' };
|
||||
TLS_CONFIG = { path: 'tls/configure', method: 'POST' };
|
||||
|
|
|
@ -55,6 +55,8 @@ class Controls extends Component {
|
|||
invalid
|
||||
|| pristine
|
||||
|| install.processingSubmit
|
||||
|| install.dns.status
|
||||
|| install.web.status
|
||||
}
|
||||
>
|
||||
<Trans>next</Trans>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Field, reduxForm, formValueSelector } from 'redux-form';
|
||||
|
@ -30,10 +30,25 @@ const toNumber = value => value && parseInt(value, 10);
|
|||
const renderInterfaces = (interfaces => (
|
||||
Object.keys(interfaces).map((item) => {
|
||||
const option = interfaces[item];
|
||||
const { name } = option;
|
||||
const {
|
||||
name,
|
||||
ip_addresses,
|
||||
flags,
|
||||
} = option;
|
||||
|
||||
if (option.ip_addresses && option.ip_addresses.length > 0) {
|
||||
if (option && ip_addresses && ip_addresses.length > 0) {
|
||||
const ip = getInterfaceIp(option);
|
||||
const isDown = flags && flags.includes('down');
|
||||
|
||||
if (isDown) {
|
||||
return (
|
||||
<option value={ip} key={name} disabled>
|
||||
<Fragment>
|
||||
{name} - {ip} (<Trans>down</Trans>)
|
||||
</Fragment>
|
||||
</option>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<option value={ip} key={name}>
|
||||
|
@ -49,15 +64,24 @@ const renderInterfaces = (interfaces => (
|
|||
let Settings = (props) => {
|
||||
const {
|
||||
handleSubmit,
|
||||
handleChange,
|
||||
handleAutofix,
|
||||
webIp,
|
||||
webPort,
|
||||
dnsIp,
|
||||
dnsPort,
|
||||
interfaces,
|
||||
invalid,
|
||||
webWarning,
|
||||
dnsWarning,
|
||||
config,
|
||||
} = props;
|
||||
const {
|
||||
status: webStatus,
|
||||
can_autofix: isWebFixAvailable,
|
||||
} = config.web;
|
||||
const {
|
||||
status: dnsStatus,
|
||||
can_autofix: isDnsFixAvailable,
|
||||
} = config.dns;
|
||||
|
||||
return (
|
||||
<form className="setup__step" onSubmit={handleSubmit}>
|
||||
|
@ -75,6 +99,7 @@ let Settings = (props) => {
|
|||
name="web.ip"
|
||||
component="select"
|
||||
className="form-control custom-select"
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option value={ALL_INTERFACES_IP}>
|
||||
<Trans>install_settings_all_interfaces</Trans>
|
||||
|
@ -96,9 +121,26 @@ let Settings = (props) => {
|
|||
placeholder="80"
|
||||
validate={[port, required]}
|
||||
normalize={toNumber}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
{webStatus &&
|
||||
<div className="setup__error text-danger">
|
||||
{webStatus}
|
||||
{isWebFixAvailable &&
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary btn-sm ml-2"
|
||||
onClick={() => handleAutofix('web', webIp, webPort)}
|
||||
>
|
||||
<Trans>fix</Trans>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="setup__desc">
|
||||
<Trans>install_settings_interface_link</Trans>
|
||||
|
@ -109,11 +151,6 @@ let Settings = (props) => {
|
|||
port={webPort}
|
||||
/>
|
||||
</div>
|
||||
{webWarning &&
|
||||
<div className="text-danger mt-2">
|
||||
{webWarning}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="setup__group">
|
||||
|
@ -130,6 +167,7 @@ let Settings = (props) => {
|
|||
name="dns.ip"
|
||||
component="select"
|
||||
className="form-control custom-select"
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option value={ALL_INTERFACES_IP}>
|
||||
<Trans>install_settings_all_interfaces</Trans>
|
||||
|
@ -151,9 +189,26 @@ let Settings = (props) => {
|
|||
placeholder="80"
|
||||
validate={[port, required]}
|
||||
normalize={toNumber}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
{dnsStatus &&
|
||||
<div className="setup__error text-danger">
|
||||
{dnsStatus}
|
||||
{isDnsFixAvailable &&
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary btn-sm ml-2"
|
||||
onClick={() => handleAutofix('dns', dnsIp, dnsPort)}
|
||||
>
|
||||
<Trans>fix</Trans>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div className="setup__desc">
|
||||
<Trans>install_settings_dns_desc</Trans>
|
||||
|
@ -165,11 +220,6 @@ let Settings = (props) => {
|
|||
isDns={true}
|
||||
/>
|
||||
</div>
|
||||
{dnsWarning &&
|
||||
<div className="text-danger mt-2">
|
||||
{dnsWarning}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<Controls invalid={invalid} />
|
||||
|
@ -179,8 +229,11 @@ let Settings = (props) => {
|
|||
|
||||
Settings.propTypes = {
|
||||
handleSubmit: PropTypes.func.isRequired,
|
||||
handleChange: PropTypes.func,
|
||||
handleAutofix: PropTypes.func,
|
||||
webIp: PropTypes.string.isRequired,
|
||||
dnsIp: PropTypes.string.isRequired,
|
||||
config: PropTypes.object.isRequired,
|
||||
webPort: PropTypes.oneOfType([
|
||||
PropTypes.string,
|
||||
PropTypes.number,
|
||||
|
@ -189,8 +242,6 @@ Settings.propTypes = {
|
|||
PropTypes.string,
|
||||
PropTypes.number,
|
||||
]),
|
||||
webWarning: PropTypes.string.isRequired,
|
||||
dnsWarning: PropTypes.string.isRequired,
|
||||
interfaces: PropTypes.object.isRequired,
|
||||
invalid: PropTypes.bool.isRequired,
|
||||
initialValues: PropTypes.object,
|
||||
|
|
|
@ -115,3 +115,7 @@
|
|||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.setup__error {
|
||||
margin: -5px 0 5px;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { Component, Fragment } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
import * as actionCreators from '../../actions/install';
|
||||
import { getWebAddress } from '../../helpers/helpers';
|
||||
|
@ -8,6 +9,7 @@ import {
|
|||
INSTALL_FIRST_STEP,
|
||||
INSTALL_TOTAL_STEPS,
|
||||
ALL_INTERFACES_IP,
|
||||
DEBOUNCE_TIMEOUT,
|
||||
} from '../../helpers/constants';
|
||||
|
||||
import Loading from '../../components/ui/Loading';
|
||||
|
@ -34,6 +36,30 @@ class Setup extends Component {
|
|||
this.props.setAllSettings(values);
|
||||
};
|
||||
|
||||
handleFormChange = debounce((values) => {
|
||||
if (values && values.web.port && values.dns.port) {
|
||||
this.props.checkConfig(values);
|
||||
}
|
||||
}, DEBOUNCE_TIMEOUT);
|
||||
|
||||
handleAutofix = (type, ip, port) => {
|
||||
const data = {
|
||||
ip,
|
||||
port,
|
||||
autofix: true,
|
||||
};
|
||||
|
||||
if (type === 'web') {
|
||||
this.props.checkConfig({
|
||||
web: { ...data },
|
||||
});
|
||||
} else {
|
||||
this.props.checkConfig({
|
||||
dns: { ...data },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
openDashboard = (ip, port) => {
|
||||
let address = getWebAddress(ip, port);
|
||||
|
||||
|
@ -63,11 +89,12 @@ class Setup extends Component {
|
|||
case 2:
|
||||
return (
|
||||
<Settings
|
||||
config={config}
|
||||
initialValues={config}
|
||||
interfaces={interfaces}
|
||||
webWarning={config.web.warning}
|
||||
dnsWarning={config.dns.warning}
|
||||
onSubmit={this.nextStep}
|
||||
onChange={this.handleFormChange}
|
||||
handleAutofix={this.handleAutofix}
|
||||
/>
|
||||
);
|
||||
case 3:
|
||||
|
@ -116,6 +143,7 @@ class Setup extends Component {
|
|||
Setup.propTypes = {
|
||||
getDefaultAddresses: PropTypes.func.isRequired,
|
||||
setAllSettings: PropTypes.func.isRequired,
|
||||
checkConfig: PropTypes.func.isRequired,
|
||||
nextStep: PropTypes.func.isRequired,
|
||||
prevStep: PropTypes.func.isRequired,
|
||||
install: PropTypes.object.isRequired,
|
||||
|
|
|
@ -10,10 +10,13 @@ const install = handleActions({
|
|||
[actions.getDefaultAddressesRequest]: state => ({ ...state, processingDefault: true }),
|
||||
[actions.getDefaultAddressesFailure]: state => ({ ...state, processingDefault: false }),
|
||||
[actions.getDefaultAddressesSuccess]: (state, { payload }) => {
|
||||
const values = payload;
|
||||
values.web.ip = state.web.ip;
|
||||
values.dns.ip = state.dns.ip;
|
||||
const newState = { ...state, ...values, processingDefault: false };
|
||||
const { interfaces } = payload;
|
||||
const web = { ...state.web, ...payload.web };
|
||||
const dns = { ...state.dns, ...payload.dns };
|
||||
|
||||
const newState = {
|
||||
...state, web, dns, interfaces, processingDefault: false,
|
||||
};
|
||||
return newState;
|
||||
},
|
||||
|
||||
|
@ -23,19 +26,34 @@ const install = handleActions({
|
|||
[actions.setAllSettingsRequest]: state => ({ ...state, processingSubmit: true }),
|
||||
[actions.setAllSettingsFailure]: state => ({ ...state, processingSubmit: false }),
|
||||
[actions.setAllSettingsSuccess]: state => ({ ...state, processingSubmit: false }),
|
||||
|
||||
[actions.checkConfigRequest]: state => ({ ...state, processingCheck: true }),
|
||||
[actions.checkConfigFailure]: state => ({ ...state, processingCheck: false }),
|
||||
[actions.checkConfigSuccess]: (state, { payload }) => {
|
||||
const web = { ...state.web, ...payload.web };
|
||||
const dns = { ...state.dns, ...payload.dns };
|
||||
|
||||
const newState = {
|
||||
...state, web, dns, processingCheck: false,
|
||||
};
|
||||
return newState;
|
||||
},
|
||||
}, {
|
||||
step: INSTALL_FIRST_STEP,
|
||||
processingDefault: true,
|
||||
processingSubmit: false,
|
||||
processingCheck: false,
|
||||
web: {
|
||||
ip: '0.0.0.0',
|
||||
port: 80,
|
||||
warning: '',
|
||||
status: '',
|
||||
can_autofix: false,
|
||||
},
|
||||
dns: {
|
||||
ip: '0.0.0.0',
|
||||
port: 53,
|
||||
warning: '',
|
||||
status: '',
|
||||
can_autofix: false,
|
||||
},
|
||||
interfaces: {},
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue