mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-12-28 13:05:26 -05:00
Feature/recipe instructions improvements (#785)
* feat(frontend): ✨ split paragraph by 1. 1) or 1: regex matches * feat(frontend): ✨ Update frontend to support ingredient To step refs * feat(backend): ✨ Update backend to support ingredient to step refs * fix title editor * move about info to site-settings * update change-log Co-authored-by: Hayden K <hay-kot@pm.me>
This commit is contained in:
@@ -92,7 +92,7 @@ def handle_one_to_many_list(session: Session, get_attr, relation_cls, all_elemen
|
||||
|
||||
updated_elems.append(existing_elem)
|
||||
|
||||
new_elems = [safe_call(relation_cls, elem) for elem in elems_to_create]
|
||||
new_elems = [safe_call(relation_cls, elem, session=session) for elem in elems_to_create]
|
||||
return new_elems + updated_elems
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ def auto_init(): # sourcery no-metrics
|
||||
setattr(self, key, instances)
|
||||
|
||||
elif relation_dir == ONETOMANY:
|
||||
instance = safe_call(relation_cls, val)
|
||||
instance = safe_call(relation_cls, val, session=session)
|
||||
setattr(self, key, instance)
|
||||
|
||||
elif relation_dir == MANYTOONE and not use_list:
|
||||
|
||||
39
mealie/db/models/_model_utils/guid.py
Normal file
39
mealie/db/models/_model_utils/guid.py
Normal file
@@ -0,0 +1,39 @@
|
||||
import uuid
|
||||
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.types import CHAR, TypeDecorator
|
||||
|
||||
|
||||
class GUID(TypeDecorator):
|
||||
"""Platform-independent GUID type.
|
||||
Uses PostgreSQL's UUID type, otherwise uses
|
||||
CHAR(32), storing as stringified hex values.
|
||||
"""
|
||||
|
||||
impl = CHAR
|
||||
|
||||
def load_dialect_impl(self, dialect):
|
||||
if dialect.name == "postgresql":
|
||||
return dialect.type_descriptor(UUID())
|
||||
else:
|
||||
return dialect.type_descriptor(CHAR(32))
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if value is None:
|
||||
return value
|
||||
elif dialect.name == "postgresql":
|
||||
return str(value)
|
||||
else:
|
||||
if not isinstance(value, uuid.UUID):
|
||||
return "%.32x" % uuid.UUID(value).int
|
||||
else:
|
||||
# hexstring
|
||||
return "%.32x" % value.int
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is None:
|
||||
return value
|
||||
else:
|
||||
if not isinstance(value, uuid.UUID):
|
||||
value = uuid.UUID(value)
|
||||
return value
|
||||
@@ -28,12 +28,16 @@ def get_valid_call(func: Callable, args_dict) -> dict:
|
||||
return {k: v for k, v in args_dict.items() if k in valid_args}
|
||||
|
||||
|
||||
def safe_call(func, dict) -> Any:
|
||||
def safe_call(func, dict_args, **kwargs) -> Any:
|
||||
"""
|
||||
Safely calls the supplied function with the supplied dictionary of arguments.
|
||||
by removing any invalid arguments.
|
||||
"""
|
||||
|
||||
if kwargs:
|
||||
dict_args.update(kwargs)
|
||||
|
||||
try:
|
||||
return func(**get_valid_call(func, dict))
|
||||
return func(**get_valid_call(func, dict_args))
|
||||
except TypeError:
|
||||
return func(**dict)
|
||||
return func(**dict_args)
|
||||
|
||||
@@ -3,6 +3,7 @@ from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, orm
|
||||
from mealie.db.models._model_base import BaseMixins, SqlAlchemyBase
|
||||
|
||||
from .._model_utils import auto_init
|
||||
from .._model_utils.guid import GUID
|
||||
|
||||
|
||||
class IngredientUnitModel(SqlAlchemyBase, BaseMixins):
|
||||
@@ -48,6 +49,8 @@ class RecipeIngredient(SqlAlchemyBase, BaseMixins):
|
||||
food = orm.relationship(IngredientFoodModel, uselist=False)
|
||||
quantity = Column(Integer)
|
||||
|
||||
reference_id = Column(GUID()) # Reference Links
|
||||
|
||||
# Extras
|
||||
|
||||
@auto_init()
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String
|
||||
from sqlalchemy import Column, ForeignKey, Integer, String, orm
|
||||
|
||||
from mealie.db.models._model_base import SqlAlchemyBase
|
||||
from .._model_base import BaseMixins, SqlAlchemyBase
|
||||
from .._model_utils import auto_init
|
||||
from .._model_utils.guid import GUID
|
||||
|
||||
|
||||
class RecipeIngredientRefLink(SqlAlchemyBase, BaseMixins):
|
||||
__tablename__ = "recipe_ingredient_ref_link"
|
||||
instruction_id = Column(Integer, ForeignKey("recipe_instructions.id"))
|
||||
reference_id = Column(GUID())
|
||||
|
||||
@auto_init()
|
||||
def __init__(self, **_) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class RecipeInstruction(SqlAlchemyBase):
|
||||
@@ -11,3 +23,9 @@ class RecipeInstruction(SqlAlchemyBase):
|
||||
type = Column(String, default="")
|
||||
title = Column(String)
|
||||
text = Column(String)
|
||||
|
||||
ingredient_references = orm.relationship("RecipeIngredientRefLink", cascade="all, delete-orphan")
|
||||
|
||||
@auto_init()
|
||||
def __init__(self, **_) -> None:
|
||||
pass
|
||||
|
||||
@@ -92,7 +92,6 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
"notes",
|
||||
"nutrition",
|
||||
"recipe_ingredient",
|
||||
"recipe_instructions",
|
||||
"settings",
|
||||
"tools",
|
||||
}
|
||||
@@ -111,7 +110,6 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
notes: list[dict] = None,
|
||||
nutrition: dict = None,
|
||||
recipe_ingredient: list[str] = None,
|
||||
recipe_instructions: list[dict] = None,
|
||||
settings: dict = None,
|
||||
tools: list[str] = None,
|
||||
**_,
|
||||
@@ -120,10 +118,10 @@ class RecipeModel(SqlAlchemyBase, BaseMixins):
|
||||
self.tools = [Tool(tool=x) for x in tools] if tools else []
|
||||
self.recipe_ingredient = [RecipeIngredient(**ingr, session=session) for ingr in recipe_ingredient]
|
||||
self.assets = [RecipeAsset(**a) for a in assets]
|
||||
self.recipe_instructions = [
|
||||
RecipeInstruction(text=instruc.get("text"), title=instruc.get("title"), type=instruc.get("@type", None))
|
||||
for instruc in recipe_instructions
|
||||
]
|
||||
# self.recipe_instructions = [
|
||||
# RecipeInstruction(text=instruc.get("text"), title=instruc.get("title"), type=instruc.get("@type", None))
|
||||
# for instruc in recipe_instructions
|
||||
# ]
|
||||
|
||||
# Mealie Specific
|
||||
self.settings = RecipeSettings(**settings) if settings else RecipeSettings()
|
||||
|
||||
Reference in New Issue
Block a user