Skip to content

Commit 260e9a1

Browse files
authored
Re-engineer UI in TypeScript (#89)
* Re-engineer UI in TypeScript * Switch to named imports where possible * Restructure file system layout * Update depencencies * Update README.md * Change explicit colors for better support for dark theme
1 parent ea6aa78 commit 260e9a1

File tree

121 files changed

+7956
-6469
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+7956
-6469
lines changed

README.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -213,21 +213,36 @@ The framework, and MaterialUI allows for a reasonable degree of customization wi
213213

214214
### Theming the app
215215

216-
The app can be easily themed by editing the [MaterialUI theme](https://material-ui.com/customization/themes/). Edit the theme in ['interface/src/App.js'](interface/src/App.js) as you desire:
216+
The app can be easily themed by editing the [MaterialUI theme](https://material-ui.com/customization/theming/). Edit the theme in ['interface/src/CustomMuiTheme.tsx'](interface/src/CustomMuiTheme.tsx) as you desire. For example, here is a dark theme:
217217

218218
```js
219219
const theme = createMuiTheme({
220220
palette: {
221-
primary: red,
222-
secondary: deepOrange,
223-
highlight_idle: blueGrey[900],
224-
highlight_warn: orange[500],
225-
highlight_error: red[500],
226-
highlight_success: green[500],
227-
},
221+
type:"dark",
222+
primary: {
223+
main: '#222',
224+
},
225+
secondary: {
226+
main: '#666',
227+
},
228+
info: {
229+
main: blueGrey[900]
230+
},
231+
warning: {
232+
main: orange[500]
233+
},
234+
error: {
235+
main: red[500]
236+
},
237+
success: {
238+
main: green[500]
239+
}
240+
}
228241
});
229242
```
230243

244+
![Dark Theme](/media/dark.png?raw=true "Dark Theme")
245+
231246
### Changing the app icon
232247

233248
You can replace the app icon is located at ['interface/public/app/icon.png'](interface/public/app/icon.png) with one of your preference. A 256 x 256 PNG is recommended for best compatibility.
@@ -448,7 +463,7 @@ Serial.println(wifiSettings.ssid);
448463
Configure the SSID and password:
449464

450465
```cpp
451-
WiFiSettings wifiSettings = esp8266React->getWiFiSettingsService()->fetch();
466+
WiFiSettings wifiSettings = esp8266React.getWiFiSettingsService()->fetch();
452467
wifiSettings.ssid = "MyNetworkSSID";
453468
wifiSettings.password = "MySuperSecretPassword";
454469
esp8266React.getWiFiSettingsService()->update(wifiSettings);

interface/.env.development

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Change the IP address to that of your ESP device to enable local development of the UI.
22
# Remember to also enable CORS in platformio.ini before uploading the code to the device.
3-
REACT_APP_ENDPOINT_ROOT=http://192.168.0.29/rest/
3+
REACT_APP_ENDPOINT_ROOT=http://192.168.0.21/rest/

interface/package-lock.json

Lines changed: 5147 additions & 3830 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

interface/package.json

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,51 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@material-ui/core": "^4.7.0",
7-
"@material-ui/icons": "^4.5.1",
8-
"compression-webpack-plugin": "^2.0.0",
6+
"@material-ui/core": "^4.9.1",
7+
"@material-ui/icons": "^4.9.1",
8+
"@types/jwt-decode": "^2.2.1",
9+
"@types/node": "^12.12.22",
10+
"@types/react": "^16.9.17",
11+
"@types/react-dom": "^16.9.4",
12+
"@types/react-material-ui-form-validator": "^2.0.5",
13+
"@types/react-router": "^5.1.3",
14+
"@types/react-router-dom": "^5.1.3",
15+
"compression-webpack-plugin": "^3.0.1",
916
"jwt-decode": "^2.2.0",
1017
"mime-types": "^2.1.25",
1118
"moment": "^2.24.0",
12-
"notistack": "^0.9.6",
13-
"prop-types": "^15.7.2",
14-
"react": "^16.10.1",
15-
"react-dom": "^16.10.1",
19+
"notistack": "^0.9.7",
20+
"react": "^16.12.0",
21+
"react-dom": "^16.12.0",
1622
"react-form-validator-core": "^0.6.4",
17-
"react-jss": "^10.0.0",
18-
"react-material-ui-form-validator": "^2.0.9",
19-
"react-router": "^5.1.1",
20-
"react-router-dom": "^5.1.1",
21-
"react-scripts": "3.0.1",
23+
"react-material-ui-form-validator": "^2.0.10",
24+
"react-router": "^5.1.2",
25+
"react-router-dom": "^5.1.2",
26+
"react-scripts": "3.3.1",
27+
"typescript": "^3.7.5",
2228
"zlib": "^1.0.5"
2329
},
2430
"scripts": {
2531
"start": "react-app-rewired start",
2632
"build": "react-app-rewired build",
27-
"test": "react-app-rewired test --env=jsdom",
2833
"eject": "react-scripts eject"
2934
},
30-
"devDependencies": {
31-
"react-app-rewired": "^2.1.3"
35+
"eslintConfig": {
36+
"extends": "react-app"
37+
},
38+
"browserslist": {
39+
"production": [
40+
">0.2%",
41+
"not dead",
42+
"not op_mini all"
43+
],
44+
"development": [
45+
"last 1 chrome version",
46+
"last 1 firefox version",
47+
"last 1 safari version"
48+
]
3249
},
33-
"browserslist": [
34-
">0.2%",
35-
"not dead",
36-
"not ie <= 11",
37-
"not op_mini all"
38-
]
50+
"devDependencies": {
51+
"react-app-rewired": "^2.1.5"
52+
}
3953
}

interface/src/App.js

Lines changed: 0 additions & 69 deletions
This file was deleted.

interface/src/App.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React, { Component, RefObject } from 'react';
2+
import { Redirect, Route, Switch } from 'react-router';
3+
import { SnackbarProvider } from 'notistack';
4+
5+
import { IconButton } from '@material-ui/core';
6+
import CloseIcon from '@material-ui/icons/Close';
7+
8+
import AppRouting from './AppRouting';
9+
import CustomMuiTheme from './CustomMuiTheme';
10+
import { PROJECT_NAME } from './api';
11+
12+
// this redirect forces a call to authenticationContext.refresh() which invalidates the JWT if it is invalid.
13+
const unauthorizedRedirect = () => <Redirect to="/" />;
14+
15+
class App extends Component {
16+
17+
notistackRef: RefObject<any> = React.createRef();
18+
19+
componentDidMount() {
20+
document.title = PROJECT_NAME;
21+
}
22+
23+
onClickDismiss = (key: string | number | undefined) => () => {
24+
this.notistackRef.current.closeSnackbar(key);
25+
}
26+
27+
render() {
28+
return (
29+
<CustomMuiTheme>
30+
<SnackbarProvider maxSnack={3} anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
31+
ref={this.notistackRef}
32+
action={(key) => (
33+
<IconButton onClick={this.onClickDismiss(key)} size="small">
34+
<CloseIcon />
35+
</IconButton>
36+
)}>
37+
<Switch>
38+
<Route exact path="/unauthorized" component={unauthorizedRedirect} />
39+
<Route component={AppRouting} />
40+
</Switch>
41+
</SnackbarProvider>
42+
</CustomMuiTheme>
43+
);
44+
}
45+
}
46+
47+
export default App

interface/src/AppRouting.js renamed to interface/src/AppRouting.tsx

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
11
import React, { Component } from 'react';
2+
import { Switch, Redirect } from 'react-router';
23

3-
import { Redirect, Switch } from 'react-router';
4-
5-
import { PROJECT_PATH } from './constants/Env';
64
import * as Authentication from './authentication/Authentication';
75
import AuthenticationWrapper from './authentication/AuthenticationWrapper';
8-
import AuthenticatedRoute from './authentication/AuthenticatedRoute';
96
import UnauthenticatedRoute from './authentication/UnauthenticatedRoute';
10-
import SignInPage from './containers/SignInPage';
11-
import WiFiConnection from './sections/WiFiConnection';
12-
import AccessPoint from './sections/AccessPoint';
13-
import NetworkTime from './sections/NetworkTime';
14-
import Security from './sections/Security';
15-
import System from './sections/System';
7+
import AuthenticatedRoute from './authentication/AuthenticatedRoute';
8+
9+
import SignIn from './SignIn';
1610
import ProjectRouting from './project/ProjectRouting';
11+
import WiFiConnection from './wifi/WiFiConnection';
12+
import AccessPoint from './ap/AccessPoint';
13+
import NetworkTime from './ntp/NetworkTime';
14+
import Security from './security/Security';
15+
import System from './system/System';
16+
17+
import { PROJECT_PATH } from './api';
1718

1819
class AppRouting extends Component {
1920

20-
componentWillMount() {
21+
componentDidMount() {
2122
Authentication.clearLoginRedirect();
2223
}
2324

2425
render() {
2526
return (
2627
<AuthenticationWrapper>
2728
<Switch>
28-
<UnauthenticatedRoute exact path="/" component={SignInPage} />
29-
<AuthenticatedRoute exact path="/wifi/*" component={WiFiConnection} />
29+
<UnauthenticatedRoute exact path="/" component={SignIn} />
30+
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/*`} component={ProjectRouting} />
31+
<AuthenticatedRoute exact path="/wifi/*" component={WiFiConnection} />
3032
<AuthenticatedRoute exact path="/ap/*" component={AccessPoint} />
3133
<AuthenticatedRoute exact path="/ntp/*" component={NetworkTime} />
32-
<AuthenticatedRoute exact path="/security/*" component={Security} />
33-
<AuthenticatedRoute exact path="/system/*" component={System} />
34-
<AuthenticatedRoute exact path={`/${PROJECT_PATH}/*`} component={ProjectRouting} />
34+
<AuthenticatedRoute exact path="/security/*" component={Security} />
35+
<AuthenticatedRoute exact path="/system/*" component={System} />
3536
<Redirect to="/" />
3637
</Switch>
3738
</AuthenticationWrapper>

interface/src/CustomMuiTheme.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React, { Component } from 'react';
2+
3+
import { CssBaseline } from '@material-ui/core';
4+
import { MuiThemeProvider, createMuiTheme, StylesProvider } from '@material-ui/core/styles';
5+
import { blueGrey, indigo, orange, red, green } from '@material-ui/core/colors';
6+
7+
const theme = createMuiTheme({
8+
palette: {
9+
primary: indigo,
10+
secondary: blueGrey,
11+
info: {
12+
main: blueGrey[900]
13+
},
14+
warning: {
15+
main: orange[500]
16+
},
17+
error: {
18+
main: red[500]
19+
},
20+
success: {
21+
main: green[500]
22+
}
23+
},
24+
});
25+
26+
export default class CustomMuiTheme extends Component {
27+
28+
render() {
29+
return (
30+
<StylesProvider>
31+
<MuiThemeProvider theme={theme}>
32+
<CssBaseline />
33+
{this.props.children}
34+
</MuiThemeProvider>
35+
</StylesProvider>
36+
);
37+
}
38+
39+
}

0 commit comments

Comments
 (0)