mirror of
				https://github.com/Telecominfraproject/wlan-cloud-owprov-ui.git
				synced 2025-11-03 20:18:11 +00:00 
			
		
		
		
	[WIFI-11706] Fix for missing analytics in venue page
Signed-off-by: Charles <charles.bourque96@gmail.com>
This commit is contained in:
		
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1,12 +1,12 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "wlan-cloud-owprov-ui",
 | 
					  "name": "wlan-cloud-owprov-ui",
 | 
				
			||||||
  "version": "2.8.0(13)",
 | 
					  "version": "2.8.0(17)",
 | 
				
			||||||
  "lockfileVersion": 2,
 | 
					  "lockfileVersion": 2,
 | 
				
			||||||
  "requires": true,
 | 
					  "requires": true,
 | 
				
			||||||
  "packages": {
 | 
					  "packages": {
 | 
				
			||||||
    "": {
 | 
					    "": {
 | 
				
			||||||
      "name": "wlan-cloud-owprov-ui",
 | 
					      "name": "wlan-cloud-owprov-ui",
 | 
				
			||||||
      "version": "2.8.0(13)",
 | 
					      "version": "2.8.0(17)",
 | 
				
			||||||
      "license": "ISC",
 | 
					      "license": "ISC",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "@chakra-ui/icons": "^2.0.11",
 | 
					        "@chakra-ui/icons": "^2.0.11",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "wlan-cloud-owprov-ui",
 | 
					  "name": "wlan-cloud-owprov-ui",
 | 
				
			||||||
  "version": "2.8.0(13)",
 | 
					  "version": "2.8.0(17)",
 | 
				
			||||||
  "description": "",
 | 
					  "description": "",
 | 
				
			||||||
  "main": "index.tsx",
 | 
					  "main": "index.tsx",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,6 +79,7 @@
 | 
				
			|||||||
		"live_view_help": "Hilfe zur Live-Ansicht",
 | 
							"live_view_help": "Hilfe zur Live-Ansicht",
 | 
				
			||||||
		"memory": "Erinnerung",
 | 
							"memory": "Erinnerung",
 | 
				
			||||||
		"memory_used": "Verwendeter Speicher",
 | 
							"memory_used": "Verwendeter Speicher",
 | 
				
			||||||
 | 
							"missing_board": "Die Analytics-Überwachung an diesem Veranstaltungsort ist nicht mehr aktiv. Bitte starten Sie die Überwachung über das obere Menü neu",
 | 
				
			||||||
		"mode": "Modus",
 | 
							"mode": "Modus",
 | 
				
			||||||
		"noise": "Lärm",
 | 
							"noise": "Lärm",
 | 
				
			||||||
		"packets": "Pakete",
 | 
							"packets": "Pakete",
 | 
				
			||||||
@@ -613,6 +614,7 @@
 | 
				
			|||||||
		"import_explanation": "Für den Massenimport von Geräten müssen Sie eine CSV-Datei mit den folgenden Spalten verwenden: SerialNumber, DeviceType, Name, Description, Note",
 | 
							"import_explanation": "Für den Massenimport von Geräten müssen Sie eine CSV-Datei mit den folgenden Spalten verwenden: SerialNumber, DeviceType, Name, Description, Note",
 | 
				
			||||||
		"invalid_serial_number": "Ungültige Seriennummer (muss 12 HEX-Zeichen lang sein)",
 | 
							"invalid_serial_number": "Ungültige Seriennummer (muss 12 HEX-Zeichen lang sein)",
 | 
				
			||||||
		"new_devices": "Neue Geräte",
 | 
							"new_devices": "Neue Geräte",
 | 
				
			||||||
 | 
							"no_model_image": "Kein Modellbild gefunden",
 | 
				
			||||||
		"not_connected": "Nicht verbunden",
 | 
							"not_connected": "Nicht verbunden",
 | 
				
			||||||
		"not_found_gateway": "Fehler: Gerät hat sich noch nicht mit dem Gateway verbunden",
 | 
							"not_found_gateway": "Fehler: Gerät hat sich noch nicht mit dem Gateway verbunden",
 | 
				
			||||||
		"notifications": "Gerätebenachrichtigungen",
 | 
							"notifications": "Gerätebenachrichtigungen",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,6 +79,7 @@
 | 
				
			|||||||
		"live_view_help": "Live View Help",
 | 
							"live_view_help": "Live View Help",
 | 
				
			||||||
		"memory": "Memory",
 | 
							"memory": "Memory",
 | 
				
			||||||
		"memory_used": "Memory Used",
 | 
							"memory_used": "Memory Used",
 | 
				
			||||||
 | 
							"missing_board": "Analytics monitoring on this venue is no longer active, please restart monitoring using the top menu",
 | 
				
			||||||
		"mode": "Mode",
 | 
							"mode": "Mode",
 | 
				
			||||||
		"noise": "Noise",
 | 
							"noise": "Noise",
 | 
				
			||||||
		"packets": "Packets",
 | 
							"packets": "Packets",
 | 
				
			||||||
@@ -613,6 +614,7 @@
 | 
				
			|||||||
		"import_explanation": "To bulk import devices, you need to use a CSV file with the following columns: SerialNumber, DeviceType, Name, Description, Note",
 | 
							"import_explanation": "To bulk import devices, you need to use a CSV file with the following columns: SerialNumber, DeviceType, Name, Description, Note",
 | 
				
			||||||
		"invalid_serial_number": "Invalid Serial Number (needs to be 12 HEX chars)",
 | 
							"invalid_serial_number": "Invalid Serial Number (needs to be 12 HEX chars)",
 | 
				
			||||||
		"new_devices": "new devices",
 | 
							"new_devices": "new devices",
 | 
				
			||||||
 | 
							"no_model_image": "No Model Image Found",
 | 
				
			||||||
		"not_connected": "Not Connected",
 | 
							"not_connected": "Not Connected",
 | 
				
			||||||
		"not_found_gateway": "Error: device has not yet connected to the controller",
 | 
							"not_found_gateway": "Error: device has not yet connected to the controller",
 | 
				
			||||||
		"notifications": "Device Notifications",
 | 
							"notifications": "Device Notifications",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,6 +79,7 @@
 | 
				
			|||||||
		"live_view_help": "Ayuda de visualización en vivo",
 | 
							"live_view_help": "Ayuda de visualización en vivo",
 | 
				
			||||||
		"memory": "Memoria",
 | 
							"memory": "Memoria",
 | 
				
			||||||
		"memory_used": "Memoria usada",
 | 
							"memory_used": "Memoria usada",
 | 
				
			||||||
 | 
							"missing_board": "El monitoreo analítico en este lugar ya no está activo, reinicie el monitoreo usando el menú superior",
 | 
				
			||||||
		"mode": "Modo",
 | 
							"mode": "Modo",
 | 
				
			||||||
		"noise": "Ruido",
 | 
							"noise": "Ruido",
 | 
				
			||||||
		"packets": "Paquetes",
 | 
							"packets": "Paquetes",
 | 
				
			||||||
@@ -613,6 +614,7 @@
 | 
				
			|||||||
		"import_explanation": "Para importar dispositivos de forma masiva, debe usar un archivo CSV con las siguientes columnas: Número de serie, Tipo de dispositivo, Nombre, Descripción, Nota",
 | 
							"import_explanation": "Para importar dispositivos de forma masiva, debe usar un archivo CSV con las siguientes columnas: Número de serie, Tipo de dispositivo, Nombre, Descripción, Nota",
 | 
				
			||||||
		"invalid_serial_number": "Número de serie no válido (debe tener 12 caracteres HEX)",
 | 
							"invalid_serial_number": "Número de serie no válido (debe tener 12 caracteres HEX)",
 | 
				
			||||||
		"new_devices": "Nuevos dispositivos",
 | 
							"new_devices": "Nuevos dispositivos",
 | 
				
			||||||
 | 
							"no_model_image": "No se encontró ninguna imagen de modelo",
 | 
				
			||||||
		"not_connected": "No conectado",
 | 
							"not_connected": "No conectado",
 | 
				
			||||||
		"not_found_gateway": "Error: el dispositivo aún no se ha conectado a la puerta de enlace",
 | 
							"not_found_gateway": "Error: el dispositivo aún no se ha conectado a la puerta de enlace",
 | 
				
			||||||
		"notifications": "notificaciones de dispositivos",
 | 
							"notifications": "notificaciones de dispositivos",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,6 +79,7 @@
 | 
				
			|||||||
		"live_view_help": "Aide sur l'affichage en direct",
 | 
							"live_view_help": "Aide sur l'affichage en direct",
 | 
				
			||||||
		"memory": "mémoire",
 | 
							"memory": "mémoire",
 | 
				
			||||||
		"memory_used": "Mémoire utilisée",
 | 
							"memory_used": "Mémoire utilisée",
 | 
				
			||||||
 | 
							"missing_board": "La surveillance analytique sur ce lieu n'est plus active, veuillez redémarrer la surveillance en utilisant le menu du haut",
 | 
				
			||||||
		"mode": "Mode",
 | 
							"mode": "Mode",
 | 
				
			||||||
		"noise": "Bruit",
 | 
							"noise": "Bruit",
 | 
				
			||||||
		"packets": "Paquets",
 | 
							"packets": "Paquets",
 | 
				
			||||||
@@ -613,6 +614,7 @@
 | 
				
			|||||||
		"import_explanation": "Pour importer en masse des appareils, vous devez utiliser un fichier CSV avec les colonnes suivantes : SerialNumber, DeviceType, Name, Description, Note",
 | 
							"import_explanation": "Pour importer en masse des appareils, vous devez utiliser un fichier CSV avec les colonnes suivantes : SerialNumber, DeviceType, Name, Description, Note",
 | 
				
			||||||
		"invalid_serial_number": "Numéro de série non valide (doit être composé de 12 caractères HEX)",
 | 
							"invalid_serial_number": "Numéro de série non valide (doit être composé de 12 caractères HEX)",
 | 
				
			||||||
		"new_devices": "nouveaux appareils",
 | 
							"new_devices": "nouveaux appareils",
 | 
				
			||||||
 | 
							"no_model_image": "Aucune image de modèle trouvée",
 | 
				
			||||||
		"not_connected": "Pas connecté",
 | 
							"not_connected": "Pas connecté",
 | 
				
			||||||
		"not_found_gateway": "Erreur : l'appareil n'est pas encore connecté à la passerelle",
 | 
							"not_found_gateway": "Erreur : l'appareil n'est pas encore connecté à la passerelle",
 | 
				
			||||||
		"notifications": "notifications de l'appareil",
 | 
							"notifications": "notifications de l'appareil",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,6 +79,7 @@
 | 
				
			|||||||
		"live_view_help": "Ajuda da visualização ao vivo",
 | 
							"live_view_help": "Ajuda da visualização ao vivo",
 | 
				
			||||||
		"memory": "Memória",
 | 
							"memory": "Memória",
 | 
				
			||||||
		"memory_used": "Memória Usada",
 | 
							"memory_used": "Memória Usada",
 | 
				
			||||||
 | 
							"missing_board": "O monitoramento analítico neste local não está mais ativo, reinicie o monitoramento usando o menu superior",
 | 
				
			||||||
		"mode": "Modo",
 | 
							"mode": "Modo",
 | 
				
			||||||
		"noise": "Barulho",
 | 
							"noise": "Barulho",
 | 
				
			||||||
		"packets": "Pacotes",
 | 
							"packets": "Pacotes",
 | 
				
			||||||
@@ -613,6 +614,7 @@
 | 
				
			|||||||
		"import_explanation": "Para importar dispositivos em massa, você precisa usar um arquivo CSV com as seguintes colunas: SerialNumber, DeviceType, Name, Description, Note",
 | 
							"import_explanation": "Para importar dispositivos em massa, você precisa usar um arquivo CSV com as seguintes colunas: SerialNumber, DeviceType, Name, Description, Note",
 | 
				
			||||||
		"invalid_serial_number": "Número de série inválido (precisa ter 12 caracteres HEX)",
 | 
							"invalid_serial_number": "Número de série inválido (precisa ter 12 caracteres HEX)",
 | 
				
			||||||
		"new_devices": "novos dispositivos",
 | 
							"new_devices": "novos dispositivos",
 | 
				
			||||||
 | 
							"no_model_image": "Nenhuma imagem de modelo encontrada",
 | 
				
			||||||
		"not_connected": "Não conectado",
 | 
							"not_connected": "Não conectado",
 | 
				
			||||||
		"not_found_gateway": "Erro: o dispositivo ainda não se conectou ao gateway",
 | 
							"not_found_gateway": "Erro: o dispositivo ainda não se conectou ao gateway",
 | 
				
			||||||
		"notifications": "Notificações do dispositivo",
 | 
							"notifications": "Notificações do dispositivo",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,45 +1,259 @@
 | 
				
			|||||||
import { useToast } from '@chakra-ui/react';
 | 
					import { useToast } from '@chakra-ui/react';
 | 
				
			||||||
import { useMutation, useQuery } from '@tanstack/react-query';
 | 
					import { useMutation, useQuery } from '@tanstack/react-query';
 | 
				
			||||||
import { AxiosError } from 'axios';
 | 
					 | 
				
			||||||
import { useTranslation } from 'react-i18next';
 | 
					import { useTranslation } from 'react-i18next';
 | 
				
			||||||
 | 
					import { AxiosError } from 'models/Axios';
 | 
				
			||||||
 | 
					import { Note } from 'models/Note';
 | 
				
			||||||
import { PageInfo, SortInfo } from 'models/Table';
 | 
					import { PageInfo, SortInfo } from 'models/Table';
 | 
				
			||||||
import { axiosAnalytics } from 'utils/axiosInstances';
 | 
					import { axiosAnalytics } from 'utils/axiosInstances';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsBoardDevice = {
 | 
				
			||||||
 | 
					  associations_2g: number;
 | 
				
			||||||
 | 
					  associations_5g: number;
 | 
				
			||||||
 | 
					  associations_6g: number;
 | 
				
			||||||
 | 
					  boardId: string;
 | 
				
			||||||
 | 
					  connected: boolean;
 | 
				
			||||||
 | 
					  connectionIp: string;
 | 
				
			||||||
 | 
					  deviceType: string;
 | 
				
			||||||
 | 
					  health: number;
 | 
				
			||||||
 | 
					  lastConnection: number;
 | 
				
			||||||
 | 
					  lastContact: number;
 | 
				
			||||||
 | 
					  lastDisconnection: number;
 | 
				
			||||||
 | 
					  lastFirmware: string;
 | 
				
			||||||
 | 
					  lastFirmwareUpdate: number;
 | 
				
			||||||
 | 
					  lastHealth: number;
 | 
				
			||||||
 | 
					  lastPing: number;
 | 
				
			||||||
 | 
					  lastState: number;
 | 
				
			||||||
 | 
					  locale: string;
 | 
				
			||||||
 | 
					  memory: number;
 | 
				
			||||||
 | 
					  pings: number;
 | 
				
			||||||
 | 
					  serialNumber: string;
 | 
				
			||||||
 | 
					  states: number;
 | 
				
			||||||
 | 
					  type: string;
 | 
				
			||||||
 | 
					  uptime: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsBoardDevicesApiResponse = {
 | 
				
			||||||
 | 
					  devices: AnalyticsBoardDevice[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsBoardApiResponse = {
 | 
				
			||||||
 | 
					  created: number;
 | 
				
			||||||
 | 
					  description: string;
 | 
				
			||||||
 | 
					  id: string;
 | 
				
			||||||
 | 
					  modified: number;
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  notes: Note[];
 | 
				
			||||||
 | 
					  tags: string[];
 | 
				
			||||||
 | 
					  venueList: {
 | 
				
			||||||
 | 
					    description: string;
 | 
				
			||||||
 | 
					    id: string;
 | 
				
			||||||
 | 
					    interval: number;
 | 
				
			||||||
 | 
					    monitorSubVenues: boolean;
 | 
				
			||||||
 | 
					    name: string;
 | 
				
			||||||
 | 
					    retention: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsClientLifecycleApiResponse = {
 | 
				
			||||||
 | 
					  ack_signal: number;
 | 
				
			||||||
 | 
					  ack_signal_avg: number;
 | 
				
			||||||
 | 
					  active_ms: number;
 | 
				
			||||||
 | 
					  bssid: string;
 | 
				
			||||||
 | 
					  busy_ms: number;
 | 
				
			||||||
 | 
					  channel: number;
 | 
				
			||||||
 | 
					  channel_width: number;
 | 
				
			||||||
 | 
					  connected: number;
 | 
				
			||||||
 | 
					  inactive: number;
 | 
				
			||||||
 | 
					  ipv4: string;
 | 
				
			||||||
 | 
					  ipv6: string;
 | 
				
			||||||
 | 
					  mode: string;
 | 
				
			||||||
 | 
					  noise: number;
 | 
				
			||||||
 | 
					  receive_ms: number;
 | 
				
			||||||
 | 
					  rssi: number;
 | 
				
			||||||
 | 
					  rx_bitrate: number;
 | 
				
			||||||
 | 
					  rx_bytes: number;
 | 
				
			||||||
 | 
					  rx_chwidth: number;
 | 
				
			||||||
 | 
					  rx_duration: number;
 | 
				
			||||||
 | 
					  rx_mcs: number;
 | 
				
			||||||
 | 
					  rx_nss: number;
 | 
				
			||||||
 | 
					  rx_packets: number;
 | 
				
			||||||
 | 
					  rx_vht: boolean;
 | 
				
			||||||
 | 
					  ssid: string;
 | 
				
			||||||
 | 
					  station_id: string;
 | 
				
			||||||
 | 
					  timestamp: number;
 | 
				
			||||||
 | 
					  tx_bitrate: number;
 | 
				
			||||||
 | 
					  tx_bytes: number;
 | 
				
			||||||
 | 
					  tx_chwidth: number;
 | 
				
			||||||
 | 
					  tx_duration: number;
 | 
				
			||||||
 | 
					  tx_mcs: number;
 | 
				
			||||||
 | 
					  tx_nss: number;
 | 
				
			||||||
 | 
					  tx_packets: number;
 | 
				
			||||||
 | 
					  tx_power: number;
 | 
				
			||||||
 | 
					  tx_retries: number;
 | 
				
			||||||
 | 
					  tx_vht: boolean;
 | 
				
			||||||
 | 
					  venue_id: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsApData = {
 | 
				
			||||||
 | 
					  collisions: number;
 | 
				
			||||||
 | 
					  multicast: number;
 | 
				
			||||||
 | 
					  rx_bytes: number;
 | 
				
			||||||
 | 
					  rx_bytes_bw: number;
 | 
				
			||||||
 | 
					  rx_bytes_delta: number;
 | 
				
			||||||
 | 
					  rx_dropped: number;
 | 
				
			||||||
 | 
					  rx_dropped_delta: number;
 | 
				
			||||||
 | 
					  rx_dropped_pct: number;
 | 
				
			||||||
 | 
					  rx_errors: number;
 | 
				
			||||||
 | 
					  rx_errors_delta: number;
 | 
				
			||||||
 | 
					  rx_errors_pct: number;
 | 
				
			||||||
 | 
					  rx_packets: number;
 | 
				
			||||||
 | 
					  rx_packets_bw: number;
 | 
				
			||||||
 | 
					  rx_packets_delta: number;
 | 
				
			||||||
 | 
					  tx_bytes: number;
 | 
				
			||||||
 | 
					  tx_bytes_bw: number;
 | 
				
			||||||
 | 
					  tx_bytes_delta: number;
 | 
				
			||||||
 | 
					  tx_dropped: number;
 | 
				
			||||||
 | 
					  tx_dropped_delta: number;
 | 
				
			||||||
 | 
					  tx_dropped_pct: number;
 | 
				
			||||||
 | 
					  tx_errors: number;
 | 
				
			||||||
 | 
					  tx_errors_delta: number;
 | 
				
			||||||
 | 
					  tx_errors_pct: number;
 | 
				
			||||||
 | 
					  tx_packets: number;
 | 
				
			||||||
 | 
					  tx_packets_bw: number;
 | 
				
			||||||
 | 
					  tx_packets_delta: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsRadioData = {
 | 
				
			||||||
 | 
					  active_ms: number;
 | 
				
			||||||
 | 
					  active_pct: number;
 | 
				
			||||||
 | 
					  band: number;
 | 
				
			||||||
 | 
					  busy_ms: number;
 | 
				
			||||||
 | 
					  busy_pct: number;
 | 
				
			||||||
 | 
					  channel: number;
 | 
				
			||||||
 | 
					  channel_width: number;
 | 
				
			||||||
 | 
					  noise: number;
 | 
				
			||||||
 | 
					  receive_ms: number;
 | 
				
			||||||
 | 
					  receive_pct: number;
 | 
				
			||||||
 | 
					  temperature: number;
 | 
				
			||||||
 | 
					  transmit_ms: number;
 | 
				
			||||||
 | 
					  transmit_pct: number;
 | 
				
			||||||
 | 
					  tx_power: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsAssociationData = {
 | 
				
			||||||
 | 
					  connected: number;
 | 
				
			||||||
 | 
					  inactive: number;
 | 
				
			||||||
 | 
					  rssi: number;
 | 
				
			||||||
 | 
					  rx_bytes: number;
 | 
				
			||||||
 | 
					  rx_bytes_bw: number;
 | 
				
			||||||
 | 
					  rx_bytes_delta: number;
 | 
				
			||||||
 | 
					  rx_packets: number;
 | 
				
			||||||
 | 
					  rx_packets_bw: number;
 | 
				
			||||||
 | 
					  rx_packets_delta: number;
 | 
				
			||||||
 | 
					  rx_rate: {
 | 
				
			||||||
 | 
					    bitrate: number;
 | 
				
			||||||
 | 
					    chwidth: number;
 | 
				
			||||||
 | 
					    ht: boolean;
 | 
				
			||||||
 | 
					    mcs: number;
 | 
				
			||||||
 | 
					    nss: number;
 | 
				
			||||||
 | 
					    sgi: boolean;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  station: string;
 | 
				
			||||||
 | 
					  tx_bytes: number;
 | 
				
			||||||
 | 
					  tx_bytes_bw: number;
 | 
				
			||||||
 | 
					  tx_bytes_delta: number;
 | 
				
			||||||
 | 
					  tx_duration: number;
 | 
				
			||||||
 | 
					  tx_duration_delta: number;
 | 
				
			||||||
 | 
					  tx_duration_pct: number;
 | 
				
			||||||
 | 
					  tx_failed: number;
 | 
				
			||||||
 | 
					  tx_failed_delta: number;
 | 
				
			||||||
 | 
					  tx_failed_pct: number;
 | 
				
			||||||
 | 
					  tx_packets: number;
 | 
				
			||||||
 | 
					  tx_packets_bw: number;
 | 
				
			||||||
 | 
					  tx_packets_delta: number;
 | 
				
			||||||
 | 
					  tx_rate: {
 | 
				
			||||||
 | 
					    bitrate: number;
 | 
				
			||||||
 | 
					    chwidth: number;
 | 
				
			||||||
 | 
					    ht: boolean;
 | 
				
			||||||
 | 
					    mcs: number;
 | 
				
			||||||
 | 
					    nss: number;
 | 
				
			||||||
 | 
					    sgi: boolean;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  tx_retries: number;
 | 
				
			||||||
 | 
					  tx_retries_delta: number;
 | 
				
			||||||
 | 
					  tx_retries_pct: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsSsidData = {
 | 
				
			||||||
 | 
					  associations: AnalyticsAssociationData[];
 | 
				
			||||||
 | 
					  band: 2;
 | 
				
			||||||
 | 
					  bssid: string;
 | 
				
			||||||
 | 
					  channel: number;
 | 
				
			||||||
 | 
					  mode: string;
 | 
				
			||||||
 | 
					  rx_bytes_bw: {
 | 
				
			||||||
 | 
					    avg: number;
 | 
				
			||||||
 | 
					    max: number;
 | 
				
			||||||
 | 
					    min: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  rx_packets_bw: {
 | 
				
			||||||
 | 
					    avg: number;
 | 
				
			||||||
 | 
					    max: number;
 | 
				
			||||||
 | 
					    min: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  ssid: string;
 | 
				
			||||||
 | 
					  tx_bytes_bw: {
 | 
				
			||||||
 | 
					    avg: number;
 | 
				
			||||||
 | 
					    max: number;
 | 
				
			||||||
 | 
					    min: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  tx_duration_pct: {
 | 
				
			||||||
 | 
					    avg: number;
 | 
				
			||||||
 | 
					    max: number;
 | 
				
			||||||
 | 
					    min: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  tx_failed_pct: {
 | 
				
			||||||
 | 
					    avg: number;
 | 
				
			||||||
 | 
					    max: number;
 | 
				
			||||||
 | 
					    min: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  tx_packets_bw: {
 | 
				
			||||||
 | 
					    avg: number;
 | 
				
			||||||
 | 
					    max: number;
 | 
				
			||||||
 | 
					    min: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  tx_retries_pct: {
 | 
				
			||||||
 | 
					    avg: number;
 | 
				
			||||||
 | 
					    max: number;
 | 
				
			||||||
 | 
					    min: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsTimePointApiResponse = {
 | 
				
			||||||
 | 
					  ap_data: AnalyticsApData;
 | 
				
			||||||
 | 
					  boardId: string;
 | 
				
			||||||
 | 
					  device_info: AnalyticsBoardDevice;
 | 
				
			||||||
 | 
					  id: string;
 | 
				
			||||||
 | 
					  radio_data: AnalyticsRadioData[];
 | 
				
			||||||
 | 
					  serialNumber: string;
 | 
				
			||||||
 | 
					  ssid_data: AnalyticsSsidData[];
 | 
				
			||||||
 | 
					  timestamp: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AnalyticsTimePointsApiResponse = {
 | 
				
			||||||
 | 
					  points: AnalyticsTimePointApiResponse[][];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useGetAnalyticsBoard = ({ id }: { id?: string }) => {
 | 
					export const useGetAnalyticsBoard = ({ id }: { id?: string }) => {
 | 
				
			||||||
  const { t } = useTranslation();
 | 
					  const { t } = useTranslation();
 | 
				
			||||||
  const toast = useToast();
 | 
					  const toast = useToast();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return useQuery(['get-board', id], () => axiosAnalytics.get(`board/${id}`).then(({ data }) => data), {
 | 
					 | 
				
			||||||
    enabled: id !== undefined && id !== null && id.length > 0,
 | 
					 | 
				
			||||||
    onError: (e: AxiosError) => {
 | 
					 | 
				
			||||||
      if (!toast.isActive('board-fetching-error'))
 | 
					 | 
				
			||||||
        toast({
 | 
					 | 
				
			||||||
          id: 'board-fetching-error',
 | 
					 | 
				
			||||||
          title: t('common.error'),
 | 
					 | 
				
			||||||
          description: t('crud.error_fetching_obj', {
 | 
					 | 
				
			||||||
            obj: t('analytics.board'),
 | 
					 | 
				
			||||||
            e: e?.response?.data?.ErrorDescription,
 | 
					 | 
				
			||||||
          }),
 | 
					 | 
				
			||||||
          status: 'error',
 | 
					 | 
				
			||||||
          duration: 5000,
 | 
					 | 
				
			||||||
          isClosable: true,
 | 
					 | 
				
			||||||
          position: 'top-right',
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const useGetAnalyticsBoardDevices = ({ id }: { id: string }) => {
 | 
					 | 
				
			||||||
  const { t } = useTranslation();
 | 
					 | 
				
			||||||
  const toast = useToast();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return useQuery(
 | 
					  return useQuery(
 | 
				
			||||||
    ['get-board-devices', id],
 | 
					    ['get-board', id],
 | 
				
			||||||
    () => axiosAnalytics.get(`board/${id}/devices`).then(({ data }) => data.devices),
 | 
					    () => axiosAnalytics.get(`board/${id}`).then(({ data }: { data: AnalyticsBoardApiResponse }) => data),
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      enabled: id !== undefined && id !== null && id.length > 0,
 | 
					      enabled: id !== undefined && id !== null && id.length > 0,
 | 
				
			||||||
      onError: (e: AxiosError) => {
 | 
					      onError: (e: AxiosError) => {
 | 
				
			||||||
        if (!toast.isActive('board-fetching-error'))
 | 
					        if (e.response?.status !== 404 && !toast.isActive('board-fetching-error'))
 | 
				
			||||||
          toast({
 | 
					          toast({
 | 
				
			||||||
            id: 'board-fetching-error',
 | 
					            id: 'board-fetching-error',
 | 
				
			||||||
            title: t('common.error'),
 | 
					            title: t('common.error'),
 | 
				
			||||||
@@ -57,24 +271,35 @@ export const useGetAnalyticsBoardDevices = ({ id }: { id: string }) => {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const getPartialClients = async (venueId: string, offset: number) =>
 | 
					export const useGetAnalyticsBoardDevices = ({ id }: { id?: string }) => {
 | 
				
			||||||
  axiosAnalytics
 | 
					  const { t } = useTranslation();
 | 
				
			||||||
    .get(`wifiClientHistory?macsOnly=true&venue=${venueId}&limit=500&offset=${offset}`)
 | 
					  const toast = useToast();
 | 
				
			||||||
    .then(({ data }) => data.entries as string[]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getAllClients = async (venueId: string) => {
 | 
					  return useQuery(
 | 
				
			||||||
  const allClients: string[] = [];
 | 
					    ['get-board-devices', id],
 | 
				
			||||||
  let continueFirmware = true;
 | 
					    () =>
 | 
				
			||||||
  let offset = 0;
 | 
					      axiosAnalytics
 | 
				
			||||||
  while (continueFirmware) {
 | 
					        .get(`board/${id}/devices`)
 | 
				
			||||||
    // eslint-disable-next-line no-await-in-loop
 | 
					        .then(({ data }: { data: AnalyticsBoardDevicesApiResponse }) => data.devices),
 | 
				
			||||||
    const newClients = await getPartialClients(venueId, offset);
 | 
					    {
 | 
				
			||||||
    if (newClients === null || newClients.length === 0 || newClients.length < 500 || offset >= 50000)
 | 
					      enabled: id !== undefined && id !== null && id.length > 0,
 | 
				
			||||||
      continueFirmware = false;
 | 
					      onError: (e: AxiosError) => {
 | 
				
			||||||
    allClients.push(...newClients);
 | 
					        if (e.response?.status !== 404 && !toast.isActive('board-fetching-error'))
 | 
				
			||||||
    offset += 500;
 | 
					          toast({
 | 
				
			||||||
  }
 | 
					            id: 'board-fetching-error',
 | 
				
			||||||
  return allClients;
 | 
					            title: t('common.error'),
 | 
				
			||||||
 | 
					            description: t('crud.error_fetching_obj', {
 | 
				
			||||||
 | 
					              obj: t('analytics.board'),
 | 
				
			||||||
 | 
					              e: e?.response?.data?.ErrorDescription,
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            status: 'error',
 | 
				
			||||||
 | 
					            duration: 5000,
 | 
				
			||||||
 | 
					            isClosable: true,
 | 
				
			||||||
 | 
					            position: 'top-right',
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useGetAnalyticsClients = ({ venueId }: { venueId: string }) => {
 | 
					export const useGetAnalyticsClients = ({ venueId }: { venueId: string }) => {
 | 
				
			||||||
@@ -83,7 +308,10 @@ export const useGetAnalyticsClients = ({ venueId }: { venueId: string }) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return useQuery(
 | 
					  return useQuery(
 | 
				
			||||||
    ['get-venue-analytics-clients', venueId],
 | 
					    ['get-venue-analytics-clients', venueId],
 | 
				
			||||||
    () => axiosAnalytics.get(`wifiClientHistory?macsOnly=true&venue=${venueId}`).then(({ data }) => data.entries),
 | 
					    () =>
 | 
				
			||||||
 | 
					      axiosAnalytics
 | 
				
			||||||
 | 
					        .get(`wifiClientHistory?macsOnly=true&venue=${venueId}`)
 | 
				
			||||||
 | 
					        .then(({ data }: { data: { entries: string[] } }) => data.entries),
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      onError: (e: AxiosError) => {
 | 
					      onError: (e: AxiosError) => {
 | 
				
			||||||
        if (!toast.isActive('get-venue-analytics-clients-error'))
 | 
					        if (!toast.isActive('get-venue-analytics-clients-error'))
 | 
				
			||||||
@@ -107,12 +335,35 @@ export const useGetAnalyticsClients = ({ venueId }: { venueId: string }) => {
 | 
				
			|||||||
export const useGetClientLifecycleTableSpecs = () =>
 | 
					export const useGetClientLifecycleTableSpecs = () =>
 | 
				
			||||||
  useQuery(
 | 
					  useQuery(
 | 
				
			||||||
    ['get-lifecycles-table-spec'],
 | 
					    ['get-lifecycles-table-spec'],
 | 
				
			||||||
    () => axiosAnalytics.get(`wifiClientHistory/0?orderSpec=true`).then(({ data }) => data.list),
 | 
					    () =>
 | 
				
			||||||
 | 
					      axiosAnalytics
 | 
				
			||||||
 | 
					        .get(`wifiClientHistory/0?orderSpec=true`)
 | 
				
			||||||
 | 
					        .then(({ data }: { data: { list: string[] } }) => data.list),
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      staleTime: Infinity,
 | 
					      staleTime: Infinity,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getPartialClients = async (venueId: string, offset: number) =>
 | 
				
			||||||
 | 
					  axiosAnalytics
 | 
				
			||||||
 | 
					    .get(`wifiClientHistory?macsOnly=true&venue=${venueId}&limit=500&offset=${offset}`)
 | 
				
			||||||
 | 
					    .then(({ data }) => data.entries as string[]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getAllClients = async (venueId: string) => {
 | 
				
			||||||
 | 
					  const allClients: string[] = [];
 | 
				
			||||||
 | 
					  let continueFirmware = true;
 | 
				
			||||||
 | 
					  let offset = 0;
 | 
				
			||||||
 | 
					  while (continueFirmware) {
 | 
				
			||||||
 | 
					    // eslint-disable-next-line no-await-in-loop
 | 
				
			||||||
 | 
					    const newClients = await getPartialClients(venueId, offset);
 | 
				
			||||||
 | 
					    if (newClients === null || newClients.length === 0 || newClients.length < 500 || offset >= 50000)
 | 
				
			||||||
 | 
					      continueFirmware = false;
 | 
				
			||||||
 | 
					    allClients.push(...newClients);
 | 
				
			||||||
 | 
					    offset += 500;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return allClients;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const useGetClientLifecycleCount = ({
 | 
					export const useGetClientLifecycleCount = ({
 | 
				
			||||||
  venueId,
 | 
					  venueId,
 | 
				
			||||||
  mac,
 | 
					  mac,
 | 
				
			||||||
@@ -134,7 +385,7 @@ export const useGetClientLifecycleCount = ({
 | 
				
			|||||||
    () =>
 | 
					    () =>
 | 
				
			||||||
      axiosAnalytics
 | 
					      axiosAnalytics
 | 
				
			||||||
        .get(`wifiClientHistory/${mac}?venue=${venueId}&countOnly=true&fromDate=${fromDate}&endDate=${endDate}`)
 | 
					        .get(`wifiClientHistory/${mac}?venue=${venueId}&countOnly=true&fromDate=${fromDate}&endDate=${endDate}`)
 | 
				
			||||||
        .then(({ data }) => data.count),
 | 
					        .then(({ data }: { data: { count: number } }) => data.count),
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      enabled: mac !== undefined,
 | 
					      enabled: mac !== undefined,
 | 
				
			||||||
      onError: (e: AxiosError) => {
 | 
					      onError: (e: AxiosError) => {
 | 
				
			||||||
@@ -190,7 +441,7 @@ export const useGetClientLifecycle = ({
 | 
				
			|||||||
            (pageInfo?.limit ?? 10) * (pageInfo?.index ?? 1)
 | 
					            (pageInfo?.limit ?? 10) * (pageInfo?.index ?? 1)
 | 
				
			||||||
          }${sortString}&fromDate=${fromDate}&endDate=${endDate}`,
 | 
					          }${sortString}&fromDate=${fromDate}&endDate=${endDate}`,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .then(({ data }) => data.entries),
 | 
					        .then(({ data }: { data: { entries: AnalyticsClientLifecycleApiResponse[] } }) => data.entries),
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      keepPreviousData: true,
 | 
					      keepPreviousData: true,
 | 
				
			||||||
      enabled: count !== undefined && pageInfo !== undefined,
 | 
					      enabled: count !== undefined && pageInfo !== undefined,
 | 
				
			||||||
@@ -205,7 +456,7 @@ export const useGetAnalyticsBoardTimepoints = ({
 | 
				
			|||||||
  endTime,
 | 
					  endTime,
 | 
				
			||||||
  enabled = true,
 | 
					  enabled = true,
 | 
				
			||||||
}: {
 | 
					}: {
 | 
				
			||||||
  id: string;
 | 
					  id?: string;
 | 
				
			||||||
  startTime: Date;
 | 
					  startTime: Date;
 | 
				
			||||||
  endTime?: Date;
 | 
					  endTime?: Date;
 | 
				
			||||||
  enabled?: boolean;
 | 
					  enabled?: boolean;
 | 
				
			||||||
@@ -214,19 +465,21 @@ export const useGetAnalyticsBoardTimepoints = ({
 | 
				
			|||||||
  const toast = useToast();
 | 
					  const toast = useToast();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return useQuery(
 | 
					  return useQuery(
 | 
				
			||||||
    ['get-board-timepoints', id],
 | 
					    ['get-venue-timepoints', id, startTime.toString(), endTime?.toString()],
 | 
				
			||||||
    () =>
 | 
					    () =>
 | 
				
			||||||
      axiosAnalytics
 | 
					      axiosAnalytics
 | 
				
			||||||
        .get(
 | 
					        .get(
 | 
				
			||||||
          `board/${id}/timepoints?fromDate=${Math.floor(startTime.getTime() / 1000)}${
 | 
					          `board/${id}/timepoints?maxRecords=1000&fromDate=${Math.floor(startTime.getTime() / 1000)}${
 | 
				
			||||||
            endTime ? `&endDate=${Math.floor(endTime.getTime() / 1000)}` : ''
 | 
					            endTime ? `&endDate=${Math.floor(endTime.getTime() / 1000)}` : ''
 | 
				
			||||||
          }`,
 | 
					          }`,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .then(({ data }) => data.points),
 | 
					        .then(({ data }: { data: AnalyticsTimePointsApiResponse }) => data.points),
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      enabled: id !== null && enabled,
 | 
					      enabled: id !== undefined && id !== '' && enabled,
 | 
				
			||||||
 | 
					      keepPreviousData: true,
 | 
				
			||||||
 | 
					      staleTime: Infinity,
 | 
				
			||||||
      onError: (e: AxiosError) => {
 | 
					      onError: (e: AxiosError) => {
 | 
				
			||||||
        if (!toast.isActive('board-fetching-error'))
 | 
					        if (e.response?.status !== 404 && !toast.isActive('board-fetching-error'))
 | 
				
			||||||
          toast({
 | 
					          toast({
 | 
				
			||||||
            id: 'board-fetching-error',
 | 
					            id: 'board-fetching-error',
 | 
				
			||||||
            title: t('common.error'),
 | 
					            title: t('common.error'),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,17 @@
 | 
				
			|||||||
import React, { useEffect, useMemo, useState } from 'react';
 | 
					import React, { useEffect, useMemo, useState } from 'react';
 | 
				
			||||||
import { Box, Center, Flex, Heading, Spacer, Spinner, useDisclosure } from '@chakra-ui/react';
 | 
					import {
 | 
				
			||||||
 | 
					  Alert,
 | 
				
			||||||
 | 
					  AlertDescription,
 | 
				
			||||||
 | 
					  AlertIcon,
 | 
				
			||||||
 | 
					  AlertTitle,
 | 
				
			||||||
 | 
					  Box,
 | 
				
			||||||
 | 
					  Center,
 | 
				
			||||||
 | 
					  Flex,
 | 
				
			||||||
 | 
					  Heading,
 | 
				
			||||||
 | 
					  Spacer,
 | 
				
			||||||
 | 
					  Spinner,
 | 
				
			||||||
 | 
					  useDisclosure,
 | 
				
			||||||
 | 
					} from '@chakra-ui/react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import { useTranslation } from 'react-i18next';
 | 
					import { useTranslation } from 'react-i18next';
 | 
				
			||||||
import VenueAnalyticsHeader from './Header';
 | 
					import VenueAnalyticsHeader from './Header';
 | 
				
			||||||
@@ -16,7 +28,7 @@ const VenueDashboard = ({ boardId }) => {
 | 
				
			|||||||
  const { t } = useTranslation();
 | 
					  const { t } = useTranslation();
 | 
				
			||||||
  const { isOpen, onOpen, onClose } = useDisclosure(false);
 | 
					  const { isOpen, onOpen, onClose } = useDisclosure(false);
 | 
				
			||||||
  const [tableOptions, setTableOptions] = useState(null);
 | 
					  const [tableOptions, setTableOptions] = useState(null);
 | 
				
			||||||
  const { data: devices, isFetching, refetch } = useGetAnalyticsBoardDevices({ id: boardId });
 | 
					  const { data: devices, isFetching, refetch, error } = useGetAnalyticsBoardDevices({ id: boardId });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleRefreshClick = () => {
 | 
					  const handleRefreshClick = () => {
 | 
				
			||||||
    refetch();
 | 
					    refetch();
 | 
				
			||||||
@@ -112,6 +124,21 @@ const VenueDashboard = ({ boardId }) => {
 | 
				
			|||||||
    if (!isOpen) setTableOptions(null);
 | 
					    if (!isOpen) setTableOptions(null);
 | 
				
			||||||
  }, [isOpen]);
 | 
					  }, [isOpen]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (error)
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <Center mt={6}>
 | 
				
			||||||
 | 
					        <Alert status="error" w="unset" borderRadius="15px">
 | 
				
			||||||
 | 
					          <AlertIcon />
 | 
				
			||||||
 | 
					          <Box>
 | 
				
			||||||
 | 
					            <AlertTitle>{t('common.error')}</AlertTitle>
 | 
				
			||||||
 | 
					            <AlertDescription>
 | 
				
			||||||
 | 
					              {error.response?.status === 404 ? t('analytics.missing_board') : error.response?.data?.ErrorDescription}
 | 
				
			||||||
 | 
					            </AlertDescription>
 | 
				
			||||||
 | 
					          </Box>
 | 
				
			||||||
 | 
					        </Alert>
 | 
				
			||||||
 | 
					      </Center>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return !devices ? (
 | 
					  return !devices ? (
 | 
				
			||||||
    <Center mt={6}>
 | 
					    <Center mt={6}>
 | 
				
			||||||
      <Spinner size="xl" />
 | 
					      <Spinner size="xl" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,19 @@
 | 
				
			|||||||
import React, { useState } from 'react';
 | 
					import React, { useState } from 'react';
 | 
				
			||||||
import { Box, Center, Flex, Spacer, Spinner, useColorModeValue } from '@chakra-ui/react';
 | 
					import {
 | 
				
			||||||
 | 
					  Alert,
 | 
				
			||||||
 | 
					  AlertDescription,
 | 
				
			||||||
 | 
					  AlertIcon,
 | 
				
			||||||
 | 
					  AlertTitle,
 | 
				
			||||||
 | 
					  Box,
 | 
				
			||||||
 | 
					  Center,
 | 
				
			||||||
 | 
					  Flex,
 | 
				
			||||||
 | 
					  Spacer,
 | 
				
			||||||
 | 
					  Spinner,
 | 
				
			||||||
 | 
					  useColorModeValue,
 | 
				
			||||||
 | 
					} from '@chakra-ui/react';
 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import { FullScreen, useFullScreenHandle } from 'react-full-screen';
 | 
					import { FullScreen, useFullScreenHandle } from 'react-full-screen';
 | 
				
			||||||
 | 
					import { useTranslation } from 'react-i18next';
 | 
				
			||||||
import CirclePack from './CirclePack';
 | 
					import CirclePack from './CirclePack';
 | 
				
			||||||
import ExpandButton from './ExpandButton';
 | 
					import ExpandButton from './ExpandButton';
 | 
				
			||||||
import CirclePackTimePickers from './TimePickers';
 | 
					import CirclePackTimePickers from './TimePickers';
 | 
				
			||||||
@@ -17,11 +29,32 @@ const propTypes = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const VenueLiveView = ({ boardId, venue }) => {
 | 
					const VenueLiveView = ({ boardId, venue }) => {
 | 
				
			||||||
 | 
					  const { t } = useTranslation();
 | 
				
			||||||
  const handle = useFullScreenHandle();
 | 
					  const handle = useFullScreenHandle();
 | 
				
			||||||
  const color = useColorModeValue('gray.50', 'gray.800');
 | 
					  const color = useColorModeValue('gray.50', 'gray.800');
 | 
				
			||||||
  const [startTime, setStartTime] = useState(getHoursAgo(1));
 | 
					  const [startTime, setStartTime] = useState(getHoursAgo(1));
 | 
				
			||||||
  const [endTime, setEndTime] = useState(new Date());
 | 
					  const [endTime, setEndTime] = useState(new Date());
 | 
				
			||||||
  const { data: timepoints, isFetching, refetch } = useGetAnalyticsBoardTimepoints({ id: boardId, startTime, endTime });
 | 
					  const {
 | 
				
			||||||
 | 
					    data: timepoints,
 | 
				
			||||||
 | 
					    isFetching,
 | 
				
			||||||
 | 
					    refetch,
 | 
				
			||||||
 | 
					    error,
 | 
				
			||||||
 | 
					  } = useGetAnalyticsBoardTimepoints({ id: boardId, startTime, endTime });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (error)
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <Center mt={6}>
 | 
				
			||||||
 | 
					        <Alert status="error" w="unset" borderRadius="15px">
 | 
				
			||||||
 | 
					          <AlertIcon />
 | 
				
			||||||
 | 
					          <Box>
 | 
				
			||||||
 | 
					            <AlertTitle>{t('common.error')}</AlertTitle>
 | 
				
			||||||
 | 
					            <AlertDescription>
 | 
				
			||||||
 | 
					              {error.response?.status === 404 ? t('analytics.missing_board') : error.response?.data?.ErrorDescription}
 | 
				
			||||||
 | 
					            </AlertDescription>
 | 
				
			||||||
 | 
					          </Box>
 | 
				
			||||||
 | 
					        </Alert>
 | 
				
			||||||
 | 
					      </Center>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return !timepoints ? (
 | 
					  return !timepoints ? (
 | 
				
			||||||
    <Center mt={6}>
 | 
					    <Center mt={6}>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user