diff --git a/package-lock.json b/package-lock.json index d589e2a..d14caae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ucentral-client", - "version": "2.10.0(45)", + "version": "2.10.0(48)", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ucentral-client", - "version": "2.10.0(45)", + "version": "2.10.0(48)", "license": "ISC", "dependencies": { "@chakra-ui/icons": "^2.0.18", diff --git a/package.json b/package.json index 856654d..990039f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ucentral-client", - "version": "2.10.0(45)", + "version": "2.10.0(48)", "description": "", "private": true, "main": "index.tsx", diff --git a/src/components/Modals/FirmwareUpgradeModal/index.tsx b/src/components/Modals/FirmwareUpgradeModal/index.tsx index 5da5d73..09ad923 100644 --- a/src/components/Modals/FirmwareUpgradeModal/index.tsx +++ b/src/components/Modals/FirmwareUpgradeModal/index.tsx @@ -11,6 +11,7 @@ import { FormLabel, Switch, Heading, + Text, } from '@chakra-ui/react'; import { Formik, FormikProps } from 'formik'; import { useTranslation } from 'react-i18next'; @@ -32,6 +33,7 @@ export type FirmwareUpgradeModalProps = { export const FirmwareUpgradeModal = ({ modalProps: { isOpen, onClose }, serialNumber }: FirmwareUpgradeModalProps) => { const { t } = useTranslation(); + const [showDevFirmware, { toggle: toggleDev }] = useBoolean(); const [formKey, setFormKey] = React.useState(uuid()); const ref = useRef< | FormikProps<{ @@ -72,7 +74,13 @@ export const FirmwareUpgradeModal = ({ modalProps: { isOpen, onClose }, serialNu } + right={ + <> + {t('controller.firmware.show_dev_releases')} + + + + } /> {isUpgrading || isFetchingDevice || isFetchingFirmware ? ( @@ -104,7 +112,11 @@ export const FirmwareUpgradeModal = ({ modalProps: { isOpen, onClose }, serialNu )} {firmware?.firmwares && ( - + showDevFirmware || !firmw.revision.includes('devel'))} + upgrade={submit} + isLoading={isUpgrading} + /> )} )} diff --git a/src/pages/Devices/Dashboard/OverallHealth.tsx b/src/pages/Devices/Dashboard/OverallHealth.tsx index 43c03d8..6661300 100644 --- a/src/pages/Devices/Dashboard/OverallHealth.tsx +++ b/src/pages/Devices/Dashboard/OverallHealth.tsx @@ -30,11 +30,15 @@ const OverallHealthSimple = ({ data }: Props) => { }, ); - const avg = Math.floor(totalDevices.totalHealth / totalDevices.totalDevices); + const avg = totalDevices.totalDevices === 0 ? -1 : Math.floor(totalDevices.totalHealth / totalDevices.totalDevices); let color: [string, string] = ['green.300', 'green.300']; let icon = Heart; + const text = avg === -1 ? '-' : `${avg}%`; - if (avg >= 80 && avg < 100) { + if (avg === -1) { + icon = Heart; + color = ['gray.300', 'gray.300']; + } else if (avg >= 80 && avg < 100) { icon = Warning; color = ['yellow.300', 'yellow.300']; } else if (avg < 80) { @@ -42,7 +46,7 @@ const OverallHealthSimple = ({ data }: Props) => { color = ['red.300', 'red.300']; } - return { title: `${avg}%`, color, icon }; + return { title: text, color, icon }; }, [data]); return ( diff --git a/src/pages/Devices/ListCard/LocaleCell.tsx b/src/pages/Devices/ListCard/LocaleCell.tsx new file mode 100644 index 0000000..ac77b0d --- /dev/null +++ b/src/pages/Devices/ListCard/LocaleCell.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; +import { CopyIcon } from '@chakra-ui/icons'; +import { Box, IconButton, Text, Tooltip, useClipboard } from '@chakra-ui/react'; +import ReactCountryFlag from 'react-country-flag'; +import { useTranslation } from 'react-i18next'; +import { DeviceWithStatus } from 'hooks/Network/Devices'; + +const ICON_STYLE = { width: '24px', height: '24px', borderRadius: '20px' }; + +type Props = { + device: DeviceWithStatus; +}; + +const DeviceLocaleCell = ({ device }: Props) => { + const { t } = useTranslation(); + const copy = useClipboard(device.ipAddress); + + return ( + + + {device.locale !== '' && device.ipAddress !== '' && ( + + )} + + } + onClick={(e) => { + copy.onCopy(); + e.stopPropagation(); + }} + size="xs" + colorScheme="teal" + hidden={device.ipAddress.length === 0} + mx={0.5} + /> + + {` ${ + device.ipAddress.length > 0 ? device.ipAddress : '-' + }`} + + + ); +}; + +export default DeviceLocaleCell; diff --git a/src/pages/Devices/ListCard/index.tsx b/src/pages/Devices/ListCard/index.tsx index 018a2c2..5f9ca49 100644 --- a/src/pages/Devices/ListCard/index.tsx +++ b/src/pages/Devices/ListCard/index.tsx @@ -9,7 +9,6 @@ import { ThermometerHot, WarningCircle, } from '@phosphor-icons/react'; -import ReactCountryFlag from 'react-country-flag'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import Actions from './Actions'; @@ -20,6 +19,7 @@ import AP from './icons/AP.png'; import IOT from './icons/IOT.png'; import MESH from './icons/MESH.png'; import SWITCH from './icons/SWITCH.png'; +import DeviceLocaleCell from './LocaleCell'; import ProvisioningStatusCell from './ProvisioningStatusCell'; import DeviceUptimeCell from './Uptime'; import { DataGrid } from 'components/DataTables/DataGrid'; @@ -50,7 +50,6 @@ const fourDigitNumber = (v?: number) => { if (fourthChar === '.') return `${str.slice(0, 3)}`; return `${str.slice(0, 4)}`; }; -const ICON_STYLE = { width: '24px', height: '24px', borderRadius: '20px' }; const ICONS = { AP: , @@ -255,19 +254,7 @@ const DeviceListCard = () => { [], ); const uptimeCell = React.useCallback((device: DeviceWithStatus) => , []); - const localeCell = React.useCallback( - (device: DeviceWithStatus) => ( - - - {device.locale !== '' && device.ipAddress !== '' && ( - - )} - {` ${device.ipAddress.length > 0 ? device.ipAddress : '-'}`} - - - ), - [], - ); + const localeCell = React.useCallback((device: DeviceWithStatus) => , []); const gpsCell = React.useCallback((device: DeviceWithStatus) => , []); const numberCell = React.useCallback( (v?: number) => ( @@ -484,9 +471,9 @@ const DeviceListCard = () => { cell: (v) => localeCell(v.cell.row.original), enableSorting: false, meta: { - customMaxWidth: '140px', - customWidth: '130px', - customMinWidth: '130px', + customMaxWidth: '160px', + customWidth: '160px', + customMinWidth: '160px', }, }, {