From a9e7cda37d76be25129a6e1c725512ed0aa45e1d Mon Sep 17 00:00:00 2001 From: Matt Aitken Date: Mon, 10 Jul 2023 15:47:13 +0100 Subject: [PATCH] Run page turned into components so it can be shared --- .../app/components/run/RunCompletedDetail.tsx | 73 ++++++++ .../webapp/app/components/run/RunOverview.tsx | 10 +- .../run}/TaskAttemptStatus.tsx | 0 apps/webapp/app/components/run/TaskDetail.tsx | 175 ++++++++++++++++++ .../app/components/run/TriggerDetail.tsx | 63 +++++++ ...r.ts => TriggerDetailsPresenter.server.ts} | 9 +- .../route.tsx | 72 +------ .../route.tsx | 174 +---------------- .../route.tsx | 66 ++----- 9 files changed, 330 insertions(+), 312 deletions(-) create mode 100644 apps/webapp/app/components/run/RunCompletedDetail.tsx rename apps/webapp/app/{routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.tasks.$taskParam => components/run}/TaskAttemptStatus.tsx (100%) create mode 100644 apps/webapp/app/components/run/TaskDetail.tsx create mode 100644 apps/webapp/app/components/run/TriggerDetail.tsx rename apps/webapp/app/presenters/{EventDetailsPresenter.server.ts => TriggerDetailsPresenter.server.ts} (81%) diff --git a/apps/webapp/app/components/run/RunCompletedDetail.tsx b/apps/webapp/app/components/run/RunCompletedDetail.tsx new file mode 100644 index 000000000..839b99bf5 --- /dev/null +++ b/apps/webapp/app/components/run/RunCompletedDetail.tsx @@ -0,0 +1,73 @@ +import { CodeBlock } from "~/components/code/CodeBlock"; +import { DateTime } from "~/components/primitives/DateTime"; +import { Paragraph } from "~/components/primitives/Paragraph"; +import { RunStatusIcon, RunStatusLabel } from "~/components/runs/RunStatuses"; +import { useRun } from "~/hooks/useRun"; +import { formatDuration } from "~/utils"; +import { + RunPanel, + RunPanelBody, + RunPanelDivider, + RunPanelError, + RunPanelHeader, + RunPanelIconProperty, + RunPanelIconSection, +} from "./RunCard"; + +export function RunCompletedDetail() { + const run = useRun(); + + return ( + + } + title={ + + + + } + /> + + + {run.startedAt && ( + } + /> + )} + {run.completedAt && ( + } + /> + )} + {run.startedAt && run.completedAt && ( + + )} + + + {run.error && ( + + )} + {run.output ? ( + + ) : ( + run.output === null && ( + This run returned nothing + ) + )} + + + ); +} diff --git a/apps/webapp/app/components/run/RunOverview.tsx b/apps/webapp/app/components/run/RunOverview.tsx index bb31546a4..88c22fe83 100644 --- a/apps/webapp/app/components/run/RunOverview.tsx +++ b/apps/webapp/app/components/run/RunOverview.tsx @@ -169,15 +169,7 @@ export function RunOverview({ selected={selectedId === "trigger"} onClick={() => navigate(runTriggerPath(paths.run))} > - } - title={ - - } - /> + + + } + title={} + accessory={ + + + + } + /> + + + {startedAt && ( + } + /> + )} + {completedAt && ( + } + /> + )} + {delayUntil && !completedAt && ( + <> + } + /> + + + )} + {delayUntil && completedAt && ( + + )} + + + {description && ( + + )} + {properties.length > 0 && ( +
+ Properties + +
+ )} + + {attempts.length > 1 && ( +
+ Retries + + + + Attempt + Status + Date + Error + + + + {attempts.map((attempt) => ( + + {attempt.number} + + + + + + + {attempt.error} + + ))} + +
+
+ )} + +
+ Input + {params ? ( + + ) : ( + No input + )} +
+
+ Output + {output ? ( + + ) : ( + No output + )} +
+
+ + ); +} diff --git a/apps/webapp/app/components/run/TriggerDetail.tsx b/apps/webapp/app/components/run/TriggerDetail.tsx new file mode 100644 index 000000000..7ff1d9817 --- /dev/null +++ b/apps/webapp/app/components/run/TriggerDetail.tsx @@ -0,0 +1,63 @@ +import { DetailedEvent } from "~/presenters/TriggerDetailsPresenter.server"; +import { CodeBlock } from "../code/CodeBlock"; +import { DateTime } from "../primitives/DateTime"; +import { Header3 } from "../primitives/Headers"; +import { + RunPanel, + RunPanelBody, + RunPanelDivider, + RunPanelHeader, + RunPanelIconProperty, + RunPanelIconSection, + RunPanelProperties, +} from "./RunCard"; +import { DisplayProperty } from "@trigger.dev/internal"; + +export function TriggerDetail({ + trigger, + event, + properties, +}: { + trigger: DetailedEvent; + event: { + title: string; + icon: string; + }; + properties: DisplayProperty[]; +}) { + const { id, name, payload, timestamp, deliveredAt } = trigger; + + return ( + + + + + } + /> + {deliveredAt && ( + } + /> + )} + + + +
+ {properties.length > 0 && ( +
+ Properties + +
+ )} + Payload + +
+
+
+ ); +} diff --git a/apps/webapp/app/presenters/EventDetailsPresenter.server.ts b/apps/webapp/app/presenters/TriggerDetailsPresenter.server.ts similarity index 81% rename from apps/webapp/app/presenters/EventDetailsPresenter.server.ts rename to apps/webapp/app/presenters/TriggerDetailsPresenter.server.ts index e8771a60f..b46377068 100644 --- a/apps/webapp/app/presenters/EventDetailsPresenter.server.ts +++ b/apps/webapp/app/presenters/TriggerDetailsPresenter.server.ts @@ -1,15 +1,10 @@ import { PrismaClient, prisma } from "~/db.server"; -type DetailsProps = { - id: string; - userId: string; -}; - export type DetailedEvent = NonNullable< - Awaited> + Awaited> >; -export class EventDetailsPresenter { +export class TriggerDetailsPresenter { #prismaClient: PrismaClient; constructor(prismaClient: PrismaClient = prisma) { diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.completed/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.completed/route.tsx index 2226328b3..0f82e7cac 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.completed/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.completed/route.tsx @@ -1,73 +1,5 @@ -import { CodeBlock } from "~/components/code/CodeBlock"; -import { DateTime } from "~/components/primitives/DateTime"; -import { Paragraph } from "~/components/primitives/Paragraph"; -import { RunStatusIcon, RunStatusLabel } from "~/components/runs/RunStatuses"; -import { useRun } from "~/hooks/useRun"; -import { formatDuration } from "~/utils"; -import { - RunPanel, - RunPanelBody, - RunPanelDivider, - RunPanelError, - RunPanelHeader, - RunPanelIconProperty, - RunPanelIconSection, -} from "../../components/run/RunCard"; +import { RunCompletedDetail } from "~/components/run/RunCompletedDetail"; export default function RunCompletedPage() { - const run = useRun(); - - return ( - - } - title={ - - - - } - /> - - - {run.startedAt && ( - } - /> - )} - {run.completedAt && ( - } - /> - )} - {run.startedAt && run.completedAt && ( - - )} - - - {run.error && ( - - )} - {run.output ? ( - - ) : ( - run.output === null && ( - This run returned nothing - ) - )} - - - ); + return ; } 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 31200180c..86ffe8131 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 @@ -1,38 +1,9 @@ import { LoaderArgs } from "@remix-run/server-runtime"; import { typedjson, useTypedLoaderData } from "remix-typedjson"; -import { CodeBlock } from "~/components/code/CodeBlock"; -import { DateTime } from "~/components/primitives/DateTime"; -import { Header3 } from "~/components/primitives/Headers"; -import { Paragraph } from "~/components/primitives/Paragraph"; -import { - Table, - TableBody, - TableCell, - TableHeader, - TableHeaderCell, - TableRow, -} from "~/components/primitives/Table"; +import { TaskDetail } from "~/components/run/TaskDetail"; import { TaskDetailsPresenter } from "~/presenters/TaskDetailsPresenter.server"; -import { sensitiveDataReplacer } from "~/services/sensitiveDataReplacer"; import { requireUserId } from "~/services/session.server"; -import { formatDuration } from "~/utils"; -import { cn } from "~/utils/cn"; import { TaskParamsSchema } from "~/utils/pathBuilder"; -import { - RunPanel, - RunPanelBody, - RunPanelDescription, - RunPanelDivider, - RunPanelHeader, - RunPanelIconProperty, - RunPanelIconSection, - RunPanelIconTitle, - RunPanelProperties, - UpdatingDelay, - UpdatingDuration, -} from "../../components/run/RunCard"; -import { TaskAttemptStatusLabel } from "./TaskAttemptStatus"; -import { TaskStatusIcon } from "~/components/run/TaskStatus"; export const loader = async ({ request, params }: LoaderArgs) => { const userId = await requireUserId(request); @@ -57,146 +28,5 @@ export const loader = async ({ request, params }: LoaderArgs) => { export default function Page() { const { task } = useTypedLoaderData(); - - const { - name, - description, - icon, - startedAt, - completedAt, - status, - delayUntil, - params, - properties, - output, - style, - attempts, - } = task; - - return ( - - - } - title={} - accessory={ - - - - } - /> - - - {startedAt && ( - } - /> - )} - {completedAt && ( - } - /> - )} - {delayUntil && !completedAt && ( - <> - } - /> - - - )} - {delayUntil && completedAt && ( - - )} - - - {description && ( - - )} - {properties.length > 0 && ( -
- Properties - -
- )} - - {attempts.length > 1 && ( -
- Retries - - - - Attempt - Status - Date - Error - - - - {attempts.map((attempt) => ( - - {attempt.number} - - - - - - - {attempt.error} - - ))} - -
-
- )} - -
- Input - {params ? ( - - ) : ( - No input - )} -
-
- Output - {output ? ( - - ) : ( - No output - )} -
-
-
- ); + return ; } diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.trigger/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.trigger/route.tsx index 4b9ab8fe1..043effc4d 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.trigger/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.jobs.$jobParam.runs.$runParam.trigger/route.tsx @@ -1,80 +1,38 @@ import { LoaderArgs } from "@remix-run/server-runtime"; import { typedjson, useTypedLoaderData } from "remix-typedjson"; -import { CodeBlock } from "~/components/code/CodeBlock"; -import { DateTime } from "~/components/primitives/DateTime"; -import { Header3 } from "~/components/primitives/Headers"; +import { TriggerDetail } from "~/components/run/TriggerDetail"; import { useJob } from "~/hooks/useJob"; import { useRun } from "~/hooks/useRun"; -import { EventDetailsPresenter } from "~/presenters/EventDetailsPresenter.server"; +import { TriggerDetailsPresenter } from "~/presenters/TriggerDetailsPresenter.server"; import { RunParamsSchema } from "~/utils/pathBuilder"; -import { - RunPanel, - RunPanelBody, - RunPanelDivider, - RunPanelHeader, - RunPanelIconProperty, - RunPanelIconSection, - RunPanelProperties, -} from "../../components/run/RunCard"; export const loader = async ({ request, params }: LoaderArgs) => { const { runParam } = RunParamsSchema.parse(params); - const presenter = new EventDetailsPresenter(); - const event = await presenter.call(runParam); + const presenter = new TriggerDetailsPresenter(); + const trigger = await presenter.call(runParam); - if (!event) { + if (!trigger) { throw new Response(null, { status: 404, }); } return typedjson({ - event, + trigger, }); }; export default function Page() { - const { event } = useTypedLoaderData(); + const { trigger } = useTypedLoaderData(); const job = useJob(); const run = useRun(); - const { id, name, payload, timestamp, deliveredAt } = event; - return ( - - - - - } - /> - {deliveredAt && ( - } - /> - )} - - - -
- {run.properties.length > 0 && ( -
- Properties - -
- )} - Payload - -
-
-
+ ); }