change ref

This commit is contained in:
Josh Hawkins 2024-02-22 11:25:21 -06:00
parent 79bcf7dcdf
commit 568148a451
2 changed files with 77 additions and 51 deletions

View File

@ -19,6 +19,7 @@ type MinimapSegmentProps = {
isLastSegmentInMinimap: boolean; isLastSegmentInMinimap: boolean;
alignedMinimapStartTime: number; alignedMinimapStartTime: number;
alignedMinimapEndTime: number; alignedMinimapEndTime: number;
firstMinimapSegmentRef: React.MutableRefObject<HTMLDivElement | null>;
}; };
type TickSegmentProps = { type TickSegmentProps = {
@ -41,11 +42,15 @@ function MinimapBounds({
isLastSegmentInMinimap, isLastSegmentInMinimap,
alignedMinimapStartTime, alignedMinimapStartTime,
alignedMinimapEndTime, alignedMinimapEndTime,
firstMinimapSegmentRef,
}: MinimapSegmentProps) { }: MinimapSegmentProps) {
return ( return (
<> <>
{isFirstSegmentInMinimap && ( {isFirstSegmentInMinimap && (
<div className="absolute inset-0 -bottom-5 w-full flex items-center justify-center text-xs text-primary font-medium z-20 text-center text-[8px]"> <div
className="absolute inset-0 -bottom-5 w-full flex items-center justify-center text-xs text-primary font-medium z-20 text-center text-[8px] scroll-mt-8"
ref={firstMinimapSegmentRef}
>
{new Date(alignedMinimapStartTime * 1000).toLocaleTimeString([], { {new Date(alignedMinimapStartTime * 1000).toLocaleTimeString([], {
hour: "2-digit", hour: "2-digit",
minute: "2-digit", minute: "2-digit",
@ -185,9 +190,12 @@ export function EventSegment({
// Check if the first segment is out of view // Check if the first segment is out of view
const firstSegment = firstMinimapSegmentRef.current; const firstSegment = firstMinimapSegmentRef.current;
if (firstSegment && showMinimap && isFirstSegmentInMinimap) { if (firstSegment && showMinimap && isFirstSegmentInMinimap) {
firstSegment.scrollIntoView({ behavior: "smooth", block: "nearest" }); firstSegment.scrollIntoView({
behavior: "smooth",
block: "center",
});
} }
}, [showMinimap, isFirstSegmentInMinimap, timestampSpread]); }, [showMinimap, isFirstSegmentInMinimap, events, segmentDuration]);
const segmentClasses = `flex flex-row ${ const segmentClasses = `flex flex-row ${
showMinimap showMinimap
@ -222,6 +230,7 @@ export function EventSegment({
isLastSegmentInMinimap={isLastSegmentInMinimap} isLastSegmentInMinimap={isLastSegmentInMinimap}
alignedMinimapStartTime={alignedMinimapStartTime} alignedMinimapStartTime={alignedMinimapStartTime}
alignedMinimapEndTime={alignedMinimapEndTime} alignedMinimapEndTime={alignedMinimapEndTime}
firstMinimapSegmentRef={firstMinimapSegmentRef}
/> />
<Tick <Tick
@ -245,7 +254,6 @@ export function EventSegment({
<div <div
className="mr-3 w-[8px] h-2 flex justify-left items-end" className="mr-3 w-[8px] h-2 flex justify-left items-end"
data-severity={severityValue} data-severity={severityValue}
ref={isFirstSegmentInMinimap ? firstMinimapSegmentRef : undefined}
> >
<div <div
key={`${segmentKey}_${index}_primary_data`} key={`${segmentKey}_${index}_primary_data`}

View File

@ -61,7 +61,8 @@ function eventsToScrubberItems(events: Event[]): ScrubberItem[] {
} }
const generateRandomEvent = (): ReviewSegment => { const generateRandomEvent = (): ReviewSegment => {
const start_time = Math.floor(Date.now() / 1000) - Math.random() * 60 * 60; const start_time =
Math.floor(Date.now() / 1000) - 10800 - Math.random() * 60 * 60;
const end_time = Math.floor(start_time + Math.random() * 60 * 10); const end_time = Math.floor(start_time + Math.random() * 60 * 10);
const severities: ReviewSeverity[] = [ const severities: ReviewSeverity[] = [
"significant_motion", "significant_motion",
@ -123,6 +124,23 @@ function UIPlayground() {
setMockEvents(initialEvents); setMockEvents(initialEvents);
}, []); }, []);
// Calculate minimap start and end times based on events
const minimapStartTime = useMemo(() => {
if (mockEvents && mockEvents.length > 0) {
return Math.min(...mockEvents.map((event) => event.start_time));
}
return Math.floor(Date.now() / 1000); // Default to current time if no events
}, [events]);
const minimapEndTime = useMemo(() => {
if (mockEvents && mockEvents.length > 0) {
return Math.max(
...mockEvents.map((event) => event.end_time ?? event.start_time)
);
}
return Math.floor(Date.now() / 1000); // Default to current time if no events
}, [events]);
const [zoomLevel, setZoomLevel] = useState(0); const [zoomLevel, setZoomLevel] = useState(0);
const [zoomSettings, setZoomSettings] = useState({ const [zoomSettings, setZoomSettings] = useState({
segmentDuration: 60, segmentDuration: 60,
@ -152,42 +170,42 @@ function UIPlayground() {
return ( return (
<> <>
<Heading as="h2">UI Playground</Heading> <div className="absolute left-0 top-12 bottom-0 right-28 flex flex-wrap content-start gap-2 overflow-y-auto no-scrollbar">
<div className="relative w-full h-full mt-4 mr-5">
<Heading as="h2">UI Playground</Heading>
<Heading as="h4" className="my-5"> <Heading as="h4" className="my-5">
Scrubber Scrubber
</Heading> </Heading>
<p className="text-small"> <p className="text-small">
Shows the 10 most recent events within the last 4 hours Shows the 10 most recent events within the last 4 hours
</p> </p>
{!config && <ActivityIndicator />} {!config && <ActivityIndicator />}
{config && ( {config && (
<div> <div>
{events && events.length > 0 && ( {events && events.length > 0 && (
<> <>
<ActivityScrubber <ActivityScrubber
items={eventsToScrubberItems(events)} items={eventsToScrubberItems(events)}
selectHandler={onSelect} selectHandler={onSelect}
/> />
</> </>
)}
</div>
)} )}
</div>
)}
{config && ( {config && (
<div> <div>
{timeline && ( {timeline && (
<> <>
<TimelineScrubber eventID={timeline} /> <TimelineScrubber eventID={timeline} />
</> </>
)}
</div>
)} )}
</div>
)}
<div className="flex">
<div className="flex-grow">
<div ref={contentRef}> <div ref={contentRef}>
<Heading as="h4" className="my-5"> <Heading as="h4" className="my-5">
Timeline Timeline
@ -229,23 +247,23 @@ function UIPlayground() {
</div> </div>
</div> </div>
</div> </div>
<div className="flex-none"> </div>
<EventReviewTimeline <div className="absolute top-12 right-0 bottom-0">
segmentDuration={zoomSettings.segmentDuration} // seconds per segment <EventReviewTimeline
timestampSpread={zoomSettings.timestampSpread} // minutes between each major timestamp segmentDuration={zoomSettings.segmentDuration} // seconds per segment
timelineStart={Math.floor(Date.now() / 1000)} // timestamp start of the timeline - the earlier time timestampSpread={zoomSettings.timestampSpread} // minutes between each major timestamp
timelineEnd={Math.floor(Date.now() / 1000) - 6 * 60 * 60} // end of timeline - the later time timelineStart={Math.floor(Date.now() / 1000)} // timestamp start of the timeline - the earlier time
showHandlebar // show / hide the handlebar timelineEnd={Math.floor(Date.now() / 1000) - 6 * 60 * 60} // end of timeline - the later time
handlebarTime={handlebarTime} // set the time of the handlebar showHandlebar // show / hide the handlebar
setHandlebarTime={setHandlebarTime} // expose handler to set the handlebar time handlebarTime={handlebarTime} // set the time of the handlebar
showMinimap // show / hide the minimap setHandlebarTime={setHandlebarTime} // expose handler to set the handlebar time
minimapStartTime={Math.floor(Date.now() / 1000) - 35 * 60} // start time of the minimap - the earlier time (eg 1:00pm) showMinimap // show / hide the minimap
minimapEndTime={Math.floor(Date.now() / 1000) - 21 * 60} // end of the minimap - the later time (eg 3:00pm) minimapStartTime={minimapStartTime} // start time of the minimap - the earlier time (eg 1:00pm)
events={mockEvents} // events, including new has_been_reviewed and severity properties minimapEndTime={minimapEndTime} // end of the minimap - the later time (eg 3:00pm)
severityType={"alert"} // choose the severity type for the middle line - all other severity types are to the right events={mockEvents} // events, including new has_been_reviewed and severity properties
contentRef={contentRef} // optional content ref where previews are, can be used for observing/scrolling later severityType={"alert"} // choose the severity type for the middle line - all other severity types are to the right
/> contentRef={contentRef} // optional content ref where previews are, can be used for observing/scrolling later
</div> />
</div> </div>
</> </>
); );