diff --git a/cookbook/forms.py b/cookbook/forms.py index f4d495aed..a097146c7 100644 --- a/cookbook/forms.py +++ b/cookbook/forms.py @@ -70,6 +70,23 @@ class RecipeForm(forms.Form): ) +class UnitMergeForm(forms.Form): + prefix = 'unit' + + new_unit = forms.ModelChoiceField( + queryset=Unit.objects.all(), + widget=SelectWidget, + label=_('New Unit'), + help_text=_('New unit that other gets replaced by.'), + ) + old_unit = forms.ModelChoiceField( + queryset=Unit.objects.all(), + widget=SelectWidget, + label=_('Old Unit'), + help_text=_('Unit that should be replaced.'), + ) + + class CommentForm(forms.ModelForm): prefix = 'comment' diff --git a/cookbook/templates/base.html b/cookbook/templates/base.html index e025f81cb..49fc150da 100644 --- a/cookbook/templates/base.html +++ b/cookbook/templates/base.html @@ -107,6 +107,9 @@ class="fas fa-history"> {% trans 'Import Log' %} {% trans 'Statistics' %} + {% trans 'Units & Ingredients' %} + diff --git a/cookbook/templates/forms/ingredients.html b/cookbook/templates/forms/ingredients.html new file mode 100644 index 000000000..06c09dd46 --- /dev/null +++ b/cookbook/templates/forms/ingredients.html @@ -0,0 +1,34 @@ +{% extends "base.html" %} +{% load django_tables2 %} +{% load crispy_forms_tags %} +{% load static %} +{% load i18n %} + +{% block title %}{% trans "Cookbook" %}{% endblock %} + +{% block extra_head %} + {{ form.media }} +{% endblock %} + +{% block content %} + +

{% trans 'Edit Ingredients' %}

+ {% blocktrans %} + The following form can be used if, accidentally, two (or more) units or ingredients where created that should be + the same. + It merges two units or ingredients and updates all recipes using them. + {% endblocktrans %} +
+
+ +

{% trans 'Units' %}

+
+ {% csrf_token %} + {{ form|crispy }} + +
+ + +{% endblock %} \ No newline at end of file diff --git a/cookbook/urls.py b/cookbook/urls.py index 0ad886e03..e62d2a67b 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -38,6 +38,7 @@ urlpatterns = [ path('edit/comment//', edit.CommentUpdate.as_view(), name='edit_comment'), path('edit/recipe-book//', edit.RecipeBookUpdate.as_view(), name='edit_recipe_book'), path('edit/plan//', edit.MealPlanUpdate.as_view(), name='edit_plan'), + path('edit/ingredient/', edit.edit_ingredients, name='edit_ingredient'), path('redirect/delete///', edit.delete_redirect, name='redirect_delete'), diff --git a/cookbook/views/edit.py b/cookbook/views/edit.py index 36e1464a9..2165a8209 100644 --- a/cookbook/views/edit.py +++ b/cookbook/views/edit.py @@ -11,10 +11,11 @@ from django.db.models import Value, CharField from django.http import HttpResponseRedirect from django.shortcuts import redirect, get_object_or_404, render from django.urls import reverse_lazy, reverse -from django.utils.translation import gettext as _ +from django.utils.translation import gettext as _, ngettext from django.views.generic import UpdateView, DeleteView -from cookbook.forms import ExternalRecipeForm, KeywordForm, StorageForm, SyncForm, InternalRecipeForm, CommentForm, MealPlanForm +from cookbook.forms import ExternalRecipeForm, KeywordForm, StorageForm, SyncForm, InternalRecipeForm, CommentForm, \ + MealPlanForm, UnitMergeForm from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeIngredients, RecipeBook, \ RecipeBookEntry, MealPlan, Unit from cookbook.provider.dropbox import Dropbox @@ -104,7 +105,9 @@ def internal_recipe_update(request, pk): else: form = InternalRecipeForm(instance=recipe_instance) - ingredients = RecipeIngredients.objects.select_related('unit__name').filter(recipe=recipe_instance).values('name', 'unit__name', 'amount') + ingredients = RecipeIngredients.objects.select_related('unit__name').filter(recipe=recipe_instance).values('name', + 'unit__name', + 'amount') return render(request, 'forms/edit_internal_recipe.html', {'form': form, 'ingredients': json.dumps(list(ingredients)), @@ -290,8 +293,29 @@ class RecipeUpdate(LoginRequiredMixin, UpdateView): return context -# Generic Delete views +@login_required +def edit_ingredients(request): + if request.method == "POST": + form = UnitMergeForm(request.POST, prefix=UnitMergeForm.prefix) + if form.is_valid(): + new_unit = form.cleaned_data['new_unit'] + old_unit = form.cleaned_data['old_unit'] + ingredients = RecipeIngredients.objects.filter(unit=old_unit).all() + for i in ingredients: + i.unit = new_unit + i.save() + old_unit.delete() + messages.add_message(request, messages.SUCCESS, _('Units merged!')) + else: + messages.add_message(request, messages.WARNING, _('There was an error in your form.')) + else: + form = UnitMergeForm() + + return render(request, 'forms/ingredients.html', {'form': form}) + + +# Generic Delete views def delete_redirect(request, name, pk): return redirect(('delete_' + name), pk)