mirror of
				https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
				synced 2025-10-30 17:57:46 +00:00 
			
		
		
		
	Merge pull request #201 from stephb9959/main
[WIFI-13153] Added IP addresses to wifi analysis
This commit is contained in:
		
							
								
								
									
										10
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|   "name": "ucentral-client", |   "name": "ucentral-client", | ||||||
|   "version": "2.11.0(15)", |   "version": "2.11.0(16)", | ||||||
|   "lockfileVersion": 3, |   "lockfileVersion": 3, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "packages": { |   "packages": { | ||||||
|     "": { |     "": { | ||||||
|       "name": "ucentral-client", |       "name": "ucentral-client", | ||||||
|       "version": "2.11.0(15)", |       "version": "2.11.0(16)", | ||||||
|       "license": "ISC", |       "license": "ISC", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@chakra-ui/anatomy": "^2.1.1", |         "@chakra-ui/anatomy": "^2.1.1", | ||||||
| @@ -4760,9 +4760,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/axios": { |     "node_modules/axios": { | ||||||
|       "version": "1.3.5", |       "version": "1.6.1", | ||||||
|       "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.5.tgz", |       "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", | ||||||
|       "integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==", |       "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "follow-redirects": "^1.15.0", |         "follow-redirects": "^1.15.0", | ||||||
|         "form-data": "^4.0.0", |         "form-data": "^4.0.0", | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "ucentral-client", |   "name": "ucentral-client", | ||||||
|   "version": "2.11.0(15)", |   "version": "2.11.0(16)", | ||||||
|   "description": "", |   "description": "", | ||||||
|   "private": true, |   "private": true, | ||||||
|   "main": "index.tsx", |   "main": "index.tsx", | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ import { ColumnPicker } from 'components/DataTables/ColumnPicker'; | |||||||
| import { DataTable } from 'components/DataTables/DataTable'; | import { DataTable } from 'components/DataTables/DataTable'; | ||||||
| import DataCell from 'components/TableCells/DataCell'; | import DataCell from 'components/TableCells/DataCell'; | ||||||
| import { Column } from 'models/Table'; | import { Column } from 'models/Table'; | ||||||
|  | import IpCell from './IpCell'; | ||||||
|  |  | ||||||
| export type ParsedAssociation = { | export type ParsedAssociation = { | ||||||
|   radio?: ParsedRadio; |   radio?: ParsedRadio; | ||||||
| @@ -35,7 +36,7 @@ type Props = { | |||||||
|   isSingle?: boolean; |   isSingle?: boolean; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const WifiAnalysisAssocationsTable = ({ data, ouis, isSingle }: Props) => { | const WifiAnalysisAssociationsTable = ({ data, ouis, isSingle }: Props) => { | ||||||
|   const { t } = useTranslation(); |   const { t } = useTranslation(); | ||||||
|   const [hiddenColumns, setHiddenColumns] = React.useState<string[]>([]); |   const [hiddenColumns, setHiddenColumns] = React.useState<string[]>([]); | ||||||
|  |  | ||||||
| @@ -50,6 +51,10 @@ const WifiAnalysisAssocationsTable = ({ data, ouis, isSingle }: Props) => { | |||||||
|   ); |   ); | ||||||
|   const dataCell = React.useCallback((v: number) => <DataCell bytes={v} />, []); |   const dataCell = React.useCallback((v: number) => <DataCell bytes={v} />, []); | ||||||
|   const indexCell = React.useCallback((assoc: ParsedAssociation) => assoc.radio?.band ?? assoc.radio?.deductedBand, []); |   const indexCell = React.useCallback((assoc: ParsedAssociation) => assoc.radio?.band ?? assoc.radio?.deductedBand, []); | ||||||
|  |   const ipCell = React.useCallback( | ||||||
|  |     (assoc: ParsedAssociation) => <IpCell ipv4={assoc.ips.ipv4} ipv6={assoc.ips.ipv6} />, | ||||||
|  |     [], | ||||||
|  |   ); | ||||||
|  |  | ||||||
|   const columns: Column<ParsedAssociation>[] = React.useMemo( |   const columns: Column<ParsedAssociation>[] = React.useMemo( | ||||||
|     (): Column<ParsedAssociation>[] => [ |     (): Column<ParsedAssociation>[] => [ | ||||||
| @@ -72,6 +77,13 @@ const WifiAnalysisAssocationsTable = ({ data, ouis, isSingle }: Props) => { | |||||||
|         isMonospace: true, |         isMonospace: true, | ||||||
|         alwaysShow: true, |         alwaysShow: true, | ||||||
|       }, |       }, | ||||||
|  |       { | ||||||
|  |         id: 'ips', | ||||||
|  |         Header: 'IPs', | ||||||
|  |         Footer: '', | ||||||
|  |         Cell: (v) => ipCell(v.cell.row.original), | ||||||
|  |         disableSortBy: true, | ||||||
|  |       }, | ||||||
|       { |       { | ||||||
|         id: 'vendor', |         id: 'vendor', | ||||||
|         Header: t('controller.wifi.vendor'), |         Header: t('controller.wifi.vendor'), | ||||||
| @@ -195,4 +207,4 @@ const WifiAnalysisAssocationsTable = ({ data, ouis, isSingle }: Props) => { | |||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export default WifiAnalysisAssocationsTable; | export default WifiAnalysisAssociationsTable; | ||||||
|   | |||||||
							
								
								
									
										90
									
								
								src/pages/Device/WifiAnalysis/IpCell.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/pages/Device/WifiAnalysis/IpCell.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | |||||||
|  | import * as React from 'react'; | ||||||
|  | import { CopyIcon } from '@chakra-ui/icons'; | ||||||
|  | import { | ||||||
|  |   Button, | ||||||
|  |   Flex, | ||||||
|  |   Heading, | ||||||
|  |   IconButton, | ||||||
|  |   ListItem, | ||||||
|  |   Popover, | ||||||
|  |   PopoverArrow, | ||||||
|  |   PopoverBody, | ||||||
|  |   PopoverCloseButton, | ||||||
|  |   PopoverContent, | ||||||
|  |   PopoverHeader, | ||||||
|  |   PopoverTrigger, | ||||||
|  |   Text, | ||||||
|  |   Tooltip, | ||||||
|  |   UnorderedList, | ||||||
|  |   useBoolean, | ||||||
|  |   useClipboard, | ||||||
|  | } from '@chakra-ui/react'; | ||||||
|  |  | ||||||
|  | const CopyString = ({ str }: { str: string }) => { | ||||||
|  |   const [isHovered, setHovered] = useBoolean(false); | ||||||
|  |   const copy = useClipboard(str); | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <Flex alignItems="center" onMouseEnter={setHovered.on} onMouseLeave={setHovered.off}> | ||||||
|  |       <Text>{str}</Text> | ||||||
|  |       <Tooltip label={copy.hasCopied ? 'Copied!' : 'Copy'} placement="top"> | ||||||
|  |         <IconButton | ||||||
|  |           aria-label={copy.hasCopied ? 'Copied!' : 'Copy'} | ||||||
|  |           size="sm" | ||||||
|  |           onClick={copy.onCopy} | ||||||
|  |           icon={<CopyIcon />} | ||||||
|  |           variant="transparent" | ||||||
|  |           opacity={!isHovered ? 0 : 1} | ||||||
|  |         /> | ||||||
|  |       </Tooltip> | ||||||
|  |     </Flex> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | type Props = { | ||||||
|  |   ipv4: string[]; | ||||||
|  |   ipv6: string[]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const IpCell = ({ ipv4, ipv6 }: Props) => { | ||||||
|  |   const length = ipv4.length + ipv6.length; | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <Popover> | ||||||
|  |       <PopoverTrigger> | ||||||
|  |         <Button colorScheme="teal" size="sm"> | ||||||
|  |           {length} | ||||||
|  |         </Button> | ||||||
|  |       </PopoverTrigger> | ||||||
|  |       <PopoverContent> | ||||||
|  |         <PopoverArrow /> | ||||||
|  |         <PopoverCloseButton /> | ||||||
|  |         <PopoverHeader> | ||||||
|  |           <Heading size="sm"> | ||||||
|  |             {length} {length === 1 ? 'IP' : 'IPs'} | ||||||
|  |           </Heading> | ||||||
|  |         </PopoverHeader> | ||||||
|  |         <PopoverBody> | ||||||
|  |           <Heading size="sm">IpV4 ({ipv4.length})</Heading> | ||||||
|  |           <UnorderedList> | ||||||
|  |             {ipv4.map((ip) => ( | ||||||
|  |               <ListItem key={ip}> | ||||||
|  |                 <CopyString str={ip} /> | ||||||
|  |               </ListItem> | ||||||
|  |             ))} | ||||||
|  |           </UnorderedList> | ||||||
|  |           <Heading size="sm">IpV6 ({ipv6.length})</Heading> | ||||||
|  |           <UnorderedList> | ||||||
|  |             {ipv6.map((ip) => ( | ||||||
|  |               <ListItem key={ip}> | ||||||
|  |                 <CopyString str={ip} /> | ||||||
|  |               </ListItem> | ||||||
|  |             ))} | ||||||
|  |           </UnorderedList> | ||||||
|  |         </PopoverBody> | ||||||
|  |       </PopoverContent> | ||||||
|  |     </Popover> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default IpCell; | ||||||
		Reference in New Issue
	
	Block a user
	 Charles Bourque
					Charles Bourque