Show list of addresses
This commit is contained in:
parent
f379d34813
commit
31b855f9ab
|
@ -164,10 +164,10 @@
|
||||||
"install_settings_title": "Admin Web Interface",
|
"install_settings_title": "Admin Web Interface",
|
||||||
"install_settings_listen": "Listen interface",
|
"install_settings_listen": "Listen interface",
|
||||||
"install_settings_port": "Port",
|
"install_settings_port": "Port",
|
||||||
"install_settings_interface_link": "Your AdGuard Home admin web interface will be available on the following addresses: <0>{{link}}</0>",
|
"install_settings_interface_link": "Your AdGuard Home admin web interface will be available on the following addresses:",
|
||||||
"form_error_port": "Enter valid port value",
|
"form_error_port": "Enter valid port value",
|
||||||
"install_settings_dns": "DNS server",
|
"install_settings_dns": "DNS server",
|
||||||
"install_settings_dns_desc": "You will need to configure your devices or router to use the DNS server at <0>{{ip}}</0>",
|
"install_settings_dns_desc": "You will need to configure your devices or router to use the DNS server on the following addresses:",
|
||||||
"install_settings_all_interfaces": "All interfaces",
|
"install_settings_all_interfaces": "All interfaces",
|
||||||
"install_auth_title": "Authentication",
|
"install_auth_title": "Authentication",
|
||||||
"install_auth_desc": "It is highly recommended to configure password authentication to your AdGuard Home admin web interface. Even if it is accessible only in your local network, it is still important to have it protected from unrestricted access.",
|
"install_auth_desc": "It is highly recommended to configure password authentication to your AdGuard Home admin web interface. Even if it is accessible only in your local network, it is still important to have it protected from unrestricted access.",
|
||||||
|
|
|
@ -70,3 +70,5 @@ export const SETTINGS_NAMES = {
|
||||||
parental: 'parental',
|
parental: 'parental',
|
||||||
safesearch: 'safesearch',
|
safesearch: 'safesearch',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const STANDARD_DNS_PORT = 53;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import subHours from 'date-fns/sub_hours';
|
||||||
import addHours from 'date-fns/add_hours';
|
import addHours from 'date-fns/add_hours';
|
||||||
import round from 'lodash/round';
|
import round from 'lodash/round';
|
||||||
|
|
||||||
import { STATS_NAMES } from './constants';
|
import { STATS_NAMES, STANDARD_DNS_PORT } from './constants';
|
||||||
|
|
||||||
export const formatTime = (time) => {
|
export const formatTime = (time) => {
|
||||||
const parsedTime = dateParse(time);
|
const parsedTime = dateParse(time);
|
||||||
|
@ -85,3 +85,46 @@ export const getPercent = (amount, number) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const captitalizeWords = text => text.split(/[ -_]/g).map(str => str.charAt(0).toUpperCase() + str.substr(1)).join(' ');
|
export const captitalizeWords = text => text.split(/[ -_]/g).map(str => str.charAt(0).toUpperCase() + str.substr(1)).join(' ');
|
||||||
|
|
||||||
|
export const getInterfaceIp = (option) => {
|
||||||
|
const onlyIPv6 = option.ip_addresses.every(ip => ip.includes(':'));
|
||||||
|
let interfaceIP = option.ip_addresses[0];
|
||||||
|
|
||||||
|
if (!onlyIPv6) {
|
||||||
|
option.ip_addresses.forEach((ip) => {
|
||||||
|
if (!ip.includes(':')) {
|
||||||
|
interfaceIP = ip;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return interfaceIP;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getIpList = (interfaces) => {
|
||||||
|
let list = [];
|
||||||
|
|
||||||
|
Object.keys(interfaces).forEach((item) => {
|
||||||
|
list = [...list, ...interfaces[item].ip_addresses];
|
||||||
|
});
|
||||||
|
|
||||||
|
return list.sort();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAddress = (ip, port = '', isDns = false) => {
|
||||||
|
if (!port) {
|
||||||
|
return isDns ? ip : `http://${ip}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDns) {
|
||||||
|
if (ip.includes(':') && port !== STANDARD_DNS_PORT) {
|
||||||
|
return `[${ip}]:${port}`;
|
||||||
|
} else if (port !== STANDARD_DNS_PORT) {
|
||||||
|
return `${ip}:${port}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip.includes(':') ? `http://[${ip}]:${port}` : `http://${ip}:${port}`;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { getIpList, getAddress } from '../../helpers/helpers';
|
||||||
|
|
||||||
|
const AddressList = (props) => {
|
||||||
|
let webAddress = getAddress(props.address, props.port);
|
||||||
|
let dnsAddress = getAddress(props.address, props.port, true);
|
||||||
|
|
||||||
|
if (props.address === '0.0.0.0') {
|
||||||
|
return getIpList(props.interfaces).map((ip) => {
|
||||||
|
webAddress = getAddress(ip, props.port);
|
||||||
|
dnsAddress = getAddress(ip, props.port, true);
|
||||||
|
|
||||||
|
if (props.isDns) {
|
||||||
|
return (
|
||||||
|
<li key={ip}>
|
||||||
|
<strong>
|
||||||
|
{dnsAddress}
|
||||||
|
</strong>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={ip}>
|
||||||
|
<a href={webAddress}>
|
||||||
|
{webAddress}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.isDns) {
|
||||||
|
return (
|
||||||
|
<strong>
|
||||||
|
{dnsAddress}
|
||||||
|
</strong>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a href={webAddress}>
|
||||||
|
{webAddress}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressList.propTypes = {
|
||||||
|
interfaces: PropTypes.object.isRequired,
|
||||||
|
address: PropTypes.string.isRequired,
|
||||||
|
port: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number,
|
||||||
|
]),
|
||||||
|
isDns: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddressList;
|
|
@ -4,26 +4,12 @@ import PropTypes from 'prop-types';
|
||||||
import { Trans } from 'react-i18next';
|
import { Trans } from 'react-i18next';
|
||||||
|
|
||||||
import * as actionCreators from '../../actions/install';
|
import * as actionCreators from '../../actions/install';
|
||||||
import { INSTALL_FIRST_STEP, INSTALL_TOTAL_STEPS } from '../../helpers/constants';
|
|
||||||
|
|
||||||
class Controls extends Component {
|
class Controls extends Component {
|
||||||
nextStep = () => {
|
|
||||||
if (this.props.step < INSTALL_TOTAL_STEPS) {
|
|
||||||
this.props.nextStep();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prevStep = () => {
|
|
||||||
if (this.props.step > INSTALL_FIRST_STEP) {
|
|
||||||
this.props.prevStep();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderPrevButton(step) {
|
renderPrevButton(step) {
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -76,7 +62,7 @@ class Controls extends Component {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-success btn-standard btn-lg"
|
className="btn btn-success btn-standard btn-lg"
|
||||||
onClick={this.props.openDashboard}
|
onClick={() => this.props.openDashboard(this.props.address)}
|
||||||
>
|
>
|
||||||
<Trans>open_dashboard</Trans>
|
<Trans>open_dashboard</Trans>
|
||||||
</button>
|
</button>
|
||||||
|
@ -106,6 +92,7 @@ Controls.propTypes = {
|
||||||
submitting: PropTypes.bool,
|
submitting: PropTypes.bool,
|
||||||
invalid: PropTypes.bool,
|
invalid: PropTypes.bool,
|
||||||
pristine: PropTypes.bool,
|
pristine: PropTypes.bool,
|
||||||
|
address: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import flow from 'lodash/flow';
|
||||||
import Tabs from '../../components/ui/Tabs';
|
import Tabs from '../../components/ui/Tabs';
|
||||||
import Icons from '../../components/ui/Icons';
|
import Icons from '../../components/ui/Icons';
|
||||||
import Controls from './Controls';
|
import Controls from './Controls';
|
||||||
|
import AddressList from './AddressList';
|
||||||
|
|
||||||
let Devices = props => (
|
let Devices = props => (
|
||||||
<div className="setup__step">
|
<div className="setup__step">
|
||||||
|
@ -20,8 +21,13 @@ let Devices = props => (
|
||||||
<div className="mt-1">
|
<div className="mt-1">
|
||||||
<Trans>install_devices_address</Trans>:
|
<Trans>install_devices_address</Trans>:
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="mt-1">
|
||||||
<strong>{`${props.dnsIp}:${props.dnsPort}`}</strong>
|
<AddressList
|
||||||
|
interfaces={props.interfaces}
|
||||||
|
address={props.dnsIp}
|
||||||
|
port={props.dnsPort}
|
||||||
|
isDns={true}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Icons />
|
<Icons />
|
||||||
|
@ -101,6 +107,7 @@ let Devices = props => (
|
||||||
);
|
);
|
||||||
|
|
||||||
Devices.propTypes = {
|
Devices.propTypes = {
|
||||||
|
interfaces: PropTypes.object.isRequired,
|
||||||
dnsIp: PropTypes.string.isRequired,
|
dnsIp: PropTypes.string.isRequired,
|
||||||
dnsPort: PropTypes.number.isRequired,
|
dnsPort: PropTypes.number.isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,9 @@ import { Trans, withNamespaces } from 'react-i18next';
|
||||||
import flow from 'lodash/flow';
|
import flow from 'lodash/flow';
|
||||||
|
|
||||||
import Controls from './Controls';
|
import Controls from './Controls';
|
||||||
|
import AddressList from './AddressList';
|
||||||
import renderField from './renderField';
|
import renderField from './renderField';
|
||||||
|
import { getInterfaceIp } from '../../helpers/helpers';
|
||||||
|
|
||||||
const required = (value) => {
|
const required = (value) => {
|
||||||
if (value || value === 0) {
|
if (value || value === 0) {
|
||||||
|
@ -28,20 +30,11 @@ const renderInterfaces = (interfaces => (
|
||||||
Object.keys(interfaces).map((item) => {
|
Object.keys(interfaces).map((item) => {
|
||||||
const option = interfaces[item];
|
const option = interfaces[item];
|
||||||
const { name } = option;
|
const { name } = option;
|
||||||
const onlyIPv6 = option.ip_addresses.every(ip => ip.includes(':'));
|
const ip = getInterfaceIp(option);
|
||||||
let interfaceIP = option.ip_addresses[0];
|
|
||||||
|
|
||||||
if (!onlyIPv6) {
|
|
||||||
option.ip_addresses.forEach((ip) => {
|
|
||||||
if (!ip.includes(':')) {
|
|
||||||
interfaceIP = ip;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<option value={interfaceIP} key={name}>
|
<option value={ip} key={name}>
|
||||||
{name} - {interfaceIP}
|
{name} - {ip}
|
||||||
</option>
|
</option>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -50,8 +43,8 @@ const renderInterfaces = (interfaces => (
|
||||||
let Settings = (props) => {
|
let Settings = (props) => {
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
interfaceIp,
|
webIp,
|
||||||
interfacePort,
|
webPort,
|
||||||
dnsIp,
|
dnsIp,
|
||||||
dnsPort,
|
dnsPort,
|
||||||
interfaces,
|
interfaces,
|
||||||
|
@ -59,8 +52,6 @@ let Settings = (props) => {
|
||||||
webWarning,
|
webWarning,
|
||||||
dnsWarning,
|
dnsWarning,
|
||||||
} = props;
|
} = props;
|
||||||
const dnsAddress = dnsPort && dnsPort !== 53 ? `${dnsIp}:${dnsPort}` : dnsIp;
|
|
||||||
const interfaceAddress = interfacePort ? `http://${interfaceIp}:${interfacePort}` : `http://${interfaceIp}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="setup__step" onSubmit={handleSubmit}>
|
<form className="setup__step" onSubmit={handleSubmit}>
|
||||||
|
@ -104,12 +95,14 @@ let Settings = (props) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="setup__desc">
|
<div className="setup__desc">
|
||||||
<Trans
|
<Trans>install_settings_interface_link</Trans>
|
||||||
components={[<a href={`http://${interfaceIp}`} key="0">link</a>]}
|
<div className="mt-1">
|
||||||
values={{ link: interfaceAddress }}
|
<AddressList
|
||||||
>
|
interfaces={interfaces}
|
||||||
install_settings_interface_link
|
address={webIp}
|
||||||
</Trans>
|
port={webPort}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{webWarning &&
|
{webWarning &&
|
||||||
<div className="text-danger mt-2">
|
<div className="text-danger mt-2">
|
||||||
{webWarning}
|
{webWarning}
|
||||||
|
@ -132,7 +125,7 @@ let Settings = (props) => {
|
||||||
component="select"
|
component="select"
|
||||||
className="form-control custom-select"
|
className="form-control custom-select"
|
||||||
>
|
>
|
||||||
<option value="0.0.0.0" defaultValue>
|
<option value="0.0.0.0">
|
||||||
<Trans>install_settings_all_interfaces</Trans>
|
<Trans>install_settings_all_interfaces</Trans>
|
||||||
</option>
|
</option>
|
||||||
{renderInterfaces(interfaces)}
|
{renderInterfaces(interfaces)}
|
||||||
|
@ -157,12 +150,15 @@ let Settings = (props) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="setup__desc">
|
<div className="setup__desc">
|
||||||
<Trans
|
<Trans>install_settings_dns_desc</Trans>
|
||||||
components={[<strong key="0">ip</strong>]}
|
<div className="mt-1">
|
||||||
values={{ ip: dnsAddress }}
|
<AddressList
|
||||||
>
|
interfaces={interfaces}
|
||||||
install_settings_dns_desc
|
address={dnsIp}
|
||||||
</Trans>
|
port={dnsPort}
|
||||||
|
isDns={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{dnsWarning &&
|
{dnsWarning &&
|
||||||
<div className="text-danger mt-2">
|
<div className="text-danger mt-2">
|
||||||
{dnsWarning}
|
{dnsWarning}
|
||||||
|
@ -177,9 +173,9 @@ let Settings = (props) => {
|
||||||
|
|
||||||
Settings.propTypes = {
|
Settings.propTypes = {
|
||||||
handleSubmit: PropTypes.func.isRequired,
|
handleSubmit: PropTypes.func.isRequired,
|
||||||
interfaceIp: PropTypes.string.isRequired,
|
webIp: PropTypes.string.isRequired,
|
||||||
dnsIp: PropTypes.string.isRequired,
|
dnsIp: PropTypes.string.isRequired,
|
||||||
interfacePort: PropTypes.oneOfType([
|
webPort: PropTypes.oneOfType([
|
||||||
PropTypes.string,
|
PropTypes.string,
|
||||||
PropTypes.number,
|
PropTypes.number,
|
||||||
]),
|
]),
|
||||||
|
@ -197,14 +193,14 @@ Settings.propTypes = {
|
||||||
const selector = formValueSelector('install');
|
const selector = formValueSelector('install');
|
||||||
|
|
||||||
Settings = connect((state) => {
|
Settings = connect((state) => {
|
||||||
const interfaceIp = selector(state, 'web.ip');
|
const webIp = selector(state, 'web.ip');
|
||||||
const interfacePort = selector(state, 'web.port');
|
const webPort = selector(state, 'web.port');
|
||||||
const dnsIp = selector(state, 'dns.ip');
|
const dnsIp = selector(state, 'dns.ip');
|
||||||
const dnsPort = selector(state, 'dns.port');
|
const dnsPort = selector(state, 'dns.port');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
interfaceIp,
|
webIp,
|
||||||
interfacePort,
|
webPort,
|
||||||
dnsIp,
|
dnsIp,
|
||||||
dnsPort,
|
dnsPort,
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Trans, withNamespaces } from 'react-i18next';
|
||||||
import flow from 'lodash/flow';
|
import flow from 'lodash/flow';
|
||||||
|
|
||||||
import Controls from './Controls';
|
import Controls from './Controls';
|
||||||
|
import { getAddress } from '../../helpers/helpers';
|
||||||
|
|
||||||
let Submit = props => (
|
let Submit = props => (
|
||||||
<div className="setup__step">
|
<div className="setup__step">
|
||||||
|
@ -17,33 +18,31 @@ let Submit = props => (
|
||||||
<Trans>install_submit_desc</Trans>
|
<Trans>install_submit_desc</Trans>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={props.handleSubmit}>
|
<Controls
|
||||||
<Controls
|
openDashboard={props.openDashboard}
|
||||||
submitting={props.submitting}
|
address={getAddress(props.webIp, props.webPort)}
|
||||||
pristine={props.pristine}
|
/>
|
||||||
address={`http://${props.interfaceIp}`}
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
Submit.propTypes = {
|
Submit.propTypes = {
|
||||||
interfaceIp: PropTypes.string.isRequired,
|
webIp: PropTypes.string.isRequired,
|
||||||
interfacePort: PropTypes.number.isRequired,
|
webPort: PropTypes.number.isRequired,
|
||||||
handleSubmit: PropTypes.func.isRequired,
|
handleSubmit: PropTypes.func.isRequired,
|
||||||
pristine: PropTypes.bool.isRequired,
|
pristine: PropTypes.bool.isRequired,
|
||||||
submitting: PropTypes.bool.isRequired,
|
submitting: PropTypes.bool.isRequired,
|
||||||
|
openDashboard: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
const selector = formValueSelector('install');
|
const selector = formValueSelector('install');
|
||||||
|
|
||||||
Submit = connect((state) => {
|
Submit = connect((state) => {
|
||||||
const interfaceIp = selector(state, 'web.ip');
|
const webIp = selector(state, 'web.ip');
|
||||||
const interfacePort = selector(state, 'web.port');
|
const webPort = selector(state, 'web.port');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
interfaceIp,
|
webIp,
|
||||||
interfacePort,
|
webPort,
|
||||||
};
|
};
|
||||||
})(Submit);
|
})(Submit);
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ class Setup extends Component {
|
||||||
this.props.setAllSettings(values);
|
this.props.setAllSettings(values);
|
||||||
};
|
};
|
||||||
|
|
||||||
openDashboard = () => {
|
openDashboard = (address) => {
|
||||||
console.log('Open dashboard');
|
window.location.replace(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
nextStep = () => {
|
nextStep = () => {
|
||||||
|
@ -64,9 +64,9 @@ class Setup extends Component {
|
||||||
<Auth onSubmit={this.handleFormSubmit} />
|
<Auth onSubmit={this.handleFormSubmit} />
|
||||||
);
|
);
|
||||||
case 4:
|
case 4:
|
||||||
return <Devices />;
|
return <Devices interfaces={interfaces} />;
|
||||||
case 5:
|
case 5:
|
||||||
return <Submit onSubmit={this.openDashboard} />;
|
return <Submit openDashboard={this.openDashboard} />;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue