diff --git a/components/searchForm.js b/components/searchForm.js
new file mode 100644
index 0000000..63f5551
--- /dev/null
+++ b/components/searchForm.js
@@ -0,0 +1,22 @@
+export const SearchForm = ({ handleSearch }) => {
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/pages/index.js b/pages/index.js
index b12d28a..d7a210d 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -2,20 +2,23 @@ import { useEffect, useState } from "react";
import { DataTable } from "primereact/datatable";
import { Column } from "primereact/column";
import { weatherTemplate, getWeatherIndex } from "../components/weatherTemplate";
+import { basePath } from "../next.config.js";
+import { SearchForm } from "../components/searchForm";
export default function Home() {
- const [loading, setLoading] = useState(true);
- const [jobs, setJobs] = useState([]);
- const [rows, setRows] = useState([]);
- const [expandedRows, setExpandedRows] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [jobs, setJobs] = useState([]);
+ const [rows, setRows] = useState([]);
+ const [expandedRows, setExpandedRows] = useState([]);
+ const [keepSearch, setKeepSearch] = useState(true);
useEffect(() => {
const fetchData = async () => {
let data = {};
if (process.env.NODE_ENV === "development") {
- data = (await import("../job_stats.json")).default;
+ data = (await import("../localData/job_stats.json")).default;
} else {
const response = await fetch(
"https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
@@ -41,15 +44,59 @@ export default function Home() {
fetchData();
}, []);
+ // Filters the jobs s.t. all values must be contained in the name.
+ const matchAll = (filteredJobs, values) => {
+ return filteredJobs.filter((job) => {
+ const jobName = job.name.toLowerCase();
+ return values.every((val) => {
+ const decodedValue = decodeURIComponent(val).toLowerCase();
+ return jobName.includes(decodedValue);
+ });
+ });
+ };
+
+ // Filters the jobs s.t. at least one value must be contained in the name.
+ const matchAny = (filteredJobs, values) => {
+ return filteredJobs.filter((job) => {
+ const jobName = job.name.toLowerCase();
+ return values.some((val) => {
+ const decodedValue = decodeURIComponent(val).toLowerCase();
+ return jobName.includes(decodedValue);
+ });
+ });
+ };
+
+
useEffect(() => {
setLoading(true);
+ let filteredJobs = jobs;
+
+ //Filter based on the URL.
+ const urlParams = new URLSearchParams(window.location.search);
+ switch(urlParams.get("matchMode")) {
+ case "and":
+ filteredJobs = matchAll(filteredJobs, urlParams.getAll("value"));
+ break;
+ case "or":
+ filteredJobs = matchAny(filteredJobs, urlParams.getAll("value"));
+ break;
+ default:
+ break;
+ }
+
+
+ //Set the rows for the table.
+ setRows(
+ filteredJobs.map((job) => ({
+ name : job.name,
+ runs : job.runs,
+ fails : job.fails,
+ skips : job.skips,
+ required : job.required,
+ weather : getWeatherIndex(job),
+ }))
+ );
- // Create rows to set into table.
- const rows = jobs.map((job) => ({
- ...job,
- weather: getWeatherIndex(job),
- }));
- setRows(rows);
setLoading(false);
}, [jobs]);
@@ -66,6 +113,11 @@ export default function Home() {
setExpandedRows(updatedExpandedRows);
};
+ const buttonClass = (active) => `tab md:px-4 px-2 py-2 border-2
+ ${active ? "border-blue-500 bg-blue-500 text-white"
+ : "border-gray-300 bg-white hover:bg-gray-100"}`;
+
+
// Template for rendering the Name column as a clickable item
const nameTemplate = (rowData) => {
return (
@@ -120,6 +172,39 @@ export default function Home() {
);
};
+ // Apply search terms to the URL and reload the page.
+ const handleSearch= (e) => {
+ // Prevent the default behavior so that we can keep search terms.
+ e.preventDefault();
+ const matchMode = e.target.matchMode.value;
+ const value = e.target.value.value.trimEnd();
+ if (value) {
+ // Append the new matchMode regardless of if search terms were kept.
+ const path = new URLSearchParams();
+ path.append("matchMode", matchMode);
+ if (keepSearch) {
+ // If keepSearch is true, add existing parameters in the URL.
+ const urlParams = new URLSearchParams(window.location.search);
+ urlParams.getAll("value").forEach((val) => {
+ path.append("value", val);
+ });
+ }
+ //Add the search term from the form and redirect.
+ path.append("value", value);
+ window.location.assign(`${basePath}/?${path.toString()}`);
+ }
+ };
+
+ // Clear the search parameters, but only if they exist.
+ const clearSearch = () => {
+ const urlParts = window.location.href.split("?");
+ if(urlParts[1] !== undefined){
+ window.location.assign(urlParts[0]);
+ }
+ }
+
+
+
const renderTable = () => (
+
+
+
+
+
+
+
+
+ Total Rows: {rows.length}
+
+
{renderTable()}
Total Rows: {rows.length}
);
-}
+}
\ No newline at end of file