mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-08-08 13:51:01 +02:00
Fixes (#18354)
* Rename classification to enrichments * Clean up config updating checks * Add Portugese --------- Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
This commit is contained in:
parent
c16e536b46
commit
858c1241db
@ -19,7 +19,7 @@ For best performance, 16GB or more of RAM and a dedicated GPU are recommended.
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Semantic Search is disabled by default, and must be enabled in your config file or in the UI's Classification Settings page before it can be used. Semantic Search is a global configuration setting.
|
Semantic Search is disabled by default, and must be enabled in your config file or in the UI's Enrichments Settings page before it can be used. Semantic Search is a global configuration setting.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
semantic_search:
|
semantic_search:
|
||||||
@ -29,7 +29,7 @@ semantic_search:
|
|||||||
|
|
||||||
:::tip
|
:::tip
|
||||||
|
|
||||||
The embeddings database can be re-indexed from the existing tracked objects in your database by pressing the "Reindex" button in the Classification Settings in the UI or by adding `reindex: True` to your `semantic_search` configuration and restarting Frigate. Depending on the number of tracked objects you have, it can take a long while to complete and may max out your CPU while indexing.
|
The embeddings database can be re-indexed from the existing tracked objects in your database by pressing the "Reindex" button in the Enrichments Settings in the UI or by adding `reindex: True` to your `semantic_search` configuration and restarting Frigate. Depending on the number of tracked objects you have, it can take a long while to complete and may max out your CPU while indexing.
|
||||||
|
|
||||||
If you are enabling Semantic Search for the first time, be advised that Frigate does not automatically index older tracked objects. You will need to reindex as described above.
|
If you are enabling Semantic Search for the first time, be advised that Frigate does not automatically index older tracked objects. You will need to reindex as described above.
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ def output_frames(
|
|||||||
move_preview_frames("cache")
|
move_preview_frames("cache")
|
||||||
|
|
||||||
for camera, cam_config in config.cameras.items():
|
for camera, cam_config in config.cameras.items():
|
||||||
if not cam_config.enabled:
|
if not cam_config.enabled_in_config:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
jsmpeg_cameras[camera] = JsmpegCamera(cam_config, stop_event, websocket_server)
|
jsmpeg_cameras[camera] = JsmpegCamera(cam_config, stop_event, websocket_server)
|
||||||
|
@ -403,6 +403,7 @@ class PreviewRecorder:
|
|||||||
self.reset_frame_cache(frame_time)
|
self.reset_frame_cache(frame_time)
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
|
self.config_subscriber.stop()
|
||||||
self.requestor.stop()
|
self.requestor.stop()
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"default": "Settings - Frigate",
|
"default": "Settings - Frigate",
|
||||||
"authentication": "Authentication Settings - Frigate",
|
"authentication": "Authentication Settings - Frigate",
|
||||||
"camera": "Camera Settings - Frigate",
|
"camera": "Camera Settings - Frigate",
|
||||||
"classification": "Classification Settings - Frigate",
|
"enrichments": "Enrichments Settings - Frigate",
|
||||||
"masksAndZones": "Mask and Zone Editor - Frigate",
|
"masksAndZones": "Mask and Zone Editor - Frigate",
|
||||||
"motionTuner": "Motion Tuner - Frigate",
|
"motionTuner": "Motion Tuner - Frigate",
|
||||||
"object": "Debug - Frigate",
|
"object": "Debug - Frigate",
|
||||||
@ -13,7 +13,7 @@
|
|||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"ui": "UI",
|
"ui": "UI",
|
||||||
"classification": "Classification",
|
"enrichments": "Enrichments",
|
||||||
"cameras": "Camera Settings",
|
"cameras": "Camera Settings",
|
||||||
"masksAndZones": "Masks / Zones",
|
"masksAndZones": "Masks / Zones",
|
||||||
"motionTuner": "Motion Tuner",
|
"motionTuner": "Motion Tuner",
|
||||||
@ -82,9 +82,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"classification": {
|
"enrichments": {
|
||||||
"title": "Classification Settings",
|
"title": "Enrichments Settings",
|
||||||
"unsavedChanges": "Unsaved Classification settings changes",
|
"unsavedChanges": "Unsaved Enrichments settings changes",
|
||||||
"birdClassification": {
|
"birdClassification": {
|
||||||
"title": "Bird Classification",
|
"title": "Bird Classification",
|
||||||
"desc": "Bird classification identifies known birds using a quantized Tensorflow model. When a known bird is recognized, its common name will be added as a sub_label. This information is included in the UI, filters, as well as in notifications."
|
"desc": "Bird classification identifies known birds using a quantized Tensorflow model. When a known bird is recognized, its common name will be added as a sub_label. This information is included in the UI, filters, as well as in notifications."
|
||||||
@ -138,9 +138,9 @@
|
|||||||
"desc": "Frigate can recognize license plates on vehicles and automatically add the detected characters to the recognized_license_plate field or a known name as a sub_label to objects that are of type car. A common use case may be to read the license plates of cars pulling into a driveway or cars passing by on a street.",
|
"desc": "Frigate can recognize license plates on vehicles and automatically add the detected characters to the recognized_license_plate field or a known name as a sub_label to objects that are of type car. A common use case may be to read the license plates of cars pulling into a driveway or cars passing by on a street.",
|
||||||
"readTheDocumentation": "Read the Documentation"
|
"readTheDocumentation": "Read the Documentation"
|
||||||
},
|
},
|
||||||
"restart_required": "Restart required (Classification settings changed)",
|
"restart_required": "Restart required (Enrichments settings changed)",
|
||||||
"toast": {
|
"toast": {
|
||||||
"success": "Classification settings have been saved. Restart Frigate to apply your changes.",
|
"success": "Enrichments settings have been saved. Restart Frigate to apply your changes.",
|
||||||
"error": "Failed to save config changes: {{errorMessage}}"
|
"error": "Failed to save config changes: {{errorMessage}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export const supportedLanguageKeys = [
|
export const supportedLanguageKeys = [
|
||||||
"en",
|
"en",
|
||||||
"es",
|
"es",
|
||||||
|
"pt",
|
||||||
"fr",
|
"fr",
|
||||||
"de",
|
"de",
|
||||||
"it",
|
"it",
|
||||||
|
@ -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 ClassificationSettingsView from "@/views/settings/ClassificationSettingsView";
|
import EnrichmentsSettingsView from "@/views/settings/EnrichmentsSettingsView";
|
||||||
import UiSettingsView from "@/views/settings/UiSettingsView";
|
import UiSettingsView from "@/views/settings/UiSettingsView";
|
||||||
import FrigatePlusSettingsView from "@/views/settings/FrigatePlusSettingsView";
|
import FrigatePlusSettingsView from "@/views/settings/FrigatePlusSettingsView";
|
||||||
import { useSearchEffect } from "@/hooks/use-overlay-state";
|
import { useSearchEffect } from "@/hooks/use-overlay-state";
|
||||||
@ -48,7 +48,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
|
|
||||||
const allSettingsViews = [
|
const allSettingsViews = [
|
||||||
"ui",
|
"ui",
|
||||||
"classification",
|
"enrichments",
|
||||||
"cameras",
|
"cameras",
|
||||||
"masksAndZones",
|
"masksAndZones",
|
||||||
"motionTuner",
|
"motionTuner",
|
||||||
@ -249,8 +249,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" && <UiSettingsView />}
|
{page == "ui" && <UiSettingsView />}
|
||||||
{page == "classification" && (
|
{page == "enrichments" && (
|
||||||
<ClassificationSettingsView setUnsavedChanges={setUnsavedChanges} />
|
<EnrichmentsSettingsView setUnsavedChanges={setUnsavedChanges} />
|
||||||
)}
|
)}
|
||||||
{page == "debug" && (
|
{page == "debug" && (
|
||||||
<ObjectSettingsView selectedCamera={selectedCamera} />
|
<ObjectSettingsView selectedCamera={selectedCamera} />
|
||||||
|
@ -33,7 +33,7 @@ import {
|
|||||||
} from "@/components/ui/alert-dialog";
|
} from "@/components/ui/alert-dialog";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/ui/button";
|
||||||
|
|
||||||
type ClassificationSettings = {
|
type EnrichmentsSettings = {
|
||||||
search: {
|
search: {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
model_size?: SearchModelSize;
|
model_size?: SearchModelSize;
|
||||||
@ -50,12 +50,12 @@ type ClassificationSettings = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type ClassificationSettingsViewProps = {
|
type EnrichmentsSettingsViewProps = {
|
||||||
setUnsavedChanges: React.Dispatch<React.SetStateAction<boolean>>;
|
setUnsavedChanges: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
};
|
};
|
||||||
export default function ClassificationSettingsView({
|
export default function EnrichmentsSettingsView({
|
||||||
setUnsavedChanges,
|
setUnsavedChanges,
|
||||||
}: ClassificationSettingsViewProps) {
|
}: EnrichmentsSettingsViewProps) {
|
||||||
const { t } = useTranslation("views/settings");
|
const { t } = useTranslation("views/settings");
|
||||||
const { data: config, mutate: updateConfig } =
|
const { data: config, mutate: updateConfig } =
|
||||||
useSWR<FrigateConfig>("config");
|
useSWR<FrigateConfig>("config");
|
||||||
@ -65,8 +65,8 @@ export default function ClassificationSettingsView({
|
|||||||
|
|
||||||
const { addMessage, removeMessage } = useContext(StatusBarMessagesContext)!;
|
const { addMessage, removeMessage } = useContext(StatusBarMessagesContext)!;
|
||||||
|
|
||||||
const [classificationSettings, setClassificationSettings] =
|
const [enrichmentsSettings, setEnrichmentsSettings] =
|
||||||
useState<ClassificationSettings>({
|
useState<EnrichmentsSettings>({
|
||||||
search: { enabled: undefined, model_size: undefined },
|
search: { enabled: undefined, model_size: undefined },
|
||||||
face: { enabled: undefined, model_size: undefined },
|
face: { enabled: undefined, model_size: undefined },
|
||||||
lpr: { enabled: undefined },
|
lpr: { enabled: undefined },
|
||||||
@ -74,7 +74,7 @@ export default function ClassificationSettingsView({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [origSearchSettings, setOrigSearchSettings] =
|
const [origSearchSettings, setOrigSearchSettings] =
|
||||||
useState<ClassificationSettings>({
|
useState<EnrichmentsSettings>({
|
||||||
search: { enabled: undefined, model_size: undefined },
|
search: { enabled: undefined, model_size: undefined },
|
||||||
face: { enabled: undefined, model_size: undefined },
|
face: { enabled: undefined, model_size: undefined },
|
||||||
lpr: { enabled: undefined },
|
lpr: { enabled: undefined },
|
||||||
@ -83,8 +83,8 @@ export default function ClassificationSettingsView({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (config) {
|
if (config) {
|
||||||
if (classificationSettings?.search.enabled == undefined) {
|
if (enrichmentsSettings?.search.enabled == undefined) {
|
||||||
setClassificationSettings({
|
setEnrichmentsSettings({
|
||||||
search: {
|
search: {
|
||||||
enabled: config.semantic_search.enabled,
|
enabled: config.semantic_search.enabled,
|
||||||
model_size: config.semantic_search.model_size,
|
model_size: config.semantic_search.model_size,
|
||||||
@ -117,10 +117,10 @@ export default function ClassificationSettingsView({
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [config]);
|
}, [config]);
|
||||||
|
|
||||||
const handleClassificationConfigChange = (
|
const handleEnrichmentsConfigChange = (
|
||||||
newConfig: Partial<ClassificationSettings>,
|
newConfig: Partial<EnrichmentsSettings>,
|
||||||
) => {
|
) => {
|
||||||
setClassificationSettings((prevConfig) => ({
|
setEnrichmentsSettings((prevConfig) => ({
|
||||||
search: { ...prevConfig.search, ...newConfig.search },
|
search: { ...prevConfig.search, ...newConfig.search },
|
||||||
face: { ...prevConfig.face, ...newConfig.face },
|
face: { ...prevConfig.face, ...newConfig.face },
|
||||||
lpr: { ...prevConfig.lpr, ...newConfig.lpr },
|
lpr: { ...prevConfig.lpr, ...newConfig.lpr },
|
||||||
@ -135,19 +135,19 @@ export default function ClassificationSettingsView({
|
|||||||
|
|
||||||
axios
|
axios
|
||||||
.put(
|
.put(
|
||||||
`config/set?semantic_search.enabled=${classificationSettings.search.enabled ? "True" : "False"}&semantic_search.model_size=${classificationSettings.search.model_size}&face_recognition.enabled=${classificationSettings.face.enabled ? "True" : "False"}&face_recognition.model_size=${classificationSettings.face.model_size}&lpr.enabled=${classificationSettings.lpr.enabled ? "True" : "False"}&classification.bird.enabled=${classificationSettings.bird.enabled ? "True" : "False"}`,
|
`config/set?semantic_search.enabled=${enrichmentsSettings.search.enabled ? "True" : "False"}&semantic_search.model_size=${enrichmentsSettings.search.model_size}&face_recognition.enabled=${enrichmentsSettings.face.enabled ? "True" : "False"}&face_recognition.model_size=${enrichmentsSettings.face.model_size}&lpr.enabled=${enrichmentsSettings.lpr.enabled ? "True" : "False"}&classification.bird.enabled=${enrichmentsSettings.bird.enabled ? "True" : "False"}`,
|
||||||
{ requires_restart: 0 },
|
{ requires_restart: 0 },
|
||||||
)
|
)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
toast.success(t("classification.toast.success"), {
|
toast.success(t("enrichments.toast.success"), {
|
||||||
position: "top-center",
|
position: "top-center",
|
||||||
});
|
});
|
||||||
setChangedValue(false);
|
setChangedValue(false);
|
||||||
updateConfig();
|
updateConfig();
|
||||||
} else {
|
} else {
|
||||||
toast.error(
|
toast.error(
|
||||||
t("classification.toast.error", { errorMessage: res.statusText }),
|
t("enrichments.toast.error", { errorMessage: res.statusText }),
|
||||||
{ position: "top-center" },
|
{ position: "top-center" },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -164,19 +164,19 @@ export default function ClassificationSettingsView({
|
|||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
addMessage(
|
addMessage(
|
||||||
"search_settings_restart",
|
"enrichments_settings_restart",
|
||||||
t("classification.restart_required"),
|
t("enrichments.restart_required"),
|
||||||
undefined,
|
undefined,
|
||||||
"search_settings",
|
"enrichments_settings",
|
||||||
);
|
);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
});
|
});
|
||||||
}, [classificationSettings, t, addMessage, updateConfig]);
|
}, [enrichmentsSettings, t, addMessage, updateConfig]);
|
||||||
|
|
||||||
const onCancel = useCallback(() => {
|
const onCancel = useCallback(() => {
|
||||||
setClassificationSettings(origSearchSettings);
|
setEnrichmentsSettings(origSearchSettings);
|
||||||
setChangedValue(false);
|
setChangedValue(false);
|
||||||
removeMessage("search_settings", "search_settings");
|
removeMessage("enrichments_settings", "enrichments_settings");
|
||||||
}, [origSearchSettings, removeMessage]);
|
}, [origSearchSettings, removeMessage]);
|
||||||
|
|
||||||
const onReindex = useCallback(() => {
|
const onReindex = useCallback(() => {
|
||||||
@ -186,12 +186,12 @@ export default function ClassificationSettingsView({
|
|||||||
.put("/reindex")
|
.put("/reindex")
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === 202) {
|
if (res.status === 202) {
|
||||||
toast.success(t("classification.semanticSearch.reindexNow.success"), {
|
toast.success(t("enrichments.semanticSearch.reindexNow.success"), {
|
||||||
position: "top-center",
|
position: "top-center",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
toast.error(
|
toast.error(
|
||||||
t("classification.semanticSearch.reindexNow.error", {
|
t("enrichments.semanticSearch.reindexNow.error", {
|
||||||
errorMessage: res.statusText,
|
errorMessage: res.statusText,
|
||||||
}),
|
}),
|
||||||
{ position: "top-center" },
|
{ position: "top-center" },
|
||||||
@ -204,7 +204,7 @@ export default function ClassificationSettingsView({
|
|||||||
error.response?.data?.detail ||
|
error.response?.data?.detail ||
|
||||||
"Unknown error";
|
"Unknown error";
|
||||||
toast.error(
|
toast.error(
|
||||||
t("classification.semanticSearch.reindexNow.error", {
|
t("enrichments.semanticSearch.reindexNow.error", {
|
||||||
errorMessage,
|
errorMessage,
|
||||||
}),
|
}),
|
||||||
{ position: "top-center" },
|
{ position: "top-center" },
|
||||||
@ -219,20 +219,20 @@ export default function ClassificationSettingsView({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (changedValue) {
|
if (changedValue) {
|
||||||
addMessage(
|
addMessage(
|
||||||
"search_settings",
|
"enrichments_settings",
|
||||||
t("classification.unsavedChanges"),
|
t("enrichments.unsavedChanges"),
|
||||||
undefined,
|
undefined,
|
||||||
"search_settings",
|
"enrichments_settings",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
removeMessage("search_settings", "search_settings");
|
removeMessage("enrichments_settings", "enrichments_settings");
|
||||||
}
|
}
|
||||||
// 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
|
||||||
}, [changedValue]);
|
}, [changedValue]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = t("documentTitle.classification");
|
document.title = t("documentTitle.enrichments");
|
||||||
}, [t]);
|
}, [t]);
|
||||||
|
|
||||||
if (!config) {
|
if (!config) {
|
||||||
@ -244,15 +244,15 @@ export default function ClassificationSettingsView({
|
|||||||
<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">
|
||||||
{t("classification.title")}
|
{t("enrichments.title")}
|
||||||
</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">
|
||||||
{t("classification.semanticSearch.title")}
|
{t("enrichments.semanticSearch.title")}
|
||||||
</Heading>
|
</Heading>
|
||||||
<div className="max-w-6xl">
|
<div className="max-w-6xl">
|
||||||
<div className="mb-5 mt-2 flex max-w-5xl flex-col gap-2 text-sm text-primary-variant">
|
<div className="mb-5 mt-2 flex max-w-5xl flex-col gap-2 text-sm text-primary-variant">
|
||||||
<p>{t("classification.semanticSearch.desc")}</p>
|
<p>{t("enrichments.semanticSearch.desc")}</p>
|
||||||
|
|
||||||
<div className="flex items-center text-primary">
|
<div className="flex items-center text-primary">
|
||||||
<Link
|
<Link
|
||||||
@ -261,7 +261,7 @@ export default function ClassificationSettingsView({
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="inline"
|
className="inline"
|
||||||
>
|
>
|
||||||
{t("classification.semanticSearch.readTheDocumentation")}
|
{t("enrichments.semanticSearch.readTheDocumentation")}
|
||||||
<LuExternalLink className="ml-2 inline-flex size-3" />
|
<LuExternalLink className="ml-2 inline-flex size-3" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@ -273,10 +273,10 @@ export default function ClassificationSettingsView({
|
|||||||
<Switch
|
<Switch
|
||||||
id="enabled"
|
id="enabled"
|
||||||
className="mr-3"
|
className="mr-3"
|
||||||
disabled={classificationSettings.search.enabled === undefined}
|
disabled={enrichmentsSettings.search.enabled === undefined}
|
||||||
checked={classificationSettings.search.enabled === true}
|
checked={enrichmentsSettings.search.enabled === true}
|
||||||
onCheckedChange={(isChecked) => {
|
onCheckedChange={(isChecked) => {
|
||||||
handleClassificationConfigChange({
|
handleEnrichmentsConfigChange({
|
||||||
search: { enabled: isChecked },
|
search: { enabled: isChecked },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@ -290,54 +290,54 @@ export default function ClassificationSettingsView({
|
|||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
disabled={isLoading || !classificationSettings.search.enabled}
|
disabled={isLoading || !enrichmentsSettings.search.enabled}
|
||||||
onClick={() => setIsReindexDialogOpen(true)}
|
onClick={() => setIsReindexDialogOpen(true)}
|
||||||
aria-label={t("classification.semanticSearch.reindexNow.label")}
|
aria-label={t("enrichments.semanticSearch.reindexNow.label")}
|
||||||
>
|
>
|
||||||
{t("classification.semanticSearch.reindexNow.label")}
|
{t("enrichments.semanticSearch.reindexNow.label")}
|
||||||
</Button>
|
</Button>
|
||||||
<div className="mt-3 text-sm text-muted-foreground">
|
<div className="mt-3 text-sm text-muted-foreground">
|
||||||
<Trans ns="views/settings">
|
<Trans ns="views/settings">
|
||||||
classification.semanticSearch.reindexNow.desc
|
enrichments.semanticSearch.reindexNow.desc
|
||||||
</Trans>
|
</Trans>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 flex flex-col space-y-6">
|
<div className="mt-2 flex flex-col space-y-6">
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<div className="text-md">
|
<div className="text-md">
|
||||||
{t("classification.semanticSearch.modelSize.label")}
|
{t("enrichments.semanticSearch.modelSize.label")}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1 text-sm text-muted-foreground">
|
<div className="space-y-1 text-sm text-muted-foreground">
|
||||||
<p>
|
<p>
|
||||||
<Trans ns="views/settings">
|
<Trans ns="views/settings">
|
||||||
classification.semanticSearch.modelSize.desc
|
enrichments.semanticSearch.modelSize.desc
|
||||||
</Trans>
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
<ul className="list-disc pl-5 text-sm">
|
<ul className="list-disc pl-5 text-sm">
|
||||||
<li>
|
<li>
|
||||||
<Trans ns="views/settings">
|
<Trans ns="views/settings">
|
||||||
classification.semanticSearch.modelSize.small.desc
|
enrichments.semanticSearch.modelSize.small.desc
|
||||||
</Trans>
|
</Trans>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Trans ns="views/settings">
|
<Trans ns="views/settings">
|
||||||
classification.semanticSearch.modelSize.large.desc
|
enrichments.semanticSearch.modelSize.large.desc
|
||||||
</Trans>
|
</Trans>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<Select
|
||||||
value={classificationSettings.search.model_size}
|
value={enrichmentsSettings.search.model_size}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) =>
|
||||||
handleClassificationConfigChange({
|
handleEnrichmentsConfigChange({
|
||||||
search: { model_size: value as SearchModelSize },
|
search: { model_size: value as SearchModelSize },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-20">
|
<SelectTrigger className="w-20">
|
||||||
{t(
|
{t(
|
||||||
`classification.semanticSearch.modelSize.${classificationSettings.search.model_size}.title`,
|
`enrichments.semanticSearch.modelSize.${enrichmentsSettings.search.model_size}.title`,
|
||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -349,7 +349,7 @@ export default function ClassificationSettingsView({
|
|||||||
value={size}
|
value={size}
|
||||||
>
|
>
|
||||||
{t(
|
{t(
|
||||||
"classification.semanticSearch.modelSize." +
|
"enrichments.semanticSearch.modelSize." +
|
||||||
size +
|
size +
|
||||||
".title",
|
".title",
|
||||||
)}
|
)}
|
||||||
@ -368,11 +368,11 @@ export default function ClassificationSettingsView({
|
|||||||
<AlertDialogContent>
|
<AlertDialogContent>
|
||||||
<AlertDialogHeader>
|
<AlertDialogHeader>
|
||||||
<AlertDialogTitle>
|
<AlertDialogTitle>
|
||||||
{t("classification.semanticSearch.reindexNow.confirmTitle")}
|
{t("enrichments.semanticSearch.reindexNow.confirmTitle")}
|
||||||
</AlertDialogTitle>
|
</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
<Trans ns="views/settings">
|
<Trans ns="views/settings">
|
||||||
classification.semanticSearch.reindexNow.confirmDesc
|
enrichments.semanticSearch.reindexNow.confirmDesc
|
||||||
</Trans>
|
</Trans>
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
@ -384,7 +384,7 @@ export default function ClassificationSettingsView({
|
|||||||
onClick={onReindex}
|
onClick={onReindex}
|
||||||
className={buttonVariants({ variant: "select" })}
|
className={buttonVariants({ variant: "select" })}
|
||||||
>
|
>
|
||||||
{t("classification.semanticSearch.reindexNow.confirmButton")}
|
{t("enrichments.semanticSearch.reindexNow.confirmButton")}
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
@ -394,11 +394,11 @@ export default function ClassificationSettingsView({
|
|||||||
<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">
|
||||||
{t("classification.faceRecognition.title")}
|
{t("enrichments.faceRecognition.title")}
|
||||||
</Heading>
|
</Heading>
|
||||||
<div className="max-w-6xl">
|
<div className="max-w-6xl">
|
||||||
<div className="mb-5 mt-2 flex max-w-5xl flex-col gap-2 text-sm text-primary-variant">
|
<div className="mb-5 mt-2 flex max-w-5xl flex-col gap-2 text-sm text-primary-variant">
|
||||||
<p>{t("classification.faceRecognition.desc")}</p>
|
<p>{t("enrichments.faceRecognition.desc")}</p>
|
||||||
|
|
||||||
<div className="flex items-center text-primary">
|
<div className="flex items-center text-primary">
|
||||||
<Link
|
<Link
|
||||||
@ -407,7 +407,7 @@ export default function ClassificationSettingsView({
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="inline"
|
className="inline"
|
||||||
>
|
>
|
||||||
{t("classification.faceRecognition.readTheDocumentation")}
|
{t("enrichments.faceRecognition.readTheDocumentation")}
|
||||||
<LuExternalLink className="ml-2 inline-flex size-3" />
|
<LuExternalLink className="ml-2 inline-flex size-3" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@ -419,10 +419,10 @@ export default function ClassificationSettingsView({
|
|||||||
<Switch
|
<Switch
|
||||||
id="enabled"
|
id="enabled"
|
||||||
className="mr-3"
|
className="mr-3"
|
||||||
disabled={classificationSettings.face.enabled === undefined}
|
disabled={enrichmentsSettings.face.enabled === undefined}
|
||||||
checked={classificationSettings.face.enabled === true}
|
checked={enrichmentsSettings.face.enabled === true}
|
||||||
onCheckedChange={(isChecked) => {
|
onCheckedChange={(isChecked) => {
|
||||||
handleClassificationConfigChange({
|
handleEnrichmentsConfigChange({
|
||||||
face: { enabled: isChecked },
|
face: { enabled: isChecked },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@ -435,32 +435,32 @@ export default function ClassificationSettingsView({
|
|||||||
</div>
|
</div>
|
||||||
<div className="space-y-0.5">
|
<div className="space-y-0.5">
|
||||||
<div className="text-md">
|
<div className="text-md">
|
||||||
{t("classification.faceRecognition.modelSize.label")}
|
{t("enrichments.faceRecognition.modelSize.label")}
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-1 text-sm text-muted-foreground">
|
<div className="space-y-1 text-sm text-muted-foreground">
|
||||||
<p>
|
<p>
|
||||||
<Trans ns="views/settings">
|
<Trans ns="views/settings">
|
||||||
classification.faceRecognition.modelSize.desc
|
enrichments.faceRecognition.modelSize.desc
|
||||||
</Trans>
|
</Trans>
|
||||||
</p>
|
</p>
|
||||||
<ul className="list-disc pl-5 text-sm">
|
<ul className="list-disc pl-5 text-sm">
|
||||||
<li>
|
<li>
|
||||||
<Trans ns="views/settings">
|
<Trans ns="views/settings">
|
||||||
classification.faceRecognition.modelSize.small.desc
|
enrichments.faceRecognition.modelSize.small.desc
|
||||||
</Trans>
|
</Trans>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<Trans ns="views/settings">
|
<Trans ns="views/settings">
|
||||||
classification.faceRecognition.modelSize.large.desc
|
enrichments.faceRecognition.modelSize.large.desc
|
||||||
</Trans>
|
</Trans>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<Select
|
||||||
value={classificationSettings.face.model_size}
|
value={enrichmentsSettings.face.model_size}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) =>
|
||||||
handleClassificationConfigChange({
|
handleEnrichmentsConfigChange({
|
||||||
face: {
|
face: {
|
||||||
model_size: value as SearchModelSize,
|
model_size: value as SearchModelSize,
|
||||||
},
|
},
|
||||||
@ -469,7 +469,7 @@ export default function ClassificationSettingsView({
|
|||||||
>
|
>
|
||||||
<SelectTrigger className="w-20">
|
<SelectTrigger className="w-20">
|
||||||
{t(
|
{t(
|
||||||
`classification.faceRecognition.modelSize.${classificationSettings.face.model_size}.title`,
|
`enrichments.faceRecognition.modelSize.${enrichmentsSettings.face.model_size}.title`,
|
||||||
)}
|
)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@ -481,7 +481,7 @@ export default function ClassificationSettingsView({
|
|||||||
value={size}
|
value={size}
|
||||||
>
|
>
|
||||||
{t(
|
{t(
|
||||||
"classification.faceRecognition.modelSize." +
|
"enrichments.faceRecognition.modelSize." +
|
||||||
size +
|
size +
|
||||||
".title",
|
".title",
|
||||||
)}
|
)}
|
||||||
@ -495,11 +495,11 @@ export default function ClassificationSettingsView({
|
|||||||
<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">
|
||||||
{t("classification.licensePlateRecognition.title")}
|
{t("enrichments.licensePlateRecognition.title")}
|
||||||
</Heading>
|
</Heading>
|
||||||
<div className="max-w-6xl">
|
<div className="max-w-6xl">
|
||||||
<div className="mb-5 mt-2 flex max-w-5xl flex-col gap-2 text-sm text-primary-variant">
|
<div className="mb-5 mt-2 flex max-w-5xl flex-col gap-2 text-sm text-primary-variant">
|
||||||
<p>{t("classification.licensePlateRecognition.desc")}</p>
|
<p>{t("enrichments.licensePlateRecognition.desc")}</p>
|
||||||
|
|
||||||
<div className="flex items-center text-primary">
|
<div className="flex items-center text-primary">
|
||||||
<Link
|
<Link
|
||||||
@ -509,7 +509,7 @@ export default function ClassificationSettingsView({
|
|||||||
className="inline"
|
className="inline"
|
||||||
>
|
>
|
||||||
{t(
|
{t(
|
||||||
"classification.licensePlateRecognition.readTheDocumentation",
|
"enrichments.licensePlateRecognition.readTheDocumentation",
|
||||||
)}
|
)}
|
||||||
<LuExternalLink className="ml-2 inline-flex size-3" />
|
<LuExternalLink className="ml-2 inline-flex size-3" />
|
||||||
</Link>
|
</Link>
|
||||||
@ -522,10 +522,10 @@ export default function ClassificationSettingsView({
|
|||||||
<Switch
|
<Switch
|
||||||
id="enabled"
|
id="enabled"
|
||||||
className="mr-3"
|
className="mr-3"
|
||||||
disabled={classificationSettings.lpr.enabled === undefined}
|
disabled={enrichmentsSettings.lpr.enabled === undefined}
|
||||||
checked={classificationSettings.lpr.enabled === true}
|
checked={enrichmentsSettings.lpr.enabled === true}
|
||||||
onCheckedChange={(isChecked) => {
|
onCheckedChange={(isChecked) => {
|
||||||
handleClassificationConfigChange({
|
handleEnrichmentsConfigChange({
|
||||||
lpr: { enabled: isChecked },
|
lpr: { enabled: isChecked },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@ -541,11 +541,11 @@ export default function ClassificationSettingsView({
|
|||||||
<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">
|
||||||
{t("classification.birdClassification.title")}
|
{t("enrichments.birdClassification.title")}
|
||||||
</Heading>
|
</Heading>
|
||||||
<div className="max-w-6xl">
|
<div className="max-w-6xl">
|
||||||
<div className="mb-5 mt-2 flex max-w-5xl flex-col gap-2 text-sm text-primary-variant">
|
<div className="mb-5 mt-2 flex max-w-5xl flex-col gap-2 text-sm text-primary-variant">
|
||||||
<p>{t("classification.birdClassification.desc")}</p>
|
<p>{t("enrichments.birdClassification.desc")}</p>
|
||||||
|
|
||||||
<div className="flex items-center text-primary">
|
<div className="flex items-center text-primary">
|
||||||
<Link
|
<Link
|
||||||
@ -554,7 +554,7 @@ export default function ClassificationSettingsView({
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="inline"
|
className="inline"
|
||||||
>
|
>
|
||||||
{t("classification.semanticSearch.readTheDocumentation")}
|
{t("enrichments.semanticSearch.readTheDocumentation")}
|
||||||
<LuExternalLink className="ml-2 inline-flex size-3" />
|
<LuExternalLink className="ml-2 inline-flex size-3" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
@ -566,10 +566,10 @@ export default function ClassificationSettingsView({
|
|||||||
<Switch
|
<Switch
|
||||||
id="enabled"
|
id="enabled"
|
||||||
className="mr-3"
|
className="mr-3"
|
||||||
disabled={classificationSettings.bird.enabled === undefined}
|
disabled={enrichmentsSettings.bird.enabled === undefined}
|
||||||
checked={classificationSettings.bird.enabled === true}
|
checked={enrichmentsSettings.bird.enabled === true}
|
||||||
onCheckedChange={(isChecked) => {
|
onCheckedChange={(isChecked) => {
|
||||||
handleClassificationConfigChange({
|
handleEnrichmentsConfigChange({
|
||||||
bird: { enabled: isChecked },
|
bird: { enabled: isChecked },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
Loading…
Reference in New Issue
Block a user