mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-11 01:27:36 +03:00
Revised plan: focus on batch assignment and explore view assignment
Co-authored-by: Teagan42 <2989925+Teagan42@users.noreply.github.com>
This commit is contained in:
parent
8d0b4b8322
commit
9a41eaceb9
@ -416,6 +416,86 @@ export default function FaceLibrary() {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{pageToggle === "train" && (
|
||||
<FaceSelectionDialog
|
||||
faceNames={faces}
|
||||
onTrainAttempt={(name) => {
|
||||
// Batch train all selected faces
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
const totalCount = selectedFaces.length;
|
||||
|
||||
selectedFaces.forEach((filename, index) => {
|
||||
axios
|
||||
.post(`/faces/train/${name}/classify`, {
|
||||
training_file: filename,
|
||||
})
|
||||
.then((resp) => {
|
||||
if (resp.status == 200) {
|
||||
successCount++;
|
||||
} else {
|
||||
failCount++;
|
||||
}
|
||||
|
||||
// Show final toast after all requests complete
|
||||
if (index === totalCount - 1) {
|
||||
if (successCount === totalCount) {
|
||||
toast.success(
|
||||
t("toast.success.batchTrainedFaces", {
|
||||
count: successCount,
|
||||
}),
|
||||
{
|
||||
position: "top-center",
|
||||
},
|
||||
);
|
||||
} else if (successCount > 0) {
|
||||
toast.warning(
|
||||
t("toast.warning.partialBatchTrained", {
|
||||
success: successCount,
|
||||
total: totalCount,
|
||||
}),
|
||||
{
|
||||
position: "top-center",
|
||||
},
|
||||
);
|
||||
} else {
|
||||
toast.error(
|
||||
t("toast.error.batchTrainFailed", {
|
||||
count: totalCount,
|
||||
}),
|
||||
{
|
||||
position: "top-center",
|
||||
},
|
||||
);
|
||||
}
|
||||
setSelectedFaces([]);
|
||||
refreshFaces();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
failCount++;
|
||||
if (index === totalCount - 1) {
|
||||
toast.error(
|
||||
t("toast.error.batchTrainFailed", {
|
||||
count: totalCount,
|
||||
}),
|
||||
{
|
||||
position: "top-center",
|
||||
},
|
||||
);
|
||||
setSelectedFaces([]);
|
||||
refreshFaces();
|
||||
}
|
||||
});
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Button className="flex gap-2">
|
||||
<AddFaceIcon className="size-7 rounded-md p-1 text-secondary-foreground" />
|
||||
{isDesktop && t("button.trainFaces")}
|
||||
</Button>
|
||||
</FaceSelectionDialog>
|
||||
)}
|
||||
<Button
|
||||
className="flex gap-2"
|
||||
onClick={() =>
|
||||
@ -811,6 +891,7 @@ type FaceAttemptGroupProps = {
|
||||
) => FaceLibraryData | undefined),
|
||||
opts?: boolean | { revalidate?: boolean },
|
||||
) => Promise<FaceLibraryData | undefined>;
|
||||
onClickEvent: (event: Event) => void;
|
||||
};
|
||||
function FaceAttemptGroup({
|
||||
config,
|
||||
@ -820,6 +901,7 @@ function FaceAttemptGroup({
|
||||
selectedFaces,
|
||||
onClickFaces,
|
||||
onRefresh,
|
||||
onClickEvent,
|
||||
}: FaceAttemptGroupProps) {
|
||||
const { t } = useTranslation(["views/faceLibrary", "views/explore"]);
|
||||
|
||||
@ -837,6 +919,10 @@ function FaceAttemptGroup({
|
||||
const handleClickEvent = useCallback(
|
||||
(meta: boolean) => {
|
||||
if (!meta) {
|
||||
// Open detail view when clicking without meta key
|
||||
if (event) {
|
||||
onClickEvent(event);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
const anySelected =
|
||||
@ -861,7 +947,7 @@ function FaceAttemptGroup({
|
||||
}
|
||||
}
|
||||
},
|
||||
[group, selectedFaces, onClickFaces],
|
||||
[group, selectedFaces, onClickFaces, event, onClickEvent],
|
||||
);
|
||||
|
||||
// api calls
|
||||
|
||||
Loading…
Reference in New Issue
Block a user