Semantic Search Triggers (#18969)

* semantic trigger test

* database and model

* config

* embeddings maintainer and trigger post-processor

* api to create, edit, delete triggers

* frontend and i18n keys

* use thumbnail and description for trigger types

* image picker tweaks

* initial sync

* thumbnail file management

* clean up logs and use saved thumbnail on frontend

* publish mqtt messages

* webpush changes to enable trigger notifications

* add enabled switch

* add triggers from explore

* renaming and deletion fixes

* fix typing

* UI updates and add last triggering event time and link

* log exception instead of return in endpoint

* highlight entry in UI when triggered

* save and delete thumbnails directly

* remove alert action for now and add descriptions

* tweaks

* clean up

* fix types

* docs

* docs tweaks

* docs

* reuse enum
This commit is contained in:
Josh Hawkins
2025-08-16 10:20:33 -05:00
committed by Blake Blackshear
parent 28f816b49a
commit 3609b41217
37 changed files with 2736 additions and 62 deletions
+1
View File
@@ -480,6 +480,7 @@ function LibrarySelector({
</Button>
<Button
variant="destructive"
className="text-white"
onClick={() => {
if (confirmDelete) {
handleDeleteFace(confirmDelete);
+13 -4
View File
@@ -45,6 +45,7 @@ import { isInIframe } from "@/utils/isIFrame";
import { isPWA } from "@/utils/isPWA";
import { useIsAdmin } from "@/hooks/use-is-admin";
import { useTranslation } from "react-i18next";
import TriggerView from "@/views/settings/TriggerView";
const allSettingsViews = [
"ui",
@@ -52,6 +53,7 @@ const allSettingsViews = [
"cameras",
"masksAndZones",
"motionTuner",
"triggers",
"debug",
"users",
"notifications",
@@ -171,7 +173,7 @@ export default function Settings() {
}
}
// don't clear url params if we're creating a new object mask
return !searchParams.has("object_mask");
return !(searchParams.has("object_mask") || searchParams.has("event_id"));
});
useSearchEffect("camera", (camera: string) => {
@@ -179,8 +181,8 @@ export default function Settings() {
if (cameraNames.includes(camera)) {
setSelectedCamera(camera);
}
// don't clear url params if we're creating a new object mask
return !searchParams.has("object_mask");
// don't clear url params if we're creating a new object mask or trigger
return !(searchParams.has("object_mask") || searchParams.has("event_id"));
});
useEffect(() => {
@@ -229,7 +231,8 @@ export default function Settings() {
{(page == "debug" ||
page == "cameras" ||
page == "masksAndZones" ||
page == "motionTuner") && (
page == "motionTuner" ||
page == "triggers") && (
<div className="ml-2 flex flex-shrink-0 items-center gap-2">
{page == "masksAndZones" && (
<ZoneMaskFilterButton
@@ -274,6 +277,12 @@ export default function Settings() {
setUnsavedChanges={setUnsavedChanges}
/>
)}
{page === "triggers" && (
<TriggerView
selectedCamera={selectedCamera}
setUnsavedChanges={setUnsavedChanges}
/>
)}
{page == "users" && <AuthenticationView />}
{page == "notifications" && (
<NotificationView setUnsavedChanges={setUnsavedChanges} />