From 616e4b6e0c22d2b43cd1fafbc03e8c9d45947137 Mon Sep 17 00:00:00 2001 From: Charles Date: Wed, 2 Nov 2022 10:32:54 +0000 Subject: [PATCH] [WIFI-11454] Display restricted devices and certificate expiry date Signed-off-by: Charles --- package-lock.json | 4 +- package.json | 2 +- public/locales/de/translation.json | 47 +++++++++++++++++++ public/locales/en/translation.json | 47 +++++++++++++++++++ public/locales/es/translation.json | 47 +++++++++++++++++++ public/locales/fr/translation.json | 47 +++++++++++++++++++ public/locales/pt/translation.json | 47 +++++++++++++++++++ .../FormattedDate/index.tsx | 14 ++++-- src/hooks/Network/Devices.ts | 7 ++- src/models/Device.ts | 1 + src/pages/Device/Summary.tsx | 8 ++++ src/pages/Device/Wrapper.tsx | 8 +++- src/pages/Devices/ListCard/index.tsx | 40 ++++++++++++++-- src/pages/SystemPage/index.tsx | 2 +- 14 files changed, 308 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8d48bf0..7341944 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ucentral-client", - "version": "2.8.0(3)", + "version": "2.8.0(4)", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ucentral-client", - "version": "2.8.0(3)", + "version": "2.8.0(4)", "license": "ISC", "dependencies": { "@chakra-ui/icons": "^2.0.11", diff --git a/package.json b/package.json index 4696f0a..2b15589 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ucentral-client", - "version": "2.8.0(3)", + "version": "2.8.0(4)", "description": "", "private": true, "main": "index.tsx", diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index aa9093c..88d66bf 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -593,6 +593,8 @@ "devices": { "all": "Alles", "associations": "Verbände", + "certificate_expires_in": "Zertifikat läuft ab in", + "certificate_expiry": "Zert. Läuft ab in", "connected": "In Verbindung gebracht", "create_errors": "Fehler beim Versuch, Geräte zu erstellen", "create_success": " Geräte erfolgreich erstellt", @@ -613,6 +615,7 @@ "notifications": "Gerätebenachrichtigungen", "one": "Gerät", "reassign_already_owned": "Geräte neu zuweisen, die bereits vorhanden sind und einem anderen Unternehmen/Veranstaltungsort/Abonnenten gehören?", + "restricted": "Beschränkt", "sanity": "Gesundheit", "start_import": "Geräteimport starten", "test_batch": "Testen Sie Importdaten", @@ -670,6 +673,7 @@ "version": "Ausführung" }, "form": { + "captive_web_root_explanation": "Bitte verwenden Sie nur .tar-Dateien (keine komprimierten Dateien wie z. B. .targz)", "certificate_file_explanation": "Bitte verwenden Sie eine .pem-Datei, die mit „-----BEGIN CERTIFICATE-----“ beginnt und mit „-----END CERTIFICATE-----“ endet.", "invalid_cidr": "Ungültige CIDR-IPv4-Adresse. Beispiel: 192.168.0.1/12", "invalid_email": "Ungültige E-Mail", @@ -678,6 +682,7 @@ "invalid_hostname": "Ungültiger Hostname: Er darf nur aus alphanumerischen Zeichen und Bindestrichen bestehen", "invalid_icon_lang": "Ungültige Sprache, sollte aus 3 Buchstaben bestehen (eng, fre, ger, ita usw.)", "invalid_ieee": "Für dieses Verschlüsselungsprotokoll muss ieee80211w entweder „optional“ oder „erforderlich“ sein.", + "invalid_ieee_required": "ieee80211w muss für dieses Verschlüsselungsprotokoll „erforderlich“ sein", "invalid_interfaces": "Ungültige Schnittstellen-JSON-Zeichenfolge. Bitte bestätigen Sie, dass Ihr Wert gültiges JSON ist und Schnittstellen als einzigen Schlüssel hat und dass der Schnittstellenwert ein Array ist. Beispiel: {\"interfaces\": []}", "invalid_ipv4": "Ungültige IPv4-Adresse (Bsp.: 192.168.0.1 oder 192.168.0.1/16", "invalid_ipv6": "Ungültige IPv6-Adresse (Bsp.: 2001:db8:3333:4444:5555:6666:7777:8888)", @@ -853,6 +858,48 @@ "one": "Serviceklasse", "other": "Serviceklassen" }, + "simulation": { + "cancel": "Simulation abbrechen", + "cancel_explanation": "Stoppen Sie die Simulation und löschen Sie ihren Datensatz", + "cancel_success": "Simulation beendet und Aufzeichnungen gelöscht!", + "client_interval": "Kundenintervall", + "concurrent_devices": "Gleichzeitige Geräte", + "controller": "Regler", + "current_live_devices": "Aktuelle Live-Geräte", + "delete_success": "Gelöschte Simulation!", + "duration": "Dauer", + "error_devices": "Fehler Geräte", + "healthcheck_interval": "Healthcheck-Intervall", + "infinite": "Unendlich", + "keep_alive": "Bleib am Leben", + "mac_prefix": "MAC-Präfix", + "max_associations": "max. Verbände", + "max_clients": "Max. Kunden", + "min_associations": "Mindest. Verbände", + "min_clients": "Mindest. Kunden", + "no_sim_running": "Derzeit läuft keine Simulation", + "one": "Simulation", + "other": "Simulationen", + "owner": "Inhaber", + "realtime_data": "Echtzeitdaten", + "realtime_messages": "Echtzeit-Nachrichten", + "reconnect_interval": "Wiederverbindungsintervall", + "result_delete_success": "Gelöschtes Ergebnis!", + "rx": "empfangen", + "rx_messages": "Rx-Meldungen", + "sim_currently_running": "Simulation \"{{sim}}\" läuft", + "sim_history": "{{sim}} Vorherige Läufe", + "start": "Simulation starten", + "start_success": "Simulationslauf gestartet!", + "state_interval": "Zustandsintervall", + "stop": "Simulation stoppen", + "stop_success": "Simulation gestoppt!", + "threads": "Themen", + "time_to_full": "Zeit für volle Geräte", + "tx": "Übertragen", + "tx_messages": "Tx-Nachrichten", + "view_previous_runs": "Vorherige Läufe anzeigen" + }, "statistics": { "last_stats": "Letzte Statistik", "memory": "Erinnerung" diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 2059466..bfcc99e 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -593,6 +593,8 @@ "devices": { "all": "All", "associations": "Associations", + "certificate_expires_in": "Certificate Expiry", + "certificate_expiry": "Cert. Expires In", "connected": "Connected", "create_errors": "errors while trying to create devices", "create_success": " devices successfully created", @@ -613,6 +615,7 @@ "notifications": "Device Notifications", "one": "Device", "reassign_already_owned": "Reassign devices which already exist and are owned by another entity/venue/subscriber?", + "restricted": "Restricted", "sanity": "Sanity", "start_import": "Start Device Importation", "test_batch": "Test Import Data", @@ -670,6 +673,7 @@ "version": "Version" }, "form": { + "captive_web_root_explanation": "Please use .tar files only (no compressed files like .targz, for example)", "certificate_file_explanation": "Please use a .pem file that starts with \"-----BEGIN CERTIFICATE-----\" and ends with \"-----END CERTIFICATE-----\"", "invalid_cidr": "Invalid CIDR IPv4 address. Example: 192.168.0.1/12", "invalid_email": "Invalid Email", @@ -678,6 +682,7 @@ "invalid_hostname": "Invalid hostname: it needs to be composed of alphanumeric characters and dashes only", "invalid_icon_lang": "Invalid language, it should be in a 3-letter format (eng, fre, ger, ita, etc.)", "invalid_ieee": "For this encryption protocol, ieee80211w needs to be either 'optional' or 'required'", + "invalid_ieee_required": "ieee80211w needs to be 'required' for this encryption protocol", "invalid_interfaces": "Invalid Interfaces JSON string. Please confirm that your value is: valid JSON and has interfaces as its only key and that the interfaces value is an array. Example: {\"interfaces\": []}", "invalid_ipv4": "Invalid IPv4 address (ex.: 192.168.0.1 or 192.168.0.1/16", "invalid_ipv6": "Invalid IPv6 address (ex.: 2001:db8:3333:4444:5555:6666:7777:8888)", @@ -853,6 +858,48 @@ "one": "Service Class", "other": "Service Classes" }, + "simulation": { + "cancel": "Cancel Simulation", + "cancel_explanation": "Stop the simulation and erase its record", + "cancel_success": "Stopped simulation and erased its record!", + "client_interval": "Client Interval", + "concurrent_devices": "Concurrent Devices", + "controller": "Controller", + "current_live_devices": "Current Live Devices", + "delete_success": "Deleted Simulation!", + "duration": "Duration", + "error_devices": "Error Devices", + "healthcheck_interval": "Healthcheck Interval", + "infinite": "Infinite", + "keep_alive": "Keep Alive", + "mac_prefix": "MAC Prefix", + "max_associations": "Max. Associations", + "max_clients": "Max. Clients", + "min_associations": "Min. Associations", + "min_clients": "Min. Clients", + "no_sim_running": "No simulation currently running", + "one": "Simulation", + "other": "Simulations", + "owner": "Owner", + "realtime_data": "Real-Time Data", + "realtime_messages": "Real-Time Messages", + "reconnect_interval": "Reconnect Interval", + "result_delete_success": "Deleted Result!", + "rx": "Received", + "rx_messages": "Rx Messages", + "sim_currently_running": "Simulation \"{{sim}}\" in progress", + "sim_history": "{{sim}} Previous Runs", + "start": "Start Simulation", + "start_success": "Started simulation run!", + "state_interval": "State Interval", + "stop": "Stop Simulation", + "stop_success": "Stopped simulation!", + "threads": "Threads", + "time_to_full": "Time to full devices", + "tx": "Transmitted", + "tx_messages": "Tx Messages", + "view_previous_runs": "View Previous Runs" + }, "statistics": { "last_stats": "Last Statistics", "memory": "Memory" diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json index b28edf1..edb986f 100644 --- a/public/locales/es/translation.json +++ b/public/locales/es/translation.json @@ -593,6 +593,8 @@ "devices": { "all": "TODOS", "associations": "Asociaciones", + "certificate_expires_in": "El certificado caduca en", + "certificate_expiry": "Cert. Expira en", "connected": "Conectado", "create_errors": "errores al intentar crear dispositivos", "create_success": " dispositivos creados con éxito", @@ -613,6 +615,7 @@ "notifications": "notificaciones de dispositivos", "one": "Dispositivo", "reassign_already_owned": "¿Reasignar dispositivos que ya existen y son propiedad de otra entidad/lugar/suscriptor?", + "restricted": "Restringido", "sanity": "Cordura", "start_import": "Iniciar la importación de dispositivos", "test_batch": "Datos de importación de prueba", @@ -670,6 +673,7 @@ "version": "Versión" }, "form": { + "captive_web_root_explanation": "Utilice únicamente archivos .tar (no archivos comprimidos como .targz, por ejemplo)", "certificate_file_explanation": "Utilice un archivo .pem que comience con \"-----BEGIN CERTIFICATE-----\" y termine con \"-----END CERTIFICATE-----\"", "invalid_cidr": "Dirección IPv4 CIDR no válida. Ejemplo: 192.168.0.1/12", "invalid_email": "Email inválido", @@ -678,6 +682,7 @@ "invalid_hostname": "Nombre de host no válido: debe estar compuesto solo de caracteres alfanuméricos y guiones", "invalid_icon_lang": "Idioma no válido, debe estar en un formato de 3 letras (eng, fre, ger, ita, etc.)", "invalid_ieee": "Para este protocolo de encriptación, ieee80211w debe ser 'opcional' u 'requerido'", + "invalid_ieee_required": "ieee80211w debe ser 'requerido' para este protocolo de encriptación", "invalid_interfaces": "Cadena JSON de interfaces no válida. Confirme que su valor es: JSON válido y tiene interfaces como su única clave y que el valor de las interfaces es una matriz. Ejemplo: {\"interfaces\": []}", "invalid_ipv4": "Dirección IPv4 no válida (ej.: 192.168.0.1 o 192.168.0.1/16", "invalid_ipv6": "Dirección IPv6 no válida (ej.: 2001:db8:3333:4444:5555:6666:7777:8888)", @@ -853,6 +858,48 @@ "one": "Clase de servicio", "other": "Clases de servicio" }, + "simulation": { + "cancel": "Cancelar simulación", + "cancel_explanation": "Detener la simulación y borrar su registro", + "cancel_success": "¡Detuvo la simulación y borró su registro!", + "client_interval": "Intervalo de cliente", + "concurrent_devices": "Dispositivos concurrentes", + "controller": "Controlador", + "current_live_devices": "Dispositivos activos actuales", + "delete_success": "¡Simulación eliminada!", + "duration": "Duración", + "error_devices": "Dispositivos de error", + "healthcheck_interval": "Intervalo de comprobación de estado", + "infinite": "infinito", + "keep_alive": "Mantener viva", + "mac_prefix": "Prefijo MAC", + "max_associations": "Max. Asociaciones", + "max_clients": "Max. Clientela", + "min_associations": "Min. Asociaciones", + "min_clients": "Min. Clientela", + "no_sim_running": "No hay ninguna simulación actualmente en ejecución", + "one": "Simulación", + "other": "Simulaciones", + "owner": "Propietario", + "realtime_data": "Datos en Tiempo real", + "realtime_messages": "Mensajes en tiempo real", + "reconnect_interval": "Intervalo de reconexión", + "result_delete_success": "¡Resultado eliminado!", + "rx": "recibido", + "rx_messages": "Mensajes prescritos", + "sim_currently_running": "Simulación \"{{sim}}\" en curso", + "sim_history": "{{sim}} ejecuciones anteriores", + "start": "Iniciar simulación", + "start_success": "¡Ejecución de simulación iniciada!", + "state_interval": "Intervalo de estado", + "stop": "Detener simulación", + "stop_success": "Simulación detenida!", + "threads": "Trapos", + "time_to_full": "Tiempo para dispositivos completos", + "tx": "Transmitido", + "tx_messages": "Mensajes TX", + "view_previous_runs": "Ver carreras anteriores" + }, "statistics": { "last_stats": "Últimas estadísticas", "memory": "Memoria" diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 84fcfbf..c5e1ab6 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -593,6 +593,8 @@ "devices": { "all": "Tout", "associations": "Les associations", + "certificate_expires_in": "Le certificat expire dans", + "certificate_expiry": "Cert. Expire dans", "connected": "Connecté", "create_errors": "erreurs lors de la tentative de création d'appareils", "create_success": " appareils créés avec succès", @@ -613,6 +615,7 @@ "notifications": "notifications de l'appareil", "one": "Dispositif", "reassign_already_owned": "Réattribuer des appareils qui existent déjà et qui appartiennent à une autre entité/salle/abonné ?", + "restricted": "Limité", "sanity": "Santé mentale", "start_import": "Démarrer l'importation de l'appareil", "test_batch": "Tester les données d'importation", @@ -670,6 +673,7 @@ "version": "Version" }, "form": { + "captive_web_root_explanation": "Veuillez utiliser uniquement des fichiers .tar (pas de fichiers compressés comme .targz, par exemple)", "certificate_file_explanation": "Veuillez utiliser un fichier .pem qui commence par \"-----BEGIN CERTIFICATE-----\" et se termine par \"-----END CERTIFICATE-----\"", "invalid_cidr": "Adresse IPv4 CIDR non valide. Exemple : 192.168.0.1/12", "invalid_email": "Email Invalide", @@ -678,6 +682,7 @@ "invalid_hostname": "Nom d'hôte non valide : il doit être composé uniquement de caractères alphanumériques et de tirets", "invalid_icon_lang": "Langue non valide, elle doit être dans un format à 3 lettres (eng, fre, ger, ita, etc.)", "invalid_ieee": "Pour ce protocole de cryptage, ieee80211w doit être soit 'facultatif' soit 'obligatoire'", + "invalid_ieee_required": "ieee80211w doit être \"obligatoire\" pour ce protocole de cryptage", "invalid_interfaces": "Chaîne JSON d'interfaces non valide. Veuillez confirmer que votre valeur est : JSON valide et a des interfaces comme seule clé et que la valeur des interfaces est un tableau. Exemple : {\"interfaces\": []}", "invalid_ipv4": "Adresse IPv4 invalide (ex. : 192.168.0.1 ou 192.168.0.1/16", "invalid_ipv6": "Adresse IPv6 invalide (ex. : 2001:db8:3333:4444:5555:6666:7777:8888)", @@ -853,6 +858,48 @@ "one": "Classe de service", "other": "Catégories de services" }, + "simulation": { + "cancel": "Annuler la simulation", + "cancel_explanation": "Arrêtez la simulation et effacez son enregistrement", + "cancel_success": "Simulation arrêtée et efface son enregistrement !", + "client_interval": "Intervalle client", + "concurrent_devices": "Périphériques simultanés", + "controller": "Manette", + "current_live_devices": "Appareils en direct actuels", + "delete_success": "Simulation supprimée !", + "duration": "Durée", + "error_devices": "Périphériques d'erreur", + "healthcheck_interval": "Intervalle de vérification de l'état", + "infinite": "Infini", + "keep_alive": "Rester en vie", + "mac_prefix": "Préfixe MAC", + "max_associations": "Max. Les associations", + "max_clients": "Max. Clients", + "min_associations": "Min. Les associations", + "min_clients": "Min. Clients", + "no_sim_running": "Aucune simulation en cours", + "one": "simulation", + "other": "Simulations", + "owner": "Propriétaire", + "realtime_data": "Données en temps réel", + "realtime_messages": "Messages en temps réel", + "reconnect_interval": "Intervalle de reconnexion", + "result_delete_success": "Résultat supprimé !", + "rx": "reçu", + "rx_messages": "Messages reçus", + "sim_currently_running": "Simulation \"{{sim}}\" en cours", + "sim_history": "{{sim}} courses précédentes", + "start": "Démarrer la simulation", + "start_success": "Lancement de la simulation !", + "state_interval": "Intervalle d'état", + "stop": "Arrêter la simulation", + "stop_success": "Simulation arrêtée !", + "threads": "Fils", + "time_to_full": "Temps pour les appareils pleins", + "tx": "Transmis", + "tx_messages": "Messages de transmission", + "view_previous_runs": "Voir les courses précédentes" + }, "statistics": { "last_stats": "Dernières statistiques", "memory": "mémoire" diff --git a/public/locales/pt/translation.json b/public/locales/pt/translation.json index c5decf9..35bdcde 100644 --- a/public/locales/pt/translation.json +++ b/public/locales/pt/translation.json @@ -593,6 +593,8 @@ "devices": { "all": "Todos", "associations": "Associações", + "certificate_expires_in": "Certificado expira em", + "certificate_expiry": "Certificado expira em", "connected": "Conectado", "create_errors": "erros ao tentar criar dispositivos", "create_success": " dispositivos criados com sucesso", @@ -613,6 +615,7 @@ "notifications": "Notificações do dispositivo", "one": "Dispositivo", "reassign_already_owned": "Reatribuir dispositivos que já existem e são de propriedade de outra entidade/local/assinante?", + "restricted": "Restrito", "sanity": "Sanidade", "start_import": "Iniciar importação de dispositivos", "test_batch": "Dados de importação de teste", @@ -670,6 +673,7 @@ "version": "Versão" }, "form": { + "captive_web_root_explanation": "Por favor, use apenas arquivos .tar (sem arquivos compactados como .targz, por exemplo)", "certificate_file_explanation": "Use um arquivo .pem que comece com \"-----BEGIN CERTIFICATE-----\" e termine com \"-----END CERTIFICATE-----\"", "invalid_cidr": "Endereço CIDR IPv4 inválido. Exemplo: 192.168.0.1/12", "invalid_email": "E-mail inválido", @@ -678,6 +682,7 @@ "invalid_hostname": "Nome de host inválido: precisa ser composto apenas de caracteres alfanuméricos e traços", "invalid_icon_lang": "Idioma inválido, deve estar em formato de 3 letras (eng, fre, ger, ita, etc.)", "invalid_ieee": "Para este protocolo de criptografia, ieee80211w precisa ser 'opcional' ou 'obrigatório'", + "invalid_ieee_required": "ieee80211w precisa ser 'obrigatório' para este protocolo de criptografia", "invalid_interfaces": "Sequência JSON de interfaces inválida. Confirme se seu valor é: JSON válido e tem interfaces como sua única chave e que o valor de interfaces é uma matriz. Exemplo: {\"interfaces\": []}", "invalid_ipv4": "Endereço IPv4 inválido (ex.: 192.168.0.1 ou 192.168.0.1/16", "invalid_ipv6": "Endereço IPv6 inválido (ex.: 2001:db8:3333:4444:5555:6666:7777:8888)", @@ -853,6 +858,48 @@ "one": "Classe de serviço", "other": "Classes de serviço" }, + "simulation": { + "cancel": "Cancelar simulação", + "cancel_explanation": "Pare a simulação e apague seu registro", + "cancel_success": "Parou a simulação e apagou seu registro!", + "client_interval": "Intervalo do Cliente", + "concurrent_devices": "Dispositivos Simultâneos", + "controller": "Controlador", + "current_live_devices": "Dispositivos ativos atuais", + "delete_success": "Simulação excluída!", + "duration": "Duração", + "error_devices": "Dispositivos de Erro", + "healthcheck_interval": "Intervalo de verificação de saúde", + "infinite": "Infinito", + "keep_alive": "Mantenha vivo", + "mac_prefix": "Prefixo MAC", + "max_associations": "Máx. Associações", + "max_clients": "Máx. Clientes", + "min_associations": "Min. Associações", + "min_clients": "Min. Clientes", + "no_sim_running": "Nenhuma simulação em execução no momento", + "one": "Simulação", + "other": "Simulações", + "owner": "Proprietário", + "realtime_data": "Dados em tempo real", + "realtime_messages": "Mensagens em tempo real", + "reconnect_interval": "Intervalo de reconexão", + "result_delete_success": "Resultado deletado!", + "rx": "recebido", + "rx_messages": "Mensagens Rx", + "sim_currently_running": "Simulação \"{{sim}}\" em andamento", + "sim_history": "{{sim}} execuções anteriores", + "start": "Iniciar simulação", + "start_success": "Corrida de simulação iniciada!", + "state_interval": "Intervalo de estado", + "stop": "Parar simulação", + "stop_success": "Simulação parada!", + "threads": "Tópicos", + "time_to_full": "Tempo para dispositivos completos", + "tx": "Transmitido", + "tx_messages": "Mensagens Tx", + "view_previous_runs": "Ver execuções anteriores" + }, "statistics": { "last_stats": "Últimas estatísticas", "memory": "Memória" diff --git a/src/components/InformationDisplays/FormattedDate/index.tsx b/src/components/InformationDisplays/FormattedDate/index.tsx index e136887..1939f03 100644 --- a/src/components/InformationDisplays/FormattedDate/index.tsx +++ b/src/components/InformationDisplays/FormattedDate/index.tsx @@ -2,9 +2,17 @@ import React from 'react'; import { Tooltip } from '@chakra-ui/react'; import { compactDate, formatDaysAgo } from 'helpers/dateFormatting'; -const FormattedDate: React.FC<{ date: number }> = ({ date }) => ( - - {date === 0 ? '-' : formatDaysAgo(date)} +type Props = { date?: number; hidePrefix?: boolean }; + +const getDaysAgo = ({ date, hidePrefix }: { date?: number; hidePrefix?: boolean }) => { + if (!date || date === 0) return '-'; + + return hidePrefix ? formatDaysAgo(date).split(' ').slice(1).join(' ') : formatDaysAgo(date); +}; + +const FormattedDate = ({ date, hidePrefix }: Props) => ( + + {getDaysAgo({ date, hidePrefix })} ); diff --git a/src/hooks/Network/Devices.ts b/src/hooks/Network/Devices.ts index 9b8efd3..7e7ffba 100644 --- a/src/hooks/Network/Devices.ts +++ b/src/hooks/Network/Devices.ts @@ -43,6 +43,7 @@ export type DeviceWithStatus = { associations_5G: number; compatible: string; connected: boolean; + certificateExpiryDate?: number; createdTimestamp: number; devicePassword: string; deviceType: 'AP' | 'SWITCH' | 'IOT' | 'MESH'; @@ -62,6 +63,7 @@ export type DeviceWithStatus = { modified: number; notes: Note[]; owner: string; + restrictedDevice: boolean; rxBytes: number; serialNumber: string; subscriber: string; @@ -124,6 +126,7 @@ export type DeviceStatus = { associations_2G: number; associations_5G: number; connected: boolean; + certificateExpiryDate: number; connectionCompletionTime: number; firmware: string; ipAddress: string; @@ -245,7 +248,7 @@ export const useDeleteDevice = ({ serialNumber }: { serialNumber: string }) => { return useMutation(deleteDevice, { onSuccess: () => { - queryClient.invalidateQueries('devices'); + queryClient.invalidateQueries(['devices']); queryClient.invalidateQueries(['device', serialNumber]); }, }); @@ -396,7 +399,7 @@ export const useUpdateDevice = ({ serialNumber }: { serialNumber: string }) => { return useMutation(modifyDevice, { onSuccess: () => { - queryClient.invalidateQueries('devices'); + queryClient.invalidateQueries(['devices']); queryClient.invalidateQueries(['device', serialNumber]); }, }); diff --git a/src/models/Device.ts b/src/models/Device.ts index 39943b2..c1c14d5 100644 --- a/src/models/Device.ts +++ b/src/models/Device.ts @@ -21,6 +21,7 @@ export interface GatewayDevice { modified: number; notes: Note[]; owner: string; + restrictedDevice: boolean; serialNumber: string; subscriber: string; venue: string; diff --git a/src/pages/Device/Summary.tsx b/src/pages/Device/Summary.tsx index 41db051..b1b1259 100644 --- a/src/pages/Device/Summary.tsx +++ b/src/pages/Device/Summary.tsx @@ -106,6 +106,14 @@ const DeviceSummary = ({ serialNumber }: Props) => { {t('analytics.memory')}: {getMemory()} + + {t('devices.certificate_expires_in')}: + + + {getStatus.data?.certificateExpiryDate && ( + + )} + diff --git a/src/pages/Device/Wrapper.tsx b/src/pages/Device/Wrapper.tsx index 14f1c10..0f0efc8 100644 --- a/src/pages/Device/Wrapper.tsx +++ b/src/pages/Device/Wrapper.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { Box, Heading, HStack, Spacer, Tag, TagLabel, TagLeftIcon, Tooltip, useDisclosure } from '@chakra-ui/react'; -import { Heart, HeartBreak, WifiHigh, WifiSlash } from 'phosphor-react'; +import { Heart, HeartBreak, LockSimple, WifiHigh, WifiSlash } from 'phosphor-react'; import { useTranslation } from 'react-i18next'; import Masonry from 'react-masonry-css'; import DeviceDetails from './Details'; @@ -97,6 +97,12 @@ const DevicePageWrapper = ({ serialNumber }: Props) => { {serialNumber} {connectedTag} {healthTag} + {getDevice.data?.restrictedDevice && ( + + + {t('devices.restricted')} + + )} diff --git a/src/pages/Devices/ListCard/index.tsx b/src/pages/Devices/ListCard/index.tsx index 941eae0..72c0b0c 100644 --- a/src/pages/Devices/ListCard/index.tsx +++ b/src/pages/Devices/ListCard/index.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { Box, Button, Heading, Image, Spacer, Tooltip, useDisclosure } from '@chakra-ui/react'; +import { LockSimple } from 'phosphor-react'; import ReactCountryFlag from 'react-country-flag'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; @@ -115,7 +116,7 @@ const DeviceListCard = () => { {ICONS[device.deviceType]} @@ -130,6 +131,26 @@ const DeviceListCard = () => { borderColor="gray.200" borderWidth={1} /> + {device.restrictedDevice && ( + + + + )} ), [], @@ -152,8 +173,12 @@ const DeviceListCard = () => { [], ); const dateCell = React.useCallback( - (v: number | string) => - v !== undefined && typeof v === 'number' && v !== 0 ? : '-', + (v?: number | string, hidePrefix?: boolean) => + v !== undefined && typeof v === 'number' && v !== 0 ? ( + + ) : ( + '-' + ), [], ); const firmwareCell = React.useCallback( @@ -303,6 +328,15 @@ const DeviceListCard = () => { customWidth: '50px', disableSortBy: true, }, + { + id: 'certificateExpiryDate', + Header: t('devices.certificate_expiry'), + Footer: '', + accessor: 'certificateExpiryDate', + Cell: (v) => dateCell(v.cell.row.original.certificateExpiryDate, true), + customWidth: '50px', + disableSortBy: true, + }, { id: 'actions', Header: t('common.actions'), diff --git a/src/pages/SystemPage/index.tsx b/src/pages/SystemPage/index.tsx index 7552d87..9125d7a 100644 --- a/src/pages/SystemPage/index.tsx +++ b/src/pages/SystemPage/index.tsx @@ -43,7 +43,7 @@ const SystemPage = () => { - {t('controller.firmware.endpoints')} ({endpoints?.length ?? 0}) + {t('controller.firmware.endpoints')}