diff options
author | Anton Tananaev <anton.tananaev@gmail.com> | 2020-09-20 22:39:04 -0700 |
---|---|---|
committer | Anton Tananaev <anton.tananaev@gmail.com> | 2020-09-20 22:39:04 -0700 |
commit | 37dd8129f8e07d00eb93262210bf1ecd4ce95532 (patch) | |
tree | 80f115342fb4624675856a9164970b81f1f5b263 | |
parent | 787c9dc0ec684d3524ec060b6422ffbaea5012ac (diff) | |
download | trackermap-web-37dd8129f8e07d00eb93262210bf1ecd4ce95532.tar.gz trackermap-web-37dd8129f8e07d00eb93262210bf1ecd4ce95532.tar.bz2 trackermap-web-37dd8129f8e07d00eb93262210bf1ecd4ce95532.zip |
Refactor collection editing
-rw-r--r-- | modern/src/DeviceList.js | 111 | ||||
-rw-r--r-- | modern/src/DevicePage.js | 6 | ||||
-rw-r--r-- | modern/src/EditCollectionView.js | 73 | ||||
-rw-r--r-- | modern/src/EditItemView.js (renamed from modern/src/EditPage.js) | 4 | ||||
-rw-r--r-- | modern/src/RemoveDialog.js | 21 | ||||
-rw-r--r-- | modern/src/UserPage.js | 6 |
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> ); } |