Skip to content

Commit 35c7a1e

Browse files
authored
Bulk action 2 fixes (#2267)
* Fix for filtering by run id Simplified to have a single filter for runId which accepts an array. This unifies the filtering by multiple runs (used by the waitpoint page) and the individual run filtering. It fixes a bug with bulk actions * Truncate long bulk action titles
1 parent a64875a commit 35c7a1e

File tree

9 files changed

+47
-27
lines changed

9 files changed

+47
-27
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export const TaskRunListSearchFilters = z.object({
104104
to: z.coerce.number().optional(),
105105
rootOnly: z.coerce.boolean().optional(),
106106
batchId: z.string().optional(),
107-
runId: z.string().optional(),
107+
runId: StringOrStringArray,
108108
scheduleId: z.string().optional(),
109109
});
110110

@@ -199,7 +199,10 @@ export function getRunFiltersFromSearchParams(
199199
from: searchParams.get("from") ?? undefined,
200200
to: searchParams.get("to") ?? undefined,
201201
rootOnly: searchParams.has("rootOnly") ? searchParams.get("rootOnly") === "true" : undefined,
202-
runId: searchParams.get("runId") ?? undefined,
202+
runId:
203+
searchParams.getAll("runId").filter((v) => v.length > 0).length > 0
204+
? searchParams.getAll("runId")
205+
: undefined,
203206
batchId: searchParams.get("batchId") ?? undefined,
204207
scheduleId: searchParams.get("scheduleId") ?? undefined,
205208
};

apps/webapp/app/presenters/RunFilters.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export async function getRunFiltersFromRequest(request: Request) {
4141
from,
4242
to,
4343
batchId,
44-
runIds: runId ? [runId] : undefined,
44+
runId,
4545
scheduleId,
4646
rootOnly: rootOnlyValue,
4747
direction: direction,

apps/webapp/app/presenters/v3/BulkActionPresenter.server.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ export class BulkActionPresenter extends BasePresenter {
5353
);
5454

5555
let mode: BulkActionMode = "filter";
56-
if (filtersParsed.success && Object.keys(filtersParsed.data).length === 0) {
56+
if (
57+
filtersParsed.success &&
58+
Object.keys(filtersParsed.data).length === 1 &&
59+
filtersParsed.data.runId?.length
60+
) {
5761
mode = "selected";
5862
}
5963

apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { ClickHouse } from "@internal/clickhouse";
2-
import { PrismaClient, PrismaClientOrTransaction, type TaskRunStatus } from "@trigger.dev/database";
1+
import { type ClickHouse } from "@internal/clickhouse";
2+
import {
3+
type PrismaClient,
4+
type PrismaClientOrTransaction,
5+
type TaskRunStatus,
6+
} from "@trigger.dev/database";
37
import { type Direction } from "~/components/ListPagination";
48
import { timeFilters } from "~/components/runs/v3/SharedFilters";
59
import { findDisplayableEnvironment } from "~/models/runtimeEnvironment.server";
610
import { getAllTaskIdentifiers } from "~/models/task.server";
711
import { RunsRepository } from "~/services/runsRepository.server";
812
import { ServiceValidationError } from "~/v3/services/baseService.server";
913
import { isCancellableRunStatus, isFinalRunStatus, isPendingRunStatus } from "~/v3/taskStatus";
10-
import parseDuration from "parse-duration";
1114

1215
export type RunListOptions = {
1316
userId?: string;
@@ -25,7 +28,7 @@ export type RunListOptions = {
2528
isTest?: boolean;
2629
rootOnly?: boolean;
2730
batchId?: string;
28-
runIds?: string[];
31+
runId?: string[];
2932
//pagination
3033
direction?: Direction;
3134
cursor?: string;
@@ -60,7 +63,7 @@ export class NextRunListPresenter {
6063
isTest,
6164
rootOnly,
6265
batchId,
63-
runIds,
66+
runId,
6467
from,
6568
to,
6669
direction = "forward",
@@ -85,7 +88,7 @@ export class NextRunListPresenter {
8588
(scheduleId !== undefined && scheduleId !== "") ||
8689
(tags !== undefined && tags.length > 0) ||
8790
batchId !== undefined ||
88-
(runIds !== undefined && runIds.length > 0) ||
91+
(runId !== undefined && runId.length > 0) ||
8992
typeof isTest === "boolean" ||
9093
rootOnly === true ||
9194
!time.isDefault;
@@ -167,7 +170,7 @@ export class NextRunListPresenter {
167170
isTest,
168171
rootOnly,
169172
batchId,
170-
runIds,
173+
runId,
171174
bulkId,
172175
page: {
173176
size: pageSize,

apps/webapp/app/presenters/v3/WaitpointPresenter.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export class WaitpointPresenter extends BasePresenter {
8585
environmentId,
8686
{
8787
projectId: projectId,
88-
runIds: connectedRunIds,
88+
runId: connectedRunIds,
8989
pageSize: 5,
9090
period: "31d",
9191
}

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.bulk-actions.$bulkActionParam/route.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ export default function Page() {
157157

158158
return (
159159
<div className="grid h-full max-h-full grid-rows-[2.5rem_2.5rem_1fr_3.25rem] overflow-hidden bg-background-bright">
160-
<div className="mx-3 flex items-center justify-between gap-2 border-b border-grid-dimmed">
161-
<Header2 className={cn("whitespace-nowrap")}>
160+
<div className="mx-3 flex items-center justify-between gap-2 overflow-x-hidden border-b border-grid-dimmed">
161+
<Header2 className={cn("truncate whitespace-nowrap")}>
162162
{bulkAction.name || bulkAction.friendlyId}
163163
</Header2>
164164
<LinkButton

apps/webapp/app/services/runsRepository.server.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,15 @@ const RunListInputOptionsSchema = z.object({
3434
isTest: z.boolean().optional(),
3535
rootOnly: z.boolean().optional(),
3636
batchId: z.string().optional(),
37-
runIds: z.array(z.string()).optional(),
37+
runId: z.array(z.string()).optional(),
3838
bulkId: z.string().optional(),
3939
});
4040

4141
export type RunListInputOptions = z.infer<typeof RunListInputOptionsSchema>;
42+
export type RunListInputFilters = Omit<
43+
RunListInputOptions,
44+
"organizationId" | "projectId" | "environmentId"
45+
>;
4246

4347
type FilterRunsOptions = Omit<RunListInputOptions, "period"> & {
4448
period: number | undefined;
@@ -256,13 +260,13 @@ export class RunsRepository {
256260
convertedOptions.bulkId = BulkActionId.toId(options.bulkId);
257261
}
258262

259-
if (options.runIds) {
263+
if (options.runId) {
260264
//convert to friendlyId
261-
convertedOptions.runIds = options.runIds.map((runId) => RunId.toFriendlyId(runId));
265+
convertedOptions.runId = options.runId.map((r) => RunId.toFriendlyId(r));
262266
}
263267

264268
// Show all runs if we are filtering by batchId or runId
265-
if (options.batchId || options.runIds?.length || options.scheduleId || options.tasks?.length) {
269+
if (options.batchId || options.runId?.length || options.scheduleId || options.tasks?.length) {
266270
convertedOptions.rootOnly = false;
267271
}
268272

@@ -342,9 +346,10 @@ function applyRunFiltersToQueryBuilder<T>(
342346
});
343347
}
344348

345-
if (options.runIds && options.runIds.length > 0) {
349+
if (options.runId && options.runId.length > 0) {
350+
// it's important that in the query it's "runIds", otherwise it clashes with the cursor which is called "runId"
346351
queryBuilder.where("friendly_id IN {runIds: Array(String)}", {
347-
runIds: options.runIds.map((runId) => RunId.toFriendlyId(runId)),
352+
runIds: options.runId.map((runId) => RunId.toFriendlyId(runId)),
348353
});
349354
}
350355
}

apps/webapp/app/v3/services/bulk/BulkActionV2.server.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import {
88
import { getRunFiltersFromRequest } from "~/presenters/RunFilters.server";
99
import { type CreateBulkActionPayload } from "~/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.bulkaction";
1010
import { clickhouseClient } from "~/services/clickhouseInstance.server";
11-
import { parseRunListInputOptions, RunsRepository } from "~/services/runsRepository.server";
11+
import {
12+
parseRunListInputOptions,
13+
type RunListInputFilters,
14+
RunsRepository,
15+
} from "~/services/runsRepository.server";
1216
import { BaseService } from "../baseService.server";
1317
import { commonWorker } from "~/v3/commonWorker.server";
1418
import { env } from "~/env.server";
@@ -378,12 +382,13 @@ export class BulkActionService extends BaseService {
378382
}
379383
}
380384

381-
async function getFilters(payload: CreateBulkActionPayload, request: Request) {
385+
async function getFilters(
386+
payload: CreateBulkActionPayload,
387+
request: Request
388+
): Promise<RunListInputFilters> {
382389
if (payload.mode === "selected") {
383390
return {
384-
runIds: payload.selectedRunIds,
385-
cursor: undefined,
386-
direction: undefined,
391+
runId: payload.selectedRunIds,
387392
};
388393
}
389394

apps/webapp/test/runsRepository.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,7 @@ describe("RunsRepository", () => {
10631063
projectId: project.id,
10641064
environmentId: runtimeEnvironment.id,
10651065
organizationId: organization.id,
1066-
runIds: ["run_abc", "run_xyz"],
1066+
runId: ["run_abc", "run_xyz"],
10671067
});
10681068

10691069
expect(runs).toHaveLength(2);
@@ -1171,7 +1171,7 @@ describe("RunsRepository", () => {
11711171
projectId: project.id,
11721172
environmentId: runtimeEnvironment.id,
11731173
organizationId: organization.id,
1174-
runIds: [run1.friendlyId, run3.friendlyId],
1174+
runId: [run1.friendlyId, run3.friendlyId],
11751175
});
11761176

11771177
expect(runs).toHaveLength(2);

0 commit comments

Comments
 (0)