Skip to content

Commit b3cb6b2

Browse files
authored
[HUD] Add option to filter jobs on main page by regex (#6986)
Add a button toggle to filter jobs by regex on the main HUD page based off the one in the cost analysis page Follow up PR for the cost analysis page to also use the component: #6986 Reason: * Sometimes I want to search for something kind of specific that the current job filtering doesn't handle, like "linux jobs but only on pull" Changes: * Add new component for the regex toggle button * Changes the styling of the input text box and search button to be larger * The HUD table is shifted slightly down but not by much Old: <img width="472" height="78" alt="image" src="https://github.com/user-attachments/assets/d0362f72-1021-4169-88f8-f5e350317d74" /> New: <img width="549" height="92" alt="image" src="https://github.com/user-attachments/assets/e2c51871-0c14-444b-8431-b71c46eb310e" />
1 parent b89e132 commit b3cb6b2

File tree

6 files changed

+135
-23
lines changed

6 files changed

+135
-23
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Button, Tooltip } from "@mui/material";
2+
3+
/**
4+
* RegexButton component for toggling regex search. Example can be seen on the
5+
* HUD main page in the job filter.
6+
* @param isRegex Whether the regex search is enabled
7+
* @param setIsRegex Function to toggle the regex search state
8+
* @returns
9+
*/
10+
export default function RegexButton({
11+
isRegex,
12+
setIsRegex,
13+
}: {
14+
isRegex: boolean;
15+
setIsRegex: (value: boolean) => void;
16+
}) {
17+
return (
18+
<Tooltip title={isRegex ? "Disable regex search" : "Enable regex search"}>
19+
<Button
20+
size="small"
21+
style={{
22+
minWidth: 0,
23+
textTransform: "none",
24+
borderColor: "transparent",
25+
fontFamily: "monospace",
26+
color: "inherit",
27+
backgroundColor: isRegex ? "rgba(63, 81, 181, 0.1)" : "transparent",
28+
}}
29+
variant="outlined"
30+
onClick={() => setIsRegex(!isRegex)}
31+
>
32+
.*
33+
</Button>
34+
</Tooltip>
35+
);
36+
}

