diff --git a/frontend/api/class-interfaces/recipes.ts b/frontend/api/class-interfaces/recipes.ts index ba218dad5506..15f28cffb405 100644 --- a/frontend/api/class-interfaces/recipes.ts +++ b/frontend/api/class-interfaces/recipes.ts @@ -1,6 +1,6 @@ import { BaseCRUDAPI } from "./_base"; -import { Recipe } from "~/types/api-types/admin"; -import { CreateRecipe } from "~/types/api-types/recipe"; +import { Recipe , CreateRecipe } from "~/types/api-types/recipe"; + const prefix = "/api"; diff --git a/frontend/components/Domain/User/UserProfileCard.vue b/frontend/components/Domain/User/UserProfileCard.vue index 71356170d9c9..02f148a60151 100644 --- a/frontend/components/Domain/User/UserProfileCard.vue +++ b/frontend/components/Domain/User/UserProfileCard.vue @@ -108,6 +108,7 @@ export default defineComponent({ }); async function updateUser() { + // @ts-ignore const { response } = await api.users.updateOne(userCopy.value.id, userCopy.value); if (response?.status === 200) { context.emit(events.REFRESH); @@ -151,17 +152,22 @@ export default defineComponent({ // } // }, async changePassword() { + // @ts-ignore this.paswordLoading = true; const data = { currentPassword: this.password.current, newPassword: this.password.newOne, }; + // @ts-ignore if (this.$refs.passChange.validate()) { + // @ts-ignore if (await api.users.changePassword(this.user.id, data)) { this.$emit("refresh"); } } + + // @ts-ignore this.paswordLoading = false; }, }, diff --git a/frontend/composables/use-recipes.ts b/frontend/composables/use-recipes.ts index a94cc2a05ce2..578b9ae8da6d 100644 --- a/frontend/composables/use-recipes.ts +++ b/frontend/composables/use-recipes.ts @@ -1,4 +1,5 @@ import { useAsync, ref } from "@nuxtjs/composition-api"; +import {set } from "@vueuse/core" import { useAsyncKey } from "./use-utils"; import { useApiSingleton } from "~/composables/use-api"; import { Recipe } from "~/types/api-types/recipe"; @@ -29,7 +30,8 @@ export const useRecipes = (all = false, fetchRecipes = true) => { async function refreshRecipes() { const { data } = await api.recipes.getAll(start, end); if (data) { - recipes.value = data; + set(recipes, data); + } } diff --git a/frontend/pages/recipe/_slug.vue b/frontend/pages/recipe/_slug.vue index cd1834fef626..741bceb96d52 100644 --- a/frontend/pages/recipe/_slug.vue +++ b/frontend/pages/recipe/_slug.vue @@ -223,7 +223,7 @@ import RecipeNotes from "~/components/Domain/Recipe/RecipeNotes.vue"; import RecipeImageUploadBtn from "~/components/Domain/Recipe/RecipeImageUploadBtn.vue"; import RecipeSettingsMenu from "~/components/Domain/Recipe/RecipeSettingsMenu.vue"; import RecipeIngredientEditor from "~/components/Domain/Recipe/RecipeIngredientEditor.vue"; -import { Recipe } from "~/types/api-types/admin"; +import { Recipe } from "~/types/api-types/recipe"; import { useStaticRoutes } from "~/composables/api"; export default defineComponent({ diff --git a/mealie/db/data_access_layer/db_access.py b/mealie/db/data_access_layer/db_access.py index 41bf5c851a2a..1380907873f5 100644 --- a/mealie/db/data_access_layer/db_access.py +++ b/mealie/db/data_access_layer/db_access.py @@ -4,9 +4,10 @@ from mealie.db.data_access_layer.group_access_model import GroupDataAccessModel from mealie.db.models.event import Event, EventNotification from mealie.db.models.group import Group from mealie.db.models.mealplan import MealPlan +from mealie.db.models.recipe.category import Category from mealie.db.models.recipe.comment import RecipeComment from mealie.db.models.recipe.ingredient import IngredientFoodModel, IngredientUnitModel -from mealie.db.models.recipe.recipe import Category, RecipeModel, Tag +from mealie.db.models.recipe.recipe import RecipeModel, Tag from mealie.db.models.settings import CustomPage, SiteSettings from mealie.db.models.shopping_list import ShoppingList from mealie.db.models.sign_up import SignUp @@ -82,5 +83,5 @@ class DatabaseAccessLayer: self.users = UserDataAccessModel(DEFAULT_PK, User, UserInDB) self.api_tokens = BaseAccessModel(DEFAULT_PK, LongLiveToken, LongLiveTokenInDB) self.groups = GroupDataAccessModel(DEFAULT_PK, Group, GroupInDB) - self.meals = BaseAccessModel("uid", MealPlan, MealPlanOut) + self.meals = BaseAccessModel(DEFAULT_PK, MealPlan, MealPlanOut) self.shopping_lists = BaseAccessModel(DEFAULT_PK, ShoppingList, ShoppingListOut) diff --git a/mealie/db/models/_model_base.py b/mealie/db/models/_model_base.py index cd33588d4f98..763298477e50 100644 --- a/mealie/db/models/_model_base.py +++ b/mealie/db/models/_model_base.py @@ -1,7 +1,6 @@ import uuid from datetime import datetime -from mealie.db.db_setup import SessionLocal from sqlalchemy import Column, DateTime, Integer from sqlalchemy.ext.declarative import as_declarative from sqlalchemy.orm import declarative_base diff --git a/mealie/db/models/mealplan.py b/mealie/db/models/mealplan.py index 861bff2afa1e..20b2d46f56a5 100644 --- a/mealie/db/models/mealplan.py +++ b/mealie/db/models/mealplan.py @@ -1,6 +1,6 @@ import sqlalchemy.orm as orm -from mealie.db.models.group import Group from mealie.db.models._model_base import BaseMixins, SqlAlchemyBase +from mealie.db.models.group import Group from mealie.db.models.recipe.recipe import RecipeModel from mealie.db.models.shopping_list import ShoppingList from sqlalchemy import Column, Date, ForeignKey, Integer, String @@ -33,7 +33,7 @@ class Meal(SqlAlchemyBase): class MealDay(SqlAlchemyBase, BaseMixins): __tablename__ = "mealdays" id = Column(Integer, primary_key=True) - parent_id = Column(Integer, ForeignKey("mealplan.uid")) + parent_id = Column(Integer, ForeignKey("mealplan.id")) date = Column(Date) meals: list[Meal] = orm.relationship( Meal, @@ -49,7 +49,7 @@ class MealDay(SqlAlchemyBase, BaseMixins): class MealPlan(SqlAlchemyBase, BaseMixins): __tablename__ = "mealplan" - uid = Column(Integer, primary_key=True, unique=True) + # TODO: Migrate to use ID as PK start_date = Column(Date) end_date = Column(Date) plan_days: list[MealDay] = orm.relationship(MealDay, cascade="all, delete, delete-orphan") diff --git a/mealie/db/models/recipe/category.py b/mealie/db/models/recipe/category.py index c8334542caa0..bba5ecb95c21 100644 --- a/mealie/db/models/recipe/category.py +++ b/mealie/db/models/recipe/category.py @@ -1,12 +1,8 @@ -from functools import lru_cache - import sqlalchemy as sa import sqlalchemy.orm as orm from mealie.core import root_logger -from mealie.db.db_setup import SessionLocal from mealie.db.models._model_base import BaseMixins, SqlAlchemyBase from slugify import slugify -from sqlalchemy import inspect from sqlalchemy.orm import validates logger = root_logger.get_logger() @@ -64,7 +60,9 @@ class Category(SqlAlchemyBase, BaseMixins): if not session or not match_value: return None - result = session.query(Category).filter(Category.name == match_value).one_or_none() + slug = slugify(match_value) + + result = session.query(Category).filter(Category.slug == slug).one_or_none() if result: logger.debug("Category exists, associating recipe") return result diff --git a/mealie/db/models/recipe/recipe.py b/mealie/db/models/recipe/recipe.py index fd79fe72413f..c4471e99dbaa 100644 --- a/mealie/db/models/recipe/recipe.py +++ b/mealie/db/models/recipe/recipe.py @@ -10,7 +10,7 @@ from .._model_base import BaseMixins, SqlAlchemyBase from .._model_utils import auto_init from .api_extras import ApiExtras from .assets import RecipeAsset -from .category import Category, recipes2categories +from .category import recipes2categories from .ingredient import RecipeIngredient from .instruction import RecipeInstruction from .note import Note diff --git a/mealie/db/models/recipe/tag.py b/mealie/db/models/recipe/tag.py index 599cbccaa4ce..26328a4d7d18 100644 --- a/mealie/db/models/recipe/tag.py +++ b/mealie/db/models/recipe/tag.py @@ -1,7 +1,6 @@ import sqlalchemy as sa import sqlalchemy.orm as orm from mealie.core import root_logger -from mealie.db.db_setup import SessionLocal from mealie.db.models._model_base import BaseMixins, SqlAlchemyBase from slugify import slugify from sqlalchemy.orm import validates @@ -35,15 +34,17 @@ class Tag(SqlAlchemyBase, BaseMixins): self.name = name.strip() self.slug = slugify(self.name) - @staticmethod - def create_if_not_exist(name: str = None): - test_slug = slugify(name) - with SessionLocal() as session: - result = session.query(Tag).filter(Tag.slug == test_slug).one_or_none() + @classmethod + def get_ref(cls, match_value: str, session=None): + if not session or not match_value: + return None - if result: - logger.debug("Tag exists, associating recipe") - return result - else: - logger.debug("Tag doesn't exists, creating tag") - return Tag(name=name) + slug = slugify(match_value) + + result = session.query(Tag).filter(Tag.slug == slug).one_or_none() + if result: + logger.debug("Category exists, associating recipe") + return result + else: + logger.debug("Category doesn't exists, creating Category") + return Tag(name=match_value) diff --git a/mealie/routes/mealplans/crud.py b/mealie/routes/mealplans/crud.py index 1ca306f6fc74..fd0db142c4ee 100644 --- a/mealie/routes/mealplans/crud.py +++ b/mealie/routes/mealplans/crud.py @@ -69,7 +69,7 @@ def get_meal_plan( ): """ Returns a single Meal Plan from the Database """ - return db.meals.get(session, id, "uid") + return db.meals.get(session, id) @router.post("/create", status_code=status.HTTP_201_CREATED) @@ -97,7 +97,7 @@ def update_meal_plan( ): """ Updates a meal plan based off ID """ set_mealplan_dates(meal_plan) - processed_plan = MealPlanOut(uid=plan_id, **meal_plan.dict()) + processed_plan = MealPlanOut(id=plan_id, **meal_plan.dict()) try: db.meals.update(session, plan_id, processed_plan.dict()) background_tasks.add_task( diff --git a/mealie/routes/mealplans/helpers.py b/mealie/routes/mealplans/helpers.py index afe5d2343e36..4dff462fd477 100644 --- a/mealie/routes/mealplans/helpers.py +++ b/mealie/routes/mealplans/helpers.py @@ -44,6 +44,6 @@ def get_shopping_list( mealplan.shopping_list = created_list.id - db.meals.update(session, mealplan.uid, mealplan) + db.meals.update(session, mealplan.id, mealplan) return created_list diff --git a/mealie/schema/meal_plan/meal.py b/mealie/schema/meal_plan/meal.py index fccb0cc5649f..b3db0f65e468 100644 --- a/mealie/schema/meal_plan/meal.py +++ b/mealie/schema/meal_plan/meal.py @@ -48,7 +48,7 @@ class MealPlanIn(CamelModel): class MealPlanOut(MealPlanIn): - uid: int + id: int shopping_list: Optional[int] class Config: diff --git a/mealie/services/migrations/_migration_base.py b/mealie/services/migrations/_migration_base.py index 0c6adca16ac7..88bff31b1091 100644 --- a/mealie/services/migrations/_migration_base.py +++ b/mealie/services/migrations/_migration_base.py @@ -140,15 +140,18 @@ class MigrationBase(BaseModel): return recipe_dict def clean_recipe_dictionary(self, recipe_dict) -> Recipe: - """Calls the rewrite_alias function and the Cleaner.clean function on a - dictionary and returns the result unpacked into a Recipe object""" + """ + Calls the rewrite_alias function and the Cleaner.clean function on a + dictionary and returns the result unpacked into a Recipe object + """ recipe_dict = self.rewrite_alias(recipe_dict) recipe_dict = cleaner.clean(recipe_dict, url=recipe_dict.get("org_url", None)) return Recipe(**recipe_dict) def import_recipes_to_database(self, validated_recipes: list[Recipe]) -> None: - """Used as a single access point to process a list of Recipe objects into the + """ + Used as a single access point to process a list of Recipe objects into the database in a predictable way. If an error occurs the session is rolled back and the process will continue. All import information is appended to the 'migration_report' attribute to be returned to the frontend for display. @@ -166,6 +169,7 @@ class MigrationBase(BaseModel): except Exception as inst: exception = inst + logger.error(inst) self.session.rollback() import_status = MigrationImport(slug=recipe.slug, name=recipe.name, status=status, exception=str(exception)) diff --git a/tests/integration_tests/test_meal_routes.py b/tests/integration_tests/test_meal_routes.py index 563f7b431f8b..7bbeea8c743b 100644 --- a/tests/integration_tests/test_meal_routes.py +++ b/tests/integration_tests/test_meal_routes.py @@ -73,7 +73,7 @@ def test_update_mealplan(api_client: TestClient, api_routes: AppRoutes, slug_1, existing_mealplan = existing_mealplan[0] # Swap - plan_uid = existing_mealplan.get("uid") + plan_uid = existing_mealplan.get("id") existing_mealplan["planDays"][0]["meals"][0]["slug"] = slug_2 existing_mealplan["planDays"][1]["meals"][0]["slug"] = slug_1 @@ -96,7 +96,7 @@ def test_delete_mealplan(api_client: TestClient, api_routes: AppRoutes, admin_to existing_mealplan = json.loads(response.text) existing_mealplan = existing_mealplan[0] - plan_uid = existing_mealplan.get("uid") + plan_uid = existing_mealplan.get("id") response = api_client.delete(api_routes.meal_plans_plan_id(plan_uid), headers=admin_token) assert response.status_code == 200