1
+
1
2
import { useEffect , useState } from "react" ;
2
3
import { DataTable } from "primereact/datatable" ;
3
4
import { Column } from "primereact/column" ;
@@ -7,29 +8,36 @@ import { weatherTemplate, getWeatherIndex } from "../components/weatherTemplate"
7
8
export default function Home ( ) {
8
9
const [ loading , setLoading ] = useState ( true ) ;
9
10
const [ jobs , setJobs ] = useState ( [ ] ) ;
10
- const [ rows , setRows ] = useState ( [ ] ) ;
11
- const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
11
+ const [ checks , setChecks ] = useState ( [ ] ) ;
12
+ const [ rowsPR , setRowsPR ] = useState ( [ ] ) ;
13
+ const [ rowsNightly , setRowsNightly ] = useState ( [ ] ) ;
14
+ const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
15
+ const [ display , setDisplay ] = useState ( "nightly" ) ;
16
+
12
17
13
18
useEffect ( ( ) => {
14
19
const fetchData = async ( ) => {
15
- let data = { } ;
20
+ let nightlyData = { } ;
21
+ let prData = { } ;
16
22
17
23
if ( process . env . NODE_ENV === "development" ) {
18
- data = ( await import ( "../job_stats.json" ) ) . default ;
24
+ nightlyData = ( await import ( "../data/job_stats.json" ) ) . default ;
25
+ prData = ( await import ( "../data/check_stats.json" ) ) . default ;
19
26
} else {
20
- const response = await fetch (
27
+ nightlyData = await fetch (
21
28
"https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
22
29
"/refs/heads/latest-dashboard-data/data/job_stats.json"
23
- ) ;
24
- data = await response . json ( ) ;
30
+ ) . then ( ( res ) => res . json ( ) ) ;
31
+ prData = await fetch (
32
+ "https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
33
+ "/refs/heads/latest-dashboard-data/data/check_stats.json"
34
+ ) . then ( ( res ) => res . json ( ) ) ;
25
35
}
26
36
27
37
try {
28
- const jobData = Object . keys ( data ) . map ( ( key ) => {
29
- const job = data [ key ] ;
30
- return { name : key , ...job } ;
31
- } ) ;
32
- setJobs ( jobData ) ;
38
+ const mapData = ( data ) => Object . keys ( data ) . map ( ( key ) => ( { name : key , ...data [ key ] } ) ) ;
39
+ setJobs ( mapData ( nightlyData ) ) ;
40
+ setChecks ( mapData ( prData ) ) ;
33
41
} catch ( error ) {
34
42
// TODO: Add pop-up/toast message for error
35
43
console . error ( "Error fetching data:" , error ) ;
@@ -41,17 +49,50 @@ export default function Home() {
41
49
fetchData ( ) ;
42
50
} , [ ] ) ;
43
51
52
+ // Filter and set the rows for Nightly view.
53
+ useEffect ( ( ) => {
54
+ setLoading ( true ) ;
55
+ let filteredJobs = jobs ;
56
+ //Set the rows for the table.
57
+ setRowsNightly (
58
+ filteredJobs . map ( ( job ) => ( {
59
+ name : job . name ,
60
+ runs : job . runs ,
61
+ fails : job . fails ,
62
+ skips : job . skips ,
63
+ required : job . required ,
64
+ weather : getWeatherIndex ( job ) ,
65
+ } ) )
66
+ ) ;
67
+ setLoading ( false ) ;
68
+ } , [ jobs ] ) ;
69
+
70
+ // Filter and set the rows for PR Checks view.
71
+ useEffect ( ( ) => {
72
+ setLoading ( true ) ;
73
+ let filteredChecks = checks
74
+
75
+ //Set the rows for the table.
76
+ setRowsPR (
77
+ filteredChecks . map ( ( check ) => ( {
78
+ name : check . name ,
79
+ runs : check . runs ,
80
+ fails : check . fails ,
81
+ skips : check . skips ,
82
+ required : check . required ,
83
+ weather : getWeatherIndex ( check ) ,
84
+ } ) )
85
+ ) ;
86
+ setLoading ( false ) ;
87
+ } , [ checks ] ) ;
88
+
89
+ // Close all rows on view switch.
90
+ // Needed because if view is switched, breaks expanded row toggling.
44
91
useEffect ( ( ) => {
45
- setLoading ( true ) ;
92
+ setExpandedRows ( [ ] )
93
+ } , [ display ] ) ;
94
+
46
95
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 ] ) ;
55
96
56
97
const toggleRow = ( rowData ) => {
57
98
const isRowExpanded = expandedRows . includes ( rowData ) ;
@@ -66,6 +107,11 @@ export default function Home() {
66
107
setExpandedRows ( updatedExpandedRows ) ;
67
108
} ;
68
109
110
+ const tabClass = ( active ) => `tab md:px-4 px-2 py-2 border-b-2 focus:outline-none
111
+ ${ active ? "border-blue-500 bg-gray-300"
112
+ : "border-gray-300 bg-white hover:bg-gray-100" } `;
113
+
114
+
69
115
// Template for rendering the Name column as a clickable item
70
116
const nameTemplate = ( rowData ) => {
71
117
return (
@@ -76,7 +122,10 @@ export default function Home() {
76
122
} ;
77
123
78
124
const rowExpansionTemplate = ( data ) => {
79
- const job = jobs . find ( ( job ) => job . name === data . name ) ;
125
+ const job = ( display === "nightly"
126
+ ? jobs
127
+ : checks ) . find ( ( job ) => job . name === data . name ) ;
128
+
80
129
81
130
// Prepare run data
82
131
const runs = [ ] ;
@@ -120,67 +169,126 @@ export default function Home() {
120
169
) ;
121
170
} ;
122
171
123
- const renderTable = ( ) => (
172
+ // Render table for nightly view.
173
+ const renderNightlyTable = ( ) => (
124
174
< DataTable
125
- value = { rows }
175
+ value = { rowsNightly }
126
176
expandedRows = { expandedRows }
127
177
stripedRows
128
178
rowExpansionTemplate = { rowExpansionTemplate }
129
179
onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
130
180
loading = { loading }
131
181
emptyMessage = "No results found."
132
182
>
133
- < Column expander style = { { width : "5rem" } } />
183
+ < Column expander />
134
184
< Column
135
185
field = "name"
136
186
header = "Name"
137
187
body = { nameTemplate }
188
+ className = "select-all"
138
189
filter
139
190
sortable
140
- maxConstraints = { 4 }
141
- filterHeader = "Filter by Name"
142
- filterPlaceholder = "Search..."
143
191
/>
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 />
192
+ < Column field = "required" header = "Required" sortable />
193
+ < Column
194
+ field = "runs"
195
+ header = "Runs"
196
+ className = "whitespace-nowrap px-2"
197
+ sortable />
198
+ < Column field = "fails" header = "Fails" sortable />
199
+ < Column field = "skips" header = "Skips" sortable />
200
+ < Column
201
+ field = "weather"
202
+ header = "Weather"
203
+ body = { weatherTemplate }
204
+ sortable />
205
+ </ DataTable >
206
+ ) ;
207
+
208
+ const renderPRTable = ( ) => (
209
+ < DataTable
210
+ value = { rowsPR }
211
+ expandedRows = { expandedRows }
212
+ stripedRows
213
+ rowExpansionTemplate = { rowExpansionTemplate }
214
+ onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
215
+ loading = { loading }
216
+ emptyMessage = "No results found."
217
+ >
218
+ < Column expander />
148
219
< Column
149
- field = "weather"
150
- header = "Weather"
151
- body = { weatherTemplate }
220
+ field = "name"
221
+ header = "Name"
222
+ body = { nameTemplate }
223
+ className = "select-all"
224
+ filter
152
225
sortable
153
226
/>
227
+ < Column field = "required" header = "Required" sortable />
228
+ < Column
229
+ field = "runs"
230
+ header = "Runs"
231
+ className = "whitespace-nowrap px-2"
232
+ sortable />
233
+ < Column field = "fails" header = "Fails" sortable />
234
+ < Column field = "skips" header = "Skips" sortable />
235
+ < Column
236
+ field = "weather"
237
+ header = "Weather"
238
+ body = { weatherTemplate }
239
+ sortable />
154
240
</ DataTable >
155
241
) ;
156
242
243
+
157
244
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 >
245
+ < >
246
+
247
+ < title > Kata CI Dashboard</ title >
248
+ < div className = "text-center text-xs md:text-base" >
249
+ < h1 className = { "text-4xl mt-4 ml-4 mb-6 underline text-inherit \
250
+ hover:text-blue-500" } >
251
+ < a
252
+ href = { display === 'nightly'
253
+ ? "https://github.com/kata-containers/kata-containers/" +
254
+ "actions/workflows/ci-nightly.yaml"
255
+ : "https://github.com/kata-containers/kata-containers/" +
256
+ "actions/workflows/ci-on-push.yaml" }
257
+ target = "_blank"
258
+ rel = "noopener noreferrer"
259
+ >
260
+ Kata CI Dashboard
261
+ </ a >
262
+ </ h1 >
263
+
264
+ < div className = "flex flex-wrap mt-2 p-4 md:text-base text-xs" >
265
+ < div className = "space-x-2 pb-2 pr-3 mx-auto flex" >
266
+ < button
267
+ className = { tabClass ( display === "nightly" ) }
268
+ onClick = { ( ) => {
269
+ setDisplay ( "nightly" ) ;
270
+ } } >
271
+ Nightly Jobs
272
+ </ button >
273
+ < button
274
+ className = { tabClass ( display === "prchecks" ) }
275
+ onClick = { ( ) => {
276
+ setDisplay ( "prchecks" ) ;
277
+ } } >
278
+ PR Checks
279
+ </ button >
280
+ </ div >
281
+ </ div >
282
+
283
+ < div className = "mt-1 text-center md:text-lg text-base" >
284
+ Total Rows: { display === "prchecks" ? rowsPR . length : rowsNightly . length }
285
+ </ div >
286
+
287
+ < main className = { "m-0 h-full px-4 overflow-x-hidden overflow-y-auto \
288
+ bg-surface-ground antialiased select-text" } >
289
+ < div > { display === "prchecks" ? renderPRTable ( ) : renderNightlyTable ( ) } </ div >
290
+ </ main >
291
+ </ div >
292
+ </ >
185
293
) ;
186
- }
294
+ }
0 commit comments