This commit is contained in:
proddy
2021-05-14 12:45:57 +02:00
parent 15df0c0552
commit fec5ff3132
108 changed files with 3508 additions and 2455 deletions

View File

@@ -1,8 +1,8 @@
import { APSettings, APProvisionMode } from './types'
import { APSettings, APProvisionMode } from './types';
export const isAPEnabled = ({ provision_mode }: APSettings) => {
return (
provision_mode === APProvisionMode.AP_MODE_ALWAYS ||
provision_mode === APProvisionMode.AP_MODE_DISCONNECTED
)
}
);
};

View File

@@ -1,7 +1,12 @@
import React, { Component } from 'react';
import { Component } from 'react';
import { AP_SETTINGS_ENDPOINT } from '../api';
import { restController, RestControllerProps, RestFormLoader, SectionContent } from '../components';
import {
restController,
RestControllerProps,
RestFormLoader,
SectionContent
} from '../components';
import APSettingsForm from './APSettingsForm';
import { APSettings } from './types';
@@ -9,7 +14,6 @@ import { APSettings } from './types';
type APSettingsControllerProps = RestControllerProps<APSettings>;
class APSettingsController extends Component<APSettingsControllerProps> {
componentDidMount() {
this.props.loadData();
}
@@ -19,12 +23,11 @@ class APSettingsController extends Component<APSettingsControllerProps> {
<SectionContent title="Access Point Settings" titleGutter>
<RestFormLoader
{...this.props}
render={formProps => <APSettingsForm {...formProps} />}
render={(formProps) => <APSettingsForm {...formProps} />}
/>
</SectionContent>
)
);
}
}
export default restController(AP_SETTINGS_ENDPOINT, APSettingsController);

View File

