aboutsummaryrefslogtreecommitdiff
path: root/modern/src
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2020-09-20 22:39:04 -0700
committerAnton Tananaev <anton.tananaev@gmail.com>2020-09-20 22:39:04 -0700
commit37dd8129f8e07d00eb93262210bf1ecd4ce95532 (patch)
tree80f115342fb4624675856a9164970b81f1f5b263 /modern/src
parent787c9dc0ec684d3524ec060b6422ffbaea5012ac (diff)
downloadtrackermap-web-37dd8129f8e07d00eb93262210bf1ecd4ce95532.tar.gz
trackermap-web-37dd8129f8e07d00eb93262210bf1ecd4ce95532.tar.bz2
trackermap-web-37dd8129f8e07d00eb93262210bf1ecd4ce95532.zip
Refactor collection editing
Diffstat (limited to 'modern/src')
-rw-r--r--modern/src/DeviceList.js111
-rw-r--r--modern/src/DevicePage.js6
-rw-r--r--modern/src/EditCollectionView.js73
-rw-r--r--modern/src/EditItemView.js (renamed from modern/src/EditPage.js)4
-rw-r--r--modern/src/RemoveDialog.js21
-rw-r--r--modern/src/UserPage.js6
6 files changed, 122 insertions, 99 deletions
diff --git a/modern/src/DeviceList.js b/modern/src/DeviceList.js
index 66b94063..b7c15dc4 100644
--- a/modern/src/DeviceList.js
+++ b/modern/src/DeviceList.js
@@ -1,109 +1,60 @@
-import React, { Fragment, useState } from 'react';
+import React, { Fragment } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { makeStyles } from '@material-ui/core/styles';
-import { useHistory } from 'react-router-dom';
import Avatar from '@material-ui/core/Avatar';
import Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
-import Menu from '@material-ui/core/Menu';
-import MenuItem from '@material-ui/core/MenuItem';
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
import ListItemText from '@material-ui/core/ListItemText';
import LocationOnIcon from '@material-ui/icons/LocationOn';
import MoreVertIcon from '@material-ui/icons/MoreVert';
-import Fab from '@material-ui/core/Fab';
-import AddIcon from '@material-ui/icons/Add';
import { devicesActions } from './store';
-import t from './common/localization';
-import RemoveDialog from './RemoveDialog';
+import EditCollectionView from './EditCollectionView';
-const useStyles = makeStyles(theme => ({
+const useStyles = makeStyles(() => ({
list: {
maxHeight: '100%',
overflow: 'auto',
},
- fab: {
- position: 'absolute',
- bottom: theme.spacing(2),
- right: theme.spacing(2),
- },
}));
-const DeviceList = () => {
- const [menuDeviceId, setMenuDeviceId] = useState(null);
- const [menuAnchorEl, setMenuAnchorEl] = useState(null);
- const [removeDialogOpen, setRemoveDialogOpen] = useState(false);
- const devices = useSelector(state => Object.values(state.devices.items));
- const dispatch = useDispatch();
+const DeviceView = ({ onMenuClick }) => {
const classes = useStyles();
- const history = useHistory();
-
- const handleMenuClick = (event, deviceId) => {
- setMenuDeviceId(deviceId);
- setMenuAnchorEl(event.currentTarget);
- }
-
- const handleMenuClose = () => {
- setMenuAnchorEl(null);
- }
-
- const handleMenuEdit = () => {
- history.push(`/device/${menuDeviceId}`);
- handleMenuClose();
- }
-
- const handleMenuRemove = () => {
- setRemoveDialogOpen(true);
- handleMenuClose();
- }
+ const dispatch = useDispatch();
- const handleAdd = () => {
- history.push('/device');
- handleMenuClose();
- }
+ const items = useSelector(state => Object.values(state.devices.items));
- const handleRemoveResult = (removed) => {
- setRemoveDialogOpen(false);
- if (removed) {
- dispatch(devicesActions.remove(menuDeviceId));
- }
- }
+ return (
+ <List className={classes.list}>
+ {items.map((item, index, list) => (
+ <Fragment key={item.id}>
+ <ListItem button key={item.id} onClick={() => dispatch(devicesActions.select(item))}>
+ <ListItemAvatar>
+ <Avatar>
+ <LocationOnIcon />
+ </Avatar>
+ </ListItemAvatar>
+ <ListItemText primary={item.name} secondary={item.uniqueId} />
+ <ListItemSecondaryAction>
+ <IconButton onClick={(event) => onMenuClick(event.currentTarget, item.id)}>
+ <MoreVertIcon />
+ </IconButton>
+ </ListItemSecondaryAction>
+ </ListItem>
+ {index < list.length - 1 ? <Divider /> : null}
+ </Fragment>
+ ))}
+ </List>
+ );
+}
+const DeviceList = () => {
return (
- <>
- <List className={classes.list}>
- {devices.map((device, index, list) => (
- <Fragment key={device.id}>
- <ListItem button key={device.id} onClick={() => dispatch(devicesActions.select(device))}>
- <ListItemAvatar>
- <Avatar>
- <LocationOnIcon />
- </Avatar>
- </ListItemAvatar>
- <ListItemText primary={device.name} secondary={device.uniqueId} />
- <ListItemSecondaryAction>
- <IconButton onClick={(event) => handleMenuClick(event, device.id)}>
- <MoreVertIcon />
- </IconButton>
- </ListItemSecondaryAction>
- </ListItem>
- {index < list.length - 1 ? <Divider /> : null}
- </Fragment>
- ))}
- </List>
- <Fab size="medium" color="primary" className={classes.fab} onClick={handleAdd}>
- <AddIcon />
- </Fab>
- <Menu id="device-menu" anchorEl={menuAnchorEl} keepMounted open={Boolean(menuAnchorEl)} onClose={handleMenuClose}>
- <MenuItem onClick={handleMenuEdit}>{t('sharedEdit')}</MenuItem>
- <MenuItem onClick={handleMenuRemove}>{t('sharedRemove')}</MenuItem>
- </Menu>
- <RemoveDialog deviceId={menuDeviceId} open={removeDialogOpen} onResult={handleRemoveResult} />
- </>
+ <EditCollectionView content={DeviceView} editPath="/device" endpoint="devices" />
);
}
diff --git a/modern/src/DevicePage.js b/modern/src/DevicePage.js
index 14e978ec..7c963b02 100644
--- a/modern/src/DevicePage.js
+++ b/modern/src/DevicePage.js
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
import t from './common/localization';
-import EditPage from './EditPage';
+import EditItemView from './EditItemView';
const DevicePage = () => {
const [item, setItem] = useState();
@@ -18,7 +18,7 @@ const DevicePage = () => {
};
return (
- <EditPage endpoint="devices" setItem={setItem} getItem={getItem}>
+ <EditItemView endpoint="devices" setItem={setItem} getItem={getItem}>
{item &&
<>
<TextField
@@ -37,7 +37,7 @@ const DevicePage = () => {
variant="filled" />
</>
}
- </EditPage>
+ </EditItemView>
);
}
diff --git a/modern/src/EditCollectionView.js b/modern/src/EditCollectionView.js
new file mode 100644
index 00000000..59ea2db0
--- /dev/null
+++ b/modern/src/EditCollectionView.js
@@ -0,0 +1,73 @@
+import React, { useState } from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import { useHistory } from 'react-router-dom';
+import Menu from '@material-ui/core/Menu';
+import MenuItem from '@material-ui/core/MenuItem';
+import Fab from '@material-ui/core/Fab';
+import AddIcon from '@material-ui/icons/Add';
+
+import t from './common/localization';
+import RemoveDialog from './RemoveDialog';
+
+const useStyles = makeStyles(theme => ({
+ fab: {
+ position: 'absolute',
+ bottom: theme.spacing(2),
+ right: theme.spacing(2),
+ },
+}));
+
+const EditCollectionView = ({ content, editPath, endpoint }) => {
+ const classes = useStyles();
+ const history = useHistory();
+
+ const [selectedId, setSelectedId] = useState(null);
+ const [selectedAnchorEl, setSelectedAnchorEl] = useState(null);
+ const [removeDialogShown, setRemoveDialogShown] = useState(false);
+
+ const menuShow = (anchorId, itemId) => {
+ setSelectedAnchorEl(anchorId);
+ setSelectedId(itemId);
+ }
+
+ const menuHide = () => {
+ setSelectedAnchorEl(null);
+ }
+
+ const handleAdd = () => {
+ history.push(editPath);
+ menuHide();
+ }
+
+ const handleEdit = () => {
+ history.push(`${editPath}/${selectedId}`);
+ menuHide();
+ }
+
+ const handleRemove = () => {
+ setRemoveDialogShown(true);
+ menuHide();
+ }
+
+ const handleRemoveResult = () => {
+ setRemoveDialogShown(false);
+ }
+
+ const Content = content;
+
+ return (
+ <>
+ <Content onMenuClick={menuShow} />
+ <Fab size="medium" color="primary" className={classes.fab} onClick={handleAdd}>
+ <AddIcon />
+ </Fab>
+ <Menu open={!!selectedAnchorEl} anchorEl={selectedAnchorEl} onClose={menuHide}>
+ <MenuItem onClick={handleEdit}>{t('sharedEdit')}</MenuItem>
+ <MenuItem onClick={handleRemove}>{t('sharedRemove')}</MenuItem>
+ </Menu>
+ <RemoveDialog open={removeDialogShown} endpoint={endpoint} itemId={selectedId} onResult={handleRemoveResult} />
+ </>
+ );
+}
+
+export default EditCollectionView;
diff --git a/modern/src/EditPage.js b/modern/src/EditItemView.js
index 23e8c07f..db8cd0dc 100644
--- a/modern/src/EditPage.js
+++ b/modern/src/EditItemView.js
@@ -22,7 +22,7 @@ const useStyles = makeStyles(theme => ({
},
}));
-const EditPage = ({ children, endpoint, setItem, getItem }) => {
+const EditItemView = ({ children, endpoint, setItem, getItem }) => {
const history = useHistory();
const classes = useStyles();
const { id } = useParams();
@@ -77,4 +77,4 @@ const EditPage = ({ children, endpoint, setItem, getItem }) => {
);
}
-export default EditPage;
+export default EditItemView;
diff --git a/modern/src/RemoveDialog.js b/modern/src/RemoveDialog.js
index bca936f4..57be7871 100644
--- a/modern/src/RemoveDialog.js
+++ b/modern/src/RemoveDialog.js
@@ -6,26 +6,25 @@ import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
-const RemoveDialog = (props) => {
- const handleRemove = () => {
- fetch(`/api/devices/${props.deviceId}`, { method: 'DELETE' }).then(response => {
- if (response.ok) {
- props.onResult(true);
- }
- });
- }
+const RemoveDialog = ({ open, endpoint, itemId, onResult }) => {
+ const handleRemove = async () => {
+ const response = fetch(`/api/${endpoint}/${itemId}`, { method: 'DELETE' })
+ if (response.ok) {
+ onResult(true);
+ }
+ };
return (
<>
<Dialog
- open={props.open}
- onClose={() => { props.onResult(false) }}>
+ open={open}
+ onClose={() => { onResult(false) }}>
<DialogContent>
<DialogContentText>{t('sharedRemoveConfirm')}</DialogContentText>
</DialogContent>
<DialogActions>
<Button color="primary" onClick={handleRemove}>{t('sharedRemove')}</Button>
- <Button autoFocus onClick={() => props.onResult(false)}>{t('sharedCancel')}</Button>
+ <Button autoFocus onClick={() => onResult(false)}>{t('sharedCancel')}</Button>
</DialogActions>
</Dialog>
</>
diff --git a/modern/src/UserPage.js b/modern/src/UserPage.js
index da8ba1b6..4b58ba81 100644
--- a/modern/src/UserPage.js
+++ b/modern/src/UserPage.js
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
import TextField from '@material-ui/core/TextField';
import t from './common/localization';
-import EditPage from './EditPage';
+import EditItemView from './EditItemView';
const UserPage = () => {
const [item, setItem] = useState();
@@ -20,7 +20,7 @@ const UserPage = () => {
};
return (
- <EditPage endpoint="users" setItem={setItem} getItem={getItem}>
+ <EditItemView endpoint="users" setItem={setItem} getItem={getItem}>
{item &&
<>
<TextField
@@ -46,7 +46,7 @@ const UserPage = () => {
variant="filled" />
</>
}
- </EditPage>
+ </EditItemView>
);
}