mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-11 10:19:55 +03:00
eslint
This commit is contained in:
@@ -1,22 +1,31 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Redirect, Switch, RouteComponentProps } from 'react-router-dom'
|
||||
import { Component } from 'react';
|
||||
import { Redirect, Switch, RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import { Tabs, Tab } from '@material-ui/core';
|
||||
|
||||
import { withAuthenticatedContext, AuthenticatedContextProps, AuthenticatedRoute } from '../authentication';
|
||||
import {
|
||||
withAuthenticatedContext,
|
||||
AuthenticatedContextProps,
|
||||
AuthenticatedRoute
|
||||
} from '../authentication';
|
||||
import { MenuAppBar } from '../components';
|
||||
|
||||
import NetworkStatusController from './NetworkStatusController';
|
||||
import NetworkSettingsController from './NetworkSettingsController';
|
||||
import WiFiNetworkScanner from './WiFiNetworkScanner';
|
||||
import { NetworkConnectionContext, NetworkConnectionContextValue } from './NetworkConnectionContext';
|
||||
import {
|
||||
NetworkConnectionContext,
|
||||
NetworkConnectionContextValue
|
||||
} from './NetworkConnectionContext';
|
||||
|
||||
import { WiFiNetwork } from './types';
|
||||
|
||||
type NetworkConnectionProps = AuthenticatedContextProps & RouteComponentProps;
|
||||
|
||||
class NetworkConnection extends Component<NetworkConnectionProps, NetworkConnectionContextValue> {
|
||||
|
||||
class NetworkConnection extends Component<
|
||||
NetworkConnectionProps,
|
||||
NetworkConnectionContextValue
|
||||
> {
|
||||
constructor(props: NetworkConnectionProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@@ -28,13 +37,13 @@ class NetworkConnection extends Component<NetworkConnectionProps, NetworkConnect
|
||||
selectNetwork = (network: WiFiNetwork) => {
|
||||
this.setState({ selectedNetwork: network });
|
||||
this.props.history.push('/network/settings');
|
||||
}
|
||||
};
|
||||
|
||||
deselectNetwork = () => {
|
||||
this.setState({ selectedNetwork: undefined });
|
||||
}
|
||||
};
|
||||
|
||||
handleTabChange = (event: React.ChangeEvent<{}>, path: string) => {
|
||||
handleTabChange = (path: string) => {
|
||||
this.props.history.push(path);
|
||||
};
|
||||
|
||||
@@ -43,20 +52,44 @@ class NetworkConnection extends Component<NetworkConnectionProps, NetworkConnect
|
||||
return (
|
||||
<NetworkConnectionContext.Provider value={this.state}>
|
||||
<MenuAppBar sectionTitle="Network Connection">
|
||||
<Tabs value={this.props.match.url} onChange={this.handleTabChange} variant="fullWidth">
|
||||
<Tabs
|
||||
value={this.props.match.url}
|
||||
onChange={(e, path) => this.handleTabChange(path)}
|
||||
variant="fullWidth"
|
||||
>
|
||||
<Tab value="/network/status" label="Network Status" />
|
||||
<Tab value="/network/scan" label="Scan WiFi Networks" disabled={!authenticatedContext.me.admin} />
|
||||
<Tab value="/network/settings" label="Network Settings" disabled={!authenticatedContext.me.admin} />
|
||||
<Tab
|
||||
value="/network/scan"
|
||||
label="Scan WiFi Networks"
|
||||
disabled={!authenticatedContext.me.admin}
|
||||
/>
|
||||
<Tab
|
||||
value="/network/settings"
|
||||
label="Network Settings"
|
||||
disabled={!authenticatedContext.me.admin}
|
||||
/>
|
||||
</Tabs>
|
||||
<Switch>
|
||||
<AuthenticatedRoute exact path="/network/status" component={NetworkStatusController} />
|
||||
<AuthenticatedRoute exact path="/network/scan" component={WiFiNetworkScanner} />
|
||||
<AuthenticatedRoute exact path="/network/settings" component={NetworkSettingsController} />
|
||||
<AuthenticatedRoute
|
||||
exact
|
||||
path="/network/status"
|
||||
component={NetworkStatusController}
|
||||
/>
|
||||
<AuthenticatedRoute
|
||||
exact
|
||||
path="/network/scan"
|
||||
component={WiFiNetworkScanner}
|
||||
/>
|
||||
<AuthenticatedRoute
|
||||
exact
|
||||
path="/network/settings"
|
||||
component={NetworkSettingsController}
|
||||
/>
|
||||
<Redirect to="/network/status" />
|
||||
</Switch>
|
||||
</MenuAppBar>
|
||||
</NetworkConnectionContext.Provider>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ export interface NetworkConnectionContextValue {
|
||||
deselectNetwork: () => void;
|
||||
}
|
||||
|
||||
const NetworkConnectionContextDefaultValue = {} as NetworkConnectionContextValue
|
||||
const NetworkConnectionContextDefaultValue = {} as NetworkConnectionContextValue;
|
||||
export const NetworkConnectionContext = React.createContext(
|
||||
NetworkConnectionContextDefaultValue
|
||||
);
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Component } from 'react';
|
||||
|
||||
import { restController, RestControllerProps, RestFormLoader, SectionContent } from '../components';
|
||||
import {
|
||||
restController,
|
||||
RestControllerProps,
|
||||
RestFormLoader,
|
||||
SectionContent
|
||||
} from '../components';
|
||||
import NetworkSettingsForm from './NetworkSettingsForm';
|
||||
import { NETWORK_SETTINGS_ENDPOINT } from '../api';
|
||||
import { NetworkSettings } from './types';
|
||||
@@ -8,7 +13,6 @@ import { NetworkSettings } from './types';
|
||||
type NetworkSettingsControllerProps = RestControllerProps<NetworkSettings>;
|
||||
|
||||
class NetworkSettingsController extends Component<NetworkSettingsControllerProps> {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.loadData();
|
||||
}
|
||||
@@ -18,12 +22,14 @@ class NetworkSettingsController extends Component<NetworkSettingsControllerProps
|
||||
<SectionContent title="Network Settings">
|
||||
<RestFormLoader
|
||||
{...this.props}
|
||||
render={formProps => <NetworkSettingsForm {...formProps} />}
|
||||
render={(formProps) => <NetworkSettingsForm {...formProps} />}
|
||||
/>
|
||||
</SectionContent>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default restController(NETWORK_SETTINGS_ENDPOINT, NetworkSettingsController);
|
||||
export default restController(
|
||||
NETWORK_SETTINGS_ENDPOINT,
|
||||
NetworkSettingsController
|
||||
);
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator';
|
||||
|
||||
import { Checkbox, List, ListItem, ListItemText, ListItemAvatar, ListItemSecondaryAction } from '@material-ui/core';
|
||||
import {
|
||||
Checkbox,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
ListItemAvatar,
|
||||
ListItemSecondaryAction
|
||||
} from '@material-ui/core';
|
||||
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
@@ -10,31 +17,42 @@ import LockOpenIcon from '@material-ui/icons/LockOpen';
|
||||
import DeleteIcon from '@material-ui/icons/Delete';
|
||||
import SaveIcon from '@material-ui/icons/Save';
|
||||
|
||||
import { RestFormProps, PasswordValidator, BlockFormControlLabel, FormActions, FormButton } from '../components';
|
||||
import {
|
||||
RestFormProps,
|
||||
PasswordValidator,
|
||||
BlockFormControlLabel,
|
||||
FormActions,
|
||||
FormButton
|
||||
} from '../components';
|
||||
import { isIP, isHostname, optional } from '../validators';
|
||||
|
||||
import { NetworkConnectionContext, NetworkConnectionContextValue } from './NetworkConnectionContext';
|
||||
import {
|
||||
NetworkConnectionContext,
|
||||
NetworkConnectionContextValue
|
||||
} from './NetworkConnectionContext';
|
||||
import { isNetworkOpen, networkSecurityMode } from './WiFiSecurityModes';
|
||||
import { NetworkSettings } from './types';
|
||||
|
||||
type NetworkStatusFormProps = RestFormProps<NetworkSettings>;
|
||||
|
||||
class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
|
||||
static contextType = NetworkConnectionContext;
|
||||
context!: React.ContextType<typeof NetworkConnectionContext>;
|
||||
|
||||
constructor(props: NetworkStatusFormProps, context: NetworkConnectionContextValue) {
|
||||
constructor(
|
||||
props: NetworkStatusFormProps,
|
||||
context: NetworkConnectionContextValue
|
||||
) {
|
||||
super(props);
|
||||
|
||||
const { selectedNetwork } = context;
|
||||
if (selectedNetwork) {
|
||||
const networkSettings: NetworkSettings = {
|
||||
ssid: selectedNetwork.ssid,
|
||||
password: "",
|
||||
password: '',
|
||||
hostname: props.data.hostname,
|
||||
static_ip_config: false,
|
||||
}
|
||||
static_ip_config: false
|
||||
};
|
||||
props.setData(networkSettings);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +66,7 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
deselectNetworkAndLoadData = () => {
|
||||
this.context.deselectNetwork();
|
||||
this.props.loadData();
|
||||
}
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
this.context.deselectNetwork();
|
||||
@@ -59,41 +77,51 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
const { data, handleValueChange, saveData } = this.props;
|
||||
return (
|
||||
<ValidatorForm onSubmit={saveData} ref="NetworkSettingsForm">
|
||||
{
|
||||
selectedNetwork ?
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
{isNetworkOpen(selectedNetwork) ? <LockOpenIcon /> : <LockIcon />}
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={selectedNetwork.ssid}
|
||||
secondary={"Security: " + networkSecurityMode(selectedNetwork) + ", Ch: " + selectedNetwork.channel}
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<IconButton aria-label="Manual Config" onClick={deselectNetwork}>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
</List>
|
||||
:
|
||||
<TextValidator
|
||||
validators={['matchRegexp:^.{0,32}$']}
|
||||
errorMessages={['SSID must be 32 characters or less']}
|
||||
name="ssid"
|
||||
label="SSID (leave blank to disable WiFi)"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={data.ssid}
|
||||
onChange={handleValueChange('ssid')}
|
||||
margin="normal"
|
||||
/>
|
||||
}
|
||||
{
|
||||
(!selectedNetwork || !isNetworkOpen(selectedNetwork)) &&
|
||||
{selectedNetwork ? (
|
||||
<List>
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
{isNetworkOpen(selectedNetwork) ? (
|
||||
<LockOpenIcon />
|
||||
) : (
|
||||
<LockIcon />
|
||||
)}
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={selectedNetwork.ssid}
|
||||
secondary={
|
||||
'Security: ' +
|
||||
networkSecurityMode(selectedNetwork) +
|
||||
', Ch: ' +
|
||||
selectedNetwork.channel
|
||||
}
|
||||
/>
|
||||
<ListItemSecondaryAction>
|
||||
<IconButton
|
||||
aria-label="Manual Config"
|
||||
onClick={deselectNetwork}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</ListItemSecondaryAction>
|
||||
</ListItem>
|
||||
</List>
|
||||
) : (
|
||||
<TextValidator
|
||||
validators={['matchRegexp:^.{0,32}$']}
|
||||
errorMessages={['SSID must be 32 characters or less']}
|
||||
name="ssid"
|
||||
label="SSID (leave blank to disable WiFi)"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={data.ssid}
|
||||
onChange={handleValueChange('ssid')}
|
||||
margin="normal"
|
||||
/>
|
||||
)}
|
||||
{(!selectedNetwork || !isNetworkOpen(selectedNetwork)) && (
|
||||
<PasswordValidator
|
||||
validators={['matchRegexp:^.{0,64}$']}
|
||||
errorMessages={['Password must be 64 characters or less']}
|
||||
@@ -105,10 +133,10 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
onChange={handleValueChange('password')}
|
||||
margin="normal"
|
||||
/>
|
||||
}
|
||||
)}
|
||||
<TextValidator
|
||||
validators={['required', 'isHostname']}
|
||||
errorMessages={['Hostname is required', "Not a valid hostname"]}
|
||||
errorMessages={['Hostname is required', 'Not a valid hostname']}
|
||||
name="hostname"
|
||||
label="Hostname"
|
||||
fullWidth
|
||||
@@ -122,13 +150,12 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
<Checkbox
|
||||
value="static_ip_config"
|
||||
checked={data.static_ip_config}
|
||||
onChange={handleValueChange("static_ip_config")}
|
||||
onChange={handleValueChange('static_ip_config')}
|
||||
/>
|
||||
}
|
||||
label="Static IP Config"
|
||||
/>
|
||||
{
|
||||
data.static_ip_config &&
|
||||
{data.static_ip_config && (
|
||||
<Fragment>
|
||||
<TextValidator
|
||||
validators={['required', 'isIP']}
|
||||
@@ -154,7 +181,10 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
/>
|
||||
<TextValidator
|
||||
validators={['required', 'isIP']}
|
||||
errorMessages={['Subnet mask is required', 'Must be an IP address']}
|
||||
errorMessages={[
|
||||
'Subnet mask is required',
|
||||
'Must be an IP address'
|
||||
]}
|
||||
name="subnet_mask"
|
||||
label="Subnet"
|
||||
fullWidth
|
||||
@@ -186,9 +216,14 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
margin="normal"
|
||||
/>
|
||||
</Fragment>
|
||||
}
|
||||
)}
|
||||
<FormActions>
|
||||
<FormButton startIcon={<SaveIcon />} variant="contained" color="primary" type="submit">
|
||||
<FormButton
|
||||
startIcon={<SaveIcon />}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
type="submit"
|
||||
>
|
||||
Save
|
||||
</FormButton>
|
||||
</FormActions>
|
||||
@@ -197,4 +232,4 @@ class NetworkSettingsForm extends React.Component<NetworkStatusFormProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export default NetworkSettingsForm;
|
||||
export default NetworkSettingsForm;
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
import { Theme } from '@material-ui/core'
|
||||
import { NetworkStatus, NetworkConnectionStatus } from './types'
|
||||
import { Theme } from '@material-ui/core';
|
||||
import { NetworkStatus, NetworkConnectionStatus } from './types';
|
||||
|
||||
export const isConnected = ({ status }: NetworkStatus) => {
|
||||
return (
|
||||
status === NetworkConnectionStatus.WIFI_STATUS_CONNECTED ||
|
||||
status === NetworkConnectionStatus.ETHERNET_STATUS_CONNECTED
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const isWiFi = ({ status }: NetworkStatus) =>
|
||||
status === NetworkConnectionStatus.WIFI_STATUS_CONNECTED
|
||||
status === NetworkConnectionStatus.WIFI_STATUS_CONNECTED;
|
||||
export const isEthernet = ({ status }: NetworkStatus) =>
|
||||
status === NetworkConnectionStatus.ETHERNET_STATUS_CONNECTED
|
||||
status === NetworkConnectionStatus.ETHERNET_STATUS_CONNECTED;
|
||||
|
||||
export const networkStatusHighlight = (
|
||||
{ status }: NetworkStatus,
|
||||
theme: Theme,
|
||||
theme: Theme
|
||||
) => {
|
||||
switch (status) {
|
||||
case NetworkConnectionStatus.WIFI_STATUS_IDLE:
|
||||
case NetworkConnectionStatus.WIFI_STATUS_DISCONNECTED:
|
||||
case NetworkConnectionStatus.WIFI_STATUS_NO_SHIELD:
|
||||
return theme.palette.info.main
|
||||
return theme.palette.info.main;
|
||||
case NetworkConnectionStatus.WIFI_STATUS_CONNECTED:
|
||||
case NetworkConnectionStatus.ETHERNET_STATUS_CONNECTED:
|
||||
return theme.palette.success.main
|
||||
return theme.palette.success.main;
|
||||
case NetworkConnectionStatus.WIFI_STATUS_CONNECT_FAILED:
|
||||
case NetworkConnectionStatus.WIFI_STATUS_CONNECTION_LOST:
|
||||
return theme.palette.error.main
|
||||
return theme.palette.error.main;
|
||||
default:
|
||||
return theme.palette.warning.main
|
||||
return theme.palette.warning.main;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const networkStatus = ({ status }: NetworkStatus) => {
|
||||
switch (status) {
|
||||
case NetworkConnectionStatus.WIFI_STATUS_NO_SHIELD:
|
||||
return 'Inactive'
|
||||
return 'Inactive';
|
||||
case NetworkConnectionStatus.WIFI_STATUS_IDLE:
|
||||
return 'Idle'
|
||||
return 'Idle';
|
||||
case NetworkConnectionStatus.WIFI_STATUS_NO_SSID_AVAIL:
|
||||
return 'No SSID Available'
|
||||
return 'No SSID Available';
|
||||
case NetworkConnectionStatus.WIFI_STATUS_CONNECTED:
|
||||
return 'Connected (WiFi)'
|
||||
return 'Connected (WiFi)';
|
||||
case NetworkConnectionStatus.ETHERNET_STATUS_CONNECTED:
|
||||
return 'Connected (Ethernet)'
|
||||
return 'Connected (Ethernet)';
|
||||
case NetworkConnectionStatus.WIFI_STATUS_CONNECT_FAILED:
|
||||
return 'Connection Failed'
|
||||
return 'Connection Failed';
|
||||
case NetworkConnectionStatus.WIFI_STATUS_CONNECTION_LOST:
|
||||
return 'Connection Lost'
|
||||
return 'Connection Lost';
|
||||
case NetworkConnectionStatus.WIFI_STATUS_DISCONNECTED:
|
||||
return 'Disconnected'
|
||||
return 'Disconnected';
|
||||
default:
|
||||
return 'Unknown'
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Component } from 'react';
|
||||
|
||||
import { restController, RestControllerProps, RestFormLoader, SectionContent } from '../components';
|
||||
import {
|
||||
restController,
|
||||
RestControllerProps,
|
||||
RestFormLoader,
|
||||
SectionContent
|
||||
} from '../components';
|
||||
import NetworkStatusForm from './NetworkStatusForm';
|
||||
import { NETWORK_STATUS_ENDPOINT } from '../api';
|
||||
import { NetworkStatus } from './types';
|
||||
@@ -8,7 +13,6 @@ import { NetworkStatus } from './types';
|
||||
type NetworkStatusControllerProps = RestControllerProps<NetworkStatus>;
|
||||
|
||||
class NetworkStatusController extends Component<NetworkStatusControllerProps> {
|
||||
|
||||
componentDidMount() {
|
||||
this.props.loadData();
|
||||
}
|
||||
@@ -18,12 +22,11 @@ class NetworkStatusController extends Component<NetworkStatusControllerProps> {
|
||||
<SectionContent title="Network Status">
|
||||
<RestFormLoader
|
||||
{...this.props}
|
||||
render={formProps => <NetworkStatusForm {...formProps} />}
|
||||
render={(formProps) => <NetworkStatusForm {...formProps} />}
|
||||
/>
|
||||
</SectionContent>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default restController(NETWORK_STATUS_ENDPOINT, NetworkStatusController);
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
import React, { Component, Fragment } from "react";
|
||||
import { Component, Fragment } from 'react';
|
||||
|
||||
import { WithTheme, withTheme } from "@material-ui/core/styles";
|
||||
import { WithTheme, withTheme } from '@material-ui/core/styles';
|
||||
import {
|
||||
Avatar,
|
||||
Divider,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemAvatar,
|
||||
ListItemText,
|
||||
} from "@material-ui/core";
|
||||
ListItemText
|
||||
} from '@material-ui/core';
|
||||
|
||||
import DNSIcon from "@material-ui/icons/Dns";
|
||||
import WifiIcon from "@material-ui/icons/Wifi";
|
||||
import RouterIcon from "@material-ui/icons/Router";
|
||||
import SettingsInputComponentIcon from "@material-ui/icons/SettingsInputComponent";
|
||||
import SettingsInputAntennaIcon from "@material-ui/icons/SettingsInputAntenna";
|
||||
import DeviceHubIcon from "@material-ui/icons/DeviceHub";
|
||||
import RefreshIcon from "@material-ui/icons/Refresh";
|
||||
import DNSIcon from '@material-ui/icons/Dns';
|
||||
import WifiIcon from '@material-ui/icons/Wifi';
|
||||
import RouterIcon from '@material-ui/icons/Router';
|
||||
import SettingsInputComponentIcon from '@material-ui/icons/SettingsInputComponent';
|
||||
import SettingsInputAntennaIcon from '@material-ui/icons/SettingsInputAntenna';
|
||||
import DeviceHubIcon from '@material-ui/icons/DeviceHub';
|
||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||
|
||||
import {
|
||||
RestFormProps,
|
||||
FormActions,
|
||||
FormButton,
|
||||
HighlightAvatar,
|
||||
} from "../components";
|
||||
HighlightAvatar
|
||||
} from '../components';
|
||||
import {
|
||||
networkStatus,
|
||||
networkStatusHighlight,
|
||||
isConnected,
|
||||
isWiFi,
|
||||
isEthernet,
|
||||
} from "./NetworkStatus";
|
||||
import { NetworkStatus } from "./types";
|
||||
isEthernet
|
||||
} from './NetworkStatus';
|
||||
import { NetworkStatus } from './types';
|
||||
|
||||
type NetworkStatusFormProps = RestFormProps<NetworkStatus> & WithTheme;
|
||||
|
||||
class NetworkStatusForm extends Component<NetworkStatusFormProps> {
|
||||
dnsServers(status: NetworkStatus) {
|
||||
if (!status.dns_ip_1) {
|
||||
return "none";
|
||||
return 'none';
|
||||
}
|
||||
return status.dns_ip_1 + (status.dns_ip_2 ? "," + status.dns_ip_2 : "");
|
||||
return status.dns_ip_1 + (status.dns_ip_2 ? ',' + status.dns_ip_2 : '');
|
||||
}
|
||||
|
||||
createListItems() {
|
||||
@@ -110,7 +110,7 @@ class NetworkStatusForm extends Component<NetworkStatusFormProps> {
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary="Gateway IP"
|
||||
secondary={data.gateway_ip || "none"}
|
||||
secondary={data.gateway_ip || 'none'}
|
||||
/>
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Component } from 'react';
|
||||
import { withSnackbar, WithSnackbarProps } from 'notistack';
|
||||
|
||||
import { createStyles, WithStyles, Theme, withStyles, Typography, LinearProgress } from '@material-ui/core';
|
||||
import {
|
||||
createStyles,
|
||||
WithStyles,
|
||||
Theme,
|
||||
withStyles,
|
||||
Typography,
|
||||
LinearProgress
|
||||
} from '@material-ui/core';
|
||||
import PermScanWifiIcon from '@material-ui/icons/PermScanWifi';
|
||||
|
||||
import { FormActions, FormButton, SectionContent } from '../components';
|
||||
@@ -11,9 +18,9 @@ import { SCAN_NETWORKS_ENDPOINT, LIST_NETWORKS_ENDPOINT } from '../api';
|
||||
import WiFiNetworkSelector from './WiFiNetworkSelector';
|
||||
import { WiFiNetworkList, WiFiNetwork } from './types';
|
||||
|
||||
const NUM_POLLS = 10
|
||||
const POLLING_FREQUENCY = 500
|
||||
const RETRY_EXCEPTION_TYPE = "retry"
|
||||
const NUM_POLLS = 10;
|
||||
const POLLING_FREQUENCY = 500;
|
||||
const RETRY_EXCEPTION_TYPE = 'retry';
|
||||
|
||||
interface WiFiNetworkScannerState {
|
||||
scanningForNetworks: boolean;
|
||||
@@ -21,28 +28,31 @@ interface WiFiNetworkScannerState {
|
||||
networkList?: WiFiNetworkList;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) => createStyles({
|
||||
scanningSettings: {
|
||||
margin: theme.spacing(0.5),
|
||||
},
|
||||
scanningSettingsDetails: {
|
||||
margin: theme.spacing(4),
|
||||
textAlign: "center"
|
||||
},
|
||||
scanningProgress: {
|
||||
margin: theme.spacing(4),
|
||||
textAlign: "center"
|
||||
}
|
||||
});
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
scanningSettings: {
|
||||
margin: theme.spacing(0.5)
|
||||
},
|
||||
scanningSettingsDetails: {
|
||||
margin: theme.spacing(4),
|
||||
textAlign: 'center'
|
||||
},
|
||||
scanningProgress: {
|
||||
margin: theme.spacing(4),
|
||||
textAlign: 'center'
|
||||
}
|
||||
});
|
||||
|
||||
type WiFiNetworkScannerProps = WithSnackbarProps & WithStyles<typeof styles>;
|
||||
|
||||
class WiFiNetworkScanner extends Component<WiFiNetworkScannerProps, WiFiNetworkScannerState> {
|
||||
|
||||
pollCount: number = 0;
|
||||
class WiFiNetworkScanner extends Component<
|
||||
WiFiNetworkScannerProps,
|
||||
WiFiNetworkScannerState
|
||||
> {
|
||||
pollCount = 0;
|
||||
|
||||
state: WiFiNetworkScannerState = {
|
||||
scanningForNetworks: false,
|
||||
scanningForNetworks: false
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
@@ -54,23 +64,36 @@ class WiFiNetworkScanner extends Component<WiFiNetworkScannerProps, WiFiNetworkS
|
||||
if (!scanningForNetworks) {
|
||||
this.scanNetworks();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scanNetworks() {
|
||||
this.pollCount = 0;
|
||||
this.setState({ scanningForNetworks: true, networkList: undefined, errorMessage: undefined });
|
||||
redirectingAuthorizedFetch(SCAN_NETWORKS_ENDPOINT).then(response => {
|
||||
if (response.status === 202) {
|
||||
this.schedulePollTimeout();
|
||||
return;
|
||||
}
|
||||
throw Error("Scanning for networks returned unexpected response code: " + response.status);
|
||||
}).catch(error => {
|
||||
this.props.enqueueSnackbar("Problem scanning: " + error.message, {
|
||||
variant: 'error',
|
||||
});
|
||||
this.setState({ scanningForNetworks: false, networkList: undefined, errorMessage: error.message });
|
||||
this.setState({
|
||||
scanningForNetworks: true,
|
||||
networkList: undefined,
|
||||
errorMessage: undefined
|
||||
});
|
||||
redirectingAuthorizedFetch(SCAN_NETWORKS_ENDPOINT)
|
||||
.then((response) => {
|
||||
if (response.status === 202) {
|
||||
this.schedulePollTimeout();
|
||||
return;
|
||||
}
|
||||
throw Error(
|
||||
'Scanning for networks returned unexpected response code: ' +
|
||||
response.status
|
||||
);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.props.enqueueSnackbar('Problem scanning: ' + error.message, {
|
||||
variant: 'error'
|
||||
});
|
||||
this.setState({
|
||||
scanningForNetworks: false,
|
||||
networkList: undefined,
|
||||
errorMessage: error.message
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
schedulePollTimeout() {
|
||||
@@ -80,21 +103,20 @@ class WiFiNetworkScanner extends Component<WiFiNetworkScannerProps, WiFiNetworkS
|
||||
retryError() {
|
||||
return {
|
||||
name: RETRY_EXCEPTION_TYPE,
|
||||
message: "Network list not ready, will retry in " + POLLING_FREQUENCY + "ms."
|
||||
message:
|
||||
'Network list not ready, will retry in ' + POLLING_FREQUENCY + 'ms.'
|
||||
};
|
||||
}
|
||||
|
||||
compareNetworks(network1: WiFiNetwork, network2: WiFiNetwork) {
|
||||
if (network1.rssi < network2.rssi)
|
||||
return 1;
|
||||
if (network1.rssi > network2.rssi)
|
||||
return -1;
|
||||
if (network1.rssi < network2.rssi) return 1;
|
||||
if (network1.rssi > network2.rssi) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pollNetworkList = () => {
|
||||
redirectingAuthorizedFetch(LIST_NETWORKS_ENDPOINT)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
if (response.status === 200) {
|
||||
return response.json();
|
||||
}
|
||||
@@ -103,24 +125,34 @@ class WiFiNetworkScanner extends Component<WiFiNetworkScannerProps, WiFiNetworkS
|
||||
this.schedulePollTimeout();
|
||||
throw this.retryError();
|
||||
} else {
|
||||
throw Error("Device did not return network list in timely manner.");
|
||||
throw Error('Device did not return network list in timely manner.');
|
||||
}
|
||||
}
|
||||
throw Error("Device returned unexpected response code: " + response.status);
|
||||
throw Error(
|
||||
'Device returned unexpected response code: ' + response.status
|
||||
);
|
||||
})
|
||||
.then(json => {
|
||||
json.networks.sort(this.compareNetworks)
|
||||
this.setState({ scanningForNetworks: false, networkList: json, errorMessage: undefined })
|
||||
.then((json) => {
|
||||
json.networks.sort(this.compareNetworks);
|
||||
this.setState({
|
||||
scanningForNetworks: false,
|
||||
networkList: json,
|
||||
errorMessage: undefined
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
if (error.name !== RETRY_EXCEPTION_TYPE) {
|
||||
this.props.enqueueSnackbar("Problem scanning: " + error.message, {
|
||||
variant: 'error',
|
||||
this.props.enqueueSnackbar('Problem scanning: ' + error.message, {
|
||||
variant: 'error'
|
||||
});
|
||||
this.setState({
|
||||
scanningForNetworks: false,
|
||||
networkList: undefined,
|
||||
errorMessage: error.message
|
||||
});
|
||||
this.setState({ scanningForNetworks: false, networkList: undefined, errorMessage: error.message });
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
renderNetworkScanner() {
|
||||
const { classes } = this.props;
|
||||
@@ -144,9 +176,7 @@ class WiFiNetworkScanner extends Component<WiFiNetworkScannerProps, WiFiNetworkS
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<WiFiNetworkSelector networkList={networkList} />
|
||||
);
|
||||
return <WiFiNetworkSelector networkList={networkList} />;
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -155,14 +185,19 @@ class WiFiNetworkScanner extends Component<WiFiNetworkScannerProps, WiFiNetworkS
|
||||
<SectionContent title="Network Scanner">
|
||||
{this.renderNetworkScanner()}
|
||||
<FormActions>
|
||||
<FormButton startIcon={<PermScanWifiIcon />} variant="contained" color="secondary" onClick={this.requestNetworkScan} disabled={scanningForNetworks}>
|
||||
<FormButton
|
||||
startIcon={<PermScanWifiIcon />}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
onClick={this.requestNetworkScan}
|
||||
disabled={scanningForNetworks}
|
||||
>
|
||||
Scan again…
|
||||
</FormButton>
|
||||
</FormActions>
|
||||
</SectionContent>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default withSnackbar(withStyles(styles)(WiFiNetworkScanner));
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { Avatar, Badge } from '@material-ui/core';
|
||||
import { List, ListItem, ListItemIcon, ListItemText, ListItemAvatar } from '@material-ui/core';
|
||||
import {
|
||||
List,
|
||||
ListItem,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
ListItemAvatar
|
||||
} from '@material-ui/core';
|
||||
|
||||
import WifiIcon from '@material-ui/icons/Wifi';
|
||||
import LockIcon from '@material-ui/icons/Lock';
|
||||
@@ -16,13 +22,16 @@ interface WiFiNetworkSelectorProps {
|
||||
}
|
||||
|
||||
class WiFiNetworkSelector extends Component<WiFiNetworkSelectorProps> {
|
||||
|
||||
static contextType = NetworkConnectionContext;
|
||||
context!: React.ContextType<typeof NetworkConnectionContext>;
|
||||
|
||||
renderNetwork = (network: WiFiNetwork) => {
|
||||
return (
|
||||
<ListItem key={network.bssid} button onClick={() => this.context.selectNetwork(network)}>
|
||||
<ListItem
|
||||
key={network.bssid}
|
||||
button
|
||||
onClick={() => this.context.selectNetwork(network)}
|
||||
>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
{isNetworkOpen(network) ? <LockOpenIcon /> : <LockIcon />}
|
||||
@@ -30,25 +39,27 @@ class WiFiNetworkSelector extends Component<WiFiNetworkSelectorProps> {
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={network.ssid}
|
||||
secondary={"Security: " + networkSecurityMode(network) + ", Ch: " + network.channel}
|
||||
secondary={
|
||||
'Security: ' +
|
||||
networkSecurityMode(network) +
|
||||
', Ch: ' +
|
||||
network.channel
|
||||
}
|
||||
/>
|
||||
<ListItemIcon>
|
||||
<Badge badgeContent={network.rssi + "db"}>
|
||||
<Badge badgeContent={network.rssi + 'db'}>
|
||||
<WifiIcon />
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
</ListItem>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<List>
|
||||
{this.props.networkList.networks.map(this.renderNetwork)}
|
||||
</List>
|
||||
<List>{this.props.networkList.networks.map(this.renderNetwork)}</List>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default WiFiNetworkSelector;
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import { WiFiNetwork, WiFiEncryptionType } from './types'
|
||||
import { WiFiNetwork, WiFiEncryptionType } from './types';
|
||||
|
||||
export const isNetworkOpen = ({ encryption_type }: WiFiNetwork) =>
|
||||
encryption_type === WiFiEncryptionType.WIFI_AUTH_OPEN
|
||||
encryption_type === WiFiEncryptionType.WIFI_AUTH_OPEN;
|
||||
|
||||
export const networkSecurityMode = ({ encryption_type }: WiFiNetwork) => {
|
||||
switch (encryption_type) {
|
||||
case WiFiEncryptionType.WIFI_AUTH_WEP:
|
||||
return 'WEP'
|
||||
return 'WEP';
|
||||
case WiFiEncryptionType.WIFI_AUTH_WPA_PSK:
|
||||
return 'WPA'
|
||||
return 'WPA';
|
||||
case WiFiEncryptionType.WIFI_AUTH_WPA2_PSK:
|
||||
return 'WPA2'
|
||||
return 'WPA2';
|
||||
case WiFiEncryptionType.WIFI_AUTH_WPA_WPA2_PSK:
|
||||
return 'WPA/WPA2'
|
||||
return 'WPA/WPA2';
|
||||
case WiFiEncryptionType.WIFI_AUTH_WPA2_ENTERPRISE:
|
||||
return 'WPA2 Enterprise'
|
||||
return 'WPA2 Enterprise';
|
||||
case WiFiEncryptionType.WIFI_AUTH_OPEN:
|
||||
return 'None'
|
||||
return 'None';
|
||||
default:
|
||||
return 'Unknown'
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ export enum NetworkConnectionStatus {
|
||||
WIFI_STATUS_CONNECTION_LOST = 5,
|
||||
WIFI_STATUS_DISCONNECTED = 6,
|
||||
ETHERNET_STATUS_CONNECTED = 10,
|
||||
WIFI_STATUS_NO_SHIELD = 255,
|
||||
WIFI_STATUS_NO_SHIELD = 255
|
||||
}
|
||||
|
||||
export enum WiFiEncryptionType {
|
||||
@@ -15,43 +15,43 @@ export enum WiFiEncryptionType {
|
||||
WIFI_AUTH_WPA_PSK = 2,
|
||||
WIFI_AUTH_WPA2_PSK = 3,
|
||||
WIFI_AUTH_WPA_WPA2_PSK = 4,
|
||||
WIFI_AUTH_WPA2_ENTERPRISE = 5,
|
||||
WIFI_AUTH_WPA2_ENTERPRISE = 5
|
||||
}
|
||||
|
||||
export interface NetworkStatus {
|
||||
status: NetworkConnectionStatus
|
||||
local_ip: string
|
||||
mac_address: string
|
||||
rssi: number
|
||||
ssid: string
|
||||
bssid: string
|
||||
channel: number
|
||||
subnet_mask: string
|
||||
gateway_ip: string
|
||||
dns_ip_1: string
|
||||
dns_ip_2: string
|
||||
status: NetworkConnectionStatus;
|
||||
local_ip: string;
|
||||
mac_address: string;
|
||||
rssi: number;
|
||||
ssid: string;
|
||||
bssid: string;
|
||||
channel: number;
|
||||
subnet_mask: string;
|
||||
gateway_ip: string;
|
||||
dns_ip_1: string;
|
||||
dns_ip_2: string;
|
||||
}
|
||||
|
||||
export interface NetworkSettings {
|
||||
ssid: string
|
||||
password: string
|
||||
hostname: string
|
||||
static_ip_config: boolean
|
||||
local_ip?: string
|
||||
gateway_ip?: string
|
||||
subnet_mask?: string
|
||||
dns_ip_1?: string
|
||||
dns_ip_2?: string
|
||||
ssid: string;
|
||||
password: string;
|
||||
hostname: string;
|
||||
static_ip_config: boolean;
|
||||
local_ip?: string;
|
||||
gateway_ip?: string;
|
||||
subnet_mask?: string;
|
||||
dns_ip_1?: string;
|
||||
dns_ip_2?: string;
|
||||
}
|
||||
|
||||
export interface WiFiNetworkList {
|
||||
networks: WiFiNetwork[]
|
||||
networks: WiFiNetwork[];
|
||||
}
|
||||
|
||||
export interface WiFiNetwork {
|
||||
rssi: number
|
||||
ssid: string
|
||||
bssid: string
|
||||
channel: number
|
||||
encryption_type: WiFiEncryptionType
|
||||
rssi: number;
|
||||
ssid: string;
|
||||
bssid: string;
|
||||
channel: number;
|
||||
encryption_type: WiFiEncryptionType;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user