import * as React from 'react';
import {
AlertDialog,
AlertDialogBody,
AlertDialogContent,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogOverlay,
Box,
Button,
Heading,
HStack,
Portal,
Spacer,
Tag,
TagLabel,
TagLeftIcon,
Tooltip,
useBreakpoint,
useColorModeValue,
useDisclosure,
useToast,
} from '@chakra-ui/react';
import axios from 'axios';
import { Heart, HeartBreak, LockSimple, LockSimpleOpen, WifiHigh, WifiSlash } from 'phosphor-react';
import { useTranslation } from 'react-i18next';
import Masonry from 'react-masonry-css';
import { useNavigate } from 'react-router-dom';
import DeviceDetails from './Details';
import DeviceLogsCard from './LogsCard';
import DeviceNotes from './Notes';
import RadiusClientsCard from './RadiusClients';
import RestrictionsCard from './RestrictionsCard';
import DeviceStatisticsCard from './StatisticsCard';
import DeviceSummary from './Summary';
import WifiAnalysisCard from './WifiAnalysis';
import { DeleteButton } from 'components/Buttons/DeleteButton';
import DeviceActionDropdown from 'components/Buttons/DeviceActionDropdown';
import { RefreshButton } from 'components/Buttons/RefreshButton';
import { Card } from 'components/Containers/Card';
import { CardHeader } from 'components/Containers/Card/CardHeader';
import GlobalSearchBar from 'components/GlobalSearchBar';
import FormattedDate from 'components/InformationDisplays/FormattedDate';
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';
import { WifiScanModal } from 'components/Modals/WifiScanModal';
import { useDeleteDevice, useGetDevice, useGetDeviceHealthChecks, useGetDeviceStatus } from 'hooks/Network/Devices';
type Props = {
serialNumber: string;
};
const DevicePageWrapper = ({ serialNumber }: Props) => {
const { t } = useTranslation();
const toast = useToast();
const breakpoint = useBreakpoint();
const cancelRef = React.useRef(null);
const navigate = useNavigate();
const { mutateAsync: deleteDevice, isLoading: isDeleting } = useDeleteDevice({
serialNumber,
});
const getDevice = useGetDevice({ serialNumber });
const getStatus = useGetDeviceStatus({ serialNumber });
const getHealth = useGetDeviceHealthChecks({ serialNumber, limit: 1 });
const { isOpen: isDeleteOpen, onOpen: onDeleteOpen, onClose: onDeleteClose } = useDisclosure();
const scanModalProps = useDisclosure();
const resetModalProps = useDisclosure();
const eventQueueProps = useDisclosure();
const configureModalProps = useDisclosure();
const upgradeModalProps = useDisclosure();
const telemetryModalProps = useDisclosure();
const traceModalProps = useDisclosure();
const rebootModalProps = useDisclosure();
const scriptModal = useScriptModal();
// Sticky-top styles
const isCompact = breakpoint === 'base' || breakpoint === 'sm' || breakpoint === 'md';
const boxShadow = useColorModeValue('0px 7px 23px rgba(0, 0, 0, 0.05)', 'none');
const handleDeleteClick = () =>
deleteDevice(serialNumber, {
onSuccess: () => {
toast({
id: `delete-device-success-${serialNumber}`,
title: t('common.success'),
status: 'success',
duration: 5000,
isClosable: true,
position: 'top-right',
});
navigate('/devices');
},
onError: (e) => {
if (axios.isAxiosError(e)) {
toast({
id: `delete-device-error-${serialNumber}`,
title: t('common.error'),
description: e.response?.data?.ErrorDescription,
status: 'error',
duration: 5000,
isClosable: true,
position: 'top-right',
});
}
},
});
const connectedTag = React.useMemo(() => {
if (!getStatus.data) return null;
return (
{getStatus?.data?.connected ? t('common.connected') : t('common.disconnected')}
);
}, [getStatus.data]);
const healthTag = React.useMemo(() => {
if (!getStatus.data || !getStatus.data.connected || !getHealth.data || getHealth.data?.values?.length === 0)
return null;
let color = 'red';
let sanity: number | undefined;
if (getHealth.data?.values?.[0]) {
const { sanity: sanityValue } = getHealth.data.values[0];
sanity = sanityValue;
if (sanityValue === 100) color = 'green';
else if (sanityValue > 80) color = 'yellow';
}
return (
) : (
''
)
}
>
{sanity ? `${sanity}%` : t('common.unknown')}
);
}, [getStatus.data, getHealth.data]);
const restrictedTag = React.useMemo(() => {
if (!getDevice.data || !getDevice.data.restrictedDevice) return null;
if (getDevice.data.restrictionDetails?.developer)
return (
{t('devices.restricted')} {isCompact ? '' : '(Dev Mode)'}
);
return (
{t('devices.restricted')}
);
}, [getDevice.data, isCompact]);
const refresh = () => {
getDevice.refetch();
getStatus.refetch();
getHealth.refetch();
};
return (
<>
{isCompact ? (
{serialNumber}
{connectedTag}
{healthTag}
{restrictedTag}
{getDevice?.data && (
)}
) : (
{serialNumber}
{connectedTag}
{healthTag}
{restrictedTag}
{getDevice?.data && (
)}
)}
{t('crud.delete')} {serialNumber}
{t('crud.delete_confirm', { obj: t('devices.one') })}
{scriptModal.modal}
{getDevice.data && getDevice.data?.hasRADIUSSessions > 0 ? (
) : null}
>
);
};
export default DevicePageWrapper;