Add error handling for unsupported label uploading to frigate+ (#9775)

This commit is contained in:
Maximo Guk 2024-02-10 15:35:17 -04:00 committed by GitHub
parent 91cdf64602
commit 86341c3172
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 87 additions and 21 deletions

View File

@ -275,6 +275,13 @@ def send_to_plus(id):
box, box,
event.label, event.label,
) )
except ValueError:
message = "Error uploading annotation, unsupported label provided."
logger.error(message)
return make_response(
jsonify({"success": False, "message": message}),
400,
)
except Exception as ex: except Exception as ex:
logger.exception(ex) logger.exception(ex)
return make_response( return make_response(
@ -346,6 +353,13 @@ def false_positive(id):
event.model_type, event.model_type,
event.detector_type, event.detector_type,
) )
except ValueError:
message = "Error uploading false positive, unsupported label provided."
logger.error(message)
return make_response(
jsonify({"success": False, "message": message}),
400,
)
except Exception as ex: except Exception as ex:
logger.exception(ex) logger.exception(ex)
return make_response( return make_response(

View File

@ -171,6 +171,17 @@ class PlusApi:
) )
if not r.ok: if not r.ok:
try:
error_response = r.json()
errors = error_response.get("errors", [])
for error in errors:
if (
error.get("param") == "label"
and error.get("type") == "invalid_enum_value"
):
raise ValueError(f"Unsupported label value provided: {label}")
except ValueError as e:
raise e
raise Exception(r.text) raise Exception(r.text)
def add_annotation( def add_annotation(
@ -193,6 +204,17 @@ class PlusApi:
) )
if not r.ok: if not r.ok:
try:
error_response = r.json()
errors = error_response.get("errors", [])
for error in errors:
if (
error.get("param") == "label"
and error.get("type") == "invalid_enum_value"
):
raise ValueError(f"Unsupported label value provided: {label}")
except ValueError as e:
raise e
raise Exception(r.text) raise Exception(r.text)
def get_model_download_url( def get_model_download_url(

View File

@ -7,7 +7,7 @@ import Link from '../components/Link';
import { useApiHost } from '../api'; import { useApiHost } from '../api';
import useSWR from 'swr'; import useSWR from 'swr';
import useSWRInfinite from 'swr/infinite'; import useSWRInfinite from 'swr/infinite';
import axios from 'axios'; import axios, { AxiosError } from 'axios';
import { useState, useRef, useCallback, useMemo } from 'preact/hooks'; import { useState, useRef, useCallback, useMemo } from 'preact/hooks';
import VideoPlayer from '../components/VideoPlayer'; import VideoPlayer from '../components/VideoPlayer';
import { StarRecording } from '../icons/StarRecording'; import { StarRecording } from '../icons/StarRecording';
@ -79,6 +79,7 @@ export default function Events({ path, ...props }) {
validBox: null, validBox: null,
}); });
const [uploading, setUploading] = useState([]); const [uploading, setUploading] = useState([]);
const [uploadErrors, setUploadErrors] = useState([]);
const [viewEvent, setViewEvent] = useState(props.event); const [viewEvent, setViewEvent] = useState(props.event);
const [eventOverlay, setEventOverlay] = useState(); const [eventOverlay, setEventOverlay] = useState();
const [eventDetailType, setEventDetailType] = useState('clip'); const [eventDetailType, setEventDetailType] = useState('clip');
@ -328,27 +329,40 @@ export default function Events({ path, ...props }) {
setUploading((prev) => [...prev, id]); setUploading((prev) => [...prev, id]);
const response = false_positive try {
? await axios.put(`events/${id}/false_positive`) const response = false_positive
: await axios.post(`events/${id}/plus`, validBox ? { include_annotation: 1 } : {}); ? await axios.put(`events/${id}/false_positive`)
: await axios.post(`events/${id}/plus`, validBox ? { include_annotation: 1 } : {});
if (response.status === 200) { if (response.status === 200) {
mutate( mutate(
(pages) => (pages) =>
pages.map((page) => pages.map((page) =>
page.map((event) => { page.map((event) => {
if (event.id === id) { if (event.id === id) {
return { ...event, plus_id: response.data.plus_id }; return { ...event, plus_id: response.data.plus_id };
} }
return event; return event;
}) })
), ),
false false
); );
}
} catch (e) {
if (
e instanceof AxiosError &&
(e.response.data.message === 'Error uploading annotation, unsupported label provided.' ||
e.response.data.message === 'Error uploading false positive, unsupported label provided.')
) {
setUploadErrors((prev) => [...prev, { id, isUnsupported: true }]);
return;
}
setUploadErrors((prev) => [...prev, { id }]);
throw e;
} finally {
setUploading((prev) => prev.filter((i) => i !== id));
} }
setUploading((prev) => prev.filter((i) => i !== id));
if (state.showDownloadMenu && downloadEvent.id === id) { if (state.showDownloadMenu && downloadEvent.id === id) {
setState({ ...state, showDownloadMenu: false }); setState({ ...state, showDownloadMenu: false });
} }
@ -681,6 +695,7 @@ export default function Events({ path, ...props }) {
viewEvent={viewEvent} viewEvent={viewEvent}
setViewEvent={setViewEvent} setViewEvent={setViewEvent}
uploading={uploading} uploading={uploading}
uploadErrors={uploadErrors}
handleEventDetailTabChange={handleEventDetailTabChange} handleEventDetailTabChange={handleEventDetailTabChange}
onEventFrameSelected={onEventFrameSelected} onEventFrameSelected={onEventFrameSelected}
onDelete={onDelete} onDelete={onDelete}
@ -721,6 +736,7 @@ export default function Events({ path, ...props }) {
lastEvent={lastEvent} lastEvent={lastEvent}
lastEventRef={lastEventRef} lastEventRef={lastEventRef}
uploading={uploading} uploading={uploading}
uploadErrors={uploadErrors}
handleEventDetailTabChange={handleEventDetailTabChange} handleEventDetailTabChange={handleEventDetailTabChange}
onEventFrameSelected={onEventFrameSelected} onEventFrameSelected={onEventFrameSelected}
onDelete={onDelete} onDelete={onDelete}
@ -760,6 +776,7 @@ function Event({
lastEvent, lastEvent,
lastEventRef, lastEventRef,
uploading, uploading,
uploadErrors,
handleEventDetailTabChange, handleEventDetailTabChange,
onEventFrameSelected, onEventFrameSelected,
onDelete, onDelete,
@ -769,6 +786,19 @@ function Event({
onSave, onSave,
showSubmitToPlus, showSubmitToPlus,
}) { }) {
const getUploadButtonState = (eventId) => {
const isUploading = uploading.includes(eventId);
const hasUploadError = uploadErrors.find((event) => event.id === eventId);
if (hasUploadError) {
if (hasUploadError.isUnsupported) {
return { isDisabled: true, label: 'Unsupported label' };
}
return { isDisabled: isUploading, label: 'Upload error' };
}
const label = isUploading ? 'Uploading...' : 'Send to Frigate+';
return { isDisabled: isUploading, label };
};
const apiHost = useApiHost(); const apiHost = useApiHost();
return ( return (
@ -849,10 +879,10 @@ function Event({
) : ( ) : (
<Button <Button
color="gray" color="gray"
disabled={uploading.includes(event.id)} disabled={getUploadButtonState(event.id).isDisabled}
onClick={(e) => showSubmitToPlus(event.id, event.label, event?.data?.box || event.box, e)} onClick={(e) => showSubmitToPlus(event.id, event.label, event?.data?.box || event.box, e)}
> >
{uploading.includes(event.id) ? 'Uploading...' : 'Send to Frigate+'} {getUploadButtonState(event.id).label}
</Button> </Button>
)} )}
</Fragment> </Fragment>