diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx index 05f49156..497e435c 100644 --- a/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx +++ b/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx @@ -180,8 +180,12 @@ export default function EventTimeline({

Raw Events ({sortedBySequence.length})

- {sortedBySequence.map((ev) => ( - + {sortedBySequence.map((ev, i) => ( + 0 ? getDisplayTime(sortedBySequence[i - 1]) : null} + /> ))}
@@ -341,11 +345,12 @@ function PhaseSection({ {isExpanded && (
- {events.map((event) => ( + {events.map((event, i) => ( 0 ? getDisplayTime(events[i - 1]) : null} /> ))}
@@ -372,7 +377,32 @@ const BACKFILL_TOOLTIP = "If enrollment progressed afterwards, this error was already resolved by a retry. " + "The timestamp shown is the original event-log time."; -function EventRow({ event, showScriptOutput }: { event: EnrollmentEvent; showScriptOutput?: boolean }) { +// Display timestamp of a row: backfilled events show the original event-log time. +function getDisplayTime(event: EnrollmentEvent): Date { + return getBackfillInfo(event).recordedAt ?? new Date(event.timestamp); +} + +// Rows render time-of-day only, so a multi-hour/multi-day gap to the previous row +// (and the date change it implies) is invisible without expanding event details. +// Shown on the row AFTER the gap; hover reveals the full date. +function GapBadge({ prevTime, eventTime }: { prevTime: Date | null; eventTime: Date }) { + if (!prevTime) return null; + const gapMs = eventTime.getTime() - prevTime.getTime(); + if (gapMs < 60 * 60 * 1000) return null; + const label = gapMs >= 48 * 60 * 60 * 1000 + ? `+${Math.round(gapMs / (24 * 60 * 60 * 1000))}d` + : `+${Math.round(gapMs / (60 * 60 * 1000))}h`; + return ( + + ⏱ {label} + + ); +} + +function EventRow({ event, showScriptOutput, prevDisplayTime }: { event: EnrollmentEvent; showScriptOutput?: boolean; prevDisplayTime?: Date | null }) { const [showDetails, setShowDetails] = useState(false); const [showRaw, setShowRaw] = useState(false); const [copied, setCopied] = useState(false); @@ -458,6 +488,7 @@ function EventRow({ event, showScriptOutput }: { event: EnrollmentEvent; showScr (reported {new Date(event.timestamp).toLocaleTimeString()}) )} + {isBackfilled && ( normalizeEventDataForDisplay(event.data), [event.data]); const hasDetails = detailData && Object.keys(detailData).length > 0; @@ -806,6 +837,7 @@ function RawEventRow({ event }: { event: EnrollmentEvent }) {
{event.sequence} {(recordedAt ?? new Date(event.timestamp)).toLocaleTimeString()} + {event.severity} {isBackfilled && ( ⟲