Add basic search page

This commit is contained in:
Nicolas Mowen 2024-06-21 16:15:06 -06:00
parent 5b761ead66
commit f3b858364d
4 changed files with 60 additions and 6 deletions

View File

@ -13,6 +13,7 @@ import { isPWA } from "./utils/isPWA";
const Live = lazy(() => import("@/pages/Live")); const Live = lazy(() => import("@/pages/Live"));
const Events = lazy(() => import("@/pages/Events")); const Events = lazy(() => import("@/pages/Events"));
const Search = lazy(() => import("@/pages/Search"));
const Exports = lazy(() => import("@/pages/Exports")); const Exports = lazy(() => import("@/pages/Exports"));
const SubmitPlus = lazy(() => import("@/pages/SubmitPlus")); const SubmitPlus = lazy(() => import("@/pages/SubmitPlus"));
const ConfigEditor = lazy(() => import("@/pages/ConfigEditor")); const ConfigEditor = lazy(() => import("@/pages/ConfigEditor"));
@ -44,6 +45,7 @@ function App() {
<Route path="/" element={<Live />} /> <Route path="/" element={<Live />} />
<Route path="/events" element={<Redirect to="/review" />} /> <Route path="/events" element={<Redirect to="/review" />} />
<Route path="/review" element={<Events />} /> <Route path="/review" element={<Events />} />
<Route path="/search" element={<Search />} />
<Route path="/export" element={<Exports />} /> <Route path="/export" element={<Exports />} />
<Route path="/plus" element={<SubmitPlus />} /> <Route path="/plus" element={<SubmitPlus />} />
<Route path="/system" element={<System />} /> <Route path="/system" element={<System />} />

View File

@ -4,10 +4,18 @@ import { FrigateConfig } from "@/types/frigateConfig";
import { NavData } from "@/types/navigation"; import { NavData } from "@/types/navigation";
import { useMemo } from "react"; import { useMemo } from "react";
import { FaCompactDisc, FaVideo } from "react-icons/fa"; import { FaCompactDisc, FaVideo } from "react-icons/fa";
import { IoSearch } from "react-icons/io5";
import { LuConstruction } from "react-icons/lu"; import { LuConstruction } from "react-icons/lu";
import { MdVideoLibrary } from "react-icons/md"; import { MdVideoLibrary } from "react-icons/md";
import useSWR from "swr"; import useSWR from "swr";
export const ID_LIVE = 1;
export const ID_REVIEW = 2;
export const ID_SEARCH = 3;
export const ID_EXPORT = 4;
export const ID_PLUS = 5;
export const ID_PLAYGROUND = 6;
export default function useNavigation( export default function useNavigation(
variant: "primary" | "secondary" = "primary", variant: "primary" | "secondary" = "primary",
) { ) {
@ -17,28 +25,36 @@ export default function useNavigation(
() => () =>
[ [
{ {
id: 1, id: ID_LIVE,
variant, variant,
icon: FaVideo, icon: FaVideo,
title: "Live", title: "Live",
url: "/", url: "/",
}, },
{ {
id: 2, id: ID_REVIEW,
variant, variant,
icon: MdVideoLibrary, icon: MdVideoLibrary,
title: "Review", title: "Review",
url: "/review", url: "/review",
}, },
{ {
id: 3, id: ID_SEARCH,
variant,
icon: IoSearch,
title: "Search",
url: "/search",
enabled: config?.semantic_search?.enabled,
},
{
id: ID_EXPORT,
variant, variant,
icon: FaCompactDisc, icon: FaCompactDisc,
title: "Export", title: "Export",
url: "/export", url: "/export",
}, },
{ {
id: 5, id: ID_PLUS,
variant, variant,
icon: Logo, icon: Logo,
title: "Frigate+", title: "Frigate+",
@ -46,7 +62,7 @@ export default function useNavigation(
enabled: config?.plus?.enabled == true, enabled: config?.plus?.enabled == true,
}, },
{ {
id: 4, id: ID_PLAYGROUND,
variant, variant,
icon: LuConstruction, icon: LuConstruction,
title: "UI Playground", title: "UI Playground",
@ -54,6 +70,6 @@ export default function useNavigation(
enabled: ENV !== "production", enabled: ENV !== "production",
}, },
] as NavData[], ] as NavData[],
[config?.plus.enabled, variant], [config?.plus.enabled, config?.semantic_search.enabled, variant],
); );
} }

32
web/src/pages/Search.tsx Normal file
View File

@ -0,0 +1,32 @@
import { Input } from "@/components/ui/input";
import { Toaster } from "@/components/ui/sonner";
import { useState } from "react";
import { LuSearchCheck } from "react-icons/lu";
export default function Search() {
const [searchTerm, setSearchTerm] = useState("");
return (
<div className="flex size-full flex-col pt-2 md:py-2">
<Toaster closeButton={true} />
<div className="relative mb-2 flex h-11 items-center justify-between pl-2 pr-2 md:pl-3">
<Input
className="w-full bg-muted md:w-1/3"
placeholder="Search for a specific detection..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
<div className="no-scrollbar flex flex-1 flex-wrap content-start gap-2 overflow-y-auto md:gap-4">
{searchTerm == "" && (
<div className="absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col items-center justify-center text-center">
<LuSearchCheck className="size-16" />
Search For Detections
</div>
)}
</div>
</div>
);
}

View File

@ -391,6 +391,10 @@ export interface FrigateConfig {
enabled: boolean; enabled: boolean;
}; };
semantic_search: {
enabled: boolean;
}
snapshots: { snapshots: {
bounding_box: boolean; bounding_box: boolean;
clean_copy: boolean; clean_copy: boolean;