mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-11-01 02:37:45 +00:00
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "ucentral-client",
|
"name": "ucentral-client",
|
||||||
"version": "2.5.18",
|
"version": "2.5.24",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ucentral-client",
|
"name": "ucentral-client",
|
||||||
"version": "2.5.18",
|
"version": "2.5.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coreui/coreui": "^3.4.0",
|
"@coreui/coreui": "^3.4.0",
|
||||||
"@coreui/icons": "^2.0.1",
|
"@coreui/icons": "^2.0.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ucentral-client",
|
"name": "ucentral-client",
|
||||||
"version": "2.5.18",
|
"version": "2.5.24",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coreui/coreui": "^3.4.0",
|
"@coreui/coreui": "^3.4.0",
|
||||||
"@coreui/icons": "^2.0.1",
|
"@coreui/icons": "^2.0.1",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
"certificate": "Zertifikat",
|
"certificate": "Zertifikat",
|
||||||
"certificates": "Zertifikate",
|
"certificates": "Zertifikate",
|
||||||
|
"claim": "Anspruch",
|
||||||
"clear": "Löschen",
|
"clear": "Löschen",
|
||||||
"close": "Schließen",
|
"close": "Schließen",
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
@@ -117,6 +118,7 @@
|
|||||||
"hours": "std",
|
"hours": "std",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
"invalid_credentials": "Ungültiger Benutzername und / oder Passwort",
|
"invalid_credentials": "Ungültiger Benutzername und / oder Passwort",
|
||||||
|
"invalid_date_explanation": "Ungültiges Datum, bitte verwenden Sie den Kalender, auf den Sie über die Schaltfläche rechts zugreifen können",
|
||||||
"invalid_file": "Die ausgewählte Datei war ungültig, bitte lesen Sie die Anweisungen und passen Sie Ihre Datei entsprechend an",
|
"invalid_file": "Die ausgewählte Datei war ungültig, bitte lesen Sie die Anweisungen und passen Sie Ihre Datei entsprechend an",
|
||||||
"invalid_password": "Dieses Passwort entspricht nicht den grundlegenden Passwortregeln. Bitte besuchen Sie unsere Seite Passwortrichtlinien, um mehr zu erfahren",
|
"invalid_password": "Dieses Passwort entspricht nicht den grundlegenden Passwortregeln. Bitte besuchen Sie unsere Seite Passwortrichtlinien, um mehr zu erfahren",
|
||||||
"invalid_pem": "Ihre PEM-Datei ist ungültig. Es sollte mit '-----BEGIN CERTIFICATE-----' ODER '-----BEGIN PRIVATE KEY-----' beginnen und mit '-----END CERTIFICATE--- enden. --' ODER '-----END PRIVATSCHLÜSSEL-----'",
|
"invalid_pem": "Ihre PEM-Datei ist ungültig. Es sollte mit '-----BEGIN CERTIFICATE-----' ODER '-----BEGIN PRIVATE KEY-----' beginnen und mit '-----END CERTIFICATE--- enden. --' ODER '-----END PRIVATSCHLÜSSEL-----'",
|
||||||
@@ -162,6 +164,7 @@
|
|||||||
"recorded": "Verzeichnet",
|
"recorded": "Verzeichnet",
|
||||||
"refresh": "Aktualisierung",
|
"refresh": "Aktualisierung",
|
||||||
"refresh_device": "Gerät aktualisieren",
|
"refresh_device": "Gerät aktualisieren",
|
||||||
|
"remove_claim": "Anspruch entfernen",
|
||||||
"required": "Erforderlich",
|
"required": "Erforderlich",
|
||||||
"result": "Ergebnis",
|
"result": "Ergebnis",
|
||||||
"save": "Sparen",
|
"save": "Sparen",
|
||||||
@@ -655,11 +658,14 @@
|
|||||||
},
|
},
|
||||||
"statistics": {
|
"statistics": {
|
||||||
"data": "Daten (KB)",
|
"data": "Daten (KB)",
|
||||||
|
"data_mb": "Daten (MB)",
|
||||||
"latest_statistics": "Neueste Statistiken",
|
"latest_statistics": "Neueste Statistiken",
|
||||||
"lifetime_stats": "Lifetime-Statistik",
|
"lifetime_stats": "Lifetime-Statistik",
|
||||||
|
"memory": "Erinnerung",
|
||||||
"no_interfaces": "Keine Statistiken zur Schnittstellenlebensdauer verfügbar",
|
"no_interfaces": "Keine Statistiken zur Schnittstellenlebensdauer verfügbar",
|
||||||
"show_latest": "Letzte Statistik",
|
"show_latest": "Letzte Statistik",
|
||||||
"title": "Statistiken"
|
"title": "Statistiken",
|
||||||
|
"used": "Verwendeter Speicher %"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"connection_status": "Status",
|
"connection_status": "Status",
|
||||||
@@ -671,17 +677,22 @@
|
|||||||
"percentage_free": "{{percentage}}% von {{total}} kostenlos",
|
"percentage_free": "{{percentage}}% von {{total}} kostenlos",
|
||||||
"percentage_used": "{{percentage}}% von {{total}} verwendet",
|
"percentage_used": "{{percentage}}% von {{total}} verwendet",
|
||||||
"title": "#{{serialNumber}} Status",
|
"title": "#{{serialNumber}} Status",
|
||||||
|
"total_memory": "Gesamtspeicher",
|
||||||
"uptime": "Betriebszeit",
|
"uptime": "Betriebszeit",
|
||||||
"used_total_memory": "{{used}} verwendet / {{total}} insgesamt"
|
"used_total_memory": "{{used}} verwendet / {{total}} insgesamt"
|
||||||
},
|
},
|
||||||
"subscriber": {
|
"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",
|
"create": "Abonnenten erstellen",
|
||||||
|
"devices_one": "{{count}} Gerät",
|
||||||
|
"devices_other": "{{count}} Geräte",
|
||||||
"edit": "Abonnent bearbeiten",
|
"edit": "Abonnent bearbeiten",
|
||||||
"error_create": "Fehler beim Erstellen des Abonnenten: {{error}}",
|
"error_create": "Fehler beim Erstellen des Abonnenten: {{error}}",
|
||||||
"error_delete": "Fehler beim Löschen des Abonnenten: {{error}}",
|
"error_delete": "Fehler beim Löschen des Abonnenten: {{error}}",
|
||||||
"error_fetching": "Fehler beim Abrufen von Abonnenten: {{error}}",
|
"error_fetching": "Fehler beim Abrufen von Abonnenten: {{error}}",
|
||||||
"error_fetching_single": "Fehler beim Abrufen des Abonnenten: {{error}}",
|
"error_fetching_single": "Fehler beim Abrufen des Abonnenten: {{error}}",
|
||||||
"error_update": "Fehler beim Aktualisieren des Abonnenten: {{error}}",
|
"error_update": "Fehler beim Aktualisieren des Abonnenten: {{error}}",
|
||||||
|
"is_already_claimed": "wird bereits beansprucht von",
|
||||||
"subscribers": "Abonnenten",
|
"subscribers": "Abonnenten",
|
||||||
"success_create": "Abonnent erfolgreich erstellt!",
|
"success_create": "Abonnent erfolgreich erstellt!",
|
||||||
"success_delete": "Abonnent erfolgreich gelöscht!",
|
"success_delete": "Abonnent erfolgreich gelöscht!",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"certificate": "Certificate",
|
"certificate": "Certificate",
|
||||||
"certificates": "Certificates",
|
"certificates": "Certificates",
|
||||||
|
"claim": "Claim",
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
@@ -117,6 +118,7 @@
|
|||||||
"hours": "hours",
|
"hours": "hours",
|
||||||
"id": "Id",
|
"id": "Id",
|
||||||
"invalid_credentials": "Invalid username and/or password",
|
"invalid_credentials": "Invalid username and/or password",
|
||||||
|
"invalid_date_explanation": "Invalid Date, please use the calendar accessible with the button on the right ",
|
||||||
"invalid_file": "The chosen file was invalid, please read the instructions and adjust your file accordingly",
|
"invalid_file": "The chosen file was invalid, please read the instructions and adjust your file accordingly",
|
||||||
"invalid_password": "This password does not confirm to basic password rules. Please visit our Password Policy page to learn more",
|
"invalid_password": "This password does not confirm to basic password rules. Please visit our Password Policy page to learn more",
|
||||||
"invalid_pem": "Your .pem file is invalid. It should start with '-----BEGIN CERTIFICATE-----' OR '-----BEGIN PRIVATE KEY-----' and it should end with '-----END CERTIFICATE-----' OR '-----END PRIVATE KEY-----'",
|
"invalid_pem": "Your .pem file is invalid. It should start with '-----BEGIN CERTIFICATE-----' OR '-----BEGIN PRIVATE KEY-----' and it should end with '-----END CERTIFICATE-----' OR '-----END PRIVATE KEY-----'",
|
||||||
@@ -162,6 +164,7 @@
|
|||||||
"recorded": "Recorded",
|
"recorded": "Recorded",
|
||||||
"refresh": "Refresh",
|
"refresh": "Refresh",
|
||||||
"refresh_device": "Refresh Device",
|
"refresh_device": "Refresh Device",
|
||||||
|
"remove_claim": "Remove Claim",
|
||||||
"required": "Required",
|
"required": "Required",
|
||||||
"result": "Result",
|
"result": "Result",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
@@ -655,11 +658,14 @@
|
|||||||
},
|
},
|
||||||
"statistics": {
|
"statistics": {
|
||||||
"data": "Data (KB)",
|
"data": "Data (KB)",
|
||||||
|
"data_mb": "Data (MB)",
|
||||||
"latest_statistics": "Latest Statistics",
|
"latest_statistics": "Latest Statistics",
|
||||||
"lifetime_stats": "Lifetime Statistics",
|
"lifetime_stats": "Lifetime Statistics",
|
||||||
|
"memory": "Memory",
|
||||||
"no_interfaces": "No interface lifetime statistics available",
|
"no_interfaces": "No interface lifetime statistics available",
|
||||||
"show_latest": "Last Statistics",
|
"show_latest": "Last Statistics",
|
||||||
"title": "Statistics"
|
"title": "Statistics",
|
||||||
|
"used": "Used Memory %"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"connection_status": "Status",
|
"connection_status": "Status",
|
||||||
@@ -671,17 +677,22 @@
|
|||||||
"percentage_free": "{{percentage}}% of {{total}} free",
|
"percentage_free": "{{percentage}}% of {{total}} free",
|
||||||
"percentage_used": "{{percentage}}% of {{total}} used",
|
"percentage_used": "{{percentage}}% of {{total}} used",
|
||||||
"title": "#{{serialNumber}} Status",
|
"title": "#{{serialNumber}} Status",
|
||||||
|
"total_memory": "Total Memory",
|
||||||
"uptime": "Uptime",
|
"uptime": "Uptime",
|
||||||
"used_total_memory": "{{used}} used / {{total}} total "
|
"used_total_memory": "{{used}} used / {{total}} total "
|
||||||
},
|
},
|
||||||
"subscriber": {
|
"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",
|
"create": "Create Subscriber",
|
||||||
|
"devices_one": "{{count}} Device",
|
||||||
|
"devices_other": "{{count}} Devices",
|
||||||
"edit": "Edit Subscriber",
|
"edit": "Edit Subscriber",
|
||||||
"error_create": "Error creating subscriber: {{error}}",
|
"error_create": "Error creating subscriber: {{error}}",
|
||||||
"error_delete": "Error deleting subscriber: {{error}}",
|
"error_delete": "Error deleting subscriber: {{error}}",
|
||||||
"error_fetching": "Error fetching subscribers: {{error}}",
|
"error_fetching": "Error fetching subscribers: {{error}}",
|
||||||
"error_fetching_single": "Error fetching subscriber: {{error}}",
|
"error_fetching_single": "Error fetching subscriber: {{error}}",
|
||||||
"error_update": "Error updating subscriber: {{error}}",
|
"error_update": "Error updating subscriber: {{error}}",
|
||||||
|
"is_already_claimed": "is already claimed by ",
|
||||||
"subscribers": "Subscribers",
|
"subscribers": "Subscribers",
|
||||||
"success_create": "Subscriber successfully created!",
|
"success_create": "Subscriber successfully created!",
|
||||||
"success_delete": "Subscriber successfully deleted!",
|
"success_delete": "Subscriber successfully deleted!",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
"certificate": "Certificado",
|
"certificate": "Certificado",
|
||||||
"certificates": "Certificados",
|
"certificates": "Certificados",
|
||||||
|
"claim": "Reclamación",
|
||||||
"clear": "Claro",
|
"clear": "Claro",
|
||||||
"close": "Cerrar",
|
"close": "Cerrar",
|
||||||
"code": "Código",
|
"code": "Código",
|
||||||
@@ -117,6 +118,7 @@
|
|||||||
"hours": "horas",
|
"hours": "horas",
|
||||||
"id": "Carné de identidad",
|
"id": "Carné de identidad",
|
||||||
"invalid_credentials": "Nombre de usuario y / o contraseña inválido",
|
"invalid_credentials": "Nombre de usuario y / o contraseña inválido",
|
||||||
|
"invalid_date_explanation": "Fecha no válida, utilice el calendario accesible con el botón de la derecha",
|
||||||
"invalid_file": "El archivo elegido no es válido, lea las instrucciones y ajuste su archivo en consecuencia",
|
"invalid_file": "El archivo elegido no es válido, lea las instrucciones y ajuste su archivo en consecuencia",
|
||||||
"invalid_password": "Esta contraseña no confirma las reglas básicas de contraseña. Visite nuestra página de Política de contraseñas para obtener más información.",
|
"invalid_password": "Esta contraseña no confirma las reglas básicas de contraseña. Visite nuestra página de Política de contraseñas para obtener más información.",
|
||||||
"invalid_pem": "Su archivo .pem no es válido. Debe comenzar con '----- BEGIN CERTIFICATE -----' O '----- BEGIN PRIVATE KEY -----' y debe terminar con '----- END CERTIFICATE --- - 'O' ----- FIN DE CLAVE PRIVADA ----- '",
|
"invalid_pem": "Su archivo .pem no es válido. Debe comenzar con '----- BEGIN CERTIFICATE -----' O '----- BEGIN PRIVATE KEY -----' y debe terminar con '----- END CERTIFICATE --- - 'O' ----- FIN DE CLAVE PRIVADA ----- '",
|
||||||
@@ -162,6 +164,7 @@
|
|||||||
"recorded": "Grabado",
|
"recorded": "Grabado",
|
||||||
"refresh": "Refrescar",
|
"refresh": "Refrescar",
|
||||||
"refresh_device": "Actualizar dispositivo",
|
"refresh_device": "Actualizar dispositivo",
|
||||||
|
"remove_claim": "Quitar reclamo",
|
||||||
"required": "Necesario",
|
"required": "Necesario",
|
||||||
"result": "Resultado",
|
"result": "Resultado",
|
||||||
"save": "Salvar",
|
"save": "Salvar",
|
||||||
@@ -655,11 +658,14 @@
|
|||||||
},
|
},
|
||||||
"statistics": {
|
"statistics": {
|
||||||
"data": "Datos (KB)",
|
"data": "Datos (KB)",
|
||||||
|
"data_mb": "Datos (MB)",
|
||||||
"latest_statistics": "Últimas estadísticas",
|
"latest_statistics": "Últimas estadísticas",
|
||||||
"lifetime_stats": "Estadísticas de por vida",
|
"lifetime_stats": "Estadísticas de por vida",
|
||||||
|
"memory": "Memoria",
|
||||||
"no_interfaces": "No hay estadísticas de vida útil de la interfaz disponibles",
|
"no_interfaces": "No hay estadísticas de vida útil de la interfaz disponibles",
|
||||||
"show_latest": "Últimas estadísticas",
|
"show_latest": "Últimas estadísticas",
|
||||||
"title": "estadística"
|
"title": "estadística",
|
||||||
|
"used": "Memoria usada %"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"connection_status": "Estado",
|
"connection_status": "Estado",
|
||||||
@@ -671,17 +677,22 @@
|
|||||||
"percentage_free": "{{percentage}}% de {{total}} gratis",
|
"percentage_free": "{{percentage}}% de {{total}} gratis",
|
||||||
"percentage_used": "{{percentage}}% de {{total}} utilizado",
|
"percentage_used": "{{percentage}}% de {{total}} utilizado",
|
||||||
"title": "#{{serialNumber}} Estado",
|
"title": "#{{serialNumber}} Estado",
|
||||||
|
"total_memory": "Memoria total",
|
||||||
"uptime": "Tiempo de actividad",
|
"uptime": "Tiempo de actividad",
|
||||||
"used_total_memory": "{{used}} usado / {{total}} total"
|
"used_total_memory": "{{used}} usado / {{total}} total"
|
||||||
},
|
},
|
||||||
"subscriber": {
|
"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",
|
"create": "Crear suscriptor",
|
||||||
|
"devices_one": "{{count}} dispositivo",
|
||||||
|
"devices_other": "{{count}} dispositivos",
|
||||||
"edit": "Editar suscriptor",
|
"edit": "Editar suscriptor",
|
||||||
"error_create": "Error al crear el suscriptor: {{error}}",
|
"error_create": "Error al crear el suscriptor: {{error}}",
|
||||||
"error_delete": "Error al eliminar el suscriptor: {{error}}",
|
"error_delete": "Error al eliminar el suscriptor: {{error}}",
|
||||||
"error_fetching": "Error al obtener suscriptores: {{error}}",
|
"error_fetching": "Error al obtener suscriptores: {{error}}",
|
||||||
"error_fetching_single": "Error al obtener el suscriptor: {{error}}",
|
"error_fetching_single": "Error al obtener el suscriptor: {{error}}",
|
||||||
"error_update": "Error al actualizar el suscriptor: {{error}}",
|
"error_update": "Error al actualizar el suscriptor: {{error}}",
|
||||||
|
"is_already_claimed": "ya es reclamado por",
|
||||||
"subscribers": "Suscriptores",
|
"subscribers": "Suscriptores",
|
||||||
"success_create": "¡Suscriptor creado correctamente!",
|
"success_create": "¡Suscriptor creado correctamente!",
|
||||||
"success_delete": "¡Suscriptor eliminado correctamente!",
|
"success_delete": "¡Suscriptor eliminado correctamente!",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
"cancel": "annuler",
|
"cancel": "annuler",
|
||||||
"certificate": "Certificat",
|
"certificate": "Certificat",
|
||||||
"certificates": "Certificats",
|
"certificates": "Certificats",
|
||||||
|
"claim": "Prétendre",
|
||||||
"clear": "Clair",
|
"clear": "Clair",
|
||||||
"close": "Fermer",
|
"close": "Fermer",
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
@@ -117,6 +118,7 @@
|
|||||||
"hours": "heures",
|
"hours": "heures",
|
||||||
"id": "Id",
|
"id": "Id",
|
||||||
"invalid_credentials": "Nom d'utilisateur et / ou mot de passe incorrect",
|
"invalid_credentials": "Nom d'utilisateur et / ou mot de passe incorrect",
|
||||||
|
"invalid_date_explanation": "Date invalide, merci d'utiliser le calendrier accessible avec le bouton à droite",
|
||||||
"invalid_file": "Le fichier choisi n'était pas valide, veuillez lire les instructions et ajuster votre fichier en conséquence",
|
"invalid_file": "Le fichier choisi n'était pas valide, veuillez lire les instructions et ajuster votre fichier en conséquence",
|
||||||
"invalid_password": "Ce mot de passe ne confirme pas les règles de base des mots de passe. Veuillez visiter notre page Politique de mot de passe pour en savoir plus",
|
"invalid_password": "Ce mot de passe ne confirme pas les règles de base des mots de passe. Veuillez visiter notre page Politique de mot de passe pour en savoir plus",
|
||||||
"invalid_pem": "Votre fichier .pem n'est pas valide. Il doit commencer par '-----BEGIN CERTIFICATE-----' OU '-----BEGIN PRIVATE KEY-----' et il doit se terminer par '-----END CERTIFICATE--- --' OU '-----FIN CLÉ PRIVÉE-----'",
|
"invalid_pem": "Votre fichier .pem n'est pas valide. Il doit commencer par '-----BEGIN CERTIFICATE-----' OU '-----BEGIN PRIVATE KEY-----' et il doit se terminer par '-----END CERTIFICATE--- --' OU '-----FIN CLÉ PRIVÉE-----'",
|
||||||
@@ -162,6 +164,7 @@
|
|||||||
"recorded": "Enregistré",
|
"recorded": "Enregistré",
|
||||||
"refresh": "Rafraîchir",
|
"refresh": "Rafraîchir",
|
||||||
"refresh_device": "Actualiser l'appareil",
|
"refresh_device": "Actualiser l'appareil",
|
||||||
|
"remove_claim": "Supprimer la réclamation",
|
||||||
"required": "Champs obligatoires",
|
"required": "Champs obligatoires",
|
||||||
"result": "Résultat",
|
"result": "Résultat",
|
||||||
"save": "Sauvegarder",
|
"save": "Sauvegarder",
|
||||||
@@ -655,11 +658,14 @@
|
|||||||
},
|
},
|
||||||
"statistics": {
|
"statistics": {
|
||||||
"data": "Données (Ko)",
|
"data": "Données (Ko)",
|
||||||
|
"data_mb": "Données (Mo)",
|
||||||
"latest_statistics": "Dernières statistiques",
|
"latest_statistics": "Dernières statistiques",
|
||||||
"lifetime_stats": "Statistiques à vie",
|
"lifetime_stats": "Statistiques à vie",
|
||||||
|
"memory": "mémoire",
|
||||||
"no_interfaces": "Aucune statistique de durée de vie de l'interface disponible",
|
"no_interfaces": "Aucune statistique de durée de vie de l'interface disponible",
|
||||||
"show_latest": "Dernières statistiques",
|
"show_latest": "Dernières statistiques",
|
||||||
"title": "statistiques"
|
"title": "statistiques",
|
||||||
|
"used": "Mémoire utilisée %"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"connection_status": "Statut",
|
"connection_status": "Statut",
|
||||||
@@ -671,17 +677,22 @@
|
|||||||
"percentage_free": "{{percentage}}% de {{total}} gratuit",
|
"percentage_free": "{{percentage}}% de {{total}} gratuit",
|
||||||
"percentage_used": "{{percentage}}% de {{total}} utilisé",
|
"percentage_used": "{{percentage}}% de {{total}} utilisé",
|
||||||
"title": "#{{serialNumber}} état",
|
"title": "#{{serialNumber}} état",
|
||||||
|
"total_memory": "Mémoire totale",
|
||||||
"uptime": "La disponibilité",
|
"uptime": "La disponibilité",
|
||||||
"used_total_memory": "{{used}} utilisé / {{total}} total"
|
"used_total_memory": "{{used}} utilisé / {{total}} total"
|
||||||
},
|
},
|
||||||
"subscriber": {
|
"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é",
|
"create": "Créer un abonné",
|
||||||
|
"devices_one": "{{count}} Appareil",
|
||||||
|
"devices_other": "{{count}} appareils",
|
||||||
"edit": "Modifier l'abonné",
|
"edit": "Modifier l'abonné",
|
||||||
"error_create": "Erreur lors de la création de l'abonné : {{error}}",
|
"error_create": "Erreur lors de la création de l'abonné : {{error}}",
|
||||||
"error_delete": "Erreur lors de la suppression 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": "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_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}}",
|
"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",
|
"subscribers": "Les abonnés",
|
||||||
"success_create": "Abonné créé avec succès !",
|
"success_create": "Abonné créé avec succès !",
|
||||||
"success_delete": "Abonné supprimé avec succès !",
|
"success_delete": "Abonné supprimé avec succès !",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
"certificate": "Certificado",
|
"certificate": "Certificado",
|
||||||
"certificates": "Certificados",
|
"certificates": "Certificados",
|
||||||
|
"claim": "Afirmação",
|
||||||
"clear": "Claro",
|
"clear": "Claro",
|
||||||
"close": "Perto",
|
"close": "Perto",
|
||||||
"code": "Código",
|
"code": "Código",
|
||||||
@@ -117,6 +118,7 @@
|
|||||||
"hours": "horas",
|
"hours": "horas",
|
||||||
"id": "identidade",
|
"id": "identidade",
|
||||||
"invalid_credentials": "Nome de usuário e / ou senha inválidos",
|
"invalid_credentials": "Nome de usuário e / ou senha inválidos",
|
||||||
|
"invalid_date_explanation": "Data inválida, use o calendário acessível com o botão à direita",
|
||||||
"invalid_file": "O arquivo escolhido era inválido, por favor, leia as instruções e ajuste seu arquivo de acordo",
|
"invalid_file": "O arquivo escolhido era inválido, por favor, leia as instruções e ajuste seu arquivo de acordo",
|
||||||
"invalid_password": "Esta senha não está de acordo com as regras básicas de senha. Visite nossa página de Política de Senha para saber mais",
|
"invalid_password": "Esta senha não está de acordo com as regras básicas de senha. Visite nossa página de Política de Senha para saber mais",
|
||||||
"invalid_pem": "Seu arquivo .pem é inválido. Deve começar com '----- BEGIN CERTIFICATE -----' OU '----- BEGIN PRIVATE KEY -----' e deve terminar com '----- END CERTIFICATE --- - 'OU' ----- END PRIVATE KEY ----- '",
|
"invalid_pem": "Seu arquivo .pem é inválido. Deve começar com '----- BEGIN CERTIFICATE -----' OU '----- BEGIN PRIVATE KEY -----' e deve terminar com '----- END CERTIFICATE --- - 'OU' ----- END PRIVATE KEY ----- '",
|
||||||
@@ -162,6 +164,7 @@
|
|||||||
"recorded": "Gravado",
|
"recorded": "Gravado",
|
||||||
"refresh": "REFRESH",
|
"refresh": "REFRESH",
|
||||||
"refresh_device": "Atualizar dispositivo",
|
"refresh_device": "Atualizar dispositivo",
|
||||||
|
"remove_claim": "Remover reivindicação",
|
||||||
"required": "Requeridos",
|
"required": "Requeridos",
|
||||||
"result": "Resultado",
|
"result": "Resultado",
|
||||||
"save": "Salve",
|
"save": "Salve",
|
||||||
@@ -655,11 +658,14 @@
|
|||||||
},
|
},
|
||||||
"statistics": {
|
"statistics": {
|
||||||
"data": "Dados (KB)",
|
"data": "Dados (KB)",
|
||||||
|
"data_mb": "Dados (MB)",
|
||||||
"latest_statistics": "Estatísticas mais recentes",
|
"latest_statistics": "Estatísticas mais recentes",
|
||||||
"lifetime_stats": "Estatísticas de vida",
|
"lifetime_stats": "Estatísticas de vida",
|
||||||
|
"memory": "Memória",
|
||||||
"no_interfaces": "Nenhuma estatística de tempo de vida da interface disponível",
|
"no_interfaces": "Nenhuma estatística de tempo de vida da interface disponível",
|
||||||
"show_latest": "Últimas estatísticas",
|
"show_latest": "Últimas estatísticas",
|
||||||
"title": "Estatisticas"
|
"title": "Estatisticas",
|
||||||
|
"used": "Memoria usada %"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"connection_status": "Status",
|
"connection_status": "Status",
|
||||||
@@ -671,17 +677,22 @@
|
|||||||
"percentage_free": "{{percentage}}% de {{total}} grátis",
|
"percentage_free": "{{percentage}}% de {{total}} grátis",
|
||||||
"percentage_used": "{{percentage}}% de {{total}} usado",
|
"percentage_used": "{{percentage}}% de {{total}} usado",
|
||||||
"title": "#{{serialNumber}} status",
|
"title": "#{{serialNumber}} status",
|
||||||
|
"total_memory": "Memória total",
|
||||||
"uptime": "Tempo de atividade",
|
"uptime": "Tempo de atividade",
|
||||||
"used_total_memory": "{{used}} usado / {{total}} total"
|
"used_total_memory": "{{used}} usado / {{total}} total"
|
||||||
},
|
},
|
||||||
"subscriber": {
|
"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",
|
"create": "Criar assinante",
|
||||||
|
"devices_one": "{{count}} Dispositivo",
|
||||||
|
"devices_other": "{{count}} dispositivos",
|
||||||
"edit": "Editar Assinante",
|
"edit": "Editar Assinante",
|
||||||
"error_create": "Erro ao criar assinante: {{error}}",
|
"error_create": "Erro ao criar assinante: {{error}}",
|
||||||
"error_delete": "Erro ao excluir assinante: {{error}}",
|
"error_delete": "Erro ao excluir assinante: {{error}}",
|
||||||
"error_fetching": "Erro ao buscar assinantes: {{error}}",
|
"error_fetching": "Erro ao buscar assinantes: {{error}}",
|
||||||
"error_fetching_single": "Erro ao buscar assinante: {{error}}",
|
"error_fetching_single": "Erro ao buscar assinante: {{error}}",
|
||||||
"error_update": "Erro ao atualizar assinante: {{error}}",
|
"error_update": "Erro ao atualizar assinante: {{error}}",
|
||||||
|
"is_already_claimed": "já é reivindicado por",
|
||||||
"subscribers": "Inscritos",
|
"subscribers": "Inscritos",
|
||||||
"success_create": "Assinante criado com sucesso!",
|
"success_create": "Assinante criado com sucesso!",
|
||||||
"success_delete": "Assinante excluído com sucesso!",
|
"success_delete": "Assinante excluído com sucesso!",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
CCard,
|
CCard,
|
||||||
CPopover,
|
CPopover,
|
||||||
CButtonToolbar,
|
CButtonToolbar,
|
||||||
|
CFormText,
|
||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import DatePicker from 'react-widgets/DatePicker';
|
import DatePicker from 'react-widgets/DatePicker';
|
||||||
@@ -41,7 +42,9 @@ const DeviceCommands = () => {
|
|||||||
const [commands, setCommands] = useState([]);
|
const [commands, setCommands] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [start, setStart] = useState('');
|
const [start, setStart] = useState('');
|
||||||
|
const [startError, setStartError] = useState(false);
|
||||||
const [end, setEnd] = useState('');
|
const [end, setEnd] = useState('');
|
||||||
|
const [endError, setEndError] = useState(false);
|
||||||
const [commandLimit, setCommandLimit] = useState(25);
|
const [commandLimit, setCommandLimit] = useState(25);
|
||||||
// Load more button related
|
// Load more button related
|
||||||
const [loadingMore, setLoadingMore] = useState(false);
|
const [loadingMore, setLoadingMore] = useState(false);
|
||||||
@@ -65,11 +68,25 @@ const DeviceCommands = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const modifyStart = (value) => {
|
const modifyStart = (value) => {
|
||||||
setStart(value);
|
try {
|
||||||
|
new Date(value).toISOString();
|
||||||
|
setStartError(false);
|
||||||
|
setStart(value);
|
||||||
|
} catch (e) {
|
||||||
|
setStart('');
|
||||||
|
setStartError(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const modifyEnd = (value) => {
|
const modifyEnd = (value) => {
|
||||||
setEnd(value);
|
try {
|
||||||
|
new Date(value).toISOString();
|
||||||
|
setEndError(false);
|
||||||
|
setEnd(value);
|
||||||
|
} catch (e) {
|
||||||
|
setEnd('');
|
||||||
|
setEndError(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteCommandFromList = (commandUuid) => {
|
const deleteCommandFromList = (commandUuid) => {
|
||||||
@@ -256,10 +273,16 @@ const DeviceCommands = () => {
|
|||||||
<CCol>
|
<CCol>
|
||||||
From:
|
From:
|
||||||
<DatePicker includeTime onChange={(date) => modifyStart(date)} />
|
<DatePicker includeTime onChange={(date) => modifyStart(date)} />
|
||||||
|
<CFormText color="danger" hidden={!startError}>
|
||||||
|
{t('common.invalid_date_explanation')}
|
||||||
|
</CFormText>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol>
|
<CCol>
|
||||||
To:
|
To:
|
||||||
<DatePicker includeTime onChange={(date) => modifyEnd(date)} />
|
<DatePicker includeTime onChange={(date) => modifyEnd(date)} />
|
||||||
|
<CFormText color="danger" hidden={!endError}>
|
||||||
|
{t('common.invalid_date_explanation')}
|
||||||
|
</CFormText>
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
<CCard>
|
<CCard>
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ DeviceStatisticsChart.propTypes = {
|
|||||||
chart: PropTypes.instanceOf(Object).isRequired,
|
chart: PropTypes.instanceOf(Object).isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DeviceStatisticsChart;
|
export default React.memo(DeviceStatisticsChart);
|
||||||
|
|||||||
@@ -1,37 +1,94 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useCallback } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { CSpinner } from '@coreui/react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { v4 as createUuid } from 'uuid';
|
import { v4 as createUuid } from 'uuid';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { useAuth, useDevice } from 'ucentral-libs';
|
import { useAuth, useDevice } from 'ucentral-libs';
|
||||||
import { unixToTime, capitalizeFirstLetter } from 'utils/helper';
|
import {
|
||||||
import eventBus from 'utils/eventBus';
|
capitalizeFirstLetter,
|
||||||
|
datesSameDay,
|
||||||
|
dateToUnix,
|
||||||
|
prettyDate,
|
||||||
|
unixToTime,
|
||||||
|
} from 'utils/helper';
|
||||||
import DeviceStatisticsChart from './DeviceStatisticsChart';
|
import DeviceStatisticsChart from './DeviceStatisticsChart';
|
||||||
|
|
||||||
const StatisticsChartList = () => {
|
const StatisticsChartList = ({ setOptions, section, setStart, setEnd, time }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
const { currentToken, endpoints } = useAuth();
|
const { currentToken, endpoints } = useAuth();
|
||||||
const { deviceSerialNumber } = useDevice();
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [statOptions, setStatOptions] = useState({
|
const [statOptions, setStatOptions] = useState({
|
||||||
interfaceList: [],
|
interfaceList: [],
|
||||||
|
memory: [],
|
||||||
settings: {},
|
settings: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
const transformIntoDataset = (data) => {
|
const transformIntoDataset = (data) => {
|
||||||
const sortedData = data.sort((a, b) => {
|
let sortedData = data.sort((a, b) => {
|
||||||
if (a.recorded > b.recorded) return 1;
|
if (a.recorded > b.recorded) return 1;
|
||||||
if (b.recorded > a.recorded) return -1;
|
if (b.recorded > a.recorded) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dataLength = sortedData.length;
|
||||||
|
if (dataLength > 1000 && dataLength < 3000) {
|
||||||
|
sortedData = sortedData.filter((dat, index) => index % 4 === 0);
|
||||||
|
} else if (dataLength >= 3000 && dataLength < 5000) {
|
||||||
|
sortedData = sortedData.filter((dat, index) => index % 8 === 0);
|
||||||
|
} else if (dataLength >= 5000 && dataLength < 7000) {
|
||||||
|
sortedData = sortedData.filter((dat, index) => index % 12 === 0);
|
||||||
|
} else if (dataLength > 7000) {
|
||||||
|
sortedData = sortedData.filter((dat, index) => index % 20 === 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,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
titleName: t('statistics.memory'),
|
||||||
|
name: 'Buffered',
|
||||||
|
backgroundColor: 'rgb(228,102,81,0.9)',
|
||||||
|
data: [],
|
||||||
|
fill: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
titleName: t('statistics.memory'),
|
||||||
|
name: 'Cached',
|
||||||
|
backgroundColor: 'rgb(228,102,81,0.9)',
|
||||||
|
data: [],
|
||||||
|
fill: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const log of sortedData) {
|
||||||
|
memoryUsed[0].data.push(
|
||||||
|
Math.floor((log.data.unit.memory.total - log.data.unit.memory.free) / 1024 / 1024),
|
||||||
|
);
|
||||||
|
memoryUsed[1].data.push(Math.floor(log.data.unit.memory.buffered / 1024 / 1024));
|
||||||
|
memoryUsed[2].data.push(Math.floor(log.data.unit.memory.cached / 1024 / 1024));
|
||||||
|
}
|
||||||
|
|
||||||
// This dictionary will have a key that is the interface name and a value of it's index in the final array
|
// 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 interfaceTypes = {};
|
||||||
const interfaceList = [];
|
const interfaceList = [];
|
||||||
const categories = [];
|
const categories = [];
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
const areSameDay = datesSameDay(
|
||||||
|
new Date(sortedData[0].recorded * 1000),
|
||||||
|
new Date(sortedData[sortedData.length - 1].recorded * 1000),
|
||||||
|
);
|
||||||
|
|
||||||
// Just building the array for all the interfaces
|
// Just building the array for all the interfaces
|
||||||
for (const log of sortedData) {
|
for (const log of sortedData) {
|
||||||
categories.push(unixToTime(log.recorded));
|
categories.push(areSameDay ? unixToTime(log.recorded) : prettyDate(log.recorded));
|
||||||
for (const logInterface of log.data.interfaces) {
|
for (const logInterface of log.data.interfaces) {
|
||||||
if (interfaceTypes[logInterface.name] === undefined) {
|
if (interfaceTypes[logInterface.name] === undefined) {
|
||||||
interfaceTypes[logInterface.name] = i;
|
interfaceTypes[logInterface.name] = i;
|
||||||
@@ -69,10 +126,9 @@ const StatisticsChartList = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = {
|
const interfaceOptions = {
|
||||||
chart: {
|
chart: {
|
||||||
id: 'chart',
|
id: 'chart',
|
||||||
group: 'txrx',
|
|
||||||
},
|
},
|
||||||
stroke: {
|
stroke: {
|
||||||
curve: 'smooth',
|
curve: 'smooth',
|
||||||
@@ -85,7 +141,7 @@ const StatisticsChartList = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
categories,
|
categories,
|
||||||
tickAmount: 20,
|
tickAmount: areSameDay ? 15 : 10,
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
labels: {
|
labels: {
|
||||||
@@ -105,76 +161,174 @@ const StatisticsChartList = () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const memoryOptions = {
|
||||||
|
chart: {
|
||||||
|
id: 'chart',
|
||||||
|
},
|
||||||
|
stroke: {
|
||||||
|
curve: 'smooth',
|
||||||
|
},
|
||||||
|
xaxis: {
|
||||||
|
tickAmount: areSameDay ? 15 : 10,
|
||||||
|
title: {
|
||||||
|
text: 'Time',
|
||||||
|
style: {
|
||||||
|
fontSize: '15px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
categories,
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
tickAmount: 5,
|
||||||
|
title: {
|
||||||
|
text: t('statistics.data_mb'),
|
||||||
|
style: {
|
||||||
|
fontSize: '15px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
position: 'top',
|
||||||
|
horizontalAlign: 'right',
|
||||||
|
float: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const newOptions = {
|
const newOptions = {
|
||||||
interfaceList,
|
interfaceList,
|
||||||
settings: options,
|
memory: [memoryUsed],
|
||||||
|
interfaceOptions,
|
||||||
|
memoryOptions,
|
||||||
|
start: new Date(sortedData[0].recorded * 1000).toISOString(),
|
||||||
|
end: new Date(sortedData[sortedData.length - 1].recorded * 1000).toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (statOptions !== newOptions) {
|
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 });
|
||||||
|
if (sortedData.length > 0) {
|
||||||
|
setStart(new Date(sortedData[0].recorded * 1000));
|
||||||
|
setEnd(new Date(sortedData[sortedData.length - 1].recorded * 1000));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 = () => {
|
const getStatistics = () => {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${currentToken}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
params: {
|
params: {},
|
||||||
serialNumber: '24f5a207a130',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let extraParams = '';
|
||||||
|
if (time.start !== null && time.end !== null) {
|
||||||
|
const utcStart = new Date(time.start).toISOString();
|
||||||
|
const utcEnd = new Date(time.end).toISOString();
|
||||||
|
options.params.startDate = dateToUnix(utcStart);
|
||||||
|
options.params.endDate = dateToUnix(utcEnd);
|
||||||
|
options.params.limit = 10000;
|
||||||
|
} else {
|
||||||
|
extraParams = '?newest=true&limit=50';
|
||||||
|
}
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(
|
.get(
|
||||||
`${endpoints.owgw}/api/v1/device/${deviceSerialNumber}/statistics?newest=true&limit=50`,
|
`${endpoints.owgw}/api/v1/device/${deviceSerialNumber}/statistics${extraParams}`,
|
||||||
options,
|
options,
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
transformIntoDataset(response.data.data);
|
transformIntoDataset(response.data.data);
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {})
|
||||||
|
.finally(() => setLoading(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (deviceSerialNumber) {
|
if (deviceSerialNumber) {
|
||||||
getStatistics();
|
getStatistics();
|
||||||
}
|
}
|
||||||
}, [deviceSerialNumber]);
|
}, [deviceSerialNumber, time.refreshId]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
eventBus.on('refreshInterfaceStatistics', () => getStatistics());
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
eventBus.remove('refreshInterfaceStatistics');
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<div className="text-center">
|
||||||
|
<CSpinner size="xl" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{statOptions.interfaceList.map((data) => {
|
{section !== 'memory' && !loading && getInterface()}
|
||||||
const options = {
|
{section === 'memory' &&
|
||||||
data,
|
!loading &&
|
||||||
options: {
|
statOptions.memory.map((data) => {
|
||||||
...statOptions.settings,
|
const options = {
|
||||||
title: {
|
data,
|
||||||
text: capitalizeFirstLetter(data[0].titleName),
|
options: {
|
||||||
align: 'left',
|
...statOptions.memoryOptions,
|
||||||
style: {
|
title: {
|
||||||
fontSize: '25px',
|
text: capitalizeFirstLetter(data[0].titleName),
|
||||||
|
align: 'left',
|
||||||
|
style: {
|
||||||
|
fontSize: '25px',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
};
|
||||||
};
|
return (
|
||||||
return (
|
<div key={createUuid()}>
|
||||||
<div key={createUuid()}>
|
<DeviceStatisticsChart chart={options} section={section} />
|
||||||
<DeviceStatisticsChart chart={options} />
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
})}
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StatisticsChartList.propTypes = {
|
||||||
|
setOptions: PropTypes.func.isRequired,
|
||||||
|
section: PropTypes.string.isRequired,
|
||||||
|
time: PropTypes.instanceOf(Object).isRequired,
|
||||||
|
setStart: PropTypes.func.isRequired,
|
||||||
|
setEnd: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default React.memo(StatisticsChartList);
|
export default React.memo(StatisticsChartList);
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
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,
|
||||||
|
CFormText,
|
||||||
|
} from '@coreui/react';
|
||||||
|
import DatePicker from 'react-widgets/DatePicker';
|
||||||
import { cilSync } from '@coreui/icons';
|
import { cilSync } from '@coreui/icons';
|
||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import eventBus from 'utils/eventBus';
|
|
||||||
import LifetimeStatsmodal from 'components/LifetimeStatsModal';
|
import LifetimeStatsmodal from 'components/LifetimeStatsModal';
|
||||||
import StatisticsChartList from './StatisticsChartList';
|
import StatisticsChartList from './StatisticsChartList';
|
||||||
import LatestStatisticsmodal from './LatestStatisticsModal';
|
import LatestStatisticsmodal from './LatestStatisticsModal';
|
||||||
@@ -12,6 +21,13 @@ const DeviceStatisticsCard = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showLatestModal, setShowLatestModal] = useState(false);
|
const [showLatestModal, setShowLatestModal] = useState(false);
|
||||||
const [showLifetimeModal, setShowLifetimeModal] = useState(false);
|
const [showLifetimeModal, setShowLifetimeModal] = useState(false);
|
||||||
|
const [options, setOptions] = useState([]);
|
||||||
|
const [section, setSection] = useState('');
|
||||||
|
const [start, setStart] = useState(null);
|
||||||
|
const [startError, setStartError] = useState(false);
|
||||||
|
const [end, setEnd] = useState(null);
|
||||||
|
const [endError, setEndError] = useState(false);
|
||||||
|
const [time, setTime] = useState({ refreshId: '0', start: null, end: null });
|
||||||
|
|
||||||
const toggleLatestModal = () => {
|
const toggleLatestModal = () => {
|
||||||
setShowLatestModal(!showLatestModal);
|
setShowLatestModal(!showLatestModal);
|
||||||
@@ -21,10 +37,36 @@ const DeviceStatisticsCard = () => {
|
|||||||
setShowLifetimeModal(!showLifetimeModal);
|
setShowLifetimeModal(!showLifetimeModal);
|
||||||
};
|
};
|
||||||
|
|
||||||
const refresh = () => {
|
const modifyStart = (value) => {
|
||||||
eventBus.dispatch('refreshInterfaceStatistics', { message: 'Refresh interface statistics' });
|
try {
|
||||||
|
new Date(value).toISOString();
|
||||||
|
setStartError(false);
|
||||||
|
setStart(value);
|
||||||
|
} catch (e) {
|
||||||
|
setStart('');
|
||||||
|
setStartError(true);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const modifyEnd = (value) => {
|
||||||
|
try {
|
||||||
|
new Date(value).toISOString();
|
||||||
|
setEndError(false);
|
||||||
|
setEnd(value);
|
||||||
|
} catch (e) {
|
||||||
|
setEnd('');
|
||||||
|
setEndError(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const refresh = () => {
|
||||||
|
setTime({ refreshId: createUuid(), start, end });
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (section === '' && options.length > 0) setSection(options[0].value);
|
||||||
|
}, [options]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<CCard className="m-0">
|
<CCard className="m-0">
|
||||||
@@ -32,12 +74,34 @@ const DeviceStatisticsCard = () => {
|
|||||||
<div className="d-flex flex-row-reverse align-items-center">
|
<div className="d-flex flex-row-reverse align-items-center">
|
||||||
<div className="pl-2">
|
<div className="pl-2">
|
||||||
<CPopover content={t('common.refresh')}>
|
<CPopover content={t('common.refresh')}>
|
||||||
<CButton size="sm" color="info" onClick={refresh}>
|
<CButton size="sm" color="info" onClick={refresh} disabled={startError || endError}>
|
||||||
<CIcon content={cilSync} />
|
<CIcon content={cilSync} />
|
||||||
</CButton>
|
</CButton>
|
||||||
</CPopover>
|
</CPopover>
|
||||||
</div>
|
</div>
|
||||||
<div className="pl-2">
|
<div className="pl-2">
|
||||||
|
<DatePicker
|
||||||
|
includeTime
|
||||||
|
onChange={(date) => modifyEnd(date)}
|
||||||
|
value={end ? new Date(end) : undefined}
|
||||||
|
/>
|
||||||
|
<CFormText color="danger" hidden={!endError}>
|
||||||
|
{t('common.invalid_date_explanation')}
|
||||||
|
</CFormText>
|
||||||
|
</div>
|
||||||
|
To:
|
||||||
|
<div className="pl-2">
|
||||||
|
<DatePicker
|
||||||
|
includeTime
|
||||||
|
onChange={(date) => modifyStart(date)}
|
||||||
|
value={start ? new Date(start) : undefined}
|
||||||
|
/>
|
||||||
|
<CFormText color="danger" hidden={!startError}>
|
||||||
|
{t('common.invalid_date_explanation')}
|
||||||
|
</CFormText>
|
||||||
|
</div>
|
||||||
|
From:
|
||||||
|
<div className="px-2">
|
||||||
<CButton size="sm" color="info" onClick={toggleLifetimeModal}>
|
<CButton size="sm" color="info" onClick={toggleLifetimeModal}>
|
||||||
Lifetime Statistics
|
Lifetime Statistics
|
||||||
</CButton>
|
</CButton>
|
||||||
@@ -47,10 +111,30 @@ const DeviceStatisticsCard = () => {
|
|||||||
{t('statistics.show_latest')}
|
{t('statistics.show_latest')}
|
||||||
</CButton>
|
</CButton>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</CCardHeader>
|
</CCardHeader>
|
||||||
<CCardBody className="p-1">
|
<CCardBody className="p-1">
|
||||||
<StatisticsChartList />
|
<StatisticsChartList
|
||||||
|
setOptions={setOptions}
|
||||||
|
section={section}
|
||||||
|
time={time}
|
||||||
|
setStart={setStart}
|
||||||
|
setEnd={setEnd}
|
||||||
|
/>
|
||||||
</CCardBody>
|
</CCardBody>
|
||||||
</CCard>
|
</CCard>
|
||||||
<LatestStatisticsmodal show={showLatestModal} toggle={toggleLatestModal} />
|
<LatestStatisticsmodal show={showLatestModal} toggle={toggleLatestModal} />
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
|
CAlert,
|
||||||
CCard,
|
CCard,
|
||||||
CCardHeader,
|
CCardHeader,
|
||||||
CRow,
|
CRow,
|
||||||
CCol,
|
CCol,
|
||||||
CCardBody,
|
CCardBody,
|
||||||
CBadge,
|
CBadge,
|
||||||
CAlert,
|
|
||||||
CPopover,
|
CPopover,
|
||||||
CButton,
|
CButton,
|
||||||
CSpinner,
|
CSpinner,
|
||||||
@@ -16,8 +16,7 @@ import {
|
|||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import { cilSync } from '@coreui/icons';
|
import { cilSync } from '@coreui/icons';
|
||||||
import { prettyDate, compactSecondsToDetailed } from 'utils/helper';
|
import { prettyDate, compactSecondsToDetailed, cleanBytesString } from 'utils/helper';
|
||||||
import MemoryBar from './MemoryBar';
|
|
||||||
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
@@ -27,6 +26,20 @@ const errorField = (t) => (
|
|||||||
</CAlert>
|
</CAlert>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getMemoryColor = (memTotal, memFree) => {
|
||||||
|
let memoryUsed = 0;
|
||||||
|
if (memTotal > 0) memoryUsed = Math.floor(((memTotal - memFree) / memTotal) * 100);
|
||||||
|
|
||||||
|
if (memoryUsed < 60) return 'success';
|
||||||
|
if (memoryUsed <= 85) return 'warning';
|
||||||
|
return 'danger';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMemoryPercentage = (memTotal, memFree) => {
|
||||||
|
if (memTotal <= 0) return `0%`;
|
||||||
|
return `${Math.floor(((memTotal - memFree) / memTotal) * 100)}%`;
|
||||||
|
};
|
||||||
|
|
||||||
const DeviceStatusCard = ({
|
const DeviceStatusCard = ({
|
||||||
t,
|
t,
|
||||||
loading,
|
loading,
|
||||||
@@ -156,6 +169,12 @@ const DeviceStatusCard = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</CCol>
|
</CCol>
|
||||||
|
<CCol className="mb-1" md="4" xl="4">
|
||||||
|
{t('status.total_memory')}:
|
||||||
|
</CCol>
|
||||||
|
<CCol className="mb-1" md="8" xl="8" style={{ paddingTop: '5px' }}>
|
||||||
|
{error ? errorField(t) : cleanBytesString(lastStats?.unit?.memory?.total)}
|
||||||
|
</CCol>
|
||||||
<CCol className="mb-1" md="4" xl="4">
|
<CCol className="mb-1" md="4" xl="4">
|
||||||
{t('status.memory')}:
|
{t('status.memory')}:
|
||||||
</CCol>
|
</CCol>
|
||||||
@@ -163,15 +182,19 @@ const DeviceStatusCard = ({
|
|||||||
{error ? (
|
{error ? (
|
||||||
errorField(t)
|
errorField(t)
|
||||||
) : (
|
) : (
|
||||||
<MemoryBar
|
<CAlert
|
||||||
t={t}
|
style={{ width: '40px' }}
|
||||||
usedBytes={
|
className="p-0 text-center"
|
||||||
lastStats?.unit?.memory?.total && lastStats?.unit?.memory?.free
|
color={getMemoryColor(
|
||||||
? lastStats?.unit?.memory?.total - lastStats?.unit?.memory?.free
|
lastStats?.unit?.memory?.total ?? 0,
|
||||||
: 0
|
lastStats?.unit?.memory?.free ?? 0,
|
||||||
}
|
)}
|
||||||
totalBytes={lastStats?.unit?.memory?.total ?? 0}
|
>
|
||||||
/>
|
{getMemoryPercentage(
|
||||||
|
lastStats?.unit?.memory?.total ?? 0,
|
||||||
|
lastStats?.unit?.memory?.free ?? 0,
|
||||||
|
)}
|
||||||
|
</CAlert>
|
||||||
)}
|
)}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
|
|||||||
@@ -124,3 +124,5 @@ export const testRegex = (value, regexString) => {
|
|||||||
const regex = new RegExp(regexString);
|
const regex = new RegExp(regexString);
|
||||||
return regex.test(value);
|
return regex.test(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const datesSameDay = (first, second) => first.getDate() === second.getDate();
|
||||||
|
|||||||
Reference in New Issue
Block a user