Skip to content

Commit

Permalink
dashboard: Add single PR view
Browse files Browse the repository at this point in the history
Added a separate view to display all tests for a given PR.
Added the display to the URL, rowExpansionTemplate is unchanged.

Fixes: kata-containers#12

Signed-off-by: Anna Finn <[email protected]>
  • Loading branch information
afinn12 committed Nov 18, 2024
1 parent 70fdee2 commit 508c992
Showing 1 changed file with 173 additions and 43 deletions.
216 changes: 173 additions & 43 deletions pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@ import { Column } from "primereact/column";
import Head from "next/head";
import { weatherTemplate, getWeatherIndex } from "../components/weatherTemplate";
import { OverlayPanel } from 'primereact/overlaypanel';
import { basePath } from "../next.config.js";




export default function Home() {
const [loading, setLoading] = useState(true);

const [jobs, setJobs] = useState([]);
const [checks, setChecks] = useState([]);

const [rowsPR, setRowsPR] = useState([]);
const [rowsNightly, setRowsNightly] = useState([]);
const [rowsSingle, setRowsSingle] = useState([]);

const [expandedRows, setExpandedRows] = useState([]);
const [display, setDisplay] = useState("nightly");
const [selectedPR, setSelectedPR] = useState("");


useEffect(() => {
Expand Down Expand Up @@ -51,46 +58,87 @@ export default function Home() {
fetchData();
}, []);

// Filter and set the rows for Nightly view.
useEffect(() => {
setLoading(true);
let filteredJobs = jobs;
//Set the rows for the table.
setRowsNightly(
filteredJobs.map((job) => ({
name : job.name,
runs : job.runs,
fails : job.fails,
skips : job.skips,
required : job.required,
weather : getWeatherIndex(job),
reruns : job.reruns,
total_reruns : job.reruns.reduce((total, r) => total + r, 0),
}))
);
setLoading(false);
}, [jobs]);

// Filter and set the rows for PR Checks view.
useEffect(() => {
setLoading(true);
let filteredChecks = checks

//Set the rows for the table.
setRowsPR(
filteredChecks.map((check) => ({
name : check.name,
runs : check.runs,
fails : check.fails,
skips : check.skips,
required : check.required,
weather : getWeatherIndex(check),
reruns : check.reruns,
total_reruns : check.reruns.reduce((total, r) => total + r, 0),
}))
);
setLoading(false);
}, [checks]);

// Set the display based on the URL.
useEffect(() => {
const initialDisplay = new URLSearchParams(window.location.search).get("display");
if (initialDisplay) {
if(initialDisplay === "prsingle"){
const initialPR = new URLSearchParams(window.location.search).get("pr");
if(initialPR){
setSelectedPR(initialPR);
}
}
setDisplay(initialDisplay);
}
}, []);



// Filter and set the rows for Nightly view.
useEffect(() => {
setLoading(true);
let filteredJobs = jobs;
//Set the rows for the table.
setRowsNightly(
filteredJobs.map((job) => ({
name : job.name,
runs : job.runs,
fails : job.fails,
skips : job.skips,
required : job.required,
weather : getWeatherIndex(job),
reruns : job.reruns,
total_reruns : job.reruns.reduce((total, r) => total + r, 0),
}))
);
setLoading(false);
}, [jobs]);

// Filter and set the rows for PR Checks view.
useEffect(() => {
setLoading(true);
let filteredChecks = checks

//Set the rows for the table.
setRowsPR(
filteredChecks.map((check) => ({
name : check.name,
runs : check.runs,
fails : check.fails,
skips : check.skips,
required : check.required,
weather : getWeatherIndex(check),
reruns : check.reruns,
total_reruns : check.reruns.reduce((total, r) => total + r, 0),
}))
);
setLoading(false);
}, [checks]);


// Filter and set the rows for Single PR view.
useEffect(() => {
setLoading(true);

let filteredData = checks;

filteredData = filteredData.map((check) => {
// Only if the check include the run number, add it to the data.
const index = check.run_nums.indexOf(Number(selectedPR));
return index !== -1
? {
name: check.name,
required: check.required,
result: check.results[index],
runs: check.reruns[index] + 1,
}
: null;
}).filter(Boolean);

setRowsSingle(filteredData);
setLoading(false);
}, [checks, selectedPR]);

// Close all rows on view switch.
// Needed because if view is switched, breaks expanded row toggling.
Expand All @@ -99,6 +147,19 @@ useEffect(() => {
}, [display]);



// Update the URL on display change
const updateUrl = (view, pr) => {
const path = new URLSearchParams();
path.append("display", view);
// Add PR number Single PR view and a PR is provided
if (view === "prsingle" && pr) {
path.append("pr", pr);
}
// Update the URL without reloading
window.history.pushState({}, '', `${basePath}/?${path.toString()}`);
};


const tabClass = (active) => `tab md:px-4 px-2 py-2 border-b-2 focus:outline-none
${active ? "border-blue-500 bg-gray-300"
Expand Down Expand Up @@ -306,6 +367,47 @@ useEffect(() => {
);



// Make a list of all unique run numbers in the check data.
const runNumOptions = [...new Set(checks.flatMap(check => check.run_nums))].sort((a, b) => b - a);

// Render table for prsingle view
const renderSingleViewTable = () => (
<DataTable
value={rowsSingle}
expandedRows={expandedRows}
stripedRows
rowExpansionTemplate={rowExpansionTemplate}
onRowToggle={(e) => setExpandedRows(e.data)}
loading={loading}
emptyMessage={selectedPR.length == 0 ? "Select a Pull Request above." : "No results found."}
>
<Column expander />
<Column
field="name"
header="Name"
body={nameTemplate}
className="select-all"
sortable
/>
<Column
field="required"
header="Required"
sortable
/>
<Column
field="result"
header="Result"
sortable
/>
<Column
field="runs"
header="Total Runs"
sortable
/>
</DataTable>
);

return (
<>

Expand Down Expand Up @@ -334,26 +436,54 @@ useEffect(() => {
className={tabClass(display === "nightly")}
onClick={() => {
setDisplay("nightly");
updateUrl("nightly");

}}>
Nightly Jobs
</button>
<button
className={tabClass(display === "prchecks")}
onClick={() => {
setDisplay("prchecks");
updateUrl("prchecks");
}}>
PR Checks
</button>
</div>
<button
className={tabClass(display === "prsingle")}
onClick={() => {
setDisplay("prsingle");
updateUrl("prsingle", selectedPR);
}}>
Single PR
</button>
{display === "prsingle" && (
<div className="bg-blue-500 p-2 rounded-xl h-fit">
<select
id="selectedrun"
className="px-1 h-fit rounded-lg"
onChange={(e) => {
setSelectedPR(e.target.value);
updateUrl("prsingle", e.target.value);
}}
value={selectedPR} >
<option value="">Select PR</option>
{runNumOptions.map(num => (
<option key={num} value={num}>#{num}</option>
))}
</select>
</div>
)}
</div>
</div>

<div className="mt-1 text-center md:text-lg text-base">
Total Rows: {display === "prchecks" ? rowsPR.length : rowsNightly.length}
Total Rows: {display === "prsingle" ? rowsSingle.length : display === "prchecks" ? rowsPR.length : rowsNightly.length}
</div>

<main className={"m-0 h-full px-4 overflow-x-hidden overflow-y-auto \
bg-surface-ground antialiased select-text"}>
<div>{display === "prchecks" ? renderPRTable() : renderNightlyTable()}</div>
<div>{display === "prsingle" ? renderSingleViewTable() : display === "prchecks" ? renderPRTable() : renderNightlyTable()}</div>
</main>
</div>
</>
Expand Down

0 comments on commit 508c992

Please sign in to comment.