Add Label notifier

* Added new label notifier
This commit is contained in:
Craig 2025-08-03 14:02:54 +00:00
commit cb340c8a09
9 changed files with 129 additions and 6 deletions

View file

@ -79,7 +79,8 @@
"tag-events": "Tag Events",
"category-events": "Category Events",
"when-a-new-user-joins-your-group": "When a new user joins your group",
"recipe-events": "Recipe Events"
"recipe-events": "Recipe Events",
"label-events": "Label Events"
},
"general": {
"add": "Add",

View file

@ -71,6 +71,9 @@ export interface GroupEventNotifierOptions {
categoryCreated?: boolean;
categoryUpdated?: boolean;
categoryDeleted?: boolean;
labelCreated?: boolean;
labelUpdated?: boolean;
labelDeleted?: boolean;
}
export interface GroupEventNotifierOptionsOut {
testMessage?: boolean;
@ -95,6 +98,9 @@ export interface GroupEventNotifierOptionsOut {
categoryCreated?: boolean;
categoryUpdated?: boolean;
categoryDeleted?: boolean;
labelCreated?: boolean;
labelUpdated?: boolean;
labelDeleted?: boolean;
id: string;
}
export interface GroupEventNotifierOptionsSave {
@ -120,6 +126,9 @@ export interface GroupEventNotifierOptionsSave {
categoryCreated?: boolean;
categoryUpdated?: boolean;
categoryDeleted?: boolean;
labelCreated?: boolean;
labelUpdated?: boolean;
labelDeleted?: boolean;
notifierId: string;
}
export interface GroupEventNotifierOut {

View file

@ -368,6 +368,24 @@ export default defineNuxtComponent({
},
],
},
{
id: 8,
text: i18n.t("events.label-events"),
options: [
{
text: i18n.t("general.create") as string,
key: "labelCreated",
},
{
text: i18n.t("general.update") as string,
key: "labelUpdated",
},
{
text: i18n.t("general.delete") as string,
key: "labelDeleted",
},
],
},
];
return {

View file

@ -0,0 +1,48 @@
"""'Add label notifier CRUD bools'
Revision ID: e6bb583aac2d
Revises: 7cf3054cbbcc
Create Date: 2025-07-30 19:32:37.285172
"""
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = "e6bb583aac2d"
down_revision: str | None = "7cf3054cbbcc"
branch_labels: str | tuple[str, ...] | None = None
depends_on: str | tuple[str, ...] | None = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("group_events_notifier_options", schema=None) as batch_op:
batch_op.add_column(
sa.Column(
"label_created", sa.Boolean(), nullable=False, default=False, server_default=sa.sql.expression.false()
)
)
batch_op.add_column(
sa.Column(
"label_updated", sa.Boolean(), nullable=False, default=False, server_default=sa.sql.expression.false()
)
)
batch_op.add_column(
sa.Column(
"label_deleted", sa.Boolean(), nullable=False, default=False, server_default=sa.sql.expression.false()
)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("group_events_notifier_options", schema=None) as batch_op:
batch_op.drop_column("label_deleted")
batch_op.drop_column("label_updated")
batch_op.drop_column("label_created")
# ### end Alembic commands ###

View file

@ -46,6 +46,10 @@ class GroupEventNotifierOptionsModel(SqlAlchemyBase, BaseMixins):
category_updated: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
category_deleted: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
label_created: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
label_updated: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
label_deleted: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
@auto_init()
def __init__(self, **_) -> None:
pass

View file

@ -3,7 +3,7 @@ from functools import cached_property
from fastapi import APIRouter, Depends
from pydantic import UUID4
from mealie.routes._base.base_controllers import BaseUserController
from mealie.routes._base.base_controllers import BaseCrudController
from mealie.routes._base.controller import controller
from mealie.routes._base.mixins import HttpRepo
from mealie.routes._base.routers import MealieCrudRoute
@ -15,13 +15,14 @@ from mealie.schema.labels import (
)
from mealie.schema.labels.multi_purpose_label import MultiPurposeLabelPagination
from mealie.schema.response.pagination import PaginationQuery
from mealie.services.event_bus_service.event_types import EventLabelData, EventOperation, EventTypes
from mealie.services.group_services.labels_service import MultiPurposeLabelService
router = APIRouter(prefix="/groups/labels", tags=["Groups: Multi Purpose Labels"], route_class=MealieCrudRoute)
@controller(router)
class MultiPurposeLabelsController(BaseUserController):
class MultiPurposeLabelsController(BaseCrudController):
@cached_property
def service(self):
return MultiPurposeLabelService(self.repos)
@ -53,7 +54,15 @@ class MultiPurposeLabelsController(BaseUserController):
@router.post("", response_model=MultiPurposeLabelOut)
def create_one(self, data: MultiPurposeLabelCreate):
return self.service.create_one(data)
new_label = self.service.create_one(data)
self.publish_event(
event_type=EventTypes.label_created,
document_data=EventLabelData(operation=EventOperation.create, label_id=new_label.id),
group_id=new_label.group_id,
household_id=None,
message=self.t("notifications.generic-created", name=new_label.name),
)
return new_label
@router.get("/{item_id}", response_model=MultiPurposeLabelOut)
def get_one(self, item_id: UUID4):
@ -61,8 +70,25 @@ class MultiPurposeLabelsController(BaseUserController):
@router.put("/{item_id}", response_model=MultiPurposeLabelOut)
def update_one(self, item_id: UUID4, data: MultiPurposeLabelUpdate):
return self.mixins.update_one(data, item_id)
label = self.mixins.update_one(data, item_id)
self.publish_event(
event_type=EventTypes.label_updated,
document_data=EventLabelData(operation=EventOperation.update, label_id=label.id),
group_id=label.group_id,
household_id=None,
message=self.t("notifications.generic-updated", name=label.name),
)
return label
@router.delete("/{item_id}", response_model=MultiPurposeLabelOut)
def delete_one(self, item_id: UUID4):
return self.mixins.delete_one(item_id) # type: ignore
label = self.mixins.delete_one(item_id)
if label:
self.publish_event(
event_type=EventTypes.label_deleted,
document_data=EventLabelData(operation=EventOperation.delete, label_id=label.id),
group_id=label.group_id,
household_id=None,
message=self.t("notifications.generic-deleted", name=label.name),
)
return label

View file

@ -47,6 +47,10 @@ class GroupEventNotifierOptions(MealieModel):
category_updated: bool = False
category_deleted: bool = False
label_created: bool = False
label_updated: bool = False
label_deleted: bool = False
class GroupEventNotifierOptionsSave(GroupEventNotifierOptions):
notifier_id: UUID4

View file

@ -53,6 +53,10 @@ class EventTypes(Enum):
category_updated = auto()
category_deleted = auto()
label_created = auto()
label_updated = auto()
label_deleted = auto()
class EventDocumentType(Enum):
generic = "generic"
@ -68,6 +72,7 @@ class EventDocumentType(Enum):
recipe_bulk_report = "recipe_bulk_report"
recipe_timeline_event = "recipe_timeline_event"
tag = "tag"
label = "label"
class EventOperation(Enum):
@ -106,6 +111,11 @@ class EventCategoryData(EventDocumentDataBase):
category_id: UUID4
class EventLabelData(EventDocumentDataBase):
document_type: EventDocumentType = EventDocumentType.label
label_id: UUID4
class EventCookbookData(EventDocumentDataBase):
document_type: EventDocumentType = EventDocumentType.cookbook
cookbook_id: UUID4

View file

@ -38,6 +38,9 @@ def preferences_generator():
category_created=random_bool(),
category_updated=random_bool(),
category_deleted=random_bool(),
label_created=random_bool(),
label_updated=random_bool(),
label_deleted=random_bool(),
).model_dump(by_alias=True)