From 881ca71bd565e8cc9df6cf3ca4b8483a0697e466 Mon Sep 17 00:00:00 2001 From: Fabian Chinchilla Date: Tue, 5 Dec 2023 03:25:00 -0600 Subject: [PATCH 1/2] Add DetailsDrawer feat: Add DetailsDrawer for showing device position details The commit adds a new component, DetailsDrawer, which displays position details for a selected device. This drawer can be opened from the StatusCard component, providing additional contextual information about the device's state. Users can view attributes such as speed, address, and total distance for the selected device. The addition of the DetailsDrawer enhances the user experience by offering a convenient way to explore and analyze position data. --- modern/src/common/components/StatusCard.jsx | 13 ++- modern/src/common/theme/dimensions.js | 1 + modern/src/main/DetailsDrawer.jsx | 106 ++++++++++++++++++++ modern/src/main/MainPage.jsx | 11 ++ modern/src/resources/l10n/en.json | 1 + modern/src/settings/PreferencesPage.jsx | 9 ++ 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 modern/src/main/DetailsDrawer.jsx diff --git a/modern/src/common/components/StatusCard.jsx b/modern/src/common/components/StatusCard.jsx index b4660d610b..417c8873c0 100644 --- a/modern/src/common/components/StatusCard.jsx +++ b/modern/src/common/components/StatusCard.jsx @@ -115,7 +115,7 @@ const StatusRow = ({ name, content }) => { ); }; -const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPadding = 0 }) => { +const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPadding = 0, onDetailsClick }) => { const classes = useStyles({ desktopPadding }); const navigate = useNavigate(); const dispatch = useDispatch(); @@ -129,6 +129,7 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin const positionAttributes = usePositionAttributes(t); const positionItems = useAttributePreference('positionItems', 'speed,address,totalDistance,course'); + const showDetailsDrawer = useAttributePreference('showDetailsDrawer', true); const [anchorEl, setAnchorEl] = useState(null); @@ -188,6 +189,14 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin } }, [deviceId, setShared]); + const handleDetails = useCatchCallback(async () =>{ + if (showDetailsDrawer==true) { + onDetailsClick(); + setAnchorEl(null); + }else{ + navigate(`/position/${position.id}`); + } + }) return ( <>
@@ -284,7 +293,7 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin
{position && ( setAnchorEl(null)}> - navigate(`/position/${position.id}`)}>{t('sharedShowDetails')} + {t('sharedShowDetails')} {t('sharedCreateGeofence')} {t('linkGoogleMaps')} {t('linkAppleMaps')} diff --git a/modern/src/common/theme/dimensions.js b/modern/src/common/theme/dimensions.js index 4930803a09..52f3b8fa30 100644 --- a/modern/src/common/theme/dimensions.js +++ b/modern/src/common/theme/dimensions.js @@ -6,6 +6,7 @@ export default { drawerHeightPhone: '250px', filterFormWidth: '160px', eventsDrawerWidth: '320px', + detailsDrawerWidth: '350px', bottomBarHeight: 56, popupMapOffset: 300, popupMaxWidth: 288, diff --git a/modern/src/main/DetailsDrawer.jsx b/modern/src/main/DetailsDrawer.jsx new file mode 100644 index 0000000000..131e14a769 --- /dev/null +++ b/modern/src/main/DetailsDrawer.jsx @@ -0,0 +1,106 @@ +import React, { useState } from 'react'; +import { useSelector } from 'react-redux'; +import { + Drawer, Toolbar, Typography, Table, TableHead, TableRow, TableCell, TableBody, AppBar, IconButton, +} from '@mui/material'; + +import CloseIcon from '@mui/icons-material/Close'; +import { makeStyles } from '@mui/styles'; +import { useTranslation } from '../common/components/LocalizationProvider'; +import { prefixString } from '../common/util/stringUtils'; +import { useEffectAsync } from '../reactHelper'; +import PositionValue from '../common/components/PositionValue'; +import usePositionAttributes from '../common/attributes/usePositionAttributes'; + +const useStyles = makeStyles((theme) => ({ + drawer: { + width: theme.dimensions.detailsDrawerWidth, + }, + toolbar: { + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + }, + title: { + flexGrow: 1, + }, +})); + +const DetailsDrawer = ({ deviceId, open, onClose }) => { + const classes = useStyles(); + const t = useTranslation(); + const positionAttributes = usePositionAttributes(t); + + const device = useSelector((state) => state.devices.items[deviceId]); + + const [item, setItem] = useState(); + + useEffectAsync(async () => { + if (device) { + const response = await fetch(`/api/positions?id=${device.positionId}`); + if (response.ok) { + const positions = await response.json(); + if (positions.length > 0) { + setItem(positions[0]); + } + } else { + throw Error(await response.text()); + } + } + }, [deviceId]); + + const deviceName = useSelector((state) => { + if (item) { + const device = state.devices.items[item.deviceId]; + if (device) { + return device.name; + } + } + return null; + }); + + return ( + + + + + {deviceName} + + + + + + + + + + {t('stateName')} + {t('sharedName')} + {t('stateValue')} + + + + {item && Object.getOwnPropertyNames(item).filter((it) => it !== 'attributes').map((property) => ( + + {property} + {positionAttributes[property]?.name || property} + + + ))} + {item && Object.getOwnPropertyNames(item.attributes).map((attribute) => ( + + {attribute} + {positionAttributes[attribute]?.name || attribute} + + + ))} + +
+
+ ); +}; + +export default DetailsDrawer; diff --git a/modern/src/main/MainPage.jsx b/modern/src/main/MainPage.jsx index 8369ba9715..7b4148c436 100644 --- a/modern/src/main/MainPage.jsx +++ b/modern/src/main/MainPage.jsx @@ -16,6 +16,7 @@ import useFilter from './useFilter'; import MainToolbar from './MainToolbar'; import MainMap from './MainMap'; import { useAttributePreference } from '../common/util/preferences'; +import DetailsDrawer from './DetailsDrawer'; const useStyles = makeStyles((theme) => ({ root: { @@ -88,8 +89,10 @@ const MainPage = () => { const [devicesOpen, setDevicesOpen] = useState(desktop); const [eventsOpen, setEventsOpen] = useState(false); + const [detailsOpen, setDetailsOpen] = useState(false); const onEventsClick = useCallback(() => setEventsOpen(true), [setEventsOpen]); + const onDetailsClick = useCallback(() => setDetailsOpen(true), [setDetailsOpen]); useEffect(() => { if (!desktop && mapOnSelect && selectedDeviceId) { @@ -150,8 +153,16 @@ const MainPage = () => { deviceId={selectedDeviceId} position={selectedPosition} onClose={() => dispatch(devicesActions.selectId(null))} + onDetailsClick={onDetailsClick} desktopPadding={theme.dimensions.drawerWidthDesktop} /> + )} + {selectedDeviceId && ( + setDetailsOpen(false)} + /> )} ); diff --git a/modern/src/resources/l10n/en.json b/modern/src/resources/l10n/en.json index 0f57b52a75..ddc5a71d22 100644 --- a/modern/src/resources/l10n/en.json +++ b/modern/src/resources/l10n/en.json @@ -115,6 +115,7 @@ "calendarFriday": "Friday", "calendarSaturday": "Saturday", "attributeShowGeofences": "Show Geofences", + "attributeShowDetailsOnDrawer": "Show Details on Drawer", "attributeSpeedLimit": "Speed Limit", "attributeFuelDropThreshold": "Fuel Drop Threshold", "attributeFuelIncreaseThreshold": "Fuel Increase Threshold", diff --git a/modern/src/settings/PreferencesPage.jsx b/modern/src/settings/PreferencesPage.jsx index bd96b1405b..8a87c94e90 100644 --- a/modern/src/settings/PreferencesPage.jsx +++ b/modern/src/settings/PreferencesPage.jsx @@ -279,6 +279,15 @@ const PreferencesPage = () => { titleGetter={(it) => t(it.name)} label={t('deviceSecondaryInfo')} /> + setAttributes({ ...attributes, showDetailsDrawer: e.target.checked })} + /> + )} + label={t('attributeShowDetailsOnDrawer')} + /> From 463980ec6fb87fd565f81a0d2d36bed9b341b005 Mon Sep 17 00:00:00 2001 From: Fabian Chinchilla Date: Tue, 5 Dec 2023 03:36:29 -0600 Subject: [PATCH 2/2] Add QuickDetailsBotton feat: Add Quick Details Button in StatusCard component This commit introduces a new feature to the StatusCard component by adding a Quick Details button. When enabled in the preferences, the button appears below the table in the card. Clicking on the button triggers the onDetailsClick function and displays additional information. This enhancement provides users with a convenient way to quickly access more details about the device. --- modern/src/common/components/StatusCard.jsx | 5 +++++ modern/src/resources/l10n/en.json | 1 + modern/src/settings/PreferencesPage.jsx | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/modern/src/common/components/StatusCard.jsx b/modern/src/common/components/StatusCard.jsx index 417c8873c0..9357901d5c 100644 --- a/modern/src/common/components/StatusCard.jsx +++ b/modern/src/common/components/StatusCard.jsx @@ -17,6 +17,7 @@ import { MenuItem, CardMedia, Snackbar, + Button, } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import CloseIcon from '@mui/icons-material/Close'; @@ -130,6 +131,7 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin const positionAttributes = usePositionAttributes(t); const positionItems = useAttributePreference('positionItems', 'speed,address,totalDistance,course'); const showDetailsDrawer = useAttributePreference('showDetailsDrawer', true); + const quickDetailsBotton = useAttributePreference('quickDetailsBotton', false); const [anchorEl, setAnchorEl] = useState(null); @@ -251,6 +253,7 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin ))} + {quickDetailsBotton === true && ()} )} @@ -293,7 +296,9 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin {position && ( setAnchorEl(null)}> + {!quickDetailsBotton && ( {t('sharedShowDetails')} + )} {t('sharedCreateGeofence')} {t('linkGoogleMaps')} {t('linkAppleMaps')} diff --git a/modern/src/resources/l10n/en.json b/modern/src/resources/l10n/en.json index ddc5a71d22..3d26ae7621 100644 --- a/modern/src/resources/l10n/en.json +++ b/modern/src/resources/l10n/en.json @@ -116,6 +116,7 @@ "calendarSaturday": "Saturday", "attributeShowGeofences": "Show Geofences", "attributeShowDetailsOnDrawer": "Show Details on Drawer", + "attributeQuickDetailsBotton": "Show Quick Button Details", "attributeSpeedLimit": "Speed Limit", "attributeFuelDropThreshold": "Fuel Drop Threshold", "attributeFuelIncreaseThreshold": "Fuel Increase Threshold", diff --git a/modern/src/settings/PreferencesPage.jsx b/modern/src/settings/PreferencesPage.jsx index 8a87c94e90..ab7f88d226 100644 --- a/modern/src/settings/PreferencesPage.jsx +++ b/modern/src/settings/PreferencesPage.jsx @@ -288,6 +288,15 @@ const PreferencesPage = () => { )} label={t('attributeShowDetailsOnDrawer')} /> + setAttributes({ ...attributes, quickDetailsBotton: e.target.checked })} + /> + )} + label={t('attributeQuickDetailsBotton')} + />