diff --git a/.gitignore b/.gitignore index 72fca36ef..99fe9b65c 100644 --- a/.gitignore +++ b/.gitignore @@ -151,3 +151,130 @@ ENV/ # Node Modules node_modules/ mealie/data/debug/last_recipe.json +mealie/data/temp/active_import/images/.gitkeep +mealie/data/temp/active_import/images/banana-bread.jpg +mealie/data/temp/active_import/images/bon-appetit-s-perfect-pizza.jpg +mealie/data/temp/active_import/images/braised-beans-and-sardines-with-fennel.jpg +mealie/data/temp/active_import/images/broccoli-beer-cheese-soup.jpg +mealie/data/temp/active_import/images/buttery-kimchi-chicken.jpg +mealie/data/temp/active_import/images/cauliflower-cacciatore.jpg +mealie/data/temp/active_import/images/chicken-salad-with-citrus-and-chile-oil.jpg +mealie/data/temp/active_import/images/coffee-hazelnut-biscotti.jpg +mealie/data/temp/active_import/images/corn-and-crab-beignets-with-yaji-aioli.jpg +mealie/data/temp/active_import/images/crispy-carrots.jpg +mealie/data/temp/active_import/images/crispy-rice-with-ginger-citrus-celery-salad.jpg +mealie/data/temp/active_import/images/crockpot-buffalo-chicken.jpg +mealie/data/temp/active_import/images/detroit-style-pepperoni-pizza.jpg +mealie/data/temp/active_import/images/downtown-marinade.jpg +mealie/data/temp/active_import/images/falafel-hummus-plate.jpg +mealie/data/temp/active_import/images/five-spice-popcorn-chicken.jpg +mealie/data/temp/active_import/images/ginger-citrus-cookies.jpg +mealie/data/temp/active_import/images/green-chile-stew.jpg +mealie/data/temp/active_import/images/green-seasoning-baked-cod.jpg +mealie/data/temp/active_import/images/green-spaghetti.jpg +mealie/data/temp/active_import/images/huevos-rancheros-con-rajas-y-champinones.jpg +mealie/data/temp/active_import/images/jalapeno-cornbread.jpg +mealie/data/temp/active_import/images/marinated-tofu-with-brussels-sprouts-and-farro.jpg +mealie/data/temp/active_import/images/marranitos-enfiestados.jpg +mealie/data/temp/active_import/images/mississippi-pot-roast.jpg +mealie/data/temp/active_import/images/mushroom-risotto.jpg +mealie/data/temp/active_import/images/new-york-strip.jpg +mealie/data/temp/active_import/images/nilla-wafer-french-toast.jpg +mealie/data/temp/active_import/images/one-minute-muffin.jpg +mealie/data/temp/active_import/images/one-pot-chicken-and-rice.jpg +mealie/data/temp/active_import/images/pace-pork.jpg +mealie/data/temp/active_import/images/pasta-with-mushrooms-and-cashew-cream.jpg +mealie/data/temp/active_import/images/pizzettes.jpg +mealie/data/temp/active_import/images/pork-steaks.jpg +mealie/data/temp/active_import/images/roasted-brussels-sprouts.jpg +mealie/data/temp/active_import/images/roasted-okra.jpg +mealie/data/temp/active_import/images/salt-vinegar-potatoes.jpg +mealie/data/temp/active_import/images/shrimp-and-cabbage-curry.jpg +mealie/data/temp/active_import/images/smashed-carrots.jpg +mealie/data/temp/active_import/images/tamarind-chicken-thighs-with-collard-greens-salad.jpg +mealie/data/temp/active_import/images/tequila-beer-and-citrus-cocktail.jpg +mealie/data/temp/active_import/recipes/banana-bread.json +mealie/data/temp/active_import/recipes/bon-appetit-s-perfect-pizza.json +mealie/data/temp/active_import/recipes/braised-beans-and-sardines-with-fennel.json +mealie/data/temp/active_import/recipes/broccoli-beer-cheese-soup.json +mealie/data/temp/active_import/recipes/buttery-kimchi-chicken.json +mealie/data/temp/active_import/recipes/cauliflower-cacciatore.json +mealie/data/temp/active_import/recipes/chicken-salad-with-citrus-and-chile-oil.json +mealie/data/temp/active_import/recipes/coffee-hazelnut-biscotti.json +mealie/data/temp/active_import/recipes/corn-and-crab-beignets-with-yaji-aioli.json +mealie/data/temp/active_import/recipes/crispy-carrots.json +mealie/data/temp/active_import/recipes/crispy-rice-with-ginger-citrus-celery-salad.json +mealie/data/temp/active_import/recipes/crockpot-buffalo-chicken.json +mealie/data/temp/active_import/recipes/detroit-style-pepperoni-pizza.json +mealie/data/temp/active_import/recipes/downtown-marinade.json +mealie/data/temp/active_import/recipes/falafel-hummus-plate.json +mealie/data/temp/active_import/recipes/five-spice-popcorn-chicken.json +mealie/data/temp/active_import/recipes/ginger-citrus-cookies.json +mealie/data/temp/active_import/recipes/green-chile-stew.json +mealie/data/temp/active_import/recipes/green-seasoning-baked-cod.json +mealie/data/temp/active_import/recipes/green-spaghetti.json +mealie/data/temp/active_import/recipes/huevos-rancheros-con-rajas-y-champinones.json +mealie/data/temp/active_import/recipes/jalapeno-cornbread.json +mealie/data/temp/active_import/recipes/marinated-tofu-with-brussels-sprouts-and-farro.json +mealie/data/temp/active_import/recipes/marranitos-enfiestados.json +mealie/data/temp/active_import/recipes/mississippi-pot-roast.json +mealie/data/temp/active_import/recipes/mushroom-risotto.json +mealie/data/temp/active_import/recipes/new-york-strip.json +mealie/data/temp/active_import/recipes/nilla-wafer-french-toast.json +mealie/data/temp/active_import/recipes/one-minute-muffin.json +mealie/data/temp/active_import/recipes/one-pot-chicken-and-rice.json +mealie/data/temp/active_import/recipes/pace-pork.json +mealie/data/temp/active_import/recipes/pasta-with-mushrooms-and-cashew-cream.json +mealie/data/temp/active_import/recipes/pizzettes.json +mealie/data/temp/active_import/recipes/pork-steaks.json +mealie/data/temp/active_import/recipes/roasted-brussels-sprouts.json +mealie/data/temp/active_import/recipes/roasted-okra.json +mealie/data/temp/active_import/recipes/salt-vinegar-potatoes.json +mealie/data/temp/active_import/recipes/shrimp-and-cabbage-curry.json +mealie/data/temp/active_import/recipes/smashed-carrots.json +mealie/data/temp/active_import/recipes/tamarind-chicken-thighs-with-collard-greens-salad.json +mealie/data/temp/active_import/recipes/tequila-beer-and-citrus-cocktail.json +mealie/data/temp/active_import/settings/settings.json +mealie/data/temp/active_import/templates/Banana Bread.md +mealie/data/temp/active_import/templates/Bon AppƩtit's Perfect Pizza.md +mealie/data/temp/active_import/templates/Braised Beans and Sardines With Fennel.md +mealie/data/temp/active_import/templates/Broccoli Beer Cheese Soup.md +mealie/data/temp/active_import/templates/Buttery Kimchi Chicken.md +mealie/data/temp/active_import/templates/Cauliflower Cacciatore.md +mealie/data/temp/active_import/templates/Chicken Salad With Citrus and Chile Oil.md +mealie/data/temp/active_import/templates/Coffee-Hazelnut Biscotti.md +mealie/data/temp/active_import/templates/Corn and Crab Beignets With Yaji Aioli.md +mealie/data/temp/active_import/templates/Crispy Carrots.md +mealie/data/temp/active_import/templates/Crispy Rice With Ginger-Citrus Celery Salad.md +mealie/data/temp/active_import/templates/Crockpot Buffalo Chicken.md +mealie/data/temp/active_import/templates/Detroit-Style Pepperoni Pizza.md +mealie/data/temp/active_import/templates/Downtown Marinade.md +mealie/data/temp/active_import/templates/Falafel-Hummus Plate.md +mealie/data/temp/active_import/templates/Five Spice Popcorn Chicken.md +mealie/data/temp/active_import/templates/Ginger-Citrus Cookies.md +mealie/data/temp/active_import/templates/Green Chile Stew.md +mealie/data/temp/active_import/templates/Green Seasoning Baked Cod.md +mealie/data/temp/active_import/templates/Green Spaghetti.md +mealie/data/temp/active_import/templates/Huevos Rancheros con Rajas y ChampiƱones.md +mealie/data/temp/active_import/templates/Jalapeno Cornbread.md +mealie/data/temp/active_import/templates/Marinated Tofu With Brussels Sprouts and Farro.md +mealie/data/temp/active_import/templates/Marranitos Enfiestados.md +mealie/data/temp/active_import/templates/Mississippi Pot Roast.md +mealie/data/temp/active_import/templates/Mushroom Risotto.md +mealie/data/temp/active_import/templates/New York Strip.md +mealie/data/temp/active_import/templates/Nilla Wafer French Toast.md +mealie/data/temp/active_import/templates/One Minute Muffin.md +mealie/data/temp/active_import/templates/One-Pot Chicken and Rice.md +mealie/data/temp/active_import/templates/Pace Pork.md +mealie/data/temp/active_import/templates/Pasta With Mushrooms and Cashew Cream.md +mealie/data/temp/active_import/templates/Pizzettes.md +mealie/data/temp/active_import/templates/Pork Steaks.md +mealie/data/temp/active_import/templates/Roasted Brussels Sprouts.md +mealie/data/temp/active_import/templates/Roasted Okra.md +mealie/data/temp/active_import/templates/Salt & Vinegar Potatoes.md +mealie/data/temp/active_import/templates/Shrimp and Cabbage Curry.md +mealie/data/temp/active_import/templates/Smashed Carrots.md +mealie/data/temp/active_import/templates/Tamarind Chicken Thighs With Collard Greens Salad.md +mealie/data/temp/active_import/templates/Tequila, Beer, and Citrus Cocktail.md +mealie/data/temp/active_import/themes/themes.json +mealie/data/mealie.sqlite diff --git a/mealie/data/mealie.sqlite b/mealie/data/mealie.sqlite index f56f7f916..b1a0df8eb 100644 Binary files a/mealie/data/mealie.sqlite and b/mealie/data/mealie.sqlite differ diff --git a/mealie/db/db_base.py b/mealie/db/db_base.py index c190897a7..b2f6d479b 100644 --- a/mealie/db/db_base.py +++ b/mealie/db/db_base.py @@ -3,12 +3,16 @@ import json import mongoengine from settings import USE_MONGO, USE_SQL +from db.sql.db_session import create_session +from db.sql.model_base import SqlAlchemyBase + class BaseDocument: def __init__(self) -> None: self.primary_key: str self.store: str self.document: mongoengine.Document + self.sql_model: SqlAlchemyBase @staticmethod # TODO: Probably Put a version in each class to speed up reads? def _unpack_mongo(document) -> dict: @@ -57,7 +61,15 @@ class BaseDocument: return docs elif USE_SQL: - return self.get_all_sql() + session = create_session() + list = [x.dict() for x in session.query(self.sql_model).all()] + session.close() + + if limit == 1: + return list[0] + + session.close() + return list def get( self, match_value: str, match_key: str = None, limit=1 @@ -82,7 +94,14 @@ class BaseDocument: db_entry = BaseDocument._unpack_mongo(document) elif USE_SQL: - return self.get_by_slug(match_value, match_key) + session = create_session() + result = ( + session.query(self.sql_model) + .filter_by(**{match_key: match_value}) + .one() + ) + + db_entry = result.dict() else: raise Exception("No database type established") @@ -100,11 +119,22 @@ class BaseDocument: elif USE_SQL: return self.save_new_sql(document) - def delete(self, primary_key) -> dict: + def delete(self, primary_key_value) -> dict: if USE_MONGO: - document = self.document.objects.get(**{str(self.primary_key): primary_key}) + document = self.document.objects.get(**{str(self.primary_key): primary_key_value}) if document: document.delete() elif USE_SQL: - pass + session = create_session() + + result = ( + session.query(self.sql_model) + .filter_by(**{self.primary_key: primary_key_value}) + .one() + ) + + print(result.dict()) + session.delete(result) + + session.commit() diff --git a/mealie/db/db_mealplan.py b/mealie/db/db_mealplan.py index c49e1fdb3..70769a414 100644 --- a/mealie/db/db_mealplan.py +++ b/mealie/db/db_mealplan.py @@ -1,9 +1,10 @@ from typing import List +from db.sql.meal_models import MealPlanModel from settings import USE_MONGO, USE_SQL from db.db_base import BaseDocument -from db.db_setup import USE_MONGO, USE_SQL, tiny_db +from db.db_setup import USE_MONGO, USE_SQL from db.mongo.meal_models import MealDocument, MealPlanDocument @@ -11,7 +12,7 @@ class _Meals(BaseDocument): def __init__(self) -> None: self.primary_key = "uid" if USE_SQL: - self.sql_model = None + self.sql_model = MealPlanModel self.document = MealPlanDocument @staticmethod diff --git a/mealie/db/db_recipes.py b/mealie/db/db_recipes.py index 7f1f76861..373dc4239 100644 --- a/mealie/db/db_recipes.py +++ b/mealie/db/db_recipes.py @@ -1,11 +1,16 @@ from settings import USE_MONGO, USE_SQL from db.db_base import BaseDocument -from db.db_setup import tiny_db from db.mongo.recipe_models import RecipeDocument from db.sql.db_session import create_session -from db.sql.recipe_models import (ApiExtras, Note, RecipeIngredient, - RecipeInstruction, RecipeModel, Tag) +from db.sql.recipe_models import ( + ApiExtras, + Note, + RecipeIngredient, + RecipeInstruction, + RecipeModel, + Tag, +) class _Recipes(BaseDocument): @@ -13,24 +18,12 @@ class _Recipes(BaseDocument): self.primary_key = "slug" if USE_SQL: self.sql_model = RecipeModel - self.document = RecipeDocument - - def get_by_slug(self, match_value: str, match_key: str): - session = create_session() - result = session.query(self.sql_model).filter_by(**{match_key: match_value}).one() - - - return result.dict() - - def get_all_sql(self): - session = create_session() - list = [x.dict() for x in session.query(self.sql_model).all()] - session.close() - return list + else: + self.document = RecipeDocument def save_new_sql(self, recipe_data: dict): session = create_session() - new_recipe = self.sql_model() + new_recipe: RecipeModel = self.sql_model() new_recipe.name = recipe_data.get("name") new_recipe.description = recipe_data.get("description") new_recipe.image = recipe_data.get("image") diff --git a/mealie/db/db_settings.py b/mealie/db/db_settings.py index 819505648..5d7e239a3 100644 --- a/mealie/db/db_settings.py +++ b/mealie/db/db_settings.py @@ -1,7 +1,8 @@ +from db.sql.settings_models import SiteSettingsModel from settings import USE_MONGO, USE_SQL from db.db_base import BaseDocument -from db.db_setup import USE_MONGO, USE_SQL, tiny_db +from db.db_setup import USE_MONGO, USE_SQL from db.mongo.settings_models import SiteSettingsDocument, WebhooksDocument @@ -11,7 +12,7 @@ class _Settings(BaseDocument): self.primary_key = "name" if USE_SQL: - self.sql_model = None + self.sql_model = SiteSettingsModel self.document = SiteSettingsDocument diff --git a/mealie/db/db_setup.py b/mealie/db/db_setup.py index 8c103aa77..ce50be17f 100644 --- a/mealie/db/db_setup.py +++ b/mealie/db/db_setup.py @@ -1,9 +1,7 @@ from settings import DATA_DIR, USE_MONGO, USE_SQL from db.sql.db_session import globa_init as sql_global_init -from db.tinydb.tinydb_setup import TinyDatabase -tiny_db: TinyDatabase = None if USE_SQL: db_file = DATA_DIR.joinpath("mealie.sqlite") sql_global_init(db_file) diff --git a/mealie/db/db_themes.py b/mealie/db/db_themes.py index ad9f9c7a9..68eb8413f 100644 --- a/mealie/db/db_themes.py +++ b/mealie/db/db_themes.py @@ -1,15 +1,17 @@ from settings import USE_MONGO, USE_SQL from db.db_base import BaseDocument -from db.db_setup import USE_MONGO, USE_SQL, tiny_db +from db.db_setup import USE_MONGO, USE_SQL from db.mongo.settings_models import SiteThemeDocument, ThemeColorsDocument +from db.sql.db_session import create_session +from db.sql.settings_models import SiteThemeModel, ThemeColorsModel class _Themes(BaseDocument): def __init__(self) -> None: self.primary_key = "name" if USE_SQL: - self.sql_model = None + self.sql_model = SiteThemeModel else: self.document = SiteThemeDocument @@ -21,7 +23,26 @@ class _Themes(BaseDocument): document.save() elif USE_SQL: - pass + session = create_session() + + colors = ThemeColorsModel() + new_colors = theme_data.get("colors") + colors.primary = new_colors.get("primary") + colors.secondary = new_colors.get("secondary") + colors.accent = new_colors.get("accent") + colors.success = new_colors.get("success") + colors.info = new_colors.get("info") + colors.warning = new_colors.get("warning") + colors.error = new_colors.get("error") + + new_theme = self.sql_model(name=theme_data.get("name")) + + new_theme.colors = colors + + session.add(new_theme) + session.commit() + + return def update(self, data: dict) -> dict: if USE_MONGO: diff --git a/mealie/db/sql/_all_models.py b/mealie/db/sql/_all_models.py index 34d6dff85..f812fe193 100644 --- a/mealie/db/sql/_all_models.py +++ b/mealie/db/sql/_all_models.py @@ -1 +1,3 @@ -from db.sql.recipe_models import RecipeModel \ No newline at end of file +from db.sql.meal_models import * +from db.sql.recipe_models import * +from db.sql.settings_models import * diff --git a/mealie/db/sql/meal_models.py b/mealie/db/sql/meal_models.py index e69de29bb..d696c37a9 100644 --- a/mealie/db/sql/meal_models.py +++ b/mealie/db/sql/meal_models.py @@ -0,0 +1,50 @@ +import uuid +from typing import List + +import sqlalchemy as sa +import sqlalchemy.orm as orm +from db.sql.model_base import SqlAlchemyBase + + +class Meal(SqlAlchemyBase): + __tablename__ = "meal" + id = sa.Column(sa.Integer, primary_key=True) + parent_id = sa.Column(sa.String, sa.ForeignKey("mealplan.uid")) + slug = sa.Column(sa.String) + name = sa.Column(sa.String) + date = sa.Column(sa.Date) + dateText = sa.Column(sa.String) + image = sa.Column(sa.String) + description = sa.Column(sa.String) + + def dict(self) -> dict: + data = { + "slug": self.slug, + "name": self.name, + "date": self.date, + "dateText": self.dateText, + "image": self.image, + "description": self.description, + } + + return data + + +class MealPlanModel(SqlAlchemyBase): + __tablename__ = "mealplan" + uid = sa.Column( + sa.String, default=uuid.uuid1, primary_key=True, unique=True + ) #! Probably Bad? + startDate = sa.Column(sa.Date) + endDate = sa.Column(sa.Date) + meals: List[Meal] = orm.relation(Meal) + + def dict(self) -> dict: + data = { + "uid": self.uid, + "startDate": self.startDate, + "endDate": self.endDate, + "meals": [meal.dict() for meal in self.meals], + } + + return data diff --git a/mealie/db/sql/recipe_models.py b/mealie/db/sql/recipe_models.py index 4d2b9a1cf..d649cf9f3 100644 --- a/mealie/db/sql/recipe_models.py +++ b/mealie/db/sql/recipe_models.py @@ -85,7 +85,7 @@ class RecipeModel(SqlAlchemyBase): slug = sa.Column(sa.String, primary_key=True, index=True, unique=True) categories: List[Category] = orm.relation("Category") tags: List[Tag] = orm.relation("Tag") - dateAdded = sa.Column(sa.Date, default=date.today()) + dateAdded = sa.Column(sa.Date, default=date.today) notes: List[Note] = orm.relation("Note") rating = sa.Column(sa.Integer) orgURL = sa.Column(sa.String) diff --git a/mealie/db/sql/settings_models.py b/mealie/db/sql/settings_models.py index e69de29bb..d4d4c0092 100644 --- a/mealie/db/sql/settings_models.py +++ b/mealie/db/sql/settings_models.py @@ -0,0 +1,75 @@ +import sqlalchemy as sa +import sqlalchemy.orm as orm +from db.sql.model_base import SqlAlchemyBase +from sqlalchemy.sql.expression import true + + +class WebhookURLModel(SqlAlchemyBase): + __tablename__ = "webhook_urls" + url = sa.Column(sa.String, primary_key=True, unique=True) + parent_id = sa.Column(sa.Integer, sa.ForeignKey("webhook_settings.id")) + + def dict(self): + return self.url + + +class WebHookModel(SqlAlchemyBase): + __tablename__ = "webhook_settings" + id = sa.Column(sa.Integer, primary_key=True) + parent_id = sa.Column(sa.String, sa.ForeignKey("site_settings.name")) + webhookURLs = orm.relation("WebhookURLModel") + webhookTime = sa.Column(sa.String, default="00:00") + enabled = sa.Column(sa.Boolean, default=False) + + def dict(self): + data = { + "webhookURLs": [url.dict for url in self.webhookURLS], + "webhookTime": self.webhookTime, + "enabled": self.enabled, + } + return data + + +class SiteSettingsModel(SqlAlchemyBase): + __tablename__ = "site_settings" + name = sa.Column(sa.String, primary_key=True) + webhooks = orm.relation("WebHookModel") + + def dict(self): + data = {"name": self.name, "webhooks": self.webhooks.dict()} + return data + + +class ThemeColorsModel(SqlAlchemyBase): + __tablename__ = "theme_colors" + id = sa.Column(sa.Integer, primary_key=True) + parent_id = sa.Column(sa.String, sa.ForeignKey("site_theme.name")) + primary = sa.Column(sa.String) + accent = sa.Column(sa.String) + secondary = sa.Column(sa.String) + success = sa.Column(sa.String) + info = sa.Column(sa.String) + warning = sa.Column(sa.String) + error = sa.Column(sa.String) + + def dict(self): + data = { + "primary": self.primary, + "accent": self.accent, + "secondary": self.secondary, + "success": self.success, + "info": self.info, + "warning": self.warning, + "error": self.error, + } + return data + + +class SiteThemeModel(SqlAlchemyBase): + __tablename__ = "site_theme" + name = sa.Column(sa.String, primary_key=True) + colors = orm.relationship("ThemeColorsModel", uselist=False, cascade="all, delete") + + def dict(self): + data = {"name": self.name, "colors": self.colors.dict()} + return data diff --git a/mealie/db/tinydb/baseclass.py b/mealie/db/tinydb.depreciated/baseclass.py similarity index 100% rename from mealie/db/tinydb/baseclass.py rename to mealie/db/tinydb.depreciated/baseclass.py diff --git a/mealie/db/tinydb/tinydb_setup.py b/mealie/db/tinydb.depreciated/tinydb_setup.py similarity index 100% rename from mealie/db/tinydb/tinydb_setup.py rename to mealie/db/tinydb.depreciated/tinydb_setup.py diff --git a/mealie/routes/setting_routes.py b/mealie/routes/setting_routes.py index df855faff..bfb5639a3 100644 --- a/mealie/routes/setting_routes.py +++ b/mealie/routes/setting_routes.py @@ -79,6 +79,7 @@ def update_theme(theme_name: str, data: SiteTheme): @router.delete("/api/site-settings/themes/{theme_name}/delete/", tags=["Themes"]) def delete_theme(theme_name: str): """ Deletes theme from the database """ + SiteTheme.delete_theme(theme_name) try: SiteTheme.delete_theme(theme_name) except: