Merge pull request #172 from stephb9959/main

[WIFI-12437] Improved commonly used device actions accessibility
This commit is contained in:
Charles Bourque
2023-04-10 11:04:31 +02:00
committed by GitHub
5 changed files with 94 additions and 53 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "ucentral-client", "name": "ucentral-client",
"version": "2.10.0(5)", "version": "2.10.0(11)",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ucentral-client", "name": "ucentral-client",
"version": "2.10.0(5)", "version": "2.10.0(11)",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@chakra-ui/icons": "^2.0.11", "@chakra-ui/icons": "^2.0.11",

View File

@@ -1,6 +1,6 @@
{ {
"name": "ucentral-client", "name": "ucentral-client",
"version": "2.10.0(5)", "version": "2.10.0(11)",
"description": "", "description": "",
"private": true, "private": true,
"main": "index.tsx", "main": "index.tsx",

View File

@@ -1,18 +1,17 @@
import React from 'react'; import React from 'react';
import { import {
Button,
IconButton, IconButton,
Menu, Menu,
MenuButton, MenuButton,
MenuItem, MenuItem,
MenuList, MenuList,
Portal, Portal,
Spinner,
Tooltip, Tooltip,
useColorModeValue,
useToast, useToast,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import axios from 'axios'; import axios from 'axios';
import { Wrench } from 'phosphor-react'; import { Barcode, Power, TerminalWindow, WifiHigh, Wrench } from 'phosphor-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useControllerStore } from 'contexts/ControllerSocketProvider/useStore'; import { useControllerStore } from 'contexts/ControllerSocketProvider/useStore';
import { useBlinkDevice, useGetDeviceRtty } from 'hooks/Network/Devices'; import { useBlinkDevice, useGetDeviceRtty } from 'hooks/Network/Devices';
@@ -51,12 +50,13 @@ const DeviceActionDropdown = ({
onOpenScriptModal, onOpenScriptModal,
onOpenRebootModal, onOpenRebootModal,
size, size,
isCompact = true, isCompact,
}: Props) => { }: Props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const toast = useToast(); const toast = useToast();
const connectColor = useColorModeValue('blackAlpha', 'gray');
const addEventListeners = useControllerStore((state) => state.addEventListeners); const addEventListeners = useControllerStore((state) => state.addEventListeners);
const { refetch: getRtty, isInitialLoading: isRtty } = useGetDeviceRtty({ const { refetch: getRtty, isFetching: isRtty } = useGetDeviceRtty({
serialNumber: device.serialNumber, serialNumber: device.serialNumber,
extraId: 'inventory-modal', extraId: 'inventory-modal',
}); });
@@ -162,49 +162,90 @@ const DeviceActionDropdown = ({
const handleRebootClick = () => onOpenRebootModal(device.serialNumber); const handleRebootClick = () => onOpenRebootModal(device.serialNumber);
return ( return (
<Menu> <>
<Tooltip label={t('common.actions')}> <Tooltip label={t('commands.connect')}>
{size === undefined || isCompact ? ( <IconButton
aria-label="Connect"
icon={<TerminalWindow size={20} />}
size={size ?? 'sm'}
isDisabled={isDisabled}
isLoading={isRtty}
onClick={handleConnectClick}
colorScheme={connectColor}
hidden={isCompact}
/>
</Tooltip>
<Tooltip label={t('controller.configure.title')}>
<IconButton
aria-label={t('controller.configure.title')}
icon={<Barcode size={20} />}
size={size ?? 'sm'}
isDisabled={isDisabled}
onClick={handleOpenConfigure}
colorScheme="purple"
hidden={isCompact}
/>
</Tooltip>
<Tooltip label={t('commands.reboot')}>
<IconButton
aria-label={t('commands.reboot')}
icon={<Power size={20} />}
size={size ?? 'sm'}
isDisabled={isDisabled}
onClick={handleRebootClick}
colorScheme="green"
hidden={isCompact}
/>
</Tooltip>
<Tooltip label={t('commands.wifiscan')}>
<IconButton
aria-label={t('commands.wifiscan')}
icon={<WifiHigh size={20} />}
size={size ?? 'sm'}
isDisabled={isDisabled}
onClick={handleOpenScan}
colorScheme="teal"
hidden={isCompact}
/>
</Tooltip>
<Menu>
<Tooltip label={t('common.actions')}>
<MenuButton <MenuButton
as={IconButton} as={IconButton}
aria-label="Commands" aria-label="Commands"
icon={isRtty ? <Spinner /> : <Wrench size={20} />} icon={<Wrench size={20} />}
size={size ?? 'sm'} size={size ?? 'sm'}
isDisabled={isDisabled} isDisabled={isDisabled}
ml={2}
/> />
) : ( </Tooltip>
<MenuButton <Portal>
as={Button} <MenuList maxH="315px" overflowY="auto">
aria-label="Commands" <MenuItem onClick={handleBlinkClick}>{t('commands.blink')}</MenuItem>
rightIcon={isRtty ? <Spinner /> : <Wrench size={20} />} <MenuItem onClick={handleOpenConfigure} hidden={!isCompact}>
size={size ?? 'sm'} {t('controller.configure.title')}
isDisabled={isDisabled} </MenuItem>
ml={2} <MenuItem onClick={handleConnectClick} hidden={!isCompact}>
> {t('commands.connect')}
{t('common.actions')} </MenuItem>
</MenuButton> <MenuItem onClick={handleOpenQueue}>{t('controller.queue.title')}</MenuItem>
)} <MenuItem onClick={handleOpenFactoryReset}>{t('commands.factory_reset')}</MenuItem>
</Tooltip> <MenuItem onClick={handleOpenUpgrade}>{t('commands.firmware_upgrade')}</MenuItem>
<Portal> <MenuItem onClick={handleRebootClick} hidden={!isCompact}>
<MenuList> {t('commands.reboot')}
<MenuItem onClick={handleBlinkClick}>{t('commands.blink')}</MenuItem> </MenuItem>
<MenuItem onClick={handleOpenConfigure}>{t('controller.configure.title')}</MenuItem> <MenuItem onClick={handleOpenTelemetry}>{t('controller.telemetry.title')}</MenuItem>
<MenuItem onClick={handleConnectClick}>{t('commands.connect')}</MenuItem> <MenuItem onClick={handleOpenScript}>{t('script.one')}</MenuItem>
<MenuItem onClick={handleOpenQueue}>{t('controller.queue.title')}</MenuItem> <MenuItem onClick={handleOpenTrace}>{t('controller.devices.trace')}</MenuItem>
<MenuItem onClick={handleOpenFactoryReset}>{t('commands.factory_reset')}</MenuItem> <MenuItem onClick={handleUpdateToLatest} hidden>
<MenuItem onClick={handleOpenUpgrade}>{t('commands.firmware_upgrade')}</MenuItem> {t('premium.toolbox.upgrade_to_latest')}
<MenuItem onClick={handleRebootClick}>{t('commands.reboot')}</MenuItem> </MenuItem>
<MenuItem onClick={handleOpenTelemetry}>{t('controller.telemetry.title')}</MenuItem> <MenuItem onClick={handleOpenScan} hidden={!isCompact}>
<MenuItem onClick={handleOpenScript}>{t('script.one')}</MenuItem> {t('commands.wifiscan')}
<MenuItem onClick={handleOpenTrace}>{t('controller.devices.trace')}</MenuItem> </MenuItem>
<MenuItem onClick={handleUpdateToLatest} hidden> </MenuList>
{t('premium.toolbox.upgrade_to_latest')} </Portal>
</MenuItem> </Menu>
<MenuItem onClick={handleOpenScan}>{t('commands.wifiscan')}</MenuItem> </>
</MenuList>
</Portal>
</Menu>
); );
}; };

View File

@@ -185,7 +185,7 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
<> <>
{isCompact ? ( {isCompact ? (
<Card p={2} mb={4}> <Card p={2} mb={4}>
<CardHeader overflowX="auto"> <CardHeader>
<HStack spacing={2}> <HStack spacing={2}>
<Heading size="md">{serialNumber}</Heading> <Heading size="md">{serialNumber}</Heading>
{connectedTag} {connectedTag}
@@ -194,7 +194,7 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
</HStack> </HStack>
<Spacer /> <Spacer />
<HStack spacing={2}> <HStack spacing={2}>
{breakpoint !== 'base' && breakpoint !== 'md' && <DeviceSearchBar />} <DeviceSearchBar />
<DeleteButton isCompact onClick={onDeleteOpen} /> <DeleteButton isCompact onClick={onDeleteOpen} />
{getDevice?.data && ( {getDevice?.data && (
<DeviceActionDropdown <DeviceActionDropdown
@@ -261,7 +261,6 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
onOpenRebootModal={rebootModalProps.onOpen} onOpenRebootModal={rebootModalProps.onOpen}
onOpenScriptModal={scriptModal.openModal} onOpenScriptModal={scriptModal.openModal}
size="md" size="md"
isCompact
/> />
)} )}
<RefreshButton <RefreshButton
@@ -282,7 +281,9 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
<AlertDialogHeader fontSize="lg" fontWeight="bold"> <AlertDialogHeader fontSize="lg" fontWeight="bold">
{t('crud.delete')} {serialNumber} {t('crud.delete')} {serialNumber}
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogBody>{t('crud.delete_confirm', { obj: t('devices.one') })}</AlertDialogBody> <AlertDialogBody>{t('crud.delete_confirm', { obj: t('devices.one') })}</AlertDialogBody>
<AlertDialogFooter> <AlertDialogFooter>
<Button colorScheme="gray" mr="1" onClick={onDeleteClose} ref={cancelRef}> <Button colorScheme="gray" mr="1" onClick={onDeleteClose} ref={cancelRef}>
{t('common.cancel')} {t('common.cancel')}
@@ -306,7 +307,7 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
<Box mt={isCompact ? '0px' : '68px'}> <Box mt={isCompact ? '0px' : '68px'}>
<Masonry <Masonry
breakpointCols={{ breakpointCols={{
default: 3, default: 2,
2200: 2, 2200: 2,
1100: 1, 1100: 1,
}} }}

View File

@@ -3,7 +3,7 @@ import {
Box, Box,
Button, Button,
Center, Center,
Flex, HStack,
IconButton, IconButton,
Link, Link,
Popover, Popover,
@@ -64,7 +64,7 @@ const Actions: React.FC<Props> = ({
}); });
return ( return (
<Flex> <HStack spacing={2}>
<Popover isOpen={isOpen} onOpen={onOpen} onClose={onClose}> <Popover isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
<Tooltip hasArrow label={t('crud.delete')} placement="top" isDisabled={isOpen}> <Tooltip hasArrow label={t('crud.delete')} placement="top" isDisabled={isOpen}>
<Box> <Box>
@@ -110,14 +110,13 @@ const Actions: React.FC<Props> = ({
<Link href={`#/devices/${device.serialNumber}`}> <Link href={`#/devices/${device.serialNumber}`}>
<IconButton <IconButton
aria-label={t('common.view_details')} aria-label={t('common.view_details')}
ml={2}
colorScheme="blue" colorScheme="blue"
icon={<MagnifyingGlass size={20} />} icon={<MagnifyingGlass size={20} />}
size="sm" size="sm"
/> />
</Link> </Link>
</Tooltip> </Tooltip>
</Flex> </HStack>
); );
}; };