[WIFI-12031] Added confirmation modal to reboot process

Signed-off-by: Charles <charles.bourque96@gmail.com>
This commit is contained in:
Charles
2023-01-05 14:02:00 -05:00
parent 1e4ccce36c
commit 623d5a5546
12 changed files with 113 additions and 46 deletions

22
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "ucentral-client",
"version": "2.8.0(46)",
"version": "2.9.0(1)",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "ucentral-client",
"version": "2.8.0(46)",
"version": "2.9.0(1)",
"license": "ISC",
"dependencies": {
"@chakra-ui/icons": "^2.0.11",
@@ -6642,8 +6642,9 @@
"license": "MIT"
},
"node_modules/json5": {
"version": "2.2.1",
"license": "MIT",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"bin": {
"json5": "lib/cli.js"
},
@@ -8853,9 +8854,10 @@
}
},
"node_modules/tsconfig-paths/node_modules/json5": {
"version": "1.0.1",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"license": "MIT",
"dependencies": {
"minimist": "^1.2.0"
},
@@ -13688,7 +13690,9 @@
"dev": true
},
"json5": {
"version": "2.2.1"
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
},
"jsonfile": {
"version": "6.1.0",
@@ -14981,7 +14985,9 @@
},
"dependencies": {
"json5": {
"version": "1.0.1",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
"requires": {
"minimist": "^1.2.0"

View File

@@ -1,6 +1,6 @@
{
"name": "ucentral-client",
"version": "2.8.0(46)",
"version": "2.9.0(1)",
"description": "",
"private": true,
"main": "index.tsx",

View File

@@ -175,6 +175,7 @@
"other": "Befehle",
"override_dfs": "DFS überschreiben",
"reboot": "Starten Sie neu",
"reboot_description": "Möchten Sie dieses Gerät neu starten?",
"reboot_error": "Fehler beim Senden des Neustartbefehls: {{e}}",
"reboot_success": "Neustartbefehl erfolgreich gesendet!",
"revision": "Revision",

View File

@@ -175,6 +175,7 @@
"other": "Commands",
"override_dfs": "Override DFS",
"reboot": "Reboot",
"reboot_description": "Do you want to reboot this device?",
"reboot_error": "Error while sending reboot command: {{e}}",
"reboot_success": "Successfully sent reboot command!",
"revision": "Revision",

View File

@@ -175,6 +175,7 @@
"other": "comandos",
"override_dfs": "Anular DFS",
"reboot": "Reiniciar",
"reboot_description": "¿Quieres reiniciar este dispositivo?",
"reboot_error": "Error al enviar el comando de reinicio: {{e}}",
"reboot_success": "¡Comando de reinicio enviado con éxito!",
"revision": "revisión",

View File

@@ -175,6 +175,7 @@
"other": "Les commandes",
"override_dfs": "Remplacer DFS",
"reboot": "Redémarrer",
"reboot_description": "Voulez-vous redémarrer cet appareil ?",
"reboot_error": "Erreur lors de l'envoi de la commande de redémarrage : {{e}}",
"reboot_success": "Commande de redémarrage envoyée avec succès !",
"revision": "Révision",

View File

@@ -175,6 +175,7 @@
"other": "comandos",
"override_dfs": "Substituir DFS",
"reboot": "Reiniciar",
"reboot_description": "Deseja reiniciar este dispositivo?",
"reboot_error": "Erro ao enviar o comando de reinicialização: {{e}}",
"reboot_success": "Comando de reinicialização enviado com sucesso!",
"revision": "revisão",

View File

@@ -1,9 +1,19 @@
import React from 'react';
import { Button, IconButton, Menu, MenuButton, MenuItem, MenuList, Spinner, Tooltip, useToast } from '@chakra-ui/react';
import {
Button,
IconButton,
Menu,
MenuButton,
MenuItem,
MenuList,
Portal,
Spinner,
Tooltip,
useToast,
} from '@chakra-ui/react';
import axios from 'axios';
import { Wrench } from 'phosphor-react';
import { useTranslation } from 'react-i18next';
import RebootMenuItem from './RebootButton';
import { useControllerStore } from 'contexts/ControllerSocketProvider/useStore';
import { useBlinkDevice, useGetDeviceRtty } from 'hooks/Network/Devices';
import { useUpdateDeviceToLatest } from 'hooks/Network/Firmware';
@@ -22,6 +32,7 @@ interface Props {
onOpenConfigureModal: (serialNumber: string) => void;
onOpenTelemetryModal: (serialNumber: string) => void;
onOpenScriptModal: (device: GatewayDevice) => void;
onOpenRebootModal: (serialNumber: string) => void;
size?: 'sm' | 'md' | 'lg';
isCompact?: boolean;
}
@@ -38,6 +49,7 @@ const DeviceActionDropdown = ({
onOpenTelemetryModal,
onOpenConfigureModal,
onOpenScriptModal,
onOpenRebootModal,
size,
isCompact,
}: Props) => {
@@ -145,7 +157,9 @@ const DeviceActionDropdown = ({
},
);
};
const handleConnectClick = () => getRtty();
const handleRebootClick = () => onOpenRebootModal(device.serialNumber);
return (
<Menu>
@@ -172,22 +186,24 @@ const DeviceActionDropdown = ({
</MenuButton>
)}
</Tooltip>
<MenuList>
<MenuItem onClick={handleBlinkClick}>{t('commands.blink')}</MenuItem>
<MenuItem onClick={handleOpenConfigure}>{t('controller.configure.title')}</MenuItem>
<MenuItem onClick={handleConnectClick}>{t('commands.connect')}</MenuItem>
<MenuItem onClick={handleOpenQueue}>{t('controller.queue.title')}</MenuItem>
<MenuItem onClick={handleOpenFactoryReset}>{t('commands.factory_reset')}</MenuItem>
<MenuItem onClick={handleOpenUpgrade}>{t('commands.firmware_upgrade')}</MenuItem>
<RebootMenuItem device={device} refresh={refresh} />
<MenuItem onClick={handleOpenTelemetry}>{t('controller.telemetry.title')}</MenuItem>
<MenuItem onClick={handleOpenScript}>{t('script.one')}</MenuItem>
<MenuItem onClick={handleOpenTrace}>{t('controller.devices.trace')}</MenuItem>
<MenuItem onClick={handleUpdateToLatest} hidden>
{t('premium.toolbox.upgrade_to_latest')}
</MenuItem>
<MenuItem onClick={handleOpenScan}>{t('commands.wifiscan')}</MenuItem>
</MenuList>
<Portal>
<MenuList>
<MenuItem onClick={handleBlinkClick}>{t('commands.blink')}</MenuItem>
<MenuItem onClick={handleOpenConfigure}>{t('controller.configure.title')}</MenuItem>
<MenuItem onClick={handleConnectClick}>{t('commands.connect')}</MenuItem>
<MenuItem onClick={handleOpenQueue}>{t('controller.queue.title')}</MenuItem>
<MenuItem onClick={handleOpenFactoryReset}>{t('commands.factory_reset')}</MenuItem>
<MenuItem onClick={handleOpenUpgrade}>{t('commands.firmware_upgrade')}</MenuItem>
<MenuItem onClick={handleRebootClick}>{t('commands.reboot')}</MenuItem>
<MenuItem onClick={handleOpenTelemetry}>{t('controller.telemetry.title')}</MenuItem>
<MenuItem onClick={handleOpenScript}>{t('script.one')}</MenuItem>
<MenuItem onClick={handleOpenTrace}>{t('controller.devices.trace')}</MenuItem>
<MenuItem onClick={handleUpdateToLatest} hidden>
{t('premium.toolbox.upgrade_to_latest')}
</MenuItem>
<MenuItem onClick={handleOpenScan}>{t('commands.wifiscan')}</MenuItem>
</MenuList>
</Portal>
</Menu>
);
};

View File

@@ -1,40 +1,42 @@
import * as React from 'react';
import { MenuItem, useToast } from '@chakra-ui/react';
import { Alert, AlertIcon, Box, Button, Center, useToast } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import { Modal } from '../Modal';
import { useControllerStore } from 'contexts/ControllerSocketProvider/useStore';
import { useRebootDevice } from 'hooks/Network/Devices';
import { useMutationResult } from 'hooks/useMutationResult';
import { AxiosError } from 'models/Axios';
import { GatewayDevice } from 'models/Device';
type Props = {
device: GatewayDevice;
refresh: () => void;
export type RebootModalProps = {
serialNumber: string;
modalProps: {
isOpen: boolean;
onClose: () => void;
};
};
const RebootMenuItem = ({ device, refresh }: Props) => {
export const RebootModal = ({ serialNumber, modalProps }: RebootModalProps) => {
const { t } = useTranslation();
const toast = useToast();
const addEventListeners = useControllerStore((state) => state.addEventListeners);
const { mutateAsync: reboot } = useRebootDevice({ serialNumber: device.serialNumber });
const { mutateAsync: reboot, isLoading } = useRebootDevice({ serialNumber });
const { onSuccess: onRebootSuccess, onError: onRebootError } = useMutationResult({
objName: t('devices.one'),
operationType: 'reboot',
refresh: () => {
refresh();
addEventListeners([
{
id: `device-connection-${device.serialNumber}`,
id: `device-connection-${serialNumber}`,
type: 'DEVICE_CONNECTION',
serialNumber: device.serialNumber,
serialNumber,
callback: () => {
const id = `device-connection-notification-${device.serialNumber}`;
const id = `device-connection-notification-${serialNumber}`;
if (!toast.isActive(id)) {
toast({
id,
title: t('common.success'),
description: t('controller.devices.finished_reboot', { serialNumber: device.serialNumber }),
description: t('controller.devices.finished_reboot', { serialNumber }),
status: 'success',
duration: 5000,
isClosable: true,
@@ -44,17 +46,17 @@ const RebootMenuItem = ({ device, refresh }: Props) => {
},
},
{
id: `device-disconnected-${device.serialNumber}`,
id: `device-disconnected-${serialNumber}`,
type: 'DEVICE_DISCONNECTION',
serialNumber: device.serialNumber,
serialNumber,
callback: () => {
const id = `device-disconnection-notification-${device.serialNumber}`;
const id = `device-disconnection-notification-${serialNumber}`;
if (!toast.isActive(id)) {
toast({
id,
title: t('common.success'),
description: t('controller.devices.started_reboot', { serialNumber: device.serialNumber }),
description: t('controller.devices.started_reboot', { serialNumber }),
status: 'success',
duration: 5000,
isClosable: true,
@@ -66,17 +68,39 @@ const RebootMenuItem = ({ device, refresh }: Props) => {
]);
},
});
const handleRebootClick = () =>
reboot(undefined, {
onSuccess: () => {
onRebootSuccess();
modalProps.onClose();
},
onError: (e) => {
onRebootError(e as AxiosError);
},
});
return <MenuItem onClick={handleRebootClick}>{t('commands.reboot')}</MenuItem>;
return (
<Modal
{...modalProps}
title={t('commands.reboot')}
topRightButtons={
<Button colorScheme="blue" onClick={handleRebootClick} isLoading={isLoading}>
{t('commands.reboot')}
</Button>
}
options={{
modalSize: 'sm',
}}
>
<Box>
<Center mb={2}>
<Alert status="info" w="unset">
<AlertIcon />
{t('commands.reboot_description')}
</Alert>
</Center>
</Box>
</Modal>
);
};
export default RebootMenuItem;

View File

@@ -33,6 +33,7 @@ import { ConfigureModal } from 'components/Modals/ConfigureModal';
import { EventQueueModal } from 'components/Modals/EventQueueModal';
import FactoryResetModal from 'components/Modals/FactoryResetModal';
import { FirmwareUpgradeModal } from 'components/Modals/FirmwareUpgradeModal';
import { RebootModal } from 'components/Modals/RebootModal';
import { useScriptModal } from 'components/Modals/ScriptModal/useScriptModal';
import { TelemetryModal } from 'components/Modals/TelemetryModal';
import { TraceModal } from 'components/Modals/TraceModal';
@@ -56,6 +57,7 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
const upgradeModalProps = useDisclosure();
const telemetryModalProps = useDisclosure();
const traceModalProps = useDisclosure();
const rebootModalProps = useDisclosure();
const scriptModal = useScriptModal();
const connectedTag = React.useMemo(() => {
if (!getStatus.data) return null;
@@ -142,6 +144,7 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
onOpenConfigureModal={configureModalProps.onOpen}
onOpenTelemetryModal={telemetryModalProps.onOpen}
onOpenScriptModal={scriptModal.openModal}
onOpenRebootModal={rebootModalProps.onOpen}
size="md"
isCompact
/>
@@ -194,6 +197,7 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
onOpenEventQueue={eventQueueProps.onOpen}
onOpenConfigureModal={configureModalProps.onOpen}
onOpenTelemetryModal={telemetryModalProps.onOpen}
onOpenRebootModal={rebootModalProps.onOpen}
onOpenScriptModal={scriptModal.openModal}
size="md"
/>
@@ -217,6 +221,7 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
<EventQueueModal serialNumber={serialNumber} modalProps={eventQueueProps} />
<ConfigureModal serialNumber={serialNumber} modalProps={configureModalProps} />
<TelemetryModal serialNumber={serialNumber} modalProps={telemetryModalProps} />
<RebootModal serialNumber={serialNumber} modalProps={rebootModalProps} />
{scriptModal.modal}
<Box mt={isCompact ? '0px' : '68px'}>
<Masonry

View File

@@ -34,6 +34,7 @@ interface Props {
onOpenConfigureModal: (serialNumber: string) => void;
onOpenTelemetryModal: (serialNumber: string) => void;
onOpenScriptModal: (device: GatewayDevice) => void;
onOpenRebootModal: (serialNumber: string) => void;
}
const Actions: React.FC<Props> = ({
@@ -47,6 +48,7 @@ const Actions: React.FC<Props> = ({
onOpenConfigureModal,
onOpenTelemetryModal,
onOpenScriptModal,
onOpenRebootModal,
}) => {
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
@@ -102,6 +104,7 @@ const Actions: React.FC<Props> = ({
onOpenConfigureModal={onOpenConfigureModal}
onOpenTelemetryModal={onOpenTelemetryModal}
onOpenScriptModal={onOpenScriptModal}
onOpenRebootModal={onOpenRebootModal}
/>
<Tooltip hasArrow label={t('common.view_details')} placement="top">
<Link href={`#/devices/${device.serialNumber}`}>

View File

@@ -20,6 +20,7 @@ import { ConfigureModal } from 'components/Modals/ConfigureModal';
import { EventQueueModal } from 'components/Modals/EventQueueModal';
import FactoryResetModal from 'components/Modals/FactoryResetModal';
import { FirmwareUpgradeModal } from 'components/Modals/FirmwareUpgradeModal';
import { RebootModal } from 'components/Modals/RebootModal';
import { useScriptModal } from 'components/Modals/ScriptModal/useScriptModal';
import { TelemetryModal } from 'components/Modals/TelemetryModal';
import { TraceModal } from 'components/Modals/TraceModal';
@@ -58,6 +59,7 @@ const DeviceListCard = () => {
const eventQueueProps = useDisclosure();
const telemetryModalProps = useDisclosure();
const configureModalProps = useDisclosure();
const rebootModalProps = useDisclosure();
const scriptModal = useScriptModal();
const getCount = useGetDeviceCount({ enabled: true });
const getDevices = useGetDevices({
@@ -96,6 +98,10 @@ const DeviceListCard = () => {
setSerialNumber(serial);
configureModalProps.onOpen();
};
const onOpenReboot = (serial: string) => {
setSerialNumber(serial);
rebootModalProps.onOpen();
};
const badgeCell = React.useCallback(
(device: DeviceWithStatus) => (
@@ -210,6 +216,7 @@ const DeviceListCard = () => {
onOpenConfigureModal={onOpenConfigure}
onOpenTelemetryModal={onOpenTelemetry}
onOpenScriptModal={scriptModal.openModal}
onOpenRebootModal={onOpenReboot}
/>
),
[],
@@ -410,6 +417,7 @@ const DeviceListCard = () => {
<EventQueueModal modalProps={eventQueueProps} serialNumber={serialNumber} />
<ConfigureModal modalProps={configureModalProps} serialNumber={serialNumber} />
<TelemetryModal modalProps={telemetryModalProps} serialNumber={serialNumber} />
<RebootModal modalProps={rebootModalProps} serialNumber={serialNumber} />
{scriptModal.modal}
</>
);