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:
Michael Genson
2024-05-01 02:20:52 -05:00
committed by GitHub
parent ee87a14401
commit 3807778e2f
22 changed files with 860 additions and 10 deletions

View File

@@ -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 *

View File

@@ -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",

View 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

View File

@@ -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

View File

@@ -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)

View 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)

View File

@@ -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",

View 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]