Refactor explore settings to classification settings

This commit is contained in:
Nicolas Mowen 2025-03-14 08:03:19 -06:00
parent 2313b8ea05
commit e34bc3764c
2 changed files with 68 additions and 55 deletions

View File

@ -35,7 +35,7 @@ import MotionTunerView from "@/views/settings/MotionTunerView";
import MasksAndZonesView from "@/views/settings/MasksAndZonesView"; import MasksAndZonesView from "@/views/settings/MasksAndZonesView";
import AuthenticationView from "@/views/settings/AuthenticationView"; import AuthenticationView from "@/views/settings/AuthenticationView";
import NotificationView from "@/views/settings/NotificationsSettingsView"; import NotificationView from "@/views/settings/NotificationsSettingsView";
import SearchSettingsView from "@/views/settings/SearchSettingsView"; import ClassificationSettingsView from "@/views/settings/SearchSettingsView";
import UiSettingsView from "@/views/settings/UiSettingsView"; import UiSettingsView from "@/views/settings/UiSettingsView";
import { useSearchEffect } from "@/hooks/use-overlay-state"; import { useSearchEffect } from "@/hooks/use-overlay-state";
import { useSearchParams } from "react-router-dom"; import { useSearchParams } from "react-router-dom";
@ -46,7 +46,7 @@ import { useIsAdmin } from "@/hooks/use-is-admin";
const allSettingsViews = [ const allSettingsViews = [
"UI settings", "UI settings",
"explore settings", "classification settings",
"camera settings", "camera settings",
"masks / zones", "masks / zones",
"motion tuner", "motion tuner",
@ -245,8 +245,8 @@ export default function Settings() {
</div> </div>
<div className="mt-2 flex h-full w-full flex-col items-start md:h-dvh md:pb-24"> <div className="mt-2 flex h-full w-full flex-col items-start md:h-dvh md:pb-24">
{page == "UI settings" && <UiSettingsView />} {page == "UI settings" && <UiSettingsView />}
{page == "explore settings" && ( {page == "classification settings" && (
<SearchSettingsView setUnsavedChanges={setUnsavedChanges} /> <ClassificationSettingsView setUnsavedChanges={setUnsavedChanges} />
)} )}
{page == "debug" && ( {page == "debug" && (
<ObjectSettingsView selectedCamera={selectedCamera} /> <ObjectSettingsView selectedCamera={selectedCamera} />

View File

@ -21,19 +21,20 @@ import {
SelectTrigger, SelectTrigger,
} from "@/components/ui/select"; } from "@/components/ui/select";
type SearchSettingsViewProps = { type ClassificationSettings = {
setUnsavedChanges: React.Dispatch<React.SetStateAction<boolean>>; search: {
};
type SearchSettings = {
enabled?: boolean; enabled?: boolean;
reindex?: boolean; reindex?: boolean;
model_size?: SearchModelSize; model_size?: SearchModelSize;
}; };
};
export default function SearchSettingsView({ type ClassificationSettingsViewProps = {
setUnsavedChanges: React.Dispatch<React.SetStateAction<boolean>>;
};
export default function ClassificationSettingsView({
setUnsavedChanges, setUnsavedChanges,
}: SearchSettingsViewProps) { }: ClassificationSettingsViewProps) {
const { data: config, mutate: updateConfig } = const { data: config, mutate: updateConfig } =
useSWR<FrigateConfig>("config"); useSWR<FrigateConfig>("config");
const [changedValue, setChangedValue] = useState(false); const [changedValue, setChangedValue] = useState(false);
@ -41,40 +42,55 @@ export default function SearchSettingsView({
const { addMessage, removeMessage } = useContext(StatusBarMessagesContext)!; const { addMessage, removeMessage } = useContext(StatusBarMessagesContext)!;
const [searchSettings, setSearchSettings] = useState<SearchSettings>({ const [classificationSettings, setClassificationSettings] =
useState<ClassificationSettings>({
search: {
enabled: undefined, enabled: undefined,
reindex: undefined, reindex: undefined,
model_size: undefined, model_size: undefined,
},
}); });
const [origSearchSettings, setOrigSearchSettings] = useState<SearchSettings>({ const [origSearchSettings, setOrigSearchSettings] =
useState<ClassificationSettings>({
search: {
enabled: undefined, enabled: undefined,
reindex: undefined, reindex: undefined,
model_size: undefined, model_size: undefined,
},
}); });
useEffect(() => { useEffect(() => {
if (config) { if (config) {
if (searchSettings?.enabled == undefined) { if (classificationSettings?.search.enabled == undefined) {
setSearchSettings({ setClassificationSettings({
search: {
enabled: config.semantic_search.enabled, enabled: config.semantic_search.enabled,
reindex: config.semantic_search.reindex, reindex: config.semantic_search.reindex,
model_size: config.semantic_search.model_size, model_size: config.semantic_search.model_size,
},
}); });
} }
setOrigSearchSettings({ setOrigSearchSettings({
search: {
enabled: config.semantic_search.enabled, enabled: config.semantic_search.enabled,
reindex: config.semantic_search.reindex, reindex: config.semantic_search.reindex,
model_size: config.semantic_search.model_size, model_size: config.semantic_search.model_size,
},
}); });
} }
// we know that these deps are correct // we know that these deps are correct
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [config]); }, [config]);
const handleSearchConfigChange = (newConfig: Partial<SearchSettings>) => { const handleSearchConfigChange = (
setSearchSettings((prevConfig) => ({ ...prevConfig, ...newConfig })); newConfig: Partial<ClassificationSettings>,
) => {
setClassificationSettings((prevConfig) => ({
...prevConfig,
...newConfig,
}));
setUnsavedChanges(true); setUnsavedChanges(true);
setChangedValue(true); setChangedValue(true);
}; };
@ -84,14 +100,14 @@ export default function SearchSettingsView({
axios axios
.put( .put(
`config/set?semantic_search.enabled=${searchSettings.enabled ? "True" : "False"}&semantic_search.reindex=${searchSettings.reindex ? "True" : "False"}&semantic_search.model_size=${searchSettings.model_size}`, `config/set?semantic_search.enabled=${classificationSettings.search.enabled ? "True" : "False"}&semantic_search.reindex=${classificationSettings.search.reindex ? "True" : "False"}&semantic_search.model_size=${classificationSettings.search.model_size}`,
{ {
requires_restart: 0, requires_restart: 0,
}, },
) )
.then((res) => { .then((res) => {
if (res.status === 200) { if (res.status === 200) {
toast.success("Explore settings have been saved.", { toast.success("Classification settings have been saved.", {
position: "top-center", position: "top-center",
}); });
setChangedValue(false); setChangedValue(false);
@ -114,15 +130,10 @@ export default function SearchSettingsView({
.finally(() => { .finally(() => {
setIsLoading(false); setIsLoading(false);
}); });
}, [ }, [updateConfig, classificationSettings.search]);
updateConfig,
searchSettings.enabled,
searchSettings.reindex,
searchSettings.model_size,
]);
const onCancel = useCallback(() => { const onCancel = useCallback(() => {
setSearchSettings(origSearchSettings); setClassificationSettings(origSearchSettings);
setChangedValue(false); setChangedValue(false);
removeMessage("search_settings", "search_settings"); removeMessage("search_settings", "search_settings");
}, [origSearchSettings, removeMessage]); }, [origSearchSettings, removeMessage]);
@ -131,7 +142,7 @@ export default function SearchSettingsView({
if (changedValue) { if (changedValue) {
addMessage( addMessage(
"search_settings", "search_settings",
`Unsaved Explore settings changes`, `Unsaved Classification settings changes`,
undefined, undefined,
"search_settings", "search_settings",
); );
@ -143,7 +154,7 @@ export default function SearchSettingsView({
}, [changedValue]); }, [changedValue]);
useEffect(() => { useEffect(() => {
document.title = "Explore Settings - Frigate"; document.title = "Classification Settings - Frigate";
}, []); }, []);
if (!config) { if (!config) {
@ -155,7 +166,7 @@ export default function SearchSettingsView({
<Toaster position="top-center" closeButton={true} /> <Toaster position="top-center" closeButton={true} />
<div className="scrollbar-container order-last mb-10 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mb-0 md:mr-2 md:mt-0"> <div className="scrollbar-container order-last mb-10 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mb-0 md:mr-2 md:mt-0">
<Heading as="h3" className="my-2"> <Heading as="h3" className="my-2">
Explore Settings Classification Settings
</Heading> </Heading>
<Separator className="my-2 flex bg-secondary" /> <Separator className="my-2 flex bg-secondary" />
<Heading as="h4" className="my-2"> <Heading as="h4" className="my-2">
@ -188,10 +199,10 @@ export default function SearchSettingsView({
<Switch <Switch
id="enabled" id="enabled"
className="mr-3" className="mr-3"
disabled={searchSettings.enabled === undefined} disabled={classificationSettings.search.enabled === undefined}
checked={searchSettings.enabled === true} checked={classificationSettings.search.enabled === true}
onCheckedChange={(isChecked) => { onCheckedChange={(isChecked) => {
handleSearchConfigChange({ enabled: isChecked }); handleSearchConfigChange({ search: { enabled: isChecked } });
}} }}
/> />
<div className="space-y-0.5"> <div className="space-y-0.5">
@ -203,10 +214,10 @@ export default function SearchSettingsView({
<Switch <Switch
id="reindex" id="reindex"
className="mr-3" className="mr-3"
disabled={searchSettings.reindex === undefined} disabled={classificationSettings.search.reindex === undefined}
checked={searchSettings.reindex === true} checked={classificationSettings.search.reindex === true}
onCheckedChange={(isChecked) => { onCheckedChange={(isChecked) => {
handleSearchConfigChange({ reindex: isChecked }); handleSearchConfigChange({ search: { reindex: isChecked } });
}} }}
/> />
<div className="space-y-0.5"> <div className="space-y-0.5">
@ -240,15 +251,17 @@ export default function SearchSettingsView({
</div> </div>
</div> </div>
<Select <Select
value={searchSettings.model_size} value={classificationSettings.search.model_size}
onValueChange={(value) => onValueChange={(value) =>
handleSearchConfigChange({ handleSearchConfigChange({
search: {
model_size: value as SearchModelSize, model_size: value as SearchModelSize,
},
}) })
} }
> >
<SelectTrigger className="w-20"> <SelectTrigger className="w-20">
{searchSettings.model_size} {classificationSettings.search.model_size}
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectGroup> <SelectGroup>