torchci/components/hud/GroupHudTableHeaders.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ import {
77
import React, { useContext } from "react";
88
import { BsFillCaretDownFill, BsFillCaretRightFill } from "react-icons/bs";
99

10-
function groupingIncludesJobFilter(jobNames: string[], filter: string) {
10+
function groupingIncludesJobFilter(
11+
jobNames: string[],
12+
filter: string,
13+
useRegex: boolean
14+
) {
1115
for (const jobName of jobNames) {
12-
if (includesCaseInsensitive(jobName, filter)) {
16+
if (includesCaseInsensitive(jobName, filter, useRegex)) {
1317
return true;
1418
}
1519
}
@@ -19,12 +23,17 @@ function groupingIncludesJobFilter(jobNames: string[], filter: string) {
1923
export function passesGroupFilter(
2024
filter: string | null,
2125
name: string,
22-
groupNameMapping: Map<string, string[]>
26+
groupNameMapping: Map<string, string[]>,
27+
useRegex: boolean
2328
) {
2429
return (
2530
filter === null ||
26-
includesCaseInsensitive(name, filter) ||
27-
groupingIncludesJobFilter(groupNameMapping.get(name) ?? [], filter)
31+
includesCaseInsensitive(name, filter, useRegex) ||
32+
groupingIncludesJobFilter(
33+
groupNameMapping.get(name) ?? [],
34+
filter,
35+
useRegex
36+
)
2837
);
2938
}
3039

torchci/components/job/JobFilterInput.tsx

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import { Button, TextField } from "@mui/material";
2+
import { Stack } from "@mui/system";
3+
import RegexButton from "components/common/RegexButton";
4+
import { formatHudUrlForRoute, packHudParams } from "lib/types";
5+
import { useRouter } from "next/router";
16
import { useEffect, useState } from "react";
27

38
export default function JobFilterInput({
@@ -11,36 +16,75 @@ export default function JobFilterInput({
1116
handleFocus?: () => void;
1217
width?: string;
1318
}) {
19+
const router = useRouter();
20+
const params = packHudParams(router.query);
21+
const [useRegexFilter, setuseRegexFilter] = useState(
22+
params.useRegexFilter || false
23+
);
24+
1425
const [currVal, setCurrVal] = useState<string>(currentFilter ?? "");
1526
useEffect(() => {
1627
// something about hydration and states is making it so that currVal remains
1728
// as "" when currentFilter changes
1829
setCurrVal(currentFilter ?? "");
1930
}, [currentFilter]);
31+
32+
useEffect(() => {
33+
router.push(
34+
formatHudUrlForRoute("hud", { ...params, useRegexFilter }),
35+
undefined,
36+
{
37+
shallow: true,
38+
}
39+
);
40+
}, [useRegexFilter]);
41+
2042
return (
2143
<div style={{ margin: 0 }}>
2244
<form
2345
onSubmit={(e) => {
2446
e.preventDefault();
2547
handleSubmit(currVal);
2648
}}
27-
style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}
2849
>
29-
<label
30-
htmlFor="name_filter"
31-
style={{ margin: 0, whiteSpace: "nowrap" }}
32-
>
33-
Job filter:
34-
</label>
35-
<input
36-
style={{ width: width || "150px" }}
37-
type="text"
38-
name="name_filter"
39-
value={currVal}
40-
onChange={(e) => setCurrVal(e.target.value)}
41-
onFocus={handleFocus}
42-
/>
43-
<input type="submit" value="Go" />
50+
<Stack direction="row" spacing={1} alignItems="center">
51+
<label htmlFor="name_filter">Job filter:</label>
52+
<TextField
53+
id="name_filter"
54+
name="name_filter"
55+
variant="outlined"
56+
size="small"
57+
value={currVal}
58+
onChange={(e) => setCurrVal(e.target.value)}
59+
onFocus={handleFocus}
60+
slotProps={{
61+
input: {
62+
endAdornment: (
63+
<RegexButton
64+
isRegex={useRegexFilter}
65+
setIsRegex={setuseRegexFilter}
66+
/>
67+
),
68+
},
69+
}}
70+
/>
71+
<Button
72+
size="large"
73+
style={{
74+
minWidth: 0,
75+
textTransform: "none",
76+
font: "inherit",
77+
backgroundColor: "transparent",
78+
borderColor: "transparent",
79+
color: "inherit",
80+
}}
81+
variant="outlined"
82+
type="submit"
83+
onClick={() => handleSubmit(currVal)}
84+
>
85+
Go
86+
</Button>
87+
</Stack>
4488
</form>
4589
</div>
4690
);

torchci/lib/GeneralUtils.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,18 @@ class ErrorWithStatusCode extends Error {
1616

1717
export function includesCaseInsensitive(
1818
value: string,
19-
pattern: string
19+
pattern: string,
20+
useRegex: boolean
2021
): boolean {
22+
if (useRegex) {
23+
try {
24+
const regex = new RegExp(pattern, "i");
25+
return regex.test(value);
26+
} catch (error) {
27+
console.error("Invalid regex pattern:", error);
28+
return false;
29+
}
30+
}
2131
return value.toLowerCase().includes(pattern.toLowerCase());
2232
}
2333

torchci/lib/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ export interface HudParams {
127127
filter_reruns: boolean;
128128
filter_unstable: boolean;
129129
mergeEphemeralLF?: boolean;
130+
useRegexFilter?: boolean;
130131
}
131132

132133
export interface PRData {
@@ -274,6 +275,7 @@ export function packHudParams(input: any) {
274275
filter_reruns: input.filter_reruns ?? (false as boolean),
275276
filter_unstable: input.filter_unstable ?? (false as boolean),
276277
mergeEphemeralLF: input.mergeEphemeralLF as boolean,
278+
useRegexFilter: input.useRegexFilter === "true",
277279
};
278280
}
279281

@@ -314,6 +316,10 @@ function formatHudURL(
314316
base += `&name_filter=${encodeURIComponent(params.nameFilter)}`;
315317
}
316318

319+
if (params.useRegexFilter && keepFilter) {
320+
base += `&useRegexFilter=true`;
321+
}
322+
317323
if (params.mergeEphemeralLF) {
318324
base += `&mergeEphemeralLF=true`;
319325
}

torchci/pages/hud/[repoOwner]/[repoName]/[branch]/[[...page]].tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,14 @@ function GroupedHudTable({
662662

663663
names = names.filter((name) => {
664664
// Filter by job filter text first
665-
if (!passesGroupFilter(jobFilter, name, groupNameMapping)) {
665+
if (
666+
!passesGroupFilter(
667+
jobFilter,
668+
name,
669+
groupNameMapping,
670+
params.useRegexFilter || false
671+
)
672+
) {
666673
return false;
667674
}
668675

0 commit comments

Comments
 (0)