diff --git a/web/public/locales/en/common.json b/web/public/locales/en/common.json
index 4771d4945..48e46f5e5 100644
--- a/web/public/locales/en/common.json
+++ b/web/public/locales/en/common.json
@@ -153,7 +153,8 @@
"continue": "Continue",
"modified": "Modified",
"overridden": "Overridden",
- "resetToGlobal": "Reset to Global"
+ "resetToGlobal": "Reset to Global",
+ "resetToDefault": "Reset to Default"
},
"menu": {
"system": "System",
diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json
index 639d1a322..45c331db5 100644
--- a/web/public/locales/en/views/settings.json
+++ b/web/public/locales/en/views/settings.json
@@ -114,7 +114,7 @@
"desc": "Semantic Search in Frigate allows you to find tracked objects within your review items using either the image itself, a user-defined text description, or an automatically generated one.",
"reindexNow": {
"label": "Reindex Now",
- "desc": "Reindexing will regenerate embeddings for all tracked object. This process runs in the background and may max out your CPU and take a fair amount of time depending on the number of tracked objects you have.",
+ "desc": "Reindexing will regenerate embeddings for all tracked objects. This process runs in the background and may max out your CPU and take a fair amount of time depending on the number of tracked objects you have.",
"confirmTitle": "Confirm Reindexing",
"confirmDesc": "Are you sure you want to reindex all tracked object embeddings? This process will run in the background but it may max out your CPU and take a fair amount of time. You can watch the progress on the Explore page.",
"confirmButton": "Reindex",
diff --git a/web/src/components/config-form/sectionConfigs.ts b/web/src/components/config-form/sectionConfigs.ts
index 1c9e87f69..e482089b0 100644
--- a/web/src/components/config-form/sectionConfigs.ts
+++ b/web/src/components/config-form/sectionConfigs.ts
@@ -604,6 +604,11 @@ const sectionConfigs: Record = {
hiddenFields: [],
advancedFields: [],
overrideFields: [],
+ uiSchema: {
+ enabled: {
+ "ui:after": { render: "SemanticSearchReindex" },
+ },
+ },
},
global: {
fieldOrder: ["enabled", "reindex", "model", "model_size", "device"],
diff --git a/web/src/components/config-form/sectionExtras/SemanticSearchReindex.tsx b/web/src/components/config-form/sectionExtras/SemanticSearchReindex.tsx
new file mode 100644
index 000000000..f44bcd8e1
--- /dev/null
+++ b/web/src/components/config-form/sectionExtras/SemanticSearchReindex.tsx
@@ -0,0 +1,106 @@
+import { useState } from "react";
+import axios from "axios";
+import { Button, buttonVariants } from "@/components/ui/button";
+import { Trans, useTranslation } from "react-i18next";
+import { toast } from "sonner";
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+} from "@/components/ui/alert-dialog";
+
+export default function SemanticSearchReindex() {
+ const { t } = useTranslation("views/settings");
+ const [isLoading, setIsLoading] = useState(false);
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
+
+ const onReindex = async () => {
+ setIsLoading(true);
+ try {
+ const res = await axios.put("/reindex");
+ if (res.status === 202) {
+ toast.success(t("enrichments.semanticSearch.reindexNow.success"), {
+ position: "top-center",
+ });
+ } else {
+ toast.error(
+ t("enrichments.semanticSearch.reindexNow.error", {
+ errorMessage: res.statusText,
+ }),
+ { position: "top-center" },
+ );
+ }
+ } catch (caught) {
+ const error = caught as {
+ response?: { data?: { message?: string; detail?: string } };
+ };
+ const errorMessage =
+ error.response?.data?.message || error.response?.data?.detail || "";
+ toast.error(
+ t("enrichments.semanticSearch.reindexNow.error", {
+ errorMessage: errorMessage || undefined,
+ }),
+ { position: "top-center" },
+ );
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ return (
+ <>
+