diff --git a/striker-ui/pages/init/index.tsx b/striker-ui/pages/init/index.tsx index beb5cd75..19b421ca 100644 --- a/striker-ui/pages/init/index.tsx +++ b/striker-ui/pages/init/index.tsx @@ -1,10 +1,13 @@ -import { FC, useState } from 'react'; +import { FC, useEffect, useState } from 'react'; import { Box as MUIBox, BoxProps as MUIBoxProps, iconButtonClasses as muiIconButtonClasses, } from '@mui/material'; -import { DragHandle as MUIDragHandleIcon } from '@mui/icons-material'; +import { + Check as MUICheckIcon, + DragHandle as MUIDragHandleIcon, +} from '@mui/icons-material'; import { DataGrid as MUIDataGrid, DataGridProps as MUIDataGridProps, @@ -12,14 +15,34 @@ import { } from '@mui/x-data-grid'; import API_BASE_URL from '../../lib/consts/API_BASE_URL'; -import { GREY, TEXT } from '../../lib/consts/DEFAULT_THEME'; +import { BLUE, GREY, TEXT } from '../../lib/consts/DEFAULT_THEME'; import Decorator from '../../components/Decorator'; -import { Panel, PanelHeader } from '../../components/Panels'; +import { + InnerPanel, + InnerPanelHeader, + Panel, + PanelHeader, +} from '../../components/Panels'; import periodicFetch from '../../lib/fetchers/periodicFetch'; import Spinner from '../../components/Spinner'; import sumstring from '../../lib/sumstring'; import { BodyText, BodyTextProps, HeaderText } from '../../components/Text'; +import OutlinedInputWithLabel from '../../components/OutlinedInputWithLabel'; + +type NetworkInput = { + interfaces: NetworkInterfaceOverviewMetadata[]; + ipAddress: string; + name: string; + subnetMask: string; +}; + +type NetworkInterfaceInputMap = Record< + string, + { + isApplied?: boolean; + } +>; const MOCK_NICS: NetworkInterfaceOverviewMetadata[] = [ { @@ -67,31 +90,68 @@ const DataGridCellText: FC = ({ /> ); +const BriefNetworkInterface: FC<{ + networkInterface: NetworkInterfaceOverviewMetadata; +}> = ({ + networkInterface: { networkInterfaceName, networkInterfaceState }, +}) => ( + :not(:first-child)': { marginLeft: '.5em' }, + }} + > + + + +); + const createNetworkInterfaceTableColumns = ( - onMouseDownDragHandle: ( + onMouseDownDragHandler: ( row: NetworkInterfaceOverviewMetadata, ...eventArgs: Parameters> ) => void, + networkInterfaceInputMap: NetworkInterfaceInputMap, ): MUIDataGridProps['columns'] => [ { align: 'center', field: '', - renderCell: ({ row }) => ( - { - onMouseDownDragHandle(row, ...eventArgs); - }} - sx={{ - alignItems: 'center', - display: 'flex', - flexDirection: 'row', + renderCell: ({ row }) => { + const { isApplied } = + networkInterfaceInputMap[row.networkInterfaceUUID] || false; - '&:hover': { cursor: 'grab' }, - }} - > - - - ), + let cursor = 'grab'; + let handleOnMouseDown: MUIBoxProps['onMouseDown'] = (...eventArgs) => { + onMouseDownDragHandler(row, ...eventArgs); + }; + let icon = ; + + if (isApplied) { + cursor = 'auto'; + handleOnMouseDown = undefined; + icon = ; + } + + return ( + + {icon} + + ); + }, sortable: false, width: 1, }, @@ -108,7 +168,7 @@ const createNetworkInterfaceTableColumns = ( }} > @@ -151,6 +211,22 @@ const createNetworkInterfaceTableColumns = ( ]; const NetworkInterfaceList: FC = () => { + const [networkInterfaceInputMap, setNetworkInterfaceInputMap] = + useState({}); + const [networkInputs] = useState([ + { + ipAddress: '10.200.1.1', + name: 'Back-Channel Network 1', + interfaces: [], + subnetMask: '255.255.0.0', + }, + { + ipAddress: '10.201.1.1', + name: 'Internet-Facing Network 1', + interfaces: [], + subnetMask: '255.255.0.0', + }, + ]); const [networkInterfaceHeld, setNetworkInterfaceHeld] = useState< NetworkInterfaceOverviewMetadata | undefined >(); @@ -159,8 +235,41 @@ const NetworkInterfaceList: FC = () => { NetworkInterfaceOverviewMetadata[] >(`${API_BASE_URL}/network-interface`, { refreshInterval: 2000, + onSuccess: (data) => { + if (data instanceof Array) { + const map = data.reduce( + (reduceContainer, { networkInterfaceUUID }) => { + reduceContainer[networkInterfaceUUID] = + networkInterfaceInputMap[networkInterfaceUUID] || {}; + + return reduceContainer; + }, + {}, + ); + + setNetworkInterfaceInputMap(map); + } + }, }); + useEffect(() => { + const map = networkInterfaces.reduce( + (reduceContainer, { networkInterfaceUUID }) => { + reduceContainer[networkInterfaceUUID] = + networkInterfaceInputMap[networkInterfaceUUID] || {}; + + return reduceContainer; + }, + {}, + ); + + setNetworkInterfaceInputMap(map); + + // This block inits the input map for the MOCK_NICS. + // TODO: remove after testing. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + return ( @@ -183,7 +292,7 @@ const NetworkInterfaceList: FC = () => { autoHeight columns={createNetworkInterfaceTableColumns((row) => { setNetworkInterfaceHeld(row); - })} + }, networkInterfaceInputMap)} disableColumnMenu disableSelectionOnClick getRowId={({ networkInterfaceUUID }) => networkInterfaceUUID} @@ -206,18 +315,77 @@ const NetworkInterfaceList: FC = () => { networkInterfaceHeld?.networkInterfaceName || 'none' }`} /> - { - setNetworkInterfaceHeld(undefined); - }} - sx={{ - borderColor: TEXT, - borderStyle: 'dashed', - borderWidth: '4px', - height: '100px', - width: '100px', - }} - /> + + {networkInputs.map(({ interfaces, ipAddress, name, subnetMask }) => ( + + + + + *': { + flexBasis: '50%', + }, + }} + > + { + if (networkInterfaceHeld) { + interfaces.push(networkInterfaceHeld); + + networkInterfaceInputMap[ + networkInterfaceHeld.networkInterfaceUUID + ].isApplied = true; + } + + setNetworkInterfaceHeld(undefined); + }} + sx={{ + borderColor: TEXT, + borderStyle: 'dashed', + borderWidth: '4px', + display: 'flex', + flexDirection: 'column', + padding: '.6em', + + '& > :not(:first-child)': { + marginTop: '.3em', + }, + }} + > + {interfaces.length > 0 ? ( + interfaces.map((networkInterface) => ( + + )) + ) : ( + + )} + + + + + + + + ))} )}