diff --git a/frigate/api/event.py b/frigate/api/event.py index 7cdb933c9..17fc5c776 100644 --- a/frigate/api/event.py +++ b/frigate/api/event.py @@ -77,6 +77,8 @@ def events(): min_length = request.args.get("min_length", type=float) max_length = request.args.get("max_length", type=float) + sort = request.args.get("sort", type=str) + clauses = [] selected_columns = [ @@ -219,10 +221,22 @@ def events(): if len(clauses) == 0: clauses.append((True)) + if sort: + if sort == "score_asc": + order_by = Event.data["score"].asc() + elif sort == "score_desc": + order_by = Event.data["score"].desc() + elif sort == "date_asc": + Event.start_time.asc() + elif sort == "date_desc": + Event.start_time.desc() + else: + order_by = Event.start_time.desc() + events = ( Event.select(*selected_columns) .where(reduce(operator.and_, clauses)) - .order_by(Event.start_time.desc()) + .order_by(order_by) .limit(limit) .dicts() .iterator() diff --git a/web/src/pages/SubmitPlus.tsx b/web/src/pages/SubmitPlus.tsx index 16d32d636..88c449362 100644 --- a/web/src/pages/SubmitPlus.tsx +++ b/web/src/pages/SubmitPlus.tsx @@ -20,13 +20,20 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { DualThumbSlider } from "@/components/ui/slider"; import { Event } from "@/types/event"; import { FrigateConfig } from "@/types/frigateConfig"; import axios from "axios"; import { useCallback, useEffect, useMemo, useState } from "react"; import { isMobile } from "react-device-detect"; -import { FaList } from "react-icons/fa"; +import { + FaList, + FaSort, + FaSortAmountDown, + FaSortAmountUp, +} from "react-icons/fa"; import { PiSlidersHorizontalFill } from "react-icons/pi"; import useSWR from "swr"; @@ -43,6 +50,10 @@ export default function SubmitPlus() { const [selectedLabels, setSelectedLabels] = useState(); const [scoreRange, setScoreRange] = useState(); + // sort + + const [sort, setSort] = useState(); + // data const { data: events, mutate: refresh } = useSWR([ @@ -55,6 +66,7 @@ export default function SubmitPlus() { labels: selectedLabels ? selectedLabels.join(",") : null, min_score: scoreRange ? scoreRange[0] : null, max_score: scoreRange ? scoreRange[1] : null, + sort: sort ? sort : null, }, ]); const [upload, setUpload] = useState(); @@ -112,14 +124,17 @@ export default function SubmitPlus() { return (
- +
+ + +
+
); } + +type PlusSortSelectorProps = { + selectedSort?: string; + setSelectedSort: (sort: string | undefined) => void; +}; +function PlusSortSelector({ + selectedSort, + setSelectedSort, +}: PlusSortSelectorProps) { + // menu state + + const [open, setOpen] = useState(false); + + // sort + + const [currentSort, setCurrentSort] = useState(); + const [currentDir, setCurrentDir] = useState("desc"); + + // components + + const Sort = selectedSort + ? selectedSort.split("_")[1] == "desc" + ? FaSortAmountDown + : FaSortAmountUp + : FaSort; + const Menu = isMobile ? Drawer : DropdownMenu; + const Trigger = isMobile ? DrawerTrigger : DropdownMenuTrigger; + const Content = isMobile ? DrawerContent : DropdownMenuContent; + + return ( +
+ { + setOpen(open); + + if (!open) { + const parts = selectedSort?.split("_"); + + if (parts?.length == 2) { + setCurrentSort(parts[0]); + setCurrentDir(parts[1]); + } + } + }} + > + + + + + setCurrentSort(value)} + > +
+ + + {currentSort == "date" ? ( + currentDir == "desc" ? ( + setCurrentDir("asc")} + /> + ) : ( + setCurrentDir("desc")} + /> + ) + ) : ( +
+ )} +
+
+ + + {currentSort == "score" ? ( + currentDir == "desc" ? ( + setCurrentDir("asc")} + /> + ) : ( + setCurrentDir("desc")} + /> + ) + ) : ( +
+ )} +
+ + +
+ + +
+ +
+
+ ); +}