mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-12-27 20:55:12 -05:00
fix(backend): 🐛 Fix recipe page issues (#778)
* fix(backend): 🐛 Fix favorite assignment on backend * fix(frontend): 🐛 fix printer button on recipe page * style(frontend): 🚸 add user feadback on copy of recipe link * fix(frontend): 🐛 Fix enableLandscape incorrect bindings to remove duplicate values * feat(frontend): ✨ add ingredient copy button for markdown list -[ ] format * feat(frontend): ✨ add remove prefix button to bulk entry * fix(frontend): 🐛 disable random button when no recipes are present * fix(frontend): ✨ fix .zip download error * fix(frontend): 🚸 close image dialog on upload/get * fix(frontend): 🐛 fix assignment on creation for categories and tags * feat(frontend): ✨ Open editor on creation / fix edit button on main screen * fix(frontend): 🐛 fix false negative regex match for urls on creationg page * feat(frontend): 🚸 provide better user feadback when recipe exists * feat(frontend): ✨ lock bulk importer on submit * remove zip from navigation * fix(frontend): ✨ rerender recipes on delete Co-authored-by: Hayden K <hay-kot@pm.me>
This commit is contained in:
@@ -8,6 +8,7 @@ router = APIRouter()
|
||||
|
||||
router.include_router(all_recipe_routes.router, prefix=prefix, tags=["Recipe: Query All"])
|
||||
router.include_router(recipe_export.user_router, prefix=prefix, tags=["Recipe: Exports"])
|
||||
router.include_router(recipe_export.public_router, prefix=prefix, tags=["Recipe: Exports"])
|
||||
router.include_router(recipe_crud_routes.user_router, prefix=prefix, tags=["Recipe: CRUD"])
|
||||
router.include_router(image_and_assets.user_router, prefix=prefix, tags=["Recipe: Images and Assets"])
|
||||
router.include_router(comments.router, prefix=prefix, tags=["Recipe: Comments"])
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
from zipfile import ZipFile
|
||||
|
||||
from fastapi import Depends, File
|
||||
from fastapi.datastructures import UploadFile
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlalchemy.orm.session import Session
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
from mealie.core.dependencies import temporary_zip_path
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.db.database import get_database
|
||||
from mealie.db.db_setup import generate_session
|
||||
from mealie.routes.routers import UserAPIRouter
|
||||
from mealie.schema.recipe import CreateRecipeByUrl, Recipe, RecipeImageTypes
|
||||
from mealie.schema.recipe import CreateRecipeByUrl, Recipe
|
||||
from mealie.schema.recipe.recipe import CreateRecipe, CreateRecipeByUrlBulk, RecipeSummary
|
||||
from mealie.schema.server.tasks import ServerTaskNames
|
||||
from mealie.services.recipe.recipe_service import RecipeService
|
||||
@@ -109,23 +105,6 @@ def get_recipe(recipe_service: RecipeService = Depends(RecipeService.read_existi
|
||||
return recipe_service.item
|
||||
|
||||
|
||||
@user_router.get("/{slug}/zip")
|
||||
async def get_recipe_as_zip(
|
||||
slug: str, session: Session = Depends(generate_session), temp_path=Depends(temporary_zip_path)
|
||||
):
|
||||
""" Get a Recipe and It's Original Image as a Zip File """
|
||||
db = get_database(session)
|
||||
recipe: Recipe = db.recipes.get(slug)
|
||||
image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
|
||||
with ZipFile(temp_path, "w") as myzip:
|
||||
myzip.writestr(f"{slug}.json", recipe.json())
|
||||
|
||||
if image_asset.is_file():
|
||||
myzip.write(image_asset, arcname=image_asset.name)
|
||||
|
||||
return FileResponse(temp_path, filename=f"{slug}.zip")
|
||||
|
||||
|
||||
@user_router.put("/{slug}")
|
||||
def update_recipe(data: Recipe, recipe_service: RecipeService = Depends(RecipeService.write_existing)):
|
||||
""" Updates a recipe by existing slug and data. """
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
from fastapi import Depends
|
||||
from zipfile import ZipFile
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy.orm.session import Session
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
from mealie.core.dependencies.dependencies import temporary_dir
|
||||
from mealie.core.dependencies import temporary_zip_path
|
||||
from mealie.core.dependencies.dependencies import temporary_dir, validate_recipe_token
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.core.security import create_recipe_slug_token
|
||||
from mealie.db.database import get_database
|
||||
from mealie.db.db_setup import generate_session
|
||||
from mealie.routes.routers import UserAPIRouter
|
||||
from mealie.schema.recipe import Recipe, RecipeImageTypes
|
||||
from mealie.services.recipe.recipe_service import RecipeService
|
||||
from mealie.services.recipe.template_service import TemplateService
|
||||
|
||||
user_router = UserAPIRouter()
|
||||
public_router = APIRouter()
|
||||
logger = get_logger()
|
||||
|
||||
|
||||
@@ -23,6 +32,12 @@ async def get_recipe_formats_and_templates(_: RecipeService = Depends(RecipeServ
|
||||
return TemplateService().templates
|
||||
|
||||
|
||||
@user_router.post("/{slug}/exports")
|
||||
async def get_recipe_zip_token(slug: str):
|
||||
""" Generates a recipe zip token to be used to download a recipe as a zip file """
|
||||
return {"token": create_recipe_slug_token(slug)}
|
||||
|
||||
|
||||
@user_router.get("/{slug}/exports", response_class=FileResponse)
|
||||
def get_recipe_as_format(
|
||||
template_name: str,
|
||||
@@ -38,3 +53,28 @@ def get_recipe_as_format(
|
||||
"""
|
||||
file = recipe_service.render_template(temp_dir, template_name)
|
||||
return FileResponse(file)
|
||||
|
||||
|
||||
@public_router.get("/{slug}/exports/zip")
|
||||
async def get_recipe_as_zip(
|
||||
token: str,
|
||||
slug: str,
|
||||
session: Session = Depends(generate_session),
|
||||
temp_path=Depends(temporary_zip_path),
|
||||
):
|
||||
""" Get a Recipe and It's Original Image as a Zip File """
|
||||
slug = validate_recipe_token(token)
|
||||
|
||||
if slug != slug:
|
||||
raise HTTPException(status_code=400, detail="Invalid Slug")
|
||||
|
||||
db = get_database(session)
|
||||
recipe: Recipe = db.recipes.get(slug)
|
||||
image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
|
||||
with ZipFile(temp_path, "w") as myzip:
|
||||
myzip.writestr(f"{slug}.json", recipe.json())
|
||||
|
||||
if image_asset.is_file():
|
||||
myzip.write(image_asset, arcname=image_asset.name)
|
||||
|
||||
return FileResponse(temp_path, filename=f"{slug}.zip")
|
||||
|
||||
@@ -26,9 +26,7 @@ def add_favorite(
|
||||
):
|
||||
""" Adds a Recipe to the users favorites """
|
||||
|
||||
assert_user_change_allowed(id, current_user)
|
||||
current_user.favorite_recipes.append(slug)
|
||||
|
||||
db = get_database(session)
|
||||
db.users.update(current_user.id, current_user)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user