@@ -12,16 +12,19 @@ import {
12
12
millisecondsToNanoseconds ,
13
13
nanosecondsToMilliseconds ,
14
14
} from "@trigger.dev/core/v3" ;
15
+ import { RuntimeEnvironmentType } from "@trigger.dev/database" ;
15
16
import { motion } from "framer-motion" ;
16
17
import { useEffect , useRef , useState } from "react" ;
17
18
import { typedjson , useTypedLoaderData } from "remix-typedjson" ;
18
19
import { ShowParentIcon , ShowParentIconSelected } from "~/assets/icons/ShowParentIcon" ;
19
20
import tileBgPath from "~/assets/images/[email protected] " ;
20
21
import { BlankstateInstructions } from "~/components/BlankstateInstructions" ;
22
+ import { InlineCode } from "~/components/code/InlineCode" ;
21
23
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel" ;
22
24
import { MainCenteredContainer , PageBody } from "~/components/layout/AppLayout" ;
23
25
import { Badge } from "~/components/primitives/Badge" ;
24
26
import { LinkButton } from "~/components/primitives/Buttons" ;
27
+ import { Callout } from "~/components/primitives/Callout" ;
25
28
import { Input } from "~/components/primitives/Input" ;
26
29
import { NavBar , PageAccessories , PageTitle } from "~/components/primitives/PageHeader" ;
27
30
import { Paragraph } from "~/components/primitives/Paragraph" ;
@@ -181,6 +184,7 @@ export default function Page() {
181
184
totalDuration = { duration }
182
185
rootSpanStatus = { rootSpanStatus }
183
186
rootStartedAt = { rootStartedAt }
187
+ environmentType = { run . environment . type }
184
188
/>
185
189
) : (
186
190
< ResizablePanelGroup
@@ -209,6 +213,7 @@ export default function Page() {
209
213
totalDuration = { duration }
210
214
rootSpanStatus = { rootSpanStatus }
211
215
rootStartedAt = { rootStartedAt }
216
+ environmentType = { run . environment . type }
212
217
/>
213
218
</ ResizablePanel >
214
219
< ResizableHandle withHandle />
@@ -231,6 +236,7 @@ type TasksTreeViewProps = {
231
236
totalDuration : number ;
232
237
rootSpanStatus : "executing" | "completed" | "failed" ;
233
238
rootStartedAt : Date | undefined ;
239
+ environmentType : RuntimeEnvironmentType ;
234
240
} ;
235
241
236
242
function TasksTreeView ( {
@@ -241,6 +247,7 @@ function TasksTreeView({
241
247
totalDuration,
242
248
rootSpanStatus,
243
249
rootStartedAt,
250
+ environmentType,
244
251
} : TasksTreeViewProps ) {
245
252
const [ filterText , setFilterText ] = useState ( "" ) ;
246
253
const [ errorsOnly , setErrorsOnly ] = useState ( false ) ;
@@ -345,63 +352,68 @@ function TasksTreeView({
345
352
getNodeProps = { getNodeProps }
346
353
getTreeProps = { getTreeProps }
347
354
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
+ )
381
392
) : (
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 >
387
396
</ div >
388
- </ div >
389
397
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 >
402
411
</ div >
403
412
</ div >
404
- </ div >
413
+ { events . length === 1 && environmentType === "DEVELOPMENT" && (
414
+ < ConnectedDevWarning />
415
+ ) }
416
+ </ >
405
417
) }
406
418
onScroll = { ( scrollTop ) => {
407
419
//sync the scroll to the tree
@@ -841,3 +853,34 @@ function CurrentTimeIndicator({ totalDuration }: { totalDuration: number }) {
841
853
</ Timeline . FollowCursor >
842
854
) ;
843
855
}
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