aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-10-23 08:25:18 -0700
committerAnton Tananaev <anton@traccar.org>2022-10-23 08:25:18 -0700
commit0a89d1ecae4e70b7c694b85b1696bf0c24b5c8d1 (patch)
treeca7944be8e954057fe4e9d4a1db3f3c0c29af393
parent0510fac36d0d852984b567104e2c9f0df9906492 (diff)
downloadtrackermap-web-0a89d1ecae4e70b7c694b85b1696bf0c24b5c8d1.tar.gz
trackermap-web-0a89d1ecae4e70b7c694b85b1696bf0c24b5c8d1.tar.bz2
trackermap-web-0a89d1ecae4e70b7c694b85b1696bf0c24b5c8d1.zip
Implement filter popover
-rw-r--r--modern/src/main/DeviceList.js25
-rw-r--r--modern/src/main/DeviceRow.js7
-rw-r--r--modern/src/main/MainPage.js1
-rw-r--r--modern/src/main/MainToolbar.js47
4 files changed, 53 insertions, 27 deletions
diff --git a/modern/src/main/DeviceList.js b/modern/src/main/DeviceList.js
index 6672ac46..eb51232f 100644
--- a/modern/src/main/DeviceList.js
+++ b/modern/src/main/DeviceList.js
@@ -1,7 +1,6 @@
import React, { useEffect, useRef, useState } from 'react';
import { useDispatch } from 'react-redux';
import makeStyles from '@mui/styles/makeStyles';
-import { List } from '@mui/material';
import { FixedSizeList } from 'react-window';
import AutoSizer from 'react-virtualized-auto-sizer';
import { devicesActions } from '../store';
@@ -48,19 +47,17 @@ const DeviceList = ({ devices }) => {
return (
<AutoSizer className={classes.list}>
{({ height, width }) => (
- <List disablePadding>
- <FixedSizeList
- width={width}
- height={height}
- itemCount={devices.length}
- itemData={devices}
- itemSize={72}
- overscanCount={10}
- innerRef={listInnerEl}
- >
- {DeviceRow}
- </FixedSizeList>
- </List>
+ <FixedSizeList
+ width={width}
+ height={height}
+ itemCount={devices.length}
+ itemData={devices}
+ itemSize={72}
+ overscanCount={10}
+ innerRef={listInnerEl}
+ >
+ {DeviceRow}
+ </FixedSizeList>
)}
</AutoSizer>
);
diff --git a/modern/src/main/DeviceRow.js b/modern/src/main/DeviceRow.js
index 978813b4..11dbfdcb 100644
--- a/modern/src/main/DeviceRow.js
+++ b/modern/src/main/DeviceRow.js
@@ -28,12 +28,6 @@ const useStyles = makeStyles((theme) => ({
height: '25px',
filter: 'brightness(0) invert(1)',
},
- listItem: {
- backgroundColor: 'white',
- '&:hover': {
- backgroundColor: 'white',
- },
- },
batteryText: {
fontSize: '0.75rem',
fontWeight: 'normal',
@@ -98,7 +92,6 @@ const DeviceRow = ({ data, index, style }) => {
<div style={style}>
<ListItemButton
key={item.id}
- className={classes.listItem}
onClick={() => dispatch(devicesActions.select(item.id))}
disabled={!admin && item.disabled}
>
diff --git a/modern/src/main/MainPage.js b/modern/src/main/MainPage.js
index a296d5f6..9a21d570 100644
--- a/modern/src/main/MainPage.js
+++ b/modern/src/main/MainPage.js
@@ -105,6 +105,7 @@ const MainPage = () => {
<div className={classes.sidebar}>
<Paper square elevation={3} className={classes.header}>
<MainToolbar
+ filteredDevices={filteredDevices}
devicesOpen={devicesOpen}
setDevicesOpen={setDevicesOpen}
filter={filter}
diff --git a/modern/src/main/MainToolbar.js b/modern/src/main/MainToolbar.js
index 015e86ba..2aa604e8 100644
--- a/modern/src/main/MainToolbar.js
+++ b/modern/src/main/MainToolbar.js
@@ -2,15 +2,16 @@ import React, { useState, useRef } from 'react';
import { useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import {
- Toolbar, IconButton, OutlinedInput, InputAdornment, Popover, FormControl, InputLabel, Select, MenuItem, FormGroup, FormControlLabel, Checkbox, Badge,
+ Toolbar, IconButton, OutlinedInput, InputAdornment, Popover, FormControl, InputLabel, Select, MenuItem, FormGroup, FormControlLabel, Checkbox, Badge, ListItemButton, ListItemText,
} from '@mui/material';
-import { makeStyles } from '@mui/styles';
+import { makeStyles, useTheme } from '@mui/styles';
import MapIcon from '@mui/icons-material/Map';
import ViewListIcon from '@mui/icons-material/ViewList';
import AddIcon from '@mui/icons-material/Add';
import TuneIcon from '@mui/icons-material/Tune';
import { useTranslation } from '../common/components/LocalizationProvider';
import { useDeviceReadonly } from '../common/util/permissions';
+import DeviceRow from './DeviceRow';
const useStyles = makeStyles((theme) => ({
toolbar: {
@@ -27,6 +28,7 @@ const useStyles = makeStyles((theme) => ({
}));
const MainToolbar = ({
+ filteredDevices,
devicesOpen,
setDevicesOpen,
filter,
@@ -37,6 +39,7 @@ const MainToolbar = ({
setFilterMap,
}) => {
const classes = useStyles();
+ const theme = useTheme();
const navigate = useNavigate();
const t = useTranslation();
@@ -45,24 +48,28 @@ const MainToolbar = ({
const groups = useSelector((state) => state.groups.items);
const devices = useSelector((state) => state.devices.items);
- const filterRef = useRef();
+ const toolbarRef = useRef();
+ const inputRef = useRef();
const [filterAnchorEl, setFilterAnchorEl] = useState(null);
+ const [devicesAnchorEl, setDevicesAnchorEl] = useState(null);
const deviceStatusCount = (status) => Object.values(devices).filter((d) => d.status === status).length;
return (
- <Toolbar className={classes.toolbar}>
+ <Toolbar ref={toolbarRef} className={classes.toolbar}>
<IconButton edge="start" onClick={() => setDevicesOpen(!devicesOpen)}>
{devicesOpen ? <MapIcon /> : <ViewListIcon />}
</IconButton>
<OutlinedInput
- ref={filterRef}
+ ref={inputRef}
placeholder={t('sharedSearchDevices')}
value={filter.keyword}
onChange={(e) => setFilter({ ...filter, keyword: e.target.value })}
+ onFocus={() => setDevicesAnchorEl(toolbarRef.current)}
+ onBlur={() => setDevicesAnchorEl(null)}
endAdornment={(
<InputAdornment position="end">
- <IconButton size="small" edge="end" onClick={() => setFilterAnchorEl(filterRef.current)}>
+ <IconButton size="small" edge="end" onClick={() => setFilterAnchorEl(inputRef.current)}>
<Badge color="info" variant="dot" invisible={!filter.statuses.length && !filter.groups.length}>
<TuneIcon fontSize="small" />
</Badge>
@@ -73,6 +80,34 @@ const MainToolbar = ({
fullWidth
/>
<Popover
+ open={!!devicesAnchorEl && !devicesOpen}
+ anchorEl={devicesAnchorEl}
+ onClose={() => setDevicesAnchorEl(null)}
+ anchorOrigin={{
+ vertical: 'bottom',
+ horizontal: Number(theme.spacing(2).slice(0, -2)),
+ }}
+ marginThreshold={0}
+ PaperProps={{
+ style: { width: `calc(${toolbarRef.current?.clientWidth}px - ${theme.spacing(4)})` },
+ }}
+ elevation={1}
+ disableAutoFocus
+ disableEnforceFocus
+ >
+ {filteredDevices.slice(0, 3).map((_, index) => (
+ <DeviceRow data={filteredDevices} index={index} />
+ ))}
+ {filteredDevices.length > 3 && (
+ <ListItemButton alignItems="center" onClick={() => setDevicesOpen(true)}>
+ <ListItemText
+ primary={t('notificationAlways')}
+ style={{ textAlign: 'center' }}
+ />
+ </ListItemButton>
+ )}
+ </Popover>
+ <Popover
open={!!filterAnchorEl}
anchorEl={filterAnchorEl}
onClose={() => setFilterAnchorEl(null)}