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; };