mirror of
https://github.com/Telecominfraproject/wlan-cloud-owprov-ui.git
synced 2025-10-29 17:52:25 +00:00
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "wlan-cloud-owprov-ui",
|
||||
"version": "2.6.83",
|
||||
"version": "2.6.88",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wlan-cloud-owprov-ui",
|
||||
"version": "2.6.83",
|
||||
"version": "2.6.88",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@chakra-ui/icons": "^1.1.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wlan-cloud-owprov-ui",
|
||||
"version": "2.6.83",
|
||||
"version": "2.6.88",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"verify_phone_number": "Verify your phone number"
|
||||
},
|
||||
"analytics": {
|
||||
"airtime": "Airtime",
|
||||
"analyze_sub_venues": "Monitor Sub Venues",
|
||||
"associations": "Associations",
|
||||
"associations_explanation": "Total associations",
|
||||
@@ -36,7 +37,9 @@
|
||||
"average_memory_explanation": "Average percentage of used memory",
|
||||
"average_uptime": "Average Uptime",
|
||||
"average_uptime_explanation": "Average device uptime (DD:HH:MM:SS)",
|
||||
"band": "Band",
|
||||
"board": "Analytics Board",
|
||||
"channel": "Channel",
|
||||
"connected": "connected",
|
||||
"connection_explanation": "{{connectedCount}} connected, {{disconnectedCount}} not connected",
|
||||
"connection_percentage": "{{count}}% connected",
|
||||
@@ -51,11 +54,15 @@
|
||||
"interval": "Interval",
|
||||
"last_connection": "Last Connection",
|
||||
"last_contact": "Last Contact",
|
||||
"last_disconnection": "Last Disconnection",
|
||||
"last_firmware_explanation": "Most common firmware running on the devices analyzed",
|
||||
"last_health": "Last Health",
|
||||
"last_ping": "Last Ping",
|
||||
"live_view": "Live View",
|
||||
"memory": "Memory",
|
||||
"memory_used": "Memory Used",
|
||||
"noise": "Noise",
|
||||
"radio": "Radio",
|
||||
"raw_analytics_data": "Raw Analytics Data",
|
||||
"raw_data": "Raw Data",
|
||||
"retention": "Retention",
|
||||
|
||||
@@ -20,10 +20,10 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import routes from 'router/routes';
|
||||
import { useAuth } from 'contexts/AuthProvider';
|
||||
import { t } from 'i18next';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { uppercaseFirstLetter } from 'utils/stringHelper';
|
||||
import { MapTrifold } from 'phosphor-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const propTypes = {
|
||||
secondary: PropTypes.bool.isRequired,
|
||||
@@ -32,6 +32,7 @@ const propTypes = {
|
||||
};
|
||||
|
||||
const Navbar = ({ secondary, toggleSidebar, isSidebarOpen }) => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, IconButton, Tooltip, useBreakpoint, useDisclosure } from '@chakra-ui/react';
|
||||
import { t } from 'i18next';
|
||||
import { UploadSimple } from 'phosphor-react';
|
||||
import ImportConfigurationModal from './Modal';
|
||||
|
||||
@@ -11,6 +11,7 @@ const propTypes = {
|
||||
};
|
||||
|
||||
const ImportConfigurationButton = ({ setConfig, isDisabled }) => {
|
||||
const { t } = useTranslation();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const breakpoint = useBreakpoint();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import isEqual from 'react-fast-compare';
|
||||
import { ArrowSquareOut, Circle, Heart } from 'phosphor-react';
|
||||
import { t } from 'i18next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGetGatewayUi } from 'hooks/Network/Endpoints';
|
||||
import AssociationsTable from './AssociationsTable';
|
||||
|
||||
@@ -46,6 +46,7 @@ const propTypes = {
|
||||
};
|
||||
|
||||
const DeviceNode = ({ data, isConnectable }) => {
|
||||
const { t } = useTranslation();
|
||||
const bgColor = useColorModeValue('blue.200', 'blue.200');
|
||||
const { data: gwUi } = useGetGatewayUi();
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import isEqual from 'react-fast-compare';
|
||||
import { WifiHigh } from 'phosphor-react';
|
||||
import { t } from 'i18next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const propTypes = {
|
||||
data: PropTypes.shape({
|
||||
@@ -31,6 +31,7 @@ const propTypes = {
|
||||
};
|
||||
|
||||
const EntityNode = ({ data, isConnectable }) => {
|
||||
const { t } = useTranslation();
|
||||
const bgColor = useColorModeValue('teal.200', 'teal.400');
|
||||
|
||||
if (data?.id === '0000-0000-0000') {
|
||||
|
||||
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
|
||||
import { useColorMode } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SimpleStatDisplay from 'components/StatisticsDisplay/SimpleStatDisplay';
|
||||
import { errorColor, successColor, warningColor } from 'utils/colors';
|
||||
|
||||
const propTypes = {
|
||||
data: PropTypes.instanceOf(Object).isRequired,
|
||||
@@ -15,9 +14,11 @@ const HealthStat = ({ data, handleModalClick }) => {
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
const getHealthColor = () => {
|
||||
if (data.avgHealth >= 90) return successColor(colorMode);
|
||||
if (data.avgHealth >= 70) return warningColor(colorMode);
|
||||
return errorColor(colorMode);
|
||||
if (data.avgHealth >= 90)
|
||||
return colorMode === 'light' ? 'var(--chakra-colors-green-200)' : 'var(--chakra-colors-green-400)';
|
||||
if (data.avgHealth >= 70)
|
||||
return colorMode === 'light' ? 'var(--chakra-colors-yellow-200)' : 'var(--chakra-colors-yellow-400)';
|
||||
return colorMode === 'light' ? 'var(--chakra-colors-red-200)' : 'var(--chakra-colors-red-400)';
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
|
||||
import { useColorMode } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SimpleStatDisplay from 'components/StatisticsDisplay/SimpleStatDisplay';
|
||||
import { errorColor, successColor, warningColor } from 'utils/colors';
|
||||
|
||||
const propTypes = {
|
||||
data: PropTypes.instanceOf(Object).isRequired,
|
||||
@@ -15,9 +14,11 @@ const MemoryStat = ({ data, handleModalClick }) => {
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
const getMemoryColor = () => {
|
||||
if (data.avgMemoryUsed < 65) return successColor(colorMode);
|
||||
if (data.avgMemoryUsed < 80) return warningColor(colorMode);
|
||||
return errorColor(colorMode);
|
||||
if (data.avgMemoryUsed < 65)
|
||||
return colorMode === 'light' ? 'var(--chakra-colors-green-200)' : 'var(--chakra-colors-green-400)';
|
||||
if (data.avgMemoryUsed < 80)
|
||||
return colorMode === 'light' ? 'var(--chakra-colors-yellow-200)' : 'var(--chakra-colors-yellow-400)';
|
||||
return colorMode === 'light' ? 'var(--chakra-colors-red-200)' : 'var(--chakra-colors-red-400)';
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -48,7 +48,7 @@ const AssociationCircle = ({ node, style, handleClicks }) => (
|
||||
<Text ml={2}>{node?.data?.name.split('/')[0]}</Text>
|
||||
</PopoverHeader>
|
||||
<PopoverBody>
|
||||
<Heading size="sm">RSSI {node.data.details.rssi}</Heading>
|
||||
<Heading size="sm">RSSI {node.data.details.rssi} db</Heading>
|
||||
<Heading size="sm">TX {bytesString(node.data.details.tx_bytes)}</Heading>
|
||||
<Heading size="sm">RX {bytesString(node.data.details.rx_bytes)}</Heading>
|
||||
</PopoverBody>
|
||||
|
||||
@@ -15,9 +15,10 @@ import {
|
||||
Text,
|
||||
Tooltip,
|
||||
} from '@chakra-ui/react';
|
||||
import { t } from 'i18next';
|
||||
import { ArrowSquareOut, Tag } from 'phosphor-react';
|
||||
import { useGetGatewayUi } from 'hooks/Network/Endpoints';
|
||||
import FormattedDate from 'components/FormattedDate';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const propTypes = {
|
||||
node: PropTypes.instanceOf(Object).isRequired,
|
||||
@@ -28,6 +29,7 @@ const propTypes = {
|
||||
};
|
||||
|
||||
const DeviceCircle = ({ node, style, handleClicks }) => {
|
||||
const { t } = useTranslation();
|
||||
const { data: gwUi } = useGetGatewayUi();
|
||||
|
||||
const handleOpenInGateway = useMemo(
|
||||
@@ -72,6 +74,24 @@ const DeviceCircle = ({ node, style, handleClicks }) => {
|
||||
<Heading size="sm">
|
||||
{node.data.details.deviceInfo.health}% {t('analytics.health')}
|
||||
</Heading>
|
||||
<Heading size="sm">
|
||||
{t('analytics.memory_used')}: {Math.floor(node.data.details.deviceInfo.memory)}%
|
||||
</Heading>
|
||||
<Heading size="sm">
|
||||
{node.data.details.deviceInfo.associations_2g} 2G {t('analytics.associations')}
|
||||
</Heading>
|
||||
<Heading size="sm">
|
||||
{node.data.details.deviceInfo.associations_5g} 5G {t('analytics.associations')}
|
||||
</Heading>
|
||||
<Heading size="sm">
|
||||
{node.data.details.deviceInfo.associations_6g} 6G {t('analytics.associations')}
|
||||
</Heading>
|
||||
{node.data.details.deviceInfo.lastDisconnection !== 0 && (
|
||||
<Heading size="sm">
|
||||
{t('analytics.last_disconnection')}:{' '}
|
||||
<FormattedDate date={node.data.details.deviceInfo.lastDisconnection} />
|
||||
</Heading>
|
||||
)}
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { animated } from '@react-spring/web';
|
||||
import {
|
||||
Heading,
|
||||
Popover,
|
||||
PopoverArrow,
|
||||
PopoverBody,
|
||||
PopoverCloseButton,
|
||||
PopoverContent,
|
||||
PopoverHeader,
|
||||
PopoverTrigger,
|
||||
Portal,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
import { Radio } from 'phosphor-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const propTypes = {
|
||||
node: PropTypes.instanceOf(Object).isRequired,
|
||||
handleClicks: PropTypes.shape({
|
||||
onClick: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
style: PropTypes.instanceOf(Object).isRequired,
|
||||
};
|
||||
|
||||
const RadioCircle = ({ node, style, handleClicks }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Popover isLazy trigger="hover" placement="top">
|
||||
<PopoverTrigger>
|
||||
<animated.circle
|
||||
key={node.id}
|
||||
cx={style.x}
|
||||
cy={style.y}
|
||||
r={style.radius}
|
||||
fill={node.data.details.color}
|
||||
stroke="black"
|
||||
strokeWidth="1px"
|
||||
opacity={style.opacity}
|
||||
onClick={handleClicks.onClick}
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
<PopoverContent>
|
||||
<PopoverArrow />
|
||||
<PopoverCloseButton alignContent="center" mt={1} />
|
||||
<PopoverHeader display="flex">
|
||||
<Radio size={24} weight="fill" />
|
||||
<Text ml={2}>
|
||||
{t('analytics.band')} {node.data.details.band}
|
||||
</Text>
|
||||
</PopoverHeader>
|
||||
<PopoverBody>
|
||||
<Heading size="sm">
|
||||
{t('analytics.channel')}: {node.data.details.channel}
|
||||
</Heading>
|
||||
<Heading size="sm">
|
||||
{t('analytics.airtime')}: {Math.floor(node.data.details.transmitPct)}%
|
||||
</Heading>
|
||||
<Heading size="sm">
|
||||
{t('analytics.noise')}: {node.data.details.noise} db
|
||||
</Heading>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
RadioCircle.propTypes = propTypes;
|
||||
export default React.memo(RadioCircle);
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
Portal,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
import { t } from 'i18next';
|
||||
import { Broadcast } from 'phosphor-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const propTypes = {
|
||||
node: PropTypes.instanceOf(Object).isRequired,
|
||||
@@ -24,42 +24,45 @@ const propTypes = {
|
||||
style: PropTypes.instanceOf(Object).isRequired,
|
||||
};
|
||||
|
||||
const SsidCircle = ({ node, style, handleClicks }) => (
|
||||
<Popover isLazy trigger="hover" placement="top">
|
||||
<PopoverTrigger>
|
||||
<animated.circle
|
||||
key={node.id}
|
||||
cx={style.x}
|
||||
cy={style.y}
|
||||
r={style.radius}
|
||||
fill={node.data.details.color}
|
||||
stroke="black"
|
||||
strokeWidth="1px"
|
||||
opacity={style.opacity}
|
||||
onClick={handleClicks.onClick}
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
<PopoverContent>
|
||||
<PopoverArrow />
|
||||
<PopoverCloseButton alignContent="center" mt={1} />
|
||||
<PopoverHeader display="flex">
|
||||
<Broadcast size={24} weight="fill" />
|
||||
<Text ml={2}>
|
||||
{node.data.details.band}G - {node?.data?.name.split('/')[0]}
|
||||
</Text>
|
||||
</PopoverHeader>
|
||||
<PopoverBody>
|
||||
<Heading size="sm">BSSID {node.data.details.bssid}</Heading>
|
||||
<Heading size="sm">
|
||||
{node.data.children.length} {t('analytics.associations')}
|
||||
</Heading>
|
||||
<Heading size="sm">RSSI {node.data.details.avgRssi}</Heading>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
</Popover>
|
||||
);
|
||||
const SsidCircle = ({ node, style, handleClicks }) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Popover isLazy trigger="hover" placement="top">
|
||||
<PopoverTrigger>
|
||||
<animated.circle
|
||||
key={node.id}
|
||||
cx={style.x}
|
||||
cy={style.y}
|
||||
r={style.radius}
|
||||
fill={node.data.details.color}
|
||||
stroke="black"
|
||||
strokeWidth="1px"
|
||||
opacity={style.opacity}
|
||||
onClick={handleClicks.onClick}
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
<PopoverContent>
|
||||
<PopoverArrow />
|
||||
<PopoverCloseButton alignContent="center" mt={1} />
|
||||
<PopoverHeader display="flex">
|
||||
<Broadcast size={24} weight="fill" />
|
||||
<Text ml={2}>
|
||||
{node.data.details.band}G - {node?.data?.name.split('/')[0]}
|
||||
</Text>
|
||||
</PopoverHeader>
|
||||
<PopoverBody>
|
||||
<Heading size="sm">BSSID: {node.data.details.bssid}</Heading>
|
||||
<Heading size="sm">
|
||||
{t('analytics.associations')}: {node.data.children.length}
|
||||
</Heading>
|
||||
<Heading size="sm">RSSI: {node.data.details.avgRssi} db</Heading>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
SsidCircle.propTypes = propTypes;
|
||||
export default React.memo(SsidCircle);
|
||||
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
Portal,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
import { t } from 'i18next';
|
||||
import { Buildings } from 'phosphor-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const propTypes = {
|
||||
node: PropTypes.instanceOf(Object).isRequired,
|
||||
@@ -24,41 +24,44 @@ const propTypes = {
|
||||
style: PropTypes.instanceOf(Object).isRequired,
|
||||
};
|
||||
|
||||
const VenueCircle = ({ node, style, handleClicks }) => (
|
||||
<Popover isLazy trigger="hover" placement="top">
|
||||
<PopoverTrigger>
|
||||
<animated.circle
|
||||
key={node.id}
|
||||
cx={style.x}
|
||||
cy={style.y}
|
||||
r={style.radius}
|
||||
fill={node.data.details.color}
|
||||
stroke="black"
|
||||
strokeWidth="1px"
|
||||
opacity={style.opacity}
|
||||
onClick={handleClicks.onClick}
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
<PopoverContent>
|
||||
<PopoverArrow />
|
||||
<PopoverCloseButton alignContent="center" mt={1} />
|
||||
<PopoverHeader display="flex">
|
||||
<Buildings weight="fill" size={24} />
|
||||
<Text ml={2}>{node?.data?.name.split('/')[0]}</Text>
|
||||
</PopoverHeader>
|
||||
<PopoverBody>
|
||||
<Heading size="sm">
|
||||
{node.data.children.length} {t('devices.title')}
|
||||
</Heading>
|
||||
<Heading size="sm">
|
||||
{node.data.details.avgHealth}% {t('analytics.average_health')}
|
||||
</Heading>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
</Popover>
|
||||
);
|
||||
const VenueCircle = ({ node, style, handleClicks }) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Popover isLazy trigger="hover" placement="top">
|
||||
<PopoverTrigger>
|
||||
<animated.circle
|
||||
key={node.id}
|
||||
cx={style.x}
|
||||
cy={style.y}
|
||||
r={style.radius}
|
||||
fill={node.data.details.color}
|
||||
stroke="black"
|
||||
strokeWidth="1px"
|
||||
opacity={style.opacity}
|
||||
onClick={handleClicks.onClick}
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<Portal>
|
||||
<PopoverContent>
|
||||
<PopoverArrow />
|
||||
<PopoverCloseButton alignContent="center" mt={1} />
|
||||
<PopoverHeader display="flex">
|
||||
<Buildings weight="fill" size={24} />
|
||||
<Text ml={2}>{node?.data?.name.split('/')[0]}</Text>
|
||||
</PopoverHeader>
|
||||
<PopoverBody>
|
||||
<Heading size="sm">
|
||||
{node.data.children.length} {t('devices.title')}
|
||||
</Heading>
|
||||
<Heading size="sm">
|
||||
{node.data.details.avgHealth}% {t('analytics.average_health')}
|
||||
</Heading>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Portal>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
VenueCircle.propTypes = propTypes;
|
||||
export default React.memo(VenueCircle);
|
||||
|
||||
@@ -4,6 +4,7 @@ import AssociationCircle from './AssociationCircle';
|
||||
import DeviceCircle from './DeviceCircle';
|
||||
import SsidCircle from './SsidCircle';
|
||||
import VenueCircle from './VenueCircle';
|
||||
import RadioCircle from './RadioCircle';
|
||||
|
||||
const propTypes = {
|
||||
node: PropTypes.instanceOf(Object).isRequired,
|
||||
@@ -23,6 +24,7 @@ const CircleComponent = ({ node, style, onClick }) => {
|
||||
if (node.data.type === 'association')
|
||||
return <AssociationCircle node={node} style={style} handleClicks={handleClicks} />;
|
||||
if (node.data.type === 'ssid') return <SsidCircle node={node} style={style} handleClicks={handleClicks} />;
|
||||
if (node.data.type === 'radio') return <RadioCircle node={node} style={style} handleClicks={handleClicks} />;
|
||||
if (node.data.type === 'device') return <DeviceCircle node={node} style={style} handleClicks={handleClicks} />;
|
||||
if (node.data.type === 'venue') return <VenueCircle node={node} style={style} handleClicks={handleClicks} />;
|
||||
return null;
|
||||
|
||||
@@ -43,7 +43,8 @@ const CirclePack = ({ timepoints, fullscreen }) => {
|
||||
};
|
||||
|
||||
let totalHealth = 0;
|
||||
for (const { device_info: deviceInfo, ssid_data: ssidData } of timepoints[pointIndex]) {
|
||||
|
||||
for (const { device_info: deviceInfo, ssid_data: ssidData, radio_data: radioData } of timepoints[pointIndex]) {
|
||||
totalHealth += deviceInfo.health;
|
||||
|
||||
const finalDevice = {
|
||||
@@ -60,6 +61,24 @@ const CirclePack = ({ timepoints, fullscreen }) => {
|
||||
else if (deviceInfo.health >= 70) finalDevice.details.color = warningColor(colorMode);
|
||||
else finalDevice.details.color = errorColor(colorMode);
|
||||
|
||||
const radioChannelIndex = {};
|
||||
|
||||
for (const [i, { band, transmit_pct: transmitPct, ...radioDetails }] of radioData.entries()) {
|
||||
const finalRadio = {
|
||||
name: `${band}/radio/${uuid()}`,
|
||||
type: 'radio',
|
||||
details: {
|
||||
band,
|
||||
transmitPct,
|
||||
...radioDetails,
|
||||
color: transmitPct > 60 ? 'var(--chakra-colors-danger-400)' : 'var(--chakra-colors-success-600)',
|
||||
},
|
||||
children: [],
|
||||
};
|
||||
radioChannelIndex[band] = i;
|
||||
finalDevice.children.push(finalRadio);
|
||||
}
|
||||
|
||||
for (const { ssid, associations, ...ssidDetails } of ssidData) {
|
||||
const finalSsid = {
|
||||
name: `${ssid}/ssid/${uuid()}`,
|
||||
@@ -70,7 +89,7 @@ const CirclePack = ({ timepoints, fullscreen }) => {
|
||||
...ssidDetails,
|
||||
},
|
||||
children: [],
|
||||
scale: associations.length === 0 ? 1 : associations.length * 4,
|
||||
scale: 1,
|
||||
};
|
||||
|
||||
let totalRssi = 0;
|
||||
@@ -83,7 +102,7 @@ const CirclePack = ({ timepoints, fullscreen }) => {
|
||||
rssi: parseDbm(rssi),
|
||||
...associationDetails,
|
||||
},
|
||||
scale: 1,
|
||||
scale: Math.max(1, Math.floor((associationDetails.tx_bytes_bw + associationDetails.rx_bytes_bw) / 1000)),
|
||||
};
|
||||
|
||||
if (rssi >= -45) finalAssociation.details.color = successColor(colorMode);
|
||||
@@ -97,10 +116,8 @@ const CirclePack = ({ timepoints, fullscreen }) => {
|
||||
if (finalSsid.details.avgRssi >= -45) finalSsid.details.color = successColor(colorMode);
|
||||
else if (finalSsid.details.avgRssi >= -60) finalSsid.details.color = warningColor(colorMode);
|
||||
else finalSsid.details.color = errorColor(colorMode);
|
||||
|
||||
finalDevice.children.push(finalSsid);
|
||||
finalDevice.children[radioChannelIndex[ssidDetails.band]].children.push(finalSsid);
|
||||
}
|
||||
|
||||
root.children.push(finalDevice);
|
||||
}
|
||||
|
||||
@@ -132,7 +149,7 @@ const CirclePack = ({ timepoints, fullscreen }) => {
|
||||
value="scale"
|
||||
data={data}
|
||||
enableLabels
|
||||
labelsSkipRadius={32}
|
||||
labelsSkipRadius={42}
|
||||
labelsFilter={(label) => label.node.height === 0}
|
||||
labelTextColor={{
|
||||
from: 'color',
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DateTimePicker from 'components/DatePickers/DateTimePicker';
|
||||
import { Flex, Heading } from '@chakra-ui/react';
|
||||
import { t } from 'i18next';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const propTypes = {
|
||||
start: PropTypes.instanceOf(Date).isRequired,
|
||||
@@ -12,22 +12,26 @@ const propTypes = {
|
||||
isDisabled: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
const CirclePackTimePickers = ({ start, end, setStart, setEnd, isDisabled }) => (
|
||||
<Flex>
|
||||
const CirclePackTimePickers = ({ start, end, setStart, setEnd, isDisabled }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Flex>
|
||||
<Heading size="sm" mt="10px" mr={2}>
|
||||
{t('common.start')}:
|
||||
</Heading>
|
||||
<DateTimePicker date={start} isStart onChange={setStart} isDisabled={isDisabled} />
|
||||
<Flex>
|
||||
<Heading size="sm" mt="10px" mr={2}>
|
||||
{t('common.start')}:
|
||||
</Heading>
|
||||
<DateTimePicker date={start} isStart onChange={setStart} isDisabled={isDisabled} />
|
||||
</Flex>
|
||||
<Flex ml={2}>
|
||||
<Heading size="sm" mt="10px" mr={2}>
|
||||
{t('common.end')}:
|
||||
</Heading>
|
||||
<DateTimePicker date={end} isEnd onChange={setEnd} startDate={start} endDate={end} isDisabled={isDisabled} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex ml={2}>
|
||||
<Heading size="sm" mt="10px" mr={2}>
|
||||
{t('common.end')}:
|
||||
</Heading>
|
||||
<DateTimePicker date={end} isEnd onChange={setEnd} startDate={start} endDate={end} isDisabled={isDisabled} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
CirclePackTimePickers.propTypes = propTypes;
|
||||
export default React.memo(CirclePackTimePickers);
|
||||
|
||||
@@ -5,6 +5,42 @@ export default {
|
||||
gray: {
|
||||
700: '#1f2733',
|
||||
},
|
||||
success: {
|
||||
50: '#deffef',
|
||||
100: '#b4f8d6',
|
||||
200: '#89f3bd',
|
||||
300: '#5deda3',
|
||||
400: '#31e88a',
|
||||
500: '#17ce71',
|
||||
600: '#0ba057',
|
||||
700: '#02733e',
|
||||
800: '#004624',
|
||||
900: '#001908',
|
||||
},
|
||||
warning: {
|
||||
50: '#feffdc',
|
||||
100: '#fbffaf',
|
||||
200: '#f9ff7e',
|
||||
300: '#f6ff4d',
|
||||
400: '#f4ff1f',
|
||||
500: '#dae609',
|
||||
600: '#aab300',
|
||||
700: '#798000',
|
||||
800: '#494d00',
|
||||
900: '#181b00',
|
||||
},
|
||||
danger: {
|
||||
50: '#FFE6E9',
|
||||
100: '#FEB8C1',
|
||||
200: '#FE8B99',
|
||||
300: '#FD5D71',
|
||||
400: '#FD3049',
|
||||
500: '#FD0221',
|
||||
600: '#CA021A',
|
||||
700: '#980114',
|
||||
800: '#65010D',
|
||||
900: '#330007',
|
||||
},
|
||||
},
|
||||
styles: {
|
||||
global: (props) => ({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const successColor = (colorMode = 'light') =>
|
||||
colorMode === 'light' ? 'var(--chakra-colors-green-200)' : 'var(--chakra-colors-green-400)';
|
||||
colorMode === 'light' ? 'var(--chakra-colors-success-600)' : 'var(--chakra-colors-success-600)';
|
||||
export const warningColor = (colorMode = 'light') =>
|
||||
colorMode === 'light' ? 'var(--chakra-colors-yellow-200)' : 'var(--chakra-colors-yellow-400)';
|
||||
colorMode === 'light' ? 'var(--chakra-colors-warning-400)' : 'var(--chakra-colors-warning-400)';
|
||||
export const errorColor = (colorMode = 'light') =>
|
||||
colorMode === 'light' ? 'var(--chakra-colors-red-200)' : 'var(--chakra-colors-red-400)';
|
||||
colorMode === 'light' ? 'var(--chakra-colors-danger-400)' : 'var(--chakra-colors-danger-400)';
|
||||
|
||||
Reference in New Issue
Block a user