diff --git a/web/src/App.tsx b/web/src/App.tsx
index 60488cb56..07e901735 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -13,6 +13,7 @@ import { isPWA } from "./utils/isPWA";
const Live = lazy(() => import("@/pages/Live"));
const Events = lazy(() => import("@/pages/Events"));
+const Search = lazy(() => import("@/pages/Search"));
const Exports = lazy(() => import("@/pages/Exports"));
const SubmitPlus = lazy(() => import("@/pages/SubmitPlus"));
const ConfigEditor = lazy(() => import("@/pages/ConfigEditor"));
@@ -44,6 +45,7 @@ function App() {
} />
} />
} />
+ } />
} />
} />
} />
diff --git a/web/src/hooks/use-navigation.ts b/web/src/hooks/use-navigation.ts
index 771dde088..fde200839 100644
--- a/web/src/hooks/use-navigation.ts
+++ b/web/src/hooks/use-navigation.ts
@@ -4,10 +4,18 @@ import { FrigateConfig } from "@/types/frigateConfig";
import { NavData } from "@/types/navigation";
import { useMemo } from "react";
import { FaCompactDisc, FaVideo } from "react-icons/fa";
+import { IoSearch } from "react-icons/io5";
import { LuConstruction } from "react-icons/lu";
import { MdVideoLibrary } from "react-icons/md";
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(
variant: "primary" | "secondary" = "primary",
) {
@@ -17,28 +25,36 @@ export default function useNavigation(
() =>
[
{
- id: 1,
+ id: ID_LIVE,
variant,
icon: FaVideo,
title: "Live",
url: "/",
},
{
- id: 2,
+ id: ID_REVIEW,
variant,
icon: MdVideoLibrary,
title: "Review",
url: "/review",
},
{
- id: 3,
+ id: ID_SEARCH,
+ variant,
+ icon: IoSearch,
+ title: "Search",
+ url: "/search",
+ enabled: config?.semantic_search?.enabled,
+ },
+ {
+ id: ID_EXPORT,
variant,
icon: FaCompactDisc,
title: "Export",
url: "/export",
},
{
- id: 5,
+ id: ID_PLUS,
variant,
icon: Logo,
title: "Frigate+",
@@ -46,7 +62,7 @@ export default function useNavigation(
enabled: config?.plus?.enabled == true,
},
{
- id: 4,
+ id: ID_PLAYGROUND,
variant,
icon: LuConstruction,
title: "UI Playground",
@@ -54,6 +70,6 @@ export default function useNavigation(
enabled: ENV !== "production",
},
] as NavData[],
- [config?.plus.enabled, variant],
+ [config?.plus.enabled, config?.semantic_search.enabled, variant],
);
}
diff --git a/web/src/pages/Search.tsx b/web/src/pages/Search.tsx
new file mode 100644
index 000000000..4b5809c9a
--- /dev/null
+++ b/web/src/pages/Search.tsx
@@ -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 (
+
+
+
+
+ setSearchTerm(e.target.value)}
+ />
+
+
+
+ {searchTerm == "" && (
+
+
+ Search For Detections
+
+ )}
+
+
+ );
+}
diff --git a/web/src/types/frigateConfig.ts b/web/src/types/frigateConfig.ts
index 2eb7622d6..1c60f2971 100644
--- a/web/src/types/frigateConfig.ts
+++ b/web/src/types/frigateConfig.ts
@@ -391,6 +391,10 @@ export interface FrigateConfig {
enabled: boolean;
};
+ semantic_search: {
+ enabled: boolean;
+ }
+
snapshots: {
bounding_box: boolean;
clean_copy: boolean;