Compare commits

..

2 Commits

Author SHA1 Message Date
TIP Automation User
f23abf0f4a Chg: update image tag in helm values to v3.1.0 2024-06-29 16:50:30 +00:00
TIP Automation User
eccff13fb2 Chg: update image tag in helm values to v3.1.0-RC1 2024-06-09 17:01:51 +00:00
12 changed files with 94 additions and 423 deletions

1
.env Normal file
View File

@@ -0,0 +1 @@
VITE_UCENTRALSEC_URL="https://ucentral.dpaas.arilia.com:16001"

View File

@@ -20,7 +20,7 @@ defaults:
jobs: jobs:
docker: docker:
runs-on: ubuntu-latest runs-on: ubuntu-20.04
env: env:
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
DOCKER_REGISTRY_USERNAME: ucentral DOCKER_REGISTRY_USERNAME: ucentral

View File

@@ -11,7 +11,7 @@ defaults:
jobs: jobs:
helm-package: helm-package:
runs-on: ubuntu-latest runs-on: ubuntu-20.04
env: env:
HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/ HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
HELM_REPO_USERNAME: ucentral HELM_REPO_USERNAME: ucentral

View File

@@ -8,7 +8,7 @@ fullnameOverride: ""
images: images:
owgwui: owgwui:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw-ui repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw-ui
tag: v4.0.0 tag: v3.1.0
pullPolicy: Always pullPolicy: Always
services: services:

