Skip to content

Commit 11fd959

Browse files
committed
url search working
1 parent 970416a commit 11fd959

File tree

1 file changed

+126
-8
lines changed

1 file changed

+126
-8
lines changed

pages/index.js

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1+
12
import { useEffect, useState } from "react";
23
import { DataTable } from "primereact/datatable";
34
import { Column } from "primereact/column";
45
import { weatherTemplate, getWeatherIndex } from "../components/weatherTemplate";
6+
import { basePath } from "../next.config.js";
57

68

79
export default function Home() {
810
const [loading, setLoading] = useState(true);
911
const [jobs, setJobs] = useState([]);
1012
const [rows, setRows] = useState([]);
1113
const [expandedRows, setExpandedRows] = useState([]);
14+
const [keepSearch, setKeepSearch] = useState(true);
1215

1316
useEffect(() => {
1417
const fetchData = async () => {
1518
let data = {};
1619

1720
if (process.env.NODE_ENV === "development") {
18-
data = (await import("../job_stats.json")).default;
21+
data = (await import("../data/job_stats.json")).default;
1922
} else {
2023
const response = await fetch(
2124
"https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
@@ -41,15 +44,55 @@ export default function Home() {
4144
fetchData();
4245
}, []);
4346

47+
// Filters the jobs s.t. all values must be contained in the name.
48+
const matchAll = (filteredJobs, urlParams) => {
49+
const values = urlParams.getAll("value");
50+
return filteredJobs.filter((job) => {
51+
const jobName = job.name.toLowerCase();
52+
return values.every((val) => {
53+
const decodedValue = decodeURIComponent(val).toLowerCase();
54+
return jobName.includes(decodedValue);
55+
});
56+
});
57+
};
58+
59+
// Filters the jobs s.t. at least one value must be contained in the name.
60+
const matchAny = (filteredJobs, urlParams) => {
61+
const values = urlParams.getAll("value");
62+
return filteredJobs.filter((job) => {
63+
const jobName = job.name.toLowerCase();
64+
return values.some((val) => {
65+
const decodedValue = decodeURIComponent(val).toLowerCase();
66+
return jobName.includes(decodedValue);
67+
});
68+
});
69+
};
70+
71+
4472
useEffect(() => {
4573
setLoading(true);
74+
let filteredJobs = jobs;
75+
76+
//Filter based on the URL.
77+
const urlParams = new URLSearchParams(window.location.search);
78+
if(urlParams.get("matchMode") === "and"){
79+
filteredJobs = matchAll(filteredJobs, urlParams);
80+
}else if(urlParams.get("matchMode") === "or"){
81+
filteredJobs = matchAny(filteredJobs, urlParams);
82+
}
83+
84+
//Set the rows for the table.
85+
setRows(
86+
filteredJobs.map((job) => ({
87+
name : job.name,
88+
runs : job.runs,
89+
fails : job.fails,
90+
skips : job.skips,
91+
required : job.required,
92+
weather : getWeatherIndex(job),
93+
}))
94+
);
4695

47-
// Create rows to set into table.
48-
const rows = jobs.map((job) => ({
49-
...job,
50-
weather: getWeatherIndex(job),
51-
}));
52-
setRows(rows);
5396
setLoading(false);
5497
}, [jobs]);
5598

@@ -66,6 +109,11 @@ export default function Home() {
66109
setExpandedRows(updatedExpandedRows);
67110
};
68111

112+
const buttonClass = (active) => `tab md:px-4 px-2 py-2 border-2
113+
${active ? "border-blue-500 bg-blue-500 text-white"
114+
: "border-gray-300 bg-white hover:bg-gray-100"}`;
115+
116+
69117
// Template for rendering the Name column as a clickable item
70118
const nameTemplate = (rowData) => {
71119
return (
@@ -120,6 +168,39 @@ export default function Home() {
120168
);
121169
};
122170

171+
// Apply search terms to the URL and reload the page.
172+
const handleSearch= (e) => {
173+
// Prevent the default behavior so that we can keep search terms.
174+
e.preventDefault();
175+
const matchMode = e.target.matchMode.value;
176+
const value = e.target.value.value.trimEnd();
177+
if (value) {
178+
// Append the new matchMode regardless of if search terms were kept.
179+
const path = new URLSearchParams();
180+
path.append("matchMode", matchMode);
181+
if (keepSearch) {
182+
// If keepSearch is true, add existing parameters in the URL.
183+
const urlParams = new URLSearchParams(window.location.search);
184+
urlParams.getAll("value").forEach((val) => {
185+
path.append("value", val);
186+
});
187+
}
188+
//Add the search term from the form and redirect.
189+
path.append("value", encodeURIComponent(value));
190+
window.location.assign(`${basePath}/?${path.toString()}`);
191+
}
192+
};
193+
194+
// Clear the search parameters, but only if they exist.
195+
const clearSearch = () => {
196+
const urlParts = window.location.href.split("?");
197+
if(urlParts[1] !== undefined){
198+
window.location.assign(urlParts[0]);
199+
}
200+
}
201+
202+
203+
123204
const renderTable = () => (
124205
<DataTable
125206
value={rows}
@@ -178,9 +259,46 @@ export default function Home() {
178259
"m-0 h-full p-4 overflow-x-hidden overflow-y-auto bg-surface-ground font-normal text-text-color antialiased select-text"
179260
}
180261
>
262+
<div className="space-x-2 mx-auto">
263+
<button
264+
className={buttonClass()}
265+
onClick={() => clearSearch()}>
266+
Clear Search
267+
</button>
268+
<button
269+
className={buttonClass(keepSearch)}
270+
onClick={() => setKeepSearch(!keepSearch)}>
271+
Keep URL Search Terms
272+
</button>
273+
</div>
274+
275+
<div className="flex flex-col items-center md:text-base text-xs">
276+
<div className="flex min-[1126px]:justify-end justify-center w-full">
277+
<form className="p-2 bg-gray-700 rounded-md flex flex-row" onSubmit={(e) => handleSearch(e)}>
278+
<div>
279+
<label className="block text-white">Match Mode:</label>
280+
<select name="matchMode" className="px-1 h-fit rounded-lg">
281+
<option value="or">Match Any</option>
282+
<option value="and">Match All</option>
283+
</select>
284+
</div>
285+
<div className="mx-2">
286+
<label className="block text-white">Search Text:</label>
287+
<input type="text" name="value" required></input>
288+
</div>
289+
<button type="submit" className="bg-blue-500 text-white px-4 rounded-3xl">Submit</button>
290+
</form>
291+
</div>
292+
</div>
293+
294+
<div className="mt-1 text-center md:text-lg text-base">
295+
Total Rows: {rows.length}
296+
</div>
297+
298+
181299
<div>{renderTable()}</div>
182300
<div className="mt-4 text-lg">Total Rows: {rows.length}</div>
183301
</main>
184302
</div>
185303
);
186-
}
304+
}

0 commit comments

Comments
 (0)