Skip to content

Commit e1b6b59

Browse files
authored
[ez][HUD] Move some functions around, new TextFieldSubmit component (#6347)
Just some generalizations + reorg of some functions * New TextFieldSubmit component that is just a text field that takes an input, and a button for submitting the input. In the future, maybe this should be generalized to have more fields? * Move encodeParams field to GeneralUtils * Moves a useClickHouse useSWR wrapper to GeneralUtils * Adjust some spacing for one of the components
1 parent 190c6f1 commit e1b6b59

File tree

9 files changed

+141
-65
lines changed

9 files changed

+141
-65
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Button, TextField } from "@mui/material";
2+
import { Box } from "@mui/system";
3+
4+
// Component that has a text field and a button to submit. Good for submitting a
5+
// filter
6+
export function TextFieldSubmit({
7+
textFieldValue,
8+
onSubmit,
9+
info,
10+
}: {
11+
textFieldValue: string;
12+
onSubmit: (s: string) => void;
13+
info: string;
14+
}) {
15+
return (
16+
<Box
17+
component="form"
18+
noValidate
19+
autoComplete="off"
20+
sx={{
21+
"& .MuiTextField-root": {
22+
marginRight: 1,
23+
width: "25ch",
24+
},
25+
"& .MuiButton-root": {
26+
marginTop: 1,
27+
marginBottom: 1,
28+
marginLeft: 2,
29+
},
30+
}}
31+
onSubmit={(e) => {
32+
e.preventDefault();
33+
// @ts-ignore
34+
onSubmit(e.target[0].value);
35+
}}
36+
>
37+
<TextField label={info} defaultValue={textFieldValue} />
38+
<Button variant="contained" color="primary" type="submit">
39+
Filter
40+
</Button>
41+
</Box>
42+
);
43+
}

torchci/components/tests/TestSearchForm.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Box, Button, TextField } from "@mui/material";
2-
import { encodeParams } from "pages/tests/search";
2+
import { encodeParams } from "lib/GeneralUtils";
33