@@ -1,10 +1,19 @@
import React, { Fragment } from 'react';
import { TextValidator, ValidatorForm, SelectValidator } from 'react-material-ui-form-validator';
import {
TextValidator,
ValidatorForm,
SelectValidator
} from 'react-material-ui-form-validator';
import MenuItem from '@material-ui/core/MenuItem';
import SaveIcon from '@material-ui/icons/Save';
import { PasswordValidator, RestFormProps, FormActions, FormButton } from '../components';
import {
PasswordValidator,
RestFormProps,
FormActions,
FormButton
} from '../components';
import { isAPEnabled } from './APModes';
import { APSettings, APProvisionMode } from './types';
@@ -13,7 +22,6 @@ import { isIP } from '../validators';
type APSettingsFormProps = RestFormProps<APSettings>;
class APSettingsForm extends React.Component<APSettingsFormProps> {
componentDidMount() {
ValidatorForm.addValidationRule('isIP', isIP);
}
@@ -22,23 +30,29 @@ class APSettingsForm extends React.Component<APSettingsFormProps> {
const { data, handleValueChange, saveData } = this.props;
return (
<ValidatorForm onSubmit={saveData} ref="APSettingsForm">
<SelectValidator name="provision_mode"
<SelectValidator
name="provision_mode"
label="Provide Access Point&hellip;"
value={data.provision_mode}
fullWidth
variant="outlined"
onChange={handleValueChange('provision_mode')}
margin="normal">
margin="normal"
>
<MenuItem value={APProvisionMode.AP_MODE_ALWAYS}>Always</MenuItem>
<MenuItem value={APProvisionMode.AP_MODE_DISCONNECTED}>When Network Disconnected</MenuItem>
<MenuItem value={APProvisionMode.AP_MODE_DISCONNECTED}>
When Network Disconnected
</MenuItem>
<MenuItem value={APProvisionMode.AP_NEVER}>Never</MenuItem>
</SelectValidator>
{
isAPEnabled(data) &&
{isAPEnabled(data) && (
<Fragment>
<TextValidator
validators={['required', 'matchRegexp:^.{1,32}$']}
errorMessages={['Access Point SSID is required', 'Access Point SSID must be 32 characters or less']}
errorMessages={[
'Access Point SSID is required',
'Access Point SSID must be 32 characters or less'
]}
name="ssid"
label="Access Point SSID"
fullWidth
@@ -49,7 +63,10 @@ class APSettingsForm extends React.Component<APSettingsFormProps> {
/>
<PasswordValidator
validators={['required', 'matchRegexp:^.{8,64}$']}
errorMessages={['Access Point Password is required', 'Access Point Password must be 8-64 characters']}
errorMessages={[
'Access Point Password is required',
'Access Point Password must be 8-64 characters'
]}
name="password"
label="Access Point Password"
fullWidth
@@ -71,7 +88,10 @@ class APSettingsForm extends React.Component<APSettingsFormProps> {
/>
<TextValidator
validators={['required', 'isIP']}
errorMessages={['Gateway IP is required', 'Must be an IP address']}
errorMessages={[
'Gateway IP is required',
'Must be an IP address'
]}
name="gateway_ip"
label="Gateway"
fullWidth
@@ -82,7 +102,10 @@ class APSettingsForm extends React.Component<APSettingsFormProps> {
/>
<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
@@ -92,9 +115,14 @@ class APSettingsForm extends React.Component<APSettingsFormProps> {
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>

View File

@@ -1,28 +1,28 @@
import { Theme } from '@material-ui/core'
import { APStatus, APNetworkStatus } from './types'
import { Theme } from '@material-ui/core';
import { APStatus, APNetworkStatus } from './types';
export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
switch (status) {
case APNetworkStatus.ACTIVE:
return theme.palette.success.main
return theme.palette.success.main;
case APNetworkStatus.INACTIVE:
return theme.palette.info.main
return theme.palette.info.main;
case APNetworkStatus.LINGERING:
return theme.palette.warning.main
return theme.palette.warning.main;
default:
return theme.palette.warning.main
return theme.palette.warning.main;
}
}
};
export const apStatus = ({ status }: APStatus) => {
switch (status) {
case APNetworkStatus.ACTIVE:
return 'Active'
return 'Active';
case APNetworkStatus.INACTIVE:
return 'Inactive'
return 'Inactive';
case APNetworkStatus.LINGERING:
return 'Lingering until idle'
return 'Lingering until idle';
default:
return 'Unknown'
return 'Unknown';
}
}
};

View File

@@ -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 { AP_STATUS_ENDPOINT } from '../api';
import APStatusForm from './APStatusForm';
@@ -9,7 +14,6 @@ import { APStatus } from './types';
type APStatusControllerProps = RestControllerProps<APStatus>;
class APStatusController extends Component<APStatusControllerProps> {
componentDidMount() {
this.props.loadData();
}
@@ -19,10 +23,10 @@ class APStatusController extends Component<APStatusControllerProps> {
<SectionContent title="Access Point Status">
<RestFormLoader
{...this.props}
render={formProps => <APStatusForm {...formProps} />}
render={(formProps) => <APStatusForm {...formProps} />}
/>
</SectionContent>
)
);
}
}

View File

@@ -1,23 +1,34 @@
import React, { Component, Fragment } from 'react';
import { WithTheme, withTheme } from '@material-ui/core/styles';
import { Avatar, Divider, List, ListItem, ListItemAvatar, ListItemText } from '@material-ui/core';
import {
Avatar,
Divider,
List,
ListItem,
ListItemAvatar,
ListItemText
} from '@material-ui/core';
import SettingsInputAntennaIcon from '@material-ui/icons/SettingsInputAntenna';
import DeviceHubIcon from '@material-ui/icons/DeviceHub';
import ComputerIcon from '@material-ui/icons/Computer';
import RefreshIcon from '@material-ui/icons/Refresh';
import { RestFormProps, FormActions, FormButton, HighlightAvatar } from '../components';
import {
RestFormProps,
FormActions,
FormButton,
HighlightAvatar
} from '../components';
import { apStatusHighlight, apStatus } from './APStatus';
import { APStatus } from './types';
type APStatusFormProps = RestFormProps<APStatus> & WithTheme;
class APStatusForm extends Component<APStatusFormProps> {
createListItems() {
const { data, theme } = this.props
const { data, theme } = this.props;
return (
<Fragment>
<ListItem>
@@ -61,18 +72,20 @@ class APStatusForm extends Component<APStatusFormProps> {
render() {
return (
<Fragment>
<List>
{this.createListItems()}
</List>
<List>{this.createListItems()}</List>
<FormActions>
<FormButton startIcon={<RefreshIcon />} variant="contained" color="secondary" onClick={this.props.loadData}>
<FormButton
startIcon={<RefreshIcon />}
variant="contained"
color="secondary"
onClick={this.props.loadData}
>
Refresh
</FormButton>
</FormActions>
</Fragment>
);
}
}
export default withTheme(APStatusForm);

View File

@@ -1,9 +1,13 @@
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 { AuthenticatedContextProps, withAuthenticatedContext, AuthenticatedRoute } from '../authentication';
import {
AuthenticatedContextProps,
withAuthenticatedContext,
AuthenticatedRoute
} from '../authentication';
import { MenuAppBar } from '../components';
import APSettingsController from './APSettingsController';
@@ -12,8 +16,7 @@ import APStatusController from './APStatusController';
type AccessPointProps = AuthenticatedContextProps & RouteComponentProps;
class AccessPoint extends Component<AccessPointProps> {
handleTabChange = (event: React.ChangeEvent<{}>, path: string) => {
handleTabChange = (path: string) => {
this.props.history.push(path);
};
@@ -21,17 +24,33 @@ class AccessPoint extends Component<AccessPointProps> {
const { authenticatedContext } = this.props;
return (
<MenuAppBar sectionTitle="Access Point">
<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="/ap/status" label="Access Point Status" />
<Tab value="/ap/settings" label="Access Point Settings" disabled={!authenticatedContext.me.admin} />
<Tab
value="/ap/settings"
label="Access Point Settings"
disabled={!authenticatedContext.me.admin}
/>
</Tabs>
<Switch>
<AuthenticatedRoute exact path="/ap/status" component={APStatusController} />
<AuthenticatedRoute exact path="/ap/settings" component={APSettingsController} />
<AuthenticatedRoute
exact
path="/ap/status"
component={APStatusController}
/>
<AuthenticatedRoute
exact
path="/ap/settings"
component={APSettingsController}
/>
<Redirect to="/ap/status" />
</Switch>
</MenuAppBar>
)
);
}
}

View File

@@ -1,27 +1,27 @@
export enum APProvisionMode {
AP_MODE_ALWAYS = 0,
AP_MODE_DISCONNECTED = 1,
AP_NEVER = 2,
AP_NEVER = 2
}
export enum APNetworkStatus {
ACTIVE = 0,
INACTIVE = 1,
LINGERING = 2,
LINGERING = 2
}
export interface APStatus {
status: APNetworkStatus
ip_address: string
mac_address: string
station_num: number
status: APNetworkStatus;
ip_address: string;
mac_address: string;
station_num: number;
}
export interface APSettings {
provision_mode: APProvisionMode
ssid: string
password: string
local_ip: string
gateway_ip: string
subnet_mask: string
provision_mode: APProvisionMode;
ssid: string;
password: string;
local_ip: string;
gateway_ip: string;
subnet_mask: string;
}