diff options
Diffstat (limited to 'modern/src')
-rw-r--r-- | modern/src/DevicesList.js | 78 | ||||
-rw-r--r-- | modern/src/MainPage.js | 22 | ||||
-rw-r--r-- | modern/src/common/selectors.js | 4 | ||||
-rw-r--r-- | modern/src/components/BottomNav.js | 5 | ||||
-rw-r--r-- | modern/src/map/StatusView.js | 3 |
5 files changed, 63 insertions, 49 deletions
diff --git a/modern/src/DevicesList.js b/modern/src/DevicesList.js index 294a9fff..cbf3a0a9 100644 --- a/modern/src/DevicesList.js +++ b/modern/src/DevicesList.js @@ -1,8 +1,7 @@ -import React, { Fragment } from 'react'; +import React, { useRef } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { makeStyles } from '@material-ui/core/styles'; import Avatar from '@material-ui/core/Avatar'; -import Divider from '@material-ui/core/Divider'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemAvatar from '@material-ui/core/ListItemAvatar'; @@ -19,11 +18,16 @@ import { devicesActions } from './store'; import EditCollectionView from './EditCollectionView'; import { useEffectAsync } from './reactHelper'; import { formatPosition } from './common/formatter'; +import { getDevices, getPosition } from './common/selectors'; const useStyles = makeStyles((theme) => ({ list: { maxHeight: '100%', }, + listInner: { + position: 'relative', + margin: theme.spacing(1.5, 0), + }, icon: { width: '25px', height: '25px', @@ -82,43 +86,40 @@ const DeviceRow = ({ data, index, style }) => { const { items } = data; const item = items[index]; - const position = useSelector((state) => state.positions.items[item.id]); + const position = useSelector(getPosition(item.id)); const showIgnition = position?.attributes.hasOwnProperty('ignition') && position.attributes.ignition; return ( <div style={style}> - <Fragment key={index}> - <ListItem button key={item.id} className={classes.listItem} onClick={() => dispatch(devicesActions.select(item))}> - <ListItemAvatar> - <Avatar> - <img className={classes.icon} src={`images/icon/${item.category || 'default'}.svg`} alt="" /> - </Avatar> - </ListItemAvatar> - <ListItemText primary={item.name} secondary={item.status} classes={{ secondary: classes[getStatusColor(item.status)] }} /> - <ListItemSecondaryAction className={classes.indicators}> - {position && ( - <Grid container direction="row" alignItems="center" alignContent="center" spacing={2}> - {showIgnition && ( - <Grid item> - <SvgIcon component={IgnitionIcon} /> - </Grid> - )} - {position.attributes.hasOwnProperty('batteryLevel') && ( - <Grid item container xs alignItems="center" alignContent="center"> - <Grid item> - <span className={classes.batteryText}>{formatPosition(position.attributes.batteryLevel, 'batteryLevel')}</span> - </Grid> - <Grid item> - <BatteryFullIcon className={classes[getBatteryStatus(position.attributes.batteryLevel)]} /> - </Grid> - </Grid> - )} + <ListItem button key={item.id} className={classes.listItem} onClick={() => dispatch(devicesActions.select(item))}> + <ListItemAvatar> + <Avatar> + <img className={classes.icon} src={`images/icon/${item.category || 'default'}.svg`} alt="" /> + </Avatar> + </ListItemAvatar> + <ListItemText primary={item.name} secondary={item.status} classes={{ secondary: classes[getStatusColor(item.status)] }} /> + <ListItemSecondaryAction className={classes.indicators}> + {position && ( + <Grid container direction="row" alignItems="center" alignContent="center" spacing={2}> + {showIgnition && ( + <Grid item> + <SvgIcon component={IgnitionIcon} /> + </Grid> + )} + {position.attributes.hasOwnProperty('batteryLevel') && ( + <Grid item container xs alignItems="center" alignContent="center"> + <Grid item> + <span className={classes.batteryText}>{formatPosition(position.attributes.batteryLevel, 'batteryLevel')}</span> + </Grid> + <Grid item> + <BatteryFullIcon className={classes[getBatteryStatus(position.attributes.batteryLevel)]} /> </Grid> + </Grid> )} - </ListItemSecondaryAction> - </ListItem> - {index < items.length - 1 ? <Divider /> : null} - </Fragment> + </Grid> + )} + </ListItemSecondaryAction> + </ListItem> </div> ); }; @@ -126,8 +127,13 @@ const DeviceRow = ({ data, index, style }) => { const DeviceView = ({ updateTimestamp, onMenuClick }) => { const classes = useStyles(); const dispatch = useDispatch(); + const listInnerEl = useRef(null); - const items = useSelector((state) => Object.values(state.devices.items)); + const items = useSelector(getDevices); + + if (listInnerEl.current) { + listInnerEl.current.className = classes.listInner; + } useEffectAsync(async () => { const response = await fetch('/api/devices'); @@ -145,7 +151,9 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => { height={height} itemCount={items.length} itemData={{ items, onMenuClick }} - itemSize={72 + 1} + itemSize={72} + overscanCount={10} + innerRef={listInnerEl} > {DeviceRow} </FixedSizeList> diff --git a/modern/src/MainPage.js b/modern/src/MainPage.js index 417cdb03..e0707404 100644 --- a/modern/src/MainPage.js +++ b/modern/src/MainPage.js @@ -36,10 +36,10 @@ const useStyles = makeStyles((theme) => ({ bottom: theme.spacing(8), zIndex: 1301, transition: 'transform .5s ease', + backgroundColor: 'white', [theme.breakpoints.down('md')]: { width: '100%', margin: 0, - backgroundColor: 'white', }, }, sidebarCollapsed: { @@ -50,7 +50,7 @@ const useStyles = makeStyles((theme) => ({ }, }, paper: { - borderRadius: '0px', + zIndex: 1, }, toolbar: { display: 'flex', @@ -61,8 +61,6 @@ const useStyles = makeStyles((theme) => ({ }, deviceList: { flex: 1, - overflow: 'auto', - padding: theme.spacing(1.5, 0), }, sidebarToggle: { position: 'absolute', @@ -71,7 +69,13 @@ const useStyles = makeStyles((theme) => ({ borderRadius: '0px', minWidth: 0, [theme.breakpoints.down('md')]: { - left: theme.spacing(0), + left: 0, + }, + }, + sidebarToggleText: { + marginLeft: theme.spacing(1), + [theme.breakpoints.only('xs')]: { + display: 'none', }, }, sidebarToggleBg: { @@ -121,10 +125,10 @@ const MainPage = () => { disableElevation > <ListIcon /> - {!isPhone ? t('deviceTitle') : ''} + <div className={classes.sidebarToggleText}>{t('deviceTitle')}</div> </Button> - <div className={`${classes.sidebar} ${collapsed && classes.sidebarCollapsed}`}> - <Paper className={classes.paper} elevation={isTablet ? 3 : 1}> + <Paper elevation={3} className={`${classes.sidebar} ${collapsed && classes.sidebarCollapsed}`}> + <Paper className={classes.paper} square elevation={3}> <Toolbar className={classes.toolbar} disableGutters> {isTablet && ( <IconButton onClick={handleClose}> @@ -154,7 +158,7 @@ const MainPage = () => { <div className={classes.deviceList}> <DevicesList /> </div> - </div> + </Paper> <BottomNav showOnDesktop /> </div> diff --git a/modern/src/common/selectors.js b/modern/src/common/selectors.js index 44a0c547..0c4c02e1 100644 --- a/modern/src/common/selectors.js +++ b/modern/src/common/selectors.js @@ -1,3 +1,7 @@ export const getIsAdmin = (state) => state.session.user?.administrator; export const getUserId = (state) => state.session.user?.id; + +export const getDevices = (state) => Object.values(state.devices.items); + +export const getPosition = (id) => (state) => state.positions.items[id]; diff --git a/modern/src/components/BottomNav.js b/modern/src/components/BottomNav.js index 6aad1dd9..c47f0f63 100644 --- a/modern/src/components/BottomNav.js +++ b/modern/src/components/BottomNav.js @@ -27,9 +27,6 @@ const useStyles = makeStyles((theme) => ({ width: theme.dimensions.drawerWidthDesktop, }, }, - paper: { - borderRadius: '0px', - }, toolbar: { padding: theme.spacing(0, 2), display: 'flex', @@ -71,7 +68,7 @@ const BottomNav = ({ showOnDesktop }) => { return ( <div className={classes.container}> - <Paper className={classes.paper} elevation={isDesktop ? 1 : 3}> + <Paper square elevation={3}> <Toolbar className={classes.toolbar} disableGutters> {isDesktop ? ( diff --git a/modern/src/map/StatusView.js b/modern/src/map/StatusView.js index 20e5b749..c0f723d2 100644 --- a/modern/src/map/StatusView.js +++ b/modern/src/map/StatusView.js @@ -2,10 +2,11 @@ import React from 'react'; import { useSelector } from 'react-redux'; import t from '../common/localization'; import { formatPosition } from '../common/formatter'; +import { getPosition } from '../common/selectors'; const StatusView = ({ deviceId, onShowDetails }) => { const device = useSelector((state) => state.devices.items[deviceId]); - const position = useSelector((state) => state.positions.items[deviceId]); + const position = useSelector(getPosition(deviceId)); const handleClick = (e) => { e.preventDefault(); |