32
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "ucentral-client", "name": "ucentral-client",
"version": "3.2.0", "version": "3.1.0(5)",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ucentral-client", "name": "ucentral-client",
"version": "3.2.0", "version": "3.1.0(5)",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@chakra-ui/anatomy": "^2.1.1", "@chakra-ui/anatomy": "^2.1.1",
@@ -3540,7 +3540,7 @@
}, },
"node_modules/@jridgewell/resolve-uri": { "node_modules/@jridgewell/resolve-uri": {
"version": "3.1.0", "version": "3.1.0",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
@@ -3548,7 +3548,7 @@
}, },
"node_modules/@jridgewell/set-array": { "node_modules/@jridgewell/set-array": {
"version": "1.1.2", "version": "1.1.2",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
@@ -3556,7 +3556,7 @@
}, },
"node_modules/@jridgewell/source-map": { "node_modules/@jridgewell/source-map": {
"version": "0.3.2", "version": "0.3.2",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/gen-mapping": "^0.3.0",
@@ -3565,7 +3565,7 @@
}, },
"node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": {
"version": "0.3.2", "version": "0.3.2",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/set-array": "^1.0.1", "@jridgewell/set-array": "^1.0.1",
@@ -3578,12 +3578,12 @@
}, },
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14", "version": "1.4.14",
"dev": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
"version": "0.3.17", "version": "0.3.17",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/resolve-uri": "3.1.0", "@jridgewell/resolve-uri": "3.1.0",
@@ -4374,7 +4374,7 @@
"version": "18.15.11", "version": "18.15.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz",
"integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==",
"dev": true "devOptional": true
}, },
"node_modules/@types/parse-json": { "node_modules/@types/parse-json": {
"version": "4.0.0", "version": "4.0.0",
@@ -4419,7 +4419,7 @@
"version": "18.0.11", "version": "18.0.11",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz",
"integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==",
"dev": true, "devOptional": true,
"dependencies": { "dependencies": {
"@types/react": "*" "@types/react": "*"
} }
@@ -4753,7 +4753,7 @@
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.8.0", "version": "8.8.0",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
@@ -5174,7 +5174,7 @@
}, },
"node_modules/buffer-from": { "node_modules/buffer-from": {
"version": "1.1.2", "version": "1.1.2",
"dev": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/builtin-modules": { "node_modules/builtin-modules": {
@@ -9781,7 +9781,7 @@
}, },
"node_modules/source-map-support": { "node_modules/source-map-support": {
"version": "0.5.21", "version": "0.5.21",
"dev": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"buffer-from": "^1.0.0", "buffer-from": "^1.0.0",
@@ -9790,7 +9790,7 @@
}, },
"node_modules/source-map-support/node_modules/source-map": { "node_modules/source-map-support/node_modules/source-map": {
"version": "0.6.1", "version": "0.6.1",
"dev": true, "devOptional": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@@ -10080,7 +10080,7 @@
}, },
"node_modules/terser": { "node_modules/terser": {
"version": "5.15.1", "version": "5.15.1",
"dev": true, "devOptional": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"@jridgewell/source-map": "^0.3.2", "@jridgewell/source-map": "^0.3.2",
@@ -10097,7 +10097,7 @@
}, },
"node_modules/terser/node_modules/commander": { "node_modules/terser/node_modules/commander": {
"version": "2.20.3", "version": "2.20.3",
"dev": true, "devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/text-table": { "node_modules/text-table": {

View File

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

View File

@@ -1,257 +0,0 @@
import React from 'react';
import {
Modal,
Text,
ModalOverlay,
ModalContent,
ModalBody,
Center,
Spinner,
Checkbox,
Stack,
Table,
Thead,
Tbody,
Tr,
Th,
Td,
} from '@chakra-ui/react';
import { PlugsConnected } from '@phosphor-icons/react';
import { useTranslation } from 'react-i18next';
import { CloseButton } from 'components/Buttons/CloseButton';
import { ResponsiveButton } from 'components/Buttons/ResponsiveButton';
import { ModalHeader } from 'components/Containers/Modal/ModalHeader';
import { useCableDiagnostics } from 'hooks/Network/Devices';
import { ModalProps } from 'models/Modal';
import Button from 'theme/components/button';
import { DataGridColumn, useDataGrid } from 'components/DataTables/DataGrid/useDataGrid';
import { DataGrid } from 'components/DataTables/DataGrid';
export type CableDiagnosticsModalProps = {
modalProps: ModalProps;
serialNumber: string;
port: string;
};
type DiagnosticsRow = {
port: string;
linkStatus: string;
pairA: string;
pairB: string;
pairC: string;
pairD: string;
type: string;
};
type OpticalRow = {
port: string;
vendorName: string;
formFactor: string;
partNumber: string;
serialNumber: string;
temperature: string;
txPower: string;
rxPower: string;
revision: string;
};
export const CableDiagnosticsModal = ({
modalProps: { isOpen, onClose },
serialNumber,
port,
}: CableDiagnosticsModalProps) => {
const { t } = useTranslation();
const [selectedPorts, setSelectedPorts] = React.useState<string[]>([]);
const [diagnosticsResult, setDiagnosticsResult] = React.useState<any>(null);
const { mutateAsync: diagnose, isLoading } = useCableDiagnostics({ serialNumber });
const handlePortToggle = (port: string) => {
setSelectedPorts((prev) => (prev.includes(port) ? prev.filter((p) => p !== port) : [...prev, port]));
};
const handleDiagnose = async () => {
if (port) {
try {
const result = await diagnose([port]);
setDiagnosticsResult(result);
} catch (error) {
console.error('Error diagnosing cable:', error);
}
}
};
const tableController = useDataGrid({
tableSettingsId: 'cable.diagnostics.table',
defaultOrder: ['port', 'linkStatus', 'pairA', 'pairB', 'pairC', 'pairD', 'type'],
showAllRows: true,
});
const columns: DataGridColumn<DiagnosticsRow | OpticalRow>[] = React.useMemo(() => {
const data = diagnosticsResult?.results?.status?.text?.[port];
const isOpticalData = data && 'form-factor' in data;
return isOpticalData
? [
{
id: 'vendorName',
header: 'Vendor Name',
accessorKey: 'vendorName',
},
{
id: 'formFactor',
header: 'Form Factor',
accessorKey: 'formFactor',
},
{
id: 'partNumber',
header: 'Part Number',
accessorKey: 'partNumber',
},
{
id: 'serialNumber',
header: 'Serial Number',
accessorKey: 'serialNumber',
},
{
id: 'temperature',
header: 'Temperature',
accessorKey: 'temperature',
},
{
id: 'txPower',
header: 'TX Power',
accessorKey: 'txPower',
},
{
id: 'rxPower',
header: 'RX Power',
accessorKey: 'rxPower',
},
{
id: 'revision',
header: 'Revision',
accessorKey: 'revision',
},
]
: [
{
id: 'port',
header: 'Port',
accessorKey: 'port',
},
{
id: 'linkStatus',
header: 'Link Status',
accessorKey: 'linkStatus',
},
{
id: 'pairA',
header: 'Pair A',
accessorKey: 'pairA',
},
{
id: 'pairB',
header: 'Pair B',
accessorKey: 'pairB',
},
{
id: 'pairC',
header: 'Pair C',
accessorKey: 'pairC',
},
{
id: 'pairD',
header: 'Pair D',
accessorKey: 'pairD',
},
{
id: 'type',
header: 'Type',
accessorKey: 'type',
},
];
}, [diagnosticsResult]);
const formatDiagnosticsData = (result: any): (DiagnosticsRow | OpticalRow)[] => {
if (!result?.results?.status?.text?.[port]) return [];
const data = result.results.status.text[port];
if (data['form-factor']) {
return [
{
port,
vendorName: data['vendor-name'] || 'N/A',
formFactor: data['form-factor'] || 'N/A',
partNumber: data['part-number'] || 'N/A',
serialNumber: data['serial-number'] || 'N/A',
temperature: data.temperature ? `${data.temperature.toFixed(2)}` : 'N/A',
txPower: data['tx-optical-power'] ? `${data['tx-optical-power']}` : 'N/A',
rxPower: data['rx-optical-power'] ? `${data['rx-optical-power']}` : 'N/A',
revision: data.revision || 'N/A',
},
];
}
return [
{
port,
linkStatus: data['link-status'],
pairA: `${data['pair-A'].meters} (${data['pair-A'].status})`,
pairB: `${data['pair-B'].meters} (${data['pair-B'].status})`,
pairC: `${data['pair-C'].meters} (${data['pair-C'].status})`,
pairD: `${data['pair-D'].meters} (${data['pair-D'].status})`,
type: data.type,
},
];
};
return (
<Modal onClose={onClose} isOpen={isOpen} size="xl">
<ModalOverlay />
<ModalContent maxW="50vw">
<ModalHeader title={t('commands.cable_diagnostics')} right={<CloseButton onClick={onClose} />} />
<ModalBody pb={6}>
{isLoading ? (
<Center my={4} flexDirection="column" gap={4}>
<Spinner size="lg" />
<Text>Please wait...</Text>
<Text fontSize="sm" color="gray.500">
Please do not close this window. This may take a few seconds.
</Text>
</Center>
) : (
<Center flexDirection="column" gap={4}>
<ResponsiveButton
color="blue"
icon={<PlugsConnected size={20} />}
label={`${
diagnosticsResult && formatDiagnosticsData(diagnosticsResult).length > 0 ? 'Retake' : 'Start'
} Test for Port ${port}`}
onClick={handleDiagnose}
isLoading={isLoading}
isDisabled={!port}
isCompact={false}
/>
{diagnosticsResult && formatDiagnosticsData(diagnosticsResult).length > 0 && (
<DataGrid<DiagnosticsRow | OpticalRow>
controller={tableController}
header={{
title: '',
objectListed: 'Cable Diagnostics',
}}
columns={columns}
isLoading={isLoading}
data={formatDiagnosticsData(diagnosticsResult)}
options={{
isHidingControls: true,
}}
/>
)}
</Center>
)}
</ModalBody>
</ModalContent>
</Modal>
);
};

View File

@@ -377,40 +377,6 @@ export const useWifiScanDevice = ({ serialNumber }: { serialNumber: string }) =>
); );
}; };
export const useCableDiagnostics = ({ serialNumber }: { serialNumber: string }) => {
const toast = useToast();
const { t } = useTranslation();
return useMutation(
(ports: string[]): Promise<unknown> =>
axiosGw
.post(`device/${serialNumber}/cable-diagnostics`, {
serial: serialNumber,
ports,
when: 0,
})
.then(({ data }) => data),
{
onSuccess: (data) => {
console.log('Success data: ', data);
},
onError: (e: AxiosError) => {
toast({
id: uuid(),
title: t('common.error'),
description: t('commands.cablediagnostics_error', {
e: e?.response?.data?.ErrorDescription,
}),
status: 'error',
duration: 5000,
isClosable: true,
position: 'top-right',
});
},
},
);
};
export const useGetDeviceRtty = ({ serialNumber, extraId }: { serialNumber: string; extraId: string | number }) => { export const useGetDeviceRtty = ({ serialNumber, extraId }: { serialNumber: string; extraId: string | number }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const toast = useToast(); const toast = useToast();

View File

@@ -1,19 +1,17 @@
import * as React from 'react'; import * as React from 'react';
import { IconButton, Tooltip, useToast } from '@chakra-ui/react'; import { IconButton, Tooltip, useToast } from '@chakra-ui/react';
import { Power, PlugsConnected } from '@phosphor-icons/react'; import { Power } from '@phosphor-icons/react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { usePowerCycle } from 'hooks/Network/Devices'; import { usePowerCycle } from 'hooks/Network/Devices';
import { useNotification } from 'hooks/useNotification'; import { useNotification } from 'hooks/useNotification';
import { DeviceLinkState } from 'hooks/Network/Statistics'; import { DeviceLinkState } from 'hooks/Network/Statistics';
import { CableDiagnosticsModalProps } from 'components/Modals/CableDiagnosticsModal';
type Props = { type Props = {
state: DeviceLinkState & { name: string }; state: DeviceLinkState & { name: string };
deviceSerialNumber: string; deviceSerialNumber: string;
onOpenCableDiagnostics: (port: string) => void;
}; };
const LinkStateTableActions = ({ state, deviceSerialNumber, onOpenCableDiagnostics }: Props) => { const LinkStateTableActions = ({ state, deviceSerialNumber }: Props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const powerCycle = usePowerCycle(); const powerCycle = usePowerCycle();
const toast = useToast(); const toast = useToast();
@@ -56,27 +54,16 @@ const LinkStateTableActions = ({ state, deviceSerialNumber, onOpenCableDiagnosti
}; };
return ( return (
<> <Tooltip label="Power Cycle" placement="auto-start">
<Tooltip label="Power Cycle" placement="auto-start"> <IconButton
<IconButton aria-label="Power Cycle"
aria-label="Power Cycle" icon={<Power size={20} />}
icon={<Power size={20} />} colorScheme="green"
colorScheme="green" onClick={onPowerCycle}
onClick={onPowerCycle} isLoading={powerCycle.isLoading}
isLoading={powerCycle.isLoading} size="xs"
size="xs" />
/> </Tooltip>
</Tooltip>
<Tooltip label="Cable Diagnostics" placement="auto-start">
<IconButton
aria-label="Cable Diagnostics"
icon={<PlugsConnected size={20} />}
colorScheme="blue"
onClick={() => onOpenCableDiagnostics(state.name)}
size="xs"
/>
</Tooltip>
</>
); );
}; };

View File

@@ -9,12 +9,8 @@ import LinkStateTableActions from './Actions';
type Row = DeviceLinkState & { name: string }; type Row = DeviceLinkState & { name: string };
const dataCell = (v: number) => <DataCell bytes={v} />; const dataCell = (v: number) => <DataCell bytes={v} />;
const actionCell = (row: Row, serialNumber: string, onOpenCableDiagnostics: (port: string) => void) => ( const actionCell = (row: Row, serialNumber: string) => (
<LinkStateTableActions <LinkStateTableActions state={row} deviceSerialNumber={serialNumber} />
state={row}
deviceSerialNumber={serialNumber}
onOpenCableDiagnostics={onOpenCableDiagnostics}
/>
); );
type Props = { type Props = {
@@ -23,10 +19,9 @@ type Props = {
isFetching: boolean; isFetching: boolean;
type: 'upstream' | 'downstream'; type: 'upstream' | 'downstream';
serialNumber: string; serialNumber: string;
onOpenCableDiagnostics: (port: string) => void;
}; };
const LinkStateTable = ({ statistics, refetch, isFetching, type, serialNumber, onOpenCableDiagnostics }: Props) => { const LinkStateTable = ({ statistics, refetch, isFetching, type, serialNumber }: Props) => {
const tableController = useDataGrid({ const tableController = useDataGrid({
tableSettingsId: 'switch.link-state.table', tableSettingsId: 'switch.link-state.table',
defaultOrder: [ defaultOrder: [
@@ -162,16 +157,10 @@ const LinkStateTable = ({ statistics, refetch, isFetching, type, serialNumber, o
id: 'actions', id: 'actions',
header: '', header: '',
accessorKey: '', accessorKey: '',
cell: ({ cell }) => ( cell: ({ cell }) => actionCell(cell.row.original, serialNumber),
<LinkStateTableActions
state={cell.row.original}
deviceSerialNumber={serialNumber}
onOpenCableDiagnostics={onOpenCableDiagnostics}
/>
),
}, },
], ],
[onOpenCableDiagnostics], [],
); );
if (!statistics || statistics?.length === 0) { if (!statistics || statistics?.length === 0) {

View File

@@ -5,8 +5,6 @@ import SwitchInterfaceTable from './SwitchInterfaceTable';
import { DeviceLinkState, useGetDeviceLastStats } from 'hooks/Network/Statistics'; import { DeviceLinkState, useGetDeviceLastStats } from 'hooks/Network/Statistics';
import { Card } from 'components/Containers/Card'; import { Card } from 'components/Containers/Card';
import { CardBody } from 'components/Containers/Card/CardBody'; import { CardBody } from 'components/Containers/Card/CardBody';
import { CableDiagnosticsModal } from 'components/Modals/CableDiagnosticsModal';
import { useDisclosure } from '@chakra-ui/react';
type Props = { type Props = {
serialNumber: string; serialNumber: string;
@@ -14,8 +12,6 @@ type Props = {
const SwitchPortExamination = ({ serialNumber }: Props) => { const SwitchPortExamination = ({ serialNumber }: Props) => {
const [tabIndex, setTabIndex] = React.useState(0); const [tabIndex, setTabIndex] = React.useState(0);
const [selectedPort, setSelectedPort] = React.useState<string>('');
const cableDiagnosticsModalProps = useDisclosure();
const handleTabsChange = React.useCallback((index: number) => { const handleTabsChange = React.useCallback((index: number) => {
setTabIndex(index); setTabIndex(index);
@@ -39,73 +35,63 @@ const SwitchPortExamination = ({ serialNumber }: Props) => {
})); }));
}, [getStats.data]); }, [getStats.data]);
const handleOpenCableDiagnostics = React.useCallback((port: string) => {
setSelectedPort(port);
cableDiagnosticsModalProps.onOpen();
}, []);
return ( return (
<> <Card p={0} mb={4}>
<Card p={0} mb={4}> <CardBody p={0} display="block">
<CardBody p={0} display="block"> <Tabs index={tabIndex} onChange={handleTabsChange} variant="enclosed" w="100%">
<Tabs index={tabIndex} onChange={handleTabsChange} variant="enclosed" w="100%"> <TabList>
<TabList> <Tab fontSize="lg" fontWeight="bold">
<Tab fontSize="lg" fontWeight="bold"> Interfaces
Interfaces </Tab>
</Tab> <Tab fontSize="lg" fontWeight="bold">
<Tab fontSize="lg" fontWeight="bold"> Link-State (Up)
Link-State (Up) </Tab>
</Tab> <Tab fontSize="lg" fontWeight="bold">
<Tab fontSize="lg" fontWeight="bold"> Link-State (Down)
Link-State (Down) </Tab>
</Tab> </TabList>
</TabList> <TabPanels>
<TabPanels> <TabPanel>
<TabPanel> {getStats.data ? (
{getStats.data ? ( <SwitchInterfaceTable
<SwitchInterfaceTable statistics={getStats.data}
statistics={getStats.data} refetch={getStats.refetch}
refetch={getStats.refetch} isFetching={getStats.isFetching}
isFetching={getStats.isFetching} />
/> ) : (
) : ( <Spinner size="xl" />
<Spinner size="xl" /> )}
)} </TabPanel>
</TabPanel> <TabPanel>
<TabPanel> {getStats.data ? (
{getStats.data ? ( <LinkStateTable
<LinkStateTable statistics={upLinkStates}
statistics={upLinkStates} refetch={getStats.refetch}
refetch={getStats.refetch} isFetching={getStats.isFetching}
isFetching={getStats.isFetching} type="upstream"
type="upstream" serialNumber={serialNumber}
serialNumber={serialNumber} />
onOpenCableDiagnostics={handleOpenCableDiagnostics} ) : (
/> <Spinner size="xl" />
) : ( )}
<Spinner size="xl" /> </TabPanel>
)} <TabPanel>
</TabPanel> {getStats.data ? (
<TabPanel> <LinkStateTable
{getStats.data ? ( statistics={downLinkStates}
<LinkStateTable refetch={getStats.refetch}
statistics={downLinkStates} isFetching={getStats.isFetching}
refetch={getStats.refetch} type="downstream"
isFetching={getStats.isFetching} serialNumber={serialNumber}
type="downstream" />
serialNumber={serialNumber} ) : (
onOpenCableDiagnostics={handleOpenCableDiagnostics} <Spinner size="xl" />
/> )}
) : ( </TabPanel>
<Spinner size="xl" /> </TabPanels>
)} </Tabs>
</TabPanel> </CardBody>
</TabPanels> </Card>
</Tabs>
</CardBody>
</Card>
<CableDiagnosticsModal modalProps={cableDiagnosticsModalProps} serialNumber={serialNumber} port={selectedPort} />
</>
); );
}; };

View File

@@ -68,7 +68,6 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
const getHealth = useGetDeviceHealthChecks({ serialNumber, limit: 1 }); const getHealth = useGetDeviceHealthChecks({ serialNumber, limit: 1 });
const { isOpen: isDeleteOpen, onOpen: onDeleteOpen, onClose: onDeleteClose } = useDisclosure(); const { isOpen: isDeleteOpen, onOpen: onDeleteOpen, onClose: onDeleteClose } = useDisclosure();
const scanModalProps = useDisclosure(); const scanModalProps = useDisclosure();
const cableDiagnosticsModalProps = useDisclosure();
const resetModalProps = useDisclosure(); const resetModalProps = useDisclosure();
const eventQueueProps = useDisclosure(); const eventQueueProps = useDisclosure();
const configureModalProps = useDisclosure(); const configureModalProps = useDisclosure();