From 5994860296fd88962944f59e47a5dcadbf5d526d Mon Sep 17 00:00:00 2001 From: Nick Mowen Date: Fri, 21 Apr 2023 07:09:21 -0600 Subject: [PATCH] Start working on timeline ui --- frigate/timeline.py | 1 + web/src/components/TimelineSummary.jsx | 57 ++++++++++++++++++++++---- web/src/routes/Events.jsx | 16 ++++---- 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/frigate/timeline.py b/frigate/timeline.py index 22279ce5f..54a26de15 100644 --- a/frigate/timeline.py +++ b/frigate/timeline.py @@ -71,6 +71,7 @@ class TimelineProcessor(threading.Thread): elif ( event_type == "update" and prev_event_data["current_zones"] != event_data["current_zones"] + and len(event_data["current_zones"]) > 0 ): Timeline.insert( timestamp=event_data["frame_time"], diff --git a/web/src/components/TimelineSummary.jsx b/web/src/components/TimelineSummary.jsx index ffa22584e..52cf09fb8 100644 --- a/web/src/components/TimelineSummary.jsx +++ b/web/src/components/TimelineSummary.jsx @@ -3,8 +3,15 @@ import useSWR from 'swr'; import Heading from './Heading'; import ActivityIndicator from './ActivityIndicator'; import { formatUnixTimestampToDateTime } from '../utils/dateUtil'; +import MotionIcon from '../icons/Motion'; +import SnapshotIcon from '../icons/Snapshot'; +import { Zone } from '../icons/Zone'; +import { useState } from 'preact/hooks'; +import { useApiHost } from '../api'; +import Button from './Button'; export default function TimelineSummary({ event }) { + const apiHost = useApiHost(); const { data: eventTimeline } = useSWR([ 'timeline', { @@ -14,26 +21,60 @@ export default function TimelineSummary({ event }) { const { data: config } = useSWR('config'); + const [timeIndex, setTimeIndex] = useState(0); + if (!eventTimeline || !config) { return ; } return (
- Timeline: - {eventTimeline.map((item, index) => ( -
{getTimelineItemDescription(config, item, event, index)}
- ))} +
+
+ {eventTimeline.map((item, index) => + item.class_type == 'visible' || item.class_type == 'gone' ? ( + + ) : ( + + ) + )} +
+
+ +
+ {getTimelineItemDescription(config, eventTimeline[timeIndex], event)} +
+ +
+
); } -function getTimelineItemDescription(config, timelineItem, event, index) { +function getTimelineItemDescription(config, timelineItem, event) { if (timelineItem.class_type == 'visible') { - return `${index + 1}. ${event.label} detected at ${formatUnixTimestampToDateTime(timelineItem.timestamp, { date_style: "short", time_style: "medium", time_format: config.ui.time_format })}`; + return `${event.label} detected at ${formatUnixTimestampToDateTime(timelineItem.timestamp, { + date_style: 'short', + time_style: 'medium', + time_format: config.ui.time_format, + })}`; } else if (timelineItem.class_type == 'entered_zone') { - return `${index + 1}. ${event.label} entered ${timelineItem.data.zones} at ${formatUnixTimestampToDateTime(timelineItem.timestamp, { date_style: "short", time_style: "medium", time_format: config.ui.time_format })}`; + return `${event.label} entered ${timelineItem.data.zones} at ${formatUnixTimestampToDateTime( + timelineItem.timestamp, + { date_style: 'short', time_style: 'medium', time_format: config.ui.time_format } + )}`; } - return `${index + 1}. ${event.label} left at ${formatUnixTimestampToDateTime(timelineItem.timestamp, { date_style: "short", time_style: "medium", time_format: config.ui.time_format })}`; + return `${event.label} left at ${formatUnixTimestampToDateTime(timelineItem.timestamp, { + date_style: 'short', + time_style: 'medium', + time_format: config.ui.time_format, + })}`; } diff --git a/web/src/routes/Events.jsx b/web/src/routes/Events.jsx index b0696a6b1..99ea30943 100644 --- a/web/src/routes/Events.jsx +++ b/web/src/routes/Events.jsx @@ -283,7 +283,7 @@ export default function Events({ path, ...props }) { }; const handleEventDetailTabChange = (index) => { - setEventDetailType(index == 0 ? 'clip' : 'image'); + setEventDetailType(index == 0 ? 'clip' : index == 1 ? 'image' : 'timeline'); }; if (!config) { @@ -366,7 +366,7 @@ export default function Events({ path, ...props }) { download /> )} - {(downloadEvent.end_time && downloadEvent.has_snapshot && !downloadEvent.plus_id) && ( + {downloadEvent.end_time && downloadEvent.has_snapshot && !downloadEvent.plus_id && (