mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-08-18 13:47:20 +02:00
Improve recognized license plate filter (#19491)
* Fetch all license plates outside of filter component If the swr call took a long time, the entire select component may not display. This change moves the fetch to the parent component (like sub labels). * add loading indicator * improve query
This commit is contained in:
parent
d1be614a10
commit
2cde58037d
@ -20,7 +20,7 @@ from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.params import Depends
|
||||
from fastapi.responses import JSONResponse, PlainTextResponse, StreamingResponse
|
||||
from markupsafe import escape
|
||||
from peewee import operator
|
||||
from peewee import SQL, operator
|
||||
from pydantic import ValidationError
|
||||
|
||||
from frigate.api.auth import require_role
|
||||
@ -685,7 +685,14 @@ def plusModels(request: Request, filterByCurrentModelDetector: bool = False):
|
||||
@router.get("/recognized_license_plates")
|
||||
def get_recognized_license_plates(split_joined: Optional[int] = None):
|
||||
try:
|
||||
events = Event.select(Event.data).distinct()
|
||||
query = (
|
||||
Event.select(
|
||||
SQL("json_extract(data, '$.recognized_license_plate') AS plate")
|
||||
)
|
||||
.where(SQL("json_extract(data, '$.recognized_license_plate') IS NOT NULL"))
|
||||
.distinct()
|
||||
)
|
||||
recognized_license_plates = [row[0] for row in query.tuples()]
|
||||
except Exception:
|
||||
return JSONResponse(
|
||||
content=(
|
||||
@ -694,14 +701,6 @@ def get_recognized_license_plates(split_joined: Optional[int] = None):
|
||||
status_code=404,
|
||||
)
|
||||
|
||||
recognized_license_plates = []
|
||||
for e in events:
|
||||
if e.data is not None and "recognized_license_plate" in e.data:
|
||||
recognized_license_plates.append(e.data["recognized_license_plate"])
|
||||
|
||||
while None in recognized_license_plates:
|
||||
recognized_license_plates.remove(None)
|
||||
|
||||
if split_joined:
|
||||
original_recognized_license_plates = recognized_license_plates.copy()
|
||||
for recognized_license_plate in original_recognized_license_plates:
|
||||
|
@ -42,6 +42,7 @@ import {
|
||||
CommandList,
|
||||
} from "@/components/ui/command";
|
||||
import { LuCheck } from "react-icons/lu";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
|
||||
type SearchFilterDialogProps = {
|
||||
config?: FrigateConfig;
|
||||
@ -64,6 +65,9 @@ export default function SearchFilterDialog({
|
||||
const { t } = useTranslation(["components/filter"]);
|
||||
const [currentFilter, setCurrentFilter] = useState(filter ?? {});
|
||||
const { data: allSubLabels } = useSWR(["sub_labels", { split_joined: 1 }]);
|
||||
const { data: allRecognizedLicensePlates } = useSWR<string[]>(
|
||||
"recognized_license_plates",
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (filter) {
|
||||
@ -130,6 +134,7 @@ export default function SearchFilterDialog({
|
||||
}
|
||||
/>
|
||||
<RecognizedLicensePlatesFilterContent
|
||||
allRecognizedLicensePlates={allRecognizedLicensePlates}
|
||||
recognizedLicensePlates={currentFilter.recognized_license_plate}
|
||||
setRecognizedLicensePlates={(plate) =>
|
||||
setCurrentFilter({
|
||||
@ -875,6 +880,7 @@ export function SnapshotClipFilterContent({
|
||||
}
|
||||
|
||||
type RecognizedLicensePlatesFilterContentProps = {
|
||||
allRecognizedLicensePlates: string[] | undefined;
|
||||
recognizedLicensePlates: string[] | undefined;
|
||||
setRecognizedLicensePlates: (
|
||||
recognizedLicensePlates: string[] | undefined,
|
||||
@ -882,18 +888,12 @@ type RecognizedLicensePlatesFilterContentProps = {
|
||||
};
|
||||
|
||||
export function RecognizedLicensePlatesFilterContent({
|
||||
allRecognizedLicensePlates,
|
||||
recognizedLicensePlates,
|
||||
setRecognizedLicensePlates,
|
||||
}: RecognizedLicensePlatesFilterContentProps) {
|
||||
const { t } = useTranslation(["components/filter"]);
|
||||
|
||||
const { data: allRecognizedLicensePlates, error } = useSWR<string[]>(
|
||||
"recognized_license_plates",
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
},
|
||||
);
|
||||
|
||||
const [selectedRecognizedLicensePlates, setSelectedRecognizedLicensePlates] =
|
||||
useState<string[]>(recognizedLicensePlates || []);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
@ -923,7 +923,7 @@ export function RecognizedLicensePlatesFilterContent({
|
||||
}
|
||||
};
|
||||
|
||||
if (!allRecognizedLicensePlates || allRecognizedLicensePlates.length === 0) {
|
||||
if (allRecognizedLicensePlates && allRecognizedLicensePlates.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -947,15 +947,12 @@ export function RecognizedLicensePlatesFilterContent({
|
||||
<div className="overflow-x-hidden">
|
||||
<DropdownMenuSeparator className="mb-3" />
|
||||
<div className="mb-3 text-lg">{t("recognizedLicensePlates.title")}</div>
|
||||
{error ? (
|
||||
<p className="text-sm text-red-500">
|
||||
{t("recognizedLicensePlates.loadFailed")}
|
||||
</p>
|
||||
) : !allRecognizedLicensePlates ? (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t("recognizedLicensePlates.loading")}
|
||||
</p>
|
||||
) : (
|
||||
{allRecognizedLicensePlates == undefined ? (
|
||||
<div className="flex flex-col items-center justify-center text-sm text-muted-foreground">
|
||||
<ActivityIndicator className="mb-3 mr-2 size-5" />
|
||||
<p>{t("recognizedLicensePlates.loading")}</p>
|
||||
</div>
|
||||
) : allRecognizedLicensePlates.length == 0 ? null : (
|
||||
<>
|
||||
<Command
|
||||
className="border border-input bg-background"
|
||||
@ -1010,11 +1007,11 @@ export function RecognizedLicensePlatesFilterContent({
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
{t("recognizedLicensePlates.selectPlatesFromList")}
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
{t("recognizedLicensePlates.selectPlatesFromList")}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user