From 05ffd24760ac2d1e8ce3c61af4b558d4eff0b83f Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Tue, 5 Dec 2023 06:04:22 -0700 Subject: [PATCH] Add support for review grid --- frigate/events/maintainer.py | 6 + frigate/http.py | 107 +++++++- frigate/timeline.py | 56 +++-- web-new/package-lock.json | 32 +++ web-new/package.json | 1 + web-new/src/App.tsx | 2 + web-new/src/components/Sidebar.tsx | 7 + web-new/src/components/card/ReviewCard.tsx | 115 +++++++++ .../src/components/player/PreviewPlayer.tsx | 100 ++++++++ web-new/src/components/player/VideoPlayer.tsx | 74 ++++++ web-new/src/components/ui/scroll-area.tsx | 46 ++++ web-new/src/pages/Review.tsx | 137 +++++++++++ web-new/src/types/frigateConfig.ts | 20 +- web-new/src/types/review.ts | 36 +++ web-new/src/utils/dateUtil.ts | 229 ++++++++++++++++++ web-new/tsconfig.json | 2 +- web-new/vite.config.ts | 13 +- web/src/components/PreviewPlayer.jsx | 83 +++++++ web/src/routes/Review.jsx | 222 +++++++++++++++++ web/vite.config.ts | 11 +- 20 files changed, 1251 insertions(+), 48 deletions(-) create mode 100644 web-new/src/components/card/ReviewCard.tsx create mode 100644 web-new/src/components/player/PreviewPlayer.tsx create mode 100644 web-new/src/components/player/VideoPlayer.tsx create mode 100644 web-new/src/components/ui/scroll-area.tsx create mode 100644 web-new/src/pages/Review.tsx create mode 100644 web-new/src/types/review.ts create mode 100644 web-new/src/utils/dateUtil.ts create mode 100644 web/src/components/PreviewPlayer.jsx create mode 100644 web/src/routes/Review.jsx diff --git a/frigate/events/maintainer.py b/frigate/events/maintainer.py index db8341656..19bb44ef4 100644 --- a/frigate/events/maintainer.py +++ b/frigate/events/maintainer.py @@ -45,6 +45,12 @@ def should_update_state(prev_event: Event, current_event: Event) -> bool: if prev_event["attributes"] != current_event["attributes"]: return True + if prev_event["sub_label"] != current_event["sub_label"]: + return True + + if len(prev_event["current_zones"]) < len(current_event["current_zones"]): + return True + return False diff --git a/frigate/http.py b/frigate/http.py index c43feee9f..b9c97b527 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -611,6 +611,57 @@ def timeline(): return jsonify([t for t in timeline]) +@bp.route("/timeline/hourly") +def hourly_timeline(): + """Get hourly summary for timeline.""" + camera = request.args.get("camera", "all") + limit = request.args.get("limit", 200) + tz_name = request.args.get("timezone", default="utc", type=str) + _, minute_modifier, _ = get_tz_modifiers(tz_name) + + clauses = [] + + if camera != "all": + clauses.append((Timeline.camera == camera)) + + if len(clauses) == 0: + clauses.append((True)) + + timeline = ( + Timeline.select( + Timeline.camera, + Timeline.timestamp, + Timeline.data, + Timeline.class_type, + Timeline.source_id, + Timeline.source, + ) + .where(reduce(operator.and_, clauses)) + .order_by(Timeline.timestamp.desc()) + .limit(limit) + .dicts() + .iterator() + ) + + hours: dict[str, list[dict[str, any]]] = {} + + for t in timeline: + hour = ( + datetime.fromtimestamp(t["timestamp"]).replace( + minute=0, second=0, microsecond=0 + ) + + timedelta( + minutes=int(minute_modifier.split(" ")[0]), + ) + ).timestamp() + if hour not in hours: + hours[hour] = [t] + else: + hours[hour].insert(0, t) + + return jsonify(hours) + + @bp.route("//