+ client: handle static IP while doing initial setup

This commit is contained in:
Ildar Kamalov 2020-01-30 18:26:54 +03:00 committed by Simon Zolin
parent 5c385521c4
commit cc2d953c9d
7 changed files with 119 additions and 31 deletions

41
client/package-lock.json generated vendored
View File

@ -5458,7 +5458,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -5479,12 +5480,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -5499,17 +5502,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -5626,7 +5632,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -5638,6 +5645,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -5652,6 +5660,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -5659,12 +5668,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -5683,6 +5694,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -5763,7 +5775,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -5775,6 +5788,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -5860,7 +5874,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -5896,6 +5911,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -5915,6 +5931,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -5958,12 +5975,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.3", "version": "3.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },

View File

@ -462,5 +462,8 @@
"client_confirm_block": "Are you sure you want to block the client \"{{ip}}\"?", "client_confirm_block": "Are you sure you want to block the client \"{{ip}}\"?",
"client_confirm_unblock": "Are you sure you want to unblock the client \"{{ip}}\"?", "client_confirm_unblock": "Are you sure you want to unblock the client \"{{ip}}\"?",
"client_blocked": "Client \"{{ip}}\" successfully blocked", "client_blocked": "Client \"{{ip}}\" successfully blocked",
"client_unblocked": "Client \"{{ip}}\" successfully unblocked" "client_unblocked": "Client \"{{ip}}\" successfully unblocked",
"set_static_ip": "Set static IP address",
"install_static_error": "We failed to determine if this network interface is configured using static IP address. Please set a static IP address manually.",
"install_static_configure": "We have detected that a dynamic IP address is used — {{ip}}. We suggest that you set this IP as static."
} }

View File

