reduce use of ternaries in form code
This commit is contained in:
		| @@ -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  }); | ||||
|           }); | ||||
|       } | ||||
|  | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="AP Settings"> | ||||
|       	<APSettingsForm           | ||||
|           apSettings={data} | ||||
|           apSettingsFetched={fetched} | ||||
|           errorMessage={errorMessage} | ||||
|           onSubmit={this.props.saveData} | ||||
|           onReset={this.props.loadData} | ||||
|           handleValueChange={this.props.handleValueChange} | ||||
|         /> | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           <APSettingsForm | ||||
|             apSettings={data} | ||||
|             onSubmit={saveData} | ||||
|             onReset={loadData} | ||||
|             handleValueChange={handleValueChange} | ||||
|           /> | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="AP Status"> | ||||
|         { | ||||
|           !fetched ? | ||||
|             <div> | ||||
|               <LinearProgress className={classes.fetching} /> | ||||
|               <Typography variant="h4" className={classes.fetching}> | ||||
|                 Loading... | ||||
|               </Typography> | ||||
|             </div> | ||||
|             : | ||||
|             data ? this.renderAPStatus(data, classes) | ||||
|               : | ||||
|               <div> | ||||
|                 <Typography variant="h4" className={classes.fetching}> | ||||
|                   {errorMessage} | ||||
|                 </Typography> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}> | ||||
|                   Refresh | ||||
|                 </Button> | ||||
|               </div> | ||||
|         } | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           {this.renderAPStatus(data, classes)} | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="Manage Users" titleGutter> | ||||
|         <ManageUsersForm | ||||
|           userData={data} | ||||
|           userDataFetched={fetched} | ||||
|           errorMessage={errorMessage} | ||||
|           onSubmit={this.props.saveData} | ||||
|           onReset={this.props.loadData} | ||||
|           setData={this.props.setData} | ||||
|           handleValueChange={this.props.handleValueChange} | ||||
|         /> | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           <ManageUsersForm | ||||
|             userData={data} | ||||
|             onSubmit={saveData} | ||||
|             onReset={loadData} | ||||
|             setData={setData} | ||||
|             handleValueChange={handleValueChange} | ||||
|           /> | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="NTP Settings"> | ||||
|       	<NTPSettingsForm | ||||
|           ntpSettings={data} | ||||
|           ntpSettingsFetched={fetched} | ||||
|           errorMessage={errorMessage} | ||||
|           onSubmit={this.props.saveData} | ||||
|           onReset={this.props.loadData} | ||||
|           handleValueChange={this.props.handleValueChange} | ||||
|         /> | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           <NTPSettingsForm | ||||
|             ntpSettings={data} | ||||
|             onSubmit={saveData} | ||||
|             onReset={loadData} | ||||
|             handleValueChange={handleValueChange} | ||||
|           /> | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="NTP Status"> | ||||
|         { | ||||
|           !fetched ? | ||||
|             <div> | ||||
|               <LinearProgress className={classes.fetching} /> | ||||
|               <Typography variant="h4" className={classes.fetching}> | ||||
|                 Loading... | ||||
|               </Typography> | ||||
|             </div> | ||||
|             : | ||||
|             data ? this.renderNTPStatus(data, classes) | ||||
|               : | ||||
|               <div> | ||||
|                 <Typography variant="h4" className={classes.fetching}> | ||||
|                   {errorMessage} | ||||
|                 </Typography> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}> | ||||
|                   Refresh | ||||
|                 </Button> | ||||
|               </div> | ||||
|         } | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           {this.renderNTPStatus(data, classes)} | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="OTA Settings"> | ||||
|       	<OTASettingsForm | ||||
|           otaSettings={data} | ||||
|           otaSettingsFetched={fetched} | ||||
|           errorMessage={errorMessage} | ||||
|           onSubmit={this.props.saveData} | ||||
|           onReset={this.props.loadData} | ||||
|           handleValueChange={this.props.handleValueChange} | ||||
|           handleCheckboxChange={this.props.handleCheckboxChange} | ||||
|         /> | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           <OTASettingsForm | ||||
|             otaSettings={data} | ||||
|             onSubmit={saveData} | ||||
|             onReset={loadData} | ||||
|             handleValueChange={handleValueChange} | ||||
|             handleCheckboxChange={handleCheckboxChange} | ||||
|           /> | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="Security Settings"> | ||||
|         <SecuritySettingsForm | ||||
|           securitySettings={data} | ||||
|           securitySettingsFetched={fetched} | ||||
|           errorMessage={errorMessage} | ||||
|           onSubmit={saveData} | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           handleValueChange={handleValueChange} | ||||
|         /> | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           <SecuritySettingsForm | ||||
|             securitySettings={data} | ||||
|             onSubmit={saveData} | ||||
|             onReset={loadData} | ||||
|             handleValueChange={handleValueChange} | ||||
|           /> | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -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 { | ||||
|           </ListItemAvatar> | ||||
|           <ListItemText primary="Flash Chip Size" secondary={data.flash_chip_size + ' bytes'} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" />         | ||||
|         <Divider variant="inset" component="li" /> | ||||
|       </Fragment> | ||||
|     ); | ||||
|   } | ||||
| @@ -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 ( | ||||
|       <SectionContent title="System Status"> | ||||
|         { | ||||
|           !fetched ? | ||||
|             <div> | ||||
|               <LinearProgress className={classes.fetching} /> | ||||
|               <Typography variant="h4" className={classes.fetching}> | ||||
|                 Loading... | ||||
|               </Typography> | ||||
|             </div> | ||||
|             : | ||||
|             data ? this.renderNTPStatus(data, classes) | ||||
|               : | ||||
|               <div> | ||||
|                 <Typography variant="h4" className={classes.fetching}> | ||||
|                   {errorMessage} | ||||
|                 </Typography> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}> | ||||
|                   Refresh | ||||
|                 </Button> | ||||
|               </div> | ||||
|         } | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           {this.renderNTPStatus(data, classes)} | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="WiFi Settings"> | ||||
|       	<WiFiSettingsForm | ||||
|           wifiSettings={data} | ||||
|           wifiSettingsFetched={fetched} | ||||
|           errorMessage={errorMessage} | ||||
|           selectedNetwork={selectedNetwork} | ||||
|           deselectNetwork={this.props.deselectNetwork} | ||||
|           onSubmit={this.props.saveData} | ||||
|           onReset={this.deselectNetworkAndLoadData} | ||||
|           handleValueChange={this.props.handleValueChange} | ||||
|           handleCheckboxChange={this.props.handleCheckboxChange} | ||||
|         /> | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           <WiFiSettingsForm | ||||
|             wifiSettings={data} | ||||
|             selectedNetwork={selectedNetwork} | ||||
|             deselectNetwork={deselectNetwork} | ||||
|             onSubmit={saveData} | ||||
|             onReset={this.deselectNetworkAndLoadData} | ||||
|             handleValueChange={handleValueChange} | ||||
|             handleCheckboxChange={handleCheckboxChange} | ||||
|           /> | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -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 ( | ||||
|       <SectionContent title="WiFi Status"> | ||||
|         { | ||||
|           !fetched ? | ||||
|             <div> | ||||
|               <LinearProgress className={classes.fetching} /> | ||||
|               <Typography variant="h4" className={classes.fetching}> | ||||
|                 Loading... | ||||
|            </Typography> | ||||
|             </div> | ||||
|             : | ||||
|             data ? this.renderWiFiStatus(data, classes) | ||||
|               : | ||||
|               <div> | ||||
|                 <Typography variant="h4" className={classes.fetching}> | ||||
|                   {errorMessage} | ||||
|                 </Typography> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}> | ||||
|                   Refresh | ||||
|           </Button> | ||||
|               </div> | ||||
|         } | ||||
|         <LoadingNotification | ||||
|           onReset={loadData} | ||||
|           fetched={fetched} | ||||
|           errorMessage={errorMessage}> | ||||
|           {this.renderWiFiStatus(data, classes)} | ||||
|         </LoadingNotification> | ||||
|       </SectionContent> | ||||
|     ) | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| export default restComponent(WIFI_STATUS_ENDPOINT, withStyles(styles)(WiFiStatus)); | ||||
|   | ||||
| @@ -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 ( | ||||
|       <div> | ||||
|       <ValidatorForm onSubmit={onSubmit} ref="APSettingsForm"> | ||||
|         <SelectValidator name="provision_mode" label="Provide Access Point..." value={apSettings.provision_mode} className={classes.selectField} | ||||
|           onChange={handleValueChange('provision_mode')}> | ||||
|           <MenuItem value={0}>Always</MenuItem> | ||||
|           <MenuItem value={1}>When WiFi Disconnected</MenuItem> | ||||
|           <MenuItem value={2}>Never</MenuItem> | ||||
|         </SelectValidator> | ||||
|         { | ||||
|          !apSettingsFetched ? | ||||
|  | ||||
|          <div className={classes.loadingSettings}> | ||||
|            <LinearProgress className={classes.loadingSettingsDetails}/> | ||||
|            <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|              Loading... | ||||
|            </Typography> | ||||
|          </div> | ||||
|  | ||||
|          : apSettings ? | ||||
|  | ||||
|         <ValidatorForm onSubmit={onSubmit} ref="APSettingsForm"> | ||||
|  | ||||
|           <SelectValidator name="provision_mode" label="Provide Access Point..." value={apSettings.provision_mode}  className={classes.selectField} | ||||
|            onChange={handleValueChange('provision_mode')}> | ||||
|             <MenuItem value={0}>Always</MenuItem> | ||||
|             <MenuItem value={1}>When WiFi Disconnected</MenuItem> | ||||
|             <MenuItem value={2}>Never</MenuItem> | ||||
|           </SelectValidator> | ||||
|  | ||||
|           { | ||||
|             isAPEnabled(apSettings.provision_mode) && | ||||
|             <Fragment> | ||||
|               <TextValidator | ||||
|                 validators={['required', 'matchRegexp:^.{1,32}$']} | ||||
|                 errorMessages={['Access Point SSID is required', 'Access Point SSID must be 32 characters or less']} | ||||
|                 name="ssid" | ||||
|                 label="Access Point SSID" | ||||
|                 className={classes.textField} | ||||
|                 value={apSettings.ssid} | ||||
|                 onChange={handleValueChange('ssid')} | ||||
|                 margin="normal" | ||||
|               /> | ||||
|               <PasswordValidator | ||||
|                     validators={['required', 'matchRegexp:^.{1,64}$']} | ||||
|                     errorMessages={['Access Point Password is required', 'Access Point Password must be 64 characters or less']} | ||||
|                     name="password" | ||||
|                     label="Access Point Password" | ||||
|                     className={classes.textField} | ||||
|                     value={apSettings.password} | ||||
|                     onChange={handleValueChange('password')} | ||||
|                     margin="normal" | ||||
|               /> | ||||
|             </Fragment> | ||||
|           } | ||||
|  | ||||
|           <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|             Save | ||||
|           </Button> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|       		  Reset | ||||
|       		</Button> | ||||
|  | ||||
|         </ValidatorForm> | ||||
|  | ||||
|         : | ||||
|  | ||||
|         <div className={classes.loadingSettings}> | ||||
|           <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|             {errorMessage} | ||||
|           </Typography> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|       		  Reset | ||||
|       		</Button> | ||||
|         </div> | ||||
|       } | ||||
|       </div> | ||||
|           isAPEnabled(apSettings.provision_mode) && | ||||
|           <Fragment> | ||||
|             <TextValidator | ||||
|               validators={['required', 'matchRegexp:^.{1,32}$']} | ||||
|               errorMessages={['Access Point SSID is required', 'Access Point SSID must be 32 characters or less']} | ||||
|               name="ssid" | ||||
|               label="Access Point SSID" | ||||
|               className={classes.textField} | ||||
|               value={apSettings.ssid} | ||||
|               onChange={handleValueChange('ssid')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|             <PasswordValidator | ||||
|               validators={['required', 'matchRegexp:^.{1,64}$']} | ||||
|               errorMessages={['Access Point Password is required', 'Access Point Password must be 64 characters or less']} | ||||
|               name="password" | ||||
|               label="Access Point Password" | ||||
|               className={classes.textField} | ||||
|               value={apSettings.password} | ||||
|               onChange={handleValueChange('password')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|           </Fragment> | ||||
|         } | ||||
|         <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|           Save | ||||
|         </Button> | ||||
|         <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|           Reset | ||||
|         </Button> | ||||
|       </ValidatorForm> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| 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 | ||||
|   | ||||
| @@ -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 ? | ||||
|         <div className={classes.loadingSettings}> | ||||
|           <LinearProgress className={classes.loadingSettingsDetails} /> | ||||
|           <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|             Loading... | ||||
|           </Typography> | ||||
|         </div> | ||||
|         : | ||||
|         userData ? | ||||
|           <Fragment> | ||||
|             <ValidatorForm onSubmit={this.onSubmit}> | ||||
|               <Table className={classes.table}> | ||||
|                 <TableHead> | ||||
|                   <TableRow> | ||||
|                     <TableCell>Username</TableCell> | ||||
|                     <TableCell align="center">Admin?</TableCell> | ||||
|                     <TableCell /> | ||||
|                   </TableRow> | ||||
|                 </TableHead> | ||||
|                 <TableBody> | ||||
|                   {userData.users.sort(compareUsers).map(user => ( | ||||
|                     <TableRow key={user.username}> | ||||
|                       <TableCell component="th" scope="row"> | ||||
|                         {user.username} | ||||
|                       </TableCell> | ||||
|                       <TableCell align="center"> | ||||
|                         { | ||||
|                           user.admin ? <CheckIcon /> : <CloseIcon /> | ||||
|                         } | ||||
|                       </TableCell> | ||||
|                       <TableCell align="center"> | ||||
|                         <IconButton aria-label="Delete" onClick={() => this.removeUser(user)}> | ||||
|                           <DeleteIcon /> | ||||
|                         </IconButton> | ||||
|                         <IconButton aria-label="Edit" onClick={() => this.startEditingUser(user)}> | ||||
|                           <EditIcon /> | ||||
|                         </IconButton> | ||||
|                       </TableCell> | ||||
|                     </TableRow> | ||||
|                   ))} | ||||
|                 </TableBody> | ||||
|                 <TableFooter> | ||||
|                   <TableRow> | ||||
|                     <TableCell colSpan={2} /> | ||||
|                     <TableCell align="center"> | ||||
|                       <Button variant="contained" color="secondary" onClick={this.createUser}> | ||||
|                         Add User | ||||
|                       </Button> | ||||
|                     </TableCell> | ||||
|                   </TableRow> | ||||
|                 </TableFooter> | ||||
|               </Table> | ||||
|               { | ||||
|                 this.noAdminConfigured() && | ||||
|                 <Typography component="div" variant="body1"> | ||||
|                   <Box bgcolor="error.main" color="error.contrastText" p={2} mt={2} mb={2}> | ||||
|                     You must have at least one admin user configured. | ||||
|                   </Box> | ||||
|                 </Typography> | ||||
|               } | ||||
|               <Button variant="contained" color="primary" className={classes.button} type="submit" disabled={this.noAdminConfigured()}> | ||||
|                 Save | ||||
|               </Button> | ||||
|               <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|                 Reset | ||||
|       		    </Button> | ||||
|             </ValidatorForm> | ||||
|             { | ||||
|               user && | ||||
|               <UserForm | ||||
|                 user={user} | ||||
|                 creating={creating} | ||||
|                 onDoneEditing={this.doneEditingUser} | ||||
|                 onCancelEditing={this.cancelEditingUser} | ||||
|                 handleValueChange={this.handleUserValueChange} | ||||
|                 handleCheckboxChange={this.handleUserCheckboxChange} | ||||
|                 uniqueUsername={this.uniqueUsername} | ||||
|               /> | ||||
|             } | ||||
|           </Fragment> | ||||
|           : | ||||
|           <div className={classes.loadingSettings}> | ||||
|             <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|               {errorMessage} | ||||
|       <Fragment> | ||||
|         <ValidatorForm onSubmit={this.onSubmit}> | ||||
|           <Table className={classes.table}> | ||||
|             <TableHead> | ||||
|               <TableRow> | ||||
|                 <TableCell>Username</TableCell> | ||||
|                 <TableCell align="center">Admin?</TableCell> | ||||
|                 <TableCell /> | ||||
|               </TableRow> | ||||
|             </TableHead> | ||||
|             <TableBody> | ||||
|               {userData.users.sort(compareUsers).map(user => ( | ||||
|                 <TableRow key={user.username}> | ||||
|                   <TableCell component="th" scope="row"> | ||||
|                     {user.username} | ||||
|                   </TableCell> | ||||
|                   <TableCell align="center"> | ||||
|                     { | ||||
|                       user.admin ? <CheckIcon /> : <CloseIcon /> | ||||
|                     } | ||||
|                   </TableCell> | ||||
|                   <TableCell align="center"> | ||||
|                     <IconButton aria-label="Delete" onClick={() => this.removeUser(user)}> | ||||
|                       <DeleteIcon /> | ||||
|                     </IconButton> | ||||
|                     <IconButton aria-label="Edit" onClick={() => this.startEditingUser(user)}> | ||||
|                       <EditIcon /> | ||||
|                     </IconButton> | ||||
|                   </TableCell> | ||||
|                 </TableRow> | ||||
|               ))} | ||||
|             </TableBody> | ||||
|             <TableFooter> | ||||
|               <TableRow> | ||||
|                 <TableCell colSpan={2} /> | ||||
|                 <TableCell align="center"> | ||||
|                   <Button variant="contained" color="secondary" onClick={this.createUser}> | ||||
|                     Add User | ||||
|                   </Button> | ||||
|                 </TableCell> | ||||
|               </TableRow> | ||||
|             </TableFooter> | ||||
|           </Table> | ||||
|           { | ||||
|             this.noAdminConfigured() && | ||||
|             <Typography component="div" variant="body1"> | ||||
|               <Box bgcolor="error.main" color="error.contrastText" p={2} mt={2} mb={2}> | ||||
|                 You must have at least one admin user configured. | ||||
|               </Box> | ||||
|             </Typography> | ||||
|             <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|               Reset | ||||
|       		  </Button> | ||||
|           </div> | ||||
|           } | ||||
|           <Button variant="contained" color="primary" className={classes.button} type="submit" disabled={this.noAdminConfigured()}> | ||||
|             Save | ||||
|           </Button> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|             Reset | ||||
|       		</Button> | ||||
|         </ValidatorForm> | ||||
|         { | ||||
|           user && | ||||
|           <UserForm | ||||
|             user={user} | ||||
|             creating={creating} | ||||
|             onDoneEditing={this.doneEditingUser} | ||||
|             onCancelEditing={this.cancelEditingUser} | ||||
|             handleValueChange={this.handleUserValueChange} | ||||
|             handleCheckboxChange={this.handleUserCheckboxChange} | ||||
|             uniqueUsername={this.uniqueUsername} | ||||
|           /> | ||||
|         } | ||||
|       </Fragment> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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 ( | ||||
|       <div> | ||||
|         { | ||||
|          !ntpSettingsFetched ? | ||||
|  | ||||
|          <div className={classes.loadingSettings}> | ||||
|            <LinearProgress className={classes.loadingSettingsDetails}/> | ||||
|            <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|              Loading... | ||||
|            </Typography> | ||||
|          </div> | ||||
|  | ||||
|          : ntpSettings ? | ||||
|  | ||||
|       	 <ValidatorForm onSubmit={onSubmit}> | ||||
|  | ||||
|            <TextValidator | ||||
|                validators={['required', 'isIPOrHostname']} | ||||
|                errorMessages={['Server is required', "Not a valid IP address or hostname"]} | ||||
|                name="server" | ||||
|                label="Server" | ||||
|                className={classes.textField} | ||||
|                value={ntpSettings.server} | ||||
|                onChange={handleValueChange('server')} | ||||
|                margin="normal" | ||||
|              /> | ||||
|  | ||||
|              <TextValidator | ||||
|                  validators={['required','isNumber','minNumber:60','maxNumber:86400']} | ||||
|                  errorMessages={['Interval is required','Interval must be a number','Must be at least 60 seconds',"Must not be more than 86400 seconds (24 hours)"]} | ||||
|                  name="interval" | ||||
|                  label="Interval (Seconds)" | ||||
|                  className={classes.textField} | ||||
|                  value={ntpSettings.interval} | ||||
|                  type="number" | ||||
|                  onChange={handleValueChange('interval')} | ||||
|                  margin="normal" | ||||
|                /> | ||||
|  | ||||
|           <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|             Save | ||||
|           </Button> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|       		  Reset | ||||
|       		</Button> | ||||
|  | ||||
|          </ValidatorForm> | ||||
|  | ||||
|         : | ||||
|  | ||||
|         <div className={classes.loadingSettings}> | ||||
|           <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|             {errorMessage} | ||||
|           </Typography> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|       		  Reset | ||||
|       		</Button> | ||||
|         </div> | ||||
|       } | ||||
|       </div> | ||||
|       <ValidatorForm onSubmit={onSubmit}> | ||||
|         <TextValidator | ||||
|           validators={['required', 'isIPOrHostname']} | ||||
|           errorMessages={['Server is required', "Not a valid IP address or hostname"]} | ||||
|           name="server" | ||||
|           label="Server" | ||||
|           className={classes.textField} | ||||
|           value={ntpSettings.server} | ||||
|           onChange={handleValueChange('server')} | ||||
|           margin="normal" | ||||
|         /> | ||||
|         <TextValidator | ||||
|           validators={['required', 'isNumber', 'minNumber:60', 'maxNumber:86400']} | ||||
|           errorMessages={['Interval is required', 'Interval must be a number', 'Must be at least 60 seconds', "Must not be more than 86400 seconds (24 hours)"]} | ||||
|           name="interval" | ||||
|           label="Interval (Seconds)" | ||||
|           className={classes.textField} | ||||
|           value={ntpSettings.interval} | ||||
|           type="number" | ||||
|           onChange={handleValueChange('interval')} | ||||
|           margin="normal" | ||||
|         /> | ||||
|         <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|           Save | ||||
|         </Button> | ||||
|         <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|           Reset | ||||
|         </Button> | ||||
|       </ValidatorForm> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| 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, | ||||
|   | ||||
| @@ -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 ( | ||||
|       <div> | ||||
|         { | ||||
|          !otaSettingsFetched ? | ||||
|  | ||||
|          <div className={classes.loadingSettings}> | ||||
|            <LinearProgress className={classes.loadingSettingsDetails}/> | ||||
|            <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|              Loading... | ||||
|            </Typography> | ||||
|          </div> | ||||
|  | ||||
|          : otaSettings ? | ||||
|  | ||||
|       	 <ValidatorForm onSubmit={onSubmit}> | ||||
|  | ||||
|             <FormControlLabel className={classes.switchControl} | ||||
|                control={ | ||||
|                  <Switch | ||||
|                         checked={otaSettings.enabled} | ||||
|                         onChange={handleCheckboxChange('enabled')} | ||||
|                         value="enabled" | ||||
|                         color="primary" | ||||
|                  /> | ||||
|                } | ||||
|               label="Enable OTA Updates?" | ||||
|              /> | ||||
|  | ||||
|            <TextValidator | ||||
|                validators={['required', 'isNumber', 'minNumber:1025', 'maxNumber:65535']} | ||||
|                errorMessages={['Port is required', "Must be a number", "Must be greater than 1024 ", "Max value is 65535"]} | ||||
|                name="port" | ||||
|                label="Port" | ||||
|                className={classes.textField} | ||||
|                value={otaSettings.port} | ||||
|                type="number" | ||||
|                onChange={handleValueChange('port')} | ||||
|                margin="normal" | ||||
|              /> | ||||
|  | ||||
|              <PasswordValidator | ||||
|                    validators={['required', 'matchRegexp:^.{1,64}$']} | ||||
|                    errorMessages={['OTA Password is required', 'OTA Point Password must be 64 characters or less']} | ||||
|                    name="password" | ||||
|                    label="Password" | ||||
|                    className={classes.textField} | ||||
|                    value={otaSettings.password} | ||||
|                    onChange={handleValueChange('password')} | ||||
|                    margin="normal" | ||||
|              /> | ||||
|  | ||||
|           <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|             Save | ||||
|           </Button> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|       		  Reset | ||||
|       		</Button> | ||||
|  | ||||
|          </ValidatorForm> | ||||
|  | ||||
|         : | ||||
|  | ||||
|         <div className={classes.loadingSettings}> | ||||
|           <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|             {errorMessage} | ||||
|           </Typography> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|       		  Reset | ||||
|       		</Button> | ||||
|         </div> | ||||
|       } | ||||
|       </div> | ||||
|       <ValidatorForm onSubmit={onSubmit}> | ||||
|         <FormControlLabel className={classes.switchControl} | ||||
|           control={ | ||||
|             <Switch | ||||
|               checked={otaSettings.enabled} | ||||
|               onChange={handleCheckboxChange('enabled')} | ||||
|               value="enabled" | ||||
|               color="primary" | ||||
|             /> | ||||
|           } | ||||
|           label="Enable OTA Updates?" | ||||
|         /> | ||||
|         <TextValidator | ||||
|           validators={['required', 'isNumber', 'minNumber:1025', 'maxNumber:65535']} | ||||
|           errorMessages={['Port is required', "Must be a number", "Must be greater than 1024 ", "Max value is 65535"]} | ||||
|           name="port" | ||||
|           label="Port" | ||||
|           className={classes.textField} | ||||
|           value={otaSettings.port} | ||||
|           type="number" | ||||
|           onChange={handleValueChange('port')} | ||||
|           margin="normal" | ||||
|         /> | ||||
|         <PasswordValidator | ||||
|           validators={['required', 'matchRegexp:^.{1,64}$']} | ||||
|           errorMessages={['OTA Password is required', 'OTA Point Password must be 64 characters or less']} | ||||
|           name="password" | ||||
|           label="Password" | ||||
|           className={classes.textField} | ||||
|           value={otaSettings.password} | ||||
|           onChange={handleValueChange('password')} | ||||
|           margin="normal" | ||||
|         /> | ||||
|         <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|           Save | ||||
|         </Button> | ||||
|         <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|           Reset | ||||
|         </Button> | ||||
|       </ValidatorForm> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| 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, | ||||
|   | ||||
| @@ -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 ? | ||||
|         <div className={classes.loadingSettings}> | ||||
|           <LinearProgress className={classes.loadingSettingsDetails} /> | ||||
|           <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|             Loading... | ||||
|           </Typography> | ||||
|         </div> | ||||
|         : | ||||
|         securitySettings ? | ||||
|           <ValidatorForm onSubmit={this.onSubmit} ref="SecuritySettingsForm"> | ||||
|             <PasswordValidator | ||||
|               validators={['required', 'matchRegexp:^.{1,64}$']} | ||||
|               errorMessages={['JWT Secret Required', 'JWT Secret must be 64 characters or less']} | ||||
|               name="jwt_secret" | ||||
|               label="JWT Secret" | ||||
|               className={classes.textField} | ||||
|               value={securitySettings.jwt_secret} | ||||
|               onChange={handleValueChange('jwt_secret')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|             <Typography component="div" variant="body1"> | ||||
|               <Box bgcolor="primary.main" color="primary.contrastText" p={2} mt={2} mb={2}> | ||||
|                 If you modify the JWT Secret, all users will be logged out. | ||||
|               </Box> | ||||
|             </Typography> | ||||
|             <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|               Save | ||||
|             </Button> | ||||
|             <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|               Reset | ||||
|       		  </Button> | ||||
|           </ValidatorForm> | ||||
|           : | ||||
|           <div className={classes.loadingSettings}> | ||||
|             <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|               {errorMessage} | ||||
|             </Typography> | ||||
|             <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|               Reset | ||||
|       		  </Button> | ||||
|           </div> | ||||
|       <ValidatorForm onSubmit={this.onSubmit} ref="SecuritySettingsForm"> | ||||
|         <PasswordValidator | ||||
|           validators={['required', 'matchRegexp:^.{1,64}$']} | ||||
|           errorMessages={['JWT Secret Required', 'JWT Secret must be 64 characters or less']} | ||||
|           name="jwt_secret" | ||||
|           label="JWT Secret" | ||||
|           className={classes.textField} | ||||
|           value={securitySettings.jwt_secret} | ||||
|           onChange={handleValueChange('jwt_secret')} | ||||
|           margin="normal" | ||||
|         /> | ||||
|         <Typography component="div" variant="body1"> | ||||
|           <Box bgcolor="primary.main" color="primary.contrastText" p={2} mt={2} mb={2}> | ||||
|             If you modify the JWT Secret, all users will be logged out. | ||||
|           </Box> | ||||
|         </Typography> | ||||
|         <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|           Save | ||||
|         </Button> | ||||
|         <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|           Reset | ||||
|       	</Button> | ||||
|       </ValidatorForm> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| 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, | ||||
|   | ||||
| @@ -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 ( | ||||
|       <div> | ||||
|       <ValidatorForm onSubmit={onSubmit} ref="WiFiSettingsForm"> | ||||
|         { | ||||
|           !wifiSettingsFetched ? | ||||
|  | ||||
|             <div className={classes.loadingSettings}> | ||||
|               <LinearProgress className={classes.loadingSettingsDetails} /> | ||||
|               <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|                 Loading... | ||||
|               </Typography> | ||||
|             </div> | ||||
|  | ||||
|             : wifiSettings ? | ||||
|  | ||||
|               <ValidatorForm onSubmit={onSubmit} ref="WiFiSettingsForm"> | ||||
|                 { | ||||
|                   selectedNetwork ? this.renderSelectedNetwork() : | ||||
|                     <TextValidator | ||||
|                       validators={['matchRegexp:^.{0,32}$']} | ||||
|                       errorMessages={['SSID must be 32 characters or less']} | ||||
|                       name="ssid" | ||||
|                       label="SSID" | ||||
|                       className={classes.textField} | ||||
|                       value={wifiSettings.ssid} | ||||
|                       onChange={handleValueChange('ssid')} | ||||
|                       margin="normal" | ||||
|                     /> | ||||
|                 } | ||||
|                 { | ||||
|                   !isNetworkOpen(selectedNetwork) && | ||||
|                   <PasswordValidator | ||||
|                     validators={['matchRegexp:^.{0,64}$']} | ||||
|                     errorMessages={['Password must be 64 characters or less']} | ||||
|                     name="password" | ||||
|                     label="Password" | ||||
|                     className={classes.textField} | ||||
|                     value={wifiSettings.password} | ||||
|                     onChange={handleValueChange('password')} | ||||
|                     margin="normal" | ||||
|                   /> | ||||
|                 } | ||||
|  | ||||
|                 <TextValidator | ||||
|                   validators={['required', 'isHostname']} | ||||
|                   errorMessages={['Hostname is required', "Not a valid hostname"]} | ||||
|                   name="hostname" | ||||
|                   label="Hostname" | ||||
|                   className={classes.textField} | ||||
|                   value={wifiSettings.hostname} | ||||
|                   onChange={handleValueChange('hostname')} | ||||
|                   margin="normal" | ||||
|                 /> | ||||
|  | ||||
|                 <FormControlLabel className={classes.checkboxControl} | ||||
|                   control={ | ||||
|                     <Checkbox | ||||
|                       value="static_ip_config" | ||||
|                       checked={wifiSettings.static_ip_config} | ||||
|                       onChange={handleCheckboxChange("static_ip_config")} | ||||
|                     /> | ||||
|                   } | ||||
|                   label="Static IP Config?" | ||||
|                 /> | ||||
|  | ||||
|                 { | ||||
|                   wifiSettings.static_ip_config && | ||||
|                   <Fragment> | ||||
|                     <TextValidator | ||||
|                       validators={['required', 'isIP']} | ||||
|                       errorMessages={['Local IP is required', 'Must be an IP address']} | ||||
|                       name="local_ip" | ||||
|                       label="Local IP" | ||||
|                       className={classes.textField} | ||||
|                       value={wifiSettings.local_ip} | ||||
|                       onChange={handleValueChange('local_ip')} | ||||
|                       margin="normal" | ||||
|                     /> | ||||
|                     <TextValidator | ||||
|                       validators={['required', 'isIP']} | ||||
|                       errorMessages={['Gateway IP is required', 'Must be an IP address']} | ||||
|                       name="gateway_ip" | ||||
|                       label="Gateway" | ||||
|                       className={classes.textField} | ||||
|                       value={wifiSettings.gateway_ip} | ||||
|                       onChange={handleValueChange('gateway_ip')} | ||||
|                       margin="normal" | ||||
|                     /> | ||||
|                     <TextValidator | ||||
|                       validators={['required', 'isIP']} | ||||
|                       errorMessages={['Subnet mask is required', 'Must be an IP address']} | ||||
|                       name="subnet_mask" | ||||
|                       label="Subnet" | ||||
|                       className={classes.textField} | ||||
|                       value={wifiSettings.subnet_mask} | ||||
|                       onChange={handleValueChange('subnet_mask')} | ||||
|                       margin="normal" | ||||
|                     /> | ||||
|                     <TextValidator | ||||
|                       validators={['isOptionalIP']} | ||||
|                       errorMessages={['Must be an IP address']} | ||||
|                       name="dns_ip_1" | ||||
|                       label="DNS IP #1" | ||||
|                       className={classes.textField} | ||||
|                       value={wifiSettings.dns_ip_1} | ||||
|                       onChange={handleValueChange('dns_ip_1')} | ||||
|                       margin="normal" | ||||
|                     /> | ||||
|                     <TextValidator | ||||
|                       validators={['isOptionalIP']} | ||||
|                       errorMessages={['Must be an IP address']} | ||||
|                       name="dns_ip_2" | ||||
|                       label="DNS IP #2" | ||||
|                       className={classes.textField} | ||||
|                       value={wifiSettings.dns_ip_2} | ||||
|                       onChange={handleValueChange('dns_ip_2')} | ||||
|                       margin="normal" | ||||
|                     /> | ||||
|                   </Fragment> | ||||
|                 } | ||||
|  | ||||
|                 <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|                   Save | ||||
|           </Button> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|                   Reset | ||||
|       		</Button> | ||||
|  | ||||
|               </ValidatorForm> | ||||
|  | ||||
|               : | ||||
|  | ||||
|               <div className={classes.loadingSettings}> | ||||
|                 <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|                   {errorMessage} | ||||
|                 </Typography> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|                   Reset | ||||
|       		</Button> | ||||
|               </div> | ||||
|           selectedNetwork ? this.renderSelectedNetwork() : | ||||
|             <TextValidator | ||||
|               validators={['matchRegexp:^.{0,32}$']} | ||||
|               errorMessages={['SSID must be 32 characters or less']} | ||||
|               name="ssid" | ||||
|               label="SSID" | ||||
|               className={classes.textField} | ||||
|               value={wifiSettings.ssid} | ||||
|               onChange={handleValueChange('ssid')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|         } | ||||
|       </div> | ||||
|         { | ||||
|           !isNetworkOpen(selectedNetwork) && | ||||
|           <PasswordValidator | ||||
|             validators={['matchRegexp:^.{0,64}$']} | ||||
|             errorMessages={['Password must be 64 characters or less']} | ||||
|             name="password" | ||||
|             label="Password" | ||||
|             className={classes.textField} | ||||
|             value={wifiSettings.password} | ||||
|             onChange={handleValueChange('password')} | ||||
|             margin="normal" | ||||
|           /> | ||||
|         } | ||||
|         <TextValidator | ||||
|           validators={['required', 'isHostname']} | ||||
|           errorMessages={['Hostname is required', "Not a valid hostname"]} | ||||
|           name="hostname" | ||||
|           label="Hostname" | ||||
|           className={classes.textField} | ||||
|           value={wifiSettings.hostname} | ||||
|           onChange={handleValueChange('hostname')} | ||||
|           margin="normal" | ||||
|         /> | ||||
|         <FormControlLabel className={classes.checkboxControl} | ||||
|           control={ | ||||
|             <Checkbox | ||||
|               value="static_ip_config" | ||||
|               checked={wifiSettings.static_ip_config} | ||||
|               onChange={handleCheckboxChange("static_ip_config")} | ||||
|             /> | ||||
|           } | ||||
|           label="Static IP Config?" | ||||
|         /> | ||||
|         { | ||||
|           wifiSettings.static_ip_config && | ||||
|           <Fragment> | ||||
|             <TextValidator | ||||
|               validators={['required', 'isIP']} | ||||
|               errorMessages={['Local IP is required', 'Must be an IP address']} | ||||
|               name="local_ip" | ||||
|               label="Local IP" | ||||
|               className={classes.textField} | ||||
|               value={wifiSettings.local_ip} | ||||
|               onChange={handleValueChange('local_ip')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|             <TextValidator | ||||
|               validators={['required', 'isIP']} | ||||
|               errorMessages={['Gateway IP is required', 'Must be an IP address']} | ||||
|               name="gateway_ip" | ||||
|               label="Gateway" | ||||
|               className={classes.textField} | ||||
|               value={wifiSettings.gateway_ip} | ||||
|               onChange={handleValueChange('gateway_ip')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|             <TextValidator | ||||
|               validators={['required', 'isIP']} | ||||
|               errorMessages={['Subnet mask is required', 'Must be an IP address']} | ||||
|               name="subnet_mask" | ||||
|               label="Subnet" | ||||
|               className={classes.textField} | ||||
|               value={wifiSettings.subnet_mask} | ||||
|               onChange={handleValueChange('subnet_mask')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|             <TextValidator | ||||
|               validators={['isOptionalIP']} | ||||
|               errorMessages={['Must be an IP address']} | ||||
|               name="dns_ip_1" | ||||
|               label="DNS IP #1" | ||||
|               className={classes.textField} | ||||
|               value={wifiSettings.dns_ip_1} | ||||
|               onChange={handleValueChange('dns_ip_1')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|             <TextValidator | ||||
|               validators={['isOptionalIP']} | ||||
|               errorMessages={['Must be an IP address']} | ||||
|               name="dns_ip_2" | ||||
|               label="DNS IP #2" | ||||
|               className={classes.textField} | ||||
|               value={wifiSettings.dns_ip_2} | ||||
|               onChange={handleValueChange('dns_ip_2')} | ||||
|               margin="normal" | ||||
|             /> | ||||
|           </Fragment> | ||||
|         } | ||||
|         <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|           Save | ||||
|         </Button> | ||||
|         <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|           Reset | ||||
|         </Button> | ||||
|       </ValidatorForm> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| 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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user