diff --git a/web/src/components/input/InputWithTags.tsx b/web/src/components/input/InputWithTags.tsx
index e4b02fa73..218f4e34e 100644
--- a/web/src/components/input/InputWithTags.tsx
+++ b/web/src/components/input/InputWithTags.tsx
@@ -189,6 +189,8 @@ export default function InputWithTags({
let timestamp = 0;
switch (type) {
+ case "query":
+ break;
case "before":
case "after":
timestamp = convertLocalDateToTimestamp(value);
@@ -584,24 +586,26 @@ export default function InputWithTags({
)}
{Object.entries(filters).map(([filterType, filterValues]) =>
Array.isArray(filterValues) ? (
- filterValues.map((value, index) => (
-
- {filterType.replaceAll("_", " ")}:{" "}
- {value.replaceAll("_", " ")}
-
-
- ))
+ {filterType.replaceAll("_", " ")}:{" "}
+ {value.replaceAll("_", " ")}
+
+
+ ))
) : (
{
if (resp.status == 200 && resp.data) {
+ const startTime = resp.data.start_time - REVIEW_PADDING;
+ const date = new Date(startTime * 1000);
+
+ setReviewFilter({
+ after: getBeginningOfDayTimestamp(date),
+ before: getEndOfDayTimestamp(date),
+ });
setRecording(
{
camera: resp.data.camera,
- startTime: resp.data.start_time - REVIEW_PADDING,
+ startTime,
severity: resp.data.severity,
},
true,
diff --git a/web/src/pages/Explore.tsx b/web/src/pages/Explore.tsx
index 32c2e1579..e8ab01b6a 100644
--- a/web/src/pages/Explore.tsx
+++ b/web/src/pages/Explore.tsx
@@ -1,30 +1,24 @@
import { useApiFilterArgs } from "@/hooks/use-api-filter";
-import { useCameraPreviews } from "@/hooks/use-camera-previews";
-import { useOverlayState, useSearchEffect } from "@/hooks/use-overlay-state";
-import { FrigateConfig } from "@/types/frigateConfig";
-import { RecordingStartingPoint } from "@/types/record";
+import { useSearchEffect } from "@/hooks/use-overlay-state";
import { SearchFilter, SearchQuery, SearchResult } from "@/types/search";
-import { TimeRange } from "@/types/timeline";
-import { RecordingView } from "@/views/recording/RecordingView";
import SearchView from "@/views/search/SearchView";
import { useCallback, useEffect, useMemo, useState } from "react";
-import useSWR from "swr";
import useSWRInfinite from "swr/infinite";
const API_LIMIT = 25;
export default function Explore() {
- const { data: config } = useSWR("config", {
- revalidateOnFocus: false,
- });
-
// search field handler
const [search, setSearch] = useState("");
- const [searchTerm, setSearchTerm] = useState("");
- const [recording, setRecording] =
- useOverlayState("recording");
+ const [searchFilter, setSearchFilter, searchSearchParams] =
+ useApiFilterArgs();
+
+ const searchTerm = useMemo(
+ () => searchSearchParams?.["query"] || "",
+ [searchSearchParams],
+ );
// search filter
@@ -36,11 +30,13 @@ export default function Explore() {
return searchTerm.split(":")[1];
}, [searchTerm]);
- const [searchFilter, setSearchFilter, searchSearchParams] =
- useApiFilterArgs();
-
// search api
+ useSearchEffect("query", (query) => {
+ setSearch(query);
+ return false;
+ });
+
useSearchEffect("similarity_search_id", (similarityId) => {
setSearch(`similarity:${similarityId}`);
// @ts-expect-error we want to clear this
@@ -49,7 +45,16 @@ export default function Explore() {
});
useEffect(() => {
- setSearchTerm(search);
+ if (!searchTerm && !search) {
+ return;
+ }
+
+ setSearchFilter({
+ ...searchFilter,
+ query: search.length > 0 ? search : undefined,
+ });
+ // only update when search is updated
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [search]);
const searchQuery: SearchQuery = useMemo(() => {
@@ -168,109 +173,19 @@ export default function Explore() {
}
}, [isReachingEnd, isLoadingMore, setSize, size, searchResults, searchQuery]);
- // previews
-
- const previewTimeRange = useMemo(() => {
- if (!searchResults) {
- return { after: 0, before: 0 };
- }
-
- return {
- after: Math.min(...searchResults.map((res) => res.start_time)),
- before: Math.max(
- ...searchResults.map((res) => res.end_time ?? Date.now() / 1000),
- ),
- };
- }, [searchResults]);
-
- const allPreviews = useCameraPreviews(previewTimeRange, {
- autoRefresh: false,
- fetchPreviews: searchResults != undefined,
- });
-
- // selection
-
- const onOpenSearch = useCallback(
- (item: SearchResult) => {
- setRecording({
- camera: item.camera,
- startTime: item.start_time,
- severity: "alert",
- });
- },
- [setRecording],
+ return (
+ setSearch(`similarity:${search.id}`)}
+ setSearchFilter={setSearchFilter}
+ onUpdateFilter={setSearchFilter}
+ loadMore={loadMore}
+ hasMore={!isReachingEnd}
+ />
);
-
- const selectedReviewData = useMemo(() => {
- if (!recording) {
- return undefined;
- }
-
- if (!config) {
- return undefined;
- }
-
- if (!searchResults) {
- return undefined;
- }
-
- const allCameras = searchFilter?.cameras ?? Object.keys(config.cameras);
-
- return {
- camera: recording.camera,
- start_time: recording.startTime,
- allCameras: allCameras,
- };
-
- // previews will not update after item is selected
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [recording, searchResults]);
-
- const selectedTimeRange = useMemo(() => {
- if (!recording) {
- return undefined;
- }
-
- const time = new Date(recording.startTime * 1000);
- time.setUTCMinutes(0, 0, 0);
- const start = time.getTime() / 1000;
- time.setHours(time.getHours() + 2);
- const end = time.getTime() / 1000;
- return {
- after: start,
- before: end,
- };
- }, [recording]);
-
- if (recording) {
- if (selectedReviewData && selectedTimeRange) {
- return (
-
- );
- }
- } else {
- return (
- setSearch(`similarity:${search.id}`)}
- setSearchFilter={setSearchFilter}
- onUpdateFilter={setSearchFilter}
- onOpenSearch={onOpenSearch}
- loadMore={loadMore}
- hasMore={!isReachingEnd}
- />
- );
- }
}
diff --git a/web/src/types/search.ts b/web/src/types/search.ts
index 141d3a72e..54cd7c948 100644
--- a/web/src/types/search.ts
+++ b/web/src/types/search.ts
@@ -29,6 +29,7 @@ export type SearchResult = {
};
export type SearchFilter = {
+ query?: string;
cameras?: string[];
labels?: string[];
subLabels?: string[];
diff --git a/web/src/utils/dateUtil.ts b/web/src/utils/dateUtil.ts
index fee8bd195..deb1dc850 100644
--- a/web/src/utils/dateUtil.ts
+++ b/web/src/utils/dateUtil.ts
@@ -285,6 +285,11 @@ export function endOfHourOrCurrentTime(timestamp: number) {
return Math.min(timestamp, now.getTime() / 1000);
}
+export function getBeginningOfDayTimestamp(date: Date) {
+ date.setHours(0, 0, 0, 0);
+ return date.getTime() / 1000;
+}
+
export function getEndOfDayTimestamp(date: Date) {
date.setHours(23, 59, 59, 999);
return date.getTime() / 1000;
diff --git a/web/src/views/search/SearchView.tsx b/web/src/views/search/SearchView.tsx
index b0ce92bec..bdde82115 100644
--- a/web/src/views/search/SearchView.tsx
+++ b/web/src/views/search/SearchView.tsx
@@ -33,7 +33,6 @@ type SearchViewProps = {
setSimilaritySearch: (search: SearchResult) => void;
setSearchFilter: (filter: SearchFilter) => void;
onUpdateFilter: (filter: SearchFilter) => void;
- onOpenSearch: (item: SearchResult) => void;
loadMore: () => void;
hasMore: boolean;
};