Merge pull request #179 from stephb9959/main

[WIFI-12515] Using simulated value directly instead of certificate
This commit is contained in:
Charles Bourque
2023-04-19 17:14:31 +02:00
committed by GitHub
8 changed files with 103 additions and 47 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "ucentral-client", "name": "ucentral-client",
"version": "2.10.0(20)", "version": "2.10.0(21)",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ucentral-client", "name": "ucentral-client",
"version": "2.10.0(20)", "version": "2.10.0(21)",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@chakra-ui/icons": "^2.0.18", "@chakra-ui/icons": "^2.0.18",

View File

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

View File

@@ -6,6 +6,7 @@ declare module '@tanstack/table-core' {
interface ColumnMeta<TData extends RowData, TValue> { interface ColumnMeta<TData extends RowData, TValue> {
stopPropagation?: boolean; stopPropagation?: boolean;
alwaysShow?: boolean; alwaysShow?: boolean;
anchored?: boolean;
hasPopover?: boolean; hasPopover?: boolean;
customMaxWidth?: string; customMaxWidth?: string;
customMinWidth?: string; customMinWidth?: string;

View File

@@ -0,0 +1,34 @@
import * as React from 'react';
import { As, Icon, Tag, TagLabel, TagLeftIcon, TagProps, Tooltip, useBreakpoint } from '@chakra-ui/react';
export interface ResponsiveTagProps extends TagProps {
label: string;
icon: As<any>;
tooltip?: string;
isCompact?: boolean;
}
export const ResponsiveTag = React.memo(({ label, icon, tooltip, isCompact, ...props }: ResponsiveTagProps) => {
const breakpoint = useBreakpoint();
const isCompactVersion = isCompact || breakpoint === 'base' || breakpoint === 'sm';
if (isCompactVersion) {
return (
<Tooltip label={tooltip ?? label}>
<Tag size="lg" colorScheme="blue" {...props}>
<Icon as={icon} boxSize="18px" />
</Tag>
</Tooltip>
);
}
return (
<Tooltip label={tooltip ?? label}>
<Tag size="lg" colorScheme="blue" {...props}>
<TagLeftIcon boxSize="18px" as={icon} />
<TagLabel>{label}</TagLabel>
</Tag>
</Tooltip>
);
});

View File

@@ -58,6 +58,7 @@ export type DeviceWithStatus = {
lastConfigurationDownload: number; lastConfigurationDownload: number;
lastContact: number | string; lastContact: number | string;
lastFWUpdate: number; lastFWUpdate: number;
lastRecordedContact: number;
load: number; load: number;
locale: string; locale: string;
location: string; location: string;
@@ -73,6 +74,7 @@ export type DeviceWithStatus = {
restrictedDevice: boolean; restrictedDevice: boolean;
rxBytes: number; rxBytes: number;
serialNumber: string; serialNumber: string;
simulated: boolean;
subscriber: string; subscriber: string;
temperature: number; temperature: number;
txBytes: number; txBytes: number;

View File

@@ -39,6 +39,7 @@ export interface GatewayDevice {
}; };
}; };
serialNumber: string; serialNumber: string;
simulated: boolean;
subscriber: string; subscriber: string;
venue: string; venue: string;
} }

View File

