Skip to content

Commit 1d27933

Browse files
0skiOskar Otwinowski
authored andcommitted
feat(webapp): persist runs table filters via tableState URL parameter
- Store current filter state from runs table as `tableState` search param when navigating to individual run pages - Restore filters when navigating back from run detail view to runs list - Update `v3RunPath` and `v3RunSpanPath` helpers to accept optional searchParams - Use `useOptimisticLocation` to capture current search params in TaskRunsTable - Parse `tableState` param in run detail route and pass filters to back button This improves UX by remembering filter selections (task, status, date range, etc.) when users click into a run and then navigate back to the runs list.
1 parent cf63fc9 commit 1d27933

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

apps/webapp/app/components/runs/v3/TaskRunsTable.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import {
5555
filterableTaskRunStatuses,
5656
TaskRunStatusCombo,
5757
} from "./TaskRunStatus";
58+
import { useOptimisticLocation } from "~/hooks/useOptimisticLocation";
5859

5960
type RunsTableProps = {
6061
total: number;
@@ -81,6 +82,8 @@ export function TaskRunsTable({
8182
const checkboxes = useRef<(HTMLInputElement | null)[]>([]);
8283
const { has, hasAll, select, deselect, toggle } = useSelectedItems(allowSelection);
8384
const { isManagedCloud } = useFeatures();
85+
const location = useOptimisticLocation();
86+
const tableStateParam = encodeURIComponent(location.search);
8487

8588
const showCompute = isManagedCloud;
8689

@@ -293,16 +296,20 @@ export function TaskRunsTable({
293296
<BlankState isLoading={isLoading} filters={filters} />
294297
) : (
295298
runs.map((run, index) => {
299+
const searchParams = new URLSearchParams();
300+
if (tableStateParam) {
301+
searchParams.set("tableState", tableStateParam);
302+
}
296303
const path = v3RunSpanPath(organization, project, run.environment, run, {
297304
spanId: run.spanId,
298-
});
305+
}, searchParams);
299306
return (
300307
<TableRow key={run.id}>
301308
{allowSelection && (
302309
<TableCell className="pl-3 pr-0">
303310
<Checkbox
304311
checked={has(run.friendlyId)}
305-
onChange={(element) => {
312+
onChange={() => {
306313
toggle(run.friendlyId);
307314
}}
308315
ref={(r) => {

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import { SpanView } from "../resources.orgs.$organizationSlug.projects.$projectP
9898
import { useSearchParams } from "~/hooks/useSearchParam";
9999
import { CopyableText } from "~/components/primitives/CopyableText";
100100
import type { SpanOverride } from "~/v3/eventRepository/eventRepository.types";
101+
import { getRunFiltersFromSearchParams } from "~/components/runs/v3/RunFilters";
101102

102103
const resizableSettings = {
103104
parent: {
@@ -191,13 +192,17 @@ export default function Page() {
191192
logCount: trace?.events.length ?? 0,
192193
isCompleted: run.completedAt !== null,
193194
});
195+
const { value } = useSearchParams();
196+
const params = decodeURIComponent(value("tableState") ?? "");
197+
const searchParams = new URLSearchParams(params);
198+
const filters = getRunFiltersFromSearchParams(searchParams);
194199

195200
return (
196201
<>
197202
<NavBar>
198203
<PageTitle
199204
backButton={{
200-
to: v3RunsPath(organization, project, environment),
205+
to: v3RunsPath(organization, project, environment, filters),
201206
text: "Runs",
202207
}}
203208
title={<CopyableText value={run.friendlyId} />}

apps/webapp/app/utils/pathBuilder.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -288,15 +288,17 @@ export function v3RunPath(
288288
organization: OrgForPath,
289289
project: ProjectForPath,
290290
environment: EnvironmentForPath,
291-
run: v3RunForPath
291+
run: v3RunForPath,
292+
searchParams?: URLSearchParams
292293
) {
293-
return `${v3RunsPath(organization, project, environment)}/${run.friendlyId}`;
294+
const query = searchParams ? `?${searchParams.toString()}` : "";
295+
return `${v3RunsPath(organization, project, environment)}/${run.friendlyId}${query}`;
294296
}
295297

296298
export function v3RunRedirectPath(
297299
organization: OrgForPath,
298300
project: ProjectForPath,
299-
run: v3RunForPath
301+
run: v3RunForPath,
300302
) {
301303
return `${v3ProjectPath(organization, project)}/runs/${run.friendlyId}`;
302304
}
@@ -310,9 +312,12 @@ export function v3RunSpanPath(
310312
project: ProjectForPath,
311313
environment: EnvironmentForPath,
312314
run: v3RunForPath,
313-
span: v3SpanForPath
315+
span: v3SpanForPath,
316+
searchParams?: URLSearchParams
314317
) {
315-
return `${v3RunPath(organization, project, environment, run)}?span=${span.spanId}`;
318+
searchParams = searchParams ?? new URLSearchParams();
319+
searchParams.set("span", encodeURIComponent(span.spanId));
320+
return `${v3RunPath(organization, project, environment, run, searchParams)}`;
316321
}
317322

318323
export function v3RunStreamingPath(

0 commit comments

Comments
 (0)