@@ -5,17 +5,20 @@ import Head from "next/head";
55import { weatherTemplate , getWeatherIndex } from "../components/weatherTemplate" ;
66import { OverlayPanel } from 'primereact/overlaypanel' ;
77import MaintainerMapping from "../maintainers.yml" ;
8+ import { basePath } from "../next.config.js" ;
89
910
1011export default function Home ( ) {
1112 const [ loading , setLoading ] = useState ( true ) ;
1213 const [ checks , setChecks ] = useState ( [ ] ) ;
1314 const [ jobs , setJobs ] = useState ( [ ] ) ;
14- const [ rowsPR , setRowsPR ] = useState ( [ ] ) ;
15- const [ rowsNightly , setRowsNightly ] = useState ( [ ] ) ;
15+ const [ rowsSingle , setRowsSingle ] = useState ( [ ] ) ;
16+ const [ rowsPR , setRowsPR ] = useState ( [ ] ) ;
17+ const [ rowsNightly , setRowsNightly ] = useState ( [ ] ) ;
1618 const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
1719 const [ requiredFilter , setRequiredFilter ] = useState ( false ) ;
18- const [ display , setDisplay ] = useState ( "nightly" ) ;
20+ const [ display , setDisplay ] = useState ( "nightly" ) ;
21+ const [ selectedPR , setSelectedPR ] = useState ( "" ) ;
1922
2023 useEffect ( ( ) => {
2124 const fetchData = async ( ) => {
@@ -53,6 +56,19 @@ export default function Home() {
5356 fetchData ( ) ;
5457 } , [ ] ) ;
5558
59+ // Set the display based on the URL.
60+ useEffect ( ( ) => {
61+ const initialDisplay = new URLSearchParams ( window . location . search ) . get ( "display" ) ;
62+ if ( initialDisplay ) {
63+ if ( initialDisplay === "prsingle" ) {
64+ const initialPR = new URLSearchParams ( window . location . search ) . get ( "pr" ) ;
65+ if ( initialPR ) {
66+ setSelectedPR ( initialPR ) ;
67+ }
68+ }
69+ setDisplay ( initialDisplay ) ;
70+ }
71+ } , [ ] ) ;
5672
5773 // Filter based on required tag.
5874 const filterRequired = ( filteredJobs ) => {
@@ -103,12 +119,47 @@ export default function Home() {
103119 setLoading ( false ) ;
104120 } , [ checks , requiredFilter ] ) ;
105121
122+ // Filter and set the rows for Single PR view.
123+ useEffect ( ( ) => {
124+ setLoading ( true ) ;
125+
126+ let filteredData = filterRequired ( checks ) ;
127+
128+ filteredData = filteredData . map ( ( check ) => {
129+ // Only if the check include the run number, add it to the data.
130+ const index = check . run_nums . indexOf ( Number ( selectedPR ) ) ;
131+ return index !== - 1
132+ ? {
133+ name : check . name ,
134+ required : check . required ,
135+ result : check . results [ index ] ,
136+ runs : check . reruns [ index ] + 1 ,
137+ }
138+ : null ;
139+ } ) . filter ( Boolean ) ;
140+
141+ setRowsSingle ( filteredData ) ;
142+ setLoading ( false ) ;
143+ } , [ checks , selectedPR , requiredFilter ] ) ;
144+
106145 // Close all rows on view switch.
107146 // Needed because if view is switched, breaks expanded row toggling.
108147 useEffect ( ( ) => {
109148 setExpandedRows ( [ ] )
110149 } , [ display ] ) ;
111150
151+ // Update the URL on display change
152+ const updateUrl = ( view , pr ) => {
153+ const path = new URLSearchParams ( ) ;
154+ path . append ( "display" , view ) ;
155+ // Add PR number Single PR view and a PR is provided
156+ if ( view === "prsingle" && pr ) {
157+ path . append ( "pr" , pr ) ;
158+ }
159+ // Update the URL without reloading
160+ window . history . pushState ( { } , '' , `${ basePath } /?${ path . toString ( ) } ` ) ;
161+ } ;
162+
112163 const toggleRow = ( rowData ) => {
113164 const isRowExpanded = expandedRows . includes ( rowData ) ;
114165
@@ -199,26 +250,6 @@ export default function Home() {
199250 } , { } ) ;
200251
201252
202- // Find maintainers for the given job
203- const maintainerData = MaintainerMapping . mappings
204- . filter ( ( { regex } ) => new RegExp ( regex ) . test ( job . name ) )
205- . flatMap ( ( match ) =>
206- match . owners . map ( ( owner ) => ( {
207- ...owner ,
208- group : match . group ,
209- } ) )
210- ) ;
211-
212- // Group maintainers by their group name
213- const groupedMaintainers = maintainerData . reduce ( ( acc , owner ) => {
214- if ( ! acc [ owner . group ] ) {
215- acc [ owner . group ] = [ ] ;
216- }
217- acc [ owner . group ] . push ( owner ) ;
218- return acc ;
219- } , { } ) ;
220-
221-
222253 return (
223254 < div key = { `${ job . name } -runs` } className = "p-3 bg-gray-100" >
224255 { /* Display last 10 runs */ }
@@ -538,6 +569,46 @@ export default function Home() {
538569 </ DataTable >
539570 ) ;
540571
572+ // Make a list of all unique run numbers in the check data.
573+ const runNumOptions = [ ...new Set ( checks . flatMap ( check => check . run_nums ) ) ] . sort ( ( a , b ) => b - a ) ;
574+
575+ // Render table for prsingle view
576+ const renderSingleViewTable = ( ) => (
577+ < DataTable
578+ value = { rowsSingle }
579+ expandedRows = { expandedRows }
580+ stripedRows
581+ rowExpansionTemplate = { rowExpansionTemplate }
582+ onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
583+ loading = { loading }
584+ emptyMessage = { selectedPR . length == 0 ? "Select a Pull Request above." : "No results found." }
585+ >
586+ < Column expander />
587+ < Column
588+ field = "name"
589+ header = "Name"
590+ body = { nameTemplate }
591+ className = "select-all"
592+ sortable
593+ />
594+ < Column
595+ field = "required"
596+ header = "Required"
597+ sortable
598+ />
599+ < Column
600+ field = "result"
601+ header = "Result"
602+ sortable
603+ />
604+ < Column
605+ field = "runs"
606+ header = "Total Runs"
607+ sortable
608+ />
609+ </ DataTable >
610+ ) ;
611+
541612 return (
542613 < div className = "text-center" >
543614 < Head >
@@ -563,21 +634,49 @@ export default function Home() {
563634 </ h1 >
564635 < div className = "flex flex-wrap mt-2 p-4 md:text-base text-xs" >
565636 < div className = "space-x-2 pb-2 pr-3 mx-auto flex" >
566- < button
567- className = { tabClass ( display === "nightly" ) }
568- onClick = { ( ) => {
569- setDisplay ( "nightly" ) ;
570- } } >
571- Nightly Jobs
572- </ button >
573- < button
574- className = { tabClass ( display === "prchecks" ) }
575- onClick = { ( ) => {
576- setDisplay ( "prchecks" ) ;
577- } } >
578- PR Checks
579- </ button >
580- </ div >
637+ < button
638+ className = { tabClass ( display === "nightly" ) }
639+ onClick = { ( ) => {
640+ setDisplay ( "nightly" ) ;
641+ updateUrl ( "nightly" ) ;
642+
643+ } } >
644+ Nightly Jobs
645+ </ button >
646+ < button
647+ className = { tabClass ( display === "prchecks" ) }
648+ onClick = { ( ) => {
649+ setDisplay ( "prchecks" ) ;
650+ updateUrl ( "prchecks" ) ;
651+ } } >
652+ PR Checks
653+ </ button >
654+ < button
655+ className = { tabClass ( display === "prsingle" ) }
656+ onClick = { ( ) => {
657+ setDisplay ( "prsingle" ) ;
658+ updateUrl ( "prsingle" , selectedPR ) ;
659+ } } >
660+ Single PR
661+ </ button >
662+ { display === "prsingle" && (
663+ < div className = "bg-blue-500 p-2 rounded-xl h-fit" >
664+ < select
665+ id = "selectedrun"
666+ className = "px-1 h-fit rounded-lg"
667+ onChange = { ( e ) => {
668+ setSelectedPR ( e . target . value ) ;
669+ updateUrl ( "prsingle" , e . target . value ) ;
670+ } }
671+ value = { selectedPR } >
672+ < option value = "" > Select PR</ option >
673+ { runNumOptions . map ( num => (
674+ < option key = { num } value = { num } > #{ num } </ option >
675+ ) ) }
676+ </ select >
677+ </ div >
678+ ) }
679+ </ div >
581680 </ div >
582681
583682
@@ -589,9 +688,9 @@ export default function Home() {
589688 Required Jobs Only
590689 </ button >
591690 < div className = "mt-4 text-center md:text-lg text-base" >
592- Total Rows: { display === "prchecks" ? rowsPR . length : rowsNightly . length }
691+ Total Rows: { display === "prsingle" ? rowsSingle . length : display === "prchecks" ? rowsPR . length : rowsNightly . length }
593692 </ div >
594- < div > { display === "prchecks" ? renderPRTable ( ) : renderNightlyTable ( ) } </ div >
693+ < div > { display === "prsingle" ? renderSingleViewTable ( ) : display === " prchecks" ? renderPRTable ( ) : renderNightlyTable ( ) } </ div >
595694 </ div >
596695 </ div >
597696 ) ;
0 commit comments