mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-04 06:53:12 -05:00
Feature/group based notifications (#918)
* fix group page * setup group notification for backend * update type generators * script to auto-generate schema exports * setup frontend CRUD interface * remove old notifications UI * drop old events api * add test functionality * update naming for fields * add event dispatcher functionality * bump to python 3.10 * bump python version * purge old event code * use-async apprise * set mealie logo as image * unify styles for buttons rows * add links to banners
This commit is contained in:
@@ -8,7 +8,7 @@ from mealie.services.group_services import CookbookService, WebhookService
|
||||
from mealie.services.group_services.meal_service import MealService
|
||||
from mealie.services.group_services.reports_service import GroupReportService
|
||||
|
||||
from . import categories, invitations, labels, migrations, preferences, self_service, shopping_lists
|
||||
from . import categories, invitations, labels, migrations, notifications, preferences, self_service, shopping_lists
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -56,3 +56,4 @@ def get_all_reports(
|
||||
router.include_router(report_router)
|
||||
router.include_router(shopping_lists.router)
|
||||
router.include_router(labels.router)
|
||||
router.include_router(notifications.router)
|
||||
|
||||
85
mealie/routes/groups/notifications.py
Normal file
85
mealie/routes/groups/notifications.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from functools import cached_property
|
||||
from sqlite3 import IntegrityError
|
||||
from typing import Type
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.routes._base.controller import controller
|
||||
from mealie.routes._base.dependencies import SharedDependencies
|
||||
from mealie.routes._base.mixins import CrudMixins
|
||||
from mealie.schema.group.group_events import (
|
||||
GroupEventNotifierCreate,
|
||||
GroupEventNotifierOut,
|
||||
GroupEventNotifierPrivate,
|
||||
GroupEventNotifierSave,
|
||||
GroupEventNotifierUpdate,
|
||||
)
|
||||
from mealie.schema.mapper import cast
|
||||
from mealie.schema.query import GetAll
|
||||
from mealie.services.event_bus_service.event_bus_service import EventBusService
|
||||
|
||||
router = APIRouter(prefix="/groups/events/notifications", tags=["Group: Event Notifications"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupEventsNotifierController:
|
||||
deps: SharedDependencies = Depends(SharedDependencies.user)
|
||||
event_bus: EventBusService = Depends(EventBusService)
|
||||
|
||||
@cached_property
|
||||
def repo(self):
|
||||
if not self.deps.acting_user:
|
||||
raise Exception("No user is logged in.")
|
||||
|
||||
return self.deps.repos.group_event_notifier.by_group(self.deps.acting_user.group_id)
|
||||
|
||||
def registered_exceptions(self, ex: Type[Exception]) -> str:
|
||||
registered = {
|
||||
Exception: "An unexpected error occurred.",
|
||||
IntegrityError: "An unexpected error occurred.",
|
||||
}
|
||||
|
||||
return registered.get(ex, "An unexpected error occurred.")
|
||||
|
||||
# =======================================================================
|
||||
# CRUD Operations
|
||||
|
||||
@property
|
||||
def mixins(self) -> CrudMixins:
|
||||
return CrudMixins(self.repo, self.deps.logger, self.registered_exceptions, "An unexpected error occurred.")
|
||||
|
||||
@router.get("", response_model=list[GroupEventNotifierOut])
|
||||
def get_all(self, q: GetAll = Depends(GetAll)):
|
||||
return self.repo.get_all(start=q.start, limit=q.limit)
|
||||
|
||||
@router.post("", response_model=GroupEventNotifierOut, status_code=201)
|
||||
def create_one(self, data: GroupEventNotifierCreate):
|
||||
save_data = cast(data, GroupEventNotifierSave, group_id=self.deps.acting_user.group_id)
|
||||
return self.mixins.create_one(save_data)
|
||||
|
||||
@router.get("/{item_id}", response_model=GroupEventNotifierOut)
|
||||
def get_one(self, item_id: UUID4):
|
||||
return self.mixins.get_one(item_id)
|
||||
|
||||
@router.put("/{item_id}", response_model=GroupEventNotifierOut)
|
||||
def update_one(self, item_id: UUID4, data: GroupEventNotifierUpdate):
|
||||
if data.apprise_url is None:
|
||||
current_data: GroupEventNotifierPrivate = self.repo.get_one(
|
||||
item_id, override_schema=GroupEventNotifierPrivate
|
||||
)
|
||||
data.apprise_url = current_data.apprise_url
|
||||
|
||||
return self.mixins.update_one(data, item_id)
|
||||
|
||||
@router.delete("/{item_id}", status_code=204)
|
||||
def delete_one(self, item_id: UUID4):
|
||||
self.mixins.delete_one(item_id) # type: ignore
|
||||
|
||||
# =======================================================================
|
||||
# Test Event Notifications
|
||||
|
||||
@router.post("/{item_id}/test", status_code=204)
|
||||
def test_notification(self, item_id: UUID4):
|
||||
item: GroupEventNotifierPrivate = self.repo.get_one(item_id, override_schema=GroupEventNotifierPrivate)
|
||||
self.event_bus.test_publisher(item.apprise_url)
|
||||
@@ -17,6 +17,8 @@ from mealie.schema.group.group_shopping_list import (
|
||||
)
|
||||
from mealie.schema.mapper import cast
|
||||
from mealie.schema.query import GetAll
|
||||
from mealie.services.event_bus_service.event_bus_service import EventBusService
|
||||
from mealie.services.event_bus_service.message_types import EventTypes
|
||||
from mealie.services.group_services.shopping_lists import ShoppingListService
|
||||
|
||||
router = APIRouter(prefix="/groups/shopping/lists", tags=["Group: Shopping Lists"])
|
||||
@@ -26,6 +28,7 @@ router = APIRouter(prefix="/groups/shopping/lists", tags=["Group: Shopping Lists
|
||||
class ShoppingListRoutes:
|
||||
deps: SharedDependencies = Depends(SharedDependencies.user)
|
||||
service: ShoppingListService = Depends(ShoppingListService.private)
|
||||
event_bus: EventBusService = Depends(EventBusService)
|
||||
|
||||
@cached_property
|
||||
def repo(self):
|
||||
@@ -56,7 +59,16 @@ class ShoppingListRoutes:
|
||||
@router.post("", response_model=ShoppingListOut)
|
||||
def create_one(self, data: ShoppingListCreate):
|
||||
save_data = cast(data, ShoppingListSave, group_id=self.deps.acting_user.group_id)
|
||||
return self.mixins.create_one(save_data)
|
||||
val = self.mixins.create_one(save_data)
|
||||
|
||||
if val:
|
||||
self.event_bus.dispatch(
|
||||
self.deps.acting_user.group_id,
|
||||
EventTypes.shopping_list_created,
|
||||
msg="A new shopping list has been created.",
|
||||
)
|
||||
|
||||
return val
|
||||
|
||||
@router.get("/{item_id}", response_model=ShoppingListOut)
|
||||
def get_one(self, item_id: UUID4):
|
||||
|
||||
Reference in New Issue
Block a user