@@ -6,31 +6,38 @@ import { weatherTemplate, getWeatherIndex } from "../components/weatherTemplate"
66
77
88export 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+
1317
1418 useEffect ( ( ) => {
1519 const fetchData = async ( ) => {
16- let data = { } ;
20+ let nightlyData = { } ;
21+ let prData = { } ;
1722
1823 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 ;
2026 } else {
21- const response = await fetch (
27+ nightlyData = await fetch (
2228 "https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
2329 "/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 ( ) ) ;
2635 }
2736
2837 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 ) ) ;
3441 } catch ( error ) {
3542 // TODO: Add pop-up/toast message for error
3643 console . error ( "Error fetching data:" , error ) ;
@@ -42,17 +49,50 @@ export default function Home() {
4249 fetchData ( ) ;
4350 } , [ ] ) ;
4451
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.
4591 useEffect ( ( ) => {
46- setLoading ( true ) ;
92+ setExpandedRows ( [ ] )
93+ } , [ display ] ) ;
94+
4795
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 ] ) ;
5696
5797 const toggleRow = ( rowData ) => {
5898 const isRowExpanded = expandedRows . includes ( rowData ) ;
@@ -67,6 +107,11 @@ export default function Home() {
67107 setExpandedRows ( updatedExpandedRows ) ;
68108 } ;
69109
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+
70115 // Template for rendering the Name column as a clickable item
71116 const nameTemplate = ( rowData ) => {
72117 return (
@@ -77,7 +122,10 @@ export default function Home() {
77122 } ;
78123
79124 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+
81129
82130 // Prepare run data
83131 const runs = [ ] ;
@@ -121,71 +169,128 @@ export default function Home() {
121169 ) ;
122170 } ;
123171
124- const renderTable = ( ) => (
172+ // Render table for nightly view.
173+ const renderNightlyTable = ( ) => (
125174 < DataTable
126- value = { rows }
175+ value = { rowsNightly }
127176 expandedRows = { expandedRows }
128177 stripedRows
129178 rowExpansionTemplate = { rowExpansionTemplate }
130179 onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
131180 loading = { loading }
132181 emptyMessage = "No results found."
133182 >
134- < Column expander style = { { width : "5rem" } } />
183+ < Column expander />
135184 < Column
136185 field = "name"
137186 header = "Name"
138187 body = { nameTemplate }
188+ className = "select-all"
139189 filter
140190 sortable
141- maxConstraints = { 4 }
142- filterHeader = "Filter by Name"
143- filterPlaceholder = "Search..."
144191 />
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 />
149219 < 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
153225 sortable
154226 />
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 />
155240 </ DataTable >
156241 ) ;
157242
243+
158244 return (
159- < div className = "text-center" >
245+ < >
246+
160247 < Head >
161248 < title > Kata CI Dashboard</ title >
162249 </ 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 >
163265
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+ </ >
190295 ) ;
191- }
296+ }
0 commit comments