Skip to content

Commit 826a64f

Browse files
committed
If your dev run hasn’t started, display an info panel saying you need to run the CLI
1 parent d1849b0 commit 826a64f

File tree

1 file changed

+95
-52
lines changed
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.runs.$runParam

1 file changed

+95
-52
lines changed

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

Lines changed: 95 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@ import {
1212
millisecondsToNanoseconds,
1313
nanosecondsToMilliseconds,
1414
} from "@trigger.dev/core/v3";
15+
import { RuntimeEnvironmentType } from "@trigger.dev/database";
1516
import { motion } from "framer-motion";
1617
import { useEffect, useRef, useState } from "react";
1718
import { typedjson, useTypedLoaderData } from "remix-typedjson";
1819
import { ShowParentIcon, ShowParentIconSelected } from "~/assets/icons/ShowParentIcon";
1920
import tileBgPath from "~/assets/images/[email protected]";
2021
import { BlankstateInstructions } from "~/components/BlankstateInstructions";
22+
import { InlineCode } from "~/components/code/InlineCode";
2123
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
2224
import { MainCenteredContainer, PageBody } from "~/components/layout/AppLayout";
2325
import { Badge } from "~/components/primitives/Badge";
2426
import { LinkButton } from "~/components/primitives/Buttons";
27+
import { Callout } from "~/components/primitives/Callout";
2528
import { Input } from "~/components/primitives/Input";
2629
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
2730
import { Paragraph } from "~/components/primitives/Paragraph";
@@ -181,6 +184,7 @@ export default function Page() {
181184
totalDuration={duration}
182185
rootSpanStatus={rootSpanStatus}
183186
rootStartedAt={rootStartedAt}
187+
environmentType={run.environment.type}
184188
/>
185189
) : (
186190
<ResizablePanelGroup
@@ -209,6 +213,7 @@ export default function Page() {
209213
totalDuration={duration}
210214
rootSpanStatus={rootSpanStatus}
211215
rootStartedAt={rootStartedAt}
216+
environmentType={run.environment.type}
212217
/>
213218
</ResizablePanel>
214219
<ResizableHandle withHandle />
@@ -231,6 +236,7 @@ type TasksTreeViewProps = {
231236
totalDuration: number;
232237
rootSpanStatus: "executing" | "completed" | "failed";
233238
rootStartedAt: Date | undefined;
239+
environmentType: RuntimeEnvironmentType;
234240
};
235241

236242
function TasksTreeView({
@@ -241,6 +247,7 @@ function TasksTreeView({
241247
totalDuration,
242248
rootSpanStatus,
243249
rootStartedAt,
250+
environmentType,
244251
}: TasksTreeViewProps) {
245252
const [filterText, setFilterText] = useState("");
246253
const [errorsOnly, setErrorsOnly] = useState(false);
@@ -345,63 +352,68 @@ function TasksTreeView({
345352
getNodeProps={getNodeProps}
346353
getTreeProps={getTreeProps}
347354
renderNode={({ node, state }) => (
348-
<div
349-
className={cn(
350-
"delay-[25ms] flex h-8 cursor-pointer items-center overflow-hidden rounded-l-sm pr-2 transition-colors",
351-
state.selected
352-
? "bg-grid-dimmed hover:bg-grid-bright"
353-
: "bg-transparent hover:bg-grid-dimmed"
354-
)}
355-
onClick={() => {
356-
toggleNodeSelection(node.id);
357-
}}
358-
>
359-
<div className="flex h-8 items-center">
360-
{Array.from({ length: node.level }).map((_, index) => (
361-
<TaskLine
362-
key={index}
363-
isError={node.data.isError}
364-
isSelected={state.selected}
365-
/>
366-
))}
367-
<div
368-
className={cn(
369-
"flex h-8 w-4 items-center",
370-
node.hasChildren && "hover:bg-charcoal-600"
371-
)}
372-
onClick={(e) => {
373-
e.stopPropagation();
374-
toggleExpandNode(node.id);
375-
scrollToNode(node.id);
376-
}}
377-
>
378-
{node.hasChildren ? (
379-
state.expanded ? (
380-
<ChevronDownIcon className="h-4 w-4 text-charcoal-400" />
355+
<>
356+
<div
357+
className={cn(
358+
"delay-[25ms] flex h-8 cursor-pointer items-center overflow-hidden rounded-l-sm pr-2 transition-colors",
359+
state.selected
360+
? "bg-grid-dimmed hover:bg-grid-bright"
361+
: "bg-transparent hover:bg-grid-dimmed"
362+
)}
363+
onClick={() => {
364+
toggleNodeSelection(node.id);
365+
}}
366+
>
367+
<div className="flex h-8 items-center">
368+
{Array.from({ length: node.level }).map((_, index) => (
369+
<TaskLine
370+
key={index}
371+
isError={node.data.isError}
372+
isSelected={state.selected}
373+
/>
374+
))}
375+
<div
376+
className={cn(
377+
"flex h-8 w-4 items-center",
378+
node.hasChildren && "hover:bg-charcoal-600"
379+
)}
380+
onClick={(e) => {
381+
e.stopPropagation();
382+
toggleExpandNode(node.id);
383+
scrollToNode(node.id);
384+
}}
385+
>
386+
{node.hasChildren ? (
387+
state.expanded ? (
388+
<ChevronDownIcon className="h-4 w-4 text-charcoal-400" />
389+
) : (
390+
<ChevronRightIcon className="h-4 w-4 text-charcoal-400" />
391+
)
381392
) : (
382-
<ChevronRightIcon className="h-4 w-4 text-charcoal-400" />
383-
)
384-
) : (
385-
<div className="h-8 w-4" />
386-
)}
393+
<div className="h-8 w-4" />
394+
)}
395+
</div>
387396
</div>
388-
</div>
389397

390-
<div className="flex w-full items-center justify-between gap-2 pl-1">
391-
<div className="flex items-center gap-2 overflow-x-hidden">
392-
<RunIcon
393-
name={node.data.style?.icon}
394-
spanName={node.data.message}
395-
className="h-4 min-h-4 w-4 min-w-4"
396-
/>
397-
<NodeText node={node} />
398-
{node.data.isRoot && <Badge variant="outline-rounded">Root</Badge>}
399-
</div>
400-
<div className="flex items-center gap-1">
401-
<NodeStatusIcon node={node} />
398+
<div className="flex w-full items-center justify-between gap-2 pl-1">
399+
<div className="flex items-center gap-2 overflow-x-hidden">
400+
<RunIcon
401+
name={node.data.style?.icon}
402+
spanName={node.data.message}
403+
className="h-4 min-h-4 w-4 min-w-4"
404+
/>
405+
<NodeText node={node} />
406+
{node.data.isRoot && <Badge variant="outline-rounded">Root</Badge>}
407+
</div>
408+
<div className="flex items-center gap-1">
409+
<NodeStatusIcon node={node} />
410+
</div>
402411
</div>
403412
</div>
404-
</div>
413+
{events.length === 1 && environmentType === "DEVELOPMENT" && (
414+
<ConnectedDevWarning />
415+
)}
416+
</>
405417
)}
406418
onScroll={(scrollTop) => {
407419
//sync the scroll to the tree
@@ -841,3 +853,34 @@ function CurrentTimeIndicator({ totalDuration }: { totalDuration: number }) {
841853
</Timeline.FollowCursor>
842854
);
843855
}
856+
857+
function ConnectedDevWarning() {
858+
const [isVisible, setIsVisible] = useState(false);
859+
860+
useEffect(() => {
861+
const timer = setTimeout(() => {
862+
setIsVisible(true);
863+
}, 3000);
864+
865+
return () => clearTimeout(timer);
866+
}, []);
867+
868+
return (
869+
<div
870+
className={cn(
871+
"flex items-center overflow-hidden pl-5 pr-2 transition-opacity duration-500",
872+
isVisible ? "opacity-100" : "h-0 opacity-0"
873+
)}
874+
>
875+
<Callout variant="info">
876+
<div className="flex flex-col gap-1">
877+
<Paragraph variant="small">
878+
Runs usually start within 1 second in{" "}
879+
<EnvironmentLabel environment={{ type: "DEVELOPMENT" }} />. Check you're running the
880+
CLI: <InlineCode className="whitespace-nowrap">npx trigger.dev@beta dev</InlineCode>
881+
</Paragraph>
882+
</div>
883+
</Callout>
884+
</div>
885+
);
886+
}

0 commit comments

Comments
 (0)