@@ -51,6 +51,7 @@ import { Size } from '../../models/size'
5151import LiveView from '../LiveView/LiveView'
5252import SessionData , { createSessionData } from '../../models/session-data'
5353import { useNavigate } from 'react-router-dom'
54+ import ColumnSelector from './ColumnSelector'
5455
5556function descendingComparator < T > ( a : T , b : T , orderBy : keyof T ) : number {
5657 if ( orderBy === 'sessionDurationMillis' ) {
@@ -94,7 +95,7 @@ interface HeadCell {
9495 numeric : boolean
9596}
9697
97- const headCells : HeadCell [ ] = [
98+ const fixedHeadCells : HeadCell [ ] = [
9899 { id : 'id' , numeric : false , label : 'Session' } ,
99100 { id : 'capabilities' , numeric : false , label : 'Capabilities' } ,
100101 { id : 'startTime' , numeric : false , label : 'Start time' } ,
@@ -107,10 +108,11 @@ interface EnhancedTableProps {
107108 property : keyof SessionData ) => void
108109 order : Order
109110 orderBy : string
111+ headCells : HeadCell [ ]
110112}
111113
112114function EnhancedTableHead ( props : EnhancedTableProps ) : JSX . Element {
113- const { order, orderBy, onRequestSort } = props
115+ const { order, orderBy, onRequestSort, headCells } = props
114116 const createSortHandler = ( property : keyof SessionData ) => ( event : React . MouseEvent < unknown > ) => {
115117 onRequestSort ( event , property )
116118 }
@@ -181,6 +183,16 @@ function RunningSessions (props) {
181183 const [ rowsPerPage , setRowsPerPage ] = useState ( 10 )
182184 const [ searchFilter , setSearchFilter ] = useState ( '' )
183185 const [ searchBarHelpOpen , setSearchBarHelpOpen ] = useState ( false )
186+ const [ selectedColumns , setSelectedColumns ] = useState < string [ ] > ( ( ) => {
187+ try {
188+ const savedColumns = localStorage . getItem ( 'selenium-grid-selected-columns' )
189+ return savedColumns ? JSON . parse ( savedColumns ) : [ ]
190+ } catch ( e ) {
191+ console . error ( 'Error loading saved columns:' , e )
192+ return [ ]
193+ }
194+ } )
195+ const [ headCells , setHeadCells ] = useState < HeadCell [ ] > ( fixedHeadCells )
184196 const liveViewRef = useRef ( null )
185197 const navigate = useNavigate ( )
186198
@@ -264,8 +276,27 @@ function RunningSessions (props) {
264276
265277 const { sessions, origin, sessionId } = props
266278
279+ const getCapabilityValue = ( capabilitiesStr : string , key : string ) : string => {
280+ try {
281+ const capabilities = JSON . parse ( capabilitiesStr as string )
282+ const value = capabilities [ key ]
283+
284+ if ( value === undefined || value === null ) {
285+ return ''
286+ }
287+
288+ if ( typeof value === 'object' ) {
289+ return JSON . stringify ( value )
290+ }
291+
292+ return String ( value )
293+ } catch ( e ) {
294+ return ''
295+ }
296+ }
297+
267298 const rows = sessions . map ( ( session ) => {
268- return createSessionData (
299+ const sessionData = createSessionData (
269300 session . id ,
270301 session . capabilities ,
271302 session . startTime ,
@@ -276,6 +307,12 @@ function RunningSessions (props) {
276307 session . slot ,
277308 origin
278309 )
310+
311+ selectedColumns . forEach ( column => {
312+ sessionData [ column ] = getCapabilityValue ( session . capabilities , column )
313+ } )
314+
315+ return sessionData
279316 } )
280317 const emptyRows = rowsPerPage - Math . min ( rowsPerPage , rows . length - page * rowsPerPage )
281318
@@ -291,19 +328,39 @@ function RunningSessions (props) {
291328 setRowLiveViewOpen ( s )
292329 }
293330 } , [ sessionId , sessions ] )
331+
332+ useEffect ( ( ) => {
333+ const dynamicHeadCells = selectedColumns . map ( column => ( {
334+ id : column ,
335+ numeric : false ,
336+ label : column
337+ } ) )
338+
339+ setHeadCells ( [ ...fixedHeadCells , ...dynamicHeadCells ] )
340+ } , [ selectedColumns ] )
294341
295342 return (
296343 < Box width = '100%' >
297344 { rows . length > 0 && (
298345 < div >
299346 < Paper sx = { { width : '100%' , marginBottom : 2 } } >
300347 < EnhancedTableToolbar title = 'Running' >
301- < RunningSessionsSearchBar
302- searchFilter = { searchFilter }
303- handleSearch = { setSearchFilter }
304- searchBarHelpOpen = { searchBarHelpOpen }
305- setSearchBarHelpOpen = { setSearchBarHelpOpen }
306- />
348+ < Box display = "flex" alignItems = "center" >
349+ < ColumnSelector
350+ sessions = { sessions }
351+ selectedColumns = { selectedColumns }
352+ onColumnSelectionChange = { ( columns ) => {
353+ setSelectedColumns ( columns )
354+ localStorage . setItem ( 'selenium-grid-selected-columns' , JSON . stringify ( columns ) )
355+ } }
356+ />
357+ < RunningSessionsSearchBar
358+ searchFilter = { searchFilter }
359+ handleSearch = { setSearchFilter }
360+ searchBarHelpOpen = { searchBarHelpOpen }
361+ setSearchBarHelpOpen = { setSearchBarHelpOpen }
362+ />
363+ </ Box >
307364 </ EnhancedTableToolbar >
308365 < TableContainer >
309366 < Table
@@ -316,6 +373,7 @@ function RunningSessions (props) {
316373 order = { order }
317374 orderBy = { orderBy }
318375 onRequestSort = { handleRequestSort }
376+ headCells = { headCells }
319377 />
320378 < TableBody >
321379 { stableSort ( rows , getComparator ( order , orderBy ) )
@@ -494,6 +552,10 @@ function RunningSessions (props) {
494552 < TableCell align = 'left' >
495553 { row . nodeUri }
496554 </ TableCell >
555+ { /* Add dynamic columns */ }
556+ { selectedColumns . map ( column => (
557+ < TableCell key = { column } align = 'left' > { row [ column ] } </ TableCell >
558+ ) ) }
497559 </ TableRow >
498560 )
499561 } ) }
0 commit comments