Factory reset feature (#114)
Implemented factory-reset feature Extract factory settings into separate ini file Hide reset/factory reset from guest user Co-authored-by: kasedy <kasedy@gmail.com>
This commit is contained in:
		
							
								
								
									
										1452
									
								
								interface/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1452
									
								
								interface/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -16,3 +16,4 @@ export const SIGN_IN_ENDPOINT = ENDPOINT_ROOT + "signIn"; | ||||
| export const VERIFY_AUTHORIZATION_ENDPOINT = ENDPOINT_ROOT + "verifyAuthorization"; | ||||
| export const SECURITY_SETTINGS_ENDPOINT = ENDPOINT_ROOT + "securitySettings"; | ||||
| export const RESTART_ENDPOINT = ENDPOINT_ROOT + "restart"; | ||||
| export const FACTORY_RESET_ENDPOINT = ENDPOINT_ROOT + "factoryReset"; | ||||
|   | ||||
							
								
								
									
										11
									
								
								interface/src/components/ErrorButton.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								interface/src/components/ErrorButton.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| import { Button, styled } from "@material-ui/core"; | ||||
|  | ||||
| const ErrorButton = styled(Button)(({ theme }) => ({ | ||||
|   color: theme.palette.getContrastText(theme.palette.error.main), | ||||
|   backgroundColor: theme.palette.error.main, | ||||
|   '&:hover': { | ||||
|     backgroundColor: theme.palette.error.dark, | ||||
|   } | ||||
| })); | ||||
|  | ||||
| export default ErrorButton; | ||||
| @@ -7,6 +7,7 @@ export { default as PasswordValidator } from './PasswordValidator'; | ||||
| export { default as RestFormLoader } from './RestFormLoader'; | ||||
| export { default as SectionContent } from './SectionContent'; | ||||
| export { default as WebSocketFormLoader } from './WebSocketFormLoader'; | ||||
| export { default as ErrorButton } from './ErrorButton'; | ||||
|  | ||||
| export * from './RestFormLoader'; | ||||
| export * from './RestController'; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import React, { Component, Fragment } from 'react'; | ||||
|  | ||||
| import { Avatar, Button, Divider, Dialog, DialogTitle, DialogContent, DialogActions } from '@material-ui/core'; | ||||
| import { Avatar, Button, Divider, Dialog, DialogTitle, DialogContent, DialogActions, Box } from '@material-ui/core'; | ||||
| import { List, ListItem, ListItemAvatar, ListItemText } from '@material-ui/core'; | ||||
|  | ||||
| import DevicesIcon from '@material-ui/icons/Devices'; | ||||
| @@ -8,26 +8,29 @@ import MemoryIcon from '@material-ui/icons/Memory'; | ||||
| import ShowChartIcon from '@material-ui/icons/ShowChart'; | ||||
| import SdStorageIcon from '@material-ui/icons/SdStorage'; | ||||
| import DataUsageIcon from '@material-ui/icons/DataUsage'; | ||||
| import AutorenewIcon from '@material-ui/icons/Autorenew'; | ||||
| import PowerSettingsNewIcon from '@material-ui/icons/PowerSettingsNew'; | ||||
| import RefreshIcon from '@material-ui/icons/Refresh'; | ||||
| import SettingsBackupRestoreIcon from '@material-ui/icons/SettingsBackupRestore'; | ||||
|  | ||||
| import { redirectingAuthorizedFetch } from '../authentication'; | ||||
| import { RestFormProps, FormButton, FormActions } from '../components'; | ||||
| import { RESTART_ENDPOINT } from '../api'; | ||||
| import { redirectingAuthorizedFetch, AuthenticatedContextProps, withAuthenticatedContext } from '../authentication'; | ||||
| import { RestFormProps, FormButton, ErrorButton } from '../components'; | ||||
| import { FACTORY_RESET_ENDPOINT, RESTART_ENDPOINT } from '../api'; | ||||
|  | ||||
| import { SystemStatus } from './types'; | ||||
|  | ||||
| interface SystemStatusFormState { | ||||
|   confirmRestart: boolean; | ||||
|   confirmFactoryReset: boolean; | ||||
|   processing: boolean; | ||||
| } | ||||
|  | ||||
| type SystemStatusFormProps = RestFormProps<SystemStatus>; | ||||
| type SystemStatusFormProps = AuthenticatedContextProps & RestFormProps<SystemStatus>; | ||||
|  | ||||
| class SystemStatusForm extends Component<SystemStatusFormProps, SystemStatusFormState> { | ||||
|  | ||||
|   state: SystemStatusFormState = { | ||||
|     confirmRestart: false, | ||||
|     confirmFactoryReset: false, | ||||
|     processing: false | ||||
|   } | ||||
|  | ||||
| @@ -95,7 +98,7 @@ class SystemStatusForm extends Component<SystemStatusFormProps, SystemStatusForm | ||||
|           Are you sure you want to restart the device? | ||||
|         </DialogContent> | ||||
|         <DialogActions> | ||||
|           <Button startIcon={<AutorenewIcon />} variant="contained" onClick={this.onRestartConfirmed} disabled={this.state.processing} color="primary" autoFocus> | ||||
|           <Button startIcon={<PowerSettingsNewIcon />} variant="contained" onClick={this.onRestartConfirmed} disabled={this.state.processing} color="primary" autoFocus> | ||||
|             Restart | ||||
|           </Button> | ||||
|           <Button variant="contained" onClick={this.onRestartRejected} color="secondary"> | ||||
| @@ -131,25 +134,83 @@ class SystemStatusForm extends Component<SystemStatusFormProps, SystemStatusForm | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|   renderFactoryResetDialog() { | ||||
|     return ( | ||||
|       <Dialog | ||||
|         open={this.state.confirmFactoryReset} | ||||
|         onClose={this.onFactoryResetRejected} | ||||
|       > | ||||
|         <DialogTitle>Confirm Factory Reset</DialogTitle> | ||||
|         <DialogContent dividers> | ||||
|           Are you sure you want to reset the device to its factory defaults? | ||||
|         </DialogContent> | ||||
|         <DialogActions> | ||||
|           <ErrorButton startIcon={<SettingsBackupRestoreIcon />} variant="contained" onClick={this.onFactoryResetConfirmed} disabled={this.state.processing} autoFocus> | ||||
|             Factory Reset | ||||
|           </ErrorButton> | ||||
|           <Button variant="contained" onClick={this.onFactoryResetRejected} color="secondary"> | ||||
|             Cancel | ||||
|           </Button> | ||||
|         </DialogActions> | ||||
|       </Dialog> | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   onFactoryReset = () => { | ||||
|     this.setState({ confirmFactoryReset: true }); | ||||
|   } | ||||
|  | ||||
|   onFactoryResetRejected = () => { | ||||
|     this.setState({ confirmFactoryReset: false }); | ||||
|   } | ||||
|  | ||||
|   onFactoryResetConfirmed = () => { | ||||
|     this.setState({ processing: true }); | ||||
|     redirectingAuthorizedFetch(FACTORY_RESET_ENDPOINT, { method: 'POST' }) | ||||
|       .then(response => { | ||||
|         if (response.status === 200) { | ||||
|           this.props.enqueueSnackbar("Factory reset in progress.", { variant: 'error' }); | ||||
|           this.setState({ processing: false, confirmFactoryReset: false }); | ||||
|         } else { | ||||
|           throw Error("Invalid status code: " + response.status); | ||||
|         } | ||||
|       }) | ||||
|       .catch(error => { | ||||
|         this.props.enqueueSnackbar(error.message || "Problem factory resetting device", { variant: 'error' }); | ||||
|         this.setState({ processing: false, confirmRestart: false }); | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|   render() { | ||||
|     const me = this.props.authenticatedContext.me; | ||||
|     return ( | ||||
|       <Fragment> | ||||
|         <List> | ||||
|           {this.createListItems()} | ||||
|         </List> | ||||
|         <FormActions> | ||||
|           <FormButton startIcon={<RefreshIcon />} variant="contained" color="secondary" onClick={this.props.loadData}> | ||||
|             Refresh | ||||
|           </FormButton> | ||||
|           <FormButton startIcon={<AutorenewIcon />} variant="contained" color="primary" onClick={this.onRestart}> | ||||
|             Restart | ||||
|           </FormButton> | ||||
|         </FormActions> | ||||
|         <Box display="flex" flexWrap="wrap"> | ||||
|           <Box flexGrow={1} padding={1}> | ||||
|             <FormButton startIcon={<RefreshIcon />} variant="contained" color="secondary" onClick={this.props.loadData}> | ||||
|               Refresh | ||||
|             </FormButton> | ||||
|           </Box> | ||||
|           {me.admin && | ||||
|             <Box flexWrap="none" padding={1} whiteSpace="nowrap"> | ||||
|               <FormButton startIcon={<PowerSettingsNewIcon />} variant="contained" color="primary" onClick={this.onRestart}> | ||||
|                 Restart | ||||
|               </FormButton> | ||||
|               <ErrorButton startIcon={<SettingsBackupRestoreIcon />} variant="contained" onClick={this.onFactoryReset}> | ||||
|                 Factory reset | ||||
|               </ErrorButton> | ||||
|             </Box> | ||||
|           } | ||||
|         </Box> | ||||
|         {this.renderRestartDialog()} | ||||
|         {this.renderFactoryResetDialog()} | ||||
|       </Fragment> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| export default SystemStatusForm; | ||||
| export default withAuthenticatedContext(SystemStatusForm); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user