WIP - demo project
This commit is contained in:
parent
4bb4871a6d
commit
a0d6524180
@ -1 +1,5 @@
|
|||||||
REACT_APP_NAME=ESP8266 React
|
# This is the name of your project. It appears on the sign-in page and in the menu bar.
|
||||||
|
REACT_APP_PROJECT_NAME=ESP8266 React
|
||||||
|
|
||||||
|
# This is the url path your project will be exposed under.
|
||||||
|
REACT_APP_PROJECT_PATH=project
|
||||||
|
@ -1 +1 @@
|
|||||||
REACT_APP_ENDPOINT_ROOT=http://192.168.0.11/rest/
|
REACT_APP_ENDPOINT_ROOT=http://192.168.0.19/rest/
|
||||||
|
@ -2,18 +2,18 @@ import React, { Component } from 'react';
|
|||||||
|
|
||||||
import { Redirect, Switch } from 'react-router';
|
import { Redirect, Switch } from 'react-router';
|
||||||
|
|
||||||
|
import { PROJECT_PATH } from './constants/Env';
|
||||||
import * as Authentication from './authentication/Authentication';
|
import * as Authentication from './authentication/Authentication';
|
||||||
import AuthenticationWrapper from './authentication/AuthenticationWrapper';
|
import AuthenticationWrapper from './authentication/AuthenticationWrapper';
|
||||||
import AuthenticatedRoute from './authentication/AuthenticatedRoute';
|
import AuthenticatedRoute from './authentication/AuthenticatedRoute';
|
||||||
import UnauthenticatedRoute from './authentication/UnauthenticatedRoute';
|
import UnauthenticatedRoute from './authentication/UnauthenticatedRoute';
|
||||||
|
|
||||||
import SignInPage from './containers/SignInPage';
|
import SignInPage from './containers/SignInPage';
|
||||||
|
|
||||||
import WiFiConnection from './sections/WiFiConnection';
|
import WiFiConnection from './sections/WiFiConnection';
|
||||||
import AccessPoint from './sections/AccessPoint';
|
import AccessPoint from './sections/AccessPoint';
|
||||||
import NetworkTime from './sections/NetworkTime';
|
import NetworkTime from './sections/NetworkTime';
|
||||||
import Security from './sections/Security';
|
import Security from './sections/Security';
|
||||||
import System from './sections/System';
|
import System from './sections/System';
|
||||||
|
import ProjectRouting from './project/ProjectRouting';
|
||||||
|
|
||||||
class AppRouting extends Component {
|
class AppRouting extends Component {
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ class AppRouting extends Component {
|
|||||||
<AuthenticatedRoute exact path="/ntp/*" component={NetworkTime} />
|
<AuthenticatedRoute exact path="/ntp/*" component={NetworkTime} />
|
||||||
<AuthenticatedRoute exact path="/security/*" component={Security} />
|
<AuthenticatedRoute exact path="/security/*" component={Security} />
|
||||||
<AuthenticatedRoute exact path="/system/*" component={System} />
|
<AuthenticatedRoute exact path="/system/*" component={System} />
|
||||||
|
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/*`} component={ProjectRouting} />
|
||||||
<Redirect to="/" />
|
<Redirect to="/" />
|
||||||
</Switch>
|
</Switch>
|
||||||
</AuthenticationWrapper>
|
</AuthenticationWrapper>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import history from '../history';
|
import history from '../history';
|
||||||
|
import { PROJECT_PATH } from '../constants/Env';
|
||||||
|
|
||||||
export const ACCESS_TOKEN = 'access_token';
|
export const ACCESS_TOKEN = 'access_token';
|
||||||
export const LOGIN_PATHNAME = 'loginPathname';
|
export const LOGIN_PATHNAME = 'loginPathname';
|
||||||
@ -21,7 +22,7 @@ export function fetchLoginRedirect() {
|
|||||||
const loginSearch = localStorage.getItem(LOGIN_SEARCH);
|
const loginSearch = localStorage.getItem(LOGIN_SEARCH);
|
||||||
clearLoginRedirect();
|
clearLoginRedirect();
|
||||||
return {
|
return {
|
||||||
pathname: loginPathname || "/wifi/",
|
pathname: loginPathname || `/${PROJECT_PATH}/`,
|
||||||
search: (loginPathname && loginSearch) || undefined
|
search: (loginPathname && loginSearch) || undefined
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,8 @@ import CardContent from '@material-ui/core/CardContent';
|
|||||||
import CardActions from '@material-ui/core/CardActions';
|
import CardActions from '@material-ui/core/CardActions';
|
||||||
import Avatar from '@material-ui/core/Avatar';
|
import Avatar from '@material-ui/core/Avatar';
|
||||||
|
|
||||||
import { APP_NAME } from '../constants/App';
|
import ProjectMenu from '../project/ProjectMenu';
|
||||||
|
import { PROJECT_NAME } from '../constants/Env';
|
||||||
import { withAuthenticationContext } from '../authentication/Context.js';
|
import { withAuthenticationContext } from '../authentication/Context.js';
|
||||||
|
|
||||||
const drawerWidth = 290;
|
const drawerWidth = 290;
|
||||||
@ -65,8 +66,7 @@ const styles = theme => ({
|
|||||||
width: drawerWidth,
|
width: drawerWidth,
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
flexGrow: 1,
|
flexGrow: 1
|
||||||
padding: theme.spacing(),
|
|
||||||
},
|
},
|
||||||
authMenu: {
|
authMenu: {
|
||||||
zIndex: theme.zIndex.tooltip,
|
zIndex: theme.zIndex.tooltip,
|
||||||
@ -112,11 +112,13 @@ class MenuAppBar extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<Typography variant="h6" color="primary">
|
<Typography variant="h6" color="primary">
|
||||||
{APP_NAME}
|
{PROJECT_NAME}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Divider absolute />
|
<Divider absolute />
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
<ProjectMenu />
|
||||||
|
<Divider />
|
||||||
<List>
|
<List>
|
||||||
<ListItem to='/wifi/' selected={path.startsWith('/wifi/')} button component={Link}>
|
<ListItem to='/wifi/' selected={path.startsWith('/wifi/')} button component={Link}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
|
@ -8,15 +8,15 @@ import Typography from '@material-ui/core/Typography';
|
|||||||
const styles = theme => ({
|
const styles = theme => ({
|
||||||
content: {
|
content: {
|
||||||
padding: theme.spacing(2),
|
padding: theme.spacing(2),
|
||||||
margin: theme.spacing(2),
|
margin: theme.spacing(3),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function SectionContent(props) {
|
function SectionContent(props) {
|
||||||
const { children, classes, title } = props;
|
const { children, classes, title, titleGutter } = props;
|
||||||
return (
|
return (
|
||||||
<Paper className={classes.content}>
|
<Paper className={classes.content}>
|
||||||
<Typography variant="h6">
|
<Typography variant="h6" gutterBottom={titleGutter}>
|
||||||
{title}
|
{title}
|
||||||
</Typography>
|
</Typography>
|
||||||
{children}
|
{children}
|
||||||
@ -30,7 +30,8 @@ SectionContent.propTypes = {
|
|||||||
PropTypes.arrayOf(PropTypes.node),
|
PropTypes.arrayOf(PropTypes.node),
|
||||||
PropTypes.node
|
PropTypes.node
|
||||||
]).isRequired,
|
]).isRequired,
|
||||||
title: PropTypes.string.isRequired
|
title: PropTypes.string.isRequired,
|
||||||
|
titleGutter: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withStyles(styles)(SectionContent);
|
export default withStyles(styles)(SectionContent);
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export const APP_NAME = process.env.REACT_APP_NAME;
|
|
2
interface/src/constants/Env.js
Normal file
2
interface/src/constants/Env.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const PROJECT_NAME = process.env.REACT_APP_PROJECT_NAME;
|
||||||
|
export const PROJECT_PATH = process.env.REACT_APP_PROJECT_PATH;
|
@ -96,9 +96,7 @@ class APStatus extends Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<List>
|
<List>
|
||||||
<Fragment>
|
|
||||||
{this.createListItems(data, classes)}
|
{this.createListItems(data, classes)}
|
||||||
</Fragment>
|
|
||||||
</List>
|
</List>
|
||||||
<Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}>
|
<Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}>
|
||||||
Refresh
|
Refresh
|
||||||
|
@ -14,7 +14,7 @@ class ManageUsers extends Component {
|
|||||||
render() {
|
render() {
|
||||||
const { data, fetched, errorMessage } = this.props;
|
const { data, fetched, errorMessage } = this.props;
|
||||||
return (
|
return (
|
||||||
<SectionContent title="Manage Users">
|
<SectionContent title="Manage Users" titleGutter>
|
||||||
<ManageUsersForm
|
<ManageUsersForm
|
||||||
userData={data}
|
userData={data}
|
||||||
userDataFetched={fetched}
|
userDataFetched={fetched}
|
||||||
|
@ -4,7 +4,7 @@ import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator';
|
|||||||
import Paper from '@material-ui/core/Paper';
|
import Paper from '@material-ui/core/Paper';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import Fab from '@material-ui/core/Fab';
|
import Fab from '@material-ui/core/Fab';
|
||||||
import { APP_NAME } from '../constants/App';
|
import { PROJECT_NAME } from '../constants/Env';
|
||||||
import ForwardIcon from '@material-ui/icons/Forward';
|
import ForwardIcon from '@material-ui/icons/Forward';
|
||||||
import { withNotifier } from '../components/SnackbarNotification';
|
import { withNotifier } from '../components/SnackbarNotification';
|
||||||
import { SIGN_IN_ENDPOINT } from '../constants/Endpoints';
|
import { SIGN_IN_ENDPOINT } from '../constants/Endpoints';
|
||||||
@ -95,7 +95,7 @@ class SignInPage extends Component {
|
|||||||
return (
|
return (
|
||||||
<div className={classes.loginPage}>
|
<div className={classes.loginPage}>
|
||||||
<Paper className={classes.loginPanel}>
|
<Paper className={classes.loginPanel}>
|
||||||
<Typography variant="h4">{APP_NAME}</Typography>
|
<Typography variant="h4">{PROJECT_NAME}</Typography>
|
||||||
<ValidatorForm onSubmit={this.onSubmit}>
|
<ValidatorForm onSubmit={this.onSubmit}>
|
||||||
<TextValidator
|
<TextValidator
|
||||||
disabled={processing}
|
disabled={processing}
|
||||||
|
22
interface/src/project/DemoController.js
Normal file
22
interface/src/project/DemoController.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
import SectionContent from '../components/SectionContent';
|
||||||
|
|
||||||
|
const styles = theme => ({
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
class DemoController extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<SectionContent title="Controller" titleGutter>
|
||||||
|
TODO - This will contain a form which controls the speed of the built in LED.
|
||||||
|
</SectionContent>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStyles(styles)(DemoController);
|
99
interface/src/project/DemoInformation.js
Normal file
99
interface/src/project/DemoInformation.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
import Table from '@material-ui/core/Table';
|
||||||
|
import TableHead from '@material-ui/core/TableHead';
|
||||||
|
import TableCell from '@material-ui/core/TableCell';
|
||||||
|
import TableBody from '@material-ui/core/TableBody';
|
||||||
|
import TableRow from '@material-ui/core/TableRow';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import SectionContent from '../components/SectionContent';
|
||||||
|
|
||||||
|
const styles = theme => ({
|
||||||
|
fileTable: {
|
||||||
|
marginBottom: theme.spacing(2)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
class DemoInformation extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { classes } = this.props;
|
||||||
|
return (
|
||||||
|
<SectionContent title="Demo Project - Blink Speed Controller" titleGutter>
|
||||||
|
<Typography variant="body1" paragraph>
|
||||||
|
This simple demo project allows you to control the blink speed of the built-in LED.
|
||||||
|
It demonstrates how the esp8266-react framework may be extended for your own IoT project.
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" paragraph>
|
||||||
|
It is recommended that you keep your project interface code under the 'project' directory.
|
||||||
|
This serves to isolate your project code from the from the rest of the user interface which should
|
||||||
|
simplify merges should you wish to update your project with future framework changes.
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" paragraph>
|
||||||
|
The demo project interface code is structured as follows:
|
||||||
|
</Typography>
|
||||||
|
<Table className={classes.fileTable}>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>
|
||||||
|
File
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
Description
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>
|
||||||
|
project/ProjectMenu.js
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
You can add your project's screens to the side bar here.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>
|
||||||
|
project/ProjectRouting.js
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
The routing which controls the screens of your project.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>
|
||||||
|
project/DemoProject.js
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
This screen, with tabs and tab routing.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>
|
||||||
|
project/DemoInformation.js
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
The demo information tab.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>
|
||||||
|
project/DemoController.js
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
The demo controller tab, to control the built-in LED.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
<Typography variant="body1" paragraph>
|
||||||
|
See the project <a href="https://github.com/rjwats/esp8266-react/">README</a> for a full description of the demo project.
|
||||||
|
</Typography>
|
||||||
|
</SectionContent>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStyles(styles)(DemoInformation);
|
37
interface/src/project/DemoProject.js
Normal file
37
interface/src/project/DemoProject.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { Redirect, Switch } from 'react-router-dom'
|
||||||
|
|
||||||
|
import { PROJECT_PATH } from '../constants/Env';
|
||||||
|
import MenuAppBar from '../components/MenuAppBar';
|
||||||
|
import AuthenticatedRoute from '../authentication/AuthenticatedRoute';
|
||||||
|
import DemoInformation from './DemoInformation';
|
||||||
|
import DemoController from './DemoController';
|
||||||
|
|
||||||
|
import Tabs from '@material-ui/core/Tabs';
|
||||||
|
import Tab from '@material-ui/core/Tab';
|
||||||
|
|
||||||
|
class DemoProject extends Component {
|
||||||
|
|
||||||
|
handleTabChange = (event, path) => {
|
||||||
|
this.props.history.push(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<MenuAppBar sectionTitle="Demo Project">
|
||||||
|
<Tabs value={this.props.match.url} onChange={this.handleTabChange} indicatorColor="primary" textColor="primary" variant="fullWidth">
|
||||||
|
<Tab value={`/${PROJECT_PATH}/demo/information`} label="Information" />
|
||||||
|
<Tab value={`/${PROJECT_PATH}/demo/controller`} label="Controller" />
|
||||||
|
</Tabs>
|
||||||
|
<Switch>
|
||||||
|
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/demo/information`} component={DemoInformation} />
|
||||||
|
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/demo/controller`} component={DemoController} />
|
||||||
|
<Redirect to={`/${PROJECT_PATH}/demo/information`} />
|
||||||
|
</Switch>
|
||||||
|
</MenuAppBar>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DemoProject;
|
31
interface/src/project/ProjectMenu.js
Normal file
31
interface/src/project/ProjectMenu.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { Link, withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { PROJECT_PATH } from '../constants/Env';
|
||||||
|
|
||||||
|
import List from '@material-ui/core/List';
|
||||||
|
import ListItem from '@material-ui/core/ListItem';
|
||||||
|
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||||
|
import ListItemText from '@material-ui/core/ListItemText';
|
||||||
|
import SettingsRemoteIcon from '@material-ui/icons/SettingsRemote';
|
||||||
|
import Divider from '@material-ui/core/Divider';
|
||||||
|
|
||||||
|
class ProjectMenu extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const path = this.props.match.url;
|
||||||
|
return (
|
||||||
|
<List>
|
||||||
|
<ListItem to={`/${PROJECT_PATH}/demo/`} selected={path.startsWith(`/${PROJECT_PATH}/demo/`)} button component={Link}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<SettingsRemoteIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary="Demo Project" />
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(ProjectMenu);
|
32
interface/src/project/ProjectRouting.js
Normal file
32
interface/src/project/ProjectRouting.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { Redirect, Switch } from 'react-router';
|
||||||
|
|
||||||
|
import { PROJECT_PATH } from '../constants/Env';
|
||||||
|
import AuthenticatedRoute from '../authentication/AuthenticatedRoute';
|
||||||
|
import DemoProject from './DemoProject';
|
||||||
|
|
||||||
|
class ProjectRouting extends Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Switch>
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Add your project page routing below.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/demo/*`} component={DemoProject} />
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The redirect below caters for the default project route and redirecting invalid paths.
|
||||||
|
* The "to" property must match one of the routes above for this to work correctly.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
<Redirect to={`/${PROJECT_PATH}/demo/`} />
|
||||||
|
</Switch>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProjectRouting;
|
@ -32,6 +32,7 @@ class NetworkTime extends Component {
|
|||||||
</MenuAppBar>
|
</MenuAppBar>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withAuthenticationContext(NetworkTime)
|
export default withAuthenticationContext(NetworkTime)
|
||||||
|
Loading…
Reference in New Issue
Block a user