Skip to content

Commit d5ba5d3

Browse files
committed
Tighten runs table filters
1 parent dce0e71 commit d5ba5d3

3 files changed

Lines changed: 158 additions & 179 deletions

File tree

apps/web/src/App.tsx

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@ export const App = () => {
4343
error: commitError,
4444
treemapError: commitTreemapError,
4545
} = useCommitDetailData(route);
46-
47-
const [commitSha, setCommitSha] = useState("");
48-
const [branch, setBranch] = useState("main");
49-
const [changedFiles, setChangedFiles] = useState("");
50-
const [resumeFromCheckpoint, setResumeFromCheckpoint] = useState(false);
51-
const [submitting, setSubmitting] = useState(false);
52-
const [submitError, setSubmitError] = useState<string | null>(null);
5346
const [draftFilters, setDraftFilters] = useState(() =>
5447
route.name === "runs"
5548
? {
@@ -155,39 +148,6 @@ export const App = () => {
155148
);
156149
const selectedRepositorySlug = selectedRepository?.slug ?? null;
157150

158-
const submitManualRun = async (): Promise<void> => {
159-
if (!selectedRepositorySlug) {
160-
return;
161-
}
162-
163-
setSubmitting(true);
164-
setSubmitError(null);
165-
166-
try {
167-
const response = await fetchJson<{ runId: string; stepRunIds: string[] }>("/runs/manual", {
168-
method: "POST",
169-
body: JSON.stringify({
170-
repositorySlug: selectedRepositorySlug,
171-
commitSha: commitSha.trim(),
172-
branch: branch.trim() || undefined,
173-
changedFiles: changedFiles
174-
.split("\n")
175-
.map((value) => value.trim())
176-
.filter(Boolean),
177-
resumeFromCheckpoint,
178-
}),
179-
});
180-
181-
if (response.runId) {
182-
navigate(buildRunPath(selectedRepositorySlug, response.runId));
183-
}
184-
} catch (error) {
185-
setSubmitError(error instanceof Error ? error.message : "Failed to start run");
186-
} finally {
187-
setSubmitting(false);
188-
}
189-
};
190-
191151
const applyRunFilters = (): void => {
192152
if (!selectedRepositorySlug) {
193153
return;
@@ -256,7 +216,6 @@ export const App = () => {
256216

257217
const error =
258218
repositoriesError ??
259-
submitError ??
260219
(route.name === "runs"
261220
? (stepSpecsError ?? runsError)
262221
: route.name === "run" || route.name === "step"
@@ -324,17 +283,7 @@ export const App = () => {
324283
repositorySlug={selectedRepositorySlug}
325284
runsPage={runsPage}
326285
processSpecs={stepSpecs}
327-
commitSha={commitSha}
328-
branch={branch}
329-
changedFiles={changedFiles}
330-
resumeFromCheckpoint={resumeFromCheckpoint}
331-
submitting={submitting}
332286
draftFilters={draftFilters}
333-
onCommitShaChange={setCommitSha}
334-
onBranchChange={setBranch}
335-
onChangedFilesChange={setChangedFiles}
336-
onResumeFromCheckpointChange={setResumeFromCheckpoint}
337-
onSubmit={() => void submitManualRun()}
338287
onDraftFilterChange={(key, value) => {
339288
setDraftFilters((current) => ({ ...current, [key]: value }));
340289
}}

apps/web/src/pages/RunsPage.tsx

Lines changed: 74 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,15 @@ export const RunsPage = ({
1515
repositorySlug,
1616
runsPage,
1717
processSpecs,
18-
commitSha,
19-
branch,
20-
changedFiles,
21-
resumeFromCheckpoint,
22-
submitting,
2318
draftFilters,
24-
onCommitShaChange,
25-
onBranchChange,
26-
onChangedFilesChange,
27-
onResumeFromCheckpointChange,
28-
onSubmit,
2919
onDraftFilterChange,
3020
onApplyFilters,
3121
onPageChange,
3222
}: {
3323
repositorySlug: string | null;
3424
runsPage: PaginatedRunList | null;
3525
processSpecs: StepSpecSummary[];
36-
commitSha: string;
37-
branch: string;
38-
changedFiles: string;
39-
resumeFromCheckpoint: boolean;
40-
submitting: boolean;
4126
draftFilters: { status: string; trigger: string; stepKey: string };
42-
onCommitShaChange: (value: string) => void;
43-
onBranchChange: (value: string) => void;
44-
onChangedFilesChange: (value: string) => void;
45-
onResumeFromCheckpointChange: (value: boolean) => void;
46-
onSubmit: () => void;
4727
onDraftFilterChange: (key: "status" | "trigger" | "stepKey", value: string) => void;
4828
onApplyFilters: () => void;
4929
onPageChange: (page: number) => void;
@@ -61,125 +41,91 @@ export const RunsPage = ({
6141
</div>
6242
</section>
6343

64-
<section className="panel">
44+
<section className="panel tablePanel">
6545
<header className="panelHeader">
6646
<div>
67-
<h2>Create a run</h2>
47+
<h2>Runs</h2>
6848
<p className="secondaryText">
69-
Manual runs live here so the repository landing page can stay focused on commits.
49+
Attempt history for this repository. Use the header controls to narrow the table.
7050
</p>
7151
</div>
72-
</header>
73-
<div className="formGrid">
74-
<label className="field">
75-
<span>Commit SHA</span>
76-
<input
77-
value={commitSha}
78-
onChange={(event) => onCommitShaChange(event.target.value)}
79-
placeholder="Paste the commit SHA to evaluate"
80-
/>
81-
</label>
82-
<label className="field">
83-
<span>Branch</span>
84-
<input
85-
value={branch}
86-
onChange={(event) => onBranchChange(event.target.value)}
87-
placeholder="main"
88-
/>
89-
</label>
90-
<label className="field span2">
91-
<span>Changed files</span>
92-
<textarea
93-
value={changedFiles}
94-
onChange={(event) => onChangedFilesChange(event.target.value)}
95-
placeholder={"apps/web/src/App.tsx\napps/web/src/styles.css"}
96-
/>
97-
</label>
98-
<label className="checkboxField span2">
99-
<input
100-
type="checkbox"
101-
checked={resumeFromCheckpoint}
102-
onChange={(event) => onResumeFromCheckpointChange(event.target.checked)}
103-
/>
104-
<span>Resume from the latest compatible checkpoint when available.</span>
105-
</label>
106-
</div>
107-
<div className="panelActions">
108-
<button
109-
className="primaryButton"
110-
disabled={submitting || commitSha.trim().length === 0}
111-
onClick={() => void onSubmit()}
112-
>
113-
{submitting ? "Submitting..." : "Start run"}
114-
</button>
115-
</div>
116-
</section>
117-
118-
<section className="panel">
119-
<header className="panelHeader">
120-
<h2>Browse runs</h2>
121-
</header>
122-
<div className="filterGrid">
123-
<label className="field">
124-
<span>Status</span>
125-
<select
126-
value={draftFilters.status}
127-
onChange={(event) => onDraftFilterChange("status", event.target.value)}
128-
>
129-
<option value="">All</option>
130-
{["passed", "failed", "running", "queued", "reused", "interrupted"].map((value) => (
131-
<option key={value} value={value}>
132-
{value}
133-
</option>
134-
))}
135-
</select>
136-
</label>
137-
<label className="field">
138-
<span>Trigger</span>
139-
<select
140-
value={draftFilters.trigger}
141-
onChange={(event) => onDraftFilterChange("trigger", event.target.value)}
142-
>
143-
<option value="">All</option>
144-
{["manual", "push", "pull_request"].map((value) => (
145-
<option key={value} value={value}>
146-
{value}
147-
</option>
148-
))}
149-
</select>
150-
</label>
151-
<label className="field">
152-
<span>Step</span>
153-
<select
154-
value={draftFilters.stepKey}
155-
onChange={(event) => onDraftFilterChange("stepKey", event.target.value)}
156-
>
157-
<option value="">All</option>
158-
{processSpecs.map((spec) => (
159-
<option key={spec.id} value={spec.key}>
160-
{spec.displayName}
161-
</option>
162-
))}
163-
</select>
164-
</label>
165-
</div>
166-
<div className="panelActions">
167-
<button className="secondaryButton" onClick={onApplyFilters}>
168-
Apply filters
169-
</button>
170-
</div>
171-
</section>
172-
173-
<section className="panel tablePanel">
174-
<header className="panelHeader">
175-
<h2>Runs</h2>
17652
<div className="secondaryText">{runsPage ? `${runsPage.total} total` : "Loading"}</div>
17753
</header>
17854
{runsPage?.items.length ? (
17955
<>
18056
<div className="tableScroller">
18157
<table className="dataTable">
18258
<thead>
59+
<tr className="tableControlsRow">
60+
<th colSpan={8}>
61+
<div className="tableControlsBar">
62+
<div className="tableControlsLabel">Browse runs</div>
63+
<div className="tableControlsGroup">
64+
<label className="headerFilter">
65+
<span>Status</span>
66+
<select
67+
value={draftFilters.status}
68+
onChange={(event) =>
69+
onDraftFilterChange("status", event.target.value)
70+
}
71+
>
72+
<option value="">All</option>
73+
{[
74+
"passed",
75+
"failed",
76+
"running",
77+
"queued",
78+
"reused",
79+
"interrupted",
80+
].map((value) => (
81+
<option key={value} value={value}>
82+
{value}
83+
</option>
84+
))}
85+
</select>
86+
</label>
87+
<label className="headerFilter">
88+
<span>Trigger</span>
89+
<select
90+
value={draftFilters.trigger}
91+
onChange={(event) =>
92+
onDraftFilterChange("trigger", event.target.value)
93+
}
94+
>
95+
<option value="">All</option>
96+
{["manual", "push", "pull_request"].map((value) => (
97+
<option key={value} value={value}>
98+
{value}
99+
</option>
100+
))}
101+
</select>
102+
</label>
103+
<label className="headerFilter">
104+
<span>Step</span>
105+
<select
106+
value={draftFilters.stepKey}
107+
onChange={(event) =>
108+
onDraftFilterChange("stepKey", event.target.value)
109+
}
110+
>
111+
<option value="">All</option>
112+
{processSpecs.map((spec) => (
113+
<option key={spec.id} value={spec.key}>
114+
{spec.displayName}
115+
</option>
116+
))}
117+
</select>
118+
</label>
119+
<button
120+
className="secondaryButton compactButton"
121+
onClick={onApplyFilters}
122+
>
123+
Apply
124+
</button>
125+
</div>
126+
</div>
127+
</th>
128+
</tr>
183129
<tr>
184130
<th>Status</th>
185131
<th>Commit</th>
@@ -275,7 +221,7 @@ export const RunsPage = ({
275221
</footer>
276222
</>
277223
) : (
278-
<EmptyState title="No runs matched" body="Change the filters or trigger a new run." />
224+
<EmptyState title="No runs matched" body="Change the filters or wait for new attempts." />
279225
)}
280226
</section>
281227
</div>

0 commit comments

Comments
 (0)