2.5.20: memory graph addded and can choose between interfaces

This commit is contained in:
Charles
2022-01-13 15:53:29 +01:00
parent 1e08ccaae3
commit 9576079bfa
9 changed files with 196 additions and 37 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "ucentral-client",
"version": "2.5.19",
"version": "2.5.20",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "ucentral-client",
"version": "2.5.19",
"version": "2.5.20",
"dependencies": {
"@coreui/coreui": "^3.4.0",
"@coreui/icons": "^2.0.1",

View File

@@ -1,6 +1,6 @@
{
"name": "ucentral-client",
"version": "2.5.19",
"version": "2.5.20",
"dependencies": {
"@coreui/coreui": "^3.4.0",
"@coreui/icons": "^2.0.1",

View File

@@ -47,6 +47,7 @@
"cancel": "Abbrechen",
"certificate": "Zertifikat",
"certificates": "Zertifikate",
"claim": "Anspruch",
"clear": "Löschen",
"close": "Schließen",
"code": "Code",
@@ -162,6 +163,7 @@
"recorded": "Verzeichnet",
"refresh": "Aktualisierung",
"refresh_device": "Gerät aktualisieren",
"remove_claim": "Anspruch entfernen",
"required": "Erforderlich",
"result": "Ergebnis",
"save": "Sparen",
@@ -657,9 +659,11 @@
"data": "Daten (KB)",
"latest_statistics": "Neueste Statistiken",
"lifetime_stats": "Lifetime-Statistik",
"memory": "Erinnerung",
"no_interfaces": "Keine Statistiken zur Schnittstellenlebensdauer verfügbar",
"show_latest": "Letzte Statistik",
"title": "Statistiken"
"title": "Statistiken",
"used": "Verwendeter Speicher %"
},
"status": {
"connection_status": "Status",
@@ -676,13 +680,17 @@
"used_total_memory": "{{used}} verwendet / {{total}} insgesamt"
},
"subscriber": {
"add_device_subscriber_explanation": "Um andere Geräte zu reklamieren, kannst du unsere Suchleiste verwenden oder direkt aus der Tabelle reklamieren. Wenn ein Gerät bereits von einem Benutzer beansprucht wurde, müssen Sie zu dessen Details gehen und die Zuweisung aufheben, bevor Sie es beanspruchen.",
"create": "Abonnenten erstellen",
"devices_one": "{{count}} Gerät",
"devices_other": "{{count}} Geräte",
"edit": "Abonnent bearbeiten",
"error_create": "Fehler beim Erstellen des Abonnenten: {{error}}",
"error_delete": "Fehler beim Löschen des Abonnenten: {{error}}",
"error_fetching": "Fehler beim Abrufen von Abonnenten: {{error}}",
"error_fetching_single": "Fehler beim Abrufen des Abonnenten: {{error}}",
"error_update": "Fehler beim Aktualisieren des Abonnenten: {{error}}",
"is_already_claimed": "wird bereits beansprucht von",
"subscribers": "Abonnenten",
"success_create": "Abonnent erfolgreich erstellt!",
"success_delete": "Abonnent erfolgreich gelöscht!",

View File

@@ -47,6 +47,7 @@
"cancel": "Cancel",
"certificate": "Certificate",
"certificates": "Certificates",
"claim": "Claim",
"clear": "Clear",
"close": "Close",
"code": "Code",
@@ -162,6 +163,7 @@
"recorded": "Recorded",
"refresh": "Refresh",
"refresh_device": "Refresh Device",
"remove_claim": "Remove Claim",
"required": "Required",
"result": "Result",
"save": "Save",
@@ -657,9 +659,11 @@
"data": "Data (KB)",
"latest_statistics": "Latest Statistics",
"lifetime_stats": "Lifetime Statistics",
"memory": "Memory",
"no_interfaces": "No interface lifetime statistics available",
"show_latest": "Last Statistics",
"title": "Statistics"
"title": "Statistics",
"used": "Used Memory %"
},
"status": {
"connection_status": "Status",
@@ -676,13 +680,17 @@
"used_total_memory": "{{used}} used / {{total}} total "
},
"subscriber": {
"add_device_subscriber_explanation": "To claim devices, you can use our search bar or claim directly from the table. If a device was already claimed by a user, you will need to go to to their details and unassign it before claiming it.",
"create": "Create Subscriber",
"devices_one": "{{count}} Device",
"devices_other": "{{count}} Devices",
"edit": "Edit Subscriber",
"error_create": "Error creating subscriber: {{error}}",
"error_delete": "Error deleting subscriber: {{error}}",
"error_fetching": "Error fetching subscribers: {{error}}",
"error_fetching_single": "Error fetching subscriber: {{error}}",
"error_update": "Error updating subscriber: {{error}}",
"is_already_claimed": "is already claimed by ",
"subscribers": "Subscribers",
"success_create": "Subscriber successfully created!",
"success_delete": "Subscriber successfully deleted!",

View File

@@ -47,6 +47,7 @@
"cancel": "Cancelar",
"certificate": "Certificado",
"certificates": "Certificados",
"claim": "Reclamación",
"clear": "Claro",
"close": "Cerrar",
"code": "Código",
@@ -162,6 +163,7 @@
"recorded": "Grabado",
"refresh": "Refrescar",
"refresh_device": "Actualizar dispositivo",
"remove_claim": "Quitar reclamo",
"required": "Necesario",
"result": "Resultado",
"save": "Salvar",
@@ -657,9 +659,11 @@
"data": "Datos (KB)",
"latest_statistics": "Últimas estadísticas",
"lifetime_stats": "Estadísticas de por vida",
"memory": "Memoria",
"no_interfaces": "No hay estadísticas de vida útil de la interfaz disponibles",
"show_latest": "Últimas estadísticas",
"title": "estadística"
"title": "estadística",
"used": "Memoria usada %"
},
"status": {
"connection_status": "Estado",
@@ -676,13 +680,17 @@
"used_total_memory": "{{used}} usado / {{total}} total"
},
"subscriber": {
"add_device_subscriber_explanation": "Para reclamar otros dispositivos, puede usar nuestra barra de búsqueda o reclamar directamente desde la tabla. Si un dispositivo ya fue reclamado por un usuario, deberá ir a sus detalles y anular la asignación antes de reclamarlo.",
"create": "Crear suscriptor",
"devices_one": "{{count}} dispositivo",
"devices_other": "{{count}} dispositivos",
"edit": "Editar suscriptor",
"error_create": "Error al crear el suscriptor: {{error}}",
"error_delete": "Error al eliminar el suscriptor: {{error}}",
"error_fetching": "Error al obtener suscriptores: {{error}}",
"error_fetching_single": "Error al obtener el suscriptor: {{error}}",
"error_update": "Error al actualizar el suscriptor: {{error}}",
"is_already_claimed": "ya es reclamado por",
"subscribers": "Suscriptores",
"success_create": "¡Suscriptor creado correctamente!",
"success_delete": "¡Suscriptor eliminado correctamente!",

View File

@@ -47,6 +47,7 @@
"cancel": "annuler",
"certificate": "Certificat",
"certificates": "Certificats",
"claim": "Prétendre",
"clear": "Clair",
"close": "Fermer",
"code": "Code",
@@ -162,6 +163,7 @@
"recorded": "Enregistré",
"refresh": "Rafraîchir",
"refresh_device": "Actualiser l'appareil",
"remove_claim": "Supprimer la réclamation",
"required": "Champs obligatoires",
"result": "Résultat",
"save": "Sauvegarder",
@@ -657,9 +659,11 @@
"data": "Données (Ko)",
"latest_statistics": "Dernières statistiques",
"lifetime_stats": "Statistiques à vie",
"memory": "mémoire",
"no_interfaces": "Aucune statistique de durée de vie de l'interface disponible",
"show_latest": "Dernières statistiques",
"title": "statistiques"
"title": "statistiques",
"used": "Mémoire utilisée %"
},
"status": {
"connection_status": "Statut",
@@ -676,13 +680,17 @@
"used_total_memory": "{{used}} utilisé / {{total}} total"
},
"subscriber": {
"add_device_subscriber_explanation": "Pour réclamer d'autres appareils, vous pouvez utiliser notre barre de recherche ou réclamer directement à partir du tableau. Si un appareil a déjà été réclamé par un utilisateur, vous devrez accéder à ses détails et le désaffecter avant de le réclamer.",
"create": "Créer un abonné",
"devices_one": "{{count}} Appareil",
"devices_other": "{{count}} appareils",
"edit": "Modifier l'abonné",
"error_create": "Erreur lors de la création de l'abonné : {{error}}",
"error_delete": "Erreur lors de la suppression de l'abonné : {{error}}",
"error_fetching": "Erreur lors de la récupération des abonnés : {{error}}",
"error_fetching_single": "Erreur lors de la récupération de l'abonné : {{error}}",
"error_update": "Erreur lors de la mise à jour de l'abonné : {{error}}",
"is_already_claimed": "est déjà réclamé par",
"subscribers": "Les abonnés",
"success_create": "Abonné créé avec succès !",
"success_delete": "Abonné supprimé avec succès !",

View File

@@ -47,6 +47,7 @@
"cancel": "Cancelar",
"certificate": "Certificado",
"certificates": "Certificados",
"claim": "Afirmação",
"clear": "Claro",
"close": "Perto",
"code": "Código",
@@ -162,6 +163,7 @@
"recorded": "Gravado",
"refresh": "REFRESH",
"refresh_device": "Atualizar dispositivo",
"remove_claim": "Remover reivindicação",
"required": "Requeridos",
"result": "Resultado",
"save": "Salve",
@@ -657,9 +659,11 @@
"data": "Dados (KB)",
"latest_statistics": "Estatísticas mais recentes",
"lifetime_stats": "Estatísticas de vida",
"memory": "Memória",
"no_interfaces": "Nenhuma estatística de tempo de vida da interface disponível",
"show_latest": "Últimas estatísticas",
"title": "Estatisticas"
"title": "Estatisticas",
"used": "Memoria usada %"
},
"status": {
"connection_status": "Status",
@@ -676,13 +680,17 @@
"used_total_memory": "{{used}} usado / {{total}} total"
},
"subscriber": {
"add_device_subscriber_explanation": "Para reivindicar outros dispositivos, você pode usar nossa barra de pesquisa ou reivindicar diretamente na tabela. Se um dispositivo já foi reivindicado por um usuário, você precisará acessar os detalhes dele e cancelar a atribuição antes de reivindicá-lo.",
"create": "Criar assinante",
"devices_one": "{{count}} Dispositivo",
"devices_other": "{{count}} dispositivos",
"edit": "Editar Assinante",
"error_create": "Erro ao criar assinante: {{error}}",
"error_delete": "Erro ao excluir assinante: {{error}}",
"error_fetching": "Erro ao buscar assinantes: {{error}}",
"error_fetching_single": "Erro ao buscar assinante: {{error}}",
"error_update": "Erro ao atualizar assinante: {{error}}",
"is_already_claimed": "já é reivindicado por",
"subscribers": "Inscritos",
"success_create": "Assinante criado com sucesso!",
"success_delete": "Assinante excluído com sucesso!",

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { v4 as createUuid } from 'uuid';
import axiosInstance from 'utils/axiosInstance';
@@ -7,12 +8,14 @@ import { unixToTime, capitalizeFirstLetter } from 'utils/helper';
import eventBus from 'utils/eventBus';
import DeviceStatisticsChart from './DeviceStatisticsChart';
const StatisticsChartList = () => {
const StatisticsChartList = ({ setOptions, section }) => {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const { currentToken, endpoints } = useAuth();
const { deviceSerialNumber } = useDevice();
const [statOptions, setStatOptions] = useState({
interfaceList: [],
memory: [],
settings: {},
});
@@ -23,6 +26,24 @@ const StatisticsChartList = () => {
return 0;
});
// Looping through data to build our memory graph data
const memoryUsed = {
titleName: t('statistics.memory'),
name: '% Used',
backgroundColor: 'rgb(228,102,81,0.9)',
data: [],
fill: true,
};
for (const log of sortedData) {
memoryUsed.data.push(
Math.floor(
((log.data.unit.memory.total - log.data.unit.memory.free) / log.data.unit.memory.total) *
100,
),
);
}
// This dictionary will have a key that is the interface name and a value of it's index in the final array
const interfaceTypes = {};
const interfaceList = [];
@@ -69,7 +90,7 @@ const StatisticsChartList = () => {
}
}
const options = {
const interfaceOptions = {
chart: {
id: 'chart',
group: 'txrx',
@@ -105,25 +126,97 @@ const StatisticsChartList = () => {
},
};
const memoryOptions = {
chart: {
id: 'chart',
},
stroke: {
curve: 'smooth',
},
xaxis: {
title: {
text: 'Time',
style: {
fontSize: '15px',
},
},
categories,
tickAmount: 20,
},
yaxis: {
min: 0,
max: 100,
tickAmount: 5, // set tickAmount to split x-axis
ticks: { min: 0, max: 100, stepSize: 20 },
title: {
text: t('statistics.used'),
style: {
fontSize: '15px',
},
},
},
legend: {
position: 'top',
horizontalAlign: 'right',
float: true,
},
};
const newOptions = {
interfaceList,
settings: options,
memory: [[memoryUsed]],
interfaceOptions,
memoryOptions,
};
if (statOptions !== newOptions) {
setStatOptions(newOptions);
const sectionOptions = newOptions.interfaceList.map((opt) => ({
value: opt[0].titleName,
label: opt[0].titleName,
}));
setOptions([...sectionOptions, { value: 'memory', label: t('statistics.memory') }]);
setStatOptions({ ...newOptions });
}
};
const getInterface = useCallback(() => {
if (statOptions.interfaceList.length === 0) return <p>N/A</p>;
const interfaceToShow = statOptions.interfaceList.find(
(inter) => inter[0].titleName === section,
);
if (interfaceToShow) {
const options = {
data: interfaceToShow,
options: {
...statOptions.interfaceOptions,
title: {
text: capitalizeFirstLetter(interfaceToShow[0].titleName),
align: 'left',
style: {
fontSize: '25px',
},
},
},
};
return (
<div key={createUuid()}>
<DeviceStatisticsChart chart={options} />
</div>
);
}
return <p>N/A</p>;
}, [statOptions, section]);
const getStatistics = () => {
setLoading(true);
const options = {
headers: {
Accept: 'application/json',
Authorization: `Bearer ${currentToken}`,
},
params: {
serialNumber: '24f5a207a130',
},
};
axiosInstance
@@ -134,7 +227,8 @@ const StatisticsChartList = () => {
.then((response) => {
transformIntoDataset(response.data.data);
})
.catch(() => {});
.catch(() => {})
.finally(() => setLoading(false));
};
useEffect(() => {
@@ -153,28 +247,36 @@ const StatisticsChartList = () => {
return (
<div>
{statOptions.interfaceList.map((data) => {
const options = {
data,
options: {
...statOptions.settings,
title: {
text: capitalizeFirstLetter(data[0].titleName),
align: 'left',
style: {
fontSize: '25px',
{section !== 'memory' && !loading && getInterface()}
{section === 'memory' &&
!loading &&
statOptions.memory.map((data) => {
const options = {
data,
options: {
...statOptions.memoryOptions,
title: {
text: capitalizeFirstLetter(data[0].titleName),
align: 'left',
style: {
fontSize: '25px',
},
},
},
},
};
return (
<div key={createUuid()}>
<DeviceStatisticsChart chart={options} />
</div>
);
})}
};
return (
<div key={createUuid()}>
<DeviceStatisticsChart chart={options} section={section} />
</div>
);
})}
</div>
);
};
StatisticsChartList.propTypes = {
setOptions: PropTypes.func.isRequired,
section: PropTypes.string.isRequired,
};
export default React.memo(StatisticsChartList);

View File

@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { CCard, CCardHeader, CCardBody, CPopover, CButton } from '@coreui/react';
import { v4 as createUuid } from 'uuid';
import { CCard, CCardHeader, CCardBody, CPopover, CButton, CSelect } from '@coreui/react';
import { cilSync } from '@coreui/icons';
import CIcon from '@coreui/icons-react';
import eventBus from 'utils/eventBus';
@@ -12,6 +13,8 @@ const DeviceStatisticsCard = () => {
const { t } = useTranslation();
const [showLatestModal, setShowLatestModal] = useState(false);
const [showLifetimeModal, setShowLifetimeModal] = useState(false);
const [options, setOptions] = useState([]);
const [section, setSection] = useState('memory');
const toggleLatestModal = () => {
setShowLatestModal(!showLatestModal);
@@ -47,10 +50,24 @@ const DeviceStatisticsCard = () => {
{t('statistics.show_latest')}
</CButton>
</div>
<div className="pl-2">
<CSelect
custom
value={section}
disabled={options.length === 0}
onChange={(e) => setSection(e.target.value)}
>
{options.map((opt) => (
<option value={opt.value} key={createUuid()}>
{opt.label}
</option>
))}
</CSelect>
</div>
</div>
</CCardHeader>
<CCardBody className="p-1">
<StatisticsChartList />
<StatisticsChartList setOptions={setOptions} section={section} />
</CCardBody>
</CCard>
<LatestStatisticsmodal show={showLatestModal} toggle={toggleLatestModal} />