diff --git a/cookbook/serializer.py b/cookbook/serializer.py
index a843b56e..f7a004c4 100644
--- a/cookbook/serializer.py
+++ b/cookbook/serializer.py
@@ -4,7 +4,8 @@ from rest_framework import serializers
from rest_framework.exceptions import APIException, ValidationError
from rest_framework.fields import CurrentUserDefault
-from cookbook.models import MealPlan, MealType, Recipe, ViewLog, UserPreference, Storage, Sync, SyncLog, Keyword, Unit, Ingredient, Comment, RecipeImport, RecipeBook, RecipeBookEntry, ShareLink, CookLog, Food, Step
+from cookbook.models import MealPlan, MealType, Recipe, ViewLog, UserPreference, Storage, Sync, SyncLog, Keyword, Unit, Ingredient, Comment, RecipeImport, RecipeBook, RecipeBookEntry, ShareLink, CookLog, Food, Step, ShoppingList, \
+ ShoppingListEntry, ShoppingListRecipe
from cookbook.templatetags.custom_tags import markdown
@@ -193,6 +194,34 @@ class MealPlanSerializer(serializers.ModelSerializer):
fields = ('id', 'title', 'recipe', 'note', 'note_markdown', 'date', 'meal_type', 'created_by', 'shared', 'recipe_name', 'meal_type_name')
+class ShoppingListRecipeSerializer(serializers.ModelSerializer):
+ recipe = RecipeSerializer(read_only=True)
+
+ def create(self, validated_data):
+ return ShoppingListRecipe.objects.create(**validated_data)
+
+ def update(self, instance, validated_data):
+ return super(ShoppingListRecipeSerializer, self).update(instance, validated_data)
+
+ class Meta:
+ model = ShoppingListRecipe
+ fields = ('recipe', 'multiplier')
+
+
+class ShoppingListEntrySerializer(serializers.ModelSerializer):
+ class Meta:
+ model = ShoppingListEntry
+ fields = ('list_recipe', 'food', 'unit', 'amount', 'order', 'checked')
+
+
+class ShoppingListSerializer(serializers.ModelSerializer):
+ recipes = ShoppingListRecipeSerializer(many=True, allow_null=True, read_only=True)
+
+ class Meta:
+ model = ShoppingList
+ fields = ('id', 'uuid', 'note', 'recipes', 'shared', 'created_by', 'created_at',)
+
+
class ShareLinkSerializer(serializers.ModelSerializer):
class Meta:
model = ShareLink
diff --git a/cookbook/templates/shopping_list.html b/cookbook/templates/shopping_list.html
index 0b9628e7..2db45f28 100644
--- a/cookbook/templates/shopping_list.html
+++ b/cookbook/templates/shopping_list.html
@@ -7,11 +7,124 @@
{% block title %}{% trans "Shopping List" %}{% endblock %}
{% block extra_head %}
+ {% include 'include/vue_base.html' %}
+
+
+
+
+
{% endblock %}
{% block content %}
+
+
+
{% trans 'Shopping List' %}
+
+
+ {% trans 'Edit' %}
+
+
+
+
+ Non Edit
+
+
+
+
+{% endblock %}
+{% block script %}
+
+
{% endblock %}
\ No newline at end of file
diff --git a/cookbook/urls.py b/cookbook/urls.py
index b4e29d8f..ecf8ac20 100644
--- a/cookbook/urls.py
+++ b/cookbook/urls.py
@@ -23,6 +23,7 @@ router.register(r'recipe', api.RecipeViewSet)
router.register(r'ingredient', api.IngredientViewSet)
router.register(r'meal-plan', api.MealPlanViewSet)
router.register(r'meal-type', api.MealTypeViewSet)
+router.register(r'shopping-list', api.ShoppingListViewSet)
router.register(r'view-log', api.ViewLogViewSet)
urlpatterns = [
@@ -34,6 +35,7 @@ urlpatterns = [
path('plan/', views.meal_plan, name='view_plan'),
path('plan/entry/', views.meal_plan_entry, name='view_plan_entry'),
path('shopping/', views.shopping_list, name='view_shopping'),
+ path('shopping/', views.shopping_list, name='view_shopping'),
path('settings/', views.user_settings, name='view_settings'),
path('history/', views.history, name='view_history'),
path('test/', views.test, name='view_test'),
diff --git a/cookbook/views/api.py b/cookbook/views/api.py
index 7988fcce..079a04bd 100644
--- a/cookbook/views/api.py
+++ b/cookbook/views/api.py
@@ -28,11 +28,11 @@ from rest_framework.viewsets import ViewSetMixin
from cookbook.helper.permission_helper import group_required, CustomIsOwner, CustomIsAdmin, CustomIsUser, CustomIsGuest, CustomIsShare
from cookbook.helper.recipe_url_import import get_from_html
-from cookbook.models import Recipe, Sync, Storage, CookLog, MealPlan, MealType, ViewLog, UserPreference, RecipeBook, Ingredient, Food, Step, Keyword, Unit, SyncLog
+from cookbook.models import Recipe, Sync, Storage, CookLog, MealPlan, MealType, ViewLog, UserPreference, RecipeBook, Ingredient, Food, Step, Keyword, Unit, SyncLog, ShoppingListRecipe, ShoppingList
from cookbook.provider.dropbox import Dropbox
from cookbook.provider.nextcloud import Nextcloud
from cookbook.serializer import MealPlanSerializer, MealTypeSerializer, RecipeSerializer, ViewLogSerializer, UserNameSerializer, UserPreferenceSerializer, RecipeBookSerializer, IngredientSerializer, FoodSerializer, StepSerializer, \
- KeywordSerializer, RecipeImageSerializer, StorageSerializer, SyncSerializer, SyncLogSerializer, UnitSerializer
+ KeywordSerializer, RecipeImageSerializer, StorageSerializer, SyncSerializer, SyncLogSerializer, UnitSerializer, ShoppingListSerializer
class UserNameViewSet(viewsets.ReadOnlyModelViewSet):
@@ -233,6 +233,16 @@ class RecipeViewSet(viewsets.ModelViewSet, StandardFilterMixin):
return Response(serializer.errors, 400)
+class ShoppingListViewSet(viewsets.ModelViewSet):
+ queryset = ShoppingList.objects.all()
+ serializer_class = ShoppingListSerializer
+ permission_classes = [CustomIsOwner]
+
+ def get_queryset(self):
+ queryset = self.queryset.filter(created_by=self.request.user).all()
+ return queryset
+
+
class ViewLogViewSet(viewsets.ModelViewSet):
queryset = ViewLog.objects.all()
serializer_class = ViewLogSerializer
diff --git a/cookbook/views/lists.py b/cookbook/views/lists.py
index 2869fad6..8ae428e7 100644
--- a/cookbook/views/lists.py
+++ b/cookbook/views/lists.py
@@ -50,7 +50,7 @@ def shopping_list(request):
table = ShoppingListTable(ShoppingList.objects.filter(created_by=request.user).all())
RequestConfig(request, paginate={'per_page': 25}).configure(table)
- return render(request, 'generic/list_template.html', {'title': _("Shopping Lists"), 'table': table, 'create_url': 'new_storage'})
+ return render(request, 'generic/list_template.html', {'title': _("Shopping Lists"), 'table': table, 'create_url': 'view_shopping'})
@group_required('admin')
diff --git a/cookbook/views/views.py b/cookbook/views/views.py
index 95b846cf..c3bd4806 100644
--- a/cookbook/views/views.py
+++ b/cookbook/views/views.py
@@ -164,44 +164,8 @@ def meal_plan_entry(request, pk):
@group_required('user')
-def shopping_list(request):
- markdown_format = True
-
- if request.method == "POST":
- form = ShoppingForm(request.POST)
- if form.is_valid():
- recipes = form.cleaned_data['recipe']
- markdown_format = form.cleaned_data['markdown_format']
- else:
- recipes = []
- else:
- raw_list = request.GET.getlist('r')
-
- recipes = []
- for r in raw_list:
- if re.match(r'^([1-9])+$', r):
- if Recipe.objects.filter(pk=int(r)).exists():
- recipes.append(int(r))
-
- markdown_format = False
- form = ShoppingForm(initial={'recipe': recipes, 'markdown_format': False})
-
- ingredients = []
-
- for r in recipes:
- for s in r.steps.all():
- for ri in s.ingredients.exclude(unit__name__contains='Special:').all():
- index = None
- for x, ig in enumerate(ingredients):
- if ri.food == ig.food and ri.unit == ig.unit:
- index = x
-
- if index:
- ingredients[index].amount = ingredients[index].amount + ri.amount
- else:
- ingredients.append(ri)
-
- return render(request, 'shopping_list.html', {'ingredients': ingredients, 'recipes': recipes, 'form': form, 'markdown_format': markdown_format})
+def shopping_list(request, pk=None):
+ return render(request, 'shopping_list.html', {})
@group_required('guest')