@@ -9,31 +9,39 @@ import MaintainerMapping from "../maintainers.yml";
9
9
10
10
export default function Home ( ) {
11
11
const [ loading , setLoading ] = useState ( true ) ;
12
+ const [ checks , setChecks ] = useState ( [ ] ) ;
12
13
const [ jobs , setJobs ] = useState ( [ ] ) ;
13
- const [ rows , setRows ] = useState ( [ ] ) ;
14
+ const [ rowsPR , setRowsPR ] = useState ( [ ] ) ;
15
+ const [ rowsNightly , setRowsNightly ] = useState ( [ ] ) ;
14
16
const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
15
17
const [ requiredFilter , setRequiredFilter ] = useState ( false ) ;
18
+ const [ display , setDisplay ] = useState ( "nightly" ) ;
16
19
17
20
useEffect ( ( ) => {
18
21
const fetchData = async ( ) => {
19
- let data = { } ;
22
+ let nightlyData = { } ;
23
+ let prData = { } ;
20
24
21
25
if ( process . env . NODE_ENV === "development" ) {
22
- data = ( await import ( "../localData/job_stats.json" ) ) . default ;
26
+ nightlyData = ( await import ( "../localData/job_stats.json" ) ) . default ;
27
+ prData = ( await import ( "../localData/check_stats.json" ) ) . default ;
23
28
} else {
24
- const response = await fetch (
29
+ nightlyData = await fetch (
25
30
"https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
26
31
"/refs/heads/latest-dashboard-data/data/job_stats.json"
27
- ) ;
28
- data = await response . json ( ) ;
32
+ ) . then ( ( res ) => res . json ( ) ) ;
33
+ prData = await fetch (
34
+ "https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
35
+ "/refs/heads/latest-dashboard-data/data/check_stats.json"
36
+ ) . then ( ( res ) => res . json ( ) ) ;
29
37
}
30
38
31
39
try {
32
- const jobData = Object . keys ( data ) . map ( ( key ) => {
33
- const job = data [ key ] ;
34
- return { name : key , ... job } ;
35
- } ) ;
36
- setJobs ( jobData ) ;
40
+ const mapData = ( data ) => Object . keys ( data ) . map ( ( key ) =>
41
+ ( { name : key , ... data [ key ] } )
42
+ ) ;
43
+ setJobs ( mapData ( nightlyData ) ) ;
44
+ setChecks ( mapData ( prData ) ) ;
37
45
} catch ( error ) {
38
46
// TODO: Add pop-up/toast message for error
39
47
console . error ( "Error fetching data:" , error ) ;
@@ -54,14 +62,12 @@ export default function Home() {
54
62
return filteredJobs ;
55
63
} ;
56
64
65
+ // Filter and set the rows for Nightly view.
57
66
useEffect ( ( ) => {
58
67
setLoading ( true ) ;
59
-
60
- // Filter based on required tag.
61
68
let filteredJobs = filterRequired ( jobs ) ;
62
-
63
69
//Set the rows for the table.
64
- setRows (
70
+ setRowsNightly (
65
71
filteredJobs . map ( ( job ) => ( {
66
72
name : job . name ,
67
73
runs : job . runs ,
@@ -74,6 +80,31 @@ export default function Home() {
74
80
setLoading ( false ) ;
75
81
} , [ jobs , requiredFilter ] ) ;
76
82
83
+ // Filter and set the rows for PR Checks view.
84
+ useEffect ( ( ) => {
85
+ setLoading ( true ) ;
86
+ let filteredChecks = filterRequired ( checks )
87
+
88
+ //Set the rows for the table.
89
+ setRowsPR (
90
+ filteredChecks . map ( ( check ) => ( {
91
+ name : check . name ,
92
+ runs : check . runs ,
93
+ fails : check . fails ,
94
+ skips : check . skips ,
95
+ required : check . required ,
96
+ weather : getWeatherIndex ( check ) ,
97
+ } ) )
98
+ ) ;
99
+ setLoading ( false ) ;
100
+ } , [ checks , requiredFilter ] ) ;
101
+
102
+ // Close all rows on view switch.
103
+ // Needed because if view is switched, breaks expanded row toggling.
104
+ useEffect ( ( ) => {
105
+ setExpandedRows ( [ ] )
106
+ } , [ display ] ) ;
107
+
77
108
const toggleRow = ( rowData ) => {
78
109
const isRowExpanded = expandedRows . includes ( rowData ) ;
79
110
@@ -91,6 +122,10 @@ export default function Home() {
91
122
${ active ? "border-blue-500 bg-blue-500 text-white"
92
123
: "border-gray-300 bg-white hover:bg-gray-100" } `;
93
124
125
+ const tabClass = ( active ) => `tab md:px-4 px-2 py-2 border-b-2 focus:outline-none
126
+ ${ active ? "border-blue-500 bg-gray-300"
127
+ : "border-gray-300 bg-white hover:bg-gray-100" } `;
128
+
94
129
95
130
// Template for rendering the Name column as a clickable item
96
131
const nameTemplate = ( rowData ) => {
@@ -104,7 +139,9 @@ export default function Home() {
104
139
const maintainRefs = useRef ( [ ] ) ;
105
140
106
141
const rowExpansionTemplate = ( data ) => {
107
- const job = jobs . find ( ( job ) => job . name === data . name ) ;
142
+ const job = ( display === "nightly"
143
+ ? jobs
144
+ : checks ) . find ( ( job ) => job . name === data . name ) ;
108
145
109
146
// Prepare run data
110
147
const runs = [ ] ;
@@ -115,7 +152,7 @@ export default function Home() {
115
152
url : job . urls [ i ] ,
116
153
} ) ;
117
154
}
118
-
155
+
119
156
// Find maintainers for the given job
120
157
const maintainerData = MaintainerMapping . mappings
121
158
. filter ( ( { regex } ) => new RegExp ( regex ) . test ( job . name ) )
@@ -135,6 +172,7 @@ export default function Home() {
135
172
return acc ;
136
173
} , { } ) ;
137
174
175
+
138
176
return (
139
177
< div key = { `${ job . name } -runs` } className = "p-3 bg-gray-100" >
140
178
{ /* Display last 10 runs */ }
@@ -149,7 +187,7 @@ export default function Home() {
149
187
: "⚠️" ;
150
188
return (
151
189
< span key = { `${ job . name } -runs-${ run . run_num } ` } >
152
- < a href = { run . url } >
190
+ < a href = { run . url } target = "_blank" rel = "noopener noreferrer" >
153
191
{ emoji } { run . run_num }
154
192
</ a >
155
193
@@ -251,9 +289,10 @@ export default function Home() {
251
289
) ;
252
290
} ;
253
291
254
- const renderTable = ( ) => (
292
+ // Render table for nightly view.
293
+ const renderNightlyTable = ( ) => (
255
294
< DataTable
256
- value = { rows }
295
+ value = { rowsNightly }
257
296
expandedRows = { expandedRows }
258
297
stripedRows
259
298
rowExpansionTemplate = { rowExpansionTemplate }
@@ -263,27 +302,63 @@ export default function Home() {
263
302
sortField = "fails"
264
303
sortOrder = { - 1 }
265
304
>
266
- < Column expander style = { { width : "5rem" } } />
305
+ < Column expander />
267
306
< Column
268
307
field = "name"
269
308
header = "Name"
270
309
body = { nameTemplate }
271
- filter
310
+ className = "select-text"
272
311
sortable
273
- maxConstraints = { 4 }
274
- filterHeader = "Filter by Name"
275
- filterPlaceholder = "Search..."
276
312
/>
277
- < Column field = "required" header = "Required" sortable />
278
- < Column field = "runs" header = "Runs" sortable />
279
- < Column field = "fails" header = "Fails" sortable />
280
- < Column field = "skips" header = "Skips" sortable />
313
+ < Column field = "required" header = "Required" sortable />
314
+ < Column
315
+ field = "runs"
316
+ header = "Runs"
317
+ className = "whitespace-nowrap px-2"
318
+ sortable />
319
+ < Column field = "fails" header = "Fails" sortable />
320
+ < Column field = "skips" header = "Skips" sortable />
321
+ < Column
322
+ field = "weather"
323
+ header = "Weather"
324
+ body = { weatherTemplate }
325
+ sortable />
326
+ </ DataTable >
327
+ ) ;
328
+
329
+ const renderPRTable = ( ) => (
330
+ < DataTable
331
+ value = { rowsPR }
332
+ expandedRows = { expandedRows }
333
+ stripedRows
334
+ rowExpansionTemplate = { rowExpansionTemplate }
335
+ onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
336
+ loading = { loading }
337
+ emptyMessage = "No results found."
338
+ sortField = "fails"
339
+ sortOrder = { - 1 }
340
+ >
341
+ < Column expander />
281
342
< Column
282
- field = "weather"
283
- header = "Weather"
284
- body = { weatherTemplate }
343
+ field = "name"
344
+ header = "Name"
345
+ body = { nameTemplate }
346
+ className = "select-text"
285
347
sortable
286
348
/>
349
+ < Column field = "required" header = "Required" sortable />
350
+ < Column
351
+ field = "runs"
352
+ header = "Runs"
353
+ className = "whitespace-nowrap px-2"
354
+ sortable />
355
+ < Column field = "fails" header = "Fails" sortable />
356
+ < Column field = "skips" header = "Skips" sortable />
357
+ < Column
358
+ field = "weather"
359
+ header = "Weather"
360
+ body = { weatherTemplate }
361
+ sortable />
287
362
</ DataTable >
288
363
) ;
289
364
@@ -299,30 +374,49 @@ export default function Home() {
299
374
}
300
375
>
301
376
< a
302
- href = {
303
- "https://github.com/kata-containers/kata-containers/" +
304
- "actions/workflows/ci-nightly.yaml"
305
- }
306
- target = "_blank"
307
- rel = "noopener noreferrer"
308
- >
309
- Kata CI Dashboard
310
- </ a >
377
+ href = { display === 'nightly'
378
+ ? "https://github.com/kata-containers/kata-containers/" +
379
+ "actions/workflows/ci-nightly.yaml"
380
+ : "https://github.com/kata-containers/kata-containers/" +
381
+ "/pulls?state=closed" }
382
+ target = "_blank"
383
+ rel = "noopener noreferrer"
384
+ >
385
+ Kata CI Dashboard
386
+ </ a >
311
387
</ h1 >
388
+ < div className = "flex flex-wrap mt-2 p-4 md:text-base text-xs" >
389
+ < div className = "space-x-2 pb-2 pr-3 mx-auto flex" >
390
+ < button
391
+ className = { tabClass ( display === "nightly" ) }
392
+ onClick = { ( ) => {
393
+ setDisplay ( "nightly" ) ;
394
+ } } >
395
+ Nightly Jobs
396
+ </ button >
397
+ < button
398
+ className = { tabClass ( display === "prchecks" ) }
399
+ onClick = { ( ) => {
400
+ setDisplay ( "prchecks" ) ;
401
+ } } >
402
+ PR Checks
403
+ </ button >
404
+ </ div >
405
+ </ div >
312
406
313
- < main
314
- className = {
315
- "m-0 h-full p-4 overflow-x-hidden overflow-y-auto bg-surface-ground font-normal text-text-color antialiased select-text"
316
- }
317
- >
407
+
408
+ < div className = { "m-0 h-full px-4 overflow-x-hidden overflow-y-auto \
409
+ bg-surface-ground antialiased select-text" } >
318
410
< button
319
- className = { buttonClass ( requiredFilter ) }
320
- onClick = { ( ) => setRequiredFilter ( ! requiredFilter ) } >
321
- Required Jobs Only
411
+ className = { buttonClass ( requiredFilter ) }
412
+ onClick = { ( ) => setRequiredFilter ( ! requiredFilter ) } >
413
+ Required Jobs Only
322
414
</ button >
323
- < div className = "mt-4 text-lg" > Total Rows: { rows . length } </ div >
324
- < div > { renderTable ( ) } </ div >
325
- </ main >
415
+ < div className = "mt-4 text-center md:text-lg text-base" >
416
+ Total Rows: { display === "prchecks" ? rowsPR . length : rowsNightly . length }
417
+ </ div >
418
+ < div > { display === "prchecks" ? renderPRTable ( ) : renderNightlyTable ( ) } </ div >
419
+ </ div >
326
420
</ div >
327
421
) ;
328
422
}
0 commit comments