aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modern/src/App.js2
-rw-r--r--modern/src/DevicePage.js123
-rw-r--r--modern/src/EditPage.js80
-rw-r--r--modern/src/UserPage.js53
4 files changed, 165 insertions, 93 deletions
diff --git a/modern/src/App.js b/modern/src/App.js
index 0f2a69b..a4c00e2 100644
--- a/modern/src/App.js
+++ b/modern/src/App.js
@@ -6,6 +6,7 @@ import LoginPage from './LoginPage';
import RouteReportPage from './reports/RouteReportPage';
import UsersPage from './admin/UsersPage';
import DevicePage from './DevicePage';
+import UserPage from './UserPage';
import SocketController from './SocketController';
const App = () => {
@@ -16,6 +17,7 @@ const App = () => {
<Switch>
<Route exact path='/' component={MainPage} />
<Route exact path='/login' component={LoginPage} />
+ <Route exact path='/user/:id?' component={UserPage} />
<Route exact path='/device/:id?' component={DevicePage} />
<Route exact path='/reports/route' component={RouteReportPage} />
<Route exact path='/admin/users' component={UsersPage} />
diff --git a/modern/src/DevicePage.js b/modern/src/DevicePage.js
index ee52549..14e978e 100644
--- a/modern/src/DevicePage.js
+++ b/modern/src/DevicePage.js
@@ -1,106 +1,43 @@
-import React, { useEffect, useState } from 'react';
-import MainToobar from './MainToolbar';
-import { useHistory, useParams } from 'react-router-dom';
-import { makeStyles } from '@material-ui/core/styles';
+import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
-import Container from '@material-ui/core/Container';
-import Button from '@material-ui/core/Button';
-import FormControl from '@material-ui/core/FormControl';
import t from './common/localization';
-
-const useStyles = makeStyles(theme => ({
- container: {
- marginTop: theme.spacing(2),
- },
- buttons: {
- display: 'flex',
- justifyContent: 'space-evenly',
- '& > *': {
- flexBasis: '33%',
- },
- },
-}));
+import EditPage from './EditPage';
const DevicePage = () => {
- const history = useHistory();
- const classes = useStyles();
- const { id } = useParams();
- const [device, setDevice] = useState();
+ const [item, setItem] = useState();
+
const [name, setName] = useState('');
const [uniqueId, setUniqueId] = useState('');
- useEffect(() => {
- fetch(`/api/devices/${id}`).then(response => {
- if (response.ok) {
- response.json().then(setDevice);
- }
- });
- }, [id]);
-
- const handleSave = () => {
- const updatedDevice = id ? device : {};
- updatedDevice.name = name || updatedDevice.name;
- updatedDevice.uniqueId = uniqueId || updatedDevice.uniqueId;
-
- let request;
- if (id) {
- request = fetch(`/api/devices/${id}`, {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(updatedDevice),
- });
- } else {
- request = fetch('/api/devices', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(updatedDevice),
- });
- }
-
- request.then(response => {
- if (response.ok) {
- history.goBack();
- }
- });
- }
+ const getItem = () => {
+ const updatedItem = item;
+ updatedItem.name = name;
+ updatedItem.uniqueId = uniqueId;
+ return updatedItem;
+ };
return (
- <>
- <MainToobar history={history} />
- <Container maxWidth='xs' className={classes.container}>
- <form>
- {(!id || device) &&
- <TextField
- margin='normal'
- fullWidth
- defaultValue={device && device.name}
- onChange={(event) => setName(event.target.value)}
- label={t('sharedName')}
- variant='filled' />
- }
- {(!id || device) &&
- <TextField
- margin='normal'
- fullWidth
- defaultValue={device && device.uniqueId}
- onChange={(event) => setUniqueId(event.target.value)}
- label={t('deviceIdentifier')}
- variant='filled' />
- }
- <FormControl fullWidth margin='normal'>
- <div className={classes.buttons}>
- <Button type='button' color='primary' variant='outlined' onClick={() => history.goBack()}>
- {t('sharedCancel')}
- </Button>
- <Button type='button' color='primary' variant='contained' onClick={handleSave}>
- {t('sharedSave')}
- </Button>
- </div>
- </FormControl>
- </form>
- </Container>
- </>
+ <EditPage endpoint="devices" setItem={setItem} getItem={getItem}>
+ {item &&
+ <>
+ <TextField
+ margin="normal"
+ fullWidth
+ defaultValue={item.name}
+ onChange={(event) => setName(event.target.value)}
+ label={t('sharedName')}
+ variant="filled" />
+ <TextField
+ margin="normal"
+ fullWidth
+ defaultValue={item.uniqueId}
+ onChange={(event) => setUniqueId(event.target.value)}
+ label={t('deviceIdentifier')}
+ variant="filled" />
+ </>
+ }
+ </EditPage>
);
}
diff --git a/modern/src/EditPage.js b/modern/src/EditPage.js
new file mode 100644
index 0000000..23e8c07
--- /dev/null
+++ b/modern/src/EditPage.js
@@ -0,0 +1,80 @@
+import React from 'react';
+import MainToobar from './MainToolbar';
+import { useHistory, useParams } from 'react-router-dom';
+import { makeStyles } from '@material-ui/core/styles';
+import Container from '@material-ui/core/Container';
+import Button from '@material-ui/core/Button';
+import FormControl from '@material-ui/core/FormControl';
+
+import t from './common/localization';
+import { useEffectAsync } from './reactHelper';
+
+const useStyles = makeStyles(theme => ({
+ container: {
+ marginTop: theme.spacing(2),
+ },
+ buttons: {
+ display: 'flex',
+ justifyContent: 'space-evenly',
+ '& > *': {
+ flexBasis: '33%',
+ },
+ },
+}));
+
+const EditPage = ({ children, endpoint, setItem, getItem }) => {
+ const history = useHistory();
+ const classes = useStyles();
+ const { id } = useParams();
+
+ useEffectAsync(async () => {
+ if (id) {
+ const response = await fetch(`/api/${endpoint}/${id}`);
+ if (response.ok) {
+ setItem(await response.json());
+ }
+ } else {
+ setItem({});
+ }
+ }, [id]);
+
+ const handleSave = async () => {
+ let url = `/api/${endpoint}`;
+ if (id) {
+ url += `/${id}`;
+ }
+
+ const response = await fetch(url, {
+ method: !id ? 'POST' : 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(getItem()),
+ });
+
+ if (response.ok) {
+ history.goBack();
+ }
+ };
+
+ return (
+ <>
+ <MainToobar history={history} />
+ <Container maxWidth='xs' className={classes.container}>
+ <form>
+ {children}
+ <FormControl fullWidth margin='normal'>
+ <div className={classes.buttons}>
+ <Button type='button' color='primary' variant='outlined' onClick={() => history.goBack()}>
+ {t('sharedCancel')}
+ </Button>
+ <Button type='button' color='primary' variant='contained' onClick={handleSave}>
+ {t('sharedSave')}
+ </Button>
+ </div>
+ </FormControl>
+ </form>
+ </Container>
+ </>
+ );
+}
+
+export default EditPage;
diff --git a/modern/src/UserPage.js b/modern/src/UserPage.js
new file mode 100644
index 0000000..da8ba1b
--- /dev/null
+++ b/modern/src/UserPage.js
@@ -0,0 +1,53 @@
+import React, { useState } from 'react';
+import TextField from '@material-ui/core/TextField';
+
+import t from './common/localization';
+import EditPage from './EditPage';
+
+const UserPage = () => {
+ const [item, setItem] = useState();
+
+ const [name, setName] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+
+ const getItem = () => {
+ const updatedItem = item;
+ updatedItem.name = name;
+ updatedItem.email = email;
+ updatedItem.password = password;
+ return updatedItem;
+ };
+
+ return (
+ <EditPage endpoint="users" setItem={setItem} getItem={getItem}>
+ {item &&
+ <>
+ <TextField
+ margin="normal"
+ fullWidth
+ defaultValue={item.name}
+ onChange={(event) => setName(event.target.value)}
+ label={t('sharedName')}
+ variant="filled" />
+ <TextField
+ margin="normal"
+ fullWidth
+ defaultValue={item.email}
+ onChange={(event) => setEmail(event.target.value)}
+ label={t('userEmail')}
+ variant="filled" />
+ <TextField
+ margin="normal"
+ fullWidth
+ type="password"
+ onChange={(event) => setPassword(event.target.value)}
+ label={t('userPassword')}
+ variant="filled" />
+ </>
+ }
+ </EditPage>
+ );
+}
+
+export default UserPage;