show Frigate+ submission failures in the UI instead of showing a false success (#23579)
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions

This commit is contained in:
Josh Hawkins 2026-06-27 17:38:24 -05:00 committed by GitHub
parent 1ec511b66c
commit e2ce0c82ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 69 additions and 34 deletions

View File

@ -24,6 +24,9 @@
}, },
"state": { "state": {
"submitted": "Submitted" "submitted": "Submitted"
},
"toast": {
"error": "Failed to submit to Frigate+. Please check your network connection and try again."
} }
} }
}, },

View File

@ -1251,30 +1251,42 @@ function ObjectDetailsTab({
return; return;
} }
falsePositive try {
? axios.put(`events/${search.id}/false_positive`) const resp = falsePositive
: axios.post(`events/${search.id}/plus`, { ? await axios.put(`events/${search.id}/false_positive`)
include_annotation: 1, : await axios.post(`events/${search.id}/plus`, {
}); include_annotation: 1,
});
setState("submitted"); if (resp.status !== 200 || !resp.data?.success) {
setSearch({ ...search, plus_id: "new_upload" }); throw new Error();
mutate( }
(key) => isEventsKey(key),
(currentData: SearchResult[][] | SearchResult[] | undefined) => setState("submitted");
mapSearchResults(currentData, (event) => setSearch({ ...search, plus_id: "new_upload" });
event.id === search.id mutate(
? { ...event, plus_id: "new_upload" } (key) => isEventsKey(key),
: event, (currentData: SearchResult[][] | SearchResult[] | undefined) =>
), mapSearchResults(currentData, (event) =>
{ event.id === search.id
optimisticData: true, ? { ...event, plus_id: "new_upload" }
rollbackOnError: true, : event,
revalidate: false, ),
}, {
); optimisticData: true,
rollbackOnError: true,
revalidate: false,
},
);
} catch {
setState("reviewing");
toast.error(
t("explore.plus.review.toast.error", { ns: "components/dialog" }),
{ position: "top-center" },
);
}
}, },
[search, mutate, mapSearchResults, setSearch, isEventsKey], [search, mutate, mapSearchResults, setSearch, isEventsKey, t],
); );
const popoverContainerRef = useRef<HTMLDivElement | null>(null); const popoverContainerRef = useRef<HTMLDivElement | null>(null);

View File

@ -1225,11 +1225,15 @@ function LifecycleIconRow({
<DropdownMenuItem <DropdownMenuItem
className="cursor-pointer" className="cursor-pointer"
onSelect={async () => { onSelect={async () => {
const resp = await axios.post( try {
`/${item.camera}/plus/${item.timestamp + annotationOffset / 1000}`, const resp = await axios.post(
); `/${item.camera}/plus/${item.timestamp + annotationOffset / 1000}`,
);
if (resp.status !== 200) {
throw new Error();
}
if (resp && resp.status == 200) {
toast.success( toast.success(
t("toast.success.submittedFrigatePlus", { t("toast.success.submittedFrigatePlus", {
ns: "components/player", ns: "components/player",
@ -1238,8 +1242,8 @@ function LifecycleIconRow({
position: "top-center", position: "top-center",
}, },
); );
} else { } catch {
toast.success( toast.error(
t("toast.error.submitFrigatePlusFailed", { t("toast.error.submitFrigatePlusFailed", {
ns: "components/player", ns: "components/player",
}), }),

View File

@ -10,6 +10,7 @@ import { isDesktop, isMobile, isSafari } from "react-device-detect";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import axios from "axios"; import axios from "axios";
import { toast } from "sonner";
import { useTranslation, Trans } from "react-i18next"; import { useTranslation, Trans } from "react-i18next";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import ActivityIndicator from "@/components/indicators/activity-indicator"; import ActivityIndicator from "@/components/indicators/activity-indicator";
@ -48,13 +49,28 @@ export function FrigatePlusDialog({
const onSubmitToPlus = useCallback( const onSubmitToPlus = useCallback(
async (falsePositive: boolean) => { async (falsePositive: boolean) => {
if (!upload) return; if (!upload) return;
falsePositive
? axios.put(`events/${upload.id}/false_positive`) try {
: axios.post(`events/${upload.id}/plus`, { include_annotation: 1 }); const resp = falsePositive
setState("submitted"); ? await axios.put(`events/${upload.id}/false_positive`)
onEventUploaded(); : await axios.post(`events/${upload.id}/plus`, {
include_annotation: 1,
});
if (resp.status !== 200 || !resp.data?.success) {
throw new Error();
}
setState("submitted");
onEventUploaded();
} catch {
setState("reviewing");
toast.error(t("explore.plus.review.toast.error"), {
position: "top-center",
});
}
}, },
[upload, onEventUploaded], [upload, onEventUploaded, t],
); );
const [imgRef, imgLoaded, onImgLoad] = useImageLoaded(); const [imgRef, imgLoaded, onImgLoad] = useImageLoaded();