import os import uuid from io import BytesIO import simplejson import simplejson as json from PIL import Image from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.core.files import File from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.utils.translation import gettext as _ from django.views.generic import UpdateView from cookbook.forms import ExternalRecipeForm, KeywordForm, StorageForm, SyncForm, InternalRecipeForm, CommentForm, \ MealPlanForm, UnitMergeForm, IngredientMergeForm, RecipeBookForm, FoodForm from cookbook.helper.permission_helper import group_required, GroupRequiredMixin from cookbook.helper.permission_helper import OwnerRequiredMixin from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, Ingredient, RecipeBook, \ MealPlan, Unit, Food from cookbook.provider.dropbox import Dropbox from cookbook.provider.nextcloud import Nextcloud @group_required('guest') def switch_recipe(request, pk): recipe = get_object_or_404(Recipe, pk=pk) if recipe.internal: return HttpResponseRedirect(reverse('edit_internal_recipe', args=[pk])) else: return HttpResponseRedirect(reverse('edit_external_recipe', args=[pk])) @group_required('user') def convert_recipe(request, pk): recipe = get_object_or_404(Recipe, pk=pk) if not recipe.internal: recipe.internal = True recipe.save() return HttpResponseRedirect(reverse('edit_internal_recipe', args=[pk])) @group_required('user') def internal_recipe_update(request, pk): recipe_instance = get_object_or_404(Recipe, pk=pk) return render(request, 'forms/edit_internal_recipe.html', {'recipe': recipe_instance}) class SyncUpdate(GroupRequiredMixin, UpdateView): groups_required = ['admin'] template_name = "generic/edit_template.html" model = Sync form_class = SyncForm # TODO add msg box def get_success_url(self): return reverse('edit_sync', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): context = super(SyncUpdate, self).get_context_data(**kwargs) context['title'] = _("Sync") return context class KeywordUpdate(GroupRequiredMixin, UpdateView): groups_required = ['user'] template_name = "generic/edit_template.html" model = Keyword form_class = KeywordForm # TODO add msg box def get_success_url(self): return reverse('edit_keyword', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): context = super(KeywordUpdate, self).get_context_data(**kwargs) context['title'] = _("Keyword") return context class FoodUpdate(GroupRequiredMixin, UpdateView): groups_required = ['user'] template_name = "generic/edit_template.html" model = Food form_class = FoodForm # TODO add msg box def get_success_url(self): return reverse('edit_food', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): context = super(FoodUpdate, self).get_context_data(**kwargs) context['title'] = _("Food") return context @group_required('admin') def edit_storage(request, pk): instance = get_object_or_404(Storage, pk=pk) if not (instance.created_by == request.user or request.user.is_superuser): messages.add_message(request, messages.ERROR, _('You cannot edit this storage!')) return HttpResponseRedirect(reverse('list_storage')) if request.method == "POST": form = StorageForm(request.POST, instance=instance) if form.is_valid(): instance.name = form.cleaned_data['name'] instance.method = form.cleaned_data['method'] instance.username = form.cleaned_data['username'] instance.url = form.cleaned_data['url'] if form.cleaned_data['password'] != '__NO__CHANGE__': instance.password = form.cleaned_data['password'] if form.cleaned_data['token'] != '__NO__CHANGE__': instance.token = form.cleaned_data['token'] instance.save() messages.add_message(request, messages.SUCCESS, _('Storage saved!')) else: messages.add_message(request, messages.ERROR, _('There was an error updating this storage backend!')) else: pseudo_instance = instance pseudo_instance.password = '__NO__CHANGE__' pseudo_instance.token = '__NO__CHANGE__' form = StorageForm(instance=pseudo_instance) return render(request, 'generic/edit_template.html', {'form': form, 'title': _('Storage')}) class CommentUpdate(OwnerRequiredMixin, UpdateView): template_name = "generic/edit_template.html" model = Comment form_class = CommentForm def get_success_url(self): return reverse('edit_comment', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): context = super(CommentUpdate, self).get_context_data(**kwargs) context['title'] = _("Comment") context['view_url'] = reverse('view_recipe', args=[self.object.recipe.pk]) return context class ImportUpdate(GroupRequiredMixin, UpdateView): groups_required = ['user'] template_name = "generic/edit_template.html" model = RecipeImport fields = ['name', 'path'] # TODO add msg box def get_success_url(self): return reverse('edit_import', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): context = super(ImportUpdate, self).get_context_data(**kwargs) context['title'] = _("Import") return context class RecipeBookUpdate(OwnerRequiredMixin, UpdateView): template_name = "generic/edit_template.html" model = RecipeBook form_class = RecipeBookForm def get_success_url(self): return reverse('view_books') def get_context_data(self, **kwargs): context = super(RecipeBookUpdate, self).get_context_data(**kwargs) context['title'] = _("Recipe Book") return context class MealPlanUpdate(OwnerRequiredMixin, UpdateView): template_name = "generic/edit_template.html" model = MealPlan form_class = MealPlanForm def get_success_url(self): return reverse('view_plan_entry', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): context = super(MealPlanUpdate, self).get_context_data(**kwargs) context['title'] = _("Meal-Plan") return context class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView): groups_required = ['user'] model = Recipe form_class = ExternalRecipeForm template_name = "generic/edit_template.html" def form_valid(self, form): self.object = form.save(commit=False) old_recipe = Recipe.objects.get(pk=self.object.pk) if not old_recipe.name == self.object.name: if self.object.storage.method == Storage.DROPBOX: Dropbox.rename_file(old_recipe, self.object.name) # TODO central location to handle storage type switches if self.object.storage.method == Storage.NEXTCLOUD: Nextcloud.rename_file(old_recipe, self.object.name) self.object.file_path = os.path.dirname(self.object.file_path) + '/' + self.object.name + os.path.splitext(self.object.file_path)[1] messages.add_message(self.request, messages.SUCCESS, _('Changes saved!')) return super(ExternalRecipeUpdate, self).form_valid(form) def form_invalid(self, form): messages.add_message(self.request, messages.ERROR, _('Error saving changes!')) return super(ExternalRecipeUpdate, self).form_valid(form) def get_success_url(self): return reverse('edit_recipe', kwargs={'pk': self.object.pk}) def get_context_data(self, **kwargs): context = super(ExternalRecipeUpdate, self).get_context_data(**kwargs) context['title'] = _("Recipe") context['view_url'] = reverse('view_recipe', args=[self.object.pk]) if self.object.storage: context['delete_external_url'] = reverse('delete_recipe_source', args=[self.object.pk]) return context @group_required('user') def edit_ingredients(request): if request.method == "POST": success = False units_form = UnitMergeForm(request.POST, prefix=UnitMergeForm.prefix) if units_form.is_valid(): new_unit = units_form.cleaned_data['new_unit'] old_unit = units_form.cleaned_data['old_unit'] recipe_ingredients = Ingredient.objects.filter(unit=old_unit).all() for i in recipe_ingredients: i.unit = new_unit i.save() old_unit.delete() success = True messages.add_message(request, messages.SUCCESS, _('Units merged!')) ingredients_form = IngredientMergeForm(request.POST, prefix=IngredientMergeForm.prefix) if ingredients_form.is_valid(): new_ingredient = ingredients_form.cleaned_data['new_food'] old_ingredient = ingredients_form.cleaned_data['old_food'] recipe_ingredients = Ingredient.objects.filter(food=old_ingredient).all() for i in recipe_ingredients: i.ingredient = new_ingredient i.save() old_ingredient.delete() success = True messages.add_message(request, messages.SUCCESS, _('Ingredients merged!')) if success: units_form = UnitMergeForm() ingredients_form = IngredientMergeForm() else: units_form = UnitMergeForm() ingredients_form = IngredientMergeForm() return render(request, 'forms/ingredients.html', {'units_form': units_form, 'ingredients_form': ingredients_form})