@@ -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
@@ -432,6 +483,46 @@ export default function Home() {
432483 </ DataTable >
433484 ) ;
434485
486+ // Make a list of all unique run numbers in the check data.
487+ const runNumOptions = [ ...new Set ( checks . flatMap ( check => check . run_nums ) ) ] . sort ( ( a , b ) => b - a ) ;
488+
489+ // Render table for prsingle view
490+ const renderSingleViewTable = ( ) => (
491+ < DataTable
492+ value = { rowsSingle }
493+ expandedRows = { expandedRows }
494+ stripedRows
495+ rowExpansionTemplate = { rowExpansionTemplate }
496+ onRowToggle = { ( e ) => setExpandedRows ( e . data ) }
497+ loading = { loading }
498+ emptyMessage = { selectedPR . length == 0 ? "Select a Pull Request above." : "No results found." }
499+ >
500+ < Column expander />
501+ < Column
502+ field = "name"
503+ header = "Name"
504+ body = { nameTemplate }
505+ className = "select-all"
506+ sortable
507+ />
508+ < Column
509+ field = "required"
510+ header = "Required"
511+ sortable
512+ />
513+ < Column
514+ field = "result"
515+ header = "Result"
516+ sortable
517+ />
518+ < Column
519+ field = "runs"
520+ header = "Total Runs"
521+ sortable
522+ />
523+ </ DataTable >
524+ ) ;
525+
435526 return (
436527 < div className = "text-center" >
437528 < Head >
@@ -457,21 +548,49 @@ export default function Home() {
457548 </ h1 >
458549 < div className = "flex flex-wrap mt-2 p-4 md:text-base text-xs" >
459550 < div className = "space-x-2 pb-2 pr-3 mx-auto flex" >
460- < button
461- className = { tabClass ( display === "nightly" ) }
462- onClick = { ( ) => {
463- setDisplay ( "nightly" ) ;
464- } } >
465- Nightly Jobs
466- </ button >
467- < button
468- className = { tabClass ( display === "prchecks" ) }
469- onClick = { ( ) => {
470- setDisplay ( "prchecks" ) ;
471- } } >
472- PR Checks
473- </ button >
474- </ div >
551+ < button
552+ className = { tabClass ( display === "nightly" ) }
553+ onClick = { ( ) => {
554+ setDisplay ( "nightly" ) ;
555+ updateUrl ( "nightly" ) ;
556+
557+ } } >
558+ Nightly Jobs
559+ </ button >
560+ < button
561+ className = { tabClass ( display === "prchecks" ) }
562+ onClick = { ( ) => {
563+ setDisplay ( "prchecks" ) ;
564+ updateUrl ( "prchecks" ) ;
565+ } } >
566+ PR Checks
567+ </ button >
568+ < button
569+ className = { tabClass ( display === "prsingle" ) }
570+ onClick = { ( ) => {
571+ setDisplay ( "prsingle" ) ;
572+ updateUrl ( "prsingle" , selectedPR ) ;
573+ } } >
574+ Single PR
575+ </ button >
576+ { display === "prsingle" && (
577+ < div className = "bg-blue-500 p-2 rounded-xl h-fit" >
578+ < select
579+ id = "selectedrun"
580+ className = "px-1 h-fit rounded-lg"
581+ onChange = { ( e ) => {
582+ setSelectedPR ( e . target . value ) ;
583+ updateUrl ( "prsingle" , e . target . value ) ;
584+ } }
585+ value = { selectedPR } >
586+ < option value = "" > Select PR</ option >
587+ { runNumOptions . map ( num => (
588+ < option key = { num } value = { num } > #{ num } </ option >
589+ ) ) }
590+ </ select >
591+ </ div >
592+ ) }
593+ </ div >
475594 </ div >
476595
477596
@@ -483,9 +602,9 @@ export default function Home() {
483602 Required Jobs Only
484603 </ button >
485604 < div className = "mt-4 text-center md:text-lg text-base" >
486- Total Rows: { display === "prchecks" ? rowsPR . length : rowsNightly . length }
605+ Total Rows: { display === "prsingle" ? rowsSingle . length : display === "prchecks" ? rowsPR . length : rowsNightly . length }
487606 </ div >
488- < div > { display === "prchecks" ? renderPRTable ( ) : renderNightlyTable ( ) } </ div >
607+ < div > { display === "prsingle" ? renderSingleViewTable ( ) : display === " prchecks" ? renderPRTable ( ) : renderNightlyTable ( ) } </ div >
489608 </ div >
490609 </ div >
491610 ) ;
0 commit comments