1+ import { useMemo } from "react" ;
12import { AlertTriangle , Clock3 } from "lucide-react" ;
2- import type { ResourceDetails , ResourceEvent } from "../types/kube" ;
3+ import { compareEventResources , relatedEventResourcesFor } from "../lib/resourceEvents" ;
4+ import type { ResourceDetails , ResourceEvent , ResourceRow } from "../types/kube" ;
35
46export function PodEventRail ( {
57 details,
68 detailsError,
79 detailsLoading,
10+ onOpenResource,
11+ resource,
12+ resources = [ ] ,
813} : {
914 details : ResourceDetails ;
1015 detailsError : string ;
1116 detailsLoading : boolean ;
17+ onOpenResource ?: ( id : string , intent ?: "logs" | null ) => void ;
18+ resource ?: ResourceRow ;
19+ resources ?: ResourceRow [ ] ;
1220} ) {
1321 const { events, warningCount } = eventRailView ( details . events ) ;
22+ const eventResources = useMemo (
23+ ( ) => resource ? relatedEventResourcesFor ( resource , resources ) . sort ( compareEventResources ) : [ ] ,
24+ [ resource , resources ] ,
25+ ) ;
26+ const linkedEvents = linkEventResources ( events , eventResources ) ;
1427
1528 return (
1629 < section className = "pod-event-rail" aria-label = "Pod event timeline" >
@@ -35,8 +48,15 @@ export function PodEventRail({
3548 < div className = "pod-event-list" >
3649 { detailsLoading ? (
3750 < PodEventEmpty label = "Syncing events" message = "Waiting for Kubernetes event data." />
38- ) : events . length ? (
39- events . map ( ( event , index ) => < PodEventItem event = { event } key = { `${ event . reason } -${ event . age } -${ index } ` } /> )
51+ ) : linkedEvents . length ? (
52+ linkedEvents . map ( ( { event, eventResource } , index ) => (
53+ < PodEventItem
54+ event = { event }
55+ eventResource = { eventResource }
56+ key = { `${ event . reason } -${ event . age } -${ index } ` }
57+ onOpenResource = { onOpenResource }
58+ />
59+ ) )
4060 ) : (
4161 < PodEventEmpty label = "No pod events" message = { detailsError || "No warning or normal events returned." } />
4262 ) }
@@ -45,12 +65,19 @@ export function PodEventRail({
4565 ) ;
4666}
4767
48- function PodEventItem ( { event } : { event : ResourceEvent } ) {
68+ function PodEventItem ( {
69+ event,
70+ eventResource,
71+ onOpenResource,
72+ } : {
73+ event : ResourceEvent ;
74+ eventResource ?: ResourceRow ;
75+ onOpenResource ?: ( id : string , intent ?: "logs" | null ) => void ;
76+ } ) {
4977 const warning = isWarningEvent ( event ) ;
5078 const count = eventCount ( event ) ;
51-
52- return (
53- < article className = { warning ? "pod-event-item warning" : "pod-event-item" } >
79+ const content = (
80+ < >
5481 < i aria-hidden = "true" />
5582 < div >
5683 < span > { event . type || "Normal" } </ span >
@@ -61,6 +88,25 @@ function PodEventItem({ event }: { event: ResourceEvent }) {
6188 </ div >
6289 < p > { event . message || event . age || "Event recorded." } </ p >
6390 < time > { event . age || "live" } </ time >
91+ </ >
92+ ) ;
93+
94+ if ( eventResource && onOpenResource ) {
95+ return (
96+ < button
97+ className = { warning ? "pod-event-item warning linked" : "pod-event-item linked" }
98+ title = { `Open Event ${ eventResource . name } ` }
99+ type = "button"
100+ onClick = { ( ) => onOpenResource ( eventResource . id ) }
101+ >
102+ { content }
103+ </ button >
104+ ) ;
105+ }
106+
107+ return (
108+ < article className = { warning ? "pod-event-item warning" : "pod-event-item" } >
109+ { content }
64110 </ article >
65111 ) ;
66112}
@@ -101,3 +147,24 @@ function isWarningEvent(event: ResourceEvent) {
101147function eventCount ( event : ResourceEvent ) {
102148 return Number . isFinite ( event . count ) && event . count > 0 ? event . count : 1 ;
103149}
150+
151+ function linkEventResources ( events : ResourceEvent [ ] , eventResources : ResourceRow [ ] ) {
152+ const unusedResources = [ ...eventResources ] ;
153+
154+ return events . map ( ( event ) => {
155+ const resourceIndex = unusedResources . findIndex ( ( resource ) =>
156+ eventResourceType ( resource ) . toLowerCase ( ) === event . type . toLowerCase ( ) &&
157+ resource . diagnostic === event . reason
158+ ) ;
159+ const eventResource = resourceIndex >= 0 ? unusedResources . splice ( resourceIndex , 1 ) [ 0 ] : undefined ;
160+
161+ return { event, eventResource } ;
162+ } ) ;
163+ }
164+
165+ function eventResourceType ( resource : ResourceRow ) {
166+ if ( resource . image ) {
167+ return resource . image ;
168+ }
169+ return resource . status === "warning" ? "Warning" : "Normal" ;
170+ }
0 commit comments