mirror of
				https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
				synced 2025-10-30 17:57:46 +00:00 
			
		
		
		
	Merge pull request #179 from stephb9959/main
[WIFI-12515] Using simulated value directly instead of certificate
This commit is contained in:
		
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -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", | ||||||
|   | |||||||
| @@ -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", | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								src/@tanstack.react-table.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/@tanstack.react-table.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -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; | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								src/components/Containers/ResponsiveTag/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/components/Containers/ResponsiveTag/index.tsx
									
									
									
									
									
										Normal 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> | ||||||
|  |   ); | ||||||
|  | }); | ||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ export interface GatewayDevice { | |||||||
|     }; |     }; | ||||||
|   }; |   }; | ||||||
|   serialNumber: string; |   serialNumber: string; | ||||||
|  |   simulated: boolean; | ||||||
|   subscriber: string; |   subscriber: string; | ||||||
|   venue: string; |   venue: string; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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} | ||||||
|   | |||||||
| @@ -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'), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Charles Bourque
					Charles Bourque