1- import {
2- Chart ,
3- ChartBar ,
4- ChartAxis ,
5- ChartThemeColor ,
6- } from "@patternfly/react-charts/victory" ;
1+ import { Card , CardBody } from "@patternfly/react-core" ;
72import {
83 Table ,
94 Thead ,
@@ -13,118 +8,83 @@ import {
138 Td ,
149 Caption ,
1510} from "@patternfly/react-table" ;
16- import { useState } from "react" ;
1711
18- const TableWrapper = ( {
19- columns,
20- rows,
21- caption,
22- variant,
23- graph,
24- selectable = false ,
25- onRowSelect,
26- actions,
27- setCustomData,
28- } ) => {
29- const [ selectedRows , setSelectedRows ] = useState ( [ ] ) ;
12+ interface FieldData {
13+ name : string ;
14+ data_path : string ;
15+ data : ( string | number | boolean | null | ( string | number ) [ ] ) [ ] ;
16+ }
3017
31- const toggleRow = ( index ) => {
32- const newSelected = selectedRows . includes ( index )
33- ? selectedRows . filter ( ( i ) => i !== index )
34- : [ ...selectedRows , index ] ;
35- setSelectedRows ( newSelected ) ;
18+ interface TableWrapperProps {
19+ component : "table" ;
20+ title : string ;
21+ id : string ;
22+ fields : FieldData [ ] ;
23+ className ?: string ;
24+ }
3625
37- onRowSelect ?.( newSelected . map ( ( i ) => rows [ i ] ) ) ;
38- setCustomData ( newSelected . map ( ( i ) => rows [ i ] ) ) ;
39- } ;
26+ const TableWrapper = ( props : TableWrapperProps ) => {
27+ const { title, id, fields, className } = props ;
28+ // Transform fields data into table format
29+ const transformFieldsToTableData = ( ) => {
30+ if ( ! fields || fields . length === 0 ) return { columns : [ ] , rows : [ ] } ;
31+
32+ // Find the maximum number of data items across all fields
33+ const maxDataLength = Math . max ( ...fields . map ( ( field ) => field . data . length ) ) ;
34+
35+ // Create columns from field names
36+ const transformedColumns = fields . map ( ( field ) => ( {
37+ key : field . name ,
38+ label : field . name ,
39+ } ) ) ;
4040
41- const toggleAllRows = ( ) => {
42- const allSelected = selectedRows . length === rows . length ;
43- const newSelected = allSelected ? [ ] : rows . map ( ( _ , i ) => i ) ;
44- setSelectedRows ( newSelected ) ;
41+ // Create rows based on the maximum data length
42+ const transformedRows = [ ] ;
43+ for ( let i = 0 ; i < maxDataLength ; i ++ ) {
44+ const row : Record < string , string | number | null > = { } ;
45+ fields . forEach ( ( field ) => {
46+ const value = field . data [ i ] ;
47+ if ( value === null || value === undefined ) {
48+ row [ field . name ] = "" ;
49+ } else if ( Array . isArray ( value ) ) {
50+ row [ field . name ] = value . join ( ", " ) ;
51+ } else {
52+ row [ field . name ] = String ( value ) ;
53+ }
54+ } ) ;
55+ transformedRows . push ( row ) ;
56+ }
4557
46- onRowSelect ?.( newSelected . map ( ( i ) => rows [ i ] ) ) ;
47- setCustomData ( newSelected . map ( ( i ) => rows [ i ] ) ) ;
58+ return { columns : transformedColumns , rows : transformedRows } ;
4859 } ;
4960
50- const graphData =
51- graph && graph . column
52- ? rows . map ( ( row ) => ( { x : row [ columns [ 0 ] . key ] , y : row [ graph . column ] } ) )
53- : [ ] ;
61+ const { columns, rows } = transformFieldsToTableData ( ) ;
5462
5563 return (
56- < div >
57- < Table variant = { variant } borders = { variant !== "compactBorderless" } >
58- { caption && (
59- < Caption >
60- < div
61- style = { {
62- display : "flex" ,
63- justifyContent : "space-between" ,
64- alignItems : "center" ,
65- } }
66- >
67- < span > { caption } </ span >
68- { actions }
69- </ div >
70- </ Caption >
71- ) }
72- < Thead >
73- < Tr >
74- { selectable && (
75- < Th >
76- < input
77- type = "checkbox"
78- aria-label = "Select all rows"
79- checked = { selectedRows . length === rows . length }
80- onChange = { toggleAllRows }
81- />
82- </ Th >
83- ) }
84- { columns . map ( ( col , index ) => (
85- < Th key = { index } > { col . label } </ Th >
86- ) ) }
87- </ Tr >
88- </ Thead >
89- < Tbody >
90- { rows . map ( ( row , rowIndex ) => (
91- < Tr key = { rowIndex } data-testid = { `row-${ row . id ?? rowIndex } ` } >
92- { selectable && (
93- < Td >
94- < input
95- type = "checkbox"
96- aria-label = { `Select row ${ rowIndex } ` }
97- checked = { selectedRows . includes ( rowIndex ) }
98- onChange = { ( ) => toggleRow ( rowIndex ) }
99- />
100- </ Td >
101- ) }
102- { columns . map ( ( col , colIndex ) => (
103- < Td key = { colIndex } > { row [ col . key ] } </ Td >
64+ < Card id = { id } className = { className } >
65+ < CardBody >
66+ < Table variant = "compact" borders >
67+ < Caption > { title } </ Caption >
68+ < Thead >
69+ < Tr >
70+ { columns . map ( ( col , index ) => (
71+ < Th key = { index } > { col . label } </ Th >
10472 ) ) }
10573 </ Tr >
106- ) ) }
107- </ Tbody >
108- </ Table >
109-
110- { graph && (
111- < div style = { { height : "300px" } } >
112- < Chart
113- ariaTitle = { graph . title || "Chart" }
114- domainPadding = { { x : [ 30 , 25 ] } }
115- height = { 300 }
116- width = { 600 }
117- themeColor = { ChartThemeColor . multiUnordered }
118- >
119- < ChartAxis />
120- < ChartAxis dependentAxis />
121- < ChartBar data = { graphData } barWidth = { 30 } />
122- </ Chart >
123- </ div >
124- ) }
125- </ div >
74+ </ Thead >
75+ < Tbody >
76+ { rows . map ( ( row , rowIndex ) => (
77+ < Tr key = { rowIndex } data-testid = { `row-${ rowIndex } ` } >
78+ { columns . map ( ( col , colIndex ) => (
79+ < Td key = { colIndex } > { row [ col . key ] } </ Td >
80+ ) ) }
81+ </ Tr >
82+ ) ) }
83+ </ Tbody >
84+ </ Table >
85+ </ CardBody >
86+ </ Card >
12687 ) ;
12788} ;
12889
12990export default TableWrapper ;
130-
0 commit comments