diff options
Diffstat (limited to 'modern/src/DevicesList.js')
-rw-r--r-- | modern/src/DevicesList.js | 141 |
1 files changed, 99 insertions, 42 deletions
diff --git a/modern/src/DevicesList.js b/modern/src/DevicesList.js index e06fd58..b98956c 100644 --- a/modern/src/DevicesList.js +++ b/modern/src/DevicesList.js @@ -1,7 +1,6 @@ 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 List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; import ListItemAvatar from '@material-ui/core/ListItemAvatar'; @@ -14,11 +13,19 @@ import AutoSizer from 'react-virtualized-auto-sizer'; import BatteryFullIcon from '@material-ui/icons/BatteryFull'; import { ReactComponent as IgnitionIcon } from '../public/images/ignition.svg'; -import { devicesActions } from './store'; +import FiberManualRecordIcon from '@material-ui/icons/FiberManualRecord'; +import PersonIcon from '@material-ui/icons/Person'; +import SpeedIcon from '@material-ui/icons/Speed'; +import CalendarTodayIcon from '@material-ui/icons/CalendarToday'; +import LockIcon from '@material-ui/icons/Lock'; +import LockOpenIcon from '@material-ui/icons/LockOpen'; + +import { devicesActions, uiActions } from './store'; import EditCollectionView from './EditCollectionView'; import { useEffectAsync } from './reactHelper'; -import { formatPosition } from './common/formatter'; -import { getDevices, getPosition } from './common/selectors'; +import { formatPosition, formatSpeed, formatHours } from './common/formatter'; +import { useAttributePreference } from './common/preferences'; +import { getDevices, getFilteredDevices, getFilterTerm, getPosition } from './common/selectors'; import { useTranslation } from './LocalizationProvider'; const useStyles = makeStyles((theme) => ({ @@ -30,15 +37,21 @@ const useStyles = makeStyles((theme) => ({ margin: theme.spacing(1.5, 0), }, icon: { - width: '25px', - height: '25px', - filter: 'brightness(0) invert(1)', + width: '40px', + height: '40px', + }, + statusIcon: { + paddingRight: '5px', }, listItem: { backgroundColor: 'white', '&:hover': { backgroundColor: 'white', }, + height: '150px', + }, + listItemSecondary: { + fontSize: '0.92rem', }, batteryText: { fontSize: '0.75rem', @@ -59,18 +72,6 @@ const useStyles = makeStyles((theme) => ({ }, })); -const getStatusColor = (status) => { - switch (status) { - case 'online': - return 'green'; - case 'offline': - return 'red'; - case 'unknown': - default: - return 'gray'; - } -}; - const getBatteryStatus = (batteryLevel) => { if (batteryLevel >= 70) { return 'green'; @@ -86,39 +87,91 @@ const DeviceRow = ({ data, index, style }) => { const dispatch = useDispatch(); const t = useTranslation(); + const speedUnit = useAttributePreference('speedUnit'); + const { items } = data; const item = items[index]; const position = useSelector(getPosition(item.id)); const showIgnition = position?.attributes.hasOwnProperty('ignition') && position.attributes.ignition; + const statusColor = () => { + if (position && position.speed >= 2) { + return 'primary'; + } else { + return 'error'; + } + }; + return ( <div style={style}> - <ListItem button key={item.id} className={classes.listItem} onClick={() => dispatch(devicesActions.select(item))}> + <ListItem button key={item.id} className={classes.listItem} onClick={() => { + dispatch(devicesActions.select(item)); + dispatch(uiActions.setCollapsed(true)); + setTimeout(() => { + dispatch(devicesActions.unselect()); + }, 1000); + }}> + {/* Avatar */} <ListItemAvatar> - <Avatar> - <img className={classes.icon} src={`images/icon/${item.category || 'default'}.svg`} alt="" /> - </Avatar> + <img className={classes.icon} src={`images/icon/${(item.category || 'default').toLowerCase()}.png`} alt="" /> </ListItemAvatar> - <ListItemText primary={item.name} secondary={item.status} classes={{ secondary: classes[getStatusColor(item.status)] }} /> + + {/* Status icon */} + <ListItemText primary={ + <> + <FiberManualRecordIcon fontSize="inherit" color={statusColor()} classes={{ colorPrimary: classes.green }} /> + {position && position.attributes.out1 == false && ( + <LockOpenIcon fontSize="inherit" color="primary" classes={{ colorPrimary: classes.green }} /> + )} + {position && position.attributes.out1 == true && ( + <LockIcon fontSize="inherit" color="error" /> + )} + {` ${item.name}`} + </>} secondary={( + <> + {/* Contact */} + {item.contact && ( + <> + <PersonIcon fontSize="inherit" /> {item.contact}<br /> + </> + )} + {position && ( + <> + {/* Speed */} + <SpeedIcon fontSize="inherit" /> {formatSpeed(position.speed, speedUnit, t)}<br /> + {/* Datetime */} + <CalendarTodayIcon fontSize="inherit" /> {formatPosition(position, 'fixTime', t)} + {/* Hours */} + {item.category + && (item.category.toLowerCase() === 'backhoe' || item.category.toLowerCase() === 'tractor' ) + && position.attributes.hours + && position.attributes.hours > 1 + && ` (${formatHours(position.attributes.hours, t)})`} + </> + )} + </> + )} classes={{ secondary: classes.listItemSecondary }} /> <ListItemSecondaryAction className={classes.indicators}> {position && ( - <Grid container direction="row" alignItems="center" alignContent="center" spacing={2}> - {showIgnition && ( - <Grid item> - <SvgIcon component={IgnitionIcon} /> + <Grid container direction="row" alignItems="center" alignContent="center" spacing={2}> + {/* Ignition */} + {showIgnition && ( + <Grid item> + <SvgIcon component={IgnitionIcon} /> + </Grid> + )} + {/* Battery level */} + {position.attributes.hasOwnProperty('batteryLevel') && ( + <Grid item container xs alignItems="center" alignContent="center"> + <Grid item> + <span className={classes.batteryText}>{formatPosition(position.attributes.batteryLevel, 'batteryLevel', t)}</span> + </Grid> + <Grid item> + <BatteryFullIcon className={classes[getBatteryStatus(position.attributes.batteryLevel)]} /> + </Grid> + </Grid> + )} </Grid> - )} - {position.attributes.hasOwnProperty('batteryLevel') && ( - <Grid item container xs alignItems="center" alignContent="center"> - <Grid item> - <span className={classes.batteryText}>{formatPosition(position.attributes.batteryLevel, 'batteryLevel', t)}</span> - </Grid> - <Grid item> - <BatteryFullIcon className={classes[getBatteryStatus(position.attributes.batteryLevel)]} /> - </Grid> - </Grid> - )} - </Grid> )} </ListItemSecondaryAction> </ListItem> @@ -131,7 +184,11 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => { const dispatch = useDispatch(); const listInnerEl = useRef(null); - const items = useSelector(getDevices); + const filterTerm = useSelector(getFilterTerm); + const filteredItems = useSelector(getFilteredDevices); + const unfilteredItems = useSelector(getDevices); + + const items = (filterTerm.length > 0 ? filteredItems : unfilteredItems).sort((a, b) => a.name.localeCompare(b.name)); if (listInnerEl.current) { listInnerEl.current.className = classes.listInner; @@ -153,7 +210,7 @@ const DeviceView = ({ updateTimestamp, onMenuClick }) => { height={height} itemCount={items.length} itemData={{ items, onMenuClick }} - itemSize={72} + itemSize={150} overscanCount={10} innerRef={listInnerEl} > |