refactor list_from_recipe as class RecipeShoppingEditor

This commit is contained in:
Chris Scoggins 2022-01-29 10:28:01 -06:00
parent 85bbcb0010
commit e2f8f29ec8
No known key found for this signature in database
GPG Key ID: 41617A4206CCBAC6
11 changed files with 403 additions and 244 deletions

View File

@ -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') 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 class RecipeShoppingEditor():
def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None, ingredients=None, created_by=None, space=None, append=False): def __init__(self, user, space, **kwargs):
""" self.created_by = user
Creates ShoppingListRecipe and associated ShoppingListEntrys from a recipe or a meal plan with a recipe self.space = space
:param list_recipe: Modify an existing ShoppingListRecipe self._kwargs = {**kwargs}
: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) self.mealplan = self._kwargs.get('mealplan', None)
if not created_by: self.id = self._kwargs.get('id', None)
raise ValueError(_("You must supply a created_by"))
try: self._shopping_list_recipe = self.get_shopping_list_recipe(self.id, self.created_by, self.space)
servings = float(servings)
except (ValueError, TypeError):
servings = getattr(mealplan, 'servings', 1.0)
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()) self.recipe = getattr(self._shopping_list_recipe, 'recipe', None) or self._kwargs.get('recipe', None) or getattr(self.mealplan, 'recipe', None)
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 = [] try:
if servings == 0 and not created: self.servings = float(self._kwargs.get('servings', None))
list_recipe.delete() except (ValueError, TypeError):
return [] self.servings = getattr(self._shopping_list_recipe, 'servings', None) or getattr(self.mealplan, 'servings', None) or getattr(self.recipe, 'servings', None)
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: @property
ingredients = ingredients.exclude(food__onhand_users__id__in=[x.id for x in shared_users]) def _servings_factor(self):
return self.servings / self.recipe.servings
if related := created_by.userpreference.mealplan_autoinclude_related: @property
# TODO: add levels of related recipes (related recipes of related recipes) to use when auto-adding mealplans def _shared_users(self):
related_recipes = r.get_related_recipes() return [*list(self.created_by.get_shopping_share()), self.created_by]
for x in related_recipes: @staticmethod
# related recipe is a Step serving size is driven by recipe serving size def get_shopping_list_recipe(id, user, space):
# TODO once/if Steps can have a serving size this needs to be refactored return ShoppingListRecipe.objects.filter(id=id).filter(Q(shoppinglist__space=space) | Q(entries__space=space)).filter(
if exclude_onhand: Q(shoppinglist__created_by=user)
# if steps are used more than once in a recipe or subrecipe - I don' think this results in the desired behavior | Q(shoppinglist__shared=user)
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) | Q(entries__created_by=user)
else: | Q(entries__created_by__in=list(user.get_shopping_share()))
related_step_ing += Ingredient.objects.filter(step__recipe=x, space=space).values_list('id', flat=True) ).prefetch_related('entries').first()
x_ing = [] def get_recipe_ingredients(self, id, exclude_onhand=False):
if ingredients.filter(food__recipe=x).exists(): if exclude_onhand:
for ing in ingredients.filter(food__recipe=x): 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])
if exclude_onhand: else:
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]) return Ingredient.objects.filter(step__recipe__id=id, food__ignore_shopping=False, space=self.space)
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 @property
if not append: def _include_related(self):
existing_list = ShoppingListEntry.objects.filter(list_recipe=list_recipe) return self.created_by.userpreference.mealplan_autoinclude_related
# 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 @property
if servings <= 0: def _exclude_onhand(self):
servings = 1 return self.created_by.userpreference.mealplan_autoexclude_onhand
if not created and list_recipe.servings != servings: def create(self, **kwargs):
update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True)) ingredients = kwargs.get('ingredients', None)
list_recipe.servings = servings exclude_onhand = not ingredients and self._exclude_onhand
list_recipe.save() if servings := kwargs.get('servings', None):
for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients): self.servings = float(servings)
sle.amount = sle.ingredient.amount * Decimal(servings_factor)
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() sle.save()
self._shopping_list_recipe.servings = self.servings
self._shopping_list_recipe.save()
return True
# add any missing Entries def delete(self, **kwargs):
for i in [x for x in add_ingredients if x.food]: try:
self._shopping_list_recipe.delete()
return True
except:
return False
ShoppingListEntry.objects.create( def _add_ingredients(self, ingredients=None):
list_recipe=list_recipe, if not ingredients:
food=i.food, return
unit=i.unit, elif type(ingredients) == list:
ingredient=i, ingredients = Ingredient.objects.filter(id__in=ingredients)
amount=i.amount * Decimal(servings_factor), existing = self._shopping_list_recipe.entries.filter(ingredient__in=ingredients).values_list('ingredient__pk', flat=True)
created_by=created_by, add_ingredients = ingredients.exclude(id__in=existing)
space=space,
)
# return all shopping list items for i in [x for x in add_ingredients if x.food]:
return list_recipe 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

View File

@ -13,7 +13,7 @@ from rest_framework.exceptions import NotFound, ValidationError
from rest_framework.fields import empty from rest_framework.fields import empty
from cookbook.helper.HelperFunctions import str2bool 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, from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Food,
FoodInheritField, ImportLog, Ingredient, Keyword, MealPlan, MealType, FoodInheritField, ImportLog, Ingredient, Keyword, MealPlan, MealType,
NutritionInformation, Recipe, RecipeBook, RecipeBookEntry, NutritionInformation, Recipe, RecipeBook, RecipeBookEntry,
@ -660,7 +660,8 @@ class MealPlanSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
validated_data['created_by'] = self.context['request'].user validated_data['created_by'] = self.context['request'].user
mealplan = super().create(validated_data) mealplan = super().create(validated_data)
if self.context['request'].data.get('addshopping', False): 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 return mealplan
class Meta: class Meta:
@ -694,12 +695,8 @@ class ShoppingListRecipeSerializer(serializers.ModelSerializer):
def update(self, instance, validated_data): def update(self, instance, validated_data):
# TODO remove once old shopping list # TODO remove once old shopping list
if 'servings' in validated_data and self.context.get('view', None).__class__.__name__ != 'ShoppingListViewSet': if 'servings' in validated_data and self.context.get('view', None).__class__.__name__ != 'ShoppingListViewSet':
list_from_recipe( SLR = RecipeShoppingEditor(user=self.context['request'].user, space=self.context['request'].space)
list_recipe=instance, SLR.edit_servings(servings=validated_data['servings'], id=instance.id)
servings=validated_data['servings'],
created_by=self.context['request'].user,
space=self.context['request'].space
)
return super().update(instance, validated_data) return super().update(instance, validated_data)
class Meta: class Meta:

View File

@ -6,8 +6,9 @@ from django.contrib.postgres.search import SearchVector
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from django.utils import translation 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.managers import DICTIONARY
from cookbook.models import (Food, FoodInheritField, Ingredient, MealPlan, Recipe, from cookbook.models import (Food, FoodInheritField, Ingredient, MealPlan, Recipe,
ShoppingListEntry, Step) ShoppingListEntry, Step)
@ -104,20 +105,31 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
@receiver(post_save, sender=MealPlan) @receiver(post_save, sender=MealPlan)
def auto_add_shopping(sender, instance=None, created=False, weak=False, **kwargs): def auto_add_shopping(sender, instance=None, created=False, weak=False, **kwargs):
if not instance:
return
user = instance.get_owner() 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 return
if not created and instance.shoppinglistrecipe_set.exists(): if created:
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 creating a mealplan - perform shopping list activities # if creating a mealplan - perform shopping list activities
kwargs = { # kwargs = {
'mealplan': instance, # 'mealplan': instance,
'space': instance.space, # 'space': instance.space,
'created_by': user, # 'created_by': user,
'servings': instance.servings # 'servings': instance.servings
} # }
list_recipe = list_from_recipe(**kwargs) SLR = RecipeShoppingEditor(user=user, space=instance.space)
SLR.create(mealplan=instance, servings=instance.servings)
# list_recipe = list_from_recipe(**kwargs)

View File

@ -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(r) == sle_count
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == 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}), u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
{'list_recipe': list_recipe, 'ingredients': keep_ing}, {'list_recipe': list_recipe, 'ingredients': keep_ing},
content_type='application/json' content_type='application/json'

View File

@ -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_html_import import get_recipe_from_source
from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch, old_search from cookbook.helper.recipe_search import RecipeFacet, RecipeSearch, old_search
from cookbook.helper.recipe_url_import import get_from_scraper 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, from cookbook.models import (Automation, BookmarkletImport, CookLog, Food, FoodInheritField,
ImportLog, Ingredient, Keyword, MealPlan, MealType, Recipe, RecipeBook, ImportLog, Ingredient, Keyword, MealPlan, MealType, Recipe, RecipeBook,
RecipeBookEntry, ShareLink, ShoppingList, ShoppingListEntry, RecipeBookEntry, ShareLink, ShoppingList, ShoppingListEntry,
@ -717,16 +717,26 @@ class RecipeViewSet(viewsets.ModelViewSet):
obj = self.get_object() obj = self.get_object()
ingredients = request.data.get('ingredients', None) ingredients = request.data.get('ingredients', None)
servings = request.data.get('servings', None) servings = request.data.get('servings', None)
list_recipe = ShoppingListRecipe.objects.filter(id=request.data.get('list_recipe', None)).first() list_recipe = request.data.get('list_recipe', None)
if servings is None: SLR = RecipeShoppingEditor(request.user, request.space, id=list_recipe, recipe=obj)
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)
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( @decorators.action(
detail=True, detail=True,

View File

@ -54,20 +54,14 @@
<div class="col-12 col-md-3 calender-options"> <div class="col-12 col-md-3 calender-options">
<h5>{{ $t("Planner_Settings") }}</h5> <h5>{{ $t("Planner_Settings") }}</h5>
<b-form> <b-form>
<b-form-group id="UomInput" :label="$t('Period')" :description="$t('Plan_Period_To_Show')" <b-form-group id="UomInput" :label="$t('Period')" :description="$t('Plan_Period_To_Show')" label-for="UomInput">
label-for="UomInput"> <b-form-select id="UomInput" v-model="settings.displayPeriodUom" :options="options.displayPeriodUom"></b-form-select>
<b-form-select id="UomInput" v-model="settings.displayPeriodUom"
:options="options.displayPeriodUom"></b-form-select>
</b-form-group> </b-form-group>
<b-form-group id="PeriodInput" :label="$t('Periods')" <b-form-group id="PeriodInput" :label="$t('Periods')" :description="$t('Plan_Show_How_Many_Periods')" label-for="PeriodInput">
:description="$t('Plan_Show_How_Many_Periods')" label-for="PeriodInput"> <b-form-select id="PeriodInput" v-model="settings.displayPeriodCount" :options="options.displayPeriodCount"></b-form-select>
<b-form-select id="PeriodInput" v-model="settings.displayPeriodCount"
:options="options.displayPeriodCount"></b-form-select>
</b-form-group> </b-form-group>
<b-form-group id="DaysInput" :label="$t('Starting_Day')" :description="$t('Starting_Day')" <b-form-group id="DaysInput" :label="$t('Starting_Day')" :description="$t('Starting_Day')" label-for="DaysInput">
label-for="DaysInput"> <b-form-select id="DaysInput" v-model="settings.startingDayOfWeek" :options="dayNames"></b-form-select>
<b-form-select id="DaysInput" v-model="settings.startingDayOfWeek"
:options="dayNames"></b-form-select>
</b-form-group> </b-form-group>
<b-form-group id="WeekNumInput" :label="$t('Week_Numbers')"> <b-form-group id="WeekNumInput" :label="$t('Week_Numbers')">
<b-form-checkbox v-model="settings.displayWeekNumbers" name="week_num"> <b-form-checkbox v-model="settings.displayWeekNumbers" name="week_num">
@ -80,23 +74,18 @@
<h5>{{ $t("Meal_Types") }}</h5> <h5>{{ $t("Meal_Types") }}</h5>
<div> <div>
<draggable :list="meal_types" group="meal_types" :empty-insert-threshold="10" @sort="sortMealTypes()" ghost-class="ghost"> <draggable :list="meal_types" group="meal_types" :empty-insert-threshold="10" @sort="sortMealTypes()" ghost-class="ghost">
<b-card no-body class="mt-1 list-group-item p-2" style="cursor:move" v-for="(meal_type, index) in meal_types" v-hover <b-card no-body class="mt-1 list-group-item p-2" style="cursor: move" v-for="(meal_type, index) in meal_types" v-hover :key="meal_type.id">
:key="meal_type.id">
<b-card-header class="p-2 border-0"> <b-card-header class="p-2 border-0">
<div class="row"> <div class="row">
<div class="col-2"> <div class="col-2">
<button type="button" class="btn btn-lg shadow-none"><i <button type="button" class="btn btn-lg shadow-none"><i class="fas fa-arrows-alt-v"></i></button>
class="fas fa-arrows-alt-v"></i></button>
</div> </div>
<div class="col-10"> <div class="col-10">
<h5 class="mt-1 mb-1"> <h5 class="mt-1 mb-1">
{{ meal_type.icon }} {{ {{ meal_type.icon }} {{ meal_type.name
meal_type.name }}<span class="float-right text-primary" style="cursor: pointer"
}}<span class="float-right text-primary" style="cursor:pointer" ><i class="fa" v-bind:class="{ 'fa-pen': !meal_type.editing, 'fa-save': meal_type.editing }" @click="editOrSaveMealType(index)" aria-hidden="true"></i
><i class="fa" ></span>
v-bind:class="{ 'fa-pen': !meal_type.editing, 'fa-save': meal_type.editing }"
@click="editOrSaveMealType(index)" aria-hidden="true"></i
></span>
</h5> </h5>
</div> </div>
</div> </div>
@ -104,26 +93,19 @@
<b-card-body class="p-4" v-if="meal_type.editing"> <b-card-body class="p-4" v-if="meal_type.editing">
<div class="form-group"> <div class="form-group">
<label>{{ $t("Name") }}</label> <label>{{ $t("Name") }}</label>
<input class="form-control" placeholder="Name" v-model="meal_type.name"/> <input class="form-control" placeholder="Name" v-model="meal_type.name" />
</div> </div>
<div class="form-group"> <div class="form-group">
<emoji-input :field="'icon'" :label="$t('Icon')" <emoji-input :field="'icon'" :label="$t('Icon')" :value="meal_type.icon"></emoji-input>
:value="meal_type.icon"></emoji-input>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>{{ $t("Color") }}</label> <label>{{ $t("Color") }}</label>
<input class="form-control" type="color" name="Name" <input class="form-control" type="color" name="Name" :value="meal_type.color" @change="meal_type.color = $event.target.value" />
:value="meal_type.color"
@change="meal_type.color = $event.target.value"/>
</div> </div>
<b-form-checkbox id="checkbox-1" v-model="meal_type.default" <b-form-checkbox id="checkbox-1" v-model="meal_type.default" name="default_checkbox" class="mb-2">
name="default_checkbox" class="mb-2">
{{ $t("Default") }} {{ $t("Default") }}
</b-form-checkbox> </b-form-checkbox>
<button class="btn btn-danger" @click="deleteMealType(index)">{{ <button class="btn btn-danger" @click="deleteMealType(index)">{{ $t("Delete") }}</button>
$t("Delete")
}}
</button>
<button class="btn btn-primary float-right" @click="editOrSaveMealType(index)"> <button class="btn btn-primary float-right" @click="editOrSaveMealType(index)">
{{ $t("Save") }} {{ $t("Save") }}
</button> </button>
@ -147,15 +129,16 @@
openEntryEdit(contextData.originalItem.entry) openEntryEdit(contextData.originalItem.entry)
" "
> >
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-pen"></i> {{ <a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-pen"></i> {{ $t("Edit") }}</a>
$t("Edit")
}}</a>
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem <ContextMenuItem
v-if="contextData.originalItem.entry.recipe != null" v-if="contextData && contextData.originalItem && contextData.originalItem.entry.recipe != null"
@click="$refs.menu.close();openRecipe(contextData.originalItem.entry.recipe)"> @click="
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-pizza-slice"></i> $refs.menu.close()
{{ $t("Recipe") }}</a> openRecipe(contextData.originalItem.entry.recipe)
"
>
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-pizza-slice"></i> {{ $t("Recipe") }}</a>
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem <ContextMenuItem
@click=" @click="
@ -163,8 +146,7 @@
moveEntryLeft(contextData) moveEntryLeft(contextData)
" "
> >
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-arrow-left"></i> <a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-arrow-left"></i> {{ $t("Move") }}</a>
{{ $t("Move") }}</a>
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem <ContextMenuItem
@click=" @click="
@ -172,8 +154,7 @@
moveEntryRight(contextData) moveEntryRight(contextData)
" "
> >
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-arrow-right"></i> <a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-arrow-right"></i> {{ $t("Move") }}</a>
{{ $t("Move") }}</a>
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem <ContextMenuItem
@click=" @click="
@ -189,8 +170,7 @@
addToShopping(contextData) addToShopping(contextData)
" "
> >
<a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-shopping-cart"></i> <a class="dropdown-item p-2" href="javascript:void(0)"><i class="fas fa-shopping-cart"></i> {{ $t("Add_to_Shopping") }}</a>
{{ $t("Add_to_Shopping") }}</a>
</ContextMenuItem> </ContextMenuItem>
<ContextMenuItem <ContextMenuItem
@click=" @click="
@ -198,15 +178,12 @@
deleteEntry(contextData) deleteEntry(contextData)
" "
> >
<a class="dropdown-item p-2 text-danger" href="javascript:void(0)"><i class="fas fa-trash"></i> <a class="dropdown-item p-2 text-danger" href="javascript:void(0)"><i class="fas fa-trash"></i> {{ $t("Delete") }}</a>
{{ $t("Delete") }}</a>
</ContextMenuItem> </ContextMenuItem>
</template> </template>
</ContextMenu> </ContextMenu>
<meal-plan-edit-modal <meal-plan-edit-modal
:entry="entryEditing" :entry="entryEditing"
:entryEditing_initial_recipe="entryEditing_initial_recipe"
:entry-editing_initial_meal_type="entryEditing_initial_meal_type"
:modal_title="modal_title" :modal_title="modal_title"
:edit_modal_show="edit_modal_show" :edit_modal_show="edit_modal_show"
@save-entry="editEntry" @save-entry="editEntry"
@ -230,10 +207,11 @@
<div class="col-12 mt-1" v-if="shopping_list.length > 0"> <div class="col-12 mt-1" v-if="shopping_list.length > 0">
<b-button-group> <b-button-group>
<b-button variant="success" @click="saveShoppingList" <b-button variant="success" @click="saveShoppingList"
><i class="fas fa-external-link-alt"></i> ><i class="fas fa-external-link-alt"></i>
{{ $t("Open") }} {{ $t("Open") }}
</b-button> </b-button>
<b-button variant="danger" @click="shopping_list = []"><i class="fa fa-trash"></i> <b-button variant="danger" @click="shopping_list = []"
><i class="fa fa-trash"></i>
{{ $t("Clear") }} {{ $t("Clear") }}
</b-button> </b-button>
</b-button-group> </b-button-group>
@ -243,46 +221,37 @@
</div> </div>
</template> </template>
<transition name="slide-fade"> <transition name="slide-fade">
<div class="row fixed-bottom p-2 b-1 border-top text-center" style="background: rgba(255, 255, 255, 0.6)" <div class="row fixed-bottom p-2 b-1 border-top text-center" style="background: rgba(255, 255, 255, 0.6)" v-if="current_tab === 0">
v-if="current_tab === 0">
<div class="col-md-3 col-6"> <div class="col-md-3 col-6">
<button class="btn btn-block btn-success shadow-none" @click="createEntryClick(new Date())"><i <button class="btn btn-block btn-success shadow-none" @click="createEntryClick(new Date())"><i class="fas fa-calendar-plus"></i> {{ $t("Create") }}</button>
class="fas fa-calendar-plus"></i> {{ $t("Create") }}
</button>
</div> </div>
<div class="col-md-3 col-6"> <div class="col-md-3 col-6">
<button class="btn btn-block btn-primary shadow-none" v-b-toggle.sidebar-shopping><i <button class="btn btn-block btn-primary shadow-none" v-b-toggle.sidebar-shopping><i class="fas fa-shopping-cart"></i> {{ $t("Shopping_list") }}</button>
class="fas fa-shopping-cart"></i> {{ $t("Shopping_list") }}
</button>
</div> </div>
<div class="col-md-3 col-6"> <div class="col-md-3 col-6">
<a class="btn btn-block btn-primary shadow-none" :href="iCalUrl" <a class="btn btn-block btn-primary shadow-none" :href="iCalUrl"
><i class="fas fa-download"></i> ><i class="fas fa-download"></i>
{{ $t("Export_To_ICal") }} {{ $t("Export_To_ICal") }}
</a> </a>
</div> </div>
<div class="col-md-3 col-6"> <div class="col-md-3 col-6">
<button class="btn btn-block btn-primary shadow-none disabled" v-b-tooltip.focus.top <button class="btn btn-block btn-primary shadow-none disabled" v-b-tooltip.focus.top :title="$t('Coming_Soon')">
:title="$t('Coming_Soon')">
{{ $t("Auto_Planner") }} {{ $t("Auto_Planner") }}
</button> </button>
</div> </div>
<div class="col-12 d-flex justify-content-center mt-2 d-block d-md-none"> <div class="col-12 d-flex justify-content-center mt-2 d-block d-md-none">
<b-button-toolbar key-nav aria-label="Toolbar with button groups"> <b-button-toolbar key-nav aria-label="Toolbar with button groups">
<b-button-group class="mx-1"> <b-button-group class="mx-1">
<b-button v-html="'<<'" <b-button v-html="'<<'" @click="setShowDate($refs.header.headerProps.previousPeriod)"></b-button>
@click="setShowDate($refs.header.headerProps.previousPeriod)"></b-button>
<b-button v-html="'<'" @click="setStartingDay(-1)"></b-button> <b-button v-html="'<'" @click="setStartingDay(-1)"></b-button>
</b-button-group> </b-button-group>
<b-button-group class="mx-1"> <b-button-group class="mx-1">
<b-button @click="setShowDate($refs.header.headerProps.currentPeriod)"><i <b-button @click="setShowDate($refs.header.headerProps.currentPeriod)"><i class="fas fa-home"></i></b-button>
class="fas fa-home"></i></b-button>
<b-form-datepicker button-only button-variant="secondary"></b-form-datepicker> <b-form-datepicker button-only button-variant="secondary"></b-form-datepicker>
</b-button-group> </b-button-group>
<b-button-group class="mx-1"> <b-button-group class="mx-1">
<b-button v-html="'>'" @click="setStartingDay(1)"></b-button> <b-button v-html="'>'" @click="setStartingDay(1)"></b-button>
<b-button v-html="'>>'" <b-button v-html="'>>'" @click="setShowDate($refs.header.headerProps.nextPeriod)"></b-button>
@click="setShowDate($refs.header.headerProps.nextPeriod)"></b-button>
</b-button-group> </b-button-group>
</b-button-toolbar> </b-button-toolbar>
</div> </div>
@ -293,7 +262,7 @@
<script> <script>
import Vue from "vue" import Vue from "vue"
import {BootstrapVue} from "bootstrap-vue" import { BootstrapVue } from "bootstrap-vue"
import "bootstrap-vue/dist/bootstrap-vue.css" import "bootstrap-vue/dist/bootstrap-vue.css"
import ContextMenu from "@/components/ContextMenu/ContextMenu" import ContextMenu from "@/components/ContextMenu/ContextMenu"
@ -307,11 +276,11 @@ import moment from "moment"
import draggable from "vuedraggable" import draggable from "vuedraggable"
import VueCookies from "vue-cookies" import VueCookies from "vue-cookies"
import {ApiMixin, StandardToasts, ResolveUrlMixin} from "@/utils/utils" import { ApiMixin, StandardToasts, ResolveUrlMixin } from "@/utils/utils"
import {CalendarView, CalendarMathMixin} from "vue-simple-calendar/src/components/bundle" import { CalendarView, CalendarMathMixin } from "vue-simple-calendar/src/components/bundle"
import {ApiApiFactory} from "@/utils/openapi/api" import { ApiApiFactory } from "@/utils/openapi/api"
const {makeToast} = require("@/utils/utils") const { makeToast } = require("@/utils/utils")
Vue.prototype.moment = moment Vue.prototype.moment = moment
Vue.use(BootstrapVue) Vue.use(BootstrapVue)
@ -349,12 +318,12 @@ export default {
current_context_menu_item: null, current_context_menu_item: null,
options: { options: {
displayPeriodUom: [ displayPeriodUom: [
{text: this.$t("Week"), value: "week"}, { text: this.$t("Week"), value: "week" },
{ {
text: this.$t("Month"), text: this.$t("Month"),
value: "month", value: "month",
}, },
{text: this.$t("Year"), value: "year"}, { text: this.$t("Year"), value: "year" },
], ],
displayPeriodCount: [1, 2, 3], displayPeriodCount: [1, 2, 3],
entryEditing: { entryEditing: {
@ -385,20 +354,6 @@ export default {
return this.$t("Edit_Meal_Plan_Entry") return this.$t("Edit_Meal_Plan_Entry")
} }
}, },
entryEditing_initial_recipe: function () {
if (this.entryEditing.recipe != null) {
return [this.entryEditing.recipe]
} else {
return []
}
},
entryEditing_initial_meal_type: function () {
if (this.entryEditing.meal_type != null) {
return [this.entryEditing.meal_type]
} else {
return []
}
},
plan_items: function () { plan_items: function () {
let items = [] let items = []
this.plan_entries.forEach((entry) => { this.plan_entries.forEach((entry) => {
@ -412,7 +367,7 @@ export default {
dayNames: function () { dayNames: function () {
let options = [] let options = []
this.getFormattedWeekdayNames(this.userLocale, "long", 0).forEach((day, index) => { this.getFormattedWeekdayNames(this.userLocale, "long", 0).forEach((day, index) => {
options.push({text: day, value: index}) options.push({ text: day, value: index })
}) })
return options return options
}, },
@ -455,7 +410,7 @@ export default {
}, },
methods: { methods: {
openRecipe: function (recipe) { openRecipe: function (recipe) {
window.open(this.resolveDjangoUrl('view_recipe', recipe.id)) window.open(this.resolveDjangoUrl("view_recipe", recipe.id))
}, },
addToShopping(entry) { addToShopping(entry) {
if (entry.originalItem.entry.recipe !== null) { if (entry.originalItem.entry.recipe !== null) {
@ -491,7 +446,7 @@ export default {
let apiClient = new ApiApiFactory() let apiClient = new ApiApiFactory()
apiClient apiClient
.createMealType({name: this.$t("Meal_Type")}) .createMealType({ name: this.$t("Meal_Type") })
.then((e) => { .then((e) => {
this.periodChangedCallback(this.current_period) this.periodChangedCallback(this.current_period)
}) })
@ -879,7 +834,7 @@ having to override as much.
} }
.ghost { .ghost {
opacity: 0.5; opacity: 0.5;
background: #c8ebfb; background: #c8ebfb;
} }
</style> </style>

View File

@ -3,7 +3,7 @@
v-model="selected_objects" v-model="selected_objects"
:options="objects" :options="objects"
:close-on-select="true" :close-on-select="true"
:clear-on-select="true" :clear-on-select="multiple"
:hide-selected="multiple" :hide-selected="multiple"
:preserve-search="true" :preserve-search="true"
:internal-search="false" :internal-search="false"
@ -48,7 +48,7 @@ export default {
}, },
label: { type: String, default: "name" }, label: { type: String, default: "name" },
parent_variable: { type: String, default: undefined }, parent_variable: { type: String, default: undefined },
limit: { type: Number, default: 10 }, limit: { type: Number, default: 25 },
sticky_options: { sticky_options: {
type: Array, type: Array,
default() { default() {
@ -61,6 +61,10 @@ export default {
return [] return []
}, },
}, },
initial_single_selection: {
type: Object,
default: undefined,
},
multiple: { type: Boolean, default: true }, multiple: { type: Boolean, default: true },
allow_create: { type: Boolean, default: false }, allow_create: { type: Boolean, default: false },
create_placeholder: { type: String, default: "You Forgot to Add a Tag Placeholder" }, create_placeholder: { type: String, default: "You Forgot to Add a Tag Placeholder" },
@ -71,18 +75,37 @@ export default {
// watch it // watch it
this.selected_objects = newVal this.selected_objects = newVal
}, },
initial_single_selection: function (newVal, oldVal) {
// watch it
this.selected_objects = newVal
},
clear: function (newVal, oldVal) { clear: function (newVal, oldVal) {
this.selected_objects = [] if (this.multiple) {
this.selected_objects = []
} else {
this.selected_objects = undefined
}
}, },
}, },
mounted() { mounted() {
this.search("") this.search("")
this.selected_objects = this.initial_selection if (this.multiple || !this.initial_single_selection) {
this.selected_objects = this.initial_selection
} else {
this.selected_objects = this.initial_single_selection
}
}, },
computed: { computed: {
lookupPlaceholder() { lookupPlaceholder() {
return this.placeholder || this.model.name || this.$t("Search") return this.placeholder || this.model.name || this.$t("Search")
}, },
nothingSelected() {
if (this.multiple) {
return this.selected_objects.length === 0 && this.initial_selection.length === 0
} else {
return !this.selected_objects && !this.initial_selection
}
},
}, },
methods: { methods: {
// this.genericAPI inherited from ApiMixin // this.genericAPI inherited from ApiMixin
@ -95,8 +118,9 @@ export default {
} }
this.genericAPI(this.model, this.Actions.LIST, options).then((result) => { this.genericAPI(this.model, this.Actions.LIST, options).then((result) => {
this.objects = this.sticky_options.concat(result.data?.results ?? result.data) this.objects = this.sticky_options.concat(result.data?.results ?? result.data)
if (this.selected_objects.length === 0 && this.initial_selection.length === 0 && this.objects.length > 0) { if (this.nothingSelected && this.objects.length > 0) {
this.objects.forEach((item) => { this.objects.forEach((item) => {
// select default items when present in object
if ("default" in item) { if ("default" in item) {
if (item.default) { if (item.default) {
if (this.multiple) { if (this.multiple) {
@ -109,6 +133,7 @@ export default {
} }
}) })
} }
// this.removeMissingItems() # This removes items that are on another page of results
}) })
}, },
selectionChanged: function () { selectionChanged: function () {
@ -121,6 +146,13 @@ export default {
this.search("") this.search("")
}, 750) }, 750)
}, },
// removeMissingItems: function () {
// if (this.multiple) {
// this.selected_objects = this.selected_objects.filter((x) => !this.objects.map((y) => y.id).includes(x))
// } else {
// this.selected_objects = this.objects.filter((x) => x.id === this.selected_objects.id)[0]
// }
// },
}, },
} }
</script> </script>

View File

@ -146,7 +146,7 @@ export default {
saveShopping: function (del_shopping = false) { saveShopping: function (del_shopping = false) {
let servings = this.servings let servings = this.servings
if (del_shopping) { if (del_shopping) {
servings = 0 servings = -1
} }
let params = { let params = {
id: this.recipe, id: this.recipe,

View File

@ -25,7 +25,7 @@
<b-form-group> <b-form-group>
<generic-multiselect <generic-multiselect
@change="selectRecipe" @change="selectRecipe"
:initial_selection="entryEditing_initial_recipe" :initial_single_selection="entryEditing.recipe"
:label="'name'" :label="'name'"
:model="Models.RECIPE" :model="Models.RECIPE"
style="flex-grow: 1; flex-shrink: 1; flex-basis: 0" style="flex-grow: 1; flex-shrink: 1; flex-basis: 0"
@ -45,7 +45,7 @@
v-bind:placeholder="$t('Meal_Type')" v-bind:placeholder="$t('Meal_Type')"
:limit="10" :limit="10"
:multiple="false" :multiple="false"
:initial_selection="entryEditing_initial_meal_type" :initial_single_selection="entryEditing.meal_type"
:allow_create="true" :allow_create="true"
:create_placeholder="$t('Create_New_Meal_Type')" :create_placeholder="$t('Create_New_Meal_Type')"
@new="createMealType" @new="createMealType"
@ -81,8 +81,7 @@
</b-input-group> </b-input-group>
</div> </div>
<div class="col-lg-6 d-none d-lg-block d-xl-block"> <div class="col-lg-6 d-none d-lg-block d-xl-block">
<recipe-card v-if="entryEditing.recipe && !entryEditing.addshopping" :recipe="entryEditing.recipe" :detailed="false"></recipe-card> <recipe-card v-if="entryEditing.recipe" :recipe="entryEditing.recipe" :detailed="false"></recipe-card>
<ingredients-card v-if="entryEditing.recipe && entryEditing.addshopping" :recipe="entryEditing.recipe" :detailed="false"></ingredients-card>
</div> </div>
</div> </div>
<div class="row mt-3 mb-3"> <div class="row mt-3 mb-3">
@ -113,8 +112,6 @@ export default {
name: "MealPlanEditModal", name: "MealPlanEditModal",
props: { props: {
entry: Object, entry: Object,
entryEditing_initial_recipe: Array,
entryEditing_initial_meal_type: Array,
entryEditing_inital_servings: Number, entryEditing_inital_servings: Number,
modal_title: String, modal_title: String,
modal_id: { modal_id: {
@ -130,7 +127,6 @@ export default {
components: { components: {
GenericMultiselect, GenericMultiselect,
RecipeCard: () => import("@/components/RecipeCard.vue"), RecipeCard: () => import("@/components/RecipeCard.vue"),
IngredientsCard: () => import("@/components/IngredientsCard.vue"),
}, },
data() { data() {
return { return {
@ -144,12 +140,20 @@ export default {
entry: { entry: {
handler() { handler() {
this.entryEditing = Object.assign({}, this.entry) this.entryEditing = Object.assign({}, this.entry)
console.log("entryEditing", this.entryEditing)
if (this.entryEditing_inital_servings) { if (this.entryEditing_inital_servings) {
this.entryEditing.servings = this.entryEditing_inital_servings this.entryEditing.servings = this.entryEditing_inital_servings
} }
}, },
deep: true, deep: true,
}, },
entryEditing: {
handler(newVal) {},
deep: true,
},
entryEditing_inital_servings: function (newVal) {
this.entryEditing.servings = newVal
},
}, },
mounted: function () {}, mounted: function () {},
computed: { computed: {

View File

@ -106,7 +106,6 @@ export default {
deep: true, deep: true,
}, },
servings: function (newVal) { servings: function (newVal) {
console.log(newVal)
this.recipe_servings = parseInt(newVal) this.recipe_servings = parseInt(newVal)
}, },
}, },

View File

@ -64,8 +64,8 @@
</b-modal> </b-modal>
<meal-plan-edit-modal <meal-plan-edit-modal
v-if="entryEditing"
:entry="entryEditing" :entry="entryEditing"
:entryEditing_initial_recipe="[recipe]"
:entryEditing_inital_servings="servings_value" :entryEditing_inital_servings="servings_value"
:entry-editing_initial_meal_type="[]" :entry-editing_initial_meal_type="[]"
@save-entry="saveMealPlan" @save-entry="saveMealPlan"