diff --git a/web/src/components/timeline/ReviewTimeline.tsx b/web/src/components/timeline/EventReviewTimeline.tsx similarity index 96% rename from web/src/components/timeline/ReviewTimeline.tsx rename to web/src/components/timeline/EventReviewTimeline.tsx index f7b4b911f..71c8b8912 100644 --- a/web/src/components/timeline/ReviewTimeline.tsx +++ b/web/src/components/timeline/EventReviewTimeline.tsx @@ -11,7 +11,7 @@ import EventSegment from "./EventSegment"; import { useEventUtils } from "@/hooks/use-event-utils"; import { Event } from "@/types/event"; -export type ReviewTimelineProps = { +export type EventReviewTimelineProps = { segmentDuration: number; timestampSpread: number; timelineStart: number; @@ -26,7 +26,7 @@ export type ReviewTimelineProps = { contentRef: RefObject; }; -export function ReviewTimeline({ +export function EventReviewTimeline({ segmentDuration, timestampSpread, timelineStart, @@ -39,7 +39,7 @@ export function ReviewTimeline({ events, severityType, contentRef, -}: ReviewTimelineProps) { +}: EventReviewTimelineProps) { const [isDragging, setIsDragging] = useState(false); const [currentTimeSegment, setCurrentTimeSegment] = useState(0); const scrollTimeRef = useRef(null); @@ -203,7 +203,7 @@ export function ReviewTimeline({ return (
@@ -237,4 +237,4 @@ export function ReviewTimeline({ ); } -export default ReviewTimeline; +export default EventReviewTimeline; diff --git a/web/src/components/timeline/EventSegment.tsx b/web/src/components/timeline/EventSegment.tsx index 88d92e5e4..16c5112ac 100644 --- a/web/src/components/timeline/EventSegment.tsx +++ b/web/src/components/timeline/EventSegment.tsx @@ -14,6 +14,109 @@ type EventSegmentProps = { severityType: string; }; +type MinimapSegmentProps = { + isFirstSegmentInMinimap: boolean; + isLastSegmentInMinimap: boolean; + alignedMinimapStartTime: number; + alignedMinimapEndTime: number; +}; + +type TickSegmentProps = { + isFirstSegmentInMinimap: boolean; + isLastSegmentInMinimap: boolean; + timestamp: Date; + timestampSpread: number; +}; + +type TimestampSegmentProps = { + isFirstSegmentInMinimap: boolean; + isLastSegmentInMinimap: boolean; + timestamp: Date; + timestampSpread: number; + segmentKey: number; +}; + +function MinimapBounds({ + isFirstSegmentInMinimap, + isLastSegmentInMinimap, + alignedMinimapStartTime, + alignedMinimapEndTime, +}: MinimapSegmentProps) { + return ( + <> + {isFirstSegmentInMinimap && ( +
+ {new Date(alignedMinimapStartTime).toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + month: "short", + day: "2-digit", + })} +
+ )} + + {isLastSegmentInMinimap && ( +
+ {new Date(alignedMinimapEndTime).toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + month: "short", + day: "2-digit", + })} +
+ )} + + ); +} + +function Tick({ + isFirstSegmentInMinimap, + isLastSegmentInMinimap, + timestamp, + timestampSpread, +}: TickSegmentProps) { + return ( +
+ {!isFirstSegmentInMinimap && !isLastSegmentInMinimap && ( +
+ )} +
+ ); +} + +function Timestamp({ + isFirstSegmentInMinimap, + isLastSegmentInMinimap, + timestamp, + timestampSpread, + segmentKey, +}: TimestampSegmentProps) { + return ( +
+ {!isFirstSegmentInMinimap && !isLastSegmentInMinimap && ( +
+ {timestamp.getMinutes() % timestampSpread === 0 && + timestamp.getSeconds() === 0 && + timestamp.toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + })} +
+ )} +
+ ); +} + export function EventSegment({ events, segmentTime, @@ -97,56 +200,39 @@ export function EventSegment({ : "" }`; + const severityColors: { [key: number]: string } = { + 1: reviewed + ? "from-yellow-200/30 to-yellow-400/30" + : "from-yellow-200 to-yellow-400", + 2: reviewed + ? "from-orange-400/30 to-orange-600/30" + : "from-orange-400 to-orange-600", + 3: reviewed ? "from-red-500/30 to-red-800/30" : "from-red-500 to-red-800", + }; + return (
- {isFirstSegmentInMinimap && ( -
- {new Date(alignedMinimapStartTime).toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", - month: "short", - day: "2-digit", - })} -
- )} + - {isLastSegmentInMinimap && ( -
- {new Date(alignedMinimapEndTime).toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", - month: "short", - day: "2-digit", - })} -
- )} -
- {!isFirstSegmentInMinimap && !isLastSegmentInMinimap && ( -
- )} -
-
- {!isFirstSegmentInMinimap && !isLastSegmentInMinimap && ( -
- {timestamp.getMinutes() % timestampSpread === 0 && - timestamp.getSeconds() === 0 && - timestamp.toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", - })} -
- )} -
+ + + {severity == displaySeverityType && (
@@ -164,23 +250,7 @@ export function EventSegment({ ? "rounded-tl-full rounded-tr-full" : "" } - ${ - reviewed - ? severity === 1 - ? "from-yellow-200/30 to-yellow-400/30" - : severity === 2 - ? "from-orange-400/30 to-orange-600/30" - : severity === 3 - ? "from-red-500/30 to-red-800/30" - : "" - : severity === 1 - ? "from-yellow-200 to-yellow-400" - : severity === 2 - ? "from-orange-400 to-orange-600" - : severity === 3 - ? "from-red-500 to-red-800" - : "" - } + ${severityColors[severity]} `} >
@@ -203,23 +273,7 @@ export function EventSegment({ ? "rounded-tl-full rounded-tr-full" : "" } - ${ - reviewed - ? severity === 1 - ? "from-yellow-200/30 to-yellow-400/30" - : severity === 2 - ? "from-orange-400/30 to-orange-600/30" - : severity === 3 - ? "from-red-500/30 to-red-800/30" - : "" - : severity === 1 - ? "from-yellow-200 to-yellow-400" - : severity === 2 - ? "from-orange-400 to-orange-600" - : severity === 3 - ? "from-red-500 to-red-800" - : "" - } + ${severityColors[severity]} `} >
diff --git a/web/src/pages/UIPlayground.tsx b/web/src/pages/UIPlayground.tsx index 4d9f69223..9d6602902 100644 --- a/web/src/pages/UIPlayground.tsx +++ b/web/src/pages/UIPlayground.tsx @@ -9,7 +9,7 @@ import { Event } from "@/types/event"; import ActivityIndicator from "@/components/ui/activity-indicator"; import { useApiHost } from "@/api"; import TimelineScrubber from "@/components/playground/TimelineScrubber"; -import { ReviewTimeline } from "@/components/timeline/ReviewTimeline"; +import EventReviewTimeline from "@/components/timeline/EventReviewTimeline"; // Color data const colors = [ @@ -60,7 +60,7 @@ function eventsToScrubberItems(events: Event[]): ScrubberItem[] { const generateRandomEvent = (): Event => { const start_time = Date.now() - Math.random() * 3600000 * 3; - const end_time = start_time + Math.random() * 36000; + const end_time = start_time + Math.random() * 360000; const severities = ["motion", "detection", "alert"]; const severity = severities[Math.floor(Math.random() * severities.length)]; const has_been_reviewed = Math.random() < 0.2; @@ -158,7 +158,7 @@ function UIPlayground() {
-