Device # in analysis page, UI fix for status card

This commit is contained in:
BourqueCharles
2021-08-09 16:02:05 -04:00
parent ebc44fa1ea
commit 6e90ed67ad
13 changed files with 35 additions and 215 deletions

18
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "ucentral-client",
"version": "2.0.11",
"version": "2.0.12",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "ucentral-client",
"version": "2.0.11",
"version": "2.0.12",
"dependencies": {
"@coreui/coreui": "^3.4.0",
"@coreui/icons": "^2.0.1",
@@ -29,7 +29,7 @@
"react-tooltip": "^4.2.21",
"react-widgets": "^5.1.1",
"sass": "^1.35.1",
"ucentral-libs": "^0.8.51",
"ucentral-libs": "^0.8.52",
"uuid": "^8.3.2"
},
"devDependencies": {
@@ -14311,9 +14311,9 @@
}
},
"node_modules/ucentral-libs": {
"version": "0.8.51",
"resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.8.51.tgz",
"integrity": "sha512-gZHo07Mu1Wl5Gq8fRwRKQOCGVuUC5FA/QrOiLalMahyIhmocRW3rBnE/ieWtV9O3nW5hkBXEpFigiZxX/T9LmA==",
"version": "0.8.52",
"resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.8.52.tgz",
"integrity": "sha512-ifyXRDxzMnV1NzpsFXy6fn2NMtgR1361cHcRBRjPEdAPY7AWRBFoRsq858ZOU9rD0Loe6gGzVnwSF62rhSMTAw==",
"engines": {
"node": ">=10"
},
@@ -26634,9 +26634,9 @@
}
},
"ucentral-libs": {
"version": "0.8.51",
"resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.8.51.tgz",
"integrity": "sha512-gZHo07Mu1Wl5Gq8fRwRKQOCGVuUC5FA/QrOiLalMahyIhmocRW3rBnE/ieWtV9O3nW5hkBXEpFigiZxX/T9LmA==",
"version": "0.8.52",
"resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.8.52.tgz",
"integrity": "sha512-ifyXRDxzMnV1NzpsFXy6fn2NMtgR1361cHcRBRjPEdAPY7AWRBFoRsq858ZOU9rD0Loe6gGzVnwSF62rhSMTAw==",
"requires": {}
},
"unbox-primitive": {

View File

@@ -1,6 +1,6 @@
{
"name": "ucentral-client",
"version": "2.0.11",
"version": "2.0.12",
"dependencies": {
"@coreui/coreui": "^3.4.0",
"@coreui/icons": "^2.0.1",
@@ -23,7 +23,7 @@
"react-tooltip": "^4.2.21",
"react-widgets": "^5.1.1",
"sass": "^1.35.1",
"ucentral-libs": "^0.8.51",
"ucentral-libs": "^0.8.52",
"uuid": "^8.3.2"
},
"main": "index.js",

View File

@@ -56,6 +56,7 @@
"delete": "Löschen",
"delete_device": "Gerät löschen",
"details": "Einzelheiten",
"device": "Gerät #{{serialNumber}}",
"device_dashboard": "Geräte-Dashboard",
"device_delete": "Gerät Nr.{{serialNumber}}löschen",
"device_deleted": "Gerät erfolgreich gelöscht",

View File

@@ -56,6 +56,7 @@
"delete": "Delete",
"delete_device": "Delete Device",
"details": "Details",
"device": "Device #{{serialNumber}}",
"device_dashboard": "Device Dashboard",
"device_delete": "Delete Device #{{serialNumber}}",
"device_deleted": "Device Successfully Deleted",

View File

@@ -56,6 +56,7 @@
"delete": "Borrar",
"delete_device": "Eliminar dispositivo",
"details": "Detalles",
"device": "Dispositivo n.º{{serialNumber}}",
"device_dashboard": "Panel de control del dispositivo",
"device_delete": "Eliminar dispositivo n.º{{serialNumber}}",
"device_deleted": "Dispositivo eliminado correctamente",

View File

@@ -56,6 +56,7 @@
"delete": "Effacer",
"delete_device": "Supprimer le périphérique",
"details": "Détails",
"device": "N° d'appareil{{serialNumber}}",
"device_dashboard": "Tableau de bord de l'appareil",
"device_delete": "Supprimer l'appareil n°{{serialNumber}}",
"device_deleted": "Appareil supprimé avec succès",

View File

@@ -56,6 +56,7 @@
"delete": "Excluir",
"delete_device": "Apagar dispositivo",
"details": "Detalhes",
"device": "Dispositivo nº{{serialNumber}}",
"device_dashboard": "Painel do dispositivo",
"device_delete": "Excluir dispositivo nº{{serialNumber}}",
"device_deleted": "Dispositivo excluído com sucesso",

View File

@@ -1,36 +0,0 @@
import React from 'react';
import { CPopover, CProgress, CProgressBar } from '@coreui/react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { cleanBytesString } from 'utils/helper';
const MemoryBar = ({ usedBytes, totalBytes }) => {
const { t } = useTranslation();
const used = cleanBytesString(usedBytes);
const total = cleanBytesString(totalBytes);
const percentage = Math.floor((usedBytes / totalBytes) * 100);
return (
<CPopover content={t('status.used_total_memory', { used, total })}>
<CProgress>
<CProgressBar value={percentage}>
{percentage >= 25 ? t('status.percentage_used', { percentage, total }) : ''}
</CProgressBar>
<CProgressBar value={100 - percentage} color="transparent">
<div style={{ color: 'black' }}>
{percentage < 25
? t('status.percentage_free', { percentage: 100 - percentage, total })
: ''}
</div>
</CProgressBar>
</CProgress>
</CPopover>
);
};
MemoryBar.propTypes = {
usedBytes: PropTypes.number.isRequired,
totalBytes: PropTypes.number.isRequired,
};
export default React.memo(MemoryBar);

View File

@@ -1,26 +1,7 @@
import React, { useState, useEffect } from 'react';
import {
CCard,
CCardHeader,
CRow,
CCol,
CCardBody,
CBadge,
CModalBody,
CAlert,
CPopover,
CButton,
CSpinner,
} from '@coreui/react';
import CIcon from '@coreui/icons-react';
import { useDevice, useAuth } from 'ucentral-libs';
import { cilSync } from '@coreui/icons';
import { useTranslation } from 'react-i18next';
import axiosInstance from 'utils/axiosInstance';
import { prettyDate, secondsToDetailed } from 'utils/helper';
import MemoryBar from './MemoryBar';
import styles from './index.module.scss';
import { DeviceStatusCard as Card, useDevice, useAuth } from 'ucentral-libs';
const DeviceStatusCard = () => {
const { t } = useTranslation();
@@ -31,11 +12,6 @@ const DeviceStatusCard = () => {
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const transformLoad = (load) => {
if (load === undefined) return t('common.na');
return `${((load / 65536) * 100).toFixed(2)}%`;
};
const getData = () => {
setLoading(true);
const options = {
@@ -74,123 +50,17 @@ const DeviceStatusCard = () => {
if (deviceSerialNumber) getData();
}, [deviceSerialNumber]);
if (!error) {
return (
<CCard>
<CCardHeader>
<CRow>
<CCol>
<div className="text-value-lg">
{t('status.title', { serialNumber: deviceSerialNumber })}
</div>
</CCol>
<CCol>
<div className="text-right">
<CPopover content={t('common.refresh')}>
<CButton color="secondary" onClick={getData} size="sm">
<CIcon content={cilSync} />
</CButton>
</CPopover>
</div>
</CCol>
</CRow>
</CCardHeader>
<CCardBody>
{(!lastStats || !status) && loading ? (
<div className={styles.centerContainer}>
<CSpinner className={styles.spinner} />
</div>
) : (
<div style={{ position: 'relative' }}>
<div className={styles.overlayContainer} hidden={!loading}>
<CSpinner className={styles.spinner} />
</div>
<CRow className="my-2">
<CCol md="5">{t('status.connection_status')} :</CCol>
<CCol xs="10" md="7">
{status?.connected ? (
<CBadge color="success">{t('common.connected')}</CBadge>
) : (
<CBadge color="danger">{t('common.not_connected')}</CBadge>
)}
</CCol>
</CRow>
<CRow className="my-2">
<CCol md="5">{t('status.uptime')} :</CCol>
<CCol xs="10" md="7">
{secondsToDetailed(
lastStats?.unit?.uptime,
t('common.day'),
t('common.days'),
t('common.hour'),
t('common.hours'),
t('common.minute'),
t('common.minutes'),
t('common.second'),
t('common.seconds'),
)}
</CCol>
</CRow>
<CRow className="my-2">
<CCol md="5">{t('status.last_contact')} :</CCol>
<CCol xs="10" md="7">
{prettyDate(status?.lastContact)}
</CCol>
</CRow>
<CRow className="my-2">
<CCol md="5">{t('status.localtime')} :</CCol>
<CCol xs="10" md="7">
{prettyDate(lastStats?.unit?.localtime)}
</CCol>
</CRow>
<CRow className="my-2">
<CCol md="5">{t('status.load_averages')} :</CCol>
<CCol xs="10" md="7">
{transformLoad(lastStats?.unit?.load[0])}
{' / '}
{transformLoad(lastStats?.unit?.load[1])}
{' / '}
{transformLoad(lastStats?.unit?.load[2])}
</CCol>
</CRow>
<CRow className="my-2">
<CCol md="5">{t('status.memory')} :</CCol>
<CCol xs="9" md="6" style={{ paddingTop: '5px' }}>
<MemoryBar
usedBytes={
lastStats?.unit?.memory?.total && lastStats?.unit?.memory?.free
? lastStats?.unit?.memory?.total - lastStats?.unit?.memory?.free
: 0
}
totalBytes={lastStats?.unit?.memory?.total ?? 0}
/>
</CCol>
</CRow>
</div>
)}
</CCardBody>
</CCard>
);
}
return (
<CCard>
<CCardHeader>
<CRow>
<CCol>
<div className="text-value-lg">
{t('status.title', { serialNumber: deviceSerialNumber })}
</div>
</CCol>
</CRow>
</CCardHeader>
<CModalBody>
<CAlert hidden={!error} color="danger" className={styles.centerContainer}>
{t('status.error')}
</CAlert>
</CModalBody>
</CCard>
<Card
t={t}
loading={loading}
error={error}
deviceSerialNumber={deviceSerialNumber}
getData={getData}
status={status}
lastStats={lastStats}
/>
);
};
export default React.memo(DeviceStatusCard);
export default DeviceStatusCard;

View File

@@ -1,20 +0,0 @@
.centerContainer {
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.overlayContainer {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
width: 100%;
height: 100%;
}
.spinner {
height: 50px;
width: 50px;
}

View File

@@ -89,7 +89,7 @@ const TheLayout = () => {
<PageContainer t={t} routes={routes} redirectTo="/devices" />
</ToastProvider>
</div>
<Footer t={t} version="2.0.11" />
<Footer t={t} version="2.0.12" />
</div>
</div>
);

View File

@@ -3,11 +3,11 @@ import { useParams } from 'react-router-dom';
import { CRow, CCol } from '@coreui/react';
import DeviceHealth from 'components/DeviceHealth';
import DeviceConfiguration from 'components/DeviceConfiguration';
import DeviceStatusCard from 'components/DeviceStatusCard';
import CommandHistory from 'components/CommandHistory';
import DeviceLogs from 'components/DeviceLogs';
import DeviceStatisticsCard from 'components/InterfaceStatistics';
import DeviceActionCard from 'components/DeviceActionCard';
import DeviceStatusCard from 'components/DeviceStatusCard';
import axiosInstance from 'utils/axiosInstance';
import { DeviceProvider } from 'ucentral-libs';
@@ -18,11 +18,11 @@ const DevicePage = () => {
<div className="App">
<DeviceProvider axiosInstance={axiosInstance} serialNumber={deviceId}>
<CRow>
<CCol xs="12" sm="6">
<CCol xs="12" lg="6">
<DeviceStatusCard />
<DeviceConfiguration />
</CCol>
<CCol xs="12" sm="6">
<CCol xs="12" lg="6">
<DeviceLogs />
<DeviceHealth />
<DeviceActionCard />

View File

@@ -180,7 +180,10 @@ const WifiAnalysisPage = () => {
<div>
<CCard>
<CCardHeader>
<CRow>
<h5 className="mb-0">{t('common.device', { serialNumber: deviceId })}</h5>
</CCardHeader>
<CCardBody className="overflow-auto" style={{ height: 'calc(100vh - 300px)' }}>
<CRow className="mb-4">
<CCol className="text-center">
<input
type="range"
@@ -198,8 +201,6 @@ const WifiAnalysisPage = () => {
</h5>
</CCol>
</CRow>
</CCardHeader>
<CCardBody className="overflow-auto" style={{ height: 'calc(100vh - 300px)' }}>
<h5 className="pb-3 text-center">{t('wifi_analysis.radios')}</h5>
<RadioAnalysisTable data={selectedRadioStats ?? []} loading={loading} range={range} />
<h5 className="pt-5 pb-3 text-center">{t('wifi_analysis.associations')}</h5>