diff --git a/frontend/src/api/about.js b/frontend/src/api/about.js
index 211e63169..1cfa13f23 100644
--- a/frontend/src/api/about.js
+++ b/frontend/src/api/about.js
@@ -1,5 +1,6 @@
import { baseURL } from "./api-utils";
import { apiReq } from "./api-utils";
+import i18n from "@/i18n.js";
const prefix = baseURL + "about";
@@ -47,11 +48,21 @@ export const aboutAPI = {
return response.data;
},
async testNotificationByID(id) {
- const response = await apiReq.post(aboutURLs.testNotifications, { id: id });
+ const response = await apiReq.post(
+ aboutURLs.testNotifications,
+ { id: id },
+ () => i18n.t("events.something-went-wrong"),
+ () => i18n.t("events.test-message-sent")
+ );
return response.data;
},
async testNotificationByURL(url) {
- const response = await apiReq.post(aboutURLs.testNotifications, { test_url: url });
+ const response = await apiReq.post(
+ aboutURLs.testNotifications,
+ { test_url: url },
+ () => i18n.t("events.something-went-wrong"),
+ () => i18n.t("events.test-message-sent")
+ );
return response.data;
},
// async getAppInfo() {
diff --git a/frontend/src/api/users.js b/frontend/src/api/users.js
index 1ded3c6e9..68e42c4ae 100644
--- a/frontend/src/api/users.js
+++ b/frontend/src/api/users.js
@@ -71,7 +71,7 @@ export const userAPI = {
},
delete(id) {
- return apiReq.delete(usersURLs.userID(id), null, deleteErrorText, function() {
+ return apiReq.delete(usersURLs.userID(id), null, deleteErrorText, () => {
return i18n.t("user.user-deleted");
});
},
diff --git a/frontend/src/components/UI/Dialogs/BaseDialog.vue b/frontend/src/components/UI/Dialogs/BaseDialog.vue
index e4a80296e..e83d4d584 100644
--- a/frontend/src/components/UI/Dialogs/BaseDialog.vue
+++ b/frontend/src/components/UI/Dialogs/BaseDialog.vue
@@ -2,7 +2,7 @@
-
+
{{ titleIcon }}
@@ -11,7 +11,9 @@
-
+
+
+
@@ -22,13 +24,15 @@
{{ $t("general.delete") }}
-
+
{{ submitText }}
-
+
+
+
@@ -59,6 +63,9 @@ export default {
submitText: {
default: () => i18n.t("general.create"),
},
+ keepOpen: {
+ default: false,
+ },
},
data() {
return {
@@ -68,7 +75,7 @@ export default {
},
computed: {
determineClose() {
- return this.submitted && !this.loading;
+ return this.submitted && !this.loading && !this.keepOpen;
},
},
watch: {
@@ -82,6 +89,7 @@ export default {
},
methods: {
submitEvent() {
+ console.log("Submit");
this.$emit("submit");
this.submitted = true;
},
diff --git a/frontend/src/components/UI/GlobalSnackbar.vue b/frontend/src/components/UI/GlobalSnackbar.vue
index 437d20a46..777c82b2f 100644
--- a/frontend/src/components/UI/GlobalSnackbar.vue
+++ b/frontend/src/components/UI/GlobalSnackbar.vue
@@ -1,6 +1,10 @@
+
+ {{ icon }}
+
+
{{ snackbar.title }}
{{ snackbar.text }}
@@ -25,6 +29,18 @@ export default {
return this.$store.getters.getSnackbar;
},
},
+ icon() {
+ switch (this.snackbar.color) {
+ case "error":
+ return "mdi-alert";
+ case "success":
+ return "mdi-checkbox-marked-circle";
+ case "info":
+ return "mdi-information";
+ default:
+ return "mdi-bell-alert";
+ }
+ },
},
};
\ No newline at end of file
diff --git a/frontend/src/locales/messages/en-US.json b/frontend/src/locales/messages/en-US.json
index 7330f3846..b20d79950 100644
--- a/frontend/src/locales/messages/en-US.json
+++ b/frontend/src/locales/messages/en-US.json
@@ -31,6 +31,16 @@
"category-updated": "Category updated",
"uncategorized-count": "Uncategorized {count}"
},
+ "events": {
+ "notification": "Notification",
+ "apprise-url": "Apprise URL",
+ "subscribed-events": "Subscribed Events",
+ "scheduled": "Scheduled",
+ "database": "Database",
+ "test-message-sent": "Test Message Sent",
+ "something-went-wrong": "Something Went Wrong!",
+ "new-notification-form-description": "Mealie uses the Apprise library to generate notifications. They offer many options for services to use for notifications. Refer to their wiki for a comprehensive guide on how to create the URL for your service. If available, selecting the type of your notification may include extra features."
+ },
"general": {
"apply": "Apply",
"cancel": "Cancel",
@@ -55,6 +65,7 @@
"file-uploaded": "File uploaded",
"filter": "Filter",
"friday": "Friday",
+ "general": "General",
"get": "Get",
"image": "Image",
"image-upload-failed": "Image upload failed",
@@ -70,6 +81,7 @@
"random": "Random",
"rating": "Rating",
"recent": "Recent",
+ "recipe": "Recipe",
"recipes": "Recipes",
"rename-object": "Rename {0}",
"reset": "Reset",
@@ -88,6 +100,8 @@
"thursday": "Thursday",
"token": "Token",
"tuesday": "Tuesday",
+ "type": "Type",
+ "test": "Test",
"update": "Update",
"updated": "Updated",
"upload": "Upload",
diff --git a/frontend/src/pages/Admin/ToolBox/CategoryTagEditor/BulkAssign.vue b/frontend/src/pages/Admin/ToolBox/CategoryTagEditor/BulkAssign.vue
index bcee4e3c8..809adc0b8 100644
--- a/frontend/src/pages/Admin/ToolBox/CategoryTagEditor/BulkAssign.vue
+++ b/frontend/src/pages/Admin/ToolBox/CategoryTagEditor/BulkAssign.vue
@@ -1,6 +1,6 @@
-
-
+
{{ $t("settings.toolbox.bulk-assign") }}
diff --git a/frontend/src/pages/Admin/ToolBox/EventNotification.vue b/frontend/src/pages/Admin/ToolBox/EventNotification.vue
new file mode 100644
index 000000000..8965ab85a
--- /dev/null
+++ b/frontend/src/pages/Admin/ToolBox/EventNotification.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+
+
+
+
+ mdi-plus
+
+ {{ $t("events.notification") }}
+
+
+
+
+ {{ $t("events.new-notification-form-description") }}
+
+
+
+
+
+
+
+
+
+
+
+ mdi-test-tube
+ {{ $t("general.test") }}
+
+
+ {{ $t("events.subscribed-events") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t("general.type") }}
+ |
+
+ {{ $t("general.name") }}
+ |
+
+ {{ $t("general.general") }}
+ |
+
+ {{ $t("general.recipe") }}
+ |
+
+ {{ $t("events.database") }}
+ |
+
+ {{ $t("events.scheduled") }}
+ |
+
+ {{ $t("settings.migrations") }}
+ |
+
+ {{ $t("group.group") }}
+ |
+
+ {{ $t("user.user") }}
+ |
+
+
+
+
+
+
+ {{ getIcon(item.type).icon }}
+
+
+ {{ item.type }}
+ |
+
+ {{ item.name }}
+ |
+
+ {{ item.general ? "mdi-check" : "" }}
+ |
+
+ {{ item.recipe ? "mdi-check" : "" }}
+ |
+
+ {{ item.backup ? "mdi-check" : "" }}
+ |
+
+ {{ item.scheduled ? "mdi-check" : "" }}
+ |
+
+ {{ item.migration ? "mdi-check" : "" }}
+ |
+
+ {{ item.group ? "mdi-check" : "" }}
+ |
+
+ {{ item.user ? "mdi-check" : "" }}
+ |
+
+
+ mdi-delete
+ {{ $t("general.delete") }}
+
+
+ mdi-test-tube
+ {{ $t("general.test") }}
+
+ |
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/pages/Admin/ToolBox/EventNotification/index.vue b/frontend/src/pages/Admin/ToolBox/EventNotification/index.vue
deleted file mode 100644
index c12d30f5c..000000000
--- a/frontend/src/pages/Admin/ToolBox/EventNotification/index.vue
+++ /dev/null
@@ -1,221 +0,0 @@
-
-
-
-
-
-
-
-
-
- mdi-plus
-
- Notification
-
-
-
- We use the Apprise library to
- generate notifications. They offer many options for services to use for notifications. Refer to their wiki
- for a comprehensive guide on how to create the URL for your service. If available, selecting the type of
- your notification can include extra features Here are some common choices.
-
-
-
-
-
-
-
-
-
- mdi-test-tube
- Test
-
-
- Select the events you would like to recieve notifications for on this URL
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Type
- |
-
- Name
- |
-
- General
- |
-
- Recipe
- |
-
- Backup
- |
-
- Scheduled
- |
-
- Migration
- |
-
- Group
- |
-
- User
- |
-
-
-
-
-
-
- {{ getIcon(item.type).icon }}
-
-
- {{ item.type }}
- |
-
- {{ item.name }}
- |
-
- {{ item.general ? "mdi-check" : "" }}
- |
-
- {{ item.recipe ? "mdi-check" : "" }}
- |
-
- {{ item.backup ? "mdi-check" : "" }}
- |
-
- {{ item.scheduled ? "mdi-check" : "" }}
- |
-
- {{ item.migration ? "mdi-check" : "" }}
- |
-
- {{ item.group ? "mdi-check" : "" }}
- |
-
- {{ item.user ? "mdi-check" : "" }}
- |
-
-
- mdi-delete
- Delete
-
-
- mdi-test-tube
- Test
-
- |
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/mealie/routes/about/events.py b/mealie/routes/about/events.py
index c61dda2c6..4f6405253 100644
--- a/mealie/routes/about/events.py
+++ b/mealie/routes/about/events.py
@@ -6,9 +6,9 @@ from mealie.db.database import db
from mealie.db.db_setup import generate_session
from mealie.routes.deps import get_current_user
from mealie.schema.event_notifications import EventNotificationIn, EventNotificationOut
-from mealie.schema.events import Event, EventCategory, EventsOut, TestEvent
+from mealie.schema.events import EventsOut, TestEvent
from mealie.schema.user import UserInDB
-from mealie.services.events import post_notifications
+from mealie.services.events import test_notification
from sqlalchemy.orm.session import Session
router = APIRouter(prefix="/events", tags=["App Events"])
@@ -52,7 +52,7 @@ async def create_event_notification(
@router.post("/notifications/test")
-async def test_notification(
+async def test_notification_route(
test_data: TestEvent,
session: Session = Depends(generate_session),
current_user: UserInDB = Depends(get_current_user),
@@ -60,17 +60,11 @@ async def test_notification(
""" Create event_notification in the Database """
if test_data.id:
- print("TEST ID")
event_obj: EventNotificationIn = db.event_notifications.get(session, test_data.id)
test_data.test_url = event_obj.notification_url
- test_event = Event(
- title="Test Notification",
- text="This is a test message from the Mealie API server",
- category=EventCategory.general.value,
- )
try:
- post_notifications(test_event, [test_data.test_url])
+ test_notification(test_data.test_url)
except Exception as e:
logger.error(e)
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)
diff --git a/mealie/schema/event_notifications.py b/mealie/schema/event_notifications.py
index 097188ff3..ea3ad424c 100644
--- a/mealie/schema/event_notifications.py
+++ b/mealie/schema/event_notifications.py
@@ -8,6 +8,8 @@ class DeclaredTypes(str, Enum):
general = "General"
discord = "Discord"
gotify = "Gotify"
+ pushover = "Pushover"
+ home_assistant = "Home Assistant"
class EventNotificationOut(CamelModel):
diff --git a/mealie/services/events.py b/mealie/services/events.py
index 1a68cde06..3ac042ecd 100644
--- a/mealie/services/events.py
+++ b/mealie/services/events.py
@@ -5,12 +5,27 @@ from mealie.schema.events import Event, EventCategory
from sqlalchemy.orm.session import Session
-def post_notifications(event: Event, notification_urls=list[str]):
+def test_notification(notification_url, event=None) -> bool:
+
+ if event is None:
+ event = Event(
+ title="Test Notification",
+ text="This is a test message from the Mealie API server",
+ category=EventCategory.general.value,
+ )
+
+ post_notifications(event, [notification_url], hard_fail=True)
+
+
+def post_notifications(event: Event, notification_urls=list[str], hard_fail=False):
asset = apprise.AppriseAsset(async_mode=False)
apobj = apprise.Apprise(asset=asset)
for dest in notification_urls:
- apobj.add(dest)
+ status = apobj.add(dest)
+
+ if not status and hard_fail:
+ raise Exception("Apprise URL Add Failed")
apobj.notify(
body=event.text,