Refactor search details into Explore Page (#13665)

This commit is contained in:
Nicolas Mowen
2024-09-11 08:41:16 -06:00
committed by GitHub
parent e016bd6900
commit 3972642ba0
18 changed files with 1075 additions and 713 deletions

View File

@@ -1,8 +1,8 @@
import SearchThumbnail from "@/components/card/SearchThumbnail";
import SearchFilterGroup from "@/components/filter/SearchFilterGroup";
import ActivityIndicator from "@/components/indicators/activity-indicator";
import Chip from "@/components/indicators/Chip";
import SearchDetailDialog from "@/components/overlay/detail/SearchDetailDialog";
import SearchThumbnailPlayer from "@/components/player/SearchThumbnailPlayer";
import { Input } from "@/components/ui/input";
import { Toaster } from "@/components/ui/sonner";
import {
@@ -12,7 +12,6 @@ import {
} from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
import { FrigateConfig } from "@/types/frigateConfig";
import { Preview } from "@/types/preview";
import {
PartialSearchResult,
SearchFilter,
@@ -22,13 +21,13 @@ import { useCallback, useMemo, useState } from "react";
import { isMobileOnly } from "react-device-detect";
import { LuImage, LuSearchX, LuText, LuXCircle } from "react-icons/lu";
import useSWR from "swr";
import ExploreView from "../explore/ExploreView";
type SearchViewProps = {
search: string;
searchTerm: string;
searchFilter?: SearchFilter;
searchResults?: SearchResult[];
allPreviews?: Preview[];
isLoading: boolean;
similaritySearch?: PartialSearchResult;
setSearch: (search: string) => void;
@@ -41,13 +40,11 @@ export default function SearchView({
searchTerm,
searchFilter,
searchResults,
allPreviews,
isLoading,
similaritySearch,
setSearch,
setSimilaritySearch,
onUpdateFilter,
onOpenSearch,
}: SearchViewProps) {
const { data: config } = useSWR<FrigateConfig>("config", {
revalidateOnFocus: false,
@@ -68,16 +65,13 @@ export default function SearchView({
// search interaction
const onSelectSearch = useCallback(
(item: SearchResult, detail: boolean) => {
if (detail) {
setSearchDetail(item);
} else {
onOpenSearch(item);
}
},
[onOpenSearch],
);
const onSelectSearch = useCallback((item: SearchResult, detail: boolean) => {
if (detail) {
setSearchDetail(item);
} else {
setSearchDetail(item);
}
}, []);
// confidence score - probably needs tweaking
@@ -116,25 +110,23 @@ export default function SearchView({
<div
className={cn(
"relative mb-2 flex h-11 items-center pl-2 pr-2 md:pl-3",
"flex h-11 items-center pl-2 pr-2 md:pl-3",
config?.semantic_search?.enabled
? "justify-between"
: "justify-center",
isMobileOnly && "h-[88px] flex-wrap gap-2",
isMobileOnly && "mb-3 h-auto flex-wrap gap-2",
)}
>
{config?.semantic_search?.enabled && (
<div
className={cn(
"relative w-full",
hasExistingSearch ? "mr-3 md:w-1/3" : "md:ml-[25%] md:w-1/2",
hasExistingSearch ? "md:mr-3 md:w-1/3" : "md:ml-[25%] md:w-1/2",
)}
>
<Input
className="text-md w-full bg-muted pr-10"
placeholder={
isMobileOnly ? "Search" : "Search for a detected object..."
}
placeholder={"Search for a detected object..."}
value={similaritySearch ? "" : search}
onChange={(e) => setSearch(e.target.value)}
/>
@@ -168,66 +160,73 @@ export default function SearchView({
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
)}
<div className="grid w-full gap-2 px-1 sm:grid-cols-2 md:mx-2 md:grid-cols-4 md:gap-4 3xl:grid-cols-6">
{uniqueResults &&
uniqueResults.map((value) => {
const selected = false;
{uniqueResults && (
<div className="mt-2 grid w-full gap-2 px-1 sm:grid-cols-2 md:mx-2 md:grid-cols-4 md:gap-4 3xl:grid-cols-6">
{uniqueResults &&
uniqueResults.map((value) => {
const selected = false;
return (
<div
key={value.id}
data-start={value.start_time}
className="review-item relative rounded-lg"
>
return (
<div
className={cn(
"aspect-square size-full overflow-hidden rounded-lg",
)}
key={value.id}
data-start={value.start_time}
className="review-item relative rounded-lg"
>
<SearchThumbnailPlayer
searchResult={value}
allPreviews={allPreviews}
scrollLock={false}
onClick={onSelectSearch}
/>
{(searchTerm || similaritySearch) && (
<div className={cn("absolute right-2 top-2 z-40")}>
<Tooltip>
<TooltipTrigger>
<Chip
className={`flex select-none items-center justify-between space-x-1 bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500 text-xs capitalize text-white`}
>
{value.search_source == "thumbnail" ? (
<LuImage className="mr-1 size-3" />
) : (
<LuText className="mr-1 size-3" />
)}
<div
className={cn(
"aspect-square size-full overflow-hidden rounded-lg",
)}
>
<SearchThumbnail
searchResult={value}
scrollLock={false}
findSimilar={() => setSimilaritySearch(value)}
onClick={onSelectSearch}
/>
{(searchTerm || similaritySearch) && (
<div className={cn("absolute right-2 top-2 z-40")}>
<Tooltip>
<TooltipTrigger>
<Chip
className={`flex select-none items-center justify-between space-x-1 bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500 text-xs capitalize text-white`}
>
{value.search_source == "thumbnail" ? (
<LuImage className="mr-1 size-3" />
) : (
<LuText className="mr-1 size-3" />
)}
{zScoreToConfidence(
value.search_distance,
value.search_source,
)}
%
</Chip>
</TooltipTrigger>
<TooltipContent>
Matched {value.search_source} at{" "}
{zScoreToConfidence(
value.search_distance,
value.search_source,
)}
%
</Chip>
</TooltipTrigger>
<TooltipContent>
Matched {value.search_source} at{" "}
{zScoreToConfidence(
value.search_distance,
value.search_source,
)}
%
</TooltipContent>
</Tooltip>
</div>
)}
</TooltipContent>
</Tooltip>
</div>
)}
</div>
<div
className={`review-item-ring pointer-events-none absolute inset-0 z-10 size-full rounded-lg outline outline-[3px] -outline-offset-[2.8px] ${selected ? `shadow-severity_alert outline-severity_alert` : "outline-transparent duration-500"}`}
/>
</div>
<div
className={`review-item-ring pointer-events-none absolute inset-0 z-10 size-full rounded-lg outline outline-[3px] -outline-offset-[2.8px] ${selected ? `shadow-severity_alert outline-severity_alert` : "outline-transparent duration-500"}`}
/>
</div>
);
})}
</div>
);
})}
</div>
)}
{!uniqueResults && !isLoading && (
<div className="flex size-full flex-col">
<ExploreView onSelectSearch={onSelectSearch} />
</div>
)}
</div>
</div>
);