Reclassification (#22603)

* add ability to reclassify images

* add ability to reclassify faces

* work around radix pointer events issue again
This commit is contained in:
Josh Hawkins
2026-03-24 07:18:06 -06:00
committed by GitHub
parent 91ef3b2ceb
commit 854ef320de
7 changed files with 324 additions and 13 deletions
@@ -34,7 +34,11 @@ type ClassificationSelectionDialogProps = {
classes: string[];
modelName: string;
image: string;
onRefresh: () => void;
onRefresh?: () => void;
onCategorize?: (category: string) => void;
excludeCategory?: string;
dialogLabel?: string;
tooltipLabel?: string;
children: ReactNode;
};
export default function ClassificationSelectionDialog({
@@ -43,12 +47,21 @@ export default function ClassificationSelectionDialog({
modelName,
image,
onRefresh,
onCategorize,
excludeCategory,
dialogLabel,
tooltipLabel,
children,
}: ClassificationSelectionDialogProps) {
const { t } = useTranslation(["views/classificationModel"]);
const onCategorizeImage = useCallback(
(category: string) => {
if (onCategorize) {
onCategorize(category);
return;
}
axios
.post(`/classification/${modelName}/dataset/categorize`, {
category,
@@ -59,7 +72,7 @@ export default function ClassificationSelectionDialog({
toast.success(t("toast.success.categorizedImage"), {
position: "top-center",
});
onRefresh();
onRefresh?.();
}
})
.catch((error) => {
@@ -72,7 +85,13 @@ export default function ClassificationSelectionDialog({
});
});
},
[modelName, image, onRefresh, t],
[modelName, image, onRefresh, onCategorize, t],
);
const filteredClasses = useMemo(
() =>
excludeCategory ? classes.filter((c) => c !== excludeCategory) : classes,
[classes, excludeCategory],
);
const isChildButton = useMemo(
@@ -111,6 +130,7 @@ export default function ClassificationSelectionDialog({
</SelectorTrigger>
<SelectorContent
className={cn("", isMobile && "mx-1 gap-2 rounded-t-2xl px-4")}
onCloseAutoFocus={(e) => e.preventDefault()}
>
{isMobile && (
<DrawerHeader className="sr-only">
@@ -118,14 +138,16 @@ export default function ClassificationSelectionDialog({
<DrawerDescription>Details</DrawerDescription>
</DrawerHeader>
)}
<DropdownMenuLabel>{t("categorizeImageAs")}</DropdownMenuLabel>
<DropdownMenuLabel>
{dialogLabel ?? t("categorizeImageAs")}
</DropdownMenuLabel>
<div
className={cn(
"flex max-h-[40dvh] flex-col overflow-y-auto",
isMobile && "gap-2 pb-4",
)}
>
{classes
{filteredClasses
.sort((a, b) => {
if (a === "none") return 1;
if (b === "none") return -1;
@@ -152,7 +174,7 @@ export default function ClassificationSelectionDialog({
</div>
</SelectorContent>
</Selector>
<TooltipContent>{t("categorizeImage")}</TooltipContent>
<TooltipContent>{tooltipLabel ?? t("categorizeImage")}</TooltipContent>
</Tooltip>
</div>
);