33 * See the LICENSE file in the repository root folder for details.
44 */
55
6- import { DataGrid , GridColDef , GridFilterModel , GridRow , GridRowProps , GridToolbar } from '@mui/x-data-grid' ;
6+ import {
7+ DataGrid ,
8+ GridColDef ,
9+ GridFilterModel ,
10+ GridRow ,
11+ GridRowProps ,
12+ GridToolbarContainer ,
13+ GridToolbarFilterButton ,
14+ GridToolbarQuickFilter
15+ } from '@mui/x-data-grid' ;
716import { routes } from '../../utils/routes' ;
817import { datePipe , fullNamePipe , wbsPipe } from '../../utils/pipes' ;
918import { useAllChangeRequests } from '../../hooks/change-requests.hooks' ;
1019import LoadingIndicator from '../../components/LoadingIndicator' ;
1120import ErrorPage from '../ErrorPage' ;
12- import { useTheme } from '@mui/system' ;
13- import { useState } from 'react' ;
21+ import { Box , useTheme } from '@mui/system' ;
22+ import { useEffect , useState } from 'react' ;
1423import { ChangeRequest , ChangeRequestType , validateWBS , WbsNumber } from 'shared' ;
1524import { GridColDefStyle } from '../../utils/tables' ;
1625import { Link } from '@mui/material' ;
1726import { Link as RouterLink } from 'react-router-dom' ;
1827
28+ const CustomToolbar = ( ) => (
29+ < GridToolbarContainer >
30+ < GridToolbarQuickFilter />
31+ < GridToolbarFilterButton />
32+ </ GridToolbarContainer >
33+ ) ;
34+
1935const ChangeRequestsTable : React . FC = ( ) => {
36+ const [ windowSize , setWindowSize ] = useState ( window . innerWidth ) ;
2037 const { isLoading, isError, data, error } = useAllChangeRequests ( ) ;
2138 if ( localStorage . getItem ( 'cr-table-row-count' ) === null ) {
2239 localStorage . setItem ( 'cr-table-row-count' , '50' ) ;
@@ -32,18 +49,76 @@ const ChangeRequestsTable: React.FC = () => {
3249
3350 const theme = useTheme ( ) ;
3451
52+ useEffect ( ( ) => {
53+ const handleResize = ( ) => {
54+ setWindowSize ( window . innerWidth ) ;
55+ } ;
56+
57+ // Attach the event listener to the window object
58+ window . addEventListener ( 'resize' , handleResize ) ;
59+
60+ // Remove the event listener when the component unmounts
61+ return ( ) => {
62+ window . removeEventListener ( 'resize' , handleResize ) ;
63+ } ;
64+ } , [ ] ) ;
65+
3566 if ( isLoading || ! data ) return < LoadingIndicator /> ;
3667
3768 if ( isError ) return < ErrorPage message = { error ?. message } /> ;
3869
70+ const idColumn : GridColDef = {
71+ ...baseColDef ,
72+ field : 'crId' ,
73+ type : 'number' ,
74+ headerName : 'ID' ,
75+ maxWidth : 75
76+ } ;
77+
78+ const dateReviewedColumn : GridColDef = {
79+ ...baseColDef ,
80+ field : 'dateReviewed' ,
81+ headerName : 'Date Reviewed' ,
82+ type : 'date' ,
83+ valueFormatter : ( params ) => ( params . value ? datePipe ( params . value ) : '' ) ,
84+ maxWidth : 200
85+ } ;
86+
87+ const wbsColumn : GridColDef = {
88+ ...baseColDef ,
89+ field : 'wbs' ,
90+ headerName : 'WBS' ,
91+ filterable : true ,
92+ sortable : true ,
93+ maxWidth : 300 ,
94+ valueGetter : ( params ) => `${ wbsPipe ( params . value . wbsNum ) } - ${ params . value . name } ` ,
95+ sortComparator : ( _v1 , _v2 , param1 , param2 ) => {
96+ const wbs1 : WbsNumber = validateWBS ( ( param1 . value as string ) . split ( ' ' ) [ 0 ] ) ;
97+ const wbs2 : WbsNumber = validateWBS ( ( param2 . value as string ) . split ( ' ' ) [ 0 ] ) ;
98+
99+ if ( wbs1 . carNumber !== wbs2 . carNumber ) {
100+ return wbs1 . carNumber - wbs2 . carNumber ;
101+ } else if ( wbs1 . projectNumber !== wbs2 . projectNumber ) {
102+ return wbs1 . projectNumber - wbs2 . projectNumber ;
103+ } else if ( wbs1 . workPackageNumber !== wbs2 . workPackageNumber ) {
104+ return wbs1 . workPackageNumber - wbs2 . workPackageNumber ;
105+ } else {
106+ return 0 ;
107+ }
108+ }
109+ } ;
110+
111+ const submitterColumn : GridColDef = {
112+ ...baseColDef ,
113+ field : 'submitter' ,
114+ headerName : 'Submitter' ,
115+ maxWidth : 200
116+ } ;
117+
118+ const smallColumns : GridColDef [ ] = [ idColumn , dateReviewedColumn , wbsColumn , submitterColumn ] ;
119+
39120 const columns : GridColDef [ ] = [
40- {
41- ...baseColDef ,
42- field : 'crId' ,
43- type : 'number' ,
44- headerName : 'ID' ,
45- maxWidth : 75
46- } ,
121+ idColumn ,
47122 {
48123 ...baseColDef ,
49124 field : 'type' ,
@@ -53,29 +128,7 @@ const ChangeRequestsTable: React.FC = () => {
53128 maxWidth : 150
54129 } ,
55130 { ...baseColDef , field : 'carNumber' , headerName : 'Car #' , type : 'number' , maxWidth : 50 } ,
56- {
57- ...baseColDef ,
58- field : 'wbs' ,
59- headerName : 'WBS' ,
60- filterable : true ,
61- sortable : true ,
62- maxWidth : 300 ,
63- valueGetter : ( params ) => `${ wbsPipe ( params . value . wbsNum ) } - ${ params . value . name } ` ,
64- sortComparator : ( _v1 , _v2 , param1 , param2 ) => {
65- const wbs1 : WbsNumber = validateWBS ( ( param1 . value as string ) . split ( ' ' ) [ 0 ] ) ;
66- const wbs2 : WbsNumber = validateWBS ( ( param2 . value as string ) . split ( ' ' ) [ 0 ] ) ;
67-
68- if ( wbs1 . carNumber !== wbs2 . carNumber ) {
69- return wbs1 . carNumber - wbs2 . carNumber ;
70- } else if ( wbs1 . projectNumber !== wbs2 . projectNumber ) {
71- return wbs1 . projectNumber - wbs2 . projectNumber ;
72- } else if ( wbs1 . workPackageNumber !== wbs2 . workPackageNumber ) {
73- return wbs1 . workPackageNumber - wbs2 . workPackageNumber ;
74- } else {
75- return 0 ;
76- }
77- }
78- } ,
131+ wbsColumn ,
79132 {
80133 ...baseColDef ,
81134 field : 'dateSubmitted' ,
@@ -84,20 +137,8 @@ const ChangeRequestsTable: React.FC = () => {
84137 valueFormatter : ( params ) => datePipe ( params . value ) ,
85138 maxWidth : 200
86139 } ,
87- {
88- ...baseColDef ,
89- field : 'submitter' ,
90- headerName : 'Submitter' ,
91- maxWidth : 200
92- } ,
93- {
94- ...baseColDef ,
95- field : 'dateReviewed' ,
96- headerName : 'Date Reviewed' ,
97- type : 'date' ,
98- valueFormatter : ( params ) => ( params . value ? datePipe ( params . value ) : '' ) ,
99- maxWidth : 200
100- } ,
140+ submitterColumn ,
141+ dateReviewedColumn ,
101142 {
102143 ...baseColDef ,
103144 field : 'reviewer' ,
@@ -141,7 +182,15 @@ const ChangeRequestsTable: React.FC = () => {
141182 ) ;
142183
143184 return (
144- < div >
185+ < Box
186+ sx = { {
187+ '& .Mui-even' : {
188+ backgroundColor : theme . palette . background . paper ,
189+ border : `1px solid ${ theme . palette . mode === 'light' ? '#f0f0f0' : '#303030' } `
190+ } ,
191+ '& .Mui-odd' : { border : `1px solid ${ theme . palette . mode === 'light' ? '#f0f0f0' : '#303030' } ` }
192+ } }
193+ >
145194 < DataGrid
146195 autoHeight
147196 disableSelectionOnClick
@@ -164,11 +213,27 @@ const ChangeRequestsTable: React.FC = () => {
164213 reviewer : fullNamePipe ( v . reviewer )
165214 } ) ) || [ ]
166215 }
167- columns = { columns }
216+ columns = { windowSize < 900 ? smallColumns : columns }
168217 getRowId = { ( row ) => row . crId }
169- sx = { { background : theme . palette . background . paper } }
218+ sx = { {
219+ border : 0 ,
220+ '& .MuiDataGrid-row:hover' : {
221+ backgroundColor : '#ef4345'
222+ } ,
223+ '& .MuiDataGrid-columnHeader' : {
224+ borderRight : `1px solid ${ theme . palette . mode === 'light' ? '#f0f0f0' : '#303030' } ` ,
225+ borderLeft : `1px solid ${ theme . palette . mode === 'light' ? '#f0f0f0' : '#303030' } `
226+ } ,
227+ '& .MuiDataGrid-columnHeaders' : {
228+ border : `1px solid ${ theme . palette . mode === 'light' ? '#f0f0f0' : '#303030' } `
229+ } ,
230+ '.MuiDataGrid-columnSeparator' : {
231+ display : 'none'
232+ }
233+ } }
234+ getRowClassName = { ( params ) => ( params . indexRelativeToCurrentPage % 2 === 0 ? 'Mui-even' : 'Mui-odd' ) }
170235 components = { {
171- Toolbar : GridToolbar ,
236+ Toolbar : CustomToolbar ,
172237 Row : ( props : GridRowProps & { row : ChangeRequest } ) => {
173238 return (
174239 < Link
@@ -213,7 +278,7 @@ const ChangeRequestsTable: React.FC = () => {
213278 }
214279 } }
215280 />
216- </ div >
281+ </ Box >
217282 ) ;
218283} ;
219284
0 commit comments