@@ -639,7 +639,7 @@ function InspectorPane({ session, status }: { session: LoadedSession; status: Se
639639 { tab === "overview" ? (
640640 < OverviewTab session = { session } status = { status } />
641641 ) : tab === "runs" ? (
642- < RunsTab session = { session } allRunsPath = { allRunsPath } />
642+ < RunsTab session = { session } status = { status } allRunsPath = { allRunsPath } />
643643 ) : (
644644 < MetadataTab session = { session } />
645645 ) }
@@ -821,7 +821,15 @@ function MetadataTab({ session }: { session: LoadedSession }) {
821821 return < CodeBlock code = { json } language = "json" showLineNumbers = { false } showTextWrapping /> ;
822822}
823823
824- function RunsTab ( { session, allRunsPath } : { session : LoadedSession ; allRunsPath : string } ) {
824+ function RunsTab ( {
825+ session,
826+ status,
827+ allRunsPath,
828+ } : {
829+ session : LoadedSession ;
830+ status : SessionStatus ;
831+ allRunsPath : string ;
832+ } ) {
825833 const organization = useOrganization ( ) ;
826834 const project = useProject ( ) ;
827835 const environment = useEnvironment ( ) ;
@@ -831,55 +839,94 @@ function RunsTab({ session, allRunsPath }: { session: LoadedSession; allRunsPath
831839 }
832840
833841 return (
834- < div className = "flex flex-col gap-3" >
835- < Property . Table >
836- { session . runs . map ( ( entry ) => {
837- const runPath = entry . run
838- ? v3RunPath ( organization , project , environment , {
839- friendlyId : entry . run . friendlyId ,
840- } )
841- : undefined ;
842- return (
843- < Property . Item key = { entry . id } >
844- < Property . Label >
845- < div className = "flex flex-col gap-0.5" >
846- < span className = "capitalize" > { entry . reason } </ span >
847- < span className = "text-xs text-text-dimmed" >
848- < DateTime date = { entry . triggeredAt } />
849- </ span >
850- </ div >
851- </ Property . Label >
852- < Property . Value >
853- { entry . run && runPath ? (
854- < SimpleTooltip
855- button = {
856- < TextLink
857- to = { runPath }
858- className = "group flex flex-wrap items-center gap-x-2 gap-y-0"
859- >
860- < CopyableText
861- value = { entry . run . friendlyId }
862- copyValue = { entry . run . friendlyId }
863- asChild
864- />
865- < TaskRunStatusCombo status = { entry . run . status } />
866- </ TextLink >
867- }
868- content = { `Jump to run` }
869- disableHoverableContent
870- />
871- ) : (
872- < span className = "text-text-dimmed" > –</ span >
873- ) }
874- </ Property . Value >
875- </ Property . Item >
876- ) ;
877- } ) }
878- </ Property . Table >
879- < div className = "flex justify-end" >
880- < LinkButton variant = "tertiary/small" to = { allRunsPath } >
842+ < div className = "flex flex-col" >
843+ < TimelineRow lineVariant = "dashed" >
844+ < span className = "flex items-center gap-1.5 text-sm font-medium text-text-bright" >
845+ < span > Session:</ span >
846+ < SessionStatusCombo status = { status } className = "text-sm" />
847+ </ span >
848+ < span className = "text-xs text-text-dimmed" > { sessionStatusBlurb ( status ) } </ span >
849+ < LinkButton variant = "secondary/small" to = { allRunsPath } className = "mt-1 w-fit" >
881850 View all runs
882851 </ LinkButton >
852+ </ TimelineRow >
853+ { session . runs . map ( ( entry , idx ) => {
854+ const isLast = idx === session . runs . length - 1 ;
855+ const runPath = entry . run
856+ ? v3RunPath ( organization , project , environment , {
857+ friendlyId : entry . run . friendlyId ,
858+ } )
859+ : undefined ;
860+ return (
861+ < TimelineRow key = { entry . id } isLast = { isLast } >
862+ < span className = "text-sm font-medium text-text-bright" >
863+ < span className = "capitalize" > { entry . reason } </ span > run
864+ </ span >
865+ < span className = "text-xs text-text-dimmed" >
866+ < DateTime date = { entry . triggeredAt } />
867+ </ span >
868+ { entry . run && runPath ? (
869+ < >
870+ < SimpleTooltip
871+ asChild
872+ buttonClassName = "w-fit self-start"
873+ button = {
874+ < TextLink to = { runPath } className = "font-mono text-sm" >
875+ < CopyableText
876+ value = { entry . run . friendlyId }
877+ copyValue = { entry . run . friendlyId }
878+ asChild
879+ />
880+ </ TextLink >
881+ }
882+ content = "Jump to run"
883+ disableHoverableContent
884+ />
885+ < TaskRunStatusCombo status = { entry . run . status } className = "text-sm" />
886+ </ >
887+ ) : (
888+ < span className = "text-text-dimmed" > –</ span >
889+ ) }
890+ </ TimelineRow >
891+ ) ;
892+ } ) }
893+ </ div >
894+ ) ;
895+ }
896+
897+ function sessionStatusBlurb ( status : SessionStatus ) : string {
898+ switch ( status ) {
899+ case "ACTIVE" :
900+ return "Accepting new runs" ;
901+ case "CLOSED" :
902+ return "No longer accepting new runs" ;
903+ case "EXPIRED" :
904+ return "Expired without being closed" ;
905+ }
906+ }
907+
908+ function TimelineRow ( {
909+ children,
910+ isLast,
911+ lineVariant = "solid" ,
912+ } : {
913+ children : React . ReactNode ;
914+ isLast ?: boolean ;
915+ lineVariant ?: "solid" | "dashed" ;
916+ } ) {
917+ return (
918+ < div className = "flex gap-3" >
919+ < div className = "flex flex-none flex-col items-center" >
920+ < div className = "my-1.5 size-2.5 shrink-0 rounded-full border border-charcoal-500" />
921+ { ! isLast &&
922+ ( lineVariant === "dashed" ? (
923+ < div className = "flex-1 border-l border-dashed border-charcoal-600" />
924+ ) : (
925+ < div className = "w-px flex-1 bg-charcoal-600" />
926+ ) ) }
927+ </ div >
928+ < div className = { cn ( "flex min-w-0 flex-1 flex-col gap-0.5" , ! isLast && "pb-4" ) } >
929+ { children }
883930 </ div >
884931 </ div >
885932 ) ;
0 commit comments