Add ability to filter Explore by Frigate+ submission status (#14909)

* backend

* add is_submitted to query params

* add submitted filter to dialog

* allow is_submitted filter selection with input
This commit is contained in:
Josh Hawkins
2024-11-10 16:57:11 -06:00
committed by GitHub
parent c1bfc1df67
commit 0829517b72
7 changed files with 135 additions and 13 deletions

View File

@@ -119,6 +119,7 @@ export default function SearchFilterDialog({
}
/>
<SnapshotClipFilterContent
config={config}
hasSnapshot={
currentFilter.has_snapshot !== undefined
? currentFilter.has_snapshot === 1
@@ -129,12 +130,19 @@ export default function SearchFilterDialog({
? currentFilter.has_clip === 1
: undefined
}
setSnapshotClip={(snapshot, clip) =>
submittedToFrigatePlus={
currentFilter.is_submitted !== undefined
? currentFilter.is_submitted === 1
: undefined
}
setSnapshotClip={(snapshot, clip, submitted) =>
setCurrentFilter({
...currentFilter,
has_snapshot:
snapshot !== undefined ? (snapshot ? 1 : 0) : undefined,
has_clip: clip !== undefined ? (clip ? 1 : 0) : undefined,
is_submitted:
submitted !== undefined ? (submitted ? 1 : 0) : undefined,
})
}
/>
@@ -508,17 +516,22 @@ export function ScoreFilterContent({
}
type SnapshotClipContentProps = {
config?: FrigateConfig;
hasSnapshot: boolean | undefined;
hasClip: boolean | undefined;
submittedToFrigatePlus: boolean | undefined;
setSnapshotClip: (
snapshot: boolean | undefined,
clip: boolean | undefined,
submittedToFrigate: boolean | undefined,
) => void;
};
function SnapshotClipFilterContent({
export function SnapshotClipFilterContent({
config,
hasSnapshot,
hasClip,
submittedToFrigatePlus,
setSnapshotClip,
}: SnapshotClipContentProps) {
const [isSnapshotFilterActive, setIsSnapshotFilterActive] = useState(
@@ -527,6 +540,11 @@ function SnapshotClipFilterContent({
const [isClipFilterActive, setIsClipFilterActive] = useState(
hasClip !== undefined,
);
const [isFrigatePlusFilterActive, setIsFrigatePlusFilterActive] = useState(
submittedToFrigatePlus !== undefined &&
isSnapshotFilterActive &&
hasSnapshot === true,
);
useEffect(() => {
setIsSnapshotFilterActive(hasSnapshot !== undefined);
@@ -536,6 +554,14 @@ function SnapshotClipFilterContent({
setIsClipFilterActive(hasClip !== undefined);
}, [hasClip]);
useEffect(() => {
setIsFrigatePlusFilterActive(
submittedToFrigatePlus !== undefined &&
isSnapshotFilterActive &&
hasSnapshot === true,
);
}, [submittedToFrigatePlus, isSnapshotFilterActive, hasSnapshot]);
return (
<div className="overflow-x-hidden">
<DropdownMenuSeparator className="mb-3" />
@@ -551,9 +577,9 @@ function SnapshotClipFilterContent({
onCheckedChange={(checked) => {
setIsSnapshotFilterActive(checked as boolean);
if (checked) {
setSnapshotClip(true, hasClip);
setSnapshotClip(true, hasClip, submittedToFrigatePlus);
} else {
setSnapshotClip(undefined, hasClip);
setSnapshotClip(undefined, hasClip, undefined);
}
}}
/>
@@ -570,8 +596,10 @@ function SnapshotClipFilterContent({
hasSnapshot === undefined ? undefined : hasSnapshot ? "yes" : "no"
}
onValueChange={(value) => {
if (value === "yes") setSnapshotClip(true, hasClip);
else if (value === "no") setSnapshotClip(false, hasClip);
if (value === "yes")
setSnapshotClip(true, hasClip, submittedToFrigatePlus);
else if (value === "no")
setSnapshotClip(false, hasClip, undefined);
}}
disabled={!isSnapshotFilterActive}
>
@@ -592,6 +620,66 @@ function SnapshotClipFilterContent({
</ToggleGroup>
</div>
{config?.plus?.enabled && (
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<Checkbox
id="plus-filter"
className="size-5 text-white accent-white data-[state=checked]:bg-selected data-[state=checked]:text-white"
checked={isFrigatePlusFilterActive}
disabled={!isSnapshotFilterActive || hasSnapshot !== true}
onCheckedChange={(checked) => {
setIsFrigatePlusFilterActive(checked as boolean);
if (checked) {
setSnapshotClip(hasSnapshot, hasClip, true);
} else {
setSnapshotClip(hasSnapshot, hasClip, undefined);
}
}}
/>
<Label
htmlFor="plus-filter"
className="cursor-pointer text-sm font-medium leading-none"
>
Submitted to Frigate+
</Label>
</div>
<ToggleGroup
type="single"
value={
submittedToFrigatePlus === undefined
? undefined
: submittedToFrigatePlus
? "yes"
: "no"
}
onValueChange={(value) => {
if (value === "yes")
setSnapshotClip(hasSnapshot, hasClip, true);
else if (value === "no")
setSnapshotClip(hasSnapshot, hasClip, false);
else setSnapshotClip(hasSnapshot, hasClip, undefined);
}}
disabled={!isFrigatePlusFilterActive}
>
<ToggleGroupItem
value="yes"
aria-label="Yes"
className="data-[state=on]:bg-selected data-[state=on]:text-white data-[state=on]:hover:bg-selected data-[state=on]:hover:text-white"
>
Yes
</ToggleGroupItem>
<ToggleGroupItem
value="no"
aria-label="No"
className="data-[state=on]:bg-selected data-[state=on]:text-white data-[state=on]:hover:bg-selected data-[state=on]:hover:text-white"
>
No
</ToggleGroupItem>
</ToggleGroup>
</div>
)}
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<Checkbox
@@ -601,9 +689,13 @@ function SnapshotClipFilterContent({
onCheckedChange={(checked) => {
setIsClipFilterActive(checked as boolean);
if (checked) {
setSnapshotClip(hasSnapshot, true);
setSnapshotClip(hasSnapshot, true, submittedToFrigatePlus);
} else {
setSnapshotClip(hasSnapshot, undefined);
setSnapshotClip(
hasSnapshot,
undefined,
submittedToFrigatePlus,
);
}
}}
/>
@@ -618,8 +710,10 @@ function SnapshotClipFilterContent({
type="single"
value={hasClip === undefined ? undefined : hasClip ? "yes" : "no"}
onValueChange={(value) => {
if (value === "yes") setSnapshotClip(hasSnapshot, true);
else if (value === "no") setSnapshotClip(hasSnapshot, false);
if (value === "yes")
setSnapshotClip(hasSnapshot, true, submittedToFrigatePlus);
else if (value === "no")
setSnapshotClip(hasSnapshot, false, submittedToFrigatePlus);
}}
disabled={!isClipFilterActive}
>