@@ -6,31 +6,38 @@ import { weatherTemplate, getWeatherIndex } from "../components/weatherTemplate"
6
6
7
7
8
8
export default function Home ( ) {
9
- const [ loading , setLoading ] = useState ( true ) ;
10
- const [ jobs , setJobs ] = useState ( [ ] ) ;
11
- const [ rows , setRows ] = useState ( [ ] ) ;
12
- const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
9
+ const [ loading , setLoading ] = useState ( true ) ;
10
+ const [ jobs , setJobs ] = 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
+
13
17
14
18
useEffect ( ( ) => {
15
19
const fetchData = async ( ) => {
16
- let data = { } ;
20
+ let nightlyData = { } ;
21
+ let prData = { } ;
17
22
18
23
if ( process . env . NODE_ENV === "development" ) {
19
- data = ( await import ( "../job_stats.json" ) ) . default ;
24
+ nightlyData = ( await import ( "../localData/job_stats.json" ) ) . default ;
25
+ prData = ( await import ( "../localData/check_stats.json" ) ) . default ;
20
26
} else {
21
- const response = await fetch (
27
+ nightlyData = await fetch (
22
28
"https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
23
29
"/refs/heads/latest-dashboard-data/data/job_stats.json"
24
- ) ;
25
- 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 ( ) ) ;
26
35
}
27
36
28
37
try {
29
- const jobData = Object . keys ( data ) . map ( ( key ) => {
30
- const job = data [ key ] ;
31
- return { name : key , ...job } ;
32
- } ) ;
33
- setJobs ( jobData ) ;
38
+ const mapData = ( data ) => Object . keys ( data ) . map ( ( key ) => ( { name : key , ...data [ key ] } ) ) ;
39
+ setJobs ( mapData ( nightlyData ) ) ;
40
+ setChecks ( mapData ( prData ) ) ;
34
41
} catch ( error ) {
35
42
// TODO: Add pop-up/toast message for error
36
43
console . error ( "Error fetching data:" , error ) ;
@@ -42,17 +49,50 @@ export default function Home() {
42
49
fetchData ( ) ;
43
50
} , [ ] ) ;
44
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.
45
91
useEffect ( ( ) => {
46
- setLoading ( true ) ;
92
+ setExpandedRows ( [ ] )
93
+ } , [ display ] ) ;
94
+
47
95
48
- // Create rows to set into table.
49
- const rows = jobs . map ( ( job ) => ( {
50
- ...job ,
51
- weather : getWeatherIndex ( job ) ,
52
- } ) ) ;
53
- setRows ( rows ) ;
54
- setLoading ( false ) ;
55
- } , [ jobs ] ) ;
56
96
57
97
const toggleRow = ( rowData ) => {
58
98
const isRowExpanded = expandedRows . includes ( rowData ) ;
@@ -67,6 +107,11 @@ export default function Home() {
67
107
setExpandedRows ( updatedExpandedRows ) ;
68
108
} ;
69
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
+
70
115
// Template for rendering the Name column as a clickable item
71
116
const nameTemplate = ( rowData ) => {
72
117
return (
@@ -77,7 +122,10 @@ export default function Home() {
77
122
} ;
78
123
79
124
const rowExpansionTemplate = ( data ) => {
80
- 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
+
81
129
82
130
// Prepare run data
83
131
const runs = [ ] ;
@@ -121,71 +169,128 @@ export default function Home() {
121
169
) ;
122
170
} ;
123
171
124
- const renderTable = ( ) => (
172
+ // Render table for nightly view.
173
+ const renderNightlyTable = ( ) => (
125
174
< DataTable
126
- value = { rows }
175
+ value = { rowsNightly }
127
176
expandedRows = { expandedRows }
128
177
stripedRows
129
178
rowExpansionTemplate = { rowExpansionTemplate }
130
179
onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
131
180
loading = { loading }
132
181
emptyMessage = "No results found."
133
182
>
134
- < Column expander style = { { width : "5rem" } } />
183
+ < Column expander />
135
184
< Column
136
185
field = "name"
137
186
header = "Name"
138
187
body = { nameTemplate }
188
+ className = "select-all"
139
189
filter
140
190
sortable
141
- maxConstraints = { 4 }
142
- filterHeader = "Filter by Name"
143
- filterPlaceholder = "Search..."
144
191
/>
145
- < Column field = "required" header = "Required" sortable />
146
- < Column field = "runs" header = "Runs" sortable />
147
- < Column field = "fails" header = "Fails" sortable />
148
- < 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 />
149
219
< Column
150
- field = "weather"
151
- header = "Weather"
152
- body = { weatherTemplate }
220
+ field = "name"
221
+ header = "Name"
222
+ body = { nameTemplate }
223
+ className = "select-all"
224
+ filter
153
225
sortable
154
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 />
155
240
</ DataTable >
156
241
) ;
157
242
243
+
158
244
return (
159
- < div className = "text-center" >
245
+ < >
246
+
160
247
< Head >
161
248
< title > Kata CI Dashboard</ title >
162
249
</ Head >
250
+ < div className = "text-center text-xs md:text-base" >
251
+ < h1 className = { "text-4xl mt-4 ml-4 mb-6 underline text-inherit \
252
+ hover:text-blue-500" } >
253
+ < a
254
+ href = { display === 'nightly'
255
+ ? "https://github.com/kata-containers/kata-containers/" +
256
+ "actions/workflows/ci-nightly.yaml"
257
+ : "https://github.com/kata-containers/kata-containers/" +
258
+ "actions/workflows/ci-on-push.yaml" }
259
+ target = "_blank"
260
+ rel = "noopener noreferrer"
261
+ >
262
+ Kata CI Dashboard
263
+ </ a >
264
+ </ h1 >
163
265
164
- < h1
165
- className = {
166
- "text-4xl mt-4 mb-0 underline text-inherit hover:text-blue-500"
167
- }
168
- >
169
- < a
170
- href = {
171
- "https://github.com/kata-containers/kata-containers/" +
172
- "actions/workflows/ci-nightly.yaml"
173
- }
174
- target = "_blank"
175
- rel = "noopener noreferrer"
176
- >
177
- Kata CI Dashboard
178
- </ a >
179
- </ h1 >
180
-
181
- < main
182
- className = {
183
- "m-0 h-full p-4 overflow-x-hidden overflow-y-auto bg-surface-ground font-normal text-text-color antialiased select-text"
184
- }
185
- >
186
- < div > { renderTable ( ) } </ div >
187
- < div className = "mt-4 text-lg" > Total Rows: { rows . length } </ div >
188
- </ main >
189
- </ div >
266
+ < div className = "flex flex-wrap mt-2 p-4 md:text-base text-xs" >
267
+ < div className = "space-x-2 pb-2 pr-3 mx-auto flex" >
268
+ < button
269
+ className = { tabClass ( display === "nightly" ) }
270
+ onClick = { ( ) => {
271
+ setDisplay ( "nightly" ) ;
272
+ } } >
273
+ Nightly Jobs
274
+ </ button >
275
+ < button
276
+ className = { tabClass ( display === "prchecks" ) }
277
+ onClick = { ( ) => {
278
+ setDisplay ( "prchecks" ) ;
279
+ } } >
280
+ PR Checks
281
+ </ button >
282
+ </ div >
283
+ </ div >
284
+
285
+ < div className = "mt-1 text-center md:text-lg text-base" >
286
+ Total Rows: { display === "prchecks" ? rowsPR . length : rowsNightly . length }
287
+ </ div >
288
+
289
+ < main className = { "m-0 h-full px-4 overflow-x-hidden overflow-y-auto \
290
+ bg-surface-ground antialiased select-text" } >
291
+ < div > { display === "prchecks" ? renderPRTable ( ) : renderNightlyTable ( ) } </ div >
292
+ </ main >
293
+ </ div >
294
+ </ >
190
295
) ;
191
- }
296
+ }
0 commit comments