From a0d65241804e39aec5f73e38eca2dc05031fc5ee Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Sat, 6 Jul 2019 23:56:30 +0100 Subject: [PATCH 01/19] WIP - demo project --- interface/.env | 6 +- interface/.env.development | 2 +- interface/src/AppRouting.js | 5 +- .../src/authentication/Authentication.js | 3 +- interface/src/components/MenuAppBar.js | 10 +- interface/src/components/SectionContent.js | 9 +- interface/src/constants/App.js | 1 - interface/src/constants/Env.js | 2 + interface/src/containers/APStatus.js | 4 +- interface/src/containers/ManageUsers.js | 2 +- interface/src/containers/SignInPage.js | 4 +- interface/src/project/DemoController.js | 22 +++++ interface/src/project/DemoInformation.js | 99 +++++++++++++++++++ interface/src/project/DemoProject.js | 37 +++++++ interface/src/project/ProjectMenu.js | 31 ++++++ interface/src/project/ProjectRouting.js | 32 ++++++ interface/src/sections/NetworkTime.js | 1 + 17 files changed, 250 insertions(+), 20 deletions(-) delete mode 100644 interface/src/constants/App.js create mode 100644 interface/src/constants/Env.js create mode 100644 interface/src/project/DemoController.js create mode 100644 interface/src/project/DemoInformation.js create mode 100644 interface/src/project/DemoProject.js create mode 100644 interface/src/project/ProjectMenu.js create mode 100644 interface/src/project/ProjectRouting.js diff --git a/interface/.env b/interface/.env index 54f3b9d..a312b2a 100644 --- a/interface/.env +++ b/interface/.env @@ -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 diff --git a/interface/.env.development b/interface/.env.development index a5bcdb0..ce8e236 100644 --- a/interface/.env.development +++ b/interface/.env.development @@ -1 +1 @@ -REACT_APP_ENDPOINT_ROOT=http://192.168.0.11/rest/ +REACT_APP_ENDPOINT_ROOT=http://192.168.0.19/rest/ diff --git a/interface/src/AppRouting.js b/interface/src/AppRouting.js index 10670f1..2a85b10 100644 --- a/interface/src/AppRouting.js +++ b/interface/src/AppRouting.js @@ -2,18 +2,18 @@ import React, { Component } from 'react'; import { Redirect, Switch } from 'react-router'; +import { PROJECT_PATH } from './constants/Env'; import * as Authentication from './authentication/Authentication'; import AuthenticationWrapper from './authentication/AuthenticationWrapper'; import AuthenticatedRoute from './authentication/AuthenticatedRoute'; import UnauthenticatedRoute from './authentication/UnauthenticatedRoute'; - import SignInPage from './containers/SignInPage'; - import WiFiConnection from './sections/WiFiConnection'; import AccessPoint from './sections/AccessPoint'; import NetworkTime from './sections/NetworkTime'; import Security from './sections/Security'; import System from './sections/System'; +import ProjectRouting from './project/ProjectRouting'; class AppRouting extends Component { @@ -31,6 +31,7 @@ class AppRouting extends Component { + diff --git a/interface/src/authentication/Authentication.js b/interface/src/authentication/Authentication.js index eb3acdc..4d4d5d1 100644 --- a/interface/src/authentication/Authentication.js +++ b/interface/src/authentication/Authentication.js @@ -1,4 +1,5 @@ import history from '../history'; +import { PROJECT_PATH } from '../constants/Env'; export const ACCESS_TOKEN = 'access_token'; export const LOGIN_PATHNAME = 'loginPathname'; @@ -21,7 +22,7 @@ export function fetchLoginRedirect() { const loginSearch = localStorage.getItem(LOGIN_SEARCH); clearLoginRedirect(); return { - pathname: loginPathname || "/wifi/", + pathname: loginPathname || `/${PROJECT_PATH}/`, search: (loginPathname && loginSearch) || undefined }; } diff --git a/interface/src/components/MenuAppBar.js b/interface/src/components/MenuAppBar.js index f3f0f15..30b5288 100644 --- a/interface/src/components/MenuAppBar.js +++ b/interface/src/components/MenuAppBar.js @@ -30,7 +30,8 @@ import CardContent from '@material-ui/core/CardContent'; import CardActions from '@material-ui/core/CardActions'; 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'; const drawerWidth = 290; @@ -65,8 +66,7 @@ const styles = theme => ({ width: drawerWidth, }, content: { - flexGrow: 1, - padding: theme.spacing(), + flexGrow: 1 }, authMenu: { zIndex: theme.zIndex.tooltip, @@ -112,11 +112,13 @@ class MenuAppBar extends React.Component {
- {APP_NAME} + {PROJECT_NAME} + + diff --git a/interface/src/components/SectionContent.js b/interface/src/components/SectionContent.js index 71e82c0..f5a48ee 100644 --- a/interface/src/components/SectionContent.js +++ b/interface/src/components/SectionContent.js @@ -8,15 +8,15 @@ import Typography from '@material-ui/core/Typography'; const styles = theme => ({ content: { padding: theme.spacing(2), - margin: theme.spacing(2), + margin: theme.spacing(3), } }); function SectionContent(props) { - const { children, classes, title } = props; + const { children, classes, title, titleGutter } = props; return ( - + {title} {children} @@ -30,7 +30,8 @@ SectionContent.propTypes = { PropTypes.arrayOf(PropTypes.node), PropTypes.node ]).isRequired, - title: PropTypes.string.isRequired + title: PropTypes.string.isRequired, + titleGutter: PropTypes.bool }; export default withStyles(styles)(SectionContent); diff --git a/interface/src/constants/App.js b/interface/src/constants/App.js deleted file mode 100644 index da2a94d..0000000 --- a/interface/src/constants/App.js +++ /dev/null @@ -1 +0,0 @@ -export const APP_NAME = process.env.REACT_APP_NAME; diff --git a/interface/src/constants/Env.js b/interface/src/constants/Env.js new file mode 100644 index 0000000..d0b5ff5 --- /dev/null +++ b/interface/src/constants/Env.js @@ -0,0 +1,2 @@ +export const PROJECT_NAME = process.env.REACT_APP_PROJECT_NAME; +export const PROJECT_PATH = process.env.REACT_APP_PROJECT_PATH; diff --git a/interface/src/containers/APStatus.js b/interface/src/containers/APStatus.js index 95d3d64..afd019c 100644 --- a/interface/src/containers/APStatus.js +++ b/interface/src/containers/APStatus.js @@ -96,9 +96,7 @@ class APStatus extends Component { return (
- - {this.createListItems(data, classes)} - + {this.createListItems(data, classes)} +
+ : + children + : +
+ + + Loading... + +
+ } +
+ ); +} + +LoadingNotification.propTypes = { + fetched: PropTypes.bool.isRequired, + onReset: PropTypes.func.isRequired, + errorMessage: PropTypes.string +}; diff --git a/interface/src/components/RestComponent.js b/interface/src/components/RestComponent.js index 5fee544..d633761 100644 --- a/interface/src/components/RestComponent.js +++ b/interface/src/components/RestComponent.js @@ -1,6 +1,7 @@ import React from 'react'; import { withSnackbar } from 'notistack'; import { redirectingAuthorizedFetch } from '../authentication/Authentication'; + /* * It is unlikely this application will grow complex enough to require redux. * @@ -86,9 +87,9 @@ export const restComponent = (endpointUrl, FormComponent) => { }); } - handleValueChange = name => event => { + handleValueChange = name => (event, newValue) => { const { data } = this.state; - data[name] = event.target.value; + data[name] = newValue; this.setState({ data }); }; diff --git a/interface/src/containers/SecuritySettings.js b/interface/src/containers/SecuritySettings.js index f6adb11..0ceb890 100644 --- a/interface/src/containers/SecuritySettings.js +++ b/interface/src/containers/SecuritySettings.js @@ -12,16 +12,16 @@ class SecuritySettings extends Component { } render() { - const { data, fetched, errorMessage } = this.props; + const { data, fetched, errorMessage, saveData, loadData, handleValueChange } = this.props; return ( ) diff --git a/interface/src/project/DemoController.js b/interface/src/project/DemoController.js index ea25d31..4a711c5 100644 --- a/interface/src/project/DemoController.js +++ b/interface/src/project/DemoController.js @@ -1,22 +1,78 @@ import React, { Component } from 'react'; - -import { withStyles } from '@material-ui/core/styles'; import SectionContent from '../components/SectionContent'; +import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; -const styles = theme => ({ +import Button from '@material-ui/core/Button'; +import Typography from '@material-ui/core/Typography'; +import Slider from '@material-ui/core/Slider'; +import { makeStyles } from '@material-ui/core/styles'; +import { ValidatorForm } from 'react-material-ui-form-validator'; -}); +export const DEMO_SETTINGS_ENDPOINT = process.env.REACT_APP_ENDPOINT_ROOT + "demoSettings"; + +const valueToPercentage = (value) => `${Math.round(value / 255 * 100)}%`; class DemoController extends Component { - - render() { + componentDidMount() { + this.props.loadData(); + } + + render() { + const { data, fetched, errorMessage, saveData, loadData, handleValueChange } = this.props; return ( - TODO - This will contain a form which controls the speed of the built in LED. + + + ) } - } -export default withStyles(styles)(DemoController); +const useStyles = makeStyles(theme => ({ + button: { + marginRight: theme.spacing(2), + marginTop: theme.spacing(2), + }, + blinkSpeedLabel:{ + marginBottom: theme.spacing(5), + } +})); + +function DemoControllerForm(props) { + const { demoSettings, onSubmit, onReset, handleValueChange } = props; + const classes = useStyles(); + return ( + + + Blink Speed + + + + + + ); +} + +export default restComponent(DEMO_SETTINGS_ENDPOINT, DemoController); diff --git a/interface/src/project/DemoInformation.js b/interface/src/project/DemoInformation.js index 4f59bbf..6d7749e 100644 --- a/interface/src/project/DemoInformation.js +++ b/interface/src/project/DemoInformation.js @@ -7,6 +7,7 @@ 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 => ({ diff --git a/interface/src/project/ProjectMenu.js b/interface/src/project/ProjectMenu.js index 9a806b3..721c799 100644 --- a/interface/src/project/ProjectMenu.js +++ b/interface/src/project/ProjectMenu.js @@ -8,7 +8,6 @@ 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 { diff --git a/platformio.ini b/platformio.ini index 44ee3cf..2bb437d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,9 +7,10 @@ ; ; Please visit documentation for the other options and examples ; http://docs.platformio.org/page/projectconf.html -[env:node32s] -platform = espressif32 -board = node32s +[env:esp12e] +platform = espressif8266 +board = esp12e +board_build.f_cpu = 160000000L extra_scripts = pre:timelib_fix.py diff --git a/src/DemoProject.cpp b/src/DemoProject.cpp index e73a1fa..20fc953 100644 --- a/src/DemoProject.cpp +++ b/src/DemoProject.cpp @@ -1,9 +1,25 @@ #include -void DemoProject::begin() { - +void DemoProject::init(AsyncWebServer* server) { + AdminSettingsService::init(server); + pinMode(BLINK_LED, OUTPUT); } void DemoProject::loop() { - + unsigned delay = MAX_DELAY / 255 * (255 - _blinkSpeed); + unsigned long currentMillis = millis(); + if (!_lastBlink || (unsigned long)(currentMillis - _lastBlink) >= delay) { + _lastBlink = currentMillis; + digitalWrite(BLINK_LED, !digitalRead(BLINK_LED)); + } } + +void DemoProject::readFromJsonObject(JsonObject& root) { + _blinkSpeed = root["blink_speed"] | DEFAULT_BLINK_SPEED; +} + +void DemoProject::writeToJsonObject(JsonObject& root) { + // connection settings + root["blink_speed"] = _blinkSpeed; +} + diff --git a/src/DemoProject.h b/src/DemoProject.h index 81d0f47..7b85111 100644 --- a/src/DemoProject.h +++ b/src/DemoProject.h @@ -1,23 +1,35 @@ #ifndef DemoProject_h #define DemoProject_h -#include -#include +#include -class DemoProject { +#define BLINK_LED 2 +#define MAX_DELAY 1000 + +#define DEFAULT_BLINK_SPEED 100 +#define DEMO_SETTINGS_FILE "/config/demoSettings.json" +#define DEMO_SETTINGS_PATH "/rest/demoSettings" + +class DemoProject : public AdminSettingsService { public: - DemoProject(AsyncWebServer *server, SecurityManager* securityManager) : _server(server), _securityManager(securityManager) {} + DemoProject(FS* fs, SecurityManager* securityManager) : AdminSettingsService(fs, securityManager, DEMO_SETTINGS_PATH, DEMO_SETTINGS_FILE) {} + ~DemoProject() {} - void begin(); + void init(AsyncWebServer* server); void loop(); private: - AsyncWebServer* _server; - SecurityManager* _securityManager; + unsigned long _lastBlink = 0; + uint8_t _blinkSpeed = 255; + protected: + + void readFromJsonObject(JsonObject& root); + void writeToJsonObject(JsonObject& root); + }; #endif diff --git a/src/main.cpp b/src/main.cpp index ddddba7..cda4d75 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,9 +7,10 @@ AsyncWebServer server(80); ESP8266React espServer(&SPIFFS); -DemoProject demoProject = DemoProject(&server, espServer.getSecurityManager()); +DemoProject demoProject = DemoProject(&SPIFFS, espServer.getSecurityManager()); void setup() { + // start serial and filesystem Serial.begin(SERIAL_BAUD_RATE); SPIFFS.begin(); @@ -17,15 +18,16 @@ void setup() { espServer.init(&server); // begin the demo project - demoProject.begin(); + demoProject.init(&server); + // start the server server.begin(); } void loop() { - // run the framework loop + // run the framework's loop function espServer.loop(); - // run the demo project loop + // run the demo project's loop function demoProject.loop(); } From ff85c2e6617784a3479e9d4b6a3ec560622ad99c Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Fri, 9 Aug 2019 18:21:28 +0100 Subject: [PATCH 04/19] reduce use of ternaries in form code --- interface/src/components/RestComponent.js | 10 +- interface/src/containers/APSettings.js | 24 +- interface/src/containers/APStatus.js | 36 +-- interface/src/containers/ManageUsers.js | 26 +- interface/src/containers/NTPSettings.js | 28 +- interface/src/containers/NTPStatus.js | 38 +-- interface/src/containers/OTASettings.js | 30 ++- interface/src/containers/SecuritySettings.js | 18 +- interface/src/containers/SystemStatus.js | 38 +-- .../src/containers/WiFiNetworkScanner.js | 2 +- interface/src/containers/WiFiSettings.js | 38 +-- interface/src/containers/WiFiStatus.js | 40 +-- interface/src/forms/APSettingsForm.js | 130 +++------ interface/src/forms/ManageUsersForm.js | 174 +++++------- interface/src/forms/NTPSettingsForm.js | 103 +++---- interface/src/forms/OTASettingsForm.js | 124 +++------ interface/src/forms/SecuritySettingsForm.js | 76 ++---- interface/src/forms/WiFiSettingsForm.js | 251 ++++++++---------- 18 files changed, 456 insertions(+), 730 deletions(-) diff --git a/interface/src/components/RestComponent.js b/interface/src/components/RestComponent.js index d633761..5bcd8ec 100644 --- a/interface/src/components/RestComponent.js +++ b/interface/src/components/RestComponent.js @@ -52,10 +52,11 @@ export const restComponent = (endpointUrl, FormComponent) => { }) .then(json => { this.setState({ data: json, fetched: true }) }) .catch(error => { - this.props.enqueueSnackbar("Problem fetching: " + error.message, { + const errorMessage = error.message || "Unknown error"; + this.props.enqueueSnackbar("Problem fetching: " + errorMessage, { variant: 'error', }); - this.setState({ data: null, fetched: true, errorMessage: error.message }); + this.setState({ data: null, fetched: true, errorMessage }); }); } @@ -80,10 +81,11 @@ export const restComponent = (endpointUrl, FormComponent) => { }); this.setState({ data: json, fetched: true }); }).catch(error => { - this.props.enqueueSnackbar("Problem saving: " + error.message, { + const errorMessage = error.message || "Unknown error"; + this.props.enqueueSnackbar("Problem saving: " + errorMessage, { variant: 'error', }); - this.setState({ data: null, fetched: true, errorMessage: error.message }); + this.setState({ data: null, fetched: true, errorMessage }); }); } diff --git a/interface/src/containers/APSettings.js b/interface/src/containers/APSettings.js index 0ca9c53..3e8cab2 100644 --- a/interface/src/containers/APSettings.js +++ b/interface/src/containers/APSettings.js @@ -1,7 +1,8 @@ import React, { Component } from 'react'; -import { AP_SETTINGS_ENDPOINT } from '../constants/Endpoints'; +import { AP_SETTINGS_ENDPOINT } from '../constants/Endpoints'; import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent'; import APSettingsForm from '../forms/APSettingsForm'; @@ -12,17 +13,20 @@ class APSettings extends Component { } render() { - const { data, fetched, errorMessage } = this.props; + const { fetched, errorMessage, data, saveData, loadData, handleValueChange } = this.props; return ( - + + + ) } diff --git a/interface/src/containers/APStatus.js b/interface/src/containers/APStatus.js index afd019c..354a1da 100644 --- a/interface/src/containers/APStatus.js +++ b/interface/src/containers/APStatus.js @@ -2,8 +2,6 @@ import React, { Component, Fragment } from 'react'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; -import Typography from '@material-ui/core/Typography'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemText from '@material-ui/core/ListItemText'; @@ -15,6 +13,7 @@ import DeviceHubIcon from '@material-ui/icons/DeviceHub'; import ComputerIcon from '@material-ui/icons/Computer'; import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent' import * as Highlight from '../constants/Highlight'; @@ -27,10 +26,6 @@ const styles = theme => ({ ["apStatus_" + Highlight.IDLE]: { backgroundColor: theme.palette.highlight_idle }, - fetching: { - margin: theme.spacing(4), - textAlign: "center" - }, button: { marginRight: theme.spacing(2), marginTop: theme.spacing(2), @@ -106,30 +101,15 @@ class APStatus extends Component { } render() { - const { data, fetched, errorMessage, classes } = this.props; - + const { fetched, errorMessage, data, loadData, classes } = this.props; return ( - { - !fetched ? -
- - - Loading... - -
- : - data ? this.renderAPStatus(data, classes) - : -
- - {errorMessage} - - -
- } + + {this.renderAPStatus(data, classes)} +
) } diff --git a/interface/src/containers/ManageUsers.js b/interface/src/containers/ManageUsers.js index 478dcae..63727cd 100644 --- a/interface/src/containers/ManageUsers.js +++ b/interface/src/containers/ManageUsers.js @@ -2,8 +2,9 @@ import React, { Component } from 'react'; import { SECURITY_SETTINGS_ENDPOINT } from '../constants/Endpoints'; import { restComponent } from '../components/RestComponent'; -import ManageUsersForm from '../forms/ManageUsersForm'; +import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent'; +import ManageUsersForm from '../forms/ManageUsersForm'; class ManageUsers extends Component { @@ -12,18 +13,21 @@ class ManageUsers extends Component { } render() { - const { data, fetched, errorMessage } = this.props; + const { fetched, errorMessage, data, saveData, loadData, setData, handleValueChange } = this.props; return ( - + + + ) } diff --git a/interface/src/containers/NTPSettings.js b/interface/src/containers/NTPSettings.js index 2e291a9..2b903a8 100644 --- a/interface/src/containers/NTPSettings.js +++ b/interface/src/containers/NTPSettings.js @@ -1,28 +1,32 @@ import React, { Component } from 'react'; -import { NTP_SETTINGS_ENDPOINT } from '../constants/Endpoints'; -import {restComponent} from '../components/RestComponent'; +import { NTP_SETTINGS_ENDPOINT } from '../constants/Endpoints'; +import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent'; import NTPSettingsForm from '../forms/NTPSettingsForm'; class NTPSettings extends Component { componentDidMount() { - this.props.loadData(); + this.props.loadData(); } render() { - const { data, fetched, errorMessage } = this.props; + const { fetched, errorMessage, data, saveData, loadData, handleValueChange } = this.props; return ( - + + + ) } diff --git a/interface/src/containers/NTPStatus.js b/interface/src/containers/NTPStatus.js index a9b5270..195f5fa 100644 --- a/interface/src/containers/NTPStatus.js +++ b/interface/src/containers/NTPStatus.js @@ -2,8 +2,6 @@ import React, { Component, Fragment } from 'react'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; -import Typography from '@material-ui/core/Typography'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemAvatar from '@material-ui/core/ListItemAvatar'; @@ -22,6 +20,7 @@ import * as Highlight from '../constants/Highlight'; import { unixTimeToTimeAndDate } from '../constants/TimeFormat'; import { NTP_STATUS_ENDPOINT } from '../constants/Endpoints'; import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent'; import moment from 'moment'; @@ -36,10 +35,6 @@ const styles = theme => ({ ["ntpStatus_" + Highlight.WARN]: { backgroundColor: theme.palette.highlight_warn }, - fetching: { - margin: theme.spacing(4), - textAlign: "center" - }, button: { marginRight: theme.spacing(2), marginTop: theme.spacing(2), @@ -131,32 +126,17 @@ class NTPStatus extends Component { } render() { - const { data, fetched, errorMessage, classes } = this.props; - + const { data, fetched, errorMessage, loadData, classes } = this.props; return ( - { - !fetched ? -
- - - Loading... - -
- : - data ? this.renderNTPStatus(data, classes) - : -
- - {errorMessage} - - -
- } + + {this.renderNTPStatus(data, classes)} +
- ) + ); } } diff --git a/interface/src/containers/OTASettings.js b/interface/src/containers/OTASettings.js index 95be458..189e620 100644 --- a/interface/src/containers/OTASettings.js +++ b/interface/src/containers/OTASettings.js @@ -1,29 +1,33 @@ import React, { Component } from 'react'; -import { OTA_SETTINGS_ENDPOINT } from '../constants/Endpoints'; -import {restComponent} from '../components/RestComponent'; +import { OTA_SETTINGS_ENDPOINT } from '../constants/Endpoints'; +import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent'; import OTASettingsForm from '../forms/OTASettingsForm'; class OTASettings extends Component { componentDidMount() { - this.props.loadData(); + this.props.loadData(); } render() { - const { data, fetched, errorMessage } = this.props; + const { fetched, errorMessage, data, saveData, loadData, handleValueChange, handleCheckboxChange } = this.props; return ( - + + + ) } diff --git a/interface/src/containers/SecuritySettings.js b/interface/src/containers/SecuritySettings.js index 0ceb890..e1c70a6 100644 --- a/interface/src/containers/SecuritySettings.js +++ b/interface/src/containers/SecuritySettings.js @@ -2,6 +2,7 @@ import React, { Component } from 'react'; import { SECURITY_SETTINGS_ENDPOINT } from '../constants/Endpoints'; import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; import SecuritySettingsForm from '../forms/SecuritySettingsForm'; import SectionContent from '../components/SectionContent'; @@ -15,14 +16,17 @@ class SecuritySettings extends Component { const { data, fetched, errorMessage, saveData, loadData, handleValueChange } = this.props; return ( - + fetched={fetched} + errorMessage={errorMessage}> + + ) } diff --git a/interface/src/containers/SystemStatus.js b/interface/src/containers/SystemStatus.js index 20728f5..b9c1410 100644 --- a/interface/src/containers/SystemStatus.js +++ b/interface/src/containers/SystemStatus.js @@ -2,8 +2,6 @@ import React, { Component, Fragment } from 'react'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; -import Typography from '@material-ui/core/Typography'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemAvatar from '@material-ui/core/ListItemAvatar'; @@ -16,16 +14,12 @@ import ShowChartIcon from '@material-ui/icons/ShowChart'; import SdStorageIcon from '@material-ui/icons/SdStorage'; import DataUsageIcon from '@material-ui/icons/DataUsage'; - import { SYSTEM_STATUS_ENDPOINT } from '../constants/Endpoints'; import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent'; const styles = theme => ({ - fetching: { - margin: theme.spacing(4), - textAlign: "center" - }, button: { marginRight: theme.spacing(2), marginTop: theme.spacing(2), @@ -85,7 +79,7 @@ class SystemStatus extends Component { - + ); } @@ -104,29 +98,15 @@ class SystemStatus extends Component { } render() { - const { data, fetched, errorMessage, classes } = this.props; + const { data, fetched, errorMessage, loadData, classes } = this.props; return ( - { - !fetched ? -
- - - Loading... - -
- : - data ? this.renderNTPStatus(data, classes) - : -
- - {errorMessage} - - -
- } + + {this.renderNTPStatus(data, classes)} +
) } diff --git a/interface/src/containers/WiFiNetworkScanner.js b/interface/src/containers/WiFiNetworkScanner.js index 4b3d126..4cdb9be 100644 --- a/interface/src/containers/WiFiNetworkScanner.js +++ b/interface/src/containers/WiFiNetworkScanner.js @@ -1,10 +1,10 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { withSnackbar } from 'notistack'; import { SCAN_NETWORKS_ENDPOINT, LIST_NETWORKS_ENDPOINT } from '../constants/Endpoints'; import SectionContent from '../components/SectionContent'; import WiFiNetworkSelector from '../forms/WiFiNetworkSelector'; -import { withSnackbar } from 'notistack'; import { redirectingAuthorizedFetch } from '../authentication/Authentication'; const NUM_POLLS = 10 diff --git a/interface/src/containers/WiFiSettings.js b/interface/src/containers/WiFiSettings.js index 17f913c..fb0bfb0 100644 --- a/interface/src/containers/WiFiSettings.js +++ b/interface/src/containers/WiFiSettings.js @@ -1,8 +1,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { WIFI_SETTINGS_ENDPOINT } from '../constants/Endpoints'; +import { WIFI_SETTINGS_ENDPOINT } from '../constants/Endpoints'; import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent'; import WiFiSettingsForm from '../forms/WiFiSettingsForm'; @@ -18,10 +19,10 @@ class WiFiSettings extends Component { const { selectedNetwork } = this.props; if (selectedNetwork) { var wifiSettings = { - ssid:selectedNetwork.ssid, - password:"", - hostname:"esp8266-react", - static_ip_config:false, + ssid: selectedNetwork.ssid, + password: "", + hostname: "esp8266-react", + static_ip_config: false, } this.props.setData(wifiSettings); } else { @@ -35,20 +36,23 @@ class WiFiSettings extends Component { } render() { - const { data, fetched, errorMessage, selectedNetwork } = this.props; + const { data, fetched, errorMessage, saveData, loadData, handleValueChange, handleCheckboxChange, selectedNetwork, deselectNetwork } = this.props; return ( - + + + ) } diff --git a/interface/src/containers/WiFiStatus.js b/interface/src/containers/WiFiStatus.js index 773e958..4c47f2c 100644 --- a/interface/src/containers/WiFiStatus.js +++ b/interface/src/containers/WiFiStatus.js @@ -2,14 +2,10 @@ import React, { Component, Fragment } from 'react'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; -import Typography from '@material-ui/core/Typography'; - import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemText from '@material-ui/core/ListItemText'; import ListItemAvatar from '@material-ui/core/ListItemAvatar'; - import Avatar from '@material-ui/core/Avatar'; import Divider from '@material-ui/core/Divider'; import WifiIcon from '@material-ui/icons/Wifi'; @@ -23,6 +19,7 @@ import { WIFI_STATUS_ENDPOINT } from '../constants/Endpoints'; import { isConnected, connectionStatus, connectionStatusHighlight } from '../constants/WiFiConnectionStatus'; import * as Highlight from '../constants/Highlight'; import { restComponent } from '../components/RestComponent'; +import LoadingNotification from '../components/LoadingNotification'; const styles = theme => ({ ["wifiStatus_" + Highlight.IDLE]: { @@ -37,10 +34,6 @@ const styles = theme => ({ ["wifiStatus_" + Highlight.WARN]: { backgroundColor: theme.palette.highlight_warn }, - fetching: { - margin: theme.spacing(4), - textAlign: "center" - }, button: { marginRight: theme.spacing(2), marginTop: theme.spacing(2), @@ -145,32 +138,19 @@ class WiFiStatus extends Component { } render() { - const { data, fetched, errorMessage, classes } = this.props; + const { data, fetched, errorMessage, loadData, classes } = this.props; return ( - { - !fetched ? -
- - - Loading... - -
- : - data ? this.renderWiFiStatus(data, classes) - : -
- - {errorMessage} - - -
- } + + {this.renderWiFiStatus(data, classes)} +
- ) + ); } + } export default restComponent(WIFI_STATUS_ENDPOINT, withStyles(styles)(WiFiStatus)); diff --git a/interface/src/forms/APSettingsForm.js b/interface/src/forms/APSettingsForm.js index bdd9191..e708884 100644 --- a/interface/src/forms/APSettingsForm.js +++ b/interface/src/forms/APSettingsForm.js @@ -1,29 +1,19 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; +import { TextValidator, ValidatorForm, SelectValidator } from 'react-material-ui-form-validator'; + +import { isAPEnabled } from '../constants/WiFiAPModes'; +import PasswordValidator from '../components/PasswordValidator'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; -import Typography from '@material-ui/core/Typography'; import MenuItem from '@material-ui/core/MenuItem'; -import { TextValidator, ValidatorForm, SelectValidator } from 'react-material-ui-form-validator'; - -import {isAPEnabled} from '../constants/WiFiAPModes'; -import PasswordValidator from '../components/PasswordValidator'; - const styles = theme => ({ - loadingSettings: { - margin: theme.spacing(0.5), - }, - loadingSettingsDetails: { - margin: theme.spacing(4), - textAlign: "center" - }, textField: { width: "100%" }, - selectField:{ + selectField: { width: "100%", marginTop: theme.spacing(2), marginBottom: theme.spacing(0.5) @@ -37,86 +27,54 @@ const styles = theme => ({ class APSettingsForm extends React.Component { render() { - const { classes, apSettingsFetched, apSettings, errorMessage, handleValueChange, onSubmit, onReset } = this.props; + const { classes, apSettings, handleValueChange, onSubmit, onReset } = this.props; return ( -
+ + + Always + When WiFi Disconnected + Never + { - !apSettingsFetched ? - -
- - - Loading... - -
- - : apSettings ? - - - - - Always - When WiFi Disconnected - Never - - - { - isAPEnabled(apSettings.provision_mode) && - - - - - } - - - - - - - : - -
- - {errorMessage} - - -
- } -
+ isAPEnabled(apSettings.provision_mode) && + + + + + } + + + ); } } APSettingsForm.propTypes = { classes: PropTypes.object.isRequired, - apSettingsFetched: PropTypes.bool.isRequired, apSettings: PropTypes.object, - errorMessage: PropTypes.string, onSubmit: PropTypes.func.isRequired, onReset: PropTypes.func.isRequired, handleValueChange: PropTypes.func.isRequired diff --git a/interface/src/forms/ManageUsersForm.js b/interface/src/forms/ManageUsersForm.js index c2e2768..bdae121 100644 --- a/interface/src/forms/ManageUsersForm.js +++ b/interface/src/forms/ManageUsersForm.js @@ -5,7 +5,6 @@ import { ValidatorForm } from 'react-material-ui-form-validator'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; import Typography from '@material-ui/core/Typography'; import Table from '@material-ui/core/Table'; import TableBody from '@material-ui/core/TableBody'; @@ -14,7 +13,6 @@ import TableFooter from '@material-ui/core/TableFooter'; import TableHead from '@material-ui/core/TableHead'; import TableRow from '@material-ui/core/TableRow'; import Box from '@material-ui/core/Box'; - import EditIcon from '@material-ui/icons/Edit'; import DeleteIcon from '@material-ui/icons/Delete'; import CloseIcon from '@material-ui/icons/Close'; @@ -25,22 +23,12 @@ import UserForm from './UserForm'; import { withAuthenticationContext } from '../authentication/Context'; const styles = theme => ({ - loadingSettings: { - margin: theme.spacing(0.5), - }, - loadingSettingsDetails: { - margin: theme.spacing(4), - textAlign: "center" - }, button: { marginRight: theme.spacing(2), marginTop: theme.spacing(2), }, table: { '& td, & th': { padding: theme.spacing(0.5) } - }, - actions: { - whiteSpace: "nowrap" } }); @@ -134,98 +122,80 @@ class ManageUsersForm extends React.Component { } render() { - const { classes, userData, userDataFetched, errorMessage, onReset } = this.props; + const { classes, userData, onReset } = this.props; const { user, creating } = this.state; return ( - !userDataFetched ? -
- - - Loading... - -
- : - userData ? - - - - - - Username - Admin? - - - - - {userData.users.sort(compareUsers).map(user => ( - - - {user.username} - - - { - user.admin ? : - } - - - this.removeUser(user)}> - - - this.startEditingUser(user)}> - - - - - ))} - - - - - - - - - -
- { - this.noAdminConfigured() && - - - You must have at least one admin user configured. - - - } - - -
- { - user && - - } -
- : -
- - {errorMessage} + + + + + + Username + Admin? + + + + + {userData.users.sort(compareUsers).map(user => ( + + + {user.username} + + + { + user.admin ? : + } + + + this.removeUser(user)}> + + + this.startEditingUser(user)}> + + + + + ))} + + + + + + + + + +
+ { + this.noAdminConfigured() && + + + You must have at least one admin user configured. + - -
+ } + + + + { + user && + + } + ); } @@ -234,8 +204,6 @@ class ManageUsersForm extends React.Component { ManageUsersForm.propTypes = { classes: PropTypes.object.isRequired, userData: PropTypes.object, - userDataFetched: PropTypes.bool.isRequired, - errorMessage: PropTypes.string, onSubmit: PropTypes.func.isRequired, onReset: PropTypes.func.isRequired, setData: PropTypes.func.isRequired, diff --git a/interface/src/forms/NTPSettingsForm.js b/interface/src/forms/NTPSettingsForm.js index ba89b9c..8214825 100644 --- a/interface/src/forms/NTPSettingsForm.js +++ b/interface/src/forms/NTPSettingsForm.js @@ -1,24 +1,15 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; -import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator'; -import Typography from '@material-ui/core/Typography'; import isIP from '../validators/isIP'; import isHostname from '../validators/isHostname'; import or from '../validators/or'; const styles = theme => ({ - loadingSettings: { - margin: theme.spacing(0.5), - }, - loadingSettingsDetails: { - margin: theme.spacing(4), - textAlign: "center" - }, textField: { width: "100%" }, @@ -35,76 +26,44 @@ class NTPSettingsForm extends React.Component { } render() { - const { classes, ntpSettingsFetched, ntpSettings, errorMessage, handleValueChange, onSubmit, onReset } = this.props; + const { classes, ntpSettings, handleValueChange, onSubmit, onReset } = this.props; return ( -
- { - !ntpSettingsFetched ? - -
- - - Loading... - -
- - : ntpSettings ? - - - - - - - - - - - - - : - -
- - {errorMessage} - - -
- } -
+ + + + + + ); } } NTPSettingsForm.propTypes = { classes: PropTypes.object.isRequired, - ntpSettingsFetched: PropTypes.bool.isRequired, ntpSettings: PropTypes.object, - errorMessage: PropTypes.string, onSubmit: PropTypes.func.isRequired, onReset: PropTypes.func.isRequired, handleValueChange: PropTypes.func.isRequired, diff --git a/interface/src/forms/OTASettingsForm.js b/interface/src/forms/OTASettingsForm.js index 31bb411..29ee5b8 100644 --- a/interface/src/forms/OTASettingsForm.js +++ b/interface/src/forms/OTASettingsForm.js @@ -4,9 +4,7 @@ import PropTypes from 'prop-types'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; import Switch from '@material-ui/core/Switch'; -import LinearProgress from '@material-ui/core/LinearProgress'; import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator'; -import Typography from '@material-ui/core/Typography'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import isIP from '../validators/isIP'; @@ -15,13 +13,6 @@ import or from '../validators/or'; import PasswordValidator from '../components/PasswordValidator'; const styles = theme => ({ - loadingSettings: { - margin: theme.spacing(0.5), - }, - loadingSettingsDetails: { - margin: theme.spacing(4), - textAlign: "center" - }, switchControl: { width: "100%", marginTop: theme.spacing(2), @@ -43,88 +34,55 @@ class OTASettingsForm extends React.Component { } render() { - const { classes, otaSettingsFetched, otaSettings, errorMessage, handleValueChange, handleCheckboxChange, onSubmit, onReset } = this.props; + const { classes, otaSettings, handleValueChange, handleCheckboxChange, onSubmit, onReset } = this.props; return ( -
- { - !otaSettingsFetched ? - -
- - - Loading... - -
- - : otaSettings ? - - - - - } - label="Enable OTA Updates?" - /> - - - - - - - - - - - : - -
- - {errorMessage} - - -
- } -
+ + + } + label="Enable OTA Updates?" + /> + + + + + ); } } OTASettingsForm.propTypes = { classes: PropTypes.object.isRequired, - otaSettingsFetched: PropTypes.bool.isRequired, otaSettings: PropTypes.object, - errorMessage: PropTypes.string, onSubmit: PropTypes.func.isRequired, onReset: PropTypes.func.isRequired, handleValueChange: PropTypes.func.isRequired, diff --git a/interface/src/forms/SecuritySettingsForm.js b/interface/src/forms/SecuritySettingsForm.js index 00a339c..16d74a3 100644 --- a/interface/src/forms/SecuritySettingsForm.js +++ b/interface/src/forms/SecuritySettingsForm.js @@ -4,7 +4,6 @@ import { ValidatorForm } from 'react-material-ui-form-validator'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; import Typography from '@material-ui/core/Typography'; import Box from '@material-ui/core/Box'; @@ -12,13 +11,6 @@ import PasswordValidator from '../components/PasswordValidator'; import { withAuthenticationContext } from '../authentication/Context'; const styles = theme => ({ - loadingSettings: { - margin: theme.spacing(0.5), - }, - loadingSettingsDetails: { - margin: theme.spacing(4), - textAlign: "center" - }, textField: { width: "100%" }, @@ -36,58 +28,38 @@ class SecuritySettingsForm extends React.Component { } render() { - const { classes, securitySettingsFetched, securitySettings, errorMessage, handleValueChange, onReset } = this.props; + const { classes, securitySettings, handleValueChange, onReset } = this.props; return ( - !securitySettingsFetched ? -
- - - Loading... - -
- : - securitySettings ? - - - - - If you modify the JWT Secret, all users will be logged out. - - - - - - : -
- - {errorMessage} - - -
+ + + + + If you modify the JWT Secret, all users will be logged out. + + + + + ); } } SecuritySettingsForm.propTypes = { classes: PropTypes.object.isRequired, - securitySettingsFetched: PropTypes.bool.isRequired, securitySettings: PropTypes.object, - errorMessage: PropTypes.string, onSubmit: PropTypes.func.isRequired, onReset: PropTypes.func.isRequired, handleValueChange: PropTypes.func.isRequired, diff --git a/interface/src/forms/WiFiSettingsForm.js b/interface/src/forms/WiFiSettingsForm.js index fd7b453..b59ddda 100644 --- a/interface/src/forms/WiFiSettingsForm.js +++ b/interface/src/forms/WiFiSettingsForm.js @@ -3,10 +3,8 @@ import PropTypes from 'prop-types'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; -import LinearProgress from '@material-ui/core/LinearProgress'; import Checkbox from '@material-ui/core/Checkbox'; import FormControlLabel from '@material-ui/core/FormControlLabel'; -import Typography from '@material-ui/core/Typography'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemText from '@material-ui/core/ListItemText'; @@ -80,157 +78,124 @@ class WiFiSettingsForm extends React.Component { } render() { - const { classes, wifiSettingsFetched, wifiSettings, errorMessage, selectedNetwork, handleValueChange, handleCheckboxChange, onSubmit, onReset } = this.props; + const { classes, wifiSettings, selectedNetwork, handleValueChange, handleCheckboxChange, onSubmit, onReset } = this.props; return ( -
+ { - !wifiSettingsFetched ? - -
- - - Loading... - -
- - : wifiSettings ? - - - { - selectedNetwork ? this.renderSelectedNetwork() : - - } - { - !isNetworkOpen(selectedNetwork) && - - } - - - - - } - label="Static IP Config?" - /> - - { - wifiSettings.static_ip_config && - - - - - - - - } - - - - - - - : - -
- - {errorMessage} - - -
+ selectedNetwork ? this.renderSelectedNetwork() : + } -
+ { + !isNetworkOpen(selectedNetwork) && + + } + + + } + label="Static IP Config?" + /> + { + wifiSettings.static_ip_config && + + + + + + + + } + + + ); } } WiFiSettingsForm.propTypes = { classes: PropTypes.object.isRequired, - wifiSettingsFetched: PropTypes.bool.isRequired, wifiSettings: PropTypes.object, - errorMessage: PropTypes.string, deselectNetwork: PropTypes.func, selectedNetwork: PropTypes.object, onSubmit: PropTypes.func.isRequired, From ef8061cbc32aab6fef8d839d62bdbfe6fdad781d Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Fri, 9 Aug 2019 18:55:11 +0100 Subject: [PATCH 05/19] use render callbacks for loading notification --- .../src/components/LoadingNotification.js | 7 +++--- interface/src/containers/APSettings.js | 18 +++++++------- interface/src/containers/APStatus.js | 8 ++++--- interface/src/containers/ManageUsers.js | 20 +++++++++------- interface/src/containers/NTPSettings.js | 18 +++++++------- interface/src/containers/NTPStatus.js | 8 ++++--- interface/src/containers/OTASettings.js | 20 +++++++++------- interface/src/containers/SecuritySettings.js | 18 +++++++------- interface/src/containers/SystemStatus.js | 10 ++++---- interface/src/containers/WiFiSettings.js | 24 ++++++++++--------- interface/src/containers/WiFiStatus.js | 8 ++++--- interface/src/project/DemoController.js | 24 ++++++++++--------- 12 files changed, 103 insertions(+), 80 deletions(-) diff --git a/interface/src/components/LoadingNotification.js b/interface/src/components/LoadingNotification.js index 5765412..db1cd31 100644 --- a/interface/src/components/LoadingNotification.js +++ b/interface/src/components/LoadingNotification.js @@ -22,7 +22,7 @@ const useStyles = makeStyles(theme => ({ export default function LoadingNotification(props) { const classes = useStyles(); - const { fetched, errorMessage, onReset, children } = props; + const { fetched, errorMessage, onReset, render } = props; return (
{ @@ -37,7 +37,7 @@ export default function LoadingNotification(props) {
: - children + render() :
@@ -53,5 +53,6 @@ export default function LoadingNotification(props) { LoadingNotification.propTypes = { fetched: PropTypes.bool.isRequired, onReset: PropTypes.func.isRequired, - errorMessage: PropTypes.string + errorMessage: PropTypes.string, + render: PropTypes.func.isRequired }; diff --git a/interface/src/containers/APSettings.js b/interface/src/containers/APSettings.js index 3e8cab2..45ae270 100644 --- a/interface/src/containers/APSettings.js +++ b/interface/src/containers/APSettings.js @@ -19,14 +19,16 @@ class APSettings extends Component { - - + errorMessage={errorMessage} + render={() => + + } + /> ) } diff --git a/interface/src/containers/APStatus.js b/interface/src/containers/APStatus.js index 354a1da..eadaf9b 100644 --- a/interface/src/containers/APStatus.js +++ b/interface/src/containers/APStatus.js @@ -107,9 +107,11 @@ class APStatus extends Component { - {this.renderAPStatus(data, classes)} - + errorMessage={errorMessage} + render={ + () => this.renderAPStatus(data, classes) + } + /> ) } diff --git a/interface/src/containers/ManageUsers.js b/interface/src/containers/ManageUsers.js index 63727cd..6b91556 100644 --- a/interface/src/containers/ManageUsers.js +++ b/interface/src/containers/ManageUsers.js @@ -19,15 +19,17 @@ class ManageUsers extends Component { - - + errorMessage={errorMessage} + render={() => + + } + /> ) } diff --git a/interface/src/containers/NTPSettings.js b/interface/src/containers/NTPSettings.js index 2b903a8..9393545 100644 --- a/interface/src/containers/NTPSettings.js +++ b/interface/src/containers/NTPSettings.js @@ -19,14 +19,16 @@ class NTPSettings extends Component { - - + errorMessage={errorMessage} + render={() => + + } + /> ) } diff --git a/interface/src/containers/NTPStatus.js b/interface/src/containers/NTPStatus.js index 195f5fa..f58e467 100644 --- a/interface/src/containers/NTPStatus.js +++ b/interface/src/containers/NTPStatus.js @@ -132,9 +132,11 @@ class NTPStatus extends Component { - {this.renderNTPStatus(data, classes)} - + errorMessage={errorMessage} + render={ + () => this.renderNTPStatus(data, classes) + } + /> ); } diff --git a/interface/src/containers/OTASettings.js b/interface/src/containers/OTASettings.js index 189e620..46fd4ec 100644 --- a/interface/src/containers/OTASettings.js +++ b/interface/src/containers/OTASettings.js @@ -19,15 +19,17 @@ class OTASettings extends Component { - - + errorMessage={errorMessage} + render={() => + + } + /> ) } diff --git a/interface/src/containers/SecuritySettings.js b/interface/src/containers/SecuritySettings.js index e1c70a6..9ee2c55 100644 --- a/interface/src/containers/SecuritySettings.js +++ b/interface/src/containers/SecuritySettings.js @@ -19,14 +19,16 @@ class SecuritySettings extends Component { - - + errorMessage={errorMessage} + render={() => + + } + /> ) } diff --git a/interface/src/containers/SystemStatus.js b/interface/src/containers/SystemStatus.js index b9c1410..560c936 100644 --- a/interface/src/containers/SystemStatus.js +++ b/interface/src/containers/SystemStatus.js @@ -84,7 +84,7 @@ class SystemStatus extends Component { ); } - renderNTPStatus(data, classes) { + renderSystemStatus(data, classes) { return (
@@ -104,9 +104,11 @@ class SystemStatus extends Component { - {this.renderNTPStatus(data, classes)} - + errorMessage={errorMessage} + render={ + () => this.renderSystemStatus(data, classes) + } + /> ) } diff --git a/interface/src/containers/WiFiSettings.js b/interface/src/containers/WiFiSettings.js index fb0bfb0..9c0802d 100644 --- a/interface/src/containers/WiFiSettings.js +++ b/interface/src/containers/WiFiSettings.js @@ -42,17 +42,19 @@ class WiFiSettings extends Component { - - + errorMessage={errorMessage} + render={() => + + } + /> ) } diff --git a/interface/src/containers/WiFiStatus.js b/interface/src/containers/WiFiStatus.js index 4c47f2c..43724d9 100644 --- a/interface/src/containers/WiFiStatus.js +++ b/interface/src/containers/WiFiStatus.js @@ -144,9 +144,11 @@ class WiFiStatus extends Component { - {this.renderWiFiStatus(data, classes)} - + errorMessage={errorMessage} + render={ + () => this.renderWiFiStatus(data, classes) + } + /> ); } diff --git a/interface/src/project/DemoController.js b/interface/src/project/DemoController.js index 4a711c5..4eb3579 100644 --- a/interface/src/project/DemoController.js +++ b/interface/src/project/DemoController.js @@ -17,7 +17,7 @@ class DemoController extends Component { componentDidMount() { this.props.loadData(); } - + render() { const { data, fetched, errorMessage, saveData, loadData, handleValueChange } = this.props; return ( @@ -25,14 +25,16 @@ class DemoController extends Component { - - + errorMessage={errorMessage} + render={() => + + } + /> ) } @@ -43,11 +45,11 @@ const useStyles = makeStyles(theme => ({ marginRight: theme.spacing(2), marginTop: theme.spacing(2), }, - blinkSpeedLabel:{ + blinkSpeedLabel: { marginBottom: theme.spacing(5), } })); - + function DemoControllerForm(props) { const { demoSettings, onSubmit, onReset, handleValueChange } = props; const classes = useStyles(); From 2a8599d8555bd068f68ee82c0bb0d946db599639 Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Fri, 9 Aug 2019 18:59:45 +0100 Subject: [PATCH 06/19] remove unused styles missed in main refactor --- interface/src/forms/WiFiSettingsForm.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/interface/src/forms/WiFiSettingsForm.js b/interface/src/forms/WiFiSettingsForm.js index b59ddda..eb365ae 100644 --- a/interface/src/forms/WiFiSettingsForm.js +++ b/interface/src/forms/WiFiSettingsForm.js @@ -26,13 +26,6 @@ import optional from '../validators/optional'; import PasswordValidator from '../components/PasswordValidator'; const styles = theme => ({ - loadingSettings: { - margin: theme.spacing(0.5), - }, - loadingSettingsDetails: { - margin: theme.spacing(4), - textAlign: "center" - }, textField: { width: "100%" }, From 5069cd90a11be2764497583c8cd95144837d723c Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Fri, 9 Aug 2019 20:33:15 +0100 Subject: [PATCH 07/19] Add ENDPOINT_ROOT to Env constants, replace usages. --- interface/src/constants/Endpoints.js | 2 +- interface/src/constants/Env.js | 1 + interface/src/project/DemoController.js | 6 ++++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/constants/Endpoints.js b/interface/src/constants/Endpoints.js index e253c16..5474bdf 100644 --- a/interface/src/constants/Endpoints.js +++ b/interface/src/constants/Endpoints.js @@ -1,4 +1,4 @@ -const ENDPOINT_ROOT = process.env.REACT_APP_ENDPOINT_ROOT; +import { ENDPOINT_ROOT } from '../constants/Env'; export const NTP_STATUS_ENDPOINT = ENDPOINT_ROOT + "ntpStatus"; export const NTP_SETTINGS_ENDPOINT = ENDPOINT_ROOT + "ntpSettings"; diff --git a/interface/src/constants/Env.js b/interface/src/constants/Env.js index d0b5ff5..df674aa 100644 --- a/interface/src/constants/Env.js +++ b/interface/src/constants/Env.js @@ -1,2 +1,3 @@ export const PROJECT_NAME = process.env.REACT_APP_PROJECT_NAME; export const PROJECT_PATH = process.env.REACT_APP_PROJECT_PATH; +export const ENDPOINT_ROOT = process.env.REACT_APP_ENDPOINT_ROOT; diff --git a/interface/src/project/DemoController.js b/interface/src/project/DemoController.js index 4eb3579..3ebd2f3 100644 --- a/interface/src/project/DemoController.js +++ b/interface/src/project/DemoController.js @@ -1,4 +1,7 @@ import React, { Component } from 'react'; +import { ValidatorForm } from 'react-material-ui-form-validator'; + +import { ENDPOINT_ROOT } from '../constants/Env'; import SectionContent from '../components/SectionContent'; import { restComponent } from '../components/RestComponent'; import LoadingNotification from '../components/LoadingNotification'; @@ -7,9 +10,8 @@ import Button from '@material-ui/core/Button'; import Typography from '@material-ui/core/Typography'; import Slider from '@material-ui/core/Slider'; import { makeStyles } from '@material-ui/core/styles'; -import { ValidatorForm } from 'react-material-ui-form-validator'; -export const DEMO_SETTINGS_ENDPOINT = process.env.REACT_APP_ENDPOINT_ROOT + "demoSettings"; +export const DEMO_SETTINGS_ENDPOINT = ENDPOINT_ROOT + "demoSettings"; const valueToPercentage = (value) => `${Math.round(value / 255 * 100)}%`; From 391fe85a4bbd1b5b0bc397a4d10fbe168d0e9f3c Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Fri, 9 Aug 2019 20:36:18 +0100 Subject: [PATCH 08/19] comment out CORS setting --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 2bb437d..c06a090 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,7 +26,7 @@ monitor_speed = 115200 build_flags= -D NO_GLOBAL_ARDUINOOTA ; Uncomment ENABLE_CORS to enable Cross-Origin Resource Sharing (required for local React development) - -D ENABLE_CORS + ;-D ENABLE_CORS -D CORS_ORIGIN=\"http://localhost:3000\" lib_deps = NtpClientLib@>=2.5.1,<3.0.0 From cf48c79b4d34088f53e2a9b0c37dd48db5fc5c9d Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Fri, 9 Aug 2019 21:26:31 +0100 Subject: [PATCH 09/19] fix bug introduced in value change code --- interface/src/components/RestComponent.js | 9 ++++++++- interface/src/project/DemoController.js | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/interface/src/components/RestComponent.js b/interface/src/components/RestComponent.js index 5bcd8ec..813840a 100644 --- a/interface/src/components/RestComponent.js +++ b/interface/src/components/RestComponent.js @@ -89,7 +89,13 @@ export const restComponent = (endpointUrl, FormComponent) => { }); } - handleValueChange = name => (event, newValue) => { + handleValueChange = name => (event) => { + const { data } = this.state; + data[name] = event.target.value; + this.setState({ data }); + }; + + handleSliderChange = name => (event, newValue) => { const { data } = this.state; data[name] = newValue; this.setState({ data }); @@ -105,6 +111,7 @@ export const restComponent = (endpointUrl, FormComponent) => { return } /> @@ -53,7 +53,7 @@ const useStyles = makeStyles(theme => ({ })); function DemoControllerForm(props) { - const { demoSettings, onSubmit, onReset, handleValueChange } = props; + const { demoSettings, onSubmit, onReset, handleSliderChange } = props; const classes = useStyles(); return ( @@ -67,7 +67,7 @@ function DemoControllerForm(props) { valueLabelDisplay="on" min={0} max={255} - onChange={handleValueChange('blink_speed')} + onChange={handleSliderChange('blink_speed')} />