mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2025-12-26 03:43:34 -05:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8f16b50a7 | ||
|
|
752df5a1d2 | ||
|
|
fe6e351349 | ||
|
|
8cc9273268 | ||
|
|
0c1763b347 | ||
|
|
88dc713683 | ||
|
|
fc1cc70870 | ||
|
|
42e09fcae9 | ||
|
|
4843568d10 | ||
|
|
2e7e4b23dd | ||
|
|
8192a8dc8f | ||
|
|
c98dbd065e | ||
|
|
43d03ed17d | ||
|
|
8ba34414a1 | ||
|
|
46dffe2f63 | ||
|
|
04cbe6cb2c | ||
|
|
8fd6dcc81c | ||
|
|
b89e96476a |
2
.idea/jsLibraryMappings.xml
generated
2
.idea/jsLibraryMappings.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptLibraryMappings">
|
||||
<file url="file://$PROJECT_DIR$" libraries="{jquery-3.4.1}" />
|
||||
<file url="file://$PROJECT_DIR$" libraries="{jquery-3.4.1, pdf, pdf_viewer, pretty-checkbox}" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,4 +1,4 @@
|
||||
# Recipes 
|
||||
# Recipes 
|
||||
Recipes is a Django application to manage, tag and search recipes using either built in models or external storage providers hosting PDF's, Images or other files.
|
||||
|
||||

