From 622dd6aba4308678ce7d21d260730fe606d2c808 Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Tue, 20 Jun 2023 11:30:07 +0100 Subject: [PATCH] Show a table of Task retries if there were some --- .../presenters/TaskDetailsPresenter.server.ts | 12 +++ .../TaskAttemptStatus.tsx | 90 +++++++++++++++++++ .../route.tsx | 41 +++++++++ 3 files changed, 143 insertions(+) create mode 100644 apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/TaskAttemptStatus.tsx diff --git a/apps/webapp/app/presenters/TaskDetailsPresenter.server.ts b/apps/webapp/app/presenters/TaskDetailsPresenter.server.ts index 3a582d9bd..7f44a8aea 100644 --- a/apps/webapp/app/presenters/TaskDetailsPresenter.server.ts +++ b/apps/webapp/app/presenters/TaskDetailsPresenter.server.ts @@ -63,6 +63,18 @@ export class TaskDetailsPresenter { completedAt: true, style: true, parentId: true, + attempts: { + select: { + number: true, + status: true, + error: true, + runAt: true, + updatedAt: true, + }, + orderBy: { + number: "asc", + }, + }, }, where: { id, diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/TaskAttemptStatus.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/TaskAttemptStatus.tsx new file mode 100644 index 000000000..67c699f28 --- /dev/null +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/TaskAttemptStatus.tsx @@ -0,0 +1,90 @@ +import { + CheckCircleIcon, + ClockIcon, + XCircleIcon, +} from "@heroicons/react/24/solid"; +import { TaskAttemptStatus } from "@trigger.dev/database"; +import { Paragraph } from "~/components/primitives/Paragraph"; +import { Spinner } from "~/components/primitives/Spinner"; +import { cn } from "~/utils/cn"; + +type TaskAttemptStatusProps = { + status: TaskAttemptStatus; + className?: string; +}; + +export function TaskAttemptStatusLabel({ + status, +}: { + status: TaskAttemptStatus; +}) { + return ( + + + + {taskAttemptStatusTitle(status)} + + + ); +} + +export function TaskAttemptStatusIcon({ + status, + className, +}: TaskAttemptStatusProps) { + switch (status) { + case "COMPLETED": + return ( + + ); + case "PENDING": + return ( + + ); + case "STARTED": + return ( + + ); + case "ERRORED": + return ( + + ); + } +} + +function taskAttemptStatusClassNameColor(status: TaskAttemptStatus): string { + switch (status) { + case "COMPLETED": + return "text-green-500"; + case "PENDING": + return "text-slate-500"; + case "STARTED": + return "text-blue-500"; + case "ERRORED": + return "text-rose-500"; + } +} + +function taskAttemptStatusTitle(status: TaskAttemptStatus): string { + switch (status) { + case "COMPLETED": + return "Complete"; + case "PENDING": + return "Scheduled"; + case "STARTED": + return "Running"; + case "ERRORED": + return "Error"; + } +} diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/route.tsx index 21397c7dd..6686524eb 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam/route.tsx @@ -23,6 +23,15 @@ import { } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam/RunCard"; import { TaskStatusIcon } from "../_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam/TaskStatus"; import { sensitiveDataReplacer } from "~/services/logger"; +import { + Table, + TableBody, + TableCell, + TableHeader, + TableHeaderCell, + TableRow, +} from "~/components/primitives/Table"; +import { TaskAttemptStatusLabel } from "./TaskAttemptStatus"; export const loader = async ({ request, params }: LoaderArgs) => { const userId = await requireUserId(request); @@ -63,6 +72,7 @@ export default function Page() { properties, output, style, + attempts, } = task; return ( @@ -132,6 +142,37 @@ export default function Page() { )} + + {attempts.length > 0 && ( +
+ Retries + + + Attempt + Status + Date + Error + + + {attempts.map((attempt) => ( + + {attempt.number} + + + + + {attempt.status === "PENDING" && attempt.runAt + ? formatDateTime(attempt.runAt, "long") + : formatDateTime(attempt.updatedAt, "long")} + + {attempt.error} + + ))} + +
+
+ )} +
Input {params ? (