aboutsummaryrefslogtreecommitdiff
path: root/modern/src/DevicesList.js
diff options
context:
space:
mode:
Diffstat (limited to 'modern/src/DevicesList.js')
-rw-r--r--modern/src/DevicesList.js141
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}
>