@ -240,6 +240,13 @@ export const port = (value) => {
return undefined; return undefined;
}; };
export const validInstallPort = (value) => {
if (value < 1 || value > 65535) {
return <Trans>form_error_port</Trans>;
}
return undefined;
};
export const portTLS = (value) => { export const portTLS = (value) => {
if (value === 0) { if (value === 0) {
return undefined; return undefined;

View File

@ -7,26 +7,18 @@ import flow from 'lodash/flow';
import Controls from './Controls'; import Controls from './Controls';
import AddressList from './AddressList'; import AddressList from './AddressList';
import Accordion from '../../components/ui/Accordion';
import { getInterfaceIp } from '../../helpers/helpers'; import { getInterfaceIp } from '../../helpers/helpers';
import { ALL_INTERFACES_IP } from '../../helpers/constants'; import { ALL_INTERFACES_IP } from '../../helpers/constants';
import { renderInputField } from '../../helpers/form'; import { renderInputField, required, validInstallPort, toNumber } from '../../helpers/form';
const required = (value) => { const STATIC_STATUS = {
if (value || value === 0) { ENABLED: 'yes',
return false; DISABLED: 'no',
} ERROR: 'error',
return <Trans>form_error_required</Trans>;
}; };
const port = (value) => {
if (value < 1 || value > 65535) {
return <Trans>form_error_port</Trans>;
}
return false;
};
const toNumber = value => value && parseInt(value, 10);
const renderInterfaces = (interfaces => ( const renderInterfaces = (interfaces => (
Object.keys(interfaces).map((item) => { Object.keys(interfaces).map((item) => {
const option = interfaces[item]; const option = interfaces[item];
@ -79,11 +71,54 @@ class Settings extends Component {
}); });
} }
getStaticIpMessage = (staticIp, handleStaticIp) => {
const { static: status, ip, error } = staticIp;
if (!status || status === STATIC_STATUS.ENABLED) {
return '';
}
return (
<div className="col-12">
<Fragment>
<div className="text-danger">
{status === STATIC_STATUS.DISABLED && (
<Fragment>
<Trans values={{ ip }}>
install_static_configure
</Trans>
<button
type="button"
className="btn btn-secondary btn-sm ml-2"
onClick={() => handleStaticIp()}
>
<Trans>set_static_ip</Trans>
</button>
</Fragment>
)}
{status === STATIC_STATUS.ERROR && (
<Fragment>
<Trans>install_static_error</Trans>
<div className="mt-2 mb-2">
<Accordion label={this.props.t('error_details')}>
<span>{error}</span>
</Accordion>
</div>
</Fragment>
)}
<hr className="divider divider--small" />
</div>
</Fragment>
</div>
);
};
render() { render() {
const { const {
handleSubmit, handleSubmit,
handleChange, handleChange,
handleAutofix, handleAutofix,
handleStaticIp,
webIp, webIp,
webPort, webPort,
dnsIp, dnsIp,
@ -100,6 +135,7 @@ class Settings extends Component {
status: dnsStatus, status: dnsStatus,
can_autofix: isDnsFixAvailable, can_autofix: isDnsFixAvailable,
} = config.dns; } = config.dns;
const { staticIp } = config;
return ( return (
<form className="setup__step" onSubmit={handleSubmit}> <form className="setup__step" onSubmit={handleSubmit}>
@ -137,7 +173,7 @@ class Settings extends Component {
type="number" type="number"
className="form-control" className="form-control"
placeholder="80" placeholder="80"
validate={[port, required]} validate={[validInstallPort, required]}
normalize={toNumber} normalize={toNumber}
onChange={handleChange} onChange={handleChange}
/> />
@ -205,12 +241,13 @@ class Settings extends Component {
type="number" type="number"
className="form-control" className="form-control"
placeholder="80" placeholder="80"
validate={[port, required]} validate={[validInstallPort, required]}
normalize={toNumber} normalize={toNumber}
onChange={handleChange} onChange={handleChange}
/> />
</div> </div>
</div> </div>
{this.getStaticIpMessage(staticIp, handleStaticIp)}
<div className="col-12"> <div className="col-12">
{dnsStatus && {dnsStatus &&
<Fragment> <Fragment>
@ -237,6 +274,7 @@ class Settings extends Component {
<Trans>autofix_warning_result</Trans> <Trans>autofix_warning_result</Trans>
</p> </p>
</div> </div>
<hr className="divider--small" />
</Fragment> </Fragment>
} }
</div> </div>
@ -278,6 +316,8 @@ Settings.propTypes = {
interfaces: PropTypes.object.isRequired, interfaces: PropTypes.object.isRequired,
invalid: PropTypes.bool.isRequired, invalid: PropTypes.bool.isRequired,
initialValues: PropTypes.object, initialValues: PropTypes.object,
t: PropTypes.func.isRequired,
handleStaticIp: PropTypes.func.isRequired,
}; };
const selector = formValueSelector('install'); const selector = formValueSelector('install');

View File

@ -119,3 +119,8 @@
.setup__error { .setup__error {
margin: -5px 0 5px; margin: -5px 0 5px;
} }
.divider--small {
margin-top: 1rem;
margin-bottom: 1rem;
}

View File

@ -60,6 +60,12 @@ class Setup extends Component {
} }
}; };
handleStaticIp = () => {
this.props.checkConfig({
set_static_ip: true,
});
};
openDashboard = (ip, port) => { openDashboard = (ip, port) => {
let address = getWebAddress(ip, port); let address = getWebAddress(ip, port);
@ -96,6 +102,7 @@ class Setup extends Component {
onChange={this.handleFormChange} onChange={this.handleFormChange}
validateForm={this.handleFormChange} validateForm={this.handleFormChange}
handleAutofix={this.handleAutofix} handleAutofix={this.handleAutofix}
handleStaticIp={this.handleStaticIp}
/> />
); );
case 3: case 3:
@ -117,6 +124,7 @@ class Setup extends Component {
step, step,
web, web,
dns, dns,
staticIp,
interfaces, interfaces,
} = this.props.install; } = this.props.install;
@ -128,7 +136,7 @@ class Setup extends Component {
<div className="setup"> <div className="setup">
<div className="setup__container"> <div className="setup__container">
<img src={logo} className="setup__logo" alt="logo" /> <img src={logo} className="setup__logo" alt="logo" />
{this.renderPage(step, { web, dns }, interfaces)} {this.renderPage(step, { web, dns, staticIp }, interfaces)}
<Progress step={step} /> <Progress step={step} />
</div> </div>
</div> </div>

View File

@ -32,9 +32,10 @@ const install = handleActions({
[actions.checkConfigSuccess]: (state, { payload }) => { [actions.checkConfigSuccess]: (state, { payload }) => {
const web = { ...state.web, ...payload.web }; const web = { ...state.web, ...payload.web };
const dns = { ...state.dns, ...payload.dns }; const dns = { ...state.dns, ...payload.dns };
const staticIp = { ...state.staticIp, ...payload.static_ip };
const newState = { const newState = {
...state, web, dns, processingCheck: false, ...state, web, dns, staticIp, processingCheck: false,
}; };
return newState; return newState;
}, },
@ -55,6 +56,11 @@ const install = handleActions({
status: '', status: '',
can_autofix: false, can_autofix: false,
}, },
staticIp: {
static: '',
ip: '',
error: '',
},
interfaces: {}, interfaces: {},
}); });