mirror of
				https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
				synced 2025-10-31 10:17:45 +00:00 
			
		
		
		
	Version 2.5.25: added refresh to logs/health/wifi analysis, added vendors to wifi analysis, changed configure feedback to use toast
This commit is contained in:
		
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|   "name": "ucentral-client", |   "name": "ucentral-client", | ||||||
|   "version": "2.5.24", |   "version": "2.5.25", | ||||||
|   "lockfileVersion": 2, |   "lockfileVersion": 2, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "packages": { |   "packages": { | ||||||
|     "": { |     "": { | ||||||
|       "name": "ucentral-client", |       "name": "ucentral-client", | ||||||
|       "version": "2.5.24", |       "version": "2.5.25", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@coreui/coreui": "^3.4.0", |         "@coreui/coreui": "^3.4.0", | ||||||
|         "@coreui/icons": "^2.0.1", |         "@coreui/icons": "^2.0.1", | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "ucentral-client", |   "name": "ucentral-client", | ||||||
|   "version": "2.5.24", |   "version": "2.5.25", | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@coreui/coreui": "^3.4.0", |     "@coreui/coreui": "^3.4.0", | ||||||
|     "@coreui/icons": "^2.0.1", |     "@coreui/icons": "^2.0.1", | ||||||
|   | |||||||
| @@ -804,6 +804,7 @@ | |||||||
| 		"mode": "Modus", | 		"mode": "Modus", | ||||||
| 		"network_diagram": "Netzwerkdiagramm", | 		"network_diagram": "Netzwerkdiagramm", | ||||||
| 		"radios": "Radios", | 		"radios": "Radios", | ||||||
| 		"title": "WLAN-Analyse" | 		"title": "WLAN-Analyse", | ||||||
|  | 		"vendor": "Verkäufer" | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -804,6 +804,7 @@ | |||||||
| 		"mode": "Mode", | 		"mode": "Mode", | ||||||
| 		"network_diagram": "Network Diagram", | 		"network_diagram": "Network Diagram", | ||||||
| 		"radios": "Radios", | 		"radios": "Radios", | ||||||
| 		"title": "Wi-Fi Analysis" | 		"title": "Wi-Fi Analysis", | ||||||
|  | 		"vendor": "Vendor" | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -804,6 +804,7 @@ | |||||||
| 		"mode": "Modo", | 		"mode": "Modo", | ||||||
| 		"network_diagram": "Diagrama de Red", | 		"network_diagram": "Diagrama de Red", | ||||||
| 		"radios": "Radios", | 		"radios": "Radios", | ||||||
| 		"title": "Análisis de Wi-Fi" | 		"title": "Análisis de Wi-Fi", | ||||||
|  | 		"vendor": "Vendedor" | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -804,6 +804,7 @@ | |||||||
| 		"mode": "Mode", | 		"mode": "Mode", | ||||||
| 		"network_diagram": "Diagramme de réseau", | 		"network_diagram": "Diagramme de réseau", | ||||||
| 		"radios": "Radios", | 		"radios": "Radios", | ||||||
| 		"title": "Analyse Wi-Fi" | 		"title": "Analyse Wi-Fi", | ||||||
|  | 		"vendor": "vendeur" | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -804,6 +804,7 @@ | |||||||
| 		"mode": "Modo", | 		"mode": "Modo", | ||||||
| 		"network_diagram": "Diagrama de rede", | 		"network_diagram": "Diagrama de rede", | ||||||
| 		"radios": "Rádios", | 		"radios": "Rádios", | ||||||
| 		"title": "Análise de Wi-Fi" | 		"title": "Análise de Wi-Fi", | ||||||
|  | 		"vendor": "fornecedor" | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ import React, { useState, useEffect } from 'react'; | |||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
| import PropTypes from 'prop-types'; | import PropTypes from 'prop-types'; | ||||||
| import 'react-widgets/styles.css'; | import 'react-widgets/styles.css'; | ||||||
| import { useAuth, useDevice } from 'ucentral-libs'; | import { useAuth, useDevice, useToast } from 'ucentral-libs'; | ||||||
| import { checkIfJson } from 'utils/helper'; | import { checkIfJson } from 'utils/helper'; | ||||||
| import axiosInstance from 'utils/axiosInstance'; | import axiosInstance from 'utils/axiosInstance'; | ||||||
| import eventBus from 'utils/eventBus'; | import eventBus from 'utils/eventBus'; | ||||||
| @@ -29,6 +29,7 @@ import SuccessfulActionModalBody from 'components/SuccessfulActionModalBody'; | |||||||
| const ConfigureModal = ({ show, toggleModal }) => { | const ConfigureModal = ({ show, toggleModal }) => { | ||||||
|   const { t } = useTranslation(); |   const { t } = useTranslation(); | ||||||
|   const { currentToken, endpoints } = useAuth(); |   const { currentToken, endpoints } = useAuth(); | ||||||
|  |   const { addToast } = useToast(); | ||||||
|   const { deviceSerialNumber } = useDevice(); |   const { deviceSerialNumber } = useDevice(); | ||||||
|   const [hadSuccess, setHadSuccess] = useState(false); |   const [hadSuccess, setHadSuccess] = useState(false); | ||||||
|   const [hadFailure, setHadFailure] = useState(false); |   const [hadFailure, setHadFailure] = useState(false); | ||||||
| @@ -91,7 +92,13 @@ const ConfigureModal = ({ show, toggleModal }) => { | |||||||
|         { headers }, |         { headers }, | ||||||
|       ) |       ) | ||||||
|       .then(() => { |       .then(() => { | ||||||
|         setHadSuccess(true); |         addToast({ | ||||||
|  |           title: t('common.success'), | ||||||
|  |           body: t('commands.command_success'), | ||||||
|  |           color: 'success', | ||||||
|  |           autohide: true, | ||||||
|  |         }); | ||||||
|  |         toggleModal(); | ||||||
|       }) |       }) | ||||||
|       .catch(() => { |       .catch(() => { | ||||||
|         setResponseBody('Error while submitting command!'); |         setResponseBody('Error while submitting command!'); | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ import { | |||||||
|   CPopover, |   CPopover, | ||||||
| } from '@coreui/react'; | } from '@coreui/react'; | ||||||
| import CIcon from '@coreui/icons-react'; | import CIcon from '@coreui/icons-react'; | ||||||
| import { cilTrash } from '@coreui/icons'; | import { cilSync, cilTrash } from '@coreui/icons'; | ||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
| import DatePicker from 'react-widgets/DatePicker'; | import DatePicker from 'react-widgets/DatePicker'; | ||||||
| import { dateToUnix } from 'utils/helper'; | import { dateToUnix } from 'utils/helper'; | ||||||
| @@ -231,6 +231,11 @@ const DeviceHealth = () => { | |||||||
|             <CIcon name="cil-trash" content={cilTrash} className="text-white" size="2xl" /> |             <CIcon name="cil-trash" content={cilTrash} className="text-white" size="2xl" /> | ||||||
|           </CButton> |           </CButton> | ||||||
|         </CPopover> |         </CPopover> | ||||||
|  |         <CPopover content={t('common.refresh')}> | ||||||
|  |           <CButton onClick={getDeviceHealth} size="sm"> | ||||||
|  |             <CIcon name="cil-sync" content={cilSync} className="text-white" size="2xl" /> | ||||||
|  |           </CButton> | ||||||
|  |         </CPopover> | ||||||
|       </div> |       </div> | ||||||
|     </CWidgetDropdown> |     </CWidgetDropdown> | ||||||
|   ); |   ); | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ import { | |||||||
|   CPopover, |   CPopover, | ||||||
| } from '@coreui/react'; | } from '@coreui/react'; | ||||||
| import CIcon from '@coreui/icons-react'; | import CIcon from '@coreui/icons-react'; | ||||||
| import { cilTrash } from '@coreui/icons'; | import { cilSync, cilTrash } from '@coreui/icons'; | ||||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||||
| import DatePicker from 'react-widgets/DatePicker'; | import DatePicker from 'react-widgets/DatePicker'; | ||||||
| import { dateToUnix } from 'utils/helper'; | import { dateToUnix } from 'utils/helper'; | ||||||
| @@ -250,6 +250,11 @@ const DeviceLogs = () => { | |||||||
|               <CIcon name="cil-trash" content={cilTrash} className="text-white" size="2xl" /> |               <CIcon name="cil-trash" content={cilTrash} className="text-white" size="2xl" /> | ||||||
|             </CButton> |             </CButton> | ||||||
|           </CPopover> |           </CPopover> | ||||||
|  |           <CPopover content={t('common.refresh')}> | ||||||
|  |             <CButton onClick={getLogs} size="sm"> | ||||||
|  |               <CIcon name="cil-sync" content={cilSync} className="text-white" size="2xl" /> | ||||||
|  |             </CButton> | ||||||
|  |           </CPopover> | ||||||
|         </div> |         </div> | ||||||
|       </CWidgetDropdown> |       </CWidgetDropdown> | ||||||
|       <DeleteLogModal |       <DeleteLogModal | ||||||
|   | |||||||
| @@ -22,10 +22,11 @@ const WifiAnalysisTable = ({ t, data, loading }) => { | |||||||
|     setShow(!show); |     setShow(!show); | ||||||
|   }; |   }; | ||||||
|   const columns = [ |   const columns = [ | ||||||
|     { key: 'radio', label: '#', _style: { width: '5%' } }, |     { key: 'radio', label: '#', _style: { width: '1%' } }, | ||||||
|     { key: 'bssid', label: 'BSSID', _style: { width: '14%' } }, |     { key: 'bssid', label: 'BSSID', _style: { width: '1%' } }, | ||||||
|     { key: 'mode', label: t('wifi_analysis.mode'), _style: { width: '9%' }, sorter: false }, |     { key: 'vendor', label: t('wifi_analysis.vendor'), _style: { width: '15%' }, sorter: false }, | ||||||
|     { key: 'ssid', label: 'SSID', _style: { width: '17%' } }, |     { key: 'mode', label: t('wifi_analysis.mode'), _style: { width: '1%' }, sorter: false }, | ||||||
|  |     { key: 'ssid', label: 'SSID', _style: { width: '15%' } }, | ||||||
|     { key: 'rssi', label: 'RSSI', _style: { width: '5%' }, sorter: false }, |     { key: 'rssi', label: 'RSSI', _style: { width: '5%' }, sorter: false }, | ||||||
|     { key: 'rxRate', label: 'Rx Rate', _style: { width: '7%' }, sorter: false }, |     { key: 'rxRate', label: 'Rx Rate', _style: { width: '7%' }, sorter: false }, | ||||||
|     { key: 'rxBytes', label: 'Rx', _style: { width: '7%' }, sorter: false }, |     { key: 'rxBytes', label: 'Rx', _style: { width: '7%' }, sorter: false }, | ||||||
| @@ -70,6 +71,7 @@ const WifiAnalysisTable = ({ t, data, loading }) => { | |||||||
|         sorter |         sorter | ||||||
|         sorterValue={{ column: 'radio', asc: true }} |         sorterValue={{ column: 'radio', asc: true }} | ||||||
|         scopedSlots={{ |         scopedSlots={{ | ||||||
|  |           bssid: (item) => <td className="text-center text-monospace">{item.bssid}</td>, | ||||||
|           radio: (item) => <td className="text-center">{item.radio.radio}</td>, |           radio: (item) => <td className="text-center">{item.radio.radio}</td>, | ||||||
|           rxMcs: (item) => centerIfEmpty(item.rxMcs), |           rxMcs: (item) => centerIfEmpty(item.rxMcs), | ||||||
|           rxNss: (item) => centerIfEmpty(item.rxNss), |           rxNss: (item) => centerIfEmpty(item.rxNss), | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ import { | |||||||
|   CPopover, |   CPopover, | ||||||
| } from '@coreui/react'; | } from '@coreui/react'; | ||||||
| import CIcon from '@coreui/icons-react'; | import CIcon from '@coreui/icons-react'; | ||||||
| import { cilX } from '@coreui/icons'; | import { cilSync, cilX } from '@coreui/icons'; | ||||||
| import RadioAnalysisTable from './RadioAnalysis'; | import RadioAnalysisTable from './RadioAnalysis'; | ||||||
| import WifiAnalysisTable from './WifiAnalysis'; | import WifiAnalysisTable from './WifiAnalysis'; | ||||||
|  |  | ||||||
| @@ -67,9 +67,33 @@ const WifiAnalysis = () => { | |||||||
|     return ips; |     return ips; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   const parseAssociationStats = (json) => { |   const getVendors = async (bssids) => { | ||||||
|  |     setLoading(true); | ||||||
|  |     setRange(19); | ||||||
|  |  | ||||||
|  |     const options = { | ||||||
|  |       headers: { | ||||||
|  |         Accept: 'application/json', | ||||||
|  |         Authorization: `Bearer ${currentToken}`, | ||||||
|  |       }, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     return axiosInstance | ||||||
|  |       .get(`${endpoints.owgw}/api/v1/ouis?macList=${bssids.join(',')}`, options) | ||||||
|  |       .then((response) => { | ||||||
|  |         const newObj = bssids; | ||||||
|  |         for (const tag of response.data.tagList) { | ||||||
|  |           newObj[tag.tag] = tag.value; | ||||||
|  |         } | ||||||
|  |         return newObj; | ||||||
|  |       }) | ||||||
|  |       .catch(() => ({})); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   const parseAssociationStats = async (json) => { | ||||||
|     const newParsedAssociationStats = []; |     const newParsedAssociationStats = []; | ||||||
|     const newParsedRadioStats = []; |     const newParsedRadioStats = []; | ||||||
|  |     const bssidObj = {}; | ||||||
|  |  | ||||||
|     for (const stat of json.data) { |     for (const stat of json.data) { | ||||||
|       const associations = []; |       const associations = []; | ||||||
| @@ -123,6 +147,8 @@ const WifiAnalysis = () => { | |||||||
|  |  | ||||||
|             if ('associations' in ssid) { |             if ('associations' in ssid) { | ||||||
|               for (const association of ssid.associations) { |               for (const association of ssid.associations) { | ||||||
|  |                 bssidObj[association.bssid] = 0; | ||||||
|  |  | ||||||
|                 const data = { |                 const data = { | ||||||
|                   radio: radioInfo, |                   radio: radioInfo, | ||||||
|                   ...extractIp(stat.data, association.bssid), |                   ...extractIp(stat.data, association.bssid), | ||||||
| @@ -149,6 +175,16 @@ const WifiAnalysis = () => { | |||||||
|       newParsedAssociationStats.push(associations); |       newParsedAssociationStats.push(associations); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Adding Vendor info to associations | ||||||
|  |     const vendors = await getVendors(Object.keys(bssidObj)); | ||||||
|  |  | ||||||
|  |     for (let i = 0; i < newParsedAssociationStats.length; i += 1) { | ||||||
|  |       for (let y = 0; y < newParsedAssociationStats[i].length; y += 1) { | ||||||
|  |         newParsedAssociationStats[i][y].vendor = | ||||||
|  |           vendors[newParsedAssociationStats[i][y].bssid] ?? '-'; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Radio Stats |     // Radio Stats | ||||||
|     const ascOrderedRadioStats = newParsedRadioStats.reverse(); |     const ascOrderedRadioStats = newParsedRadioStats.reverse(); | ||||||
|     setParsedRadioStats(ascOrderedRadioStats); |     setParsedRadioStats(ascOrderedRadioStats); | ||||||
| @@ -203,14 +239,19 @@ const WifiAnalysis = () => { | |||||||
|   return ( |   return ( | ||||||
|     <div> |     <div> | ||||||
|       <CCard> |       <CCard> | ||||||
|         <CCardHeader className="dark-header"> |         <CCardHeader className="dark-header d-flex flex-row-reverse align-items-center"> | ||||||
|           <CRow> |           <div className="pl-2"> | ||||||
|             <CCol className="text-right"> |             <CPopover content={t('common.refresh')}> | ||||||
|  |               <CButton size="sm" color="info" onClick={getLatestAssociationStats}> | ||||||
|  |                 <CIcon content={cilSync} /> | ||||||
|  |               </CButton> | ||||||
|  |             </CPopover> | ||||||
|  |           </div> | ||||||
|  |           <div> | ||||||
|             <CButton color="info" size="sm" onClick={toggleModal}> |             <CButton color="info" size="sm" onClick={toggleModal}> | ||||||
|               {t('wifi_analysis.network_diagram')} |               {t('wifi_analysis.network_diagram')} | ||||||
|             </CButton> |             </CButton> | ||||||
|             </CCol> |           </div> | ||||||
|           </CRow> |  | ||||||
|         </CCardHeader> |         </CCardHeader> | ||||||
|         <CCardBody> |         <CCardBody> | ||||||
|           <CRow className="mb-4"> |           <CRow className="mb-4"> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Charles
					Charles