@@ -5,31 +5,38 @@ import { weatherTemplate, getWeatherIndex } from "../components/weatherTemplate"
55
66
77export default function Home ( ) {
8- const [ loading , setLoading ] = useState ( true ) ;
9- const [ jobs , setJobs ] = useState ( [ ] ) ;
10- const [ rows , setRows ] = useState ( [ ] ) ;
11- const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
8+ const [ loading , setLoading ] = useState ( true ) ;
9+ const [ jobs , setJobs ] = useState ( [ ] ) ;
10+ const [ checks , setChecks ] = useState ( [ ] ) ;
11+ const [ rowsPR , setRowsPR ] = useState ( [ ] ) ;
12+ const [ rowsNightly , setRowsNightly ] = useState ( [ ] ) ;
13+ const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
14+ const [ display , setDisplay ] = useState ( "nightly" ) ;
15+
1216
1317 useEffect ( ( ) => {
1418 const fetchData = async ( ) => {
15- let data = { } ;
19+ let nightlyData = { } ;
20+ let prData = { } ;
1621
1722 if ( process . env . NODE_ENV === "development" ) {
18- data = ( await import ( "../job_stats.json" ) ) . default ;
23+ nightlyData = ( await import ( "../localData/job_stats.json" ) ) . default ;
24+ prData = ( await import ( "../localData/check_stats.json" ) ) . default ;
1925 } else {
20- const response = await fetch (
26+ nightlyData = await fetch (
2127 "https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
2228 "/refs/heads/latest-dashboard-data/data/job_stats.json"
23- ) ;
24- data = await response . json ( ) ;
29+ ) . then ( ( res ) => res . json ( ) ) ;
30+ prData = await fetch (
31+ "https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
32+ "/refs/heads/latest-dashboard-data/data/check_stats.json"
33+ ) . then ( ( res ) => res . json ( ) ) ;
2534 }
2635
2736 try {
28- const jobData = Object . keys ( data ) . map ( ( key ) => {
29- const job = data [ key ] ;
30- return { name : key , ...job } ;
31- } ) ;
32- setJobs ( jobData ) ;
37+ const mapData = ( data ) => Object . keys ( data ) . map ( ( key ) => ( { name : key , ...data [ key ] } ) ) ;
38+ setJobs ( mapData ( nightlyData ) ) ;
39+ setChecks ( mapData ( prData ) ) ;
3340 } catch ( error ) {
3441 // TODO: Add pop-up/toast message for error
3542 console . error ( "Error fetching data:" , error ) ;
@@ -41,17 +48,50 @@ export default function Home() {
4148 fetchData ( ) ;
4249 } , [ ] ) ;
4350
51+ // Filter and set the rows for Nightly view.
52+ useEffect ( ( ) => {
53+ setLoading ( true ) ;
54+ let filteredJobs = jobs ;
55+ //Set the rows for the table.
56+ setRowsNightly (
57+ filteredJobs . map ( ( job ) => ( {
58+ name : job . name ,
59+ runs : job . runs ,
60+ fails : job . fails ,
61+ skips : job . skips ,
62+ required : job . required ,
63+ weather : getWeatherIndex ( job ) ,
64+ } ) )
65+ ) ;
66+ setLoading ( false ) ;
67+ } , [ jobs ] ) ;
68+
69+ // Filter and set the rows for PR Checks view.
70+ useEffect ( ( ) => {
71+ setLoading ( true ) ;
72+ let filteredChecks = checks
73+
74+ //Set the rows for the table.
75+ setRowsPR (
76+ filteredChecks . map ( ( check ) => ( {
77+ name : check . name ,
78+ runs : check . runs ,
79+ fails : check . fails ,
80+ skips : check . skips ,
81+ required : check . required ,
82+ weather : getWeatherIndex ( check ) ,
83+ } ) )
84+ ) ;
85+ setLoading ( false ) ;
86+ } , [ checks ] ) ;
87+
88+ // Close all rows on view switch.
89+ // Needed because if view is switched, breaks expanded row toggling.
4490 useEffect ( ( ) => {
45- setLoading ( true ) ;
91+ setExpandedRows ( [ ] )
92+ } , [ display ] ) ;
93+
4694
47- // Create rows to set into table.
48- const rows = jobs . map ( ( job ) => ( {
49- ...job ,
50- weather : getWeatherIndex ( job ) ,
51- } ) ) ;
52- setRows ( rows ) ;
53- setLoading ( false ) ;
54- } , [ jobs ] ) ;
5595
5696 const toggleRow = ( rowData ) => {
5797 const isRowExpanded = expandedRows . includes ( rowData ) ;
@@ -66,6 +106,11 @@ export default function Home() {
66106 setExpandedRows ( updatedExpandedRows ) ;
67107 } ;
68108
109+ const tabClass = ( active ) => `tab md:px-4 px-2 py-2 border-b-2 focus:outline-none
110+ ${ active ? "border-blue-500 bg-gray-300"
111+ : "border-gray-300 bg-white hover:bg-gray-100" } `;
112+
113+
69114 // Template for rendering the Name column as a clickable item
70115 const nameTemplate = ( rowData ) => {
71116 return (
@@ -76,7 +121,10 @@ export default function Home() {
76121 } ;
77122
78123 const rowExpansionTemplate = ( data ) => {
79- const job = jobs . find ( ( job ) => job . name === data . name ) ;
124+ const job = ( display === "nightly"
125+ ? jobs
126+ : checks ) . find ( ( job ) => job . name === data . name ) ;
127+
80128
81129 // Prepare run data
82130 const runs = [ ] ;
@@ -120,67 +168,126 @@ export default function Home() {
120168 ) ;
121169 } ;
122170
123- const renderTable = ( ) => (
171+ // Render table for nightly view.
172+ const renderNightlyTable = ( ) => (
124173 < DataTable
125- value = { rows }
174+ value = { rowsNightly }
126175 expandedRows = { expandedRows }
127176 stripedRows
128177 rowExpansionTemplate = { rowExpansionTemplate }
129178 onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
130179 loading = { loading }
131180 emptyMessage = "No results found."
132181 >
133- < Column expander style = { { width : "5rem" } } />
182+ < Column expander />
134183 < Column
135184 field = "name"
136185 header = "Name"
137186 body = { nameTemplate }
187+ className = "select-all"
138188 filter
139189 sortable
140- maxConstraints = { 4 }
141- filterHeader = "Filter by Name"
142- filterPlaceholder = "Search..."
143190 />
144- < Column field = "required" header = "Required" sortable />
145- < Column field = "runs" header = "Runs" sortable />
146- < Column field = "fails" header = "Fails" sortable />
147- < Column field = "skips" header = "Skips" sortable />
191+ < Column field = "required" header = "Required" sortable />
192+ < Column
193+ field = "runs"
194+ header = "Runs"
195+ className = "whitespace-nowrap px-2"
196+ sortable />
197+ < Column field = "fails" header = "Fails" sortable />
198+ < Column field = "skips" header = "Skips" sortable />
199+ < Column
200+ field = "weather"
201+ header = "Weather"
202+ body = { weatherTemplate }
203+ sortable />
204+ </ DataTable >
205+ ) ;
206+
207+ const renderPRTable = ( ) => (
208+ < DataTable
209+ value = { rowsPR }
210+ expandedRows = { expandedRows }
211+ stripedRows
212+ rowExpansionTemplate = { rowExpansionTemplate }
213+ onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
214+ loading = { loading }
215+ emptyMessage = "No results found."
216+ >
217+ < Column expander />
148218 < Column
149- field = "weather"
150- header = "Weather"
151- body = { weatherTemplate }
219+ field = "name"
220+ header = "Name"
221+ body = { nameTemplate }
222+ className = "select-all"
223+ filter
152224 sortable
153225 />
226+ < Column field = "required" header = "Required" sortable />
227+ < Column
228+ field = "runs"
229+ header = "Runs"
230+ className = "whitespace-nowrap px-2"
231+ sortable />
232+ < Column field = "fails" header = "Fails" sortable />
233+ < Column field = "skips" header = "Skips" sortable />
234+ < Column
235+ field = "weather"
236+ header = "Weather"
237+ body = { weatherTemplate }
238+ sortable />
154239 </ DataTable >
155240 ) ;
156241
242+
157243 return (
158- < div className = "text-center" >
159- < h1
160- className = {
161- "text-4xl mt-4 mb-0 underline text-inherit hover:text-blue-500"
162- }
163- >
164- < a
165- href = {
166- "https://github.com/kata-containers/kata-containers/" +
167- "actions/workflows/ci-nightly.yaml"
168- }
169- target = "_blank"
170- rel = "noopener noreferrer"
171- >
172- Kata CI Dashboard
173- </ a >
174- </ h1 >
175-
176- < main
177- className = {
178- "m-0 h-full p-4 overflow-x-hidden overflow-y-auto bg-surface-ground font-normal text-text-color antialiased select-text"
179- }
180- >
181- < div > { renderTable ( ) } </ div >
182- < div className = "mt-4 text-lg" > Total Rows: { rows . length } </ div >
183- </ main >
184- </ div >
244+ < >
245+
246+ < title > Kata CI Dashboard</ title >
247+ < div className = "text-center text-xs md:text-base" >
248+ < h1 className = { "text-4xl mt-4 ml-4 mb-6 underline text-inherit \
249+ hover:text-blue-500" } >
250+ < a
251+ href = { display === 'nightly'
252+ ? "https://github.com/kata-containers/kata-containers/" +
253+ "actions/workflows/ci-nightly.yaml"
254+ : "https://github.com/kata-containers/kata-containers/" +
255+ "actions/workflows/ci-on-push.yaml" }
256+ target = "_blank"
257+ rel = "noopener noreferrer"
258+ >
259+ Kata CI Dashboard
260+ </ a >
261+ </ h1 >
262+
263+ < div className = "flex flex-wrap mt-2 p-4 md:text-base text-xs" >
264+ < div className = "space-x-2 pb-2 pr-3 mx-auto flex" >
265+ < button
266+ className = { tabClass ( display === "nightly" ) }
267+ onClick = { ( ) => {
268+ setDisplay ( "nightly" ) ;
269+ } } >
270+ Nightly Jobs
271+ </ button >
272+ < button
273+ className = { tabClass ( display === "prchecks" ) }
274+ onClick = { ( ) => {
275+ setDisplay ( "prchecks" ) ;
276+ } } >
277+ PR Checks
278+ </ button >
279+ </ div >
280+ </ div >
281+
282+ < div className = "mt-1 text-center md:text-lg text-base" >
283+ Total Rows: { display === "prchecks" ? rowsPR . length : rowsNightly . length }
284+ </ div >
285+
286+ < main className = { "m-0 h-full px-4 overflow-x-hidden overflow-y-auto \
287+ bg-surface-ground antialiased select-text" } >
288+ < div > { display === "prchecks" ? renderPRTable ( ) : renderNightlyTable ( ) } </ div >
289+ </ main >
290+ </ div >
291+ </ >
185292 ) ;
186- }
293+ }
0 commit comments