mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-01-09 10:31:20 -05:00
feat: Recipe Actions (#3448)
Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com> Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
This commit is contained in:
@@ -5,6 +5,7 @@ from .group import *
|
||||
from .invite_tokens import *
|
||||
from .mealplan import *
|
||||
from .preferences import *
|
||||
from .recipe_action import *
|
||||
from .report import *
|
||||
from .shopping_list import *
|
||||
from .webhooks import *
|
||||
|
||||
@@ -25,6 +25,7 @@ if TYPE_CHECKING:
|
||||
from ..users import User
|
||||
from .events import GroupEventNotifierModel
|
||||
from .exports import GroupDataExportsModel
|
||||
from .recipe_action import GroupRecipeAction
|
||||
from .report import ReportModel
|
||||
from .shopping_list import ShoppingList
|
||||
|
||||
@@ -64,6 +65,7 @@ class Group(SqlAlchemyBase, BaseMixins):
|
||||
GroupMealPlan, order_by="GroupMealPlan.date", **common_args
|
||||
)
|
||||
webhooks: Mapped[list[GroupWebhooksModel]] = orm.relationship(GroupWebhooksModel, **common_args)
|
||||
recipe_actions: Mapped[list["GroupRecipeAction"]] = orm.relationship("GroupRecipeAction", **common_args)
|
||||
cookbooks: Mapped[list[CookBook]] = orm.relationship(CookBook, **common_args)
|
||||
server_tasks: Mapped[list[ServerTaskModel]] = orm.relationship(ServerTaskModel, **common_args)
|
||||
data_exports: Mapped[list["GroupDataExportsModel"]] = orm.relationship("GroupDataExportsModel", **common_args)
|
||||
@@ -82,6 +84,7 @@ class Group(SqlAlchemyBase, BaseMixins):
|
||||
exclude={
|
||||
"users",
|
||||
"webhooks",
|
||||
"recipe_actions",
|
||||
"shopping_lists",
|
||||
"cookbooks",
|
||||
"preferences",
|
||||
|
||||
25
mealie/db/models/group/recipe_action.py
Normal file
25
mealie/db/models/group/recipe_action.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import ForeignKey, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from .._model_base import BaseMixins, SqlAlchemyBase
|
||||
from .._model_utils import GUID, auto_init
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from group import Group
|
||||
|
||||
|
||||
class GroupRecipeAction(SqlAlchemyBase, BaseMixins):
|
||||
__tablename__ = "recipe_actions"
|
||||
id: Mapped[GUID] = mapped_column(GUID, primary_key=True, default=GUID.generate)
|
||||
group_id: Mapped[GUID] = mapped_column(GUID, ForeignKey("groups.id"), index=True)
|
||||
group: Mapped["Group"] = relationship("Group", back_populates="recipe_actions", single_parent=True)
|
||||
|
||||
action_type: Mapped[str] = mapped_column(String, index=True)
|
||||
title: Mapped[str] = mapped_column(String, index=True)
|
||||
url: Mapped[str] = mapped_column(String)
|
||||
|
||||
@auto_init()
|
||||
def __init__(self, **_) -> None:
|
||||
pass
|
||||
@@ -11,6 +11,7 @@ from mealie.db.models.group.exports import GroupDataExportsModel
|
||||
from mealie.db.models.group.invite_tokens import GroupInviteToken
|
||||
from mealie.db.models.group.mealplan import GroupMealPlanRules
|
||||
from mealie.db.models.group.preferences import GroupPreferencesModel
|
||||
from mealie.db.models.group.recipe_action import GroupRecipeAction
|
||||
from mealie.db.models.group.shopping_list import (
|
||||
ShoppingList,
|
||||
ShoppingListItem,
|
||||
@@ -39,6 +40,7 @@ from mealie.schema.cookbook.cookbook import ReadCookBook
|
||||
from mealie.schema.group.group_events import GroupEventNotifierOut
|
||||
from mealie.schema.group.group_exports import GroupDataExport
|
||||
from mealie.schema.group.group_preferences import ReadGroupPreferences
|
||||
from mealie.schema.group.group_recipe_action import GroupRecipeActionOut
|
||||
from mealie.schema.group.group_shopping_list import (
|
||||
ShoppingListItemOut,
|
||||
ShoppingListItemRecipeRefOut,
|
||||
@@ -192,6 +194,10 @@ class AllRepositories:
|
||||
def cookbooks(self) -> RepositoryGeneric[ReadCookBook, CookBook]:
|
||||
return RepositoryGeneric(self.session, PK_ID, CookBook, ReadCookBook)
|
||||
|
||||
@cached_property
|
||||
def group_recipe_actions(self) -> RepositoryGeneric[GroupRecipeActionOut, GroupRecipeAction]:
|
||||
return RepositoryGeneric(self.session, PK_ID, GroupRecipeAction, GroupRecipeActionOut)
|
||||
|
||||
# ================================================================
|
||||
# Meal Plan
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ from fastapi import APIRouter
|
||||
from . import (
|
||||
controller_cookbooks,
|
||||
controller_group_notifications,
|
||||
controller_group_recipe_actions,
|
||||
controller_group_reports,
|
||||
controller_group_self_service,
|
||||
controller_invitations,
|
||||
@@ -31,4 +32,5 @@ router.include_router(controller_shopping_lists.router)
|
||||
router.include_router(controller_shopping_lists.item_router)
|
||||
router.include_router(controller_labels.router)
|
||||
router.include_router(controller_group_notifications.router)
|
||||
router.include_router(controller_group_recipe_actions.router)
|
||||
router.include_router(controller_seeder.router)
|
||||
|
||||
55
mealie/routes/groups/controller_group_recipe_actions.py
Normal file
55
mealie/routes/groups/controller_group_recipe_actions.py
Normal file
@@ -0,0 +1,55 @@
|
||||
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.controller import controller
|
||||
from mealie.routes._base.mixins import HttpRepo
|
||||
from mealie.schema.group.group_recipe_action import (
|
||||
CreateGroupRecipeAction,
|
||||
GroupRecipeActionOut,
|
||||
GroupRecipeActionPagination,
|
||||
SaveGroupRecipeAction,
|
||||
)
|
||||
from mealie.schema.response.pagination import PaginationQuery
|
||||
|
||||
router = APIRouter(prefix="/groups/recipe-actions", tags=["Groups: Recipe Actions"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class GroupRecipeActionController(BaseUserController):
|
||||
@cached_property
|
||||
def repo(self):
|
||||
return self.repos.group_recipe_actions.by_group(self.group_id)
|
||||
|
||||
@property
|
||||
def mixins(self):
|
||||
return HttpRepo[CreateGroupRecipeAction, GroupRecipeActionOut, SaveGroupRecipeAction](self.repo, self.logger)
|
||||
|
||||
@router.get("", response_model=GroupRecipeActionPagination)
|
||||
def get_all(self, q: PaginationQuery = Depends(PaginationQuery)):
|
||||
response = self.repo.page_all(
|
||||
pagination=q,
|
||||
override=GroupRecipeActionOut,
|
||||
)
|
||||
|
||||
response.set_pagination_guides(router.url_path_for("get_all"), q.model_dump())
|
||||
return response
|
||||
|
||||
@router.post("", response_model=GroupRecipeActionOut, status_code=201)
|
||||
def create_one(self, data: CreateGroupRecipeAction):
|
||||
save = data.cast(SaveGroupRecipeAction, group_id=self.group.id)
|
||||
return self.mixins.create_one(save)
|
||||
|
||||
@router.get("/{item_id}", response_model=GroupRecipeActionOut)
|
||||
def get_one(self, item_id: UUID4):
|
||||
return self.mixins.get_one(item_id)
|
||||
|
||||
@router.put("/{item_id}", response_model=GroupRecipeActionOut)
|
||||
def update_one(self, item_id: UUID4, data: SaveGroupRecipeAction):
|
||||
return self.mixins.update_one(data, item_id)
|
||||
|
||||
@router.delete("/{item_id}", response_model=GroupRecipeActionOut)
|
||||
def delete_one(self, item_id: UUID4):
|
||||
return self.mixins.delete_one(item_id)
|
||||
@@ -14,7 +14,18 @@ from .group_events import (
|
||||
from .group_exports import GroupDataExport
|
||||
from .group_migration import DataMigrationCreate, SupportedMigrations
|
||||
from .group_permissions import SetPermissions
|
||||
from .group_preferences import CreateGroupPreferences, ReadGroupPreferences, UpdateGroupPreferences
|
||||
from .group_preferences import (
|
||||
CreateGroupPreferences,
|
||||
ReadGroupPreferences,
|
||||
UpdateGroupPreferences,
|
||||
)
|
||||
from .group_recipe_action import (
|
||||
CreateGroupRecipeAction,
|
||||
GroupRecipeActionOut,
|
||||
GroupRecipeActionPagination,
|
||||
GroupRecipeActionType,
|
||||
SaveGroupRecipeAction,
|
||||
)
|
||||
from .group_seeder import SeederConfig
|
||||
from .group_shopping_list import (
|
||||
ShoppingListAddRecipeParams,
|
||||
@@ -41,10 +52,56 @@ from .group_shopping_list import (
|
||||
ShoppingListUpdate,
|
||||
)
|
||||
from .group_statistics import GroupStatistics, GroupStorage
|
||||
from .invite_token import CreateInviteToken, EmailInitationResponse, EmailInvitation, ReadInviteToken, SaveInviteToken
|
||||
from .webhook import CreateWebhook, ReadWebhook, SaveWebhook, WebhookPagination, WebhookType
|
||||
from .invite_token import (
|
||||
CreateInviteToken,
|
||||
EmailInitationResponse,
|
||||
EmailInvitation,
|
||||
ReadInviteToken,
|
||||
SaveInviteToken,
|
||||
)
|
||||
from .webhook import (
|
||||
CreateWebhook,
|
||||
ReadWebhook,
|
||||
SaveWebhook,
|
||||
WebhookPagination,
|
||||
WebhookType,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"GroupEventNotifierCreate",
|
||||
"GroupEventNotifierOptions",
|
||||
"GroupEventNotifierOptionsOut",
|
||||
"GroupEventNotifierOptionsSave",
|
||||
"GroupEventNotifierOut",
|
||||
"GroupEventNotifierPrivate",
|
||||
"GroupEventNotifierSave",
|
||||
"GroupEventNotifierUpdate",
|
||||
"GroupEventPagination",
|
||||
"CreateGroupRecipeAction",
|
||||
"GroupRecipeActionOut",
|
||||
"GroupRecipeActionPagination",
|
||||
"GroupRecipeActionType",
|
||||
"SaveGroupRecipeAction",
|
||||
"CreateWebhook",
|
||||
"ReadWebhook",
|
||||
"SaveWebhook",
|
||||
"WebhookPagination",
|
||||
"WebhookType",
|
||||
"GroupDataExport",
|
||||
"CreateGroupPreferences",
|
||||
"ReadGroupPreferences",
|
||||
"UpdateGroupPreferences",
|
||||
"GroupStatistics",
|
||||
"GroupStorage",
|
||||
"DataMigrationCreate",
|
||||
"SupportedMigrations",
|
||||
"SeederConfig",
|
||||
"CreateInviteToken",
|
||||
"EmailInitationResponse",
|
||||
"EmailInvitation",
|
||||
"ReadInviteToken",
|
||||
"SaveInviteToken",
|
||||
"SetPermissions",
|
||||
"ShoppingListAddRecipeParams",
|
||||
"ShoppingListCreate",
|
||||
"ShoppingListItemBase",
|
||||
@@ -67,6 +124,7 @@ __all__ = [
|
||||
"ShoppingListSave",
|
||||
"ShoppingListSummary",
|
||||
"ShoppingListUpdate",
|
||||
"GroupAdminUpdate",
|
||||
"CreateWebhook",
|
||||
"ReadWebhook",
|
||||
"SaveWebhook",
|
||||
|
||||
32
mealie/schema/group/group_recipe_action.py
Normal file
32
mealie/schema/group/group_recipe_action.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import UUID4, ConfigDict
|
||||
|
||||
from mealie.schema._mealie import MealieModel
|
||||
from mealie.schema.response.pagination import PaginationBase
|
||||
|
||||
|
||||
class GroupRecipeActionType(Enum):
|
||||
link = "link"
|
||||
post = "post"
|
||||
|
||||
|
||||
class CreateGroupRecipeAction(MealieModel):
|
||||
action_type: GroupRecipeActionType
|
||||
title: str
|
||||
url: str
|
||||
|
||||
model_config = ConfigDict(use_enum_values=True)
|
||||
|
||||
|
||||
class SaveGroupRecipeAction(CreateGroupRecipeAction):
|
||||
group_id: UUID4
|
||||
|
||||
|
||||
class GroupRecipeActionOut(SaveGroupRecipeAction):
|
||||
id: UUID4
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class GroupRecipeActionPagination(PaginationBase):
|
||||
items: list[GroupRecipeActionOut]
|
||||
Reference in New Issue
Block a user