From 908fe03807005ef9e38b91fa5be64aff21a1e06a Mon Sep 17 00:00:00 2001 From: Nathaniel Rindlaub Date: Fri, 3 Jan 2025 14:01:50 -0800 Subject: [PATCH 1/4] Use onSelect instead of onClick on dropdown menu items --- src/features/cameras/CameraList.jsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/features/cameras/CameraList.jsx b/src/features/cameras/CameraList.jsx index 7805d59..975b801 100644 --- a/src/features/cameras/CameraList.jsx +++ b/src/features/cameras/CameraList.jsx @@ -21,7 +21,11 @@ import { registerCamera, setDeleteCameraAlertStatus, } from './wirelessCamerasSlice'; -import { setModalContent, setSelectedCamera } from '../projects/projectsSlice.js'; +import { + selectSelectedProjectId, + setModalContent, + setSelectedCamera, +} from '../projects/projectsSlice.js'; import IconButton from '../../components/IconButton'; import { Cross2Icon, @@ -165,6 +169,7 @@ const ActiveState = ({ active }) => ( ); const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { + const selectedProjectId = useSelector(selectSelectedProjectId); const userRoles = useSelector(selectUserCurrentRoles); const dispatch = useDispatch(); @@ -231,7 +236,7 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { > {hasRole(userRoles, WRITE_DEPLOYMENTS_ROLES) && ( handleSaveDepClick({ cameraId: cam._id })} + onSelect={() => handleSaveDepClick({ cameraId: cam._id })} > Add Deployment @@ -256,7 +261,7 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { )} {hasRole(userRoles, WRITE_CAMERA_REGISTRATION_ROLES) && cam.active && ( { + onSelect={(e) => { e.stopPropagation; handleUnregisterClick({ cameraId: cam._id, @@ -270,7 +275,7 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { cam.isWireless && !cam.active && ( { + onSelect={(e) => { e.stopPropagation; handleReRegisterCameraClick({ cameraId: cam._id, @@ -283,8 +288,8 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { )} {hasRole(userRoles, WRITE_CAMERA_REGISTRATION_ROLES) && ( { + disabled={cam.isWireless && selectedProjectId === 'default_project'} + onSelect={(e) => { e.stopPropagation; handleDeleteCameraClick({ cameraId: cam._id, From ce1edfe5dee460e11787c1d3a5a5a10b086bc37f Mon Sep 17 00:00:00 2001 From: Nathaniel Rindlaub Date: Fri, 3 Jan 2025 14:05:55 -0800 Subject: [PATCH 2/4] Replace rest of dropdown menu item onClick handlers with onSelect --- src/features/filters/FiltersPanelFooterDropdown.jsx | 4 ++-- src/features/loupe/Comment.jsx | 6 ++++-- src/features/loupe/LoupeDropdown.jsx | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/features/filters/FiltersPanelFooterDropdown.jsx b/src/features/filters/FiltersPanelFooterDropdown.jsx index 783e5fa..ab14bce 100644 --- a/src/features/filters/FiltersPanelFooterDropdown.jsx +++ b/src/features/filters/FiltersPanelFooterDropdown.jsx @@ -39,12 +39,12 @@ const FiltersPanelFooterDropdown = (props) => { {hasRole(userRoles, EXPORT_DATA_ROLES) && ( - props.handleModalToggle('export-modal')}> + props.handleModalToggle('export-modal')}> Export currently filtered data )} {hasRole(userRoles, DELETE_IMAGES_ROLES) && ( - + Delete all currently filtered images )} diff --git a/src/features/loupe/Comment.jsx b/src/features/loupe/Comment.jsx index 53e7b89..94a093c 100644 --- a/src/features/loupe/Comment.jsx +++ b/src/features/loupe/Comment.jsx @@ -196,8 +196,10 @@ export const Comment = ({ comment, imageId, onChangeOpen, scrollRef }) => { - setIsDeleteConfirm(true)}>Delete - setIsEdit(true)}>Edit + setIsDeleteConfirm(true)}> + Delete + + setIsEdit(true)}>Edit diff --git a/src/features/loupe/LoupeDropdown.jsx b/src/features/loupe/LoupeDropdown.jsx index 6180208..4e6cfcd 100644 --- a/src/features/loupe/LoupeDropdown.jsx +++ b/src/features/loupe/LoupeDropdown.jsx @@ -37,7 +37,7 @@ const LoupeDropdown = ({ image }) => { - Delete Image + Delete Image From d8375836fc37932eb707afd339adbe8ad98b2bc4 Mon Sep 17 00:00:00 2001 From: Nathaniel Rindlaub Date: Fri, 3 Jan 2025 14:34:41 -0800 Subject: [PATCH 3/4] Display reason for disabling dropdown menu items in tooltips --- src/features/cameras/CameraList.jsx | 82 ++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 25 deletions(-) diff --git a/src/features/cameras/CameraList.jsx b/src/features/cameras/CameraList.jsx index 975b801..47fd698 100644 --- a/src/features/cameras/CameraList.jsx +++ b/src/features/cameras/CameraList.jsx @@ -191,9 +191,12 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { dispatch(setSelectedCamera(cameraId)); }; - const [tooltipOpen, setTooltipOpen] = useState(false); const [dropdownOpen, setDropdownOpen] = useState(null); + const [editSnTooltipOpen, setEditSnTooltipOpen] = useState(false); + const [deleteCamTooltipOpen, setDeleteCamTooltipOpen] = useState(false); + const [releaseCamTooltipOpen, setReleaseCamTooltipOpen] = useState(false); + const [cameraFilter, setCameraFilter] = useState(''); const filteredCameras = cameras.filter( (cam) => @@ -242,12 +245,12 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { )} {hasRole(userRoles, WRITE_CAMERA_SERIAL_NUMBER_ROLES) && ( - + handleEditSerialNumberClick({ cameraId: cam._id })} - onClick={() => cam.isWireless && setTooltipOpen(true)} - onMouseLeave={() => setTooltipOpen(false)} + onClick={() => cam.isWireless && setEditSnTooltipOpen(true)} + onMouseLeave={() => setEditSnTooltipOpen(false)} disabled={cam.isWireless} > Edit camera serial number @@ -260,16 +263,31 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { )} {hasRole(userRoles, WRITE_CAMERA_REGISTRATION_ROLES) && cam.active && ( - { - e.stopPropagation; - handleUnregisterClick({ - cameraId: cam._id, - }); - }} - > - Release camera - + + + { + if (cam.isWireless && selectedProjectId === 'default_project') { + setReleaseCamTooltipOpen(true); + } + }} + onMouseLeave={() => setReleaseCamTooltipOpen(false)} + onSelect={(e) => { + e.stopPropagation; + handleUnregisterClick({ + cameraId: cam._id, + }); + }} + > + Release camera + + + + You cannot release wireless cameras from the Default Project + + + )} {hasRole(userRoles, WRITE_CAMERA_REGISTRATION_ROLES) && cam.isWireless && @@ -287,17 +305,31 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { )} {hasRole(userRoles, WRITE_CAMERA_REGISTRATION_ROLES) && ( - { - e.stopPropagation; - handleDeleteCameraClick({ - cameraId: cam._id, - }); - }} - > - Delete camera - + + + { + if (cam.isWireless && selectedProjectId === 'default_project') { + setDeleteCamTooltipOpen(true); + } + }} + onMouseLeave={() => setDeleteCamTooltipOpen(false)} + onSelect={(e) => { + e.stopPropagation; + handleDeleteCameraClick({ + cameraId: cam._id, + }); + }} + > + Delete camera + + + + You cannot delete wireless cameras from the Default Project + + + )} From 076e3a08c8d1b3966977bc63e8b7bd4735b971ca Mon Sep 17 00:00:00 2001 From: Nathaniel Rindlaub Date: Fri, 3 Jan 2025 16:15:28 -0800 Subject: [PATCH 4/4] Add icons to dropdown menu items --- src/components/Dropdown.jsx | 6 +++--- src/features/cameras/CameraList.jsx | 18 +++++++++++++++++- src/features/cameras/DeleteCameraAlert.jsx | 2 +- .../filters/FiltersPanelFooterDropdown.jsx | 8 ++++++++ src/features/loupe/Comment.jsx | 12 +++++++++++- src/features/loupe/LoupeDropdown.jsx | 9 ++++++++- 6 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/components/Dropdown.jsx b/src/components/Dropdown.jsx index 4b5b2d9..e84a8a5 100644 --- a/src/components/Dropdown.jsx +++ b/src/components/Dropdown.jsx @@ -49,19 +49,19 @@ const itemStyles = { fontSize: '$3', fontWeight: '$2', lineHeight: 1, - color: '$hiContrast', + color: '$textDark', borderRadius: 3, display: 'flex', alignItems: 'center', height: 27, padding: '0 5px', position: 'relative', - paddingLeft: '$2', + paddingLeft: 28, userSelect: 'none', '&[data-disabled]': { color: mauve.mauve8, - // pointerEvents: 'none', + pointerEvents: 'none', }, '&[data-state="checked"]': { diff --git a/src/features/cameras/CameraList.jsx b/src/features/cameras/CameraList.jsx index 47fd698..843a011 100644 --- a/src/features/cameras/CameraList.jsx +++ b/src/features/cameras/CameraList.jsx @@ -7,6 +7,7 @@ import { DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, + DropdownMenuItemIconLeft, DropdownMenuArrow, } from '../../components/Dropdown.jsx'; import { @@ -35,7 +36,7 @@ import { ChevronDownIcon, } from '@radix-ui/react-icons'; import { StandAloneInput as Input } from '../../components/Form'; -import { Camera, MapPin } from 'lucide-react'; +import { Camera, MapPin, IdCard, Trash2, Unlink, Link } from 'lucide-react'; import { indigo } from '@radix-ui/colors'; import { @@ -241,6 +242,9 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { handleSaveDepClick({ cameraId: cam._id })} > + + + Add Deployment )} @@ -253,6 +257,9 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { onMouseLeave={() => setEditSnTooltipOpen(false)} disabled={cam.isWireless} > + + + Edit camera serial number @@ -280,6 +287,9 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { }); }} > + + + Release camera @@ -301,6 +311,9 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { }); }} > + + + Re-register camera )} @@ -322,6 +335,9 @@ const CameraList = ({ cameras, handleSaveDepClick, handleDeleteDepClick }) => { }); }} > + + + Delete camera diff --git a/src/features/cameras/DeleteCameraAlert.jsx b/src/features/cameras/DeleteCameraAlert.jsx index ec487a6..4ebf037 100644 --- a/src/features/cameras/DeleteCameraAlert.jsx +++ b/src/features/cameras/DeleteCameraAlert.jsx @@ -93,7 +93,7 @@ const DeleteCameraAlert = () => {

Are you sure you'd like to delete Camera {selectedCamera}?{' '} {imageCount === 0 && 'This will remove the Camera and the Deployments '} - {imageCount > 0 && ( + {!imageCountLoading && imageCount > 0 && ( <> This will remove the Camera, its Deployments, and{' '} {imageCount > 1 ? 'all' : 'the'}{' '} diff --git a/src/features/filters/FiltersPanelFooterDropdown.jsx b/src/features/filters/FiltersPanelFooterDropdown.jsx index ab14bce..8dfee0a 100644 --- a/src/features/filters/FiltersPanelFooterDropdown.jsx +++ b/src/features/filters/FiltersPanelFooterDropdown.jsx @@ -7,10 +7,12 @@ import { DropdownMenuContent, DropdownMenuItem, DropdownMenuArrow, + DropdownMenuItemIconLeft, } from '../../components/Dropdown.jsx'; import { selectUserCurrentRoles } from '../auth/authSlice.js'; import { hasRole, DELETE_IMAGES_ROLES, EXPORT_DATA_ROLES } from '../auth/roles.js'; import { DotsHorizontalIcon } from '@radix-ui/react-icons'; +import { Download, Trash2 } from 'lucide-react'; import { setDeleteImagesAlertStatus } from '../images/imagesSlice'; const StyledDropdownMenuTrigger = styled(DropdownMenuTrigger, { @@ -40,11 +42,17 @@ const FiltersPanelFooterDropdown = (props) => { {hasRole(userRoles, EXPORT_DATA_ROLES) && ( props.handleModalToggle('export-modal')}> + + + Export currently filtered data )} {hasRole(userRoles, DELETE_IMAGES_ROLES) && ( + + + Delete all currently filtered images )} diff --git a/src/features/loupe/Comment.jsx b/src/features/loupe/Comment.jsx index 94a093c..8244932 100644 --- a/src/features/loupe/Comment.jsx +++ b/src/features/loupe/Comment.jsx @@ -7,6 +7,7 @@ import { DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, + DropdownMenuItemIconLeft, DropdownMenuArrow, } from '../../components/Dropdown.jsx'; import Button from '../../components/Button.jsx'; @@ -17,6 +18,7 @@ import { selectUserUsername } from '../auth/authSlice.js'; import { DateTime } from 'luxon'; import { editComment } from '../review/reviewSlice.js'; import { indigo } from '@radix-ui/colors'; +import { Trash2, Pencil } from 'lucide-react'; const StyledFieldRow = styled(FieldRow, { display: 'block', @@ -197,9 +199,17 @@ export const Comment = ({ comment, imageId, onChangeOpen, scrollRef }) => { setIsDeleteConfirm(true)}> + + + Delete - setIsEdit(true)}>Edit + setIsEdit(true)}> + + + + Edit + diff --git a/src/features/loupe/LoupeDropdown.jsx b/src/features/loupe/LoupeDropdown.jsx index 4e6cfcd..8855dd5 100644 --- a/src/features/loupe/LoupeDropdown.jsx +++ b/src/features/loupe/LoupeDropdown.jsx @@ -6,6 +6,7 @@ import { DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, + DropdownMenuItemIconLeft, DropdownMenuArrow, } from '../../components/Dropdown.jsx'; import IconButton from '../../components/IconButton.jsx'; @@ -13,6 +14,7 @@ import { DotsHorizontalIcon } from '@radix-ui/react-icons'; import DeleteImagesAlert from '../images/DeleteImagesAlert.jsx'; import { setDeleteImagesAlertStatus } from '../images/imagesSlice'; import { selectFocusIndex, setSelectedImageIndices } from '../review/reviewSlice.js'; +import { Trash2 } from 'lucide-react'; const StyledDropdownMenuTrigger = styled(DropdownMenuTrigger, { position: 'absolute', @@ -37,7 +39,12 @@ const LoupeDropdown = ({ image }) => { - Delete Image + + + + + Delete Image +