|
||||
|
||||
@@ -2,14 +2,17 @@ import django_filters
|
||||
from django.contrib.postgres.search import TrigramSimilarity
|
||||
from django.db.models import Q
|
||||
from cookbook.forms import MultiSelectWidget
|
||||
from cookbook.models import Recipe, Keyword
|
||||
from cookbook.models import Recipe, Keyword, Ingredient
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
|
||||
class RecipeFilter(django_filters.FilterSet):
|
||||
name = django_filters.CharFilter(method='filter_name')
|
||||
keywords = django_filters.ModelMultipleChoiceFilter(queryset=Keyword.objects.all(), widget=MultiSelectWidget,
|
||||
method='filter_keywords')
|
||||
ingredients = django_filters.ModelMultipleChoiceFilter(queryset=Ingredient.objects.all(), widget=MultiSelectWidget,
|
||||
method='filter_ingredients', label=_('Ingredients'))
|
||||
|
||||
@staticmethod
|
||||
def filter_keywords(queryset, name, value):
|
||||
@@ -19,6 +22,14 @@ class RecipeFilter(django_filters.FilterSet):
|
||||
queryset = queryset.filter(keywords=x)
|
||||
return queryset
|
||||
|
||||
@staticmethod
|
||||
def filter_ingredients(queryset, name, value):
|
||||
if not name == 'ingredients':
|
||||
return queryset
|
||||
for x in value:
|
||||
queryset = queryset.filter(recipeingredient__ingredient=x).distinct()
|
||||
return queryset
|
||||
|
||||
@staticmethod
|
||||
def filter_name(queryset, name, value):
|
||||
if not name == 'name':
|
||||
@@ -32,14 +43,4 @@ class RecipeFilter(django_filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = Recipe
|
||||
fields = ['name', 'keywords']
|
||||
|
||||
|
||||
class QuickRecipeFilter(django_filters.FilterSet):
|
||||
name = django_filters.CharFilter(lookup_expr='icontains')
|
||||
keywords = django_filters.ModelMultipleChoiceFilter(queryset=Keyword.objects.all(), widget=MultiSelectWidget,
|
||||
method='filter_keywords')
|
||||
|
||||
class Meta:
|
||||
model = Recipe
|
||||
fields = ['name', 'keywords']
|
||||
fields = ['name', 'keywords', 'ingredients']
|
||||
|
||||
@@ -73,11 +73,16 @@ class InternalRecipeForm(forms.ModelForm):
|
||||
widgets = {'keywords': MultiSelectWidget}
|
||||
|
||||
|
||||
class RecipeForm(forms.Form):
|
||||
class ShoppingForm(forms.Form):
|
||||
recipe = forms.ModelMultipleChoiceField(
|
||||
queryset=Recipe.objects.all(),
|
||||
widget=MultiSelectWidget
|
||||
)
|
||||
markdown_format = forms.BooleanField(
|
||||
help_text=_('Include <code>- [ ]</code> in list for easier usage in markdown based documents.'),
|
||||
required=False,
|
||||
initial=False
|
||||
)
|
||||
|
||||
|
||||
class UnitMergeForm(forms.Form):
|
||||
@@ -97,6 +102,23 @@ class UnitMergeForm(forms.Form):
|
||||
)
|
||||
|
||||
|
||||
class IngredientMergeForm(forms.Form):
|
||||
prefix = 'ingredient'
|
||||
|
||||
new_ingredient = forms.ModelChoiceField(
|
||||
queryset=Ingredient.objects.all(),
|
||||
widget=SelectWidget,
|
||||
label=_('New Ingredient'),
|
||||
help_text=_('New ingredient that other gets replaced by.'),
|
||||
)
|
||||
old_ingredient = forms.ModelChoiceField(
|
||||
queryset=Ingredient.objects.all(),
|
||||
widget=SelectWidget,
|
||||
label=_('Old Ingredient'),
|
||||
help_text=_('Ingredient that should be replaced.'),
|
||||
)
|
||||
|
||||
|
||||
class CommentForm(forms.ModelForm):
|
||||
prefix = 'comment'
|
||||
|
||||
|
||||
Binary file not shown.
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-13 12:08+0100\n"
|
||||
"POT-Creation-Date: 2020-02-18 23:20+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,152 +18,247 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: cookbook/forms.py:24 cookbook/forms.py:40 cookbook/forms.py:122
|
||||
#: .\cookbook\filters.py:15
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:28
|
||||
#: .\cookbook\templates\forms\ingredients.html:33
|
||||
#: .\cookbook\templates\recipe_view.html:67
|
||||
msgid "Ingredients"
|
||||
msgstr "Zutaten"
|
||||
|
||||
#: .\cookbook\forms.py:35
|
||||
msgid ""
|
||||
"Color of the top navigation bar. Not all colors work with all themes, just "
|
||||
"try them out!"
|
||||
msgstr ""
|
||||
"Farbe der oberen Navigationsleiste. Nicht alle Farben passen, daher einfach mal ausprobieren!"
|
||||
|
||||
#: .\cookbook\forms.py:49 .\cookbook\forms.py:67 .\cookbook\forms.py:189
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: cookbook/forms.py:25 cookbook/forms.py:41 cookbook/forms.py:123
|
||||
#: cookbook/templates/stats.html:22
|
||||
#: .\cookbook\forms.py:50 .\cookbook\forms.py:68 .\cookbook\forms.py:190
|
||||
#: .\cookbook\templates\stats.html:22
|
||||
msgid "Keywords"
|
||||
msgstr "Schlagwörter"
|
||||
|
||||
#: cookbook/forms.py:26 cookbook/forms.py:43
|
||||
#: .\cookbook\forms.py:51 .\cookbook\forms.py:70
|
||||
msgid "Preparation time in minutes"
|
||||
msgstr "Zubereitungszeit in Minuten"
|
||||
|
||||
#: cookbook/forms.py:27 cookbook/forms.py:44
|
||||
#: .\cookbook\forms.py:52 .\cookbook\forms.py:71
|
||||
msgid "Waiting time (cooking/baking) in minutes"
|
||||
msgstr "Wartezeit (kochen/backen) in Minuten"
|
||||
|
||||
#: cookbook/forms.py:28 cookbook/forms.py:124
|
||||
#: .\cookbook\forms.py:53 .\cookbook\forms.py:191
|
||||
msgid "Path"
|
||||
msgstr "Pfad"
|
||||
|
||||
#: cookbook/forms.py:29
|
||||
#: .\cookbook\forms.py:54
|
||||
msgid "Storage UID"
|
||||
msgstr "Speicher ID"
|
||||
|
||||
#: cookbook/forms.py:42
|
||||
#: .\cookbook\forms.py:69
|
||||
msgid "Instructions"
|
||||
msgstr "Anleitung"
|
||||
|
||||
#: cookbook/forms.py:57
|
||||
#: .\cookbook\forms.py:82
|
||||
msgid ""
|
||||
"Include <code>- [ ]</code> in list for easier usage in markdown based "
|
||||
"documents."
|
||||
msgstr ""
|
||||
"Füge <code>- [ ]</code> vor den Zutaten ein um sie besser in einem Markdown Dokument "
|
||||
"zu verwenden."
|
||||
|
||||
#: .\cookbook\forms.py:94
|
||||
msgid "New Unit"
|
||||
msgstr "Neue Einheit"
|
||||
|
||||
#: .\cookbook\forms.py:95
|
||||
msgid "New unit that other gets replaced by."
|
||||
msgstr "Neue Einheit die die alte ersetzt."
|
||||
|
||||
#: .\cookbook\forms.py:100
|
||||
msgid "Old Unit"
|
||||
msgstr "Alte Einheit"
|
||||
|
||||
#: .\cookbook\forms.py:101
|
||||
msgid "Unit that should be replaced."
|
||||
msgstr "Einheit die ersetzt werden soll."
|
||||
|
||||
#: .\cookbook\forms.py:111
|
||||
msgid "New Ingredient"
|
||||
msgstr "Neue Zutat"
|
||||
|
||||
#: .\cookbook\forms.py:112
|
||||
msgid "New ingredient that other gets replaced by."
|
||||
msgstr "Neue Zutat die die alte ersetzt."
|
||||
|
||||
#: .\cookbook\forms.py:117
|
||||
msgid "Old Ingredient"
|
||||
msgstr "Alte Zutat"
|
||||
|
||||
#: .\cookbook\forms.py:118
|
||||
msgid "Ingredient that should be replaced."
|
||||
msgstr "Zutat die ersetzt werden soll."
|
||||
|
||||
#: .\cookbook\forms.py:130
|
||||
msgid "Add your comment: "
|
||||
msgstr "Schreibe einen Kommentar:"
|
||||
|
||||
#: cookbook/forms.py:75
|
||||
#: .\cookbook\forms.py:148
|
||||
msgid "Leave empty for dropbox and enter app password for nextcloud."
|
||||
msgstr "Für Dropbox leer lassen, bei Nextcloud App-Passwort eingeben."
|
||||
|
||||
#: cookbook/forms.py:78
|
||||
#: .\cookbook\forms.py:151
|
||||
msgid "Leave empty for nextcloud and enter api token for dropbox."
|
||||
msgstr "Bei Nextcloud leer lassen, bei Dropbox API Token eingeben"
|
||||
|
||||
#: cookbook/forms.py:86
|
||||
#: .\cookbook\forms.py:159
|
||||
msgid ""
|
||||
"Leave empty for dropbox and enter only base url for nextcloud (<code>/remote."
|
||||
"php/webdav/</code> is added automatically)"
|
||||
msgstr "Bei Dropbox leer lassen, bei Nextcloud Server URL angeben (<code>/remote."
|
||||
"php/webdav/</code> wird automatisch hinzugefügt)"
|
||||
msgstr ""
|
||||
"Bei Dropbox leer lassen, bei Nextcloud Server URL angeben (<code>/remote.php/"
|
||||
"webdav/</code> wird automatisch hinzugefügt)"
|
||||
|
||||
#: cookbook/forms.py:111
|
||||
#: .\cookbook\forms.py:178
|
||||
msgid "Search String"
|
||||
msgstr "Such Wort"
|
||||
|
||||
#: cookbook/forms.py:125
|
||||
#: .\cookbook\forms.py:192
|
||||
msgid "File ID"
|
||||
msgstr "Datei ID"
|
||||
|
||||
#: cookbook/tables.py:75 cookbook/templates/forms/edit_internal_recipe.html:39
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:98
|
||||
#: cookbook/templates/generic/delete_template.html:5
|
||||
#: cookbook/templates/generic/delete_template.html:13
|
||||
#: cookbook/templates/generic/edit_template.html:25
|
||||
#: .\cookbook\models.py:172
|
||||
msgid "Breakfast"
|
||||
msgstr "Frühstück"
|
||||
|
||||
#: .\cookbook\models.py:172
|
||||
msgid "Lunch"
|
||||
msgstr "Mittagessen"
|
||||
|
||||
#: .\cookbook\models.py:172
|
||||
msgid "Dinner"
|
||||
msgstr "Abendessen"
|
||||
|
||||
#: .\cookbook\models.py:172
|
||||
msgid "Other"
|
||||
msgstr "Andere"
|
||||
|
||||
#: .\cookbook\tables.py:75
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:49
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:176
|
||||
#: .\cookbook\templates\generic\delete_template.html:5
|
||||
#: .\cookbook\templates\generic\delete_template.html:13
|
||||
#: .\cookbook\templates\generic\edit_template.html:25
|
||||
msgid "Delete"
|
||||
msgstr "Löschen"
|
||||
|
||||
#: cookbook/templates/base.html:64 cookbook/templates/base.html:72
|
||||
#: cookbook/templates/index.html:7
|
||||
#: .\cookbook\templates\base.html:70 .\cookbook\templates\base.html:78
|
||||
#: .\cookbook\templates\forms\ingredients.html:7
|
||||
#: .\cookbook\templates\index.html:7 .\cookbook\templates\shopping_list.html:7
|
||||
msgid "Cookbook"
|
||||
msgstr "Kochbuch"
|
||||
|
||||
#: cookbook/templates/base.html:76
|
||||
#: .\cookbook\templates\base.html:82
|
||||
msgid "Books"
|
||||
msgstr "Bücher"
|
||||
|
||||
#: cookbook/templates/base.html:81
|
||||
#: .\cookbook\templates\base.html:86 .\cookbook\templates\meal_plan.html:4
|
||||
#: .\cookbook\templates\meal_plan.html:13 .\cookbook\views\edit.py:261
|
||||
#: .\cookbook\views\edit.py:462 .\cookbook\views\new.py:130
|
||||
msgid "Meal-Plan"
|
||||
msgstr "Plan"
|
||||
|
||||
#: .\cookbook\templates\base.html:90
|
||||
#, fuzzy
|
||||
#| msgid "Shopping List"
|
||||
msgid "Shopping"
|
||||
msgstr "Einkaufsliste"
|
||||
|
||||
#: .\cookbook\templates\base.html:96
|
||||
msgid "Tags"
|
||||
msgstr "Schlagwörter"
|
||||
|
||||
#: cookbook/templates/base.html:85 cookbook/views/edit.py:130
|
||||
#: cookbook/views/edit.py:331 cookbook/views/lists.py:17
|
||||
#: cookbook/views/new.py:44
|
||||
#: .\cookbook\templates\base.html:100 .\cookbook\views\edit.py:151
|
||||
#: .\cookbook\views\edit.py:407 .\cookbook\views\lists.py:17
|
||||
#: .\cookbook\views\new.py:46
|
||||
msgid "Keyword"
|
||||
msgstr "Schlagwort"
|
||||
|
||||
#: cookbook/templates/base.html:87
|
||||
#: .\cookbook\templates\base.html:102
|
||||
msgid "Batch Edit"
|
||||
msgstr "Massenbearbeitung"
|
||||
|
||||
#: cookbook/templates/base.html:92
|
||||
#: .\cookbook\templates\base.html:107
|
||||
msgid "Storage Data"
|
||||
msgstr "Datenquellen"
|
||||
|
||||
#: cookbook/templates/base.html:96
|
||||
#: .\cookbook\templates\base.html:111
|
||||
msgid "Storage Backends"
|
||||
msgstr "Speicher Quellen"
|
||||
|
||||
#: cookbook/templates/base.html:98
|
||||
#: .\cookbook\templates\base.html:113
|
||||
msgid "Configure Sync"
|
||||
msgstr "Sync Einstellen"
|
||||
|
||||
#: cookbook/templates/base.html:100
|
||||
#: .\cookbook\templates\base.html:115
|
||||
msgid "Import Recipes"
|
||||
msgstr "Importierte Rezepte"
|
||||
|
||||
#: cookbook/templates/base.html:102 cookbook/views/lists.py:25
|
||||
#: .\cookbook\templates\base.html:117 .\cookbook\views\lists.py:25
|
||||
msgid "Import Log"
|
||||
msgstr "Import Log"
|
||||
|
||||
#: cookbook/templates/base.html:104 cookbook/templates/stats.html:10
|
||||
#: .\cookbook\templates\base.html:119 .\cookbook\templates\stats.html:10
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiken"
|
||||
|
||||
#: cookbook/templates/base.html:112
|
||||
#: .\cookbook\templates\base.html:121
|
||||
msgid "Units & Ingredients"
|
||||
msgstr "Einheiten & Zutaten"
|
||||
|
||||
#: .\cookbook\templates\base.html:130 .\cookbook\templates\settings.html:6
|
||||
#: .\cookbook\templates\settings.html:11
|
||||
msgid "Settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: .\cookbook\templates\base.html:135
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: cookbook/templates/base.html:116
|
||||
#: .\cookbook\templates\base.html:140
|
||||
msgid "Logout"
|
||||
msgstr "Ausloggen"
|
||||
|
||||
#: cookbook/templates/base.html:119
|
||||
#: .\cookbook\templates\base.html:143
|
||||
#: .\cookbook\templates\registration\login.html:44
|
||||
msgid "Login"
|
||||
msgstr "Einloggen"
|
||||
|
||||
#: cookbook/templates/batch/edit.html:6
|
||||
#: .\cookbook\templates\batch\edit.html:6
|
||||
msgid "Batch edit Category"
|
||||
msgstr "Kategorie massenbearbeitung"
|
||||
|
||||
#: cookbook/templates/batch/edit.html:15
|
||||
#: .\cookbook\templates\batch\edit.html:15
|
||||
msgid "Batch edit Recipes"
|
||||
msgstr "Rezept massenbearbeitung"
|
||||
|
||||
#: cookbook/templates/batch/edit.html:20
|
||||
#: .\cookbook\templates\batch\edit.html:20
|
||||
msgid "Add the specified keywords to all recipes containing a word"
|
||||
msgstr ""
|
||||
"Ausgewählte Schlagwörter zu allen Rezepten die das Suchwort enthalten "
|
||||
"hinzufügen"
|
||||
|
||||
#: cookbook/templates/batch/monitor.html:6 cookbook/views/edit.py:114
|
||||
#: .\cookbook\templates\batch\monitor.html:6 .\cookbook\views\edit.py:135
|
||||
msgid "Sync"
|
||||
msgstr "Synchronisieren"
|
||||
|
||||
#: cookbook/templates/batch/monitor.html:10
|
||||
#: .\cookbook\templates\batch\monitor.html:10
|
||||
msgid "Manage watched Folders"
|
||||
msgstr "Überwachte Ordner verwalten"
|
||||
|
||||
#: cookbook/templates/batch/monitor.html:14
|
||||
#: .\cookbook\templates\batch\monitor.html:14
|
||||
msgid ""
|
||||
"On this Page you can manage all storage folder locations that should be "
|
||||
"monitored and synced"
|
||||
@@ -171,20 +266,20 @@ msgstr ""
|
||||
"Auf dieser Seite kannst du alle Ordner verwalten die überwacht und "
|
||||
"synchronisiert werden sollen"
|
||||
|
||||
#: cookbook/templates/batch/monitor.html:16
|
||||
#: .\cookbook\templates\batch\monitor.html:16
|
||||
msgid "The path must be in the following format"
|
||||
msgstr "Der Pfad muss in folgendem Format sein"
|
||||
|
||||
#: cookbook/templates/batch/monitor.html:27
|
||||
#: .\cookbook\templates\batch\monitor.html:27
|
||||
msgid "Sync Now!"
|
||||
msgstr "Jetzt Synchronisieren!"
|
||||
|
||||
#: cookbook/templates/batch/waiting.html:4
|
||||
#: cookbook/templates/batch/waiting.html:10
|
||||
#: .\cookbook\templates\batch\waiting.html:4
|
||||
#: .\cookbook\templates\batch\waiting.html:10
|
||||
msgid "Importing Recipes"
|
||||
msgstr "Rezept werden importiert"
|
||||
|
||||
#: cookbook/templates/batch/waiting.html:23
|
||||
#: .\cookbook\templates\batch\waiting.html:23
|
||||
msgid ""
|
||||
"This can take a few minutes, depending on the number of recipes in sync, "
|
||||
"please wait."
|
||||
@@ -192,120 +287,165 @@ msgstr ""
|
||||
"Abhängig von der Anzahl der Rezepte kann dieser Vorgang einige Minuten "
|
||||
"dauern, bitte warten."
|
||||
|
||||
#: cookbook/templates/books.html:4 cookbook/templates/books.html:10
|
||||
#: .\cookbook\templates\books.html:4 .\cookbook\templates\books.html:10
|
||||
msgid "Recipe Books"
|
||||
msgstr "Rezept Bücher"
|
||||
|
||||
#: cookbook/templates/books.html:14
|
||||
#: .\cookbook\templates\books.html:14
|
||||
msgid "New Book"
|
||||
msgstr "Neues Buch"
|
||||
|
||||
#: cookbook/templates/books.html:53
|
||||
#: .\cookbook\templates\books.html:53
|
||||
msgid "There are no recipes in this book yet."
|
||||
msgstr "In diesem Buch sind bisher keine Rezepte."
|
||||
|
||||
#: cookbook/templates/forms/edit_import_recipe.html:5
|
||||
#: cookbook/templates/forms/edit_import_recipe.html:9
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:5
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:9
|
||||
msgid "Import new Recipe"
|
||||
msgstr "Rezept Importieren"
|
||||
|
||||
#: cookbook/templates/forms/edit_import_recipe.html:14
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:37
|
||||
#: cookbook/templates/generic/edit_template.html:23
|
||||
#: cookbook/templates/generic/new_template.html:23
|
||||
#: cookbook/templates/recipe_view.html:207
|
||||
#: .\cookbook\templates\forms\edit_import_recipe.html:14
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:47
|
||||
#: .\cookbook\templates\generic\edit_template.html:23
|
||||
#: .\cookbook\templates\generic\new_template.html:23
|
||||
#: .\cookbook\templates\recipe_view.html:214
|
||||
#: .\cookbook\templates\settings.html:33 .\cookbook\templates\settings.html:47
|
||||
msgid "Save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:7
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:16
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:8
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:18
|
||||
msgid "Edit Recipe"
|
||||
msgstr "Rezept bearbeiten"
|
||||
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:26
|
||||
#: cookbook/templates/recipe_view.html:63
|
||||
msgid "Ingredients"
|
||||
msgstr "Zutaten"
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:37
|
||||
msgid ""
|
||||
"Use <b>Ctrl</b>+<b>Space</b> to insert new Ingredient!<br/>You can also save "
|
||||
"the recipe using <b>Ctrl</b>+<b>Shift</b>+<b>S</b>."
|
||||
msgstr ""
|
||||
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:41
|
||||
#: cookbook/templates/generic/edit_template.html:27
|
||||
#: cookbook/templates/recipe_view.html:7
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:51
|
||||
#: .\cookbook\templates\generic\edit_template.html:27
|
||||
#: .\cookbook\templates\recipe_view.html:7
|
||||
msgid "View"
|
||||
msgstr "Angucken"
|
||||
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:45
|
||||
#: cookbook/templates/generic/edit_template.html:30
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:55
|
||||
#: .\cookbook\templates\generic\edit_template.html:30
|
||||
msgid "Delete original file"
|
||||
msgstr "Original löschen"
|
||||
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:90
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:127
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:159
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:208
|
||||
msgid "Ingredient"
|
||||
msgstr "Zutat"
|
||||
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:95
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:164
|
||||
msgid "Amount"
|
||||
msgstr "Menge"
|
||||
|
||||
#: cookbook/templates/forms/edit_internal_recipe.html:96
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:166
|
||||
msgid "Unit"
|
||||
msgstr "Einheit"
|
||||
|
||||
#: cookbook/templates/generic/delete_template.html:18
|
||||
#: .\cookbook\templates\forms\edit_internal_recipe.html:179
|
||||
msgid "Are you sure that you want to delete this ingredient?"
|
||||
msgstr "Bist du sicher das du diese Zutat löschen willst?"
|
||||
|
||||
#: .\cookbook\templates\forms\ingredients.html:15
|
||||
msgid "Edit Ingredients"
|
||||
msgstr "Zutaten Bearbeiten"
|
||||
|
||||
#: .\cookbook\templates\forms\ingredients.html:16
|
||||
msgid ""
|
||||
"\n"
|
||||
" The following form can be used if, accidentally, two (or more) units "
|
||||
"or ingredients where created that should be\n"
|
||||
" the same.\n"
|
||||
" It merges two units or ingredients and updates all recipes using "
|
||||
"them.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" Dieses Formular kann genutzt werden wenn versehentlich zwei (oder mehr) Einheiten"
|
||||
"oder Zutaten erstellt wurden die eigentlich identisch\n"
|
||||
" sein sollen.\n"
|
||||
" Es vereint zwei Zutaten oder Einheiten und aktualisiert alle entsprechenden "
|
||||
"Rezepte.\n"
|
||||
" "
|
||||
|
||||
#: .\cookbook\templates\forms\ingredients.html:24
|
||||
msgid "Units"
|
||||
msgstr "Einheiten"
|
||||
|
||||
#: .\cookbook\templates\forms\ingredients.html:29
|
||||
msgid "Are you sure that you want to merge these two units ?"
|
||||
msgstr "Bist du sicher diese beiden Einheiten zusammengeführt werden sollen ?"
|
||||
|
||||
#: .\cookbook\templates\forms\ingredients.html:30
|
||||
#: .\cookbook\templates\forms\ingredients.html:39
|
||||
msgid "Merge"
|
||||
msgstr "Zusammenführen"
|
||||
|
||||
#: .\cookbook\templates\forms\ingredients.html:38
|
||||
msgid "Are you sure that you want to merge these two ingredients ?"
|
||||
msgstr "Bist du sicher diese beiden Zutaten zusammengeführt werden sollen ?"
|
||||
|
||||
#: .\cookbook\templates\generic\delete_template.html:18
|
||||
#, python-format
|
||||
msgid "Are you sure you want to delete the %(title)s: <b>%(object)s</b> "
|
||||
msgstr "Bist du sicher das %(title)s: <b>%(object)s</b> gelöscht werden soll"
|
||||
|
||||
#: cookbook/templates/generic/delete_template.html:21
|
||||
#: .\cookbook\templates\generic\delete_template.html:21
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
msgstr "Bestätigen"
|
||||
|
||||
#: cookbook/templates/generic/edit_template.html:6
|
||||
#: cookbook/templates/generic/edit_template.html:14
|
||||
#: .\cookbook\templates\generic\edit_template.html:6
|
||||
#: .\cookbook\templates\generic\edit_template.html:14
|
||||
msgid "Edit"
|
||||
msgstr "Bearbeiten"
|
||||
|
||||
#: cookbook/templates/generic/list_template.html:6
|
||||
#: cookbook/templates/generic/list_template.html:12
|
||||
#: .\cookbook\templates\generic\list_template.html:6
|
||||
#: .\cookbook\templates\generic\list_template.html:12
|
||||
msgid "List"
|
||||
msgstr "Liste"
|
||||
|
||||
#: cookbook/templates/generic/list_template.html:19
|
||||
#: .\cookbook\templates\generic\list_template.html:19
|
||||
msgid "Import all"
|
||||
msgstr "Alle importieren"
|
||||
|
||||
#: cookbook/templates/generic/new_template.html:6
|
||||
#: cookbook/templates/generic/new_template.html:14
|
||||
#: .\cookbook\templates\generic\new_template.html:6
|
||||
#: .\cookbook\templates\generic\new_template.html:14
|
||||
msgid "New"
|
||||
msgstr "Neu"
|
||||
|
||||
#: cookbook/templates/generic/table_template.html:76
|
||||
#: .\cookbook\templates\generic\table_template.html:76
|
||||
msgid "previous"
|
||||
msgstr "vorherige"
|
||||
|
||||
#: cookbook/templates/generic/table_template.html:98
|
||||
#: .\cookbook\templates\generic\table_template.html:98
|
||||
msgid "next"
|
||||
msgstr "nächste"
|
||||
|
||||
#: cookbook/templates/include/recipe_open_modal.html:28
|
||||
#: cookbook/views/edit.py:258 cookbook/views/edit.py:278
|
||||
#: cookbook/views/edit.py:298 cookbook/views/new.py:32
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:28
|
||||
#: .\cookbook\views\edit.py:295 .\cookbook\views\edit.py:354
|
||||
#: .\cookbook\views\edit.py:374 .\cookbook\views\new.py:34
|
||||
msgid "Recipe"
|
||||
msgstr "Rezept"
|
||||
|
||||
#: cookbook/templates/include/recipe_open_modal.html:39
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:39
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
|
||||
#: cookbook/templates/include/recipe_open_modal.html:56
|
||||
#: .\cookbook\templates\include\recipe_open_modal.html:56
|
||||
msgid "Open Recipe"
|
||||
msgstr "Rezept öffnen"
|
||||
|
||||
#: cookbook/templates/include/storage_backend_warning.html:4
|
||||
#: .\cookbook\templates\include\storage_backend_warning.html:4
|
||||
msgid "Security Warning"
|
||||
msgstr "Sicherheitswarnung"
|
||||
|
||||
#: cookbook/templates/include/storage_backend_warning.html:5
|
||||
#: .\cookbook\templates\include\storage_backend_warning.html:5
|
||||
msgid ""
|
||||
"\n"
|
||||
" The <b>Password and Token</b> field are stored as <b>plain text</b> "
|
||||
@@ -327,48 +467,52 @@ msgstr ""
|
||||
"oder Accounts mit limitiertem Zugriff verwendet werden.\n"
|
||||
" "
|
||||
|
||||
#: cookbook/templates/index.html:21
|
||||
#: .\cookbook\templates\index.html:21
|
||||
msgid "Search recipe ..."
|
||||
msgstr "Suche Rezept ..."
|
||||
|
||||
#: cookbook/templates/index.html:40
|
||||
#: .\cookbook\templates\index.html:40
|
||||
msgid "Advanced Search"
|
||||
msgstr "Erweiterte Suche"
|
||||
|
||||
#: cookbook/templates/index.html:59
|
||||
#: .\cookbook\templates\index.html:62
|
||||
msgid "Log in to view Recipies"
|
||||
msgstr "Bitte einloggen um Rezepte zu sehen"
|
||||
|
||||
#: cookbook/templates/recipe_view.html:27
|
||||
#: .\cookbook\templates\meal_plan.html:20
|
||||
msgid "Week"
|
||||
msgstr "Woche"
|
||||
|
||||
#: .\cookbook\templates\recipe_view.html:31
|
||||
msgid "in"
|
||||
msgstr "in"
|
||||
|
||||
#: cookbook/templates/recipe_view.html:32
|
||||
#: cookbook/templates/recipe_view.html:174
|
||||
#: .\cookbook\templates\recipe_view.html:36
|
||||
#: .\cookbook\templates\recipe_view.html:181
|
||||
msgid "by"
|
||||
msgstr "von"
|
||||
|
||||
#: cookbook/templates/recipe_view.html:43
|
||||
#: .\cookbook\templates\recipe_view.html:47
|
||||
msgid "Preparation time ca."
|
||||
msgstr "Zubereitungszeit ca."
|
||||
|
||||
#: cookbook/templates/recipe_view.html:48
|
||||
#: .\cookbook\templates\recipe_view.html:52
|
||||
msgid "Waiting time ca."
|
||||
msgstr "Zubereitungszeit ca."
|
||||
|
||||
#: cookbook/templates/recipe_view.html:110
|
||||
#: .\cookbook\templates\recipe_view.html:114
|
||||
msgid "Recipe Image"
|
||||
msgstr "Rezept Bild"
|
||||
|
||||
#: cookbook/templates/recipe_view.html:126
|
||||
#: .\cookbook\templates\recipe_view.html:133
|
||||
msgid "View external recipe"
|
||||
msgstr "Externes Rezept ansehen"
|
||||
|
||||
#: cookbook/templates/recipe_view.html:137
|
||||
#: .\cookbook\templates\recipe_view.html:144
|
||||
msgid "External recipe"
|
||||
msgstr "Externes Rezept"
|
||||
|
||||
#: cookbook/templates/recipe_view.html:139
|
||||
#: .\cookbook\templates\recipe_view.html:146
|
||||
msgid ""
|
||||
"\n"
|
||||
" This is an external recipe, which means you can only "
|
||||
@@ -386,56 +530,81 @@ msgstr ""
|
||||
"bleibt weiterhin verfügbar.\n"
|
||||
" "
|
||||
|
||||
#: cookbook/templates/recipe_view.html:147
|
||||
#: .\cookbook\templates\recipe_view.html:154
|
||||
msgid "Convert now!"
|
||||
msgstr "Jetzt umwandeln!"
|
||||
|
||||
#: cookbook/templates/recipe_view.html:156
|
||||
#: .\cookbook\templates\recipe_view.html:163
|
||||
msgid "Comments"
|
||||
msgstr "Kommentare"
|
||||
|
||||
#: cookbook/templates/recipe_view.html:165 cookbook/views/edit.py:191
|
||||
#: cookbook/views/edit.py:353
|
||||
#: .\cookbook\templates\recipe_view.html:172 .\cookbook\views\edit.py:212
|
||||
#: .\cookbook\views\edit.py:429
|
||||
msgid "Comment"
|
||||
msgstr "Kommentar"
|
||||
|
||||
#: cookbook/templates/registration/login.html:8
|
||||
#: .\cookbook\templates\registration\login.html:8
|
||||
msgid "Your username and password didn't match. Please try again."
|
||||
msgstr "Nutzername oder Passwort falsch. Bitte versuch es erneut."
|
||||
|
||||
#: cookbook/templates/stats.html:4
|
||||
#: .\cookbook\templates\settings.html:17
|
||||
msgid "Language"
|
||||
msgstr "Sprache"
|
||||
|
||||
#: .\cookbook\templates\settings.html:42
|
||||
msgid "Style"
|
||||
msgstr "Stil"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:15
|
||||
msgid "Shopping List"
|
||||
msgstr "Einkaufsliste"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:20
|
||||
msgid "Load"
|
||||
msgstr "Laden"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:37
|
||||
#: .\cookbook\templates\shopping_list.html:55
|
||||
msgid "Copy list to clipboard"
|
||||
msgstr "Kopiere Liste in Zwischenablage"
|
||||
|
||||
#: .\cookbook\templates\shopping_list.html:48
|
||||
msgid "Copied!"
|
||||
msgstr "Kopiert!"
|
||||
|
||||
#: .\cookbook\templates\stats.html:4
|
||||
msgid "Stats"
|
||||
msgstr "Statistiken"
|
||||
|
||||
#: cookbook/templates/stats.html:17
|
||||
#: .\cookbook\templates\stats.html:17
|
||||
msgid "Number of objects"
|
||||
msgstr "Anzahl der Objekte"
|
||||
|
||||
#: cookbook/templates/stats.html:20
|
||||
#: .\cookbook\templates\stats.html:20
|
||||
msgid "Recipes"
|
||||
msgstr "Rezepte"
|
||||
|
||||
#: cookbook/templates/stats.html:24
|
||||
#: .\cookbook\templates\stats.html:24
|
||||
msgid "Recipe Imports"
|
||||
msgstr "Rezept Importe"
|
||||
|
||||
#: cookbook/templates/stats.html:32
|
||||
#: .\cookbook\templates\stats.html:32
|
||||
msgid "Objects stats"
|
||||
msgstr "Objekt Statistiken"
|
||||
|
||||
#: cookbook/templates/stats.html:35
|
||||
#: .\cookbook\templates\stats.html:35
|
||||
msgid "Recipes without Keywords"
|
||||
msgstr "Rezepte ohne Schlagwort"
|
||||
|
||||
#: cookbook/views/api.py:63
|
||||
#: .\cookbook\views\api.py:63
|
||||
msgid "Sync successful!"
|
||||
msgstr "Synchronisation erfolgreich!"
|
||||
|
||||
#: cookbook/views/api.py:66
|
||||
#: .\cookbook\views\api.py:66
|
||||
msgid "Error synchronizing with Storage"
|
||||
msgstr "Fehler beim Synchronisieren"
|
||||
|
||||
#: cookbook/views/data.py:71
|
||||
#: .\cookbook\views\data.py:71
|
||||
#, python-format
|
||||
msgid "Batch edit done. %(count)d recipe was updated."
|
||||
msgid_plural "Batch edit done. %(count)d Recipes where updated."
|
||||
@@ -443,65 +612,77 @@ msgstr[0] "Massenbearbeitung erfolgreich. %(count)d Rezept wurde aktualisiert."
|
||||
msgstr[1] ""
|
||||
"Massenbearbeitung erfolgreich. %(count)d Rezepte wurden aktualisiert."
|
||||
|
||||
#: cookbook/views/edit.py:88
|
||||
#: .\cookbook\views\edit.py:109
|
||||
msgid "Recipe saved!"
|
||||
msgstr "Rezept gespeichert"
|
||||
|
||||
#: cookbook/views/edit.py:91 cookbook/views/new.py:87
|
||||
msgid "There was an error importing this recipe!"
|
||||
msgstr "Beim importieren des Rezeptes ist ein Fehler aufgetreten"
|
||||
#: .\cookbook\views\edit.py:111
|
||||
msgid "There was an error saving this recipe!"
|
||||
msgstr "Es gab einen Fehler beim Speichern des Rezepts"
|
||||
|
||||
#: cookbook/views/edit.py:139 cookbook/views/edit.py:182
|
||||
#: .\cookbook\views\edit.py:160 .\cookbook\views\edit.py:203
|
||||
msgid "You cannot edit this comment!"
|
||||
msgstr "Du kannst diesen Kommentar nicht bearbeiten!"
|
||||
|
||||
#: cookbook/views/edit.py:158
|
||||
#: .\cookbook\views\edit.py:179
|
||||
msgid "Storage saved!"
|
||||
msgstr "Speicherquelle gespeichert"
|
||||
|
||||
#: cookbook/views/edit.py:161
|
||||
#: .\cookbook\views\edit.py:182
|
||||
msgid "There was an error updating this storage backend.!"
|
||||
msgstr "Es gab einen Fehler beim aktualisierung dieser Speicher Quelle"
|
||||
|
||||
#: cookbook/views/edit.py:208 cookbook/views/edit.py:309
|
||||
#: cookbook/views/lists.py:34
|
||||
#: .\cookbook\views\edit.py:229 .\cookbook\views\edit.py:385
|
||||
#: .\cookbook\views\lists.py:34
|
||||
msgid "Import"
|
||||
msgstr "Rezept Importieren"
|
||||
|
||||
#: cookbook/views/edit.py:224 cookbook/views/edit.py:364
|
||||
#: cookbook/views/new.py:110
|
||||
#: .\cookbook\views\edit.py:245 .\cookbook\views\edit.py:440
|
||||
#: .\cookbook\views\new.py:112
|
||||
msgid "Recipe Book"
|
||||
msgstr "Rezeptbuch"
|
||||
|
||||
#: cookbook/views/edit.py:246
|
||||
#: .\cookbook\views\edit.py:283
|
||||
msgid "Changes saved!"
|
||||
msgstr "Änderungen gespeichert"
|
||||
|
||||
#: cookbook/views/edit.py:250
|
||||
#: .\cookbook\views\edit.py:287
|
||||
msgid "Error saving changes!"
|
||||
msgstr "Fehler beim Speichern der Daten."
|
||||
|
||||
#: cookbook/views/edit.py:320
|
||||
#: .\cookbook\views\edit.py:317
|
||||
msgid "Units merged!"
|
||||
msgstr "Einheiten zusammengeführt"
|
||||
|
||||
#: .\cookbook\views\edit.py:330
|
||||
msgid "Ingredients merged!"
|
||||
msgstr "Zutaten zusammengeführt"
|
||||
|
||||
#: .\cookbook\views\edit.py:396
|
||||
msgid "Monitor"
|
||||
msgstr "Monitor"
|
||||
|
||||
#: cookbook/views/edit.py:342 cookbook/views/lists.py:42
|
||||
#: cookbook/views/new.py:62
|
||||
#: .\cookbook\views\edit.py:418 .\cookbook\views\lists.py:42
|
||||
#: .\cookbook\views\new.py:64
|
||||
msgid "Storage Backend"
|
||||
msgstr "Speicher Quelle"
|
||||
|
||||
#: cookbook/views/edit.py:375
|
||||
#: .\cookbook\views\edit.py:451
|
||||
msgid "Bookmarks"
|
||||
msgstr "Lesezeichen"
|
||||
|
||||
#: cookbook/views/new.py:84
|
||||
#: .\cookbook\views\new.py:86
|
||||
msgid "Imported new recipe!"
|
||||
msgstr "Importier neue Rezepte"
|
||||
|
||||
#: cookbook/views/views.py:42
|
||||
#: .\cookbook\views\new.py:89
|
||||
msgid "There was an error importing this recipe!"
|
||||
msgstr "Beim importieren des Rezeptes ist ein Fehler aufgetreten"
|
||||
|
||||
#: .\cookbook\views\views.py:44
|
||||
msgid "Comment saved!"
|
||||
msgstr "Kommentar gespeichert"
|
||||
|
||||
#: cookbook/views/views.py:52
|
||||
#: .\cookbook\views\views.py:54
|
||||
msgid "Bookmark saved!"
|
||||
msgstr "Lesezeichen gespeichert"
|
||||
|
||||
23
cookbook/migrations/0026_auto_20200219_1605.py
Normal file
23
cookbook/migrations/0026_auto_20200219_1605.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.0.2 on 2020-02-19 15:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0025_userpreference_nav_color'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='recipe',
|
||||
name='cors_link',
|
||||
field=models.CharField(blank=True, max_length=1024, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='recipe',
|
||||
name='link',
|
||||
field=models.CharField(blank=True, max_length=512, null=True),
|
||||
),
|
||||
]
|
||||
@@ -84,7 +84,8 @@ class Recipe(models.Model):
|
||||
storage = models.ForeignKey(Storage, on_delete=models.PROTECT, blank=True, null=True)
|
||||
file_uid = models.CharField(max_length=256, default="")
|
||||
file_path = models.CharField(max_length=512, default="")
|
||||
link = models.CharField(max_length=512, default="")
|
||||
link = models.CharField(max_length=512, null=True, blank=True)
|
||||
cors_link = models.CharField(max_length=1024, null=True, blank=True)
|
||||
keywords = models.ManyToManyField(Keyword, blank=True)
|
||||
working_time = models.IntegerField(default=0)
|
||||
waiting_time = models.IntegerField(default=0)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import base64
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
@@ -88,6 +89,16 @@ class Dropbox(Provider):
|
||||
response = Dropbox.create_share_link(recipe)
|
||||
return response['url']
|
||||
|
||||
@staticmethod
|
||||
def get_base64_file(recipe):
|
||||
if not recipe.link:
|
||||
recipe.link = Dropbox.get_share_link(recipe)
|
||||
recipe.save()
|
||||
|
||||
response = requests.get(recipe.link.replace('www.dropbox.', 'dl.dropboxusercontent.'))
|
||||
|
||||
return base64.b64encode(response.content)
|
||||
|
||||
@staticmethod
|
||||
def rename_file(recipe, new_name):
|
||||
url = "https://api.dropboxapi.com/2/files/move_v2"
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import base64
|
||||
import os
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
import webdav3.client as wc
|
||||
import requests
|
||||
|
||||
from io import BytesIO
|
||||
from requests.auth import HTTPBasicAuth
|
||||
|
||||
from cookbook.models import Recipe, RecipeImport, SyncLog
|
||||
@@ -81,6 +83,20 @@ class Nextcloud(Provider):
|
||||
|
||||
return Nextcloud.create_share_link(recipe)
|
||||
|
||||
@staticmethod
|
||||
def get_base64_file(recipe):
|
||||
client = Nextcloud.get_client(recipe.storage)
|
||||
|
||||
tmp_file_path = tempfile.gettempdir() + '/' + recipe.name + '.pdf'
|
||||
|
||||
client.download_file(remote_path=recipe.file_path, local_path=tmp_file_path)
|
||||
|
||||
val = base64.b64encode(open(tmp_file_path, 'rb').read())
|
||||
|
||||
os.remove(tmp_file_path)
|
||||
|
||||
return val
|
||||
|
||||
@staticmethod
|
||||
def rename_file(recipe, new_name):
|
||||
client = Nextcloud.get_client(recipe.storage)
|
||||
|
||||
@@ -11,10 +11,14 @@ class Provider:
|
||||
def get_share_link(recipe):
|
||||
raise Exception('Method not implemented in storage provider')
|
||||
|
||||
@staticmethod
|
||||
def get_base64_file(recipe):
|
||||
raise Exception('Method not implemented in storage provider')
|
||||
|
||||
@staticmethod
|
||||
def rename_file(recipe, new_name):
|
||||
raise Exception('Method not implemented in storage provider')
|
||||
|
||||
@staticmethod
|
||||
def delete_file(recipe, new_name):
|
||||
def delete_file(recipe):
|
||||
raise Exception('Method not implemented in storage provider')
|
||||
|
||||
@@ -8,8 +8,7 @@ from .models import *
|
||||
|
||||
class RecipeTable(tables.Table):
|
||||
id = tables.LinkColumn('edit_recipe', args=[A('id')])
|
||||
name = tables.TemplateColumn(
|
||||
"<a href='#' onClick='openRecipe({{record.id}})'>{{record.name}}</a>")
|
||||
name = tables.LinkColumn('view_recipe', args=[A('id')])
|
||||
all_tags = tables.Column(
|
||||
attrs={'td': {'class': 'd-none d-lg-table-cell'}, 'th': {'class': 'd-none d-lg-table-cell'}})
|
||||
|
||||
|
||||
@@ -74,18 +74,22 @@
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item active">
|
||||
<li class="nav-item {% if request.resolver_match.url_name == "index" %}active{% endif %}">
|
||||
<a class="nav-link" href="{% url 'index' %}"><i class="fas fa-book"></i> {% trans 'Cookbook' %}<span
|
||||
class="sr-only">(current)</span></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<li class="nav-item {% if request.resolver_match.url_name == "view_books" %}active{% endif %}">
|
||||
<a class="nav-link" href="{% url 'view_books' %}"><i class="fas fa-bookmark"></i> {% trans 'Books' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<li class="nav-item {% if request.resolver_match.url_name == "view_plan" %}active{% endif %}">
|
||||
<a class="nav-link" href="{% url 'view_plan' %}"><i class="fas fa-calendar"></i> {% trans 'Meal-Plan' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item {% if request.resolver_match.url_name == "view_shopping" %}active{% endif %}">
|
||||
<a class="nav-link" href="{% url 'view_shopping' %}"><i class="fas fa-shopping-cart"></i> {% trans 'Shopping' %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown"
|
||||
aria-haspopup="true" aria-expanded="false">
|
||||
@@ -121,7 +125,7 @@
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="nav-item">
|
||||
<li class="nav-item {% if request.resolver_match.url_name == "view_settings" %}active{% endif %}">
|
||||
<a class="nav-link" href="{% url 'view_settings' %}"><i
|
||||
class="fas fa-user-cog"></i> {% trans 'Settings' %}</a>
|
||||
</li>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
{% for r in b.recipes %}
|
||||
<div class="row">
|
||||
<div class="col col-md-10">
|
||||
<li><a href="#" onClick='openRecipe({{ r.recipe.pk }})'>{{ r.recipe.name }}</a></li>
|
||||
<li><a href="{% url 'view_recipe' r.recipe.pk %}">{{ r.recipe.name }}</a></li>
|
||||
</div>
|
||||
<div class="col col-md-2" style="text-align: right">
|
||||
<a href="{% url 'delete_recipe_book_entry' r.pk %}"><i class="fas fa-trash-alt"></i></a>
|
||||
@@ -58,5 +58,4 @@
|
||||
<br/>
|
||||
{% endfor %}
|
||||
|
||||
{% include 'include/recipe_open_modal.html' %}
|
||||
{% endblock %}
|
||||
@@ -7,7 +7,7 @@
|
||||
{% block title %}{% trans "Cookbook" %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
{{ form.media }}
|
||||
{{ units_form.media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@@ -24,11 +24,19 @@
|
||||
<h4>{% trans 'Units' %}</h4>
|
||||
<form action="{% url 'edit_ingredient' %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
{{ units_form|crispy }}
|
||||
<button class="btn btn-danger" type="submit"
|
||||
onclick="confirm('{% trans 'Are you sure that you want to merge these two units ?' %}')"><i
|
||||
class="fas fa-sync-alt"></i> {% trans 'Merge' %}</button>
|
||||
</form>
|
||||
|
||||
<h4>{% trans 'Ingredients' %}</h4>
|
||||
<form action="{% url 'edit_ingredient' %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ ingredients_form|crispy }}
|
||||
<button class="btn btn-danger" type="submit"
|
||||
onclick="confirm('{% trans 'Are you sure that you want to merge these two ingredients ?' %}')"><i
|
||||
class="fas fa-sync-alt"></i> {% trans 'Merge' %}</button>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@@ -23,14 +23,15 @@
|
||||
<button class="btn btn-success" type="submit"><i class="fas fa-save"></i> {% trans 'Save' %}</button>
|
||||
</form>
|
||||
|
||||
{% if default_recipe %}
|
||||
<script type="text/javascript">
|
||||
|
||||
<script type="text/javascript">
|
||||
{% if default_recipe %}
|
||||
$(document).ready(function () {
|
||||
$('#id_recipe').val({{ default_recipe.pk }}).trigger('change');
|
||||
});
|
||||
{% endif %}
|
||||
</script>
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -43,15 +43,12 @@
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function openRecipe(id, force_external = false) {
|
||||
function openRecipe(id) {
|
||||
var link = $('#a_recipe_open');
|
||||
link.hide();
|
||||
$('#div_loader').show();
|
||||
|
||||
var url = "{% url 'api_get_file_link' recipe_id=12345 %}".replace(/12345/, id);
|
||||
if (force_external) {
|
||||
url = "{% url 'api_get_external_file_link' recipe_id=12345 %}".replace(/12345/, id);
|
||||
}
|
||||
var url = "{% url 'api_get_external_file_link' recipe_id=12345 %}".replace(/12345/, id);
|
||||
|
||||
link.text("{% trans 'Open Recipe' %}");
|
||||
$('#modal_recipe').modal('show');
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
<div>
|
||||
{{ filter.form.keywords | as_crispy_field }}
|
||||
</div>
|
||||
<div>
|
||||
{{ filter.form.ingredients | as_crispy_field }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -60,6 +63,4 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% include 'include/recipe_open_modal.html' %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -56,7 +56,7 @@
|
||||
<td>
|
||||
{% for mp in days_value %}
|
||||
<a href="{% url 'edit_plan' mp.pk %}"><i class="fas fa-edit"></i></a>
|
||||
<a href="#" onclick="openRecipe({{ mp.recipe.id }})">{{ mp.recipe.name }}</a><br/>
|
||||
<a href="{% url 'view_recipe' mp.recipe.id %}">{{ mp.recipe.name }}</a><br/>
|
||||
{% endfor %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
@@ -67,6 +67,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'include/recipe_open_modal.html' %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -9,6 +9,19 @@
|
||||
{% block extra_head %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pretty-checkbox@3.0/dist/pretty-checkbox.min.css"
|
||||
integrity="sha384-ICB8i/maQ/5+tGLDUEcswB7Ch+OO9Oj8Z4Ov/Gs0gxqfTgLLkD3F43MhcEJ2x6/D" crossorigin="anonymous">
|
||||
|
||||
|
||||
<!-- prevent weired character stuff escaping the pdf box -->
|
||||
<style>
|
||||
.textLayer > span {
|
||||
color: transparent;
|
||||
position: absolute;
|
||||
white-space: pre;
|
||||
cursor: text;
|
||||
transform-origin: 0% 0%;
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@@ -20,8 +33,10 @@
|
||||
<div class="col col-md-3 d-print-none" style="text-align: right">
|
||||
<button class="btn btn-success" onclick="$('#bookmarkModal').modal({'show':true})"><i
|
||||
class="fas fa-bookmark"></i></button>
|
||||
<a class="btn btn-warning" href="{% url 'view_shopping' %}?r={{ recipe.pk }}"><i
|
||||
class="fas fa-shopping-cart"></i></a>
|
||||
{% if ingredients %}
|
||||
<a class="btn btn-warning" href="{% url 'view_shopping' %}?r={{ recipe.pk }}"><i
|
||||
class="fas fa-shopping-cart"></i></a>
|
||||
{% endif %}
|
||||
<a class="btn btn-info" href="{% url 'new_plan' %}?recipe={{ recipe.pk }}"><i
|
||||
class="fas fa-calendar"></i></a>
|
||||
</div>
|
||||
@@ -130,30 +145,98 @@
|
||||
|
||||
|
||||
{% if recipe.storage %}
|
||||
<a href='#' onClick='openRecipe({{ recipe.id }}, true)' class="d-print-none">{% trans 'View external recipe' %}
|
||||
<i
|
||||
class="fas fa-external-link-alt"></i></a>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
{% if recipe.internal %}
|
||||
<a href='#' onClick='openRecipe({{ recipe.id }})'
|
||||
class="d-print-none">{% trans 'View external recipe' %} <i class="fas fa-external-link-alt"></i></a>
|
||||
{% else %}
|
||||
|
||||
{% if not recipe.internal %}
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<div class="card border-info">
|
||||
<div class="card-body text-info">
|
||||
<h5 class="card-title">{% trans 'External recipe' %}</h5>
|
||||
<p class="card-text">
|
||||
{% blocktrans %}
|
||||
This is an external recipe, which means you can only view it by opening the link above.
|
||||
You can convert this recipe to a fancy recipe by pressing the convert button. The original file
|
||||
will still be accessible.
|
||||
{% endblocktrans %}.
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="{% url 'edit_convert_recipe' recipe.pk %}"
|
||||
class="card-link btn btn-info">{% trans 'Convert now!' %}</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col col-12" style="margin-top: 2vh">
|
||||
<div class="loader" id="id_loader"></div>
|
||||
|
||||
<div id="viewerContainer" class="border">
|
||||
<div id="viewer" class="pdfViewer"></div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning" role="alert" id="id_warning_no_preview" style="display: none">
|
||||
{% trans 'Cloud not show a file preview. Maybe its not a PDF ?' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col col-12" style="margin-top: 2vh">
|
||||
<div class="card border-info">
|
||||
<div class="card-body text-info">
|
||||
<h5 class="card-title">{% trans 'External recipe' %}</h5>
|
||||
<p class="card-text">
|
||||
{% blocktrans %}
|
||||
This is an external recipe, which means you can only view it by opening the link
|
||||
above.
|
||||
You can convert this recipe to a fancy recipe by pressing the convert button. The
|
||||
original
|
||||
file
|
||||
will still be accessible.
|
||||
{% endblocktrans %}.
|
||||
<br/>
|
||||
<br/>
|
||||
<a href="{% url 'edit_convert_recipe' recipe.pk %}"
|
||||
class="card-link btn btn-info">{% trans 'Convert now!' %}</a>
|
||||
<a href='#' onClick='openRecipe({{ recipe.id }})'
|
||||
class="d-print-none btn btn-warning">{% trans 'View external recipe' %} <i
|
||||
class="fas fa-external-link-alt"></i></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.3.200/pdf.min.js"
|
||||
integrity="sha256-J4Z8Fhj2MITUakMQatkqOVdtqodUlwHtQ/ey6fSsudE="
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.3.200/pdf_viewer.js"
|
||||
integrity="sha256-JW7ackRikw8/UM/hHV6vKaZBYc+t2ZQ77sd3LWR8vh8="
|
||||
crossorigin="anonymous"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var url = "{% url 'api_get_recipe_file' recipe_id=12345 %}".replace(/12345/, {{ recipe.id }});
|
||||
$('#viewerContainer').hide();
|
||||
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function () {
|
||||
if (this.readyState === 4 && this.status === 200) {
|
||||
var base64Pdf = atob(this.responseText);
|
||||
$('#id_loader').hide();
|
||||
$('#viewerContainer').show();
|
||||
|
||||
var container = document.getElementById("viewerContainer");
|
||||
|
||||
var pdfViewer = new pdfjsViewer.PDFViewer({
|
||||
container: container,
|
||||
});
|
||||
|
||||
document.addEventListener("pagesinit", function () {
|
||||
// We can use pdfViewer now, e.g. let's change default scale.
|
||||
pdfViewer.currentScaleValue = "page-width";
|
||||
|
||||
});
|
||||
|
||||
var loadingTask = pdfjsLib.getDocument({
|
||||
data: base64Pdf
|
||||
});
|
||||
|
||||
loadingTask.promise.then(function (pdfDocument) {
|
||||
// Document loaded, specifying document for the viewer and
|
||||
// the (optional) linkService.
|
||||
pdfViewer.setDocument(pdfDocument);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
xhttp.open("GET", url, true);
|
||||
xhttp.send();
|
||||
|
||||
</script>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -22,14 +22,22 @@
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
<button class="btn btn-success" onclick="copy()"><i class="far fa-copy"></i></button>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
<!--// @formatter:off-->
|
||||
<textarea id="id_list" style="height: 50vh" class="form-control">{% for i in ingredients %}- [ ] {{ i.amount.normalize }} {{ i.unit }} {{ i.ingredient.name }} {% endfor %}</textarea>
|
||||
<textarea id="id_list" class="form-control" rows="{{ ingredients|length|add:1 }}">{% for i in ingredients %}{% if markdown_format %}- [ ]{% endif %} {{ i.amount.normalize }} {{ i.unit }} {{ i.ingredient.name }} {% endfor %}</textarea>
|
||||
<!--// @formatter:on-->
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col col-md-12 text-center">
|
||||
<button class="btn btn-success" onclick="copy()" style="width: 15vw" data-toggle="tooltip"
|
||||
data-placement="top" title="{% trans 'Copy list to clipboard' %}" id="id_btn_copy" onmouseout="resetTooltip()"><i
|
||||
class="far fa-copy"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function copy() {
|
||||
@@ -37,8 +45,20 @@
|
||||
|
||||
list.select();
|
||||
|
||||
$('#id_btn_copy').attr('data-original-title','{% trans 'Copied!' %}').tooltip('show');
|
||||
|
||||
document.execCommand("copy");
|
||||
}
|
||||
|
||||
function resetTooltip() {
|
||||
setTimeout(function () {
|
||||
$('#id_btn_copy').attr('data-original-title','{% trans 'Copy list to clipboard' %}');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
})
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
@@ -60,8 +60,8 @@ urlpatterns = [
|
||||
path('data/sync/wait', data.sync_wait, name='data_sync_wait'),
|
||||
path('data/statistics', data.statistics, name='data_stats'),
|
||||
|
||||
path('api/get_file_link/<int:recipe_id>/', api.get_file_link, name='api_get_file_link'),
|
||||
path('api/get_external_file_link/<int:recipe_id>/', api.get_external_file_link, name='api_get_external_file_link'),
|
||||
path('api/get_recipe_file/<int:recipe_id>/', api.get_recipe_file, name='api_get_recipe_file'),
|
||||
|
||||
path('api/sync_all/', api.sync_all, name='api_sync'),
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponse
|
||||
from django.http import HttpResponse, FileResponse
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from django.contrib.auth.decorators import login_required
|
||||
@@ -10,40 +10,40 @@ from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
|
||||
|
||||
@login_required
|
||||
def get_file_link(request, recipe_id):
|
||||
recipe = Recipe.objects.get(id=recipe_id)
|
||||
def get_recipe_provider(recipe):
|
||||
if recipe.storage.method == Storage.DROPBOX:
|
||||
return Dropbox
|
||||
elif recipe.storage.method == Storage.NEXTCLOUD:
|
||||
return Nextcloud
|
||||
else:
|
||||
raise Exception('Provider not implemented')
|
||||
|
||||
if recipe.internal:
|
||||
return HttpResponse(reverse('view_recipe', args=[recipe_id]))
|
||||
if recipe.storage.method == Storage.DROPBOX: # TODO move to central location (as all provider related functions)
|
||||
if recipe.link == "":
|
||||
recipe.link = Dropbox.get_share_link(recipe) # TODO response validation
|
||||
recipe.save()
|
||||
if recipe.storage.method == Storage.NEXTCLOUD:
|
||||
if recipe.link == "":
|
||||
recipe.link = Nextcloud.get_share_link(recipe) # TODO response validation
|
||||
recipe.save()
|
||||
|
||||
return HttpResponse(recipe.link)
|
||||
def update_recipe_links(recipe):
|
||||
if not recipe.link:
|
||||
recipe.link = get_recipe_provider(recipe).get_share_link(recipe) # TODO response validation in apis
|
||||
|
||||
recipe.save()
|
||||
|
||||
|
||||
@login_required
|
||||
def get_external_file_link(request, recipe_id):
|
||||
recipe = Recipe.objects.get(id=recipe_id)
|
||||
|
||||
if recipe.storage.method == Storage.DROPBOX: # TODO move to central location (as all provider related functions)
|
||||
if recipe.link == "":
|
||||
recipe.link = Dropbox.get_share_link(recipe) # TODO response validation
|
||||
recipe.save()
|
||||
if recipe.storage.method == Storage.NEXTCLOUD:
|
||||
if recipe.link == "":
|
||||
recipe.link = Nextcloud.get_share_link(recipe) # TODO response validation
|
||||
recipe.save()
|
||||
if not recipe.link:
|
||||
update_recipe_links(recipe)
|
||||
|
||||
return HttpResponse(recipe.link)
|
||||
|
||||
|
||||
@login_required
|
||||
def get_recipe_file(request, recipe_id):
|
||||
recipe = Recipe.objects.get(id=recipe_id)
|
||||
if not recipe.cors_link:
|
||||
update_recipe_links(recipe)
|
||||
|
||||
return HttpResponse(get_recipe_provider(recipe).get_base64_file(recipe))
|
||||
|
||||
|
||||
@login_required
|
||||
def sync_all(request):
|
||||
monitors = Sync.objects.filter(active=True)
|
||||
|
||||
@@ -15,7 +15,7 @@ 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, UnitMergeForm
|
||||
MealPlanForm, UnitMergeForm, IngredientMergeForm
|
||||
from cookbook.models import Recipe, Sync, Keyword, RecipeImport, Storage, Comment, RecipeIngredient, RecipeBook, \
|
||||
RecipeBookEntry, MealPlan, Unit, Ingredient
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
@@ -302,23 +302,41 @@ class RecipeUpdate(LoginRequiredMixin, UpdateView):
|
||||
@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 = RecipeIngredient.objects.filter(unit=old_unit).all()
|
||||
for i in ingredients:
|
||||
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 = RecipeIngredient.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!'))
|
||||
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})
|
||||
ingredients_form = IngredientMergeForm(request.POST, prefix=IngredientMergeForm.prefix)
|
||||
if ingredients_form.is_valid():
|
||||
new_ingredient = ingredients_form.cleaned_data['new_ingredient']
|
||||
old_ingredient = ingredients_form.cleaned_data['old_ingredient']
|
||||
recipe_ingredients = RecipeIngredient.objects.filter(ingredient=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})
|
||||
|
||||
|
||||
# Generic Delete views
|
||||
|
||||
@@ -117,10 +117,13 @@ def meal_plan(request):
|
||||
|
||||
@login_required
|
||||
def shopping_list(request):
|
||||
markdown_format = True
|
||||
|
||||
if request.method == "POST":
|
||||
form = RecipeForm(request.POST)
|
||||
form = ShoppingForm(request.POST)
|
||||
if form.is_valid():
|
||||
recipes = form.cleaned_data['recipe']
|
||||
markdown_format = form.cleaned_data['markdown_format']
|
||||
else:
|
||||
recipes = []
|
||||
else:
|
||||
@@ -132,15 +135,23 @@ def shopping_list(request):
|
||||
if Recipe.objects.filter(pk=int(r)).exists():
|
||||
recipes.append(int(r))
|
||||
|
||||
form = RecipeForm(initial={'recipe': recipes})
|
||||
form = ShoppingForm(initial={'recipe': recipes})
|
||||
|
||||
ingredients = []
|
||||
|
||||
for r in recipes:
|
||||
for i in RecipeIngredient.objects.filter(recipe=r).all():
|
||||
ingredients.append(i)
|
||||
for ri in RecipeIngredient.objects.filter(recipe=r).all():
|
||||
index = None
|
||||
for x, ig in enumerate(ingredients):
|
||||
if ri.ingredient == ig.ingredient and ri.unit == ig.unit:
|
||||
index = x
|
||||
|
||||
return render(request, 'shopping_list.html', {'ingredients': ingredients, 'recipes': recipes, 'form': form})
|
||||
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})
|
||||
|
||||
|
||||
@login_required
|
||||
|
||||
Binary file not shown.
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-13 12:08+0100\n"
|
||||
"POT-Creation-Date: 2020-02-18 23:20+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,10 +18,10 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: recipes/settings.py:136
|
||||
#: .\recipes\settings.py:136
|
||||
msgid "German"
|
||||
msgstr "Deutsch"
|
||||
|
||||
#: recipes/settings.py:137
|
||||
#: .\recipes\settings.py:137
|
||||
msgid "English"
|
||||
msgstr "Englisch"
|
||||
|
||||
Reference in New Issue
Block a user