Skip to content

Commit 39b18aa

Browse files
committed
dashboard: Add single PR view
Added a separate view to display all tests for a given PR. Added the display to the URL, rowExpansionTemplate is unchanged. Fixes: #12 Signed-off-by: Anna Finn <[email protected]>
1 parent 362d9ab commit 39b18aa

File tree

2 files changed

+147
-42
lines changed

2 files changed

+147
-42
lines changed

Diff for: next.config.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
module.exports = {
22
reactStrictMode: true,
3-
output: 'export',
4-
basePath: "",
3+
// output: 'export',
4+
basePath: process.env.NEXT_PUBLIC_BASE_PATH || "",
55
images: {
66
unoptimized: true,
77
},
88
webpack: (config, { dev }) => {
9+
10+
config.module.rules.push({
11+
test: /\.yml$/,
12+
use: 'yaml-loader',
13+
});
14+
915
if (dev) {
1016
config.devtool = false;
1117
}

Diff for: pages/index.js

+139-40
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,20 @@ import Head from "next/head";
55
import { weatherTemplate, getWeatherIndex } from "../components/weatherTemplate";
66
import { OverlayPanel } from 'primereact/overlaypanel';
77
import MaintainerMapping from "../maintainers.yml";
8+
import { basePath } from "../next.config.js";
89

910

1011
export 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

Comments
 (0)