mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-11 02:13:12 -05:00
feat: ✨ add user recipe export functionality (#845)
* feat(frontend): ✨ add user recipe export functionality * remove depreciated folders * change/remove depreciated folders * add testing variable in config * add GUID support for group_id * improve testing feedback on 422 errors * remove/cleanup files/folders * initial user export support * delete unused css * update backup page UI * remove depreciated settings * feat: ✨ export download links * fix #813 * remove top level statements * show footer * add export purger to scheduler * update purge glob * fix meal-planner lockout * feat: ✨ add bulk delete/purge exports * style(frontend): 💄 update UI for site settings * feat: ✨ add version checker * update documentation Co-authored-by: hay-kot <hay-kot@pm.me>
This commit is contained in:
@@ -3,10 +3,12 @@ from __future__ import annotations
|
||||
from pathlib import Path
|
||||
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.schema.group.group_exports import GroupDataExport
|
||||
from mealie.schema.recipe import CategoryBase, Recipe
|
||||
from mealie.schema.recipe.recipe_category import TagBase
|
||||
from mealie.services._base_http_service.http_services import UserHttpService
|
||||
from mealie.services.events import create_recipe_event
|
||||
from mealie.services.exporter import Exporter, RecipeExporter
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -18,8 +20,36 @@ class RecipeBulkActions(UserHttpService[int, Recipe]):
|
||||
def populate_item(self, _: int) -> Recipe:
|
||||
return
|
||||
|
||||
def export_recipes(self, temp_path: Path, recipes: list[str]) -> None:
|
||||
return
|
||||
def export_recipes(self, temp_path: Path, slugs: list[str]) -> None:
|
||||
recipe_exporter = RecipeExporter(self.db, self.group_id, slugs)
|
||||
exporter = Exporter(self.group_id, temp_path, [recipe_exporter])
|
||||
|
||||
exporter.run(self.db)
|
||||
|
||||
def get_exports(self) -> list[GroupDataExport]:
|
||||
return self.db.group_exports.multi_query({"group_id": self.group_id})
|
||||
|
||||
def purge_exports(self) -> int:
|
||||
all_exports = self.get_exports()
|
||||
|
||||
exports_deleted = 0
|
||||
for export in all_exports:
|
||||
try:
|
||||
Path(export.path).unlink(missing_ok=True)
|
||||
self.db.group_exports.delete(export.id)
|
||||
exports_deleted += 1
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete export {export.id}")
|
||||
logger.error(e)
|
||||
|
||||
group = self.db.groups.get_one(self.group_id)
|
||||
|
||||
for match in group.directory.glob("**/export/*zip"):
|
||||
if match.is_file():
|
||||
match.unlink()
|
||||
exports_deleted += 1
|
||||
|
||||
return exports_deleted
|
||||
|
||||
def assign_tags(self, recipes: list[str], tags: list[TagBase]) -> None:
|
||||
for slug in recipes:
|
||||
|
||||
@@ -59,14 +59,18 @@ class RecipeService(CrudHttpMixins[CreateRecipe, Recipe, Recipe], UserHttpServic
|
||||
if not self.item.settings.public and not self.user:
|
||||
raise HTTPException(status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def get_all(self, start=0, limit=None):
|
||||
items = self.db.recipes.summary(self.user.group_id, start=start, limit=limit)
|
||||
def get_all(self, start=0, limit=None, load_foods=False) -> list[RecipeSummary]:
|
||||
items = self.db.recipes.summary(self.user.group_id, start=start, limit=limit, load_foods=load_foods)
|
||||
|
||||
new_items = []
|
||||
|
||||
for item in items:
|
||||
# Pydantic/FastAPI can't seem to serialize the ingredient field on thier own.
|
||||
new_item = item.__dict__
|
||||
new_item["recipe_ingredient"] = [x.__dict__ for x in item.recipe_ingredient]
|
||||
|
||||
if load_foods:
|
||||
new_item["recipe_ingredient"] = [x.__dict__ for x in item.recipe_ingredient]
|
||||
|
||||
new_items.append(new_item)
|
||||
|
||||
return [RecipeSummary.construct(**x) for x in new_items]
|
||||
|
||||
Reference in New Issue
Block a user