44
function setURL(name: string, suite: string, file: string) {
55
window.location.href = `/tests/search?${encodeParams({
@@ -24,8 +24,15 @@ export default function TestSearchForm({
2424
noValidate
2525
autoComplete="off"
2626
sx={{
27-
"& .MuiTextField-root": { m: 1, width: "25ch" },
28-
"& .MuiButton-root": { m: 2 },
27+
"& .MuiTextField-root": {
28+
marginRight: 1,
29+
width: "25ch",
30+
},
31+
"& .MuiButton-root": {
32+
marginTop: 1,
33+
marginBottom: 1,
34+
marginLeft: 2,
35+
},
2936
}}
3037
onSubmit={(e) => {
3138
e.preventDefault();

torchci/lib/GeneralUtils.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { Octokit } from "octokit";
2+
import useSWR from "swr";
3+
import useSWRImmutable from "swr/immutable";
24
import { isFailure } from "./JobClassifierUtil";
35
import { CommitData, JobData } from "./types";
46

@@ -83,3 +85,66 @@ export async function hasWritePermissionsUsingOctokit(
8385
const permissions = res?.data?.permission;
8486
return permissions === "admin" || permissions === "write";
8587
}
88+
89+
/**
90+
* This hook function is a convenience wrapper for useSWR that fetches data from
91+
* the ClickHouse API. Handles things like encoding the query name and
92+
* parameters into the URL in the correct format.
93+
*
94+
* @param queryName Name of query, ex "hud_query"
95+
* @param parameters Parameters, in {key: value} format. If the value is not a
96+
* string, please stringify (usually with JSON.stringify)
97+
* @param condition Condition to fetch data. Used with useSWR for conditional
98+
* fetching. See
99+
* https://swr.vercel.app/docs/conditional-fetching.en-US#conditional
100+
* @returns The same as useSWR, with the type being any[] or T[] if T is provided
101+
*/
102+
export function useClickHouseAPI<T = any>(
103+
queryName: string,
104+
parameters: { [key: string]: string },
105+
condition: boolean = true
106+
) {
107+
// Helper function to format the URL nicely
108+
return useSWR<T[]>(
109+
condition &&
110+
`/api/clickhouse/${encodeURIComponent(queryName)}?${encodeParams({
111+
parameters: JSON.stringify(parameters),
112+
})}`,
113+
fetcher
114+
);
115+
}
116+
117+
/**
118+
* This hook function is a convenience wrapper for useSWRImmutable that fetches
119+
* data from the ClickHouse API. This is the same as useClickHouseAPI, but with
120+
* the immutable version of useSWR. Handles things like encoding the query name
121+
* and parameters into the URL in the correct format.
122+
*
123+
* @param queryName Name of query, ex "hud_query"
124+
* @param parameters Parameters, in {key: value} format. If the value is not a
125+
* string, please stringify (usually with JSON.stringify)
126+
* @param condition Condition to fetch data. Used with useSWR for conditional
127+
* fetching. See
128+
* https://swr.vercel.app/docs/conditional-fetching.en-US#conditional
129+
* @returns The same as useSWR, with the type being any[] or T[] if T is provided
130+
*/
131+
export function useClickHouseAPIImmutable<T = any>(
132+
queryName: string,
133+
parameters: { [key: string]: string },
134+
condition: boolean = true
135+
) {
136+
// Helper function to format the URL nicely
137+
return useSWRImmutable<T[]>(
138+
condition &&
139+
`/api/clickhouse/${encodeURIComponent(queryName)}?${encodeParams({
140+
parameters: JSON.stringify(parameters),
141+
})}`,
142+
fetcher
143+
);
144+
}
145+
146+
export function encodeParams(params: { [key: string]: string }) {
147+
return Object.keys(params)
148+
.map((key) => `${key}=${encodeURIComponent(params[key])}`)
149+
.join("&");
150+
}

torchci/pages/build_time_metrics.tsx

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@ import { TimeSeriesPanelWithData } from "components/metrics/panels/TimeSeriesPan
1212
import { durationDisplay, formatTimeForCharts } from "components/TimeUtils";
1313
import dayjs from "dayjs";
1414
import utc from "dayjs/plugin/utc";
15-
import { fetcher } from "lib/GeneralUtils";
15+
import { useClickHouseAPIImmutable } from "lib/GeneralUtils";
1616
import _ from "lodash";
1717
import { useEffect, useMemo, useState } from "react";
18-
import useSWRImmutable from "swr/immutable";
1918
import { TimeRangePicker } from "./metrics";
20-
import { encodeParams } from "./tests/search";
2119
dayjs.extend(utc);
2220

2321
// Some common styles for components
@@ -59,21 +57,6 @@ function convertToSeries(
5957
return { xAxis, series };
6058
}
6159

62-
function useClickHouse(
63-
queryName: string,
64-
parameters: any,
65-
condition: boolean = true
66-
) {
67-
// Helper function to format the URL nicely
68-
return useSWRImmutable(
69-
condition &&
70-
`/api/clickhouse/${encodeURIComponent(queryName)}?${encodeParams({
71-
parameters: JSON.stringify(parameters),
72-
})}`,
73-
fetcher
74-
);
75-
}
76-
7760
export default function Page() {
7861
const [startTime, setStartTime] = useState(dayjs().subtract(1, "week"));
7962
const [stopTime, setStopTime] = useState(dayjs());
@@ -88,22 +71,21 @@ export default function Page() {
8871
startTime: startTime.utc().format("YYYY-MM-DDTHH:mm:ss.SSS"),
8972
stopTime: stopTime.utc().format("YYYY-MM-DDTHH:mm:ss.SSS"),
9073
};
91-
const { data: stepsData, isLoading: stepsDataIsLoading } = useClickHouse(
92-
"build_time_metrics/steps",
93-
timeParams
94-
);
74+
const { data: stepsData, isLoading: stepsDataIsLoading } =
75+
useClickHouseAPIImmutable("build_time_metrics/steps", timeParams);
9576

96-
const { data: buildData, isLoading: buildDataIsLoading } = useClickHouse(
97-
"build_time_metrics/overall",
98-
{ ...timeParams, granularity: "day" }
99-
);
77+
const { data: buildData, isLoading: buildDataIsLoading } =
78+
useClickHouseAPIImmutable("build_time_metrics/overall", {
79+
...timeParams,
80+
granularity: "day",
81+
});
10082

10183
const {
10284
data: selectedBuildSccacheStats,
10385
isLoading: selectedBuildSccacheStatsIsLoading,
104-
} = useClickHouse(
86+
} = useClickHouseAPIImmutable(
10587
"build_time_metrics/sccache_stats",
106-
{ jobName: selectedBuild, ...timeParams },
88+
{ jobName: selectedBuild as string, ...timeParams },
10789
selectedBuild != null && openSccacheStats
10890
);
10991

torchci/pages/failure.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import LoadingPage from "components/LoadingPage";
77
import LogViewer from "components/LogViewer";
88
import dayjs from "dayjs";
99
import utc from "dayjs/plugin/utc";
10+
import { encodeParams } from "lib/GeneralUtils";
1011
import { JobData } from "lib/types";
1112
import { usePreference } from "lib/useGroupingPreference";
1213
import { useRouter } from "next/router";
1314
import { CSSProperties, useEffect, useState } from "react";
1415
import { Bar, BarChart, CartesianGrid, Tooltip, XAxis, YAxis } from "recharts";
1516
import useSWR from "swr";
16-
import { encodeParams } from "./tests/search";
1717
dayjs.extend(utc);
1818

1919
const fetcher = (url: string) => fetch(url).then((res) => res.json());

torchci/pages/flakytest.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import { encodeParams } from "lib/GeneralUtils";
12
import { useRouter } from "next/router";
23
import { useEffect } from "react";
3-
import { encodeParams } from "./tests/search";
44

55
export default function Page() {
66
const router = useRouter();

torchci/pages/tests/search.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,14 @@ import { Pagination, Stack, Tooltip } from "@mui/material";
22
import { DataGrid, GridColDef } from "@mui/x-data-grid";
33
import LoadingPage from "components/LoadingPage";
44
import TestSearchForm from "components/tests/TestSearchForm";
5+
import { encodeParams } from "lib/GeneralUtils";
56
import { useRouter } from "next/router";
67
import { ListTestInfoAPIResponse } from "pages/api/flaky-tests/search";
78
import { useEffect, useState } from "react";
89
import useSWR from "swr";
910

1011
const fetcher = (url: string) => fetch(url).then((res) => res.json());
1112

12-
export function encodeParams(params: { [key: string]: string }) {
13-
return Object.keys(params)
14-
.map((key) => `${key}=${encodeURIComponent(params[key])}`)
15-
.join("&");
16-
}
17-
1813
export default function Page() {
1914
const router = useRouter();
2015
const name = (router.query.name || "") as string;

torchci/pages/tests/testInfo.tsx

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import { Box, Button, Stack, TextField } from "@mui/material";
1+
import { Stack } from "@mui/material";
22
import { BarChart } from "@mui/x-charts";
3+
import { TextFieldSubmit } from "components/common/TextFieldSubmit";
34
import JobLinks from "components/JobLinks";
45
import JobSummary from "components/JobSummary";
56
import LoadingPage from "components/LoadingPage";
67
import LogViewer from "components/LogViewer";
78
import TestSearchForm from "components/tests/TestSearchForm";
89
import dayjs from "dayjs";
9-
import { fetcher } from "lib/GeneralUtils";
10+
import { encodeParams, fetcher } from "lib/GeneralUtils";
1011
import { JobData } from "lib/types";
1112
import _ from "lodash";
1213
import { useRouter } from "next/router";
1314
import { TestInfoAPIResponse } from "pages/api/flaky-tests/3dStats";
14-
import { encodeParams } from "pages/tests/search";
1515
import { useState } from "react";
1616
import useSWRImmutable from "swr/immutable";
1717

@@ -90,30 +90,15 @@ export default function Page() {
9090
convertToSeries(last3dStats ?? []);
9191

9292
return (
93-
<Stack spacing={{ xs: 1 }}>
93+
<Stack spacing={2}>
9494
<h1>Test Info</h1>
9595
<TestSearchForm name={name} suite={suite} file={file} />
9696
<h2>Last 3 Days on main Branch</h2>
97-
<Box
98-
component="form"
99-
noValidate
100-
autoComplete="off"
101-
sx={{
102-
"& .MuiTextField-root": { m: 1, width: "25ch" },
103-
"& .MuiButton-root": { m: 2 },
104-
}}
105-
onSubmit={(e) => {
106-
e.preventDefault();
107-
// @ts-ignore
108-
setJobFilter(e.target[0].value);
109-
}}
110-
>
111-
<TextField label="Chart Job Filter" defaultValue={jobFilter} />
112-
<Button variant="contained" color="primary" type="submit">
113-
Filter
114-
</Button>
115-
</Box>
116-
97+
<TextFieldSubmit
98+
textFieldValue={jobFilter}
99+
onSubmit={setJobFilter}
100+
info={"Chart Job Filter"}
101+
/>
117102
{isLoading ? (
118103
<LoadingPage />
119104
) : (

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@ import { durationDisplay, formatTimeForCharts } from "components/TimeUtils";
1212
import dayjs from "dayjs";
1313
import { EChartsOption } from "echarts";
1414
import ReactECharts from "echarts-for-react";
15-
import { fetcher } from "lib/GeneralUtils";
15+
import { encodeParams, fetcher } from "lib/GeneralUtils";
1616
import {
1717
compressToEncodedURIComponent,
1818
decompressFromEncodedURIComponent,
1919
} from "lz-string";
2020
import { useRouter } from "next/router";
21-
import { encodeParams } from "pages/tests/search";
2221
import { useEffect, useState } from "react";
2322
import useSWRImmutable from "swr/immutable";
2423
import { TimeRangePicker, TtsPercentilePicker } from "../../../../metrics";

0 commit comments

Comments
 (0)