@@ -12,17 +12,13 @@ import {
HStack, HStack,
Portal, Portal,
Spacer, Spacer,
Tag,
TagLabel,
TagLeftIcon,
Tooltip,
useBreakpoint, useBreakpoint,
useColorModeValue, useColorModeValue,
useDisclosure, useDisclosure,
useToast, useToast,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { Circuitry, Heart, HeartBreak, LockSimple, LockSimpleOpen, WifiHigh, WifiSlash } from '@phosphor-icons/react';
import axios from 'axios'; import axios from 'axios';
import { Heart, HeartBreak, LockSimple, LockSimpleOpen, WifiHigh, WifiSlash } from '@phosphor-icons/react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Masonry from 'react-masonry-css'; import Masonry from 'react-masonry-css';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@@ -39,8 +35,8 @@ import DeviceActionDropdown from 'components/Buttons/DeviceActionDropdown';
import { RefreshButton } from 'components/Buttons/RefreshButton'; import { RefreshButton } from 'components/Buttons/RefreshButton';
import { Card } from 'components/Containers/Card'; import { Card } from 'components/Containers/Card';
import { CardHeader } from 'components/Containers/Card/CardHeader'; import { CardHeader } from 'components/Containers/Card/CardHeader';
import { ResponsiveTag } from 'components/Containers/ResponsiveTag';
import GlobalSearchBar from 'components/GlobalSearchBar'; import GlobalSearchBar from 'components/GlobalSearchBar';
import FormattedDate from 'components/InformationDisplays/FormattedDate';
import { ConfigureModal } from 'components/Modals/ConfigureModal'; import { ConfigureModal } from 'components/Modals/ConfigureModal';
import { EventQueueModal } from 'components/Modals/EventQueueModal'; import { EventQueueModal } from 'components/Modals/EventQueueModal';
import FactoryResetModal from 'components/Modals/FactoryResetModal'; import FactoryResetModal from 'components/Modals/FactoryResetModal';
@@ -114,10 +110,11 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
if (!getStatus.data) return null; if (!getStatus.data) return null;
return ( return (
<Tag size="lg" colorScheme={getStatus?.data?.connected ? 'green' : 'red'}> <ResponsiveTag
<TagLeftIcon boxSize="18px" as={getStatus.data.connected ? WifiHigh : WifiSlash} /> label={getStatus?.data?.connected ? t('common.connected') : t('common.disconnected')}
<TagLabel>{getStatus?.data?.connected ? t('common.connected') : t('common.disconnected')}</TagLabel> colorScheme={getStatus?.data?.connected ? 'green' : 'red'}
</Tag> icon={getStatus.data.connected ? WifiHigh : WifiSlash}
/>
); );
}, [getStatus.data]); }, [getStatus.data]);
@@ -133,23 +130,12 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
if (sanityValue === 100) color = 'green'; if (sanityValue === 100) color = 'green';
else if (sanityValue > 80) color = 'yellow'; else if (sanityValue > 80) color = 'yellow';
} }
return ( return (
<Tooltip <ResponsiveTag
hasArrow label={sanity ? `${sanity}%` : t('common.unknown')}
label={ colorScheme={color}
getHealth.data?.values?.[0]?.recorded !== undefined ? ( icon={color === 'green' ? Heart : HeartBreak}
<FormattedDate date={getHealth.data?.values?.[0]?.recorded} /> />
) : (
''
)
}
>
<Tag size="lg" colorScheme={color}>
<TagLeftIcon boxSize="18px" as={color === 'green' ? Heart : HeartBreak} />
<TagLabel>{sanity ? `${sanity}%` : t('common.unknown')}</TagLabel>
</Tag>
</Tooltip>
); );
}, [getStatus.data, getHealth.data]); }, [getStatus.data, getHealth.data]);
@@ -158,21 +144,21 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
if (getDevice.data.restrictionDetails?.developer) if (getDevice.data.restrictionDetails?.developer)
return ( return (
<Tooltip label={t('devices.restricted_overriden')} hasArrow> <ResponsiveTag
<Tag size="lg" colorScheme="green"> label={`${t('devices.restricted')} ${isCompact ? '' : '(Dev Mode)'}`}
<TagLeftIcon boxSize="18px" as={LockSimpleOpen} /> tooltip={t('devices.restricted_overriden')}
<TagLabel> colorScheme="green"
{t('devices.restricted')} {isCompact ? '' : '(Dev Mode)'} icon={LockSimpleOpen}
</TagLabel> />
</Tag>
</Tooltip>
); );
return ( return (
<Tag size="lg" colorScheme="red"> <ResponsiveTag
<TagLeftIcon boxSize="18px" as={LockSimple} /> label={t('devices.restricted')}
<TagLabel>{t('devices.restricted')}</TagLabel> tooltip={t('devices.restricted')}
</Tag> colorScheme="red"
icon={LockSimple}
/>
); );
}, [getDevice.data, isCompact]); }, [getDevice.data, isCompact]);
@@ -189,6 +175,9 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
<CardHeader> <CardHeader>
<HStack spacing={2}> <HStack spacing={2}>
<Heading size="md">{serialNumber}</Heading> <Heading size="md">{serialNumber}</Heading>
{getDevice.data?.simulated ? (
<ResponsiveTag label={t('simulation.simulated')} colorScheme="purple" icon={Circuitry} />
) : null}
{connectedTag} {connectedTag}
{healthTag} {healthTag}
{restrictedTag} {restrictedTag}
@@ -239,6 +228,9 @@ const DevicePageWrapper = ({ serialNumber }: Props) => {
<CardHeader> <CardHeader>
<HStack spacing={2}> <HStack spacing={2}>
<Heading size="md">{serialNumber}</Heading> <Heading size="md">{serialNumber}</Heading>
{getDevice.data?.simulated ? (
<ResponsiveTag label={t('simulation.simulated')} colorScheme="purple" icon={Circuitry} />
) : null}
{connectedTag} {connectedTag}
{healthTag} {healthTag}
{restrictedTag} {restrictedTag}

View File

@@ -81,7 +81,9 @@ const DeviceListCard = () => {
const configureModalProps = useDisclosure(); const configureModalProps = useDisclosure();
const rebootModalProps = useDisclosure(); const rebootModalProps = useDisclosure();
const scriptModal = useScriptModal(); const scriptModal = useScriptModal();
const tableController = useDataGrid({ tableSettingsId: 'gateway.devices.table' }); const tableController = useDataGrid({
tableSettingsId: 'gateway.devices.table',
});
const getCount = useGetDeviceCount({ enabled: true }); const getCount = useGetDeviceCount({ enabled: true });
const getDevices = useGetDevices({ const getDevices = useGetDevices({
pageInfo: { pageInfo: {
@@ -133,14 +135,14 @@ const DeviceListCard = () => {
h="35px" h="35px"
w="35px" w="35px"
borderRadius="50em" borderRadius="50em"
bgColor={BADGE_COLORS[device.verifiedCertificate] ?? 'red'} bgColor={BADGE_COLORS[device.simulated ? 'SIMULATED' : device.verifiedCertificate] ?? 'red'}
alignItems="center" alignItems="center"
display="inline-flex" display="inline-flex"
justifyContent="center" justifyContent="center"
position="relative" position="relative"
> >
<Tooltip <Tooltip
label={`${device.verifiedCertificate} - ${ label={`${device.simulated ? 'SIMULATED' : device.verifiedCertificate} - ${
device.connected ? t('common.connected') : t('common.disconnected') device.connected ? t('common.connected') : t('common.disconnected')
} ${device.restrictedDevice ? `- ${t('devices.restricted')}` : ''}`} } ${device.restrictedDevice ? `- ${t('devices.restricted')}` : ''}`}
> >
@@ -325,14 +327,15 @@ const DeviceListCard = () => {
const temperatureCell = React.useCallback((device: DeviceWithStatus) => { const temperatureCell = React.useCallback((device: DeviceWithStatus) => {
if (!device.connected || device.temperature === 0) return <Center>-</Center>; if (!device.connected || device.temperature === 0) return <Center>-</Center>;
const temperature = device.temperature > 1000 ? device.temperature / 1000 : device.temperature;
let colorScheme = 'red'; let colorScheme = 'red';
if (device.temperature <= 85) colorScheme = 'yellow'; if (temperature <= 85) colorScheme = 'yellow';
if (device.temperature <= 75) colorScheme = 'green'; if (temperature <= 75) colorScheme = 'green';
return ( return (
<Center> <Center>
<Tag borderRadius="full" variant="subtle" colorScheme={colorScheme}> <Tag borderRadius="full" variant="subtle" colorScheme={colorScheme}>
<TagLabel>{fourDigitNumber(device.temperature)}°C</TagLabel> <TagLabel>{fourDigitNumber(temperature)}°C</TagLabel>
<TagRightIcon marginStart="0.1rem" as={colorScheme === 'green' ? ThermometerCold : ThermometerHot} /> <TagRightIcon marginStart="0.1rem" as={colorScheme === 'green' ? ThermometerCold : ThermometerHot} />
</Tag> </Tag>
</Center> </Center>
@@ -349,6 +352,10 @@ const DeviceListCard = () => {
cell: (v) => badgeCell(v.cell.row.original), cell: (v) => badgeCell(v.cell.row.original),
enableSorting: false, enableSorting: false,
meta: { meta: {
columnSelectorOptions: {
label: 'Connection Badge',
},
anchored: true,
customWidth: '35px', customWidth: '35px',
alwaysShow: true, alwaysShow: true,
}, },
@@ -361,6 +368,7 @@ const DeviceListCard = () => {
cell: (v) => serialCell(v.cell.row.original), cell: (v) => serialCell(v.cell.row.original),
enableSorting: false, enableSorting: false,
meta: { meta: {
anchored: true,
alwaysShow: true, alwaysShow: true,
customMaxWidth: '200px', customMaxWidth: '200px',
customWidth: '130px', customWidth: '130px',
@@ -508,6 +516,24 @@ const DeviceListCard = () => {
cell: (v) => uptimeCell(v.cell.row.original), cell: (v) => uptimeCell(v.cell.row.original),
enableSorting: false, enableSorting: false,
}, },
{
id: 'lastRecordedContact',
header: t('analytics.last_connected'),
footer: '',
accessorKey: 'lastRecordedContact',
cell: (v) =>
dateCell(
v.cell.row.original.lastContact !== 0
? v.cell.row.original.lastContact
: v.cell.row.original.lastRecordedContact,
),
enableSorting: false,
meta: {
headerOptions: {
tooltip: t('analytics.last_connected_tooltip'),
},
},
},
{ {
id: 'lastContact', id: 'lastContact',
header: t('analytics.last_contact'), header: t('analytics.last_contact'),