diff --git a/cookbook/helper/shopping_helper.py b/cookbook/helper/shopping_helper.py index 7e1fa6c7..761f1e7c 100644 --- a/cookbook/helper/shopping_helper.py +++ b/cookbook/helper/shopping_helper.py @@ -38,118 +38,268 @@ def shopping_helper(qs, request): return qs.order_by(*supermarket_order).select_related('unit', 'food', 'ingredient', 'created_by', 'list_recipe', 'list_recipe__mealplan', 'list_recipe__recipe') -# TODO refactor as class -def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None, ingredients=None, created_by=None, space=None, append=False): - """ - Creates ShoppingListRecipe and associated ShoppingListEntrys from a recipe or a meal plan with a recipe - :param list_recipe: Modify an existing ShoppingListRecipe - :param recipe: Recipe to use as list of ingredients. One of [recipe, mealplan] are required - :param mealplan: alternatively use a mealplan recipe as source of ingredients - :param servings: Optional: Number of servings to use to scale shoppinglist. If servings = 0 an existing recipe list will be deleted - :param ingredients: Ingredients, list of ingredient IDs to include on the shopping list. When not provided all ingredients will be used - :param append: If False will remove any entries not included with ingredients, when True will append ingredients to the shopping list - """ - r = recipe or getattr(mealplan, 'recipe', None) or getattr(list_recipe, 'recipe', None) - if not r: - raise ValueError(_("You must supply a recipe or mealplan")) +class RecipeShoppingEditor(): + def __init__(self, user, space, **kwargs): + self.created_by = user + self.space = space + self._kwargs = {**kwargs} - created_by = created_by or getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', None) - if not created_by: - raise ValueError(_("You must supply a created_by")) + self.mealplan = self._kwargs.get('mealplan', None) + self.id = self._kwargs.get('id', None) - try: - servings = float(servings) - except (ValueError, TypeError): - servings = getattr(mealplan, 'servings', 1.0) + self._shopping_list_recipe = self.get_shopping_list_recipe(self.id, self.created_by, self.space) - servings_factor = servings / r.servings + if self._shopping_list_recipe: + # created_by needs to be sticky to original creator as it is 'their' shopping list + # changing shopping list created_by can shift some items to new owner which may not share in the other direction + self.created_by = getattr(self._shopping_list_recipe.entries.first(), 'created_by', self.created_by) - shared_users = list(created_by.get_shopping_share()) - shared_users.append(created_by) - if list_recipe: - created = False - else: - list_recipe = ShoppingListRecipe.objects.create(recipe=r, mealplan=mealplan, servings=servings) - created = True + self.recipe = getattr(self._shopping_list_recipe, 'recipe', None) or self._kwargs.get('recipe', None) or getattr(self.mealplan, 'recipe', None) - related_step_ing = [] - if servings == 0 and not created: - list_recipe.delete() - return [] - elif ingredients: - ingredients = Ingredient.objects.filter(pk__in=ingredients, space=space) - else: - ingredients = Ingredient.objects.filter(step__recipe=r, food__ignore_shopping=False, space=space) + try: + self.servings = float(self._kwargs.get('servings', None)) + except (ValueError, TypeError): + self.servings = getattr(self._shopping_list_recipe, 'servings', None) or getattr(self.mealplan, 'servings', None) or getattr(self.recipe, 'servings', None) - if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand: - ingredients = ingredients.exclude(food__onhand_users__id__in=[x.id for x in shared_users]) + @property + def _servings_factor(self): + return self.servings / self.recipe.servings - if related := created_by.userpreference.mealplan_autoinclude_related: - # TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans - related_recipes = r.get_related_recipes() + @property + def _shared_users(self): + return [*list(self.created_by.get_shopping_share()), self.created_by] - for x in related_recipes: - # related recipe is a Step serving size is driven by recipe serving size - # TODO once/if Steps can have a serving size this needs to be refactored - if exclude_onhand: - # if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior - related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users]).values_list('id', flat=True) - else: - related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True) + @staticmethod + def get_shopping_list_recipe(id, user, space): + return ShoppingListRecipe.objects.filter(id=id).filter(Q(shoppinglist__space=space) | Q(entries__space=space)).filter( + Q(shoppinglist__created_by=user) + | Q(shoppinglist__shared=user) + | Q(entries__created_by=user) + | Q(entries__created_by__in=list(user.get_shopping_share())) + ).prefetch_related('entries').first() - x_ing = [] - if ingredients.filter(food__recipe=x).exists(): - for ing in ingredients.filter(food__recipe=x): - if exclude_onhand: - x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users]) - else: - x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__ignore_shopping=True) - for i in [x for x in x_ing]: - ShoppingListEntry.objects.create( - list_recipe=list_recipe, - food=i.food, - unit=i.unit, - ingredient=i, - amount=i.amount * Decimal(servings_factor), - created_by=created_by, - space=space, - ) - # dont' add food to the shopping list that are actually recipes that will be added as ingredients - ingredients = ingredients.exclude(food__recipe=x) + def get_recipe_ingredients(self, id, exclude_onhand=False): + if exclude_onhand: + return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space).exclude(food__onhand_users__id__in=[x.id for x in self._shared_users]) + else: + return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space) - add_ingredients = list(ingredients.values_list('id', flat=True)) + related_step_ing - if not append: - existing_list = ShoppingListEntry.objects.filter(list_recipe=list_recipe) - # delete shopping list entries not included in ingredients - existing_list.exclude(ingredient__in=ingredients).delete() - # add shopping list entries that did not previously exist - add_ingredients = set(add_ingredients) - set(existing_list.values_list('ingredient__id', flat=True)) - add_ingredients = Ingredient.objects.filter(id__in=add_ingredients, space=space) + @property + def _include_related(self): + return self.created_by.userpreference.mealplan_autoinclude_related - # if servings have changed, update the ShoppingListRecipe and existing Entries - if servings <= 0: - servings = 1 + @property + def _exclude_onhand(self): + return self.created_by.userpreference.mealplan_autoexclude_onhand - if not created and list_recipe.servings != servings: - update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True)) - list_recipe.servings = servings - list_recipe.save() - for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients): - sle.amount = sle.ingredient.amount * Decimal(servings_factor) + def create(self, **kwargs): + ingredients = kwargs.get('ingredients', None) + exclude_onhand = not ingredients and self._exclude_onhand + if servings := kwargs.get('servings', None): + self.servings = float(servings) + + if mealplan := kwargs.get('mealplan', None): + self.mealplan = mealplan + self.recipe = mealplan.recipe + elif recipe := kwargs.get('recipe', None): + self.recipe = recipe + + if not self.servings: + self.servings = getattr(self.mealplan, 'servings', None) or getattr(self.recipe, 'servings', 1.0) + + self._shopping_list_recipe = ShoppingListRecipe.objects.create(recipe=self.recipe, mealplan=self.mealplan, servings=self.servings) + + if ingredients: + self._add_ingredients(ingredients=ingredients) + else: + if self._include_related: + related = self.recipe.get_related_recipes() + self._add_ingredients(self.get_recipe_ingredients(self.recipe.id, exclude_onhand=exclude_onhand).exclude(food__recipe__in=related)) + for r in related: + self._add_ingredients(self.get_recipe_ingredients(r.id, exclude_onhand=exclude_onhand).exclude(food__recipe__in=related)) + else: + self._add_ingredients(self.get_recipe_ingredients(self.recipe.id, exclude_onhand=exclude_onhand)) + + return True + + def add(self, **kwargs): + return + + def edit(self, servings=None, ingredients=None, **kwargs): + if servings: + self.servings = servings + + self._delete_ingredients(ingredients=ingredients) + if self.servings != self._shopping_list_recipe.servings: + self.edit_servings() + self._add_ingredients(ingredients=ingredients) + return True + + def edit_servings(self, servings=None, **kwargs): + if servings: + self.servings = servings + if id := kwargs.get('id', None): + self._shopping_list_recipe = self.get_shopping_list_recipe(id, self.created_by, self.space) + if not self.servings: + raise ValueError(_("You must supply a servings size")) + + if self._shopping_list_recipe.servings == self.servings: + return True + + for sle in ShoppingListEntry.objects.filter(list_recipe=self._shopping_list_recipe): + sle.amount = sle.ingredient.amount * Decimal(self._servings_factor) sle.save() + self._shopping_list_recipe.servings = self.servings + self._shopping_list_recipe.save() + return True - # add any missing Entries - for i in [x for x in add_ingredients if x.food]: + def delete(self, **kwargs): + try: + self._shopping_list_recipe.delete() + return True + except: + return False - ShoppingListEntry.objects.create( - list_recipe=list_recipe, - food=i.food, - unit=i.unit, - ingredient=i, - amount=i.amount * Decimal(servings_factor), - created_by=created_by, - space=space, - ) + def _add_ingredients(self, ingredients=None): + if not ingredients: + return + elif type(ingredients) == list: + ingredients = Ingredient.objects.filter(id__in=ingredients) + existing = self._shopping_list_recipe.entries.filter(ingredient__in=ingredients).values_list('ingredient__pk', flat=True) + add_ingredients = ingredients.exclude(id__in=existing) - # return all shopping list items - return list_recipe + for i in [x for x in add_ingredients if x.food]: + ShoppingListEntry.objects.create( + list_recipe=self._shopping_list_recipe, + food=i.food, + unit=i.unit, + ingredient=i, + amount=i.amount * Decimal(self._servings_factor), + created_by=self.created_by, + space=self.space, + ) + + # deletes shopping list entries not in ingredients list + def _delete_ingredients(self, ingredients=None): + if not ingredients: + return + to_delete = self._shopping_list_recipe.entries.exclude(ingredient__in=ingredients) + ShoppingListEntry.objects.filter(id__in=to_delete).delete() + self._shopping_list_recipe = self.get_shopping_list_recipe(self.id, self.created_by, self.space) + + +# # TODO refactor as class +# def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None, ingredients=None, created_by=None, space=None, append=False): +# """ +# Creates ShoppingListRecipe and associated ShoppingListEntrys from a recipe or a meal plan with a recipe +# :param list_recipe: Modify an existing ShoppingListRecipe +# :param recipe: Recipe to use as list of ingredients. One of [recipe, mealplan] are required +# :param mealplan: alternatively use a mealplan recipe as source of ingredients +# :param servings: Optional: Number of servings to use to scale shoppinglist. If servings = 0 an existing recipe list will be deleted +# :param ingredients: Ingredients, list of ingredient IDs to include on the shopping list. When not provided all ingredients will be used +# :param append: If False will remove any entries not included with ingredients, when True will append ingredients to the shopping list +# """ +# r = recipe or getattr(mealplan, 'recipe', None) or getattr(list_recipe, 'recipe', None) +# if not r: +# raise ValueError(_("You must supply a recipe or mealplan")) + +# created_by = created_by or getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', None) +# if not created_by: +# raise ValueError(_("You must supply a created_by")) + +# try: +# servings = float(servings) +# except (ValueError, TypeError): +# servings = getattr(mealplan, 'servings', 1.0) + +# servings_factor = servings / r.servings + +# shared_users = list(created_by.get_shopping_share()) +# shared_users.append(created_by) +# if list_recipe: +# created = False +# else: +# list_recipe = ShoppingListRecipe.objects.create(recipe=r, mealplan=mealplan, servings=servings) +# created = True + +# related_step_ing = [] +# if servings == 0 and not created: +# list_recipe.delete() +# return [] +# elif ingredients: +# ingredients = Ingredient.objects.filter(pk__in=ingredients, space=space) +# else: +# ingredients = Ingredient.objects.filter(step__recipe=r, food__ignore_shopping=False, space=space) + +# if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand: +# ingredients = ingredients.exclude(food__onhand_users__id__in=[x.id for x in shared_users]) + +# if related := created_by.userpreference.mealplan_autoinclude_related: +# # TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans +# related_recipes = r.get_related_recipes() + +# for x in related_recipes: +# # related recipe is a Step serving size is driven by recipe serving size +# # TODO once/if Steps can have a serving size this needs to be refactored +# if exclude_onhand: +# # if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior +# related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users]).values_list('id', flat=True) +# else: +# related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True) + +# x_ing = [] +# if ingredients.filter(food__recipe=x).exists(): +# for ing in ingredients.filter(food__recipe=x): +# if exclude_onhand: +# x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__onhand_users__id__in=[x.id for x in shared_users]) +# else: +# x_ing = Ingredient.objects.filter(step__recipe=x, food__ignore_shopping=False, space=space).exclude(food__ignore_shopping=True) +# for i in [x for x in x_ing]: +# ShoppingListEntry.objects.create( +# list_recipe=list_recipe, +# food=i.food, +# unit=i.unit, +# ingredient=i, +# amount=i.amount * Decimal(servings_factor), +# created_by=created_by, +# space=space, +# ) +# # dont' add food to the shopping list that are actually recipes that will be added as ingredients +# ingredients = ingredients.exclude(food__recipe=x) + +# add_ingredients = list(ingredients.values_list('id', flat=True)) + related_step_ing +# if not append: +# existing_list = ShoppingListEntry.objects.filter(list_recipe=list_recipe) +# # delete shopping list entries not included in ingredients +# existing_list.exclude(ingredient__in=ingredients).delete() +# # add shopping list entries that did not previously exist +# add_ingredients = set(add_ingredients) - set(existing_list.values_list('ingredient__id', flat=True)) +# add_ingredients = Ingredient.objects.filter(id__in=add_ingredients, space=space) + +# # if servings have changed, update the ShoppingListRecipe and existing Entries +# if servings <= 0: +# servings = 1 + +# if not created and list_recipe.servings != servings: +# update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True)) +# list_recipe.servings = servings +# list_recipe.save() +# for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients): +# sle.amount = sle.ingredient.amount * Decimal(servings_factor) +# sle.save() + +# # add any missing Entries +# for i in [x for x in add_ingredients if x.food]: + +# ShoppingListEntry.objects.create( +# list_recipe=list_recipe, +# food=i.food, +# unit=i.unit, +# ingredient=i, +# amount=i.amount * Decimal(servings_factor), +# created_by=created_by, +# space=space, +# ) + +# # return all shopping list items +# return list_recipe diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 8a5212cd..baf77d05 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -13,7 +13,7 @@ from rest_framework.exceptions import NotFound, ValidationError from rest_framework.fields import empty from cookbook.helper.HelperFunctions import str2bool -from cookbook.helper.shopping_helper import list_from_recipe +from cookbook.helper.shopping_helper import RecipeShoppingEditor from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Food, FoodInheritField, ImportLog, Ingredient, Keyword, MealPlan, MealType, NutritionInformation, Recipe, RecipeBook, RecipeBookEntry, @@ -660,7 +660,8 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer): validated_data['created_by'] = self.context['request'].user mealplan = super().create(validated_data) if self.context['request'].data.get('addshopping', False): - list_from_recipe(mealplan=mealplan, servings=validated_data['servings'], created_by=validated_data['created_by'], space=validated_data['space']) + SLR = RecipeShoppingEditor(user=validated_data['created_by'], space=validated_data['space']) + SLR.create(mealplan=mealplan, servings=validated_data['servings']) return mealplan class Meta: @@ -694,12 +695,8 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer): def update(self, instance, validated_data): # TODO remove once old shopping list if 'servings' in validated_data and self.context.get('view', None).__class__.__name__ != 'ShoppingListViewSet': - list_from_recipe( - list_recipe=instance, - servings=validated_data['servings'], - created_by=self.context['request'].user, - space=self.context['request'].space - ) + SLR = RecipeShoppingEditor(user=self.context['request'].user, space=self.context['request'].space) + SLR.edit_servings(servings=validated_data['servings'], id=instance.id) return super().update(instance, validated_data) class Meta: diff --git a/cookbook/signals.py b/cookbook/signals.py index b4a52874..17a3da86 100644 --- a/cookbook/signals.py +++ b/cookbook/signals.py @@ -6,8 +6,9 @@ from django.contrib.postgres.search import SearchVector from django.db.models.signals import post_save from django.dispatch import receiver from django.utils import translation +from django_scopes import scope -from cookbook.helper.shopping_helper import list_from_recipe +from cookbook.helper.shopping_helper import RecipeShoppingEditor from cookbook.managers import DICTIONARY from cookbook.models import (Food, FoodInheritField, Ingredient, MealPlan, Recipe, ShoppingListEntry, Step) @@ -104,20 +105,31 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs): @receiver(post_save, sender=MealPlan) def auto_add_shopping(sender, instance=None, created=False, weak=False, **kwargs): + if not instance: + return user = instance.get_owner() - if not user.userpreference.mealplan_autoadd_shopping: + with scope(space=instance.space): + slr_exists = instance.shoppinglistrecipe_set.exists() + + if not created and slr_exists: + for x in instance.shoppinglistrecipe_set.all(): + # assuming that permissions checks for the MealPlan have happened upstream + if instance.servings != x.servings: + SLR = RecipeShoppingEditor(id=x.id, user=user, space=instance.space) + SLR.edit_servings(servings=instance.servings) + # list_recipe = list_from_recipe(list_recipe=x, servings=instance.servings, space=instance.space) + elif not user.userpreference.mealplan_autoadd_shopping or not instance.recipe: return - if not created and instance.shoppinglistrecipe_set.exists(): - for x in instance.shoppinglistrecipe_set.all(): - if instance.servings != x.servings: - list_recipe = list_from_recipe(list_recipe=x, servings=instance.servings, space=instance.space) - elif created: + if created: # if creating a mealplan - perform shopping list activities - kwargs = { - 'mealplan': instance, - 'space': instance.space, - 'created_by': user, - 'servings': instance.servings - } - list_recipe = list_from_recipe(**kwargs) + # kwargs = { + # 'mealplan': instance, + # 'space': instance.space, + # 'created_by': user, + # 'servings': instance.servings + # } + SLR = RecipeShoppingEditor(user=user, space=instance.space) + SLR.create(mealplan=instance, servings=instance.servings) + + # list_recipe = list_from_recipe(**kwargs) diff --git a/cookbook/tests/api/test_api_shopping_recipe.py b/cookbook/tests/api/test_api_shopping_recipe.py index b32f2872..0fc85d86 100644 --- a/cookbook/tests/api/test_api_shopping_recipe.py +++ b/cookbook/tests/api/test_api_shopping_recipe.py @@ -164,7 +164,7 @@ def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u assert len(r) == sle_count assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count - # test removing 2 items from shopping list + # test removing 3 items from shopping list u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}), {'list_recipe': list_recipe, 'ingredients': keep_ing}, content_type='application/json' diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 9197f53e..8b6636ed 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -41,7 +41,7 @@ from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, Cus from cookbook.helper.recipe_html_import import get_recipe_from_source from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch, old_search from cookbook.helper.recipe_url_import import get_from_scraper -from cookbook.helper.shopping_helper import list_from_recipe, shopping_helper +from cookbook.helper.shopping_helper import RecipeShoppingEditor, shopping_helper from cookbook.models import (Automation, BookmarkletImport, CookLog, Food, FoodInheritField, ImportLog, Ingredient, Keyword, MealPlan, MealType, Recipe, RecipeBook, RecipeBookEntry, ShareLink, ShoppingList, ShoppingListEntry, @@ -717,16 +717,26 @@ class RecipeViewSet(viewsets.ModelViewSet): obj = self.get_object() ingredients = request.data.get('ingredients', None) servings = request.data.get('servings', None) - list_recipe = ShoppingListRecipe.objects.filter(id=request.data.get('list_recipe', None)).first() - if servings is None: - servings = getattr(list_recipe, 'servings', obj.servings) - # created_by needs to be sticky to original creator as it is 'their' shopping list - # changing shopping list created_by can shift some items to new owner which may not share in the other direction - created_by = getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', request.user) - content = {'msg': _(f'{obj.name} was added to the shopping list.')} - list_from_recipe(list_recipe=list_recipe, recipe=obj, ingredients=ingredients, servings=servings, space=request.space, created_by=created_by) + list_recipe = request.data.get('list_recipe', None) + SLR = RecipeShoppingEditor(request.user, request.space, id=list_recipe, recipe=obj) - return Response(content, status=status.HTTP_204_NO_CONTENT) + content = {'msg': _(f'{obj.name} was added to the shopping list.')} + http_status = status.HTTP_204_NO_CONTENT + if servings and servings <= 0: + result = SLR.delete() + elif list_recipe: + result = SLR.edit(servings=servings, ingredients=ingredients) + else: + result = SLR.create(servings=servings, ingredients=ingredients) + + if not result: + content = {'msg': ('An error occurred')} + http_status = status.HTTP_500_INTERNAL_SERVER_ERROR + else: + content = {'msg': _(f'{obj.name} was added to the shopping list.')} + http_status = status.HTTP_204_NO_CONTENT + + return Response(content, status=http_status) @decorators.action( detail=True, diff --git a/vue/src/apps/MealPlanView/MealPlanView.vue b/vue/src/apps/MealPlanView/MealPlanView.vue index d45fb075..9b0d59b8 100644 --- a/vue/src/apps/MealPlanView/MealPlanView.vue +++ b/vue/src/apps/MealPlanView/MealPlanView.vue @@ -54,20 +54,14 @@
{{ $t("Planner_Settings") }}
- - + + - - + + - - + + @@ -80,23 +74,18 @@
{{ $t("Meal_Types") }}
- +
- +
- {{ meal_type.icon }} {{ - meal_type.name - }} + {{ meal_type.icon }} {{ meal_type.name + }}
@@ -104,26 +93,19 @@
- +
- +
- +
- + {{ $t("Default") }} - + @@ -147,15 +129,16 @@ openEntryEdit(contextData.originalItem.entry) " > - {{ - $t("Edit") - }} + {{ $t("Edit") }} - - {{ $t("Recipe") }} + v-if="contextData && contextData.originalItem && contextData.originalItem.entry.recipe != null" + @click=" + $refs.menu.close() + openRecipe(contextData.originalItem.entry.recipe) + " + > + {{ $t("Recipe") }} - - {{ $t("Move") }} + {{ $t("Move") }} - - {{ $t("Move") }} + {{ $t("Move") }} - - {{ $t("Add_to_Shopping") }} + {{ $t("Add_to_Shopping") }} - - {{ $t("Delete") }} + {{ $t("Delete") }} + > {{ $t("Open") }} - + {{ $t("Clear") }} @@ -243,46 +221,37 @@
-
+
- +
- +
-
- + - + - +
@@ -293,7 +262,7 @@ diff --git a/vue/src/components/IngredientsCard.vue b/vue/src/components/IngredientsCard.vue index dc7a67af..7da91e73 100644 --- a/vue/src/components/IngredientsCard.vue +++ b/vue/src/components/IngredientsCard.vue @@ -146,7 +146,7 @@ export default { saveShopping: function (del_shopping = false) { let servings = this.servings if (del_shopping) { - servings = 0 + servings = -1 } let params = { id: this.recipe, diff --git a/vue/src/components/MealPlanEditModal.vue b/vue/src/components/MealPlanEditModal.vue index 78e875ac..6c3eea6c 100644 --- a/vue/src/components/MealPlanEditModal.vue +++ b/vue/src/components/MealPlanEditModal.vue @@ -25,7 +25,7 @@
- - +
@@ -113,8 +112,6 @@ export default { name: "MealPlanEditModal", props: { entry: Object, - entryEditing_initial_recipe: Array, - entryEditing_initial_meal_type: Array, entryEditing_inital_servings: Number, modal_title: String, modal_id: { @@ -130,7 +127,6 @@ export default { components: { GenericMultiselect, RecipeCard: () => import("@/components/RecipeCard.vue"), - IngredientsCard: () => import("@/components/IngredientsCard.vue"), }, data() { return { @@ -144,12 +140,20 @@ export default { entry: { handler() { this.entryEditing = Object.assign({}, this.entry) + console.log("entryEditing", this.entryEditing) if (this.entryEditing_inital_servings) { this.entryEditing.servings = this.entryEditing_inital_servings } }, deep: true, }, + entryEditing: { + handler(newVal) {}, + deep: true, + }, + entryEditing_inital_servings: function (newVal) { + this.entryEditing.servings = newVal + }, }, mounted: function () {}, computed: { diff --git a/vue/src/components/Modals/ShoppingModal.vue b/vue/src/components/Modals/ShoppingModal.vue index e59eb21d..e0c17ec5 100644 --- a/vue/src/components/Modals/ShoppingModal.vue +++ b/vue/src/components/Modals/ShoppingModal.vue @@ -106,7 +106,6 @@ export default { deep: true, }, servings: function (newVal) { - console.log(newVal) this.recipe_servings = parseInt(newVal) }, }, diff --git a/vue/src/components/RecipeContextMenu.vue b/vue/src/components/RecipeContextMenu.vue index e0a77f7a..c7d34660 100644 --- a/vue/src/components/RecipeContextMenu.vue +++ b/vue/src/components/RecipeContextMenu.vue @@ -64,8 +64,8 @@