diff --git a/package-lock.json b/package-lock.json index 3dcc8a8..bad0351 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "react-router-dom": "^5.2.0", "react-widgets": "^5.1.1", "sass": "^1.35.1", - "ucentral-libs": "^0.8.34", + "ucentral-libs": "^0.8.35", "uuid": "^8.3.2" }, "devDependencies": { @@ -14292,9 +14292,9 @@ } }, "node_modules/ucentral-libs": { - "version": "0.8.34", - "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.8.34.tgz", - "integrity": "sha512-OBNFcYSaufqRht11SSlxkQIOhX9FoXHkoTFRq6qFVGhiG6s2OYpTHnIGDFm7fTbgJ2/zkTconjYnaUhocTIOMQ==", + "version": "0.8.35", + "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.8.35.tgz", + "integrity": "sha512-rL2l21k6T9vZvwDzXSVG2hJZQImvuX3cMH9uR515Ji2UkCfqiCYinxoSoCihyey3+Fy6lO4ztjA496bfdnSwFg==", "engines": { "node": ">=10" }, @@ -26605,9 +26605,9 @@ } }, "ucentral-libs": { - "version": "0.8.34", - "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.8.34.tgz", - "integrity": "sha512-OBNFcYSaufqRht11SSlxkQIOhX9FoXHkoTFRq6qFVGhiG6s2OYpTHnIGDFm7fTbgJ2/zkTconjYnaUhocTIOMQ==", + "version": "0.8.35", + "resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.8.35.tgz", + "integrity": "sha512-rL2l21k6T9vZvwDzXSVG2hJZQImvuX3cMH9uR515Ji2UkCfqiCYinxoSoCihyey3+Fy6lO4ztjA496bfdnSwFg==", "requires": {} }, "unbox-primitive": { diff --git a/package.json b/package.json index 68e19ce..569f2b7 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "react-router-dom": "^5.2.0", "react-widgets": "^5.1.1", "sass": "^1.35.1", - "ucentral-libs": "^0.8.34", + "ucentral-libs": "^0.8.35", "uuid": "^8.3.2" }, "main": "index.js", diff --git a/public/locales/de/translation.json b/public/locales/de/translation.json index 225a17e..cc133ed 100644 --- a/public/locales/de/translation.json +++ b/public/locales/de/translation.json @@ -55,11 +55,14 @@ "days": "tage", "delete": "Löschen", "details": "Einzelheiten", + "device_dashboard": "Geräte-Dashboard", "device_health": "Gerätezustand", "device_list": "Liste der Geräte", "device_page": "Aussicht", "device_status": "Gerätestatus", "devices": "Geräte", + "devices_using_latest": "Geräte mit der neuesten Firmware", + "devices_using_unknown": "Geräte mit unbekannter Firmware", "dismiss": "entlassen", "do_now": "Sofort", "download": "Herunterladen", @@ -68,11 +71,14 @@ "edit_user": "Bearbeiten", "email_address": "E-Mail-Addresse", "endpoint": "Endpunkt", + "endpoints": "Endpunkte", "error": "Fehler", "execute_now": "Möchten Sie diesen Befehl jetzt ausführen?", "executed": "Ausgeführt", "exit": "Ausgang", "firmware": "Firmware", + "firmware_dashboard": "Firmware-Dashboard", + "firmware_installed": "Firmware installiert", "forgot_password": "Haben Sie Ihr Passwort vergessen?", "forgot_password_title": "Passwort vergessen", "from": "Von", @@ -83,6 +89,7 @@ "id": "ID", "ip_address": "IP Adresse", "later_tonight": "Später am Abend", + "latest": "Neueste", "list": "Liste", "loading_ellipsis": "Wird geladen...", "loading_more_ellipsis": "Mehr laden ...", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 326e0a3..6965800 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -55,11 +55,14 @@ "days": "days", "delete": "Delete", "details": "Details", + "device_dashboard": "Device Dashboard", "device_health": "Device Health", "device_list": "List of Devices", "device_page": "View", "device_status": "Device Status", "devices": "Devices", + "devices_using_latest": "Devices Using Latest Firmware", + "devices_using_unknown": "Devices Using Unknown Firmware", "dismiss": "Dismiss", "do_now": "Do Now!", "download": "Download", @@ -68,11 +71,14 @@ "edit_user": "Edit", "email_address": "Email Address", "endpoint": "Endpoint", + "endpoints": "Endpoints", "error": "Error", "execute_now": "Would you like to execute this command now?", "executed": "Executed", "exit": "Exit", "firmware": "Firmware", + "firmware_dashboard": "Firmware Dashboard", + "firmware_installed": "Firmware Installed", "forgot_password": "Forgot your Password?", "forgot_password_title": "Forgot Password", "from": "From", @@ -83,6 +89,7 @@ "id": "Id", "ip_address": "Ip Address", "later_tonight": "Later tonight", + "latest": "Latest", "list": "List", "loading_ellipsis": "Loading...", "loading_more_ellipsis": "Loading more...", diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json index b812d46..60e1de0 100644 --- a/public/locales/es/translation.json +++ b/public/locales/es/translation.json @@ -55,11 +55,14 @@ "days": "días", "delete": "Borrar", "details": "Detalles", + "device_dashboard": "Panel de control del dispositivo", "device_health": "Salud del dispositivo", "device_list": "Listado de dispositivos", "device_page": "Ver", "device_status": "Estado del dispositivo", "devices": "Dispositivos", + "devices_using_latest": "Dispositivos que utilizan el firmware más reciente", + "devices_using_unknown": "Dispositivos que utilizan firmware desconocido", "dismiss": "Despedir", "do_now": "¡Hagan ahora!", "download": "Descargar", @@ -68,11 +71,14 @@ "edit_user": "Editar", "email_address": "Dirección de correo electrónico", "endpoint": "punto final", + "endpoints": "Puntos finales", "error": "Error", "execute_now": "¿Le gustaría ejecutar este comando ahora?", "executed": "ejecutado", "exit": "salida", "firmware": "Firmware", + "firmware_dashboard": "Panel de firmware", + "firmware_installed": "Firmware instalado", "forgot_password": "¿Olvidaste tu contraseña?", "forgot_password_title": "Se te olvidó tu contraseña", "from": "Desde", @@ -83,6 +89,7 @@ "id": "Carné de identidad", "ip_address": "Dirección IP", "later_tonight": "Más tarde esta noche", + "latest": "último", "list": "Lista", "loading_ellipsis": "Cargando...", "loading_more_ellipsis": "Cargando más ...", diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index 0055054..f851dfa 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -55,11 +55,14 @@ "days": "journées", "delete": "Effacer", "details": "Détails", + "device_dashboard": "Tableau de bord de l'appareil", "device_health": "Santé de l'appareil", "device_list": "Liste des appareils", "device_page": "Vue", "device_status": "Statut du périphérique", "devices": "Dispositifs", + "devices_using_latest": "Appareils utilisant le dernier micrologiciel", + "devices_using_unknown": "Périphériques utilisant un micrologiciel inconnu", "dismiss": "Rejeter", "do_now": "Faire maintenant!", "download": "Télécharger", @@ -68,11 +71,14 @@ "edit_user": "Modifier", "email_address": "Adresse électronique", "endpoint": "Point final", + "endpoints": "Points de terminaison", "error": "Erreur", "execute_now": "Souhaitez-vous exécuter cette commande maintenant ?", "executed": "réalisé", "exit": "Sortie", "firmware": "Micrologiciel", + "firmware_dashboard": "Tableau de bord du micrologiciel", + "firmware_installed": "Micrologiciel installé", "forgot_password": "Mot de passe oublié?", "forgot_password_title": "Mot de passe oublié", "from": "De", @@ -83,6 +89,7 @@ "id": "Id", "ip_address": "Adresse IP", "later_tonight": "Plus tard ce soir", + "latest": "Dernier", "list": "liste", "loading_ellipsis": "Chargement...", "loading_more_ellipsis": "Chargement plus ...", diff --git a/public/locales/pt/translation.json b/public/locales/pt/translation.json index 79d2e20..1862629 100644 --- a/public/locales/pt/translation.json +++ b/public/locales/pt/translation.json @@ -55,11 +55,14 @@ "days": "dias", "delete": "Excluir", "details": "Detalhes", + "device_dashboard": "Painel do dispositivo", "device_health": "Saúde do Dispositivo", "device_list": "Lista de Dispositivos", "device_page": "Visão", "device_status": "Status do dispositivo", "devices": "Devices", + "devices_using_latest": "Dispositivos que usam o firmware mais recente", + "devices_using_unknown": "Dispositivos que usam firmware desconhecido", "dismiss": "Dispensar", "do_now": "Faça agora!", "download": "Baixar", @@ -68,11 +71,14 @@ "edit_user": "Editar", "email_address": "Endereço de e-mail", "endpoint": "Ponto final", + "endpoints": "Pontos finais", "error": "Erro", "execute_now": "Você gostaria de executar este comando agora?", "executed": "Executado", "exit": "Saída", "firmware": "Firmware", + "firmware_dashboard": "Painel de Firmware", + "firmware_installed": "Firmware Instalado", "forgot_password": "Esqueceu sua senha?", "forgot_password_title": "Esqueceu a senha", "from": "De", @@ -83,6 +89,7 @@ "id": "identidade", "ip_address": "Endereço de IP", "later_tonight": "Logo à noite", + "latest": "Mais recentes", "list": "Lista", "loading_ellipsis": "Carregando...", "loading_more_ellipsis": "Carregando mais ...", diff --git a/src/layout/index.js b/src/layout/index.js index 52a3df3..fdb76cd 100644 --- a/src/layout/index.js +++ b/src/layout/index.js @@ -28,18 +28,29 @@ const TheLayout = () => { }, ], }, + { + _tag: 'CSidebarNavDropdown', + name: t('firmware.title'), + icon: 'cilSave', + _children: [ + { + _tag: 'CSidebarNavItem', + name: t('common.dashboard'), + to: '/firmwaredashboard', + }, + { + _tag: 'CSidebarNavItem', + name: t('common.list'), + to: '/firmware', + }, + ], + }, { _tag: 'CSidebarNavItem', name: t('user.users'), to: '/users', icon: 'cilPeople', }, - { - _tag: 'CSidebarNavItem', - name: t('firmware.title'), - to: '/firmware', - icon: 'cilSave', - }, { _tag: 'CSidebarNavItem', name: t('settings.title'), diff --git a/src/pages/DeviceDashboard/index.js b/src/pages/DeviceDashboard/index.js index e0597de..12c8a77 100644 --- a/src/pages/DeviceDashboard/index.js +++ b/src/pages/DeviceDashboard/index.js @@ -4,6 +4,289 @@ import { useTranslation } from 'react-i18next'; import { DeviceDashboard as Dashboard } from 'ucentral-libs'; import axiosInstance from 'utils/axiosInstance'; +const colors = [ + '#63b598', + '#ce7d78', + '#ea9e70', + '#a48a9e', + '#c6e1e8', + '#648177', + '#0d5ac1', + '#f205e6', + '#1c0365', + '#14a9ad', + '#4ca2f9', + '#a4e43f', + '#d298e2', + '#6119d0', + '#d2737d', + '#c0a43c', + '#f2510e', + '#651be6', + '#79806e', + '#61da5e', + '#cd2f00', + '#9348af', + '#01ac53', + '#c5a4fb', + '#996635', + '#b11573', + '#4bb473', + '#75d89e', + '#2f3f94', + '#2f7b99', + '#da967d', + '#34891f', + '#b0d87b', + '#ca4751', + '#7e50a8', + '#c4d647', + '#e0eeb8', + '#11dec1', + '#289812', + '#566ca0', + '#ffdbe1', + '#2f1179', + '#935b6d', + '#916988', + '#513d98', + '#aead3a', + '#9e6d71', + '#4b5bdc', + '#0cd36d', + '#250662', + '#cb5bea', + '#228916', + '#ac3e1b', + '#df514a', + '#539397', + '#880977', + '#f697c1', + '#ba96ce', + '#679c9d', + '#c6c42c', + '#5d2c52', + '#48b41b', + '#e1cf3b', + '#5be4f0', + '#57c4d8', + '#a4d17a', + '#225b8', + '#be608b', + '#96b00c', + '#088baf', + '#f158bf', + '#e145ba', + '#ee91e3', + '#05d371', + '#5426e0', + '#4834d0', + '#802234', + '#6749e8', + '#0971f0', + '#8fb413', + '#b2b4f0', + '#c3c89d', + '#c9a941', + '#41d158', + '#fb21a3', + '#51aed9', + '#5bb32d', + '#807fb', + '#21538e', + '#89d534', + '#d36647', + '#7fb411', + '#0023b8', + '#3b8c2a', + '#986b53', + '#f50422', + '#983f7a', + '#ea24a3', + '#79352c', + '#521250', + '#c79ed2', + '#d6dd92', + '#e33e52', + '#b2be57', + '#fa06ec', + '#1bb699', + '#6b2e5f', + '#64820f', + '#1c271', + '#21538e', + '#89d534', + '#d36647', + '#7fb411', + '#0023b8', + '#3b8c2a', + '#986b53', + '#f50422', + '#983f7a', + '#ea24a3', + '#79352c', + '#521250', + '#c79ed2', + '#d6dd92', + '#e33e52', + '#b2be57', + '#fa06ec', + '#1bb699', + '#6b2e5f', + '#64820f', + '#1c271', + '#9cb64a', + '#996c48', + '#9ab9b7', + '#06e052', + '#e3a481', + '#0eb621', + '#fc458e', + '#b2db15', + '#aa226d', + '#792ed8', + '#73872a', + '#520d3a', + '#cefcb8', + '#a5b3d9', + '#7d1d85', + '#c4fd57', + '#f1ae16', + '#8fe22a', + '#ef6e3c', + '#243eeb', + '#1dc18', + '#dd93fd', + '#3f8473', + '#e7dbce', + '#421f79', + '#7a3d93', + '#635f6d', + '#93f2d7', + '#9b5c2a', + '#15b9ee', + '#0f5997', + '#409188', + '#911e20', + '#1350ce', + '#10e5b1', + '#fff4d7', + '#cb2582', + '#ce00be', + '#32d5d6', + '#17232', + '#608572', + '#c79bc2', + '#00f87c', + '#77772a', + '#6995ba', + '#fc6b57', + '#f07815', + '#8fd883', + '#060e27', + '#96e591', + '#21d52e', + '#d00043', + '#b47162', + '#1ec227', + '#4f0f6f', + '#1d1d58', + '#947002', + '#bde052', + '#e08c56', + '#28fcfd', + '#bb09b', + '#36486a', + '#d02e29', + '#1ae6db', + '#3e464c', + '#a84a8f', + '#911e7e', + '#3f16d9', + '#0f525f', + '#ac7c0a', + '#b4c086', + '#c9d730', + '#30cc49', + '#3d6751', + '#fb4c03', + '#640fc1', + '#62c03e', + '#d3493a', + '#88aa0b', + '#406df9', + '#615af0', + '#4be47', + '#2a3434', + '#4a543f', + '#79bca0', + '#a8b8d4', + '#00efd4', + '#7ad236', + '#7260d8', + '#1deaa7', + '#06f43a', + '#823c59', + '#e3d94c', + '#dc1c06', + '#f53b2a', + '#b46238', + '#2dfff6', + '#a82b89', + '#1a8011', + '#436a9f', + '#1a806a', + '#4cf09d', + '#c188a2', + '#67eb4b', + '#b308d3', + '#fc7e41', + '#af3101', + '#ff065', + '#71b1f4', + '#a2f8a5', + '#e23dd0', + '#d3486d', + '#00f7f9', + '#474893', + '#3cec35', + '#1c65cb', + '#5d1d0c', + '#2d7d2a', + '#ff3420', + '#5cdd87', + '#a259a4', + '#e4ac44', + '#1bede6', + '#8798a4', + '#d7790f', + '#b2c24f', + '#de73c2', + '#d70a9c', + '#25b67', + '#88e9b8', + '#c2b0e2', + '#86e98f', + '#ae90e2', + '#1a806b', + '#436a9e', + '#0ec0ff', + '#f812b3', + '#b17fc9', + '#8d6c2f', + '#d3277a', + '#2ca1ae', + '#9685eb', + '#8a96c6', + '#dba2e6', + '#76fc1b', + '#608fa4', + '#20f6ba', + '#07d7f6', + '#dce77a', + '#77ecca', +]; + const DeviceDashboard = () => { const { t } = useTranslation(); const { currentToken, endpoints } = useAuth(); @@ -61,6 +344,9 @@ const DeviceDashboard = () => { case 'not connected': color = '#39f'; break; + case 'disconnected': + color = '#e55353'; + break; default: break; } @@ -140,40 +426,28 @@ const DeviceDashboard = () => { vendorsLabels.push(point.tag === '' ? 'Unknown' : point.tag); vendorsColors.push('#eb7474'); } + const otherVendors = vendorsTypeDs.slice(5).reduce((acc, vendor) => acc + vendor, 0); parsedData.vendors = { datasets: [ { label: 'Devices', - data: vendorsTypeDs.slice(0, 5), + data: vendorsTypeDs.slice(0, 5).concat([otherVendors]), backgroundColor: vendorsColors, }, ], - labels: vendorsLabels.slice(0, 5), + labels: vendorsLabels.slice(0, 5).concat(['Others']), }; // Device Type pie chart const deviceTypeDs = []; const deviceTypeColors = []; const deviceTypeLabels = []; - for (const point of parsedData.deviceType) { + for (let i = 0; i < parsedData.deviceType.length; i += 1) { + const point = parsedData.deviceType[i]; + deviceTypeDs.push(point.value); deviceTypeLabels.push(point.tag); - let color = ''; - switch (point.tag) { - case '100%': - color = '#41B883'; - break; - case '>60%': - color = '#f9b115'; - break; - case '<60%%>': - color = '#e55353'; - break; - default: - color = '#39f'; - break; - } - deviceTypeColors.push(color); + deviceTypeColors.push(colors[i]); } parsedData.deviceType = { datasets: [ @@ -277,7 +551,8 @@ const DeviceDashboard = () => { parseData(response.data); setLoading(false); }) - .catch(() => { + .catch((e) => { + console.log(e); setLoading(false); }); }; diff --git a/src/pages/FirmwareDashboard/index.js b/src/pages/FirmwareDashboard/index.js new file mode 100644 index 0000000..49ab551 --- /dev/null +++ b/src/pages/FirmwareDashboard/index.js @@ -0,0 +1,530 @@ +import React, { useState, useEffect } from 'react'; +import { useAuth } from 'contexts/AuthProvider'; +import { useTranslation } from 'react-i18next'; +import { FirmwareDashboard as Dashboard } from 'ucentral-libs'; +import axiosInstance from 'utils/axiosInstance'; + +const colors = [ + '#63b598', + '#ce7d78', + '#ea9e70', + '#a48a9e', + '#c6e1e8', + '#648177', + '#0d5ac1', + '#f205e6', + '#1c0365', + '#14a9ad', + '#4ca2f9', + '#a4e43f', + '#d298e2', + '#6119d0', + '#d2737d', + '#c0a43c', + '#f2510e', + '#651be6', + '#79806e', + '#61da5e', + '#cd2f00', + '#9348af', + '#01ac53', + '#c5a4fb', + '#996635', + '#b11573', + '#4bb473', + '#75d89e', + '#2f3f94', + '#2f7b99', + '#da967d', + '#34891f', + '#b0d87b', + '#ca4751', + '#7e50a8', + '#c4d647', + '#e0eeb8', + '#11dec1', + '#289812', + '#566ca0', + '#ffdbe1', + '#2f1179', + '#935b6d', + '#916988', + '#513d98', + '#aead3a', + '#9e6d71', + '#4b5bdc', + '#0cd36d', + '#250662', + '#cb5bea', + '#228916', + '#ac3e1b', + '#df514a', + '#539397', + '#880977', + '#f697c1', + '#ba96ce', + '#679c9d', + '#c6c42c', + '#5d2c52', + '#48b41b', + '#e1cf3b', + '#5be4f0', + '#57c4d8', + '#a4d17a', + '#225b8', + '#be608b', + '#96b00c', + '#088baf', + '#f158bf', + '#e145ba', + '#ee91e3', + '#05d371', + '#5426e0', + '#4834d0', + '#802234', + '#6749e8', + '#0971f0', + '#8fb413', + '#b2b4f0', + '#c3c89d', + '#c9a941', + '#41d158', + '#fb21a3', + '#51aed9', + '#5bb32d', + '#807fb', + '#21538e', + '#89d534', + '#d36647', + '#7fb411', + '#0023b8', + '#3b8c2a', + '#986b53', + '#f50422', + '#983f7a', + '#ea24a3', + '#79352c', + '#521250', + '#c79ed2', + '#d6dd92', + '#e33e52', + '#b2be57', + '#fa06ec', + '#1bb699', + '#6b2e5f', + '#64820f', + '#1c271', + '#21538e', + '#89d534', + '#d36647', + '#7fb411', + '#0023b8', + '#3b8c2a', + '#986b53', + '#f50422', + '#983f7a', + '#ea24a3', + '#79352c', + '#521250', + '#c79ed2', + '#d6dd92', + '#e33e52', + '#b2be57', + '#fa06ec', + '#1bb699', + '#6b2e5f', + '#64820f', + '#1c271', + '#9cb64a', + '#996c48', + '#9ab9b7', + '#06e052', + '#e3a481', + '#0eb621', + '#fc458e', + '#b2db15', + '#aa226d', + '#792ed8', + '#73872a', + '#520d3a', + '#cefcb8', + '#a5b3d9', + '#7d1d85', + '#c4fd57', + '#f1ae16', + '#8fe22a', + '#ef6e3c', + '#243eeb', + '#1dc18', + '#dd93fd', + '#3f8473', + '#e7dbce', + '#421f79', + '#7a3d93', + '#635f6d', + '#93f2d7', + '#9b5c2a', + '#15b9ee', + '#0f5997', + '#409188', + '#911e20', + '#1350ce', + '#10e5b1', + '#fff4d7', + '#cb2582', + '#ce00be', + '#32d5d6', + '#17232', + '#608572', + '#c79bc2', + '#00f87c', + '#77772a', + '#6995ba', + '#fc6b57', + '#f07815', + '#8fd883', + '#060e27', + '#96e591', + '#21d52e', + '#d00043', + '#b47162', + '#1ec227', + '#4f0f6f', + '#1d1d58', + '#947002', + '#bde052', + '#e08c56', + '#28fcfd', + '#bb09b', + '#36486a', + '#d02e29', + '#1ae6db', + '#3e464c', + '#a84a8f', + '#911e7e', + '#3f16d9', + '#0f525f', + '#ac7c0a', + '#b4c086', + '#c9d730', + '#30cc49', + '#3d6751', + '#fb4c03', + '#640fc1', + '#62c03e', + '#d3493a', + '#88aa0b', + '#406df9', + '#615af0', + '#4be47', + '#2a3434', + '#4a543f', + '#79bca0', + '#a8b8d4', + '#00efd4', + '#7ad236', + '#7260d8', + '#1deaa7', + '#06f43a', + '#823c59', + '#e3d94c', + '#dc1c06', + '#f53b2a', + '#b46238', + '#2dfff6', + '#a82b89', + '#1a8011', + '#436a9f', + '#1a806a', + '#4cf09d', + '#c188a2', + '#67eb4b', + '#b308d3', + '#fc7e41', + '#af3101', + '#ff065', + '#71b1f4', + '#a2f8a5', + '#e23dd0', + '#d3486d', + '#00f7f9', + '#474893', + '#3cec35', + '#1c65cb', + '#5d1d0c', + '#2d7d2a', + '#ff3420', + '#5cdd87', + '#a259a4', + '#e4ac44', + '#1bede6', + '#8798a4', + '#d7790f', + '#b2c24f', + '#de73c2', + '#d70a9c', + '#25b67', + '#88e9b8', + '#c2b0e2', + '#86e98f', + '#ae90e2', + '#1a806b', + '#436a9e', + '#0ec0ff', + '#f812b3', + '#b17fc9', + '#8d6c2f', + '#d3277a', + '#2ca1ae', + '#9685eb', + '#8a96c6', + '#dba2e6', + '#76fc1b', + '#608fa4', + '#20f6ba', + '#07d7f6', + '#dce77a', + '#77ecca', +]; + +const FirmwareDashboard = () => { + const { t } = useTranslation(); + const { currentToken, endpoints } = useAuth(); + const [loading, setLoading] = useState(false); + const [data, setData] = useState({ + status: { + datasets: [], + labels: [], + }, + deviceType: { + datasets: [], + labels: [], + }, + firmwareDistribution: { + datasets: [], + labels: [], + }, + latest: { + datasets: [], + labels: [], + }, + unknownFirmwares: { + datasets: [], + labels: [], + }, + ouis: { + datasets: [], + labels: [], + }, + endpoints: { + datasets: [], + labels: [], + }, + }); + + const parseData = (newData) => { + const parsedData = newData; + + // Status pie chart + const statusDs = []; + const statusColors = []; + const statusLabels = []; + for (const point of parsedData.status) { + statusDs.push(point.value); + statusLabels.push(point.tag); + let color = ''; + switch (point.tag) { + case 'connected': + color = '#41B883'; + break; + case 'not connected': + color = '#39f'; + break; + case 'disconnected': + color = '#e55353'; + break; + default: + break; + } + statusColors.push(color); + } + parsedData.status = { + datasets: [ + { + data: statusDs, + backgroundColor: statusColors, + }, + ], + labels: statusLabels, + }; + + // Device Type pie chart + const deviceTypeDs = []; + const deviceTypeColors = []; + const deviceTypeLabels = []; + for (let i = 0; i < parsedData.deviceTypes.length; i += 1) { + const point = parsedData.deviceTypes[i]; + + deviceTypeDs.push(point.value); + deviceTypeLabels.push(point.tag); + deviceTypeColors.push(colors[i]); + } + parsedData.deviceType = { + datasets: [ + { + data: deviceTypeDs, + backgroundColor: deviceTypeColors, + }, + ], + labels: deviceTypeLabels, + }; + + // Latest/unknown distribution + const unknownFirmware = parsedData.unknownFirmwares.reduce( + (acc, firmware) => acc + firmware.value, + 0, + ); + const usingLatestFirmware = parsedData.usingLatest.reduce( + (acc, firmware) => acc + firmware.value, + 0, + ); + parsedData.firmwareDistribution = { + datasets: [ + { + label: t('common.devices'), + data: [unknownFirmware, usingLatestFirmware], + backgroundColor: ['#e55353', '#41B883'], + }, + ], + labels: [t('common.unknown'), t('common.latest')], + }; + + // Latest firmware distribution + const latestDs = []; + const latestColors = []; + const latestLabels = []; + const usingLatest = parsedData.usingLatest.sort((a, b) => (a.value < b.value ? 1 : -1)); + for (const point of usingLatest) { + latestDs.push(point.value); + latestLabels.push(point.tag === '' ? 'Unknown' : point.tag); + latestColors.push('#39f'); + } + parsedData.latest = { + datasets: [ + { + label: t('common.firmware'), + data: latestDs.slice(0, 5), + backgroundColor: latestColors, + }, + ], + labels: latestLabels.slice(0, 5), + }; + + // Unknown firmware distribution + const unknownDs = []; + const unknownColors = []; + const unknownLabels = []; + const unknownFirmwares = parsedData.unknownFirmwares.sort((a, b) => + a.value < b.value ? 1 : -1, + ); + for (const point of unknownFirmwares) { + unknownDs.push(point.value); + unknownLabels.push(point.tag === '' ? 'Unknown' : point.tag); + unknownColors.push('#39f'); + } + parsedData.unknownFirmwares = { + datasets: [ + { + label: t('common.firmware'), + data: unknownDs.slice(0, 5), + backgroundColor: unknownColors, + }, + ], + labels: unknownLabels.slice(0, 5), + }; + + // OUIs bar graph + const ouisDs = []; + const ouisColors = []; + const ouisLabels = []; + for (const point of parsedData.ouis) { + ouisDs.push(point.value); + ouisLabels.push(point.tag === '' ? 'Unknown' : point.tag); + ouisColors.push('#39f'); + } + parsedData.ouis = { + datasets: [ + { + label: 'OUIs', + data: ouisDs.slice(0, 5), + backgroundColor: ouisColors, + }, + ], + labels: ouisLabels.slice(0, 5), + }; + + // Endpoints pie chart + const endpointsDs = []; + const endpointsColors = []; + const endpointsLabels = []; + for (const point of parsedData.endPoints) { + endpointsDs.push(point.value); + endpointsLabels.push(point.tag); + let color = ''; + switch (point.tag) { + case 'connected': + color = '#41B883'; + break; + case 'not connected': + color = '#39f'; + break; + case 'disconnected': + color = '#e55353'; + break; + default: + break; + } + statusColors.push(color); + } + parsedData.endpoints = { + datasets: [ + { + data: endpointsDs, + backgroundColor: endpointsColors, + }, + ], + labels: endpointsLabels, + }; + + setData(parsedData); + }; + + const getDashboard = () => { + setLoading(true); + + const headers = { + Accept: 'application/json', + Authorization: `Bearer ${currentToken}`, + }; + axiosInstance + .get(`${endpoints.ucentralfms}/api/v1/deviceReport`, { + headers, + }) + .then((response) => { + parseData(response.data); + setLoading(false); + }) + .catch((e) => { + console.log(e); + setLoading(false); + }); + }; + + useEffect(() => { + getDashboard(); + }, []); + + return ; +}; + +export default FirmwareDashboard; diff --git a/src/routes.js b/src/routes.js index 3b02b11..4205a83 100644 --- a/src/routes.js +++ b/src/routes.js @@ -8,9 +8,15 @@ const ProfilePage = React.lazy(() => import('pages/ProfilePage')); const WifiAnalysisPage = React.lazy(() => import('pages/WifiAnalysisPage')); const SettingsPage = React.lazy(() => import('pages/SettingsPage')); const FirmwareListPage = React.lazy(() => import('pages/FirmwareListPage')); +const FirmwareDashboard = React.lazy(() => import('pages/FirmwareDashboard')); export default [ - { path: '/devicedashboard', exact: true, name: 'common.devices', component: DeviceDashboard }, + { + path: '/devicedashboard', + exact: true, + name: 'common.device_dashboard', + component: DeviceDashboard, + }, { path: '/devices', exact: true, name: 'common.devices', component: DeviceListPage }, { path: '/devices/:deviceId/wifianalysis', @@ -19,6 +25,12 @@ export default [ }, { path: '/devices/:deviceId', name: 'common.device_page', component: DevicePage }, { path: '/firmware', name: 'firmware.title', component: FirmwareListPage }, + { + path: '/firmwaredashboard', + exact: true, + name: 'common.firmware_dashboard', + component: FirmwareDashboard, + }, { path: '/users', exact: true, name: 'user.users', component: UserListPage }, { path: '/myprofile', exact: true, name: 'user.my_profile', component: ProfilePage }, { path: '/settings', exact: true, name: 'settings.title', component: SettingsPage },