Compare commits

..

46 Commits
1.0.1 ... 1.0.2

Author SHA1 Message Date
vabene1111
6faabe3759 compiled messages 2021-11-23 18:18:07 +01:00
vabene1111
69acca7de1 Merge branch 'develop' 2021-11-23 18:17:35 +01:00
vabene1111
9d8c08341f fixed doc links 2021-11-23 18:09:04 +01:00
vabene1111
d488559e42 added setting to disable tree fix 2021-11-23 18:02:44 +01:00
vabene1111
85f7740e9b Merge pull request #1081 from RickeyShideler/patch-2
EN Text: Various grammar corrections
2021-11-23 17:04:12 +01:00
vabene1111
72e831afcf Merge pull request #1082 from TomHutter/k8s-install
K8s install
2021-11-23 17:03:01 +01:00
Tom Hutter
cb59f046c0 added comments to 15-secrets.yaml 2021-11-21 20:24:07 +01:00
Tom Hutter
25d505161f Changed k8s installation files for a bit more sophisticated setup. 2021-11-21 20:14:02 +01:00
RickeyShideler
62aa62b90f EN Text: Various grammar corrections 2021-11-21 12:06:54 -06:00
vabene1111
3fe5340592 updated middleware 2021-11-18 16:43:44 +01:00
vabene1111
9233cb9cf9 fixed token auth request space variable 2021-11-18 13:08:29 +01:00
Luka
fd9f6f6dca Translated using Weblate (Slovenian)
Currently translated at 5.5% (28 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/sl/
2021-11-16 06:06:32 +00:00
vabene1111
ecd4ce603c Merge branch 'develop' of https://github.com/vabene1111/recipes into develop 2021-11-14 15:33:44 +01:00
vabene1111
695cab29a1 fixed book sharing and added step page 2021-11-14 15:33:25 +01:00
Luka
7b6ca94d49 Translated using Weblate (Slovenian)
Currently translated at 11.5% (24 of 208 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/sl/
2021-11-14 14:06:36 +00:00
Job Putters
35e04f94c6 Translated using Weblate (Dutch)
Currently translated at 100.0% (509 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/nl/
2021-11-14 14:06:36 +00:00
vabene1111
7c4cd02dfa fixed startup failing if fix tree fails 2021-11-14 10:33:33 +01:00
vabene1111
5ae440d5c9 fixed image on url importer 2021-11-13 12:30:23 +01:00
vabene1111
e88010310c Merge pull request #1061 from tuxuser/docs/inline_docker_yaml_proper
Docs: Inline docker yaml files (revises #1058)
2021-11-13 10:55:19 +01:00
tuxuser
b6eba9c5e7 Docs: Fix inline include of yaml files 2021-11-13 10:36:14 +01:00
tuxuser
9d827ac174 Docs: Inline docker-compose.yaml files in the documentation 2021-11-13 10:35:55 +01:00
vabene1111
27679ae8a5 Merge pull request #1060 from TandoorRecipes/revert-1058-docs/inline_docker_yaml
Revert "Docs: Inline docker-compose.yaml files in the documentation"
2021-11-13 09:19:45 +01:00
vabene1111
6cb9a7068e Revert "Docs: Inline docker-compose.yaml files in the documentation" 2021-11-13 09:19:34 +01:00
vabene1111
f41c2ee7bb Merge pull request #1058 from tuxuser/docs/inline_docker_yaml
Docs: Inline docker-compose.yaml files in the documentation
2021-11-13 09:13:56 +01:00
vabene1111
af581bb27c Added translation using Weblate (Slovenian) 2021-11-13 08:08:25 +00:00
vabene1111
885c8982c1 Added translation using Weblate (Slovenian) 2021-11-13 08:07:56 +00:00
Oliver Cervera
64a9f67802 Translated using Weblate (Italian)
Currently translated at 100.0% (208 of 208 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/
2021-11-12 20:06:33 +00:00
Henrique Silva
df45e1d523 Translated using Weblate (Portuguese)
Currently translated at 31.4% (160 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/pt/
2021-11-12 20:06:33 +00:00
Oliver Cervera
03d7aa37da Translated using Weblate (Italian)
Currently translated at 95.6% (487 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/it/
2021-11-12 20:06:33 +00:00
A. L
dd3d28ec75 Translated using Weblate (German)
Currently translated at 100.0% (509 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/de/
2021-11-12 20:06:29 +00:00
tuxuser
ea377c2f3b Docs: Inline docker-compose.yaml files in the documentation 2021-11-12 14:41:33 +01:00
Flavius Stan
6f0bf886f6 Translated using Weblate (Romanian)
Currently translated at 8.1% (17 of 208 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/ro/
2021-11-11 16:06:30 +00:00
SMunos
16fbd9fe48 Translated using Weblate (French)
Currently translated at 93.2% (194 of 208 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/fr/
2021-11-11 16:06:30 +00:00
vabene1111
79cdb56f9a added create supersuser to faq 2021-11-10 14:25:51 +01:00
vabene1111
1e6ba924ab fixed plan to eat and mealmaster imports 2021-11-10 08:45:13 +01:00
vabene1111
9ae076e426 fixed png scaling algortihm 2021-11-09 17:59:31 +01:00
vabene1111
f346022d8b improved image compression and added it to import 2021-11-09 17:38:32 +01:00
vabene1111
c9cd5325c4 improved nextcloud importer 2021-11-09 16:38:50 +01:00
vabene1111
ba6c80e04a Added translation using Weblate (Romanian) 2021-11-09 14:27:40 +00:00
vabene1111
be3f860ba1 Added translation using Weblate (Romanian) 2021-11-09 14:27:23 +00:00
Oliver Cervera
1ac4020b3d Translated using Weblate (Italian)
Currently translated at 96.6% (201 of 208 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/it/
2021-11-09 12:06:30 +00:00
Jesse
5da535b8ac Translated using Weblate (Dutch)
Currently translated at 100.0% (208 of 208 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/nl/
2021-11-09 12:06:29 +00:00
Maximilian J
b8ed99a59a Translated using Weblate (German)
Currently translated at 100.0% (208 of 208 strings)

Translation: Tandoor/Recipes Frontend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-frontend/de/
2021-11-09 12:06:29 +00:00
Jesse
c199536fca Translated using Weblate (Dutch)
Currently translated at 100.0% (509 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/nl/
2021-11-09 12:06:29 +00:00
Oliver Cervera
d60a9f0379 Translated using Weblate (Italian)
Currently translated at 95.8% (488 of 509 strings)

Translation: Tandoor/Recipes Backend
Translate-URL: http://translate.tandoor.dev/projects/tandoor/recipes-backend/it/
2021-11-09 12:06:29 +00:00
vabene1111
c5da006f4a Merge branch 'master' into develop 2021-11-08 18:44:29 +01:00
57 changed files with 6610 additions and 755 deletions

View File

@@ -14,5 +14,5 @@ jobs:
- uses: actions/setup-python@v2
with:
python-version: 3.x
- run: pip install mkdocs-material
- run: pip install mkdocs-material mkdocs-include-markdown-plugin
- run: mkdocs gh-deploy --force

View File

@@ -1,26 +1,40 @@
import traceback
from django.apps import AppConfig
from django.conf import settings
from django.db import OperationalError, ProgrammingError
from django_scopes import scopes_disabled
from recipes.settings import DEBUG
class CookbookConfig(AppConfig):
name = 'cookbook'
def ready(self):
# post_save signal is only necessary if using full-text search on postgres
if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2', 'django.db.backends.postgresql']:
if settings.DATABASES['default']['ENGINE'] in ['django.db.backends.postgresql_psycopg2',
'django.db.backends.postgresql']:
import cookbook.signals # noqa
# when starting up run fix_tree to:
# a) make sure that nodes are sorted when switching between sort modes
# b) fix problems, if any, with tree consistency
with scopes_disabled():
try:
from cookbook.models import Keyword, Food
Keyword.fix_tree(fix_paths=True)
Food.fix_tree(fix_paths=True)
except OperationalError:
pass # if model does not exist there is no need to fix it
except ProgrammingError:
pass # if migration has not been run database cannot be fixed yet
if not settings.DISABLE_TREE_FIX_STARTUP:
# when starting up run fix_tree to:
# a) make sure that nodes are sorted when switching between sort modes
# b) fix problems, if any, with tree consistency
with scopes_disabled():
try:
from cookbook.models import Keyword, Food
Keyword.fix_tree(fix_paths=True)
Food.fix_tree(fix_paths=True)
except OperationalError:
if DEBUG:
traceback.print_exc()
pass # if model does not exist there is no need to fix it
except ProgrammingError:
if DEBUG:
traceback.print_exc()
pass # if migration has not been run database cannot be fixed yet
except Exception:
if DEBUG:
traceback.print_exc()
pass # dont break startup just because fix could not run, need to investigate cases when this happens

View File

@@ -5,7 +5,7 @@ from PIL import Image
from io import BytesIO
def rescale_image_jpeg(image_object, base_width=720):
def rescale_image_jpeg(image_object, base_width=1020):
img = Image.open(image_object)
icc_profile = img.info.get('icc_profile') # remember color profile to not mess up colors
width_percent = (base_width / float(img.size[0]))
@@ -13,20 +13,20 @@ def rescale_image_jpeg(image_object, base_width=720):
img = img.resize((base_width, height), Image.ANTIALIAS)
img_bytes = BytesIO()
img.save(img_bytes, 'JPEG', quality=75, optimize=True, icc_profile=icc_profile)
img.save(img_bytes, 'JPEG', quality=90, optimize=True, icc_profile=icc_profile)
return img_bytes
def rescale_image_png(image_object, base_width=720):
basewidth = 720
wpercent = (basewidth / float(image_object.size[0]))
def rescale_image_png(image_object, base_width=1020):
image_object = Image.open(image_object)
wpercent = (base_width / float(image_object.size[0]))
hsize = int((float(image_object.size[1]) * float(wpercent)))
img = image_object.resize((basewidth, hsize), Image.ANTIALIAS)
img = image_object.resize((base_width, hsize), Image.ANTIALIAS)
im_io = BytesIO()
img.save(im_io, 'PNG', quality=70)
return img
img.save(im_io, 'PNG', quality=90)
return im_io
def get_filetype(name):
@@ -36,9 +36,11 @@ def get_filetype(name):
return '.jpeg'
# TODO this whole file needs proper documentation, refactoring, and testing
# TODO also add env variable to define which images sizes should be compressed
def handle_image(request, image_object, filetype='.jpeg'):
if sys.getsizeof(image_object) / 8 > 500:
if filetype == '.jpeg':
if (image_object.size / 1000) > 500: # if larger than 500 kb compress
if filetype == '.jpeg' or filetype == '.jpg':
return rescale_image_jpeg(image_object), filetype
if filetype == '.png':
return rescale_image_png(image_object), filetype

View File

@@ -38,6 +38,7 @@ def search_recipes(request, queryset, params):
search_keywords = params.getlist('keywords', [])
search_foods = params.getlist('foods', [])
search_books = params.getlist('books', [])
search_steps = params.getlist('steps', [])
search_units = params.get('units', None)
# TODO I think default behavior should be 'AND' which is how most sites operate with facet/filters based on results
@@ -191,6 +192,10 @@ def search_recipes(request, queryset, params):
if search_units:
queryset = queryset.filter(steps__ingredients__unit__id=search_units)
# probably only useful in Unit list view, so keeping it simple
if search_steps:
queryset = queryset.filter(steps__id__in=search_steps)
if search_internal:
queryset = queryset.filter(internal=True)

View File

@@ -1,5 +1,8 @@
from django.urls import reverse
from django_scopes import scope, scopes_disabled
from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token
from rest_framework.exceptions import AuthenticationFailed
from cookbook.views import views
@@ -33,6 +36,15 @@ class ScopeMiddleware:
with scope(space=request.space):
return self.get_response(request)
else:
if request.path.startswith('/api/'):
try:
if auth := TokenAuthentication().authenticate(request):
request.space = auth[0].userpreference.space
with scope(space=request.space):
return self.get_response(request)
except AuthenticationFailed:
pass
with scopes_disabled():
request.space = None
return self.get_response(request)

View File

@@ -14,7 +14,7 @@ from django.utils.translation import gettext as _
from django_scopes import scope
from cookbook.forms import ImportExportBase
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.image_processing import get_filetype, handle_image
from cookbook.models import Keyword, Recipe
from recipes.settings import DATABASES, DEBUG
@@ -52,7 +52,7 @@ class Integration:
icon=icon,
space=request.space
)
except IntegrityError: # in case, for whatever reason, the name does exist append UUID to it. Not nice but works for now.
except IntegrityError: # in case, for whatever reason, the name does exist append UUID to it. Not nice but works for now.
self.keyword = parent.add_child(
name=f'{name} {str(uuid.uuid4())[0:8]}',
description=description,
@@ -229,15 +229,14 @@ class Integration:
self.ignored_recipes.append(recipe.name)
recipe.delete()
@staticmethod
def import_recipe_image(recipe, image_file, filetype='.jpeg'):
def import_recipe_image(self, recipe, image_file, filetype='.jpeg'):
"""
Adds an image to a recipe naming it correctly
:param recipe: Recipe object
:param image_file: ByteIO stream containing the image
:param filetype: type of file to write bytes to, default to .jpeg if unknown
"""
recipe.image = File(image_file, name=f'{uuid.uuid4()}_{recipe.pk}{filetype}')
recipe.image = File(handle_image(self.request, File(image_file, name='image'), filetype=filetype)[0], name=f'{uuid.uuid4()}_{recipe.pk}{filetype}')
recipe.save()
def get_recipe_from_file(self, file):

View File

@@ -63,7 +63,7 @@ class MealMaster(Integration):
current_recipe = ''
for fl in file.readlines():
line = fl.decode("ANSI")
line = fl.decode("windows-1250")
if (line.startswith('MMMMM') or line.startswith('-----')) and 'meal-master' in line.lower():
if current_recipe != '':
recipe_list.append(current_recipe)

View File

@@ -5,8 +5,9 @@ from zipfile import ZipFile
from cookbook.helper.image_processing import get_filetype
from cookbook.helper.ingredient_parser import IngredientParser
from cookbook.helper.recipe_url_import import iso_duration_to_minutes
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Ingredient
from cookbook.models import Recipe, Step, Ingredient, Keyword
class NextcloudCookbook(Integration):
@@ -24,9 +25,24 @@ class NextcloudCookbook(Integration):
created_by=self.request.user, internal=True,
servings=recipe_json['recipeYield'], space=self.request.space)
# TODO parse times (given in PT2H3M )
# @vabene check recipe_url_import.iso_duration_to_minutes I think it does what you are looking for
# TODO parse keywords
try:
recipe.working_time = iso_duration_to_minutes(recipe_json['prepTime'])
recipe.waiting_time = iso_duration_to_minutes(recipe_json['cookTime'])
except Exception:
pass
if 'recipeCategory' in recipe_json:
try:
recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=recipe_json['recipeCategory'])[0])
except Exception:
pass
if 'keywords' in recipe_json:
try:
for x in recipe_json['keywords'].split(','):
recipe.keywords.add(Keyword.objects.get_or_create(space=self.request.space, name=x)[0])
except Exception:
pass
ingredients_added = False
for s in recipe_json['recipeInstructions']:
@@ -49,11 +65,20 @@ class NextcloudCookbook(Integration):
))
recipe.steps.add(step)
if 'nutrition' in recipe_json:
try:
recipe.nutrition.calories = recipe_json['nutrition']['calories'].replace(' kcal', '').replace(' ', '')
recipe.nutrition.proteins = recipe_json['nutrition']['calories'].replace(' g', '').replace(',', '.').replace(' ', '')
recipe.nutrition.fats = recipe_json['nutrition']['calories'].replace(' g', '').replace(',', '.').replace(' ', '')
recipe.nutrition.carbohydrates = recipe_json['nutrition']['calories'].replace(' g', '').replace(',', '.').replace(' ', '')
except Exception:
pass
for f in self.files:
if '.zip' in f['name']:
import_zip = ZipFile(f['file'])
for z in import_zip.filelist:
if re.match(f'^{recipe.name}/full.jpg$', z.filename):
if re.match(f'^(.)+{recipe.name}/full.jpg$', z.filename):
self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename)), filetype=get_filetype(z.filename))
return recipe

View File

@@ -78,7 +78,7 @@ class Plantoeat(Integration):
current_recipe = ''
for fl in file.readlines():
line = fl.decode("ANSI")
line = fl.decode("windows-1250")
if line.startswith('--------------'):
if current_recipe != '':
recipe_list.append(current_recipe)

View File

@@ -15,10 +15,10 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
"PO-Revision-Date: 2021-11-07 17:14+0000\n"
"Last-Translator: Kaibu <notkaibu@gmail.com>\n"
"Language-Team: German <http://translate.tandoor.dev/projects/tandoor/recipes-"
"backend/de/>\n"
"PO-Revision-Date: 2021-11-12 20:06+0000\n"
"Last-Translator: A. L. <richard@anska.de>\n"
"Language-Team: German <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/de/>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -261,10 +261,6 @@ msgid "Email address already taken!"
msgstr "Email-Adresse ist bereits vergeben!"
#: .\cookbook\forms.py:367
#, fuzzy
#| msgid ""
#| "An email address is not required but if present the invite link will be "
#| "send to the user."
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."

View File

@@ -11,8 +11,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
"PO-Revision-Date: 2021-09-18 23:06+0000\n"
"POT-Creation-Date: 2021-11-07 17:31+0100\n"
"PO-Revision-Date: 2021-11-12 20:06+0000\n"
"Last-Translator: Oliver Cervera <olivercervera@yahoo.it>\n"
"Language-Team: Italian <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/it/>\n"
@@ -31,66 +31,52 @@ msgid "Ingredients"
msgstr "Ingredienti"
#: .\cookbook\forms.py:54
#, fuzzy
#| msgid "Default"
msgid "Default unit"
msgstr "Predefinito"
msgstr "Unità predefinita"
#: .\cookbook\forms.py:55
#, fuzzy
#| msgid "System Information"
msgid "Use fractions"
msgstr "Informazioni di sistema"
msgstr "Usa frazioni"
#: .\cookbook\forms.py:56
msgid "Use KJ"
msgstr ""
msgstr "Usa KJ"
#: .\cookbook\forms.py:57
msgid "Theme"
msgstr ""
msgstr "Tema"
#: .\cookbook\forms.py:58
msgid "Navbar color"
msgstr ""
msgstr "Colore barra di navigazione"
#: .\cookbook\forms.py:59
msgid "Sticky navbar"
msgstr ""
msgstr "Barra di navigazione persistente"
#: .\cookbook\forms.py:60
#, fuzzy
#| msgid "Default"
msgid "Default page"
msgstr "Predefinito"
msgstr "Pagina predefinita"
#: .\cookbook\forms.py:61
#, fuzzy
#| msgid "Shopping Recipes"
msgid "Show recent recipes"
msgstr "Ricette per la spesa"
msgstr "Mostra ricette recenti"
#: .\cookbook\forms.py:62
#, fuzzy
#| msgid "Search"
msgid "Search style"
msgstr "Cerca"
msgstr "Cerca stile"
#: .\cookbook\forms.py:63
msgid "Plan sharing"
msgstr ""
msgstr "Condivisione piano"
#: .\cookbook\forms.py:64
#, fuzzy
#| msgid "Ingredients"
msgid "Ingredient decimal places"
msgstr "Ingredienti"
msgstr "Posizioni decimali degli ingredienti"
#: .\cookbook\forms.py:65
#, fuzzy
#| msgid "Shopping list currently empty"
msgid "Shopping list auto sync period"
msgstr "La lista della spesa è vuota"
msgstr "Frequenza di sincronizzazione automatica della lista della spesa"
#: .\cookbook\forms.py:66 .\cookbook\templates\recipe_view.html:21
#: .\cookbook\templates\space.html:62 .\cookbook\templates\stats.html:47
@@ -121,7 +107,7 @@ msgstr ""
#: .\cookbook\forms.py:76
msgid "Display nutritional energy amounts in joules instead of calories"
msgstr ""
msgstr "Mostra le informazioni nutrizionali in Joule invece che in calorie"
#: .\cookbook\forms.py:78
msgid ""
@@ -237,7 +223,7 @@ msgstr "Archiviazione"
#: .\cookbook\forms.py:260
msgid "Active"
msgstr ""
msgstr "Attivo"
#: .\cookbook\forms.py:265
msgid "Search String"
@@ -304,8 +290,8 @@ msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full desciption of choices."
msgstr ""
"Seleziona il metodo di ricerca. Clicca<a href=\"/docs/search/\">qui</a> per "
"avere maggiori informazioni."
"Seleziona il metodo di ricerca. Clicca <a href=\"/docs/search/\">qui</a> "
"per avere maggiori informazioni."
#: .\cookbook\forms.py:436
msgid ""
@@ -364,10 +350,8 @@ msgid "Starts Wtih"
msgstr "Inizia con"
#: .\cookbook\forms.py:455
#, fuzzy
#| msgid "Search"
msgid "Fuzzy Search"
msgstr "Cerca"
msgstr "Ricerca Fuzzy"
#: .\cookbook\forms.py:456
msgid "Full Text"
@@ -384,7 +368,7 @@ msgstr ""
#: .\cookbook\helper\permission_helper.py:136
#: .\cookbook\helper\permission_helper.py:159 .\cookbook\views\views.py:149
msgid "You are not logged in and therefore cannot view this page!"
msgstr "Non hai fatto l'accesso e quindi non puoi visualizzare questa pagina!"
msgstr "Non sei loggato e quindi non puoi visualizzare questa pagina!"
#: .\cookbook\helper\permission_helper.py:140
#: .\cookbook\helper\permission_helper.py:146
@@ -478,7 +462,7 @@ msgstr "Tempo di preparazione"
#: .\cookbook\templates\forms\ingredients.html:7
#: .\cookbook\templates\index.html:7
msgid "Cookbook"
msgstr "Ricettario"
msgstr "Ricette"
#: .\cookbook\integration\safron.py:31
msgid "Section"
@@ -595,22 +579,16 @@ msgid "Raw"
msgstr "Raw"
#: .\cookbook\models.py:912
#, fuzzy
#| msgid "Food"
msgid "Food Alias"
msgstr "Alimento"
msgstr "Alias Alimento"
#: .\cookbook\models.py:912
#, fuzzy
#| msgid "Units"
msgid "Unit Alias"
msgstr "Unità di misura"
msgstr "Alias Unità"
#: .\cookbook\models.py:912
#, fuzzy
#| msgid "Keywords"
msgid "Keyword Alias"
msgstr "Parole chiave"
msgstr "Alias Parola Chiave"
#: .\cookbook\serializer.py:157
msgid "File uploads are not enabled for this Space."
@@ -851,10 +829,8 @@ msgstr ""
"minuto."
#: .\cookbook\templates\account\password_reset_from_key.html:13
#, fuzzy
#| msgid "API Token"
msgid "Bad Token"
msgstr "Token API"
msgstr "Token non valido"
#: .\cookbook\templates\account\password_reset_from_key.html:25
#, python-format
@@ -866,15 +842,13 @@ msgid ""
msgstr ""
#: .\cookbook\templates\account\password_reset_from_key.html:33
#, fuzzy
#| msgid "Change Password"
msgid "change password"
msgstr "Cambia Password"
msgstr "cambia password"
#: .\cookbook\templates\account\password_reset_from_key.html:36
#: .\cookbook\templates\account\password_reset_from_key_done.html:19
msgid "Your password is now changed."
msgstr ""
msgstr "La tua password è stata aggiornata."
#: .\cookbook\templates\account\password_set.html:6
#: .\cookbook\templates\account\password_set.html:16
@@ -954,10 +928,8 @@ msgid "Supermarket"
msgstr "Supermercato"
#: .\cookbook\templates\base.html:163
#, fuzzy
#| msgid "Supermarket"
msgid "Supermarket Category"
msgstr "Supermercato"
msgstr "Categoria Supermercato"
#: .\cookbook\templates\base.html:175 .\cookbook\views\lists.py:195
#, fuzzy
@@ -1004,7 +976,7 @@ msgstr "Ricette esterne"
#: .\cookbook\templates\base.html:262 .\cookbook\templates\space.html:7
#: .\cookbook\templates\space.html:19
msgid "Space Settings"
msgstr "Impostazioni Istanza"
msgstr "Impostazioni istanza"
#: .\cookbook\templates\base.html:267 .\cookbook\templates\system.html:13
msgid "System"
@@ -1024,7 +996,7 @@ msgstr "GitHub"
#: .\cookbook\templates\base.html:277
msgid "Translate Tandoor"
msgstr ""
msgstr "Traduci Tandoor"
#: .\cookbook\templates\base.html:281
msgid "API Browser"
@@ -1089,16 +1061,12 @@ msgid "Sync Now!"
msgstr "Sincronizza Ora!"
#: .\cookbook\templates\batch\monitor.html:29
#, fuzzy
#| msgid "Shopping Recipes"
msgid "Show Recipes"
msgstr "Ricette per la spesa"
msgstr "Mostra ricette"
#: .\cookbook\templates\batch\monitor.html:30
#, fuzzy
#| msgid "Show Links"
msgid "Show Log"
msgstr "Mostra link"
msgstr "Mostra registro"
#: .\cookbook\templates\batch\waiting.html:4
#: .\cookbook\templates\batch\waiting.html:10
@@ -1171,11 +1139,11 @@ msgstr "Sei sicuro di volere eliminare %(title)s: <b>%(object)s</b>"
#: .\cookbook\templates\generic\delete_template.html:26
msgid "Protected"
msgstr ""
msgstr "Protetto"
#: .\cookbook\templates\generic\delete_template.html:41
msgid "Cascade"
msgstr ""
msgstr "Cascata"
#: .\cookbook\templates\generic\delete_template.html:72
msgid "Cancel"
@@ -1613,10 +1581,8 @@ msgstr "Pagina iniziale ricette"
#: .\cookbook\templates\search_info.html:5
#: .\cookbook\templates\search_info.html:9
#: .\cookbook\templates\settings.html:165
#, fuzzy
#| msgid "Search String"
msgid "Search Settings"
msgstr "Stringa di Ricerca"
msgstr "Impostazioni di ricerca"
#: .\cookbook\templates\search_info.html:10
msgid ""
@@ -1639,10 +1605,8 @@ msgstr ""
" "
#: .\cookbook\templates\search_info.html:19
#, fuzzy
#| msgid "Search"
msgid "Search Methods"
msgstr "Cerca"
msgstr "Metodi di ricerca"
#: .\cookbook\templates\search_info.html:23
msgid ""
@@ -1724,10 +1688,8 @@ msgid ""
msgstr ""
#: .\cookbook\templates\search_info.html:69
#, fuzzy
#| msgid "Search Recipe"
msgid "Search Fields"
msgstr "Cerca Ricetta"
msgstr "Campi di ricerca"
#: .\cookbook\templates\search_info.html:73
msgid ""
@@ -1765,10 +1727,8 @@ msgid ""
msgstr ""
#: .\cookbook\templates\search_info.html:95
#, fuzzy
#| msgid "Search"
msgid "Search Index"
msgstr "Cerca"
msgstr "Indice di ricerca"
#: .\cookbook\templates\search_info.html:99
msgid ""
@@ -1796,10 +1756,8 @@ msgid "API-Settings"
msgstr "Impostazioni API"
#: .\cookbook\templates\settings.html:49
#, fuzzy
#| msgid "Search String"
msgid "Search-Settings"
msgstr "Stringa di Ricerca"
msgstr "Cerca-Impostazioni"
#: .\cookbook\templates\settings.html:58
msgid "Name Settings"
@@ -1855,22 +1813,28 @@ msgid ""
"There are many options to configure the search depending on your personal "
"preferences."
msgstr ""
"Ci sono molte opzioni per configurare la ricerca in base alle tue preferenze."
#: .\cookbook\templates\settings.html:167
msgid ""
"Usually you do <b>not need</b> to configure any of them and can just stick "
"with either the default or one of the following presets."
msgstr ""
"Normalmente <b>non c'è bisogno</b> di configurare queste voci e puoi "
"continuare a usare le impostazioni predefinite oppure scegliere una delle "
"seguenti modalità."
#: .\cookbook\templates\settings.html:168
msgid ""
"If you do want to configure the search you can read about the different "
"options <a href=\"/docs/search/\">here</a>."
msgstr ""
"Se vuoi comunque configurare la ricerca, puoi informarti riguardo le opzioni "
"disponibili <a href=\"/docs/search/\">qui</a>."
#: .\cookbook\templates\settings.html:173
msgid "Fuzzy"
msgstr ""
msgstr "Fuzzy"
#: .\cookbook\templates\settings.html:174
msgid ""
@@ -1881,16 +1845,16 @@ msgstr ""
#: .\cookbook\templates\settings.html:175
msgid "This is the default behavior"
msgstr ""
msgstr "È il comportamento predefinito"
#: .\cookbook\templates\settings.html:176
#: .\cookbook\templates\settings.html:184
msgid "Apply"
msgstr ""
msgstr "Applica"
#: .\cookbook\templates\settings.html:181
msgid "Precise"
msgstr ""
msgstr "Preciso"
#: .\cookbook\templates\settings.html:182
msgid ""
@@ -1904,7 +1868,7 @@ msgstr ""
#: .\cookbook\templates\setup.html:6 .\cookbook\templates\system.html:5
msgid "Cookbook Setup"
msgstr "Configurazione del ricettario"
msgstr "Configurazione Recipes"
#: .\cookbook\templates\setup.html:14
msgid "Setup"
@@ -1927,10 +1891,8 @@ msgid "Shopping List"
msgstr "Lista della spesa"
#: .\cookbook\templates\shopping_list.html:34
#, fuzzy
#| msgid "Open Shopping List"
msgid "Try the new shopping list"
msgstr "Apri lista della spesa"
msgstr "Prova la nuova lista della spesa"
#: .\cookbook\templates\shopping_list.html:63
msgid "Search Recipe"
@@ -2030,7 +1992,7 @@ msgid ""
" %(site_name)s. As a final step, please complete the following form:"
msgstr ""
"Stai per usare il tuo:\n"
" Account %(provider_name)s per fare l'accesso a\n"
" account %(provider_name)s per fare l'accesso a\n"
" %(site_name)s. Per finire, completa il modulo qui sotto:"
#: .\cookbook\templates\socialaccount\snippets\provider_list.html:23
@@ -2270,11 +2232,11 @@ msgstr "Salvami nei preferiti!"
#: .\cookbook\templates\url_import.html:36
msgid "URL"
msgstr ""
msgstr "URL"
#: .\cookbook\templates\url_import.html:38
msgid "App"
msgstr ""
msgstr "App"
#: .\cookbook\templates\url_import.html:62
msgid "Enter website URL"
@@ -2468,10 +2430,8 @@ msgid "No {self.basename} with id {target} exists"
msgstr "Non esiste nessun {self.basename} con id {target}"
#: .\cookbook\views\api.py:168
#, fuzzy
#| msgid "Cannot merge with the same object!"
msgid "Cannot merge with child object!"
msgstr "Non è possibile unirlo con lo stesso oggetto!"
msgstr "Non è possibile unirlo con un oggetto secondario!"
#: .\cookbook\views\api.py:201
#, python-brace-format
@@ -2514,10 +2474,9 @@ msgstr "{child.name} è stato spostato con successo al primario {parent.name}"
#: .\cookbook\views\api.py:723 .\cookbook\views\data.py:42
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
#, fuzzy
#| msgid "This feature is not available in the demo version!"
msgid "This feature is not yet available in the hosted version of tandoor!"
msgstr "Questa funzione non è disponibile nella versione demo!"
msgstr ""
"Questa funzione non è ancora disponibile nella versione hostata di Tandor!"
#: .\cookbook\views\api.py:745
msgid "Sync successful!"
@@ -2648,28 +2607,20 @@ msgid "Shopping Lists"
msgstr "Liste della spesa"
#: .\cookbook\views\lists.py:129
#, fuzzy
#| msgid "Food"
msgid "Foods"
msgstr "Alimento"
msgstr "Alimenti"
#: .\cookbook\views\lists.py:163
#, fuzzy
#| msgid "Supermarket"
msgid "Supermarkets"
msgstr "Supermercato"
msgstr "Supermercati"
#: .\cookbook\views\lists.py:179
#, fuzzy
#| msgid "Shopping Recipes"
msgid "Shopping Categories"
msgstr "Ricette per la spesa"
msgstr "Categorie della spesa"
#: .\cookbook\views\lists.py:232
#, fuzzy
#| msgid "Shopping List"
msgid "New Shopping List"
msgstr "Lista della spesa"
msgstr "Nuova lista della spesa"
#: .\cookbook\views\new.py:126
msgid "Imported new recipe!"
@@ -2769,7 +2720,7 @@ msgstr ""
#: .\cookbook\views\views.py:349
msgid "Fuzzy search is not compatible with this search method!"
msgstr ""
msgstr "La ricerca Fuzzy non è compatibile con questo metodo di ricerca!"
#: .\cookbook\views\views.py:452
msgid ""

View File

@@ -12,11 +12,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
"PO-Revision-Date: 2021-10-26 10:06+0000\n"
"Last-Translator: Jesse <jesse.kamps@pm.me>\n"
"Language-Team: Dutch <http://translate.tandoor.dev/projects/tandoor/recipes-"
"backend/nl/>\n"
"POT-Creation-Date: 2021-11-07 17:31+0100\n"
"PO-Revision-Date: 2021-11-14 14:06+0000\n"
"Last-Translator: Job Putters <me@ixbitz.com>\n"
"Language-Team: Dutch <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/nl/>\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -32,66 +32,52 @@ msgid "Ingredients"
msgstr "Ingrediënten"
#: .\cookbook\forms.py:54
#, fuzzy
#| msgid "Default"
msgid "Default unit"
msgstr "Standaard waarde"
msgstr "Standaard eenheid"
#: .\cookbook\forms.py:55
#, fuzzy
#| msgid "System Information"
msgid "Use fractions"
msgstr "Systeeminformatie"
msgstr "Gebruik fracties"
#: .\cookbook\forms.py:56
msgid "Use KJ"
msgstr ""
msgstr "Gebruik KJ"
#: .\cookbook\forms.py:57
msgid "Theme"
msgstr ""
msgstr "Thema"
#: .\cookbook\forms.py:58
msgid "Navbar color"
msgstr ""
msgstr "Navbar kleur"
#: .\cookbook\forms.py:59
msgid "Sticky navbar"
msgstr ""
msgstr "Plak navbar"
#: .\cookbook\forms.py:60
#, fuzzy
#| msgid "Default"
msgid "Default page"
msgstr "Standaard waarde"
msgstr "Standaard pagina"
#: .\cookbook\forms.py:61
#, fuzzy
#| msgid "Show Recipes"
msgid "Show recent recipes"
msgstr "Toon Recepten"
msgstr "Toon recente recepten"
#: .\cookbook\forms.py:62
#, fuzzy
#| msgid "Search Index"
msgid "Search style"
msgstr "Zoekindex"
msgstr "Zoekstijl"
#: .\cookbook\forms.py:63
msgid "Plan sharing"
msgstr ""
msgstr "Plan delen"
#: .\cookbook\forms.py:64
#, fuzzy
#| msgid "Ingredients"
msgid "Ingredient decimal places"
msgstr "Ingrediënten"
msgstr "Ingrediënt decimalen"
#: .\cookbook\forms.py:65
#, fuzzy
#| msgid "Shopping list currently empty"
msgid "Shopping list auto sync period"
msgstr "Boodschappenlijst is momenteel leeg"
msgstr "Boodschappenlijst auto sync periode"
#: .\cookbook\forms.py:66 .\cookbook\templates\recipe_view.html:21
#: .\cookbook\templates\space.html:62 .\cookbook\templates\stats.html:47
@@ -122,7 +108,7 @@ msgstr ""
#: .\cookbook\forms.py:76
msgid "Display nutritional energy amounts in joules instead of calories"
msgstr ""
msgstr "Geef energiewaardes weer in joules in plaats van calorieën"
#: .\cookbook\forms.py:78
msgid ""
@@ -235,7 +221,7 @@ msgstr "Opslag"
#: .\cookbook\forms.py:260
msgid "Active"
msgstr ""
msgstr "Actief"
#: .\cookbook\forms.py:265
msgid "Search String"
@@ -272,10 +258,6 @@ msgid "Email address already taken!"
msgstr "E-mailadres reeds in gebruik!"
#: .\cookbook\forms.py:367
#, fuzzy
#| msgid ""
#| "An email address is not required but if present the invite link will be "
#| "send to the user."
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
@@ -296,6 +278,8 @@ msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
msgstr ""
"Bepaalt hoe 'fuzzy' een zoekopdracht is als het trigram vergelijken gebruikt "
"(lage waarden betekenen bijvoorbeeld dat meer typefouten genegeerd worden)."
#: .\cookbook\forms.py:435
msgid ""
@@ -601,25 +585,19 @@ msgstr "Web"
#: .\cookbook\models.py:874 .\cookbook\templates\search_info.html:47
msgid "Raw"
msgstr "Raw"
msgstr "Rauw"
#: .\cookbook\models.py:912
#, fuzzy
#| msgid "Foods"
msgid "Food Alias"
msgstr "Ingrediënten"
msgstr "Ingrediënt alias"
#: .\cookbook\models.py:912
#, fuzzy
#| msgid "Units"
msgid "Unit Alias"
msgstr "Eenheden"
msgstr "Eenheid alias"
#: .\cookbook\models.py:912
#, fuzzy
#| msgid "Keywords"
msgid "Keyword Alias"
msgstr "Etiketten"
msgstr "Etiket alias"
#: .\cookbook\serializer.py:157
msgid "File uploads are not enabled for this Space."
@@ -859,10 +837,8 @@ msgstr ""
"minuten ontvangen hebt."
#: .\cookbook\templates\account\password_reset_from_key.html:13
#, fuzzy
#| msgid "API Token"
msgid "Bad Token"
msgstr "API Token"
msgstr "Bad token"
#: .\cookbook\templates\account\password_reset_from_key.html:25
#, python-format
@@ -872,17 +848,19 @@ msgid ""
" Please request a <a href=\"%(passwd_reset_url)s\">new "
"password reset</a>."
msgstr ""
"De link voor het opnieuw instellen van het wachtwoord was ongeldig, mogelijk "
"omdat hij al gebruikt is.\n"
" Vraag een <a href=\"%(passwd_reset_url)s\">nieuwe link "
"voor een wachtwoord reset aan</a>."
#: .\cookbook\templates\account\password_reset_from_key.html:33
#, fuzzy
#| msgid "Change Password"
msgid "change password"
msgstr "Wijzig wachtwoord"
#: .\cookbook\templates\account\password_reset_from_key.html:36
#: .\cookbook\templates\account\password_reset_from_key_done.html:19
msgid "Your password is now changed."
msgstr ""
msgstr "Je wachtwoord is nu gewijzigd."
#: .\cookbook\templates\account\password_set.html:6
#: .\cookbook\templates\account\password_set.html:16
@@ -962,16 +940,12 @@ msgid "Supermarket"
msgstr "Supermarkt"
#: .\cookbook\templates\base.html:163
#, fuzzy
#| msgid "Supermarket"
msgid "Supermarket Category"
msgstr "Supermarkt"
msgstr "Supermarktcategorie"
#: .\cookbook\templates\base.html:175 .\cookbook\views\lists.py:195
#, fuzzy
#| msgid "Information"
msgid "Automations"
msgstr "Informatie"
msgstr "Automatiseringen"
#: .\cookbook\templates\base.html:189 .\cookbook\views\lists.py:215
msgid "Files"
@@ -1001,7 +975,7 @@ msgstr "Recept importeren"
#: .\cookbook\templates\shopping_list.html:195
#: .\cookbook\templates\shopping_list.html:217
msgid "Create"
msgstr "Nieuw recept"
msgstr "Aanmaken"
#: .\cookbook\templates\base.html:259
#: .\cookbook\templates\generic\list_template.html:14
@@ -1032,7 +1006,7 @@ msgstr "GitHub"
#: .\cookbook\templates\base.html:277
msgid "Translate Tandoor"
msgstr ""
msgstr "Vertaal Tandoor"
#: .\cookbook\templates\base.html:281
msgid "API Browser"
@@ -1176,11 +1150,11 @@ msgstr "Weet je zeker dat je %(title)s: <b>%(object)s</b> wil verwijderen "
#: .\cookbook\templates\generic\delete_template.html:26
msgid "Protected"
msgstr ""
msgstr "Beschermd"
#: .\cookbook\templates\generic\delete_template.html:41
msgid "Cascade"
msgstr ""
msgstr "Cascade"
#: .\cookbook\templates\generic\delete_template.html:72
msgid "Cancel"
@@ -1267,11 +1241,11 @@ msgid ""
" "
msgstr ""
"\n"
" Het <b>wachtwoord en token</b> veld worden als <b>plain text</b> in "
"de database opgeslagen.\n"
" Dit is nodig omdat deze benodigd zijn voor de API requests, Echter verhoogt "
"dit ook het risico van diefstal.<br/>\n"
" Om mogelijke schade te beperken kun je gebruik maken van account met "
" Het <b>wachtwoord en token</b> veld worden als <b>plain text</b> "
"opgeslagen in de database.\n"
" Dit is nodig omdat deze benodigd zijn voor de API requests, Dit verhoogt "
"echter ook het risico van diefstal.<br/>\n"
" Om mogelijke schade te beperken kun je gebruik maken van accounts met "
"gelimiteerde toegang.\n"
" "
@@ -1942,22 +1916,29 @@ msgid ""
"There are many options to configure the search depending on your personal "
"preferences."
msgstr ""
"Er zijn vele mogelijkheden om het zoeken te configureren die afhangen van je "
"persoonlijke voorkeur."
#: .\cookbook\templates\settings.html:167
msgid ""
"Usually you do <b>not need</b> to configure any of them and can just stick "
"with either the default or one of the following presets."
msgstr ""
"Normaal gesproken is het <b>niet nodig</b> ze te configureren en kan je "
"gebruikmaken van het standaard profiel of de volgende vooraf ingestelde "
"profielen."
#: .\cookbook\templates\settings.html:168
msgid ""
"If you do want to configure the search you can read about the different "
"options <a href=\"/docs/search/\">here</a>."
msgstr ""
"Als je het zoeken wil configureren kan je <a href=\"/docs/search/\">hier</a> "
"over de verschillende opties lezen."
#: .\cookbook\templates\settings.html:173
msgid "Fuzzy"
msgstr ""
msgstr "Fuzzy"
#: .\cookbook\templates\settings.html:174
msgid ""
@@ -1965,29 +1946,34 @@ msgid ""
"return more results than needed to make sure you find what you are looking "
"for."
msgstr ""
"Vind wat je nodig hebt, zelfs als je zoekopdracht of het recept typefouten "
"bevat. Mogelijk krijg je meer resultaten dan je nodig hebt, om zeker te "
"weten dat je vindt wat je nodig hebt."
#: .\cookbook\templates\settings.html:175
msgid "This is the default behavior"
msgstr ""
msgstr "Dit is het standaard gedrag"
#: .\cookbook\templates\settings.html:176
#: .\cookbook\templates\settings.html:184
msgid "Apply"
msgstr ""
msgstr "Pas toe"
#: .\cookbook\templates\settings.html:181
msgid "Precise"
msgstr ""
msgstr "Nauwkeurig"
#: .\cookbook\templates\settings.html:182
msgid ""
"Allows fine control over search results but might not return results if too "
"many spelling mistakes are made."
msgstr ""
"Staat fijnmazige controle over zoekresultaten toe, maar toont mogelijk geen "
"resultaten als er te veel spelfouten gemaakt zijn."
#: .\cookbook\templates\settings.html:183
msgid "Perfect for large Databases"
msgstr ""
msgstr "Perfect voor grote databases"
#: .\cookbook\templates\setup.html:6 .\cookbook\templates\system.html:5
msgid "Cookbook Setup"
@@ -2014,10 +2000,8 @@ msgid "Shopping List"
msgstr "Boodschappenlijst"
#: .\cookbook\templates\shopping_list.html:34
#, fuzzy
#| msgid "Open Shopping List"
msgid "Try the new shopping list"
msgstr "Open boodschappenlijst"
msgstr "Probeer de nieuwe boodschappenlijst"
#: .\cookbook\templates\shopping_list.html:63
msgid "Search Recipe"
@@ -2367,11 +2351,11 @@ msgstr "Sla mij op als bladwijzer!"
#: .\cookbook\templates\url_import.html:36
msgid "URL"
msgstr ""
msgstr "URL"
#: .\cookbook\templates\url_import.html:38
msgid "App"
msgstr ""
msgstr "App"
#: .\cookbook\templates\url_import.html:62
msgid "Enter website URL"
@@ -2612,10 +2596,8 @@ msgstr "{child.name} is succesvol verplaatst naar {parent.name}"
#: .\cookbook\views\api.py:723 .\cookbook\views\data.py:42
#: .\cookbook\views\edit.py:129 .\cookbook\views\new.py:95
#, fuzzy
#| msgid "This feature is not available in the demo version!"
msgid "This feature is not yet available in the hosted version of tandoor!"
msgstr "Deze optie is niet beschikbaar in de demo versie!"
msgstr "Deze optie is nog niet beschikbaar in de gehoste versie van Tandoor!"
#: .\cookbook\views\api.py:745
msgid "Sync successful!"
@@ -2755,10 +2737,8 @@ msgid "Shopping Categories"
msgstr "Boodschappencategorieën"
#: .\cookbook\views\lists.py:232
#, fuzzy
#| msgid "Shopping List"
msgid "New Shopping List"
msgstr "Boodschappenlijst"
msgstr "Nieuwe boodschappenlijst"
#: .\cookbook\views\new.py:126
msgid "Imported new recipe!"

View File

@@ -7,21 +7,21 @@
# Henrique Diogo Silva <hdiogosilva@gmail.com>, 2020
# João Cunha <st0rmss95@gmail.com>, 2020
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-08 16:27+0100\n"
"PO-Revision-Date: 2020-06-02 19:28+0000\n"
"Last-Translator: João Cunha <st0rmss95@gmail.com>, 2020\n"
"Language-Team: Portuguese (https://www.transifex.com/django-recipes/"
"teams/110507/pt/)\n"
"PO-Revision-Date: 2021-11-12 20:06+0000\n"
"Last-Translator: Henrique Silva <hds@mailbox.org>\n"
"Language-Team: Portuguese <http://translate.tandoor.dev/projects/tandoor/"
"recipes-backend/pt/>\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Weblate 4.8\n"
#: .\cookbook\filters.py:23 .\cookbook\templates\base.html:125
#: .\cookbook\templates\forms\ingredients.html:34
@@ -32,64 +32,56 @@ msgstr "Ingredientes"
#: .\cookbook\forms.py:54
msgid "Default unit"
msgstr ""
msgstr "Unidade predefinida"
#: .\cookbook\forms.py:55
#, fuzzy
#| msgid "Instructions"
msgid "Use fractions"
msgstr "Instruções"
msgstr "Usar frações"
#: .\cookbook\forms.py:56
msgid "Use KJ"
msgstr ""
msgstr "Usar KJ"
#: .\cookbook\forms.py:57
msgid "Theme"
msgstr ""
msgstr "Tema"
#: .\cookbook\forms.py:58
msgid "Navbar color"
msgstr ""
msgstr "Cor de barra de navegação"
#: .\cookbook\forms.py:59
msgid "Sticky navbar"
msgstr ""
msgstr "Prender barra de navegação"
#: .\cookbook\forms.py:60
msgid "Default page"
msgstr ""
msgstr "Página predefinida"
#: .\cookbook\forms.py:61
#, fuzzy
#| msgid "Recipes"
msgid "Show recent recipes"
msgstr "Receitas"
msgstr "Mostrar receitas recentes"
#: .\cookbook\forms.py:62
#, fuzzy
#| msgid "Search"
msgid "Search style"
msgstr "Procurar"
msgstr "Estilo de pesquisa"
#: .\cookbook\forms.py:63
msgid "Plan sharing"
msgstr ""
msgstr "Partilha de planos"
#: .\cookbook\forms.py:64
#, fuzzy
#| msgid "Ingredients"
msgid "Ingredient decimal places"
msgstr "Ingredientes"
msgstr "Casas decimais de ingredientes"
#: .\cookbook\forms.py:65
msgid "Shopping list auto sync period"
msgstr ""
msgstr "Período de sincronização automática"
#: .\cookbook\forms.py:66 .\cookbook\templates\recipe_view.html:21
#: .\cookbook\templates\space.html:62 .\cookbook\templates\stats.html:47
msgid "Comments"
msgstr ""
msgstr "Comentários"
#: .\cookbook\forms.py:70
msgid ""
@@ -106,16 +98,20 @@ msgid ""
"Enables support for fractions in ingredient amounts (e.g. convert decimals "
"to fractions automatically)"
msgstr ""
"Utilizar frações para apresentar quantidades de ingredientes decimais ("
"converter quantidades decimais para frações automáticamente)"
#: .\cookbook\forms.py:76
msgid "Display nutritional energy amounts in joules instead of calories"
msgstr ""
msgstr "Mostrar quantidades de energia nutricional em joules em vez de calorias"
#: .\cookbook\forms.py:78
msgid ""
"Users with whom newly created meal plan/shopping list entries should be "
"shared by default."
msgstr ""
"Utilizadores com os quais novos planos de refeições/listas de compras devem "
"ser partilhados por defeito."
#: .\cookbook\forms.py:80
msgid "Show recently viewed recipes on search page."
@@ -127,7 +123,7 @@ msgstr "Número de casas decimais para arredondamentos."
#: .\cookbook\forms.py:82
msgid "If you want to be able to create and see comments underneath recipes."
msgstr ""
msgstr "Ativar a funcionalidade comentar receitas."
#: .\cookbook\forms.py:84
msgid ""
@@ -136,10 +132,15 @@ msgid ""
"Useful when shopping with multiple people but might use a little bit of "
"mobile data. If lower than instance limit it is reset when saving."
msgstr ""
"Definir esta opção como 0 desativará a sincronização automática. Ao "
"visualizar uma lista de compras, a lista é atualizada a cada período aqui "
"definido para sincronizar as alterações que outro utilizador possa ter "
"feito. Útil ao fazer compras com vários utilizadores, mas pode aumentar o "
"uso de dados móveis."
#: .\cookbook\forms.py:87
msgid "Makes the navbar stick to the top of the page."
msgstr ""
msgstr "Mantém a barra de navegação no topo da página."
#: .\cookbook\forms.py:103
msgid ""
@@ -147,7 +148,7 @@ msgid ""
"instead"
msgstr ""
"Ambos os campos são opcionais. Se nenhum for preenchido o nome de utilizador "
"será apresentado."
"será apresentado"
#: .\cookbook\forms.py:124 .\cookbook\forms.py:289
#: .\cookbook\templates\url_import.html:158
@@ -179,13 +180,15 @@ msgstr "UID de armazenamento"
#: .\cookbook\forms.py:157
msgid "Default"
msgstr ""
msgstr "Predefinição"
#: .\cookbook\forms.py:168 .\cookbook\templates\url_import.html:94
msgid ""
"To prevent duplicates recipes with the same name as existing ones are "
"ignored. Check this box to import everything."
msgstr ""
"Para evitar repetições, receitas com o mesmo nome de receitas já existentes "
"são ignoradas. Marque esta caixa para importar tudo."
#: .\cookbook\forms.py:190
msgid "Add your comment: "
@@ -211,11 +214,11 @@ msgstr ""
#: .\cookbook\forms.py:258 .\cookbook\views\edit.py:166
msgid "Storage"
msgstr ""
msgstr "Armazenamento"
#: .\cookbook\forms.py:260
msgid "Active"
msgstr ""
msgstr "Ativo"
#: .\cookbook\forms.py:265
msgid "Search String"
@@ -245,49 +248,60 @@ msgstr ""
#: .\cookbook\forms.py:353
msgid "Maximum number of users for this space reached."
msgstr ""
msgstr "Número máximo de utilizadores alcançado."
#: .\cookbook\forms.py:359
msgid "Email address already taken!"
msgstr ""
msgstr "Endereço email já utilizado!"
#: .\cookbook\forms.py:367
msgid ""
"An email address is not required but if present the invite link will be sent "
"to the user."
msgstr ""
"Um endereço de email não é obrigatório mas se fornecido será enviada uma "
"mensagem ao utilizador."
#: .\cookbook\forms.py:382
msgid "Name already taken."
msgstr ""
msgstr "Nome já existente."
#: .\cookbook\forms.py:393
msgid "Accept Terms and Privacy"
msgstr ""
msgstr "Aceitar Termos e Condições"
#: .\cookbook\forms.py:425
msgid ""
"Determines how fuzzy a search is if it uses trigram similarity matching (e."
"g. low values mean more typos are ignored)."
msgstr ""
"Determina o quão difusa uma pesquisa é se esta utilizar uma correspondência "
"de semelhança de trigrama (valores mais baixos significam que mais erros são "
"ignorados)."
#: .\cookbook\forms.py:435
msgid ""
"Select type method of search. Click <a href=\"/docs/search/\">here</a> for "
"full desciption of choices."
msgstr ""
"Selecionar o método de pesquisa. Uma descrição completa das opções pode ser "
"encontrada <a href=\"/docs/search/\">aqui</a>."
#: .\cookbook\forms.py:436
msgid ""
"Use fuzzy matching on units, keywords and ingredients when editing and "
"importing recipes."
msgstr ""
"Utilizar correspondência difusa em unidades, palavras-chave e ingredientes "
"ao editar e importar receitas."
#: .\cookbook\forms.py:438
msgid ""
"Fields to search ignoring accents. Selecting this option can improve or "
"degrade search quality depending on language"
msgstr ""
"Campos de pesquisa que ignoram pontuação. Esta opção pode aumentar ou "
"diminuir a qualidade de pesquisa dependendo da língua em uso"
#: .\cookbook\forms.py:440
msgid ""

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -39,6 +39,11 @@ class RecipeSchema(AutoSchema):
"description": 'Id of book a recipe should have. For multiple repeat parameter.',
'schema': {'type': 'string', },
})
parameters.append({
"name": 'steps', "in": "query", "required": False,
"description": 'Id of a step a recipe should have. For multiple repeat parameter.',
'schema': {'type': 'string', },
})
parameters.append({
"name": 'keywords_or', "in": "query", "required": False,
"description": 'If recipe should have all (AND) or any (OR) of the provided keywords.',
@@ -86,7 +91,8 @@ class TreeSchema(AutoSchema):
})
parameters.append({
"name": 'root', "in": "query", "required": False,
"description": 'Return first level children of {obj} with ID [int]. Integer 0 will return root {obj}s.'.format(obj=api_name),
"description": 'Return first level children of {obj} with ID [int]. Integer 0 will return root {obj}s.'.format(
obj=api_name),
'schema': {'type': 'int', },
})
parameters.append({
@@ -110,3 +116,17 @@ class FilterSchema(AutoSchema):
'schema': {'type': 'string', },
})
return parameters
class QueryOnlySchema(AutoSchema):
def get_path_parameters(self, path, method):
if not is_list_view(path, method, self.view):
return super(QueryOnlySchema, self).get_path_parameters(path, method)
parameters = super().get_path_parameters(path, method)
parameters.append({
"name": 'query', "in": "query", "required": False,
"description": 'Query string matched (fuzzy) against object name.',
'schema': {'type': 'string', },
})
return parameters

View File

@@ -34,7 +34,8 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
api_serializer = None
# extended values are computationally expensive and not needed in normal circumstances
try:
if bool(int(self.context['request'].query_params.get('extended', False))) and self.__class__ == api_serializer:
if bool(int(
self.context['request'].query_params.get('extended', False))) and self.__class__ == api_serializer:
return fields
except AttributeError:
pass
@@ -49,11 +50,13 @@ class ExtendedRecipeMixin(serializers.ModelSerializer):
def get_image(self, obj):
# TODO add caching
recipes = Recipe.objects.filter(**{self.recipe_filter: obj}, space=obj.space).exclude(image__isnull=True).exclude(image__exact='')
recipes = Recipe.objects.filter(**{self.recipe_filter: obj}, space=obj.space).exclude(
image__isnull=True).exclude(image__exact='')
try:
if recipes.count() == 0 and obj.has_children():
obj__in = self.recipe_filter + '__in'
recipes = Recipe.objects.filter(**{obj__in: obj.get_descendants()}, space=obj.space).exclude(image__isnull=True).exclude(image__exact='') # if no recipes found - check whole tree
recipes = Recipe.objects.filter(**{obj__in: obj.get_descendants()}, space=obj.space).exclude(
image__isnull=True).exclude(image__exact='') # if no recipes found - check whole tree
except AttributeError:
# probably not a tree
pass
@@ -404,7 +407,10 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
class Meta:
model = Food
fields = ('id', 'name', 'description', 'recipe', 'ignore_shopping', 'supermarket_category', 'image', 'parent', 'numchild', 'numrecipe')
fields = (
'id', 'name', 'description', 'recipe', 'ignore_shopping', 'supermarket_category', 'image', 'parent',
'numchild',
'numrecipe')
read_only_fields = ('id', 'numchild', 'parent', 'image')
@@ -425,12 +431,13 @@ class IngredientSerializer(WritableNestedModelSerializer):
)
class StepSerializer(WritableNestedModelSerializer):
class StepSerializer(WritableNestedModelSerializer, ExtendedRecipeMixin):
ingredients = IngredientSerializer(many=True)
ingredients_markdown = serializers.SerializerMethodField('get_ingredients_markdown')
ingredients_vue = serializers.SerializerMethodField('get_ingredients_vue')
file = UserFileViewSerializer(allow_null=True, required=False)
step_recipe_data = serializers.SerializerMethodField('get_step_recipe_data')
recipe_filter = 'steps'
def create(self, validated_data):
validated_data['space'] = self.context['request'].space
@@ -442,6 +449,9 @@ class StepSerializer(WritableNestedModelSerializer):
def get_ingredients_markdown(self, obj):
return obj.get_instruction_render()
def get_step_recipes(self, obj):
return list(obj.recipe_set.values_list('id', flat=True).all())
def get_step_recipe_data(self, obj):
# check if root type is recipe to prevent infinite recursion
# can be improved later to allow multi level embedding
@@ -452,7 +462,7 @@ class StepSerializer(WritableNestedModelSerializer):
model = Step
fields = (
'id', 'name', 'type', 'instruction', 'ingredients', 'ingredients_markdown',
'ingredients_vue', 'time', 'order', 'show_as_header', 'file', 'step_recipe', 'step_recipe_data'
'ingredients_vue', 'time', 'order', 'show_as_header', 'file', 'step_recipe', 'step_recipe_data', 'numrecipe'
)

View File

@@ -92,10 +92,10 @@ def recipe_last(recipe, user):
@register.simple_tag
def page_help(page_name):
help_pages = {
'edit_storage': 'https://vabene1111.github.io/recipes/features/external_recipes/',
'view_shopping': 'https://vabene1111.github.io/recipes/features/shopping/',
'view_import': 'https://vabene1111.github.io/recipes/features/import_export/',
'view_export': 'https://vabene1111.github.io/recipes/features/import_export/',
'edit_storage': 'https://docs.tandoor.dev/features/external_recipes/',
'view_shopping': 'https://docs.tandoor.dev/features/shopping/',
'view_import': 'https://docs.tandoor.dev/features/import_export/',
'view_export': 'https://docs.tandoor.dev/features/import_export/',
}
link = help_pages.get(page_name, '')

View File

@@ -10,7 +10,8 @@ from cookbook.helper import dal
from .models import (Comment, Food, InviteLink, Keyword, MealPlan, Recipe,
RecipeBook, RecipeBookEntry, RecipeImport, ShoppingList,
Storage, Supermarket, SupermarketCategory, Sync, SyncLog, Unit, get_model_name, Automation, UserFile)
Storage, Supermarket, SupermarketCategory, Sync, SyncLog, Unit, get_model_name, Automation,
UserFile, Step)
from .views import api, data, delete, edit, import_export, lists, new, views, telegram
router = routers.DefaultRouter()
@@ -177,7 +178,7 @@ for m in generic_models:
)
)
vue_models = [Food, Keyword, Unit, Supermarket, SupermarketCategory, Automation, UserFile]
vue_models = [Food, Keyword, Unit, Supermarket, SupermarketCategory, Automation, UserFile, Step]
for m in vue_models:
py_name = get_model_name(m)
url_name = py_name.replace('_', '-')

View File

@@ -48,7 +48,7 @@ from cookbook.models import (CookLog, Food, Ingredient, Keyword, MealPlan,
from cookbook.provider.dropbox import Dropbox
from cookbook.provider.local import Local
from cookbook.provider.nextcloud import Nextcloud
from cookbook.schemas import FilterSchema, RecipeSchema, TreeSchema
from cookbook.schemas import FilterSchema, RecipeSchema, TreeSchema, QueryOnlySchema
from cookbook.serializer import (FoodSerializer, IngredientSerializer,
KeywordSerializer, MealPlanSerializer,
MealTypeSerializer, RecipeBookSerializer,
@@ -410,7 +410,7 @@ class RecipeBookViewSet(viewsets.ModelViewSet, StandardFilterMixin):
permission_classes = [CustomIsOwner]
def get_queryset(self):
self.queryset = self.queryset.filter(created_by=self.request.user).filter(space=self.request.space)
self.queryset = self.queryset.filter(Q(created_by=self.request.user) | Q(shared=self.request.user)).filter(space=self.request.space)
return super().get_queryset()
@@ -498,9 +498,16 @@ class StepViewSet(viewsets.ModelViewSet):
queryset = Step.objects
serializer_class = StepSerializer
permission_classes = [CustomIsUser]
pagination_class = DefaultPagination
schema = QueryOnlySchema()
def get_queryset(self):
return self.queryset.filter(recipe__space=self.request.space)
queryset = self.queryset.filter(recipe__space=self.request.space)
query = self.request.query_params.get('query', None)
if query is not None:
queryset = queryset.filter(Q(name__icontains=query) | Q(recipe__name__icontains=query))
return queryset
class RecipePagination(PageNumberPagination):

View File

@@ -191,13 +191,12 @@ def import_url(request):
ingredient.save()
step.ingredients.add(ingredient)
print(ingredient)
if 'image' in data and data['image'] != '' and data['image'] is not None:
try:
response = requests.get(data['image'])
img, filetype = handle_image(request, BytesIO(response.content))
img, filetype = handle_image(request, File(BytesIO(response.content), name='image'))
recipe.image = File(
img, name=f'{uuid.uuid4()}_{recipe.pk}{filetype}'
)

View File

@@ -221,6 +221,23 @@ def user_file(request):
)
@group_required('user')
def step(request):
# recipe-param is the name of the parameters used when filtering recipes by this attribute
# model-name is the models.js name of the model, probably ALL-CAPS
return render(
request,
'generic/model_template.html',
{
"title": _("Steps"),
"config": {
'model': "STEP", # *REQUIRED* name of the model in models.js
'recipe_param': 'steps',
}
}
)
@group_required('user')
def shopping_list_new(request):
# recipe-param is the name of the parameters used when filtering recipes by this attribute

View File

@@ -59,6 +59,8 @@ folder of the GitHub repository.
In order to contribute to the documentation you can fork the repository and edit the markdown files in the browser.
Now install mkdocs and dependencies: `pip install mkdocs-material mkdocs-include-markdown-plugin`.
If you want to test the documentation locally run `mkdocs serve` from the project root.
## Contribute Translations

View File

@@ -37,4 +37,13 @@ There is only one installation of the Dropbox system, but it handles multiple us
For Tandoor that means all people that work together on one recipe collection can be in one space.
If you want to host the collection of your friends family or your neighbor you can create a separate space for them (trough the admin interface).
Sharing between spaces is currently not possible but is planned for future releases.
Sharing between spaces is currently not possible but is planned for future releases.
## Create Admin user / reset passwords
To create a superuser or reset a lost password if access to the container is lost you need to
1. execute into the container using `docker-compose exec web_recipes sh`
2. activate the virtual environment `source venv/bin/activate`
3. run `python manage.py createsuperuser` and follow the steps shown.
To change a password enter `python manage.py changepassword <username>` in step 3.

View File

@@ -2,13 +2,13 @@ This application features a very versatile import and export feature in order
to offer the best experience possible and allow you to freely choose where your data goes.
!!! warning "WIP"
The Module is relatively new. There is a know issue with [Timeouts](https://github.com/vabene1111/recipes/issues/417) on large exports.
The Module is relatively new. There is a known issue with [Timeouts](https://github.com/vabene1111/recipes/issues/417) on large exports.
A fix is being developed and will likely be released with the next version.
The Module is build with maximum flexibility and expandability in mind and allows to easily add new
The Module is built with maximum flexibility and expandability in mind and allows to easily add new
integrations to allow you to both import and export your recipes into whatever format you desire.
Feel like there is an important integration missing ? Just take a look at the [integration issues](https://github.com/vabene1111/recipes/issues?q=is%3Aissue+is%3Aopen+label%3Aintegration) or open a new one
Feel like there is an important integration missing? Just take a look at the [integration issues](https://github.com/vabene1111/recipes/issues?q=is%3Aissue+is%3Aopen+label%3Aintegration) or open a new one
if your favorite one is missing.
!!! info "Export"
@@ -41,7 +41,7 @@ Overview of the capabilities of the different integrations.
✔ = implemented, ❌ = not implemented and not possible/planned, ⌚ = not yet implemented
## Default
The default integration is the build in (and preferred) way to import and export recipes.
The default integration is the built in (and preferred) way to import and export recipes.
It is maintained with new fields added and contains all data to transfer your recipes from one installation to another.
It is also one of the few recipe formats that is actually structured in a way that allows for
@@ -90,7 +90,7 @@ Mealie provides structured data similar to nextcloud.
To migrate your recipes
1. Go to you Mealie settings and create a new Backup
1. Go to your Mealie settings and create a new Backup
2. Download the backup by clicking on it and pressing download (this wasn't working for me, so I had to manually pull it from the server)
3. Upload the entire `.zip` file to the importer page and import everything
@@ -118,7 +118,7 @@ Recipes.zip/
```
## Safron
Go to you safron settings page and export your recipes.
Go to your safron settings page and export your recipes.
Then simply upload the entire `.zip` file to the importer.
!!! warning "Images"
@@ -131,8 +131,8 @@ The `.paprikarecipes` file is basically just a zip with gzipped contents. Simply
all your recipes.
## Pepperplate
Pepperplate provides a `.zip` files contain all your recipes as `.txt` files. These files are well-structured and allow
the import of all data without loosing anything.
Pepperplate provides a `.zip` file containing all of your recipes as `.txt` files. These files are well-structured and allow
the import of all data without losing anything.
Simply export the recipes from Pepperplate and upload the zip to Tandoor. Images are not included in the export and
thus cannot be imported.
@@ -145,7 +145,7 @@ This format is basically completely unstructured and every export looks differen
and leads to suboptimal results. Images are also not supported as they are not included in the export (at least
the tests I had).
Usually the import should recognize all ingredients and put everything else into the instructions. If you import fails
Usually the import should recognize all ingredients and put everything else into the instructions. If your import fails
or is worse than this feel free to provide me with more example data and I can try to improve the importer.
As ChefTap cannot import these files anyway there won't be an exporter implemented in Tandoor.
@@ -154,7 +154,7 @@ As ChefTap cannot import these files anyway there won't be an exporter implement
Meal master can be imported by uploading one or more meal master files.
The files should either be `.txt`, `.MMF` or `.MM` files.
The MealMaster spec allow for many variations. Currently, only the on column format for ingredients is supported.
The MealMaster spec allow for many variations. Currently, only the one column format for ingredients is supported.
Second line notes to ingredients are currently also not imported as a note but simply put into the instructions.
If you have MealMaster recipes that cannot be imported feel free to raise an issue.
@@ -166,7 +166,7 @@ The generated file can simply be imported into Tandoor.
As I only had limited sample data feel free to open an issue if your RezKonv export cannot be imported.
## Recipekeeper
Recipe keeper allows to export a zip file containing recipes and images using its apps.
Recipe keeper allows you to export a zip file containing recipes and images using its apps.
This zip file can simply be imported into Tandoor.
## OpenEats
@@ -213,8 +213,8 @@ Store the outputted json string in a `.json` file and simply import it using the
## Plantoeat
Plan to eat allow to export a text file containing all your recipes. Simply upload that text file to Tandoor to import all recipes
Plan to eat allows you to export a text file containing all your recipes. Simply upload that text file to Tandoor to import all recipes
## CookBookApp
CookBookApp can export .zip files containing .html files. Upload the entire ZIP to Tandoor to import all included recipes.
CookBookApp can export .zip files containing .html files. Upload the entire ZIP to Tandoor to import all included recipes.

View File

@@ -65,47 +65,9 @@ This configuration exposes the application through an nginx web server on port 8
wget https://raw.githubusercontent.com/vabene1111/recipes/develop/docs/install/docker/plain/docker-compose.yml
```
```yaml
version: "3"
services:
db_recipes:
restart: always
image: postgres:11-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
- ./.env
web_recipes:
image: vabene1111/recipes
restart: always
env_file:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
- nginx_config:/opt/recipes/nginx/conf.d
- ./mediafiles:/opt/recipes/mediafiles
depends_on:
- db_recipes
nginx_recipes:
image: nginx:mainline-alpine
restart: always
ports:
- 80:80
env_file:
- ./.env
depends_on:
- web_recipes
volumes:
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static
- ./mediafiles:/media
volumes:
nginx_config:
staticfiles:
```
~~~yaml
{% include "./docker/plain/docker-compose.yml" %}
~~~
### Reverse Proxy
@@ -123,62 +85,9 @@ If you use traefik, this configuration is the one for you.
wget https://raw.githubusercontent.com/vabene1111/recipes/develop/docs/install/docker/traefik-nginx/docker-compose.yml
```
```yaml
version: "3"
services:
db_recipes:
restart: always
image: postgres:11-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
- ./.env
networks:
- default
web_recipes:
image: vabene1111/recipes
restart: always
env_file:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
- nginx_config:/opt/recipes/nginx/conf.d
- ./mediafiles:/opt/recipes/mediafiles
depends_on:
- db_recipes
networks:
- default
nginx_recipes:
image: nginx:mainline-alpine
restart: always
env_file:
- ./.env
volumes:
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static
- ./mediafiles:/media
labels: # traefik example labels
- "traefik.enable=true"
- "traefik.http.routers.recipes.rule=Host(`recipes.mydomain.com`, `recipes.myotherdomain.com`)"
- "traefik.http.routers.recipes.entrypoints=web_secure" # your https endpoint
- "traefik.http.routers.recipes.tls.certresolver=le_resolver" # your cert resolver
depends_on:
- web_recipes
networks:
- default
- traefik
networks:
default:
traefik: # This is you external traefik network
external: true
volumes:
nginx_config:
staticfiles:
```
~~~yaml
{% include "./docker/traefik-nginx/docker-compose.yml" %}
~~~
#### nginx-proxy
@@ -198,58 +107,9 @@ LETSENCRYPT_EMAIL=
wget https://raw.githubusercontent.com/vabene1111/recipes/develop/docs/install/docker/nginx-proxy/docker-compose.yml
```
```yaml
version: "3"
services:
db_recipes:
restart: always
image: postgres:11-alpine
volumes:
- ./postgresql:/var/lib/postgresql/data
env_file:
- ./.env
networks:
- default
web_recipes:
image: vabene1111/recipes
restart: always
env_file:
- ./.env
volumes:
- staticfiles:/opt/recipes/staticfiles
- nginx_config:/opt/recipes/nginx/conf.d
- ./mediafiles:/opt/recipes/mediafiles
depends_on:
- db_recipes
networks:
- default
nginx_recipes:
image: nginx:mainline-alpine
restart: always
env_file:
- ./.env
depends_on:
- web_recipes
volumes:
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static
- ./mediafiles:/media
networks:
- default
- nginx-proxy
networks:
default:
nginx-proxy:
external:
name: nginx-proxy
volumes:
nginx_config:
staticfiles:
```
~~~yaml
{% include "./docker/nginx-proxy/docker-compose.yml" %}
~~~
## Additional Information

View File

@@ -4,12 +4,14 @@ metadata:
labels:
app: recipes
name: recipes-nginx-config
namespace: default
data:
nginx-config: |-
events {
worker_connections 1024;
}
http {
include mime.types;
server {
listen 80;
server_name _;
@@ -24,10 +26,5 @@ data:
location /media/ {
alias /media/;
}
# pass requests for dynamic content to gunicorn
location / {
proxy_set_header Host $host;
proxy_pass http://localhost:8080;
}
}
}

View File

@@ -0,0 +1,13 @@
kind: Secret
apiVersion: v1
metadata:
name: recipes
namespace: default
type: Opaque
data:
# echo -n 'db-password' | base64
postgresql-password: ZGItcGFzc3dvcmQ=
# echo -n 'postgres-user-password' | base64
postgresql-postgres-password: cG9zdGdyZXMtdXNlci1wYXNzd29yZA==
# echo -n 'secret-key' | sha256sum | awk '{ printf $1 }' | base64
secret-key: ODVkYmUxNWQ3NWVmOTMwOGM3YWUwZjMzYzdhMzI0Y2M2ZjRiZjUxOWEyZWQyZjMwMjdiZDMzYzE0MGE0ZjlhYQ==

View File

@@ -0,0 +1,5 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: recipes
namespace: default

View File

@@ -1,50 +0,0 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: recipes-db
labels:
app: recipes
type: local
tier: db
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
hostPath:
path: "/data/recipes/db"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: recipes-media
labels:
app: recipes
type: local
tier: media
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
hostPath:
path: "/data/recipes/media"
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: recipes-static
labels:
app: recipes
type: local
tier: static
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteMany
hostPath:
path: "/data/recipes/static"

View File

@@ -1,34 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: recipes-db
labels:
app: recipes
spec:
selector:
matchLabels:
tier: db
storageClassName: manual
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: recipes-media
namespace: default
labels:
app: recipes
spec:
selector:
matchLabels:
tier: media
app: recipes
storageClassName: manual
accessModes:
- ReadWriteMany
- ReadWriteOnce
resources:
requests:
storage: 1Gi
@@ -37,16 +16,12 @@ apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: recipes-static
namespace: default
labels:
app: recipes
spec:
selector:
matchLabels:
tier: static
app: recipes
storageClassName: manual
accessModes:
- ReadWriteMany
- ReadWriteOnce
resources:
requests:
storage: 1Gi

View File

@@ -0,0 +1,142 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: recipes
tier: database
name: recipes-postgresql
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: recipes
serviceName: recipes-postgresql
updateStrategy:
type: RollingUpdate
template:
metadata:
annotations:
backup.velero.io/backup-volumes: data
labels:
app: recipes
tier: database
name: recipes-postgresql
namespace: default
spec:
restartPolicy: Always
securityContext:
fsGroup: 999
serviceAccount: recipes
serviceAccountName: recipes
terminationGracePeriodSeconds: 30
containers:
- name: recipes-db
env:
- name: BITNAMI_DEBUG
value: "false"
- name: POSTGRESQL_PORT_NUMBER
value: "5432"
- name: POSTGRESQL_VOLUME_DIR
value: /bitnami/postgresql
- name: PGDATA
value: /bitnami/postgresql/data
- name: POSTGRES_USER
value: recipes
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: recipes
key: postgresql-password
- name: POSTGRESQL_POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: recipes
key: postgresql-postgres-password
- name: POSTGRES_DB
value: recipes
image: docker.io/bitnami/postgresql:11.5.0-debian-9-r60
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- sh
- -c
- exec pg_isready -U "postgres" -d "wiki" -h 127.0.0.1 -p 5432
failureThreshold: 6
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
ports:
- containerPort: 5432
name: postgresql
protocol: TCP
readinessProbe:
exec:
command:
- sh
- -c
- -e
- |
pg_isready -U "postgres" -d "wiki" -h 127.0.0.1 -p 5432
[ -f /opt/bitnami/postgresql/tmp/.initialized ]
failureThreshold: 6
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
resources:
requests:
cpu: 250m
memory: 256Mi
securityContext:
runAsUser: 1001
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /bitnami/postgresql
name: data
dnsPolicy: ClusterFirst
initContainers:
- command:
- sh
- -c
- |
mkdir -p /bitnami/postgresql/data
chmod 700 /bitnami/postgresql/data
find /bitnami/postgresql -mindepth 0 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" | \
xargs chown -R 1001:1001
image: docker.io/bitnami/minideb:stretch
imagePullPolicy: Always
name: init-chmod-data
resources:
requests:
cpu: 250m
memory: 256Mi
securityContext:
runAsUser: 0
volumeMounts:
- mountPath: /bitnami/postgresql
name: data
restartPolicy: Always
securityContext:
fsGroup: 1001
serviceAccount: recipes
serviceAccountName: recipes
terminationGracePeriodSeconds: 30
updateStrategy:
type: RollingUpdate
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
volumeMode: Filesystem

View File

@@ -0,0 +1,19 @@
apiVersion: v1
kind: Service
metadata:
labels:
app: recipes
tier: database
name: recipes-postgresql
namespace: default
spec:
ports:
- name: postgresql
port: 5432
protocol: TCP
targetPort: postgresql
selector:
app: recipes
tier: database
sessionAffinity: None
type: ClusterIP

View File

@@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: recipes
namespace: default
labels:
app: recipes
environment: production
@@ -9,17 +10,78 @@ metadata:
spec:
replicas: 1
strategy:
type: RollingUpdate
type: Recreate
selector:
matchLabels:
app: recipes
environment: production
template:
metadata:
annotations:
backup.velero.io/backup-volumes: media,static
labels:
app: recipes
tier: frontend
environment: production
spec:
restartPolicy: Always
serviceAccount: recipes
serviceAccountName: recipes
initContainers:
- name: init-chmod-data
env:
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: recipes
key: secret-key
- name: DB_ENGINE
value: django.db.backends.postgresql_psycopg2
- name: POSTGRES_HOST
value: recipes-postgresql
- name: POSTGRES_PORT
value: "5432"
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_DB
value: recipes
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: recipes
key: postgresql-postgres-password
image: vabene1111/recipes:1.0.1
imagePullPolicy: Always
resources:
requests:
cpu: 250m
memory: 64Mi
command:
- sh
- -c
- |
set -e
source venv/bin/activate
echo "Updating database"
python manage.py migrate
python manage.py collectstatic_js_reverse
python manage.py collectstatic --noinput
echo "Setting media file attributes"
chown -R 65534:65534 /opt/recipes/mediafiles
find /opt/recipes/mediafiles -type d | xargs -r chmod 755
find /opt/recipes/mediafiles -type f | xargs -r chmod 644
echo "Done"
securityContext:
runAsUser: 0
volumeMounts:
- mountPath: /opt/recipes/mediafiles
name: media
# mount as subPath due to lost+found on ext4 pvc
subPath: files
- mountPath: /opt/recipes/staticfiles
name: static
# mount as subPath due to lost+found on ext4 pvc
subPath: files
containers:
- name: recipes-nginx
image: nginx:latest
@@ -28,69 +90,94 @@ spec:
- containerPort: 80
protocol: TCP
name: http
- containerPort: 8080
protocol: TCP
name: gunicorn
resources:
requests:
cpu: 250m
memory: 64Mi
volumeMounts:
- mountPath: '/media'
- mountPath: /media
name: media
- mountPath: '/static'
# mount as subPath due to lost+found on ext4 pvc
subPath: files
- mountPath: /static
name: static
# mount as subPath due to lost+found on ext4 pvc
subPath: files
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx-config
readOnly: true
- name: recipes
image: 'vabene1111/recipes:latest'
image: vabene1111/recipes:1.0.1
imagePullPolicy: IfNotPresent
command:
- /opt/recipes/venv/bin/gunicorn
- -b
- :8080
- --access-logfile
- "-"
- --error-logfile
- "-"
- --log-level
- INFO
- recipes.wsgi
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: 8080
scheme: HTTP
periodSeconds: 30
readinessProbe:
httpGet:
path: /
port: 8080
scheme: HTTP
periodSeconds: 30
resources:
requests:
cpu: 250m
memory: 64Mi
volumeMounts:
- mountPath: '/opt/recipes/mediafiles'
- mountPath: /opt/recipes/mediafiles
name: media
- mountPath: '/opt/recipes/staticfiles'
# mount as subPath due to lost+found on ext4 pvc
subPath: files
- mountPath: /opt/recipes/staticfiles
name: static
# mount as subPath due to lost+found on ext4 pvc
subPath: files
env:
- name: DEBUG
value: "0"
- name: ALLOWED_HOSTS
value: '*'
- name: SECRET_KEY
value: # CHANGEME
valueFrom:
secretKeyRef:
name: recipes
key: secret-key
- name: DB_ENGINE
value: django.db.backends.postgresql_psycopg2
- name: POSTGRES_HOST
value: localhost
value: recipes-postgresql
- name: POSTGRES_PORT
value: "5432"
- name: POSTGRES_USER
value: recipes
value: postgres
- name: POSTGRES_DB
value: recipes
- name: POSTGRES_PASSWORD
value: # CHANGEME
- name: recipes-db
image: 'postgres:latest'
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5432
volumeMounts:
- mountPath: '/var/lib/postgresql/data'
name: database
env:
- name: POSTGRES_USER
value: recipes
- name: POSTGRES_DB
value: recipes
- name: POSTGRES_PASSWORD
value: # CHANGEME
valueFrom:
secretKeyRef:
name: recipes
key: postgresql-postgres-password
securityContext:
runAsUser: 65534
volumes:
- name: database
persistentVolumeClaim:
claimName: recipes-db
- name: media
persistentVolumeClaim:
claimName: recipes-media

View File

@@ -2,14 +2,21 @@ apiVersion: v1
kind: Service
metadata:
name: recipes
namespace: default
labels:
app: recipes
tier: frontend
spec:
selector:
app: recipes
tier: frontend
environment: production
ports:
- port: 80
targetPort: http
name: http
protocol: TCP
- port: 8080
targetPort: gunicorn
name: gunicorn
protocol: TCP

View File

@@ -0,0 +1,38 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
#cert-manager.io/cluster-issuer: letsencrypt-prod
#kubernetes.io/ingress.class: nginx
name: recipes
namespace: default
spec:
rules:
- host: recipes.local
http:
paths:
- backend:
service:
name: recipes
port:
number: 8080
path: /
pathType: Prefix
- backend:
service:
name: recipes
port:
number: 80
path: /media
pathType: Prefix
- backend:
service:
name: recipes
port:
number: 80
path: /static
pathType: Prefix
#tls:
#- hosts:
# - recipes.local
# secretName: recipes-local-tls

View File

@@ -1,31 +1,98 @@
!!! info "Community Contributed"
This guide was contributed by the community and is neither officially supported, nor updated or tested.
**!!! info "Community Contributed" This guide was contributed by the community and is neither officially supported, nor updated or tested.**
This is a basic kubernetes setup.
Please note that this does not necessarily follow Kubernetes best practices and should only used as a
basis to build your own setup from!
# K8s Setup
All files con be found here in the Github Repo:
[docs/install/k8s](https://github.com/vabene1111/recipes/tree/develop/docs/install/k8s)
This is a setup which should be sufficent for production use. Be sure to replace the default secrets!
## Important notes
# Files
State (database, static files and media files) is handled via `PersistentVolumes`.
## 10-configmap.yaml
Note that you will most likely have to change the `PersistentVolumes` in `30-pv.yaml`. The current setup is only usable for a single-node cluster because it uses local storage on the kubernetes worker nodes under `/data/recipes/`. It should just serve as an example.
The nginx config map. This is loaded as nginx.conf in the nginx sidecar to configure nginx to deliver static content.
Currently, the deployment in `50-deployment.yaml` just pulls the `latest` tag of all containers. In a production setup, you should set this to a fixed version!
## 15-secrets.yaml
See env variables tagged with `CHANGEME` in `50-deployment.yaml` and make sure to change those! A better setup would use kubernetes secrets but this is not implemented yet.
The secrets **replace them!!** This file is only here for a quick start. Be aware that changing secrets after installation will be messy and is not documented here. **You should set new secrets before the installation.** As you are reading this document **before** the installation ;-)
## Updates
Create your own postgresql passwords and the secret key for the django app
These manifests are not tested against new versions.
see also [Managing Secrets using kubectl](https://kubernetes.io/docs/tasks/configmap-secret/managing-secret-using-kubectl/)
## Apply the manifets
**Replace** `db-password`, `postgres-user-password` and `secret-key` **with something - well - secret :-)**
To apply the manifest with `kubectl`, use the following command:
~~~
echo -n 'db-password' > ./db-password.txt
echo -n 'postgres-user-password' > ./postgres-password.txt
echo -n 'secret-key' | sha256sum | awk '{ printf $1 }' > ./secret-key.txt
~~~
```
Delete the default secrets file `15-secrets.yaml` and generate the K8s secret from your files.
~~~
kubectl create secret generic recipes \
--from-file=postgresql-password=./db-password.txt \
--from-file=postgresql-postgres-password=./postgres-password.txt \
--from-file=secret-key=./secret-key.txt
~~~
## 20-service-account.yml
Creating service account `recipes` for deployment and stateful set.
## 30-pvc.yaml
The creation of the persistent volume claims for media and static content. May you want to increase the size. This expects to have a storage class installed.
## 40-sts-postgresql.yaml
The PostgreSQL stateful set, based on a bitnami image. It runs a init container as root to do the preparations. The postgres container itsef runs as a lower privileged user. The recipes app uses the database super user (postgres) as the recipies app is doing some db migrations on startup, which needs super user privileges.
## 45-service-db.yaml
Creating the database service.
## 50-deployment.yaml
The deployment first fires up a init container to do the database migrations and file modifications. This init container runs as root. The init conainer runs part of the [boot.sh](https://github.com/TandoorRecipes/recipes/blob/develop/boot.sh) script from the `vabene1111/recipes` image.
The deployment then runs two containers, the recipes-nginx and the recipes container which runs the gunicorn app. The nginx container gets it's nginx.conf via config map to deliver static content `/static` and `/media`. The guincorn container gets it's secret key and the database password from the secret `recipes`. `gunicorn` runs as user `nobody`.
## 60-service.yaml
Creating the app service.
## 70-ingress.yaml
Setting up the ingress for the recipes service. Requests for static content `/static` and `/media` are send to the nginx container, everything else to gunicorn. TLS setup via cert-manager is prepared. You have to **change the host** from `recipes.local` to your specific domain.
# Conclusion
All in all:
- The database is set up as a stateful set.
- The database container runs as a low privileged user.
- Database and application use secrets.
- The application also runs as a low privileged user.
- nginx runs as root but forks children with a low privileged user.
- There's an ingress rule to access the application from outside.
I tried the setup with [kind](https://kind.sigs.k8s.io/) and it runs well on my local cluster.
There is a warning, when you check your system as super user:
**Media Serving Warning**
Serving media files directly using gunicorn/python is not recommend! Please follow the steps described here to update your installation.
I don't know how this check works, but this warning is simply wrong! ;-) Media and static files are routed by ingress to the nginx container - I promise :-)
# Updates
These manifests are tested against Release 1.0.1. Newer versions may not work without changes.
# Apply the manifets
To apply the manifest with kubectl, use the following command:
~~~
kubectl apply -f ./docs/k8s/
```
~~~

View File

@@ -21,6 +21,9 @@ markdown_extensions:
- pymdownx.highlight
- pymdownx.superfences
plugins:
- include-markdown
nav:
- Home: 'index.md'
- Installation:

View File

@@ -151,6 +151,7 @@ MIDDLEWARE = [
]
SORT_TREE_BY_NAME = bool(int(os.getenv('SORT_TREE_BY_NAME', False)))
DISABLE_TREE_FIX_STARTUP = bool(int(os.getenv('DISABLE_TREE_FIX_STARTUP', False)))
if bool(int(os.getenv('SQL_DEBUG', False))):
MIDDLEWARE += ('recipes.middleware.SqlPrintingMiddleware',)

View File

@@ -28,8 +28,8 @@
<!-- <span><b-button variant="link" size="sm" class="text-dark shadow-none"><i class="fas fa-chevron-down"></i></b-button></span> -->
<model-menu/>
<span>{{ this.this_model.name }}</span>
<span><b-button variant="link" @click="startAction({'action':'new'})"><i
class="fas fa-plus-circle fa-2x"></i></b-button></span>
<span v-if="this_model.name !== 'Step'"><b-button variant="link" @click="startAction({'action':'new'})"><i
class="fas fa-plus-circle fa-2x"></i></b-button></span><!-- TODO add proper field to model config to determine if create should be available or not -->
</h3>
</div>
<div class="col-md-3" style="position: relative; margin-top: 1vh">
@@ -431,7 +431,7 @@ export default {
// TODO: make this generic
let params = {'pageSize': 50}
params[this.this_recipe_param] = item.id
console.log('RECIPE PARAM', this.this_recipe_param, params, item.id)
this.genericAPI(this.Models.RECIPE, this.Actions.LIST, params).then((result) => {
parent = this.findCard(item.id, this['items_' + col])
if (parent) {

View File

@@ -34,6 +34,10 @@
<i class="fas fa-file fa-fw"></i> {{ Models['USERFILE'].name }}
</b-dropdown-item>
<b-dropdown-item :href="resolveDjangoUrl('list_step')">
<i class="fas fa-puzzle-piece fa-fw"></i>{{ Models['STEP'].name }}
</b-dropdown-item>
</b-dropdown>
</span>
</template>

View File

@@ -169,7 +169,7 @@
"Week": "Woche",
"Month": "Monat",
"Year": "Jahr",
"Drag_Here_To_Delete": "Ziehen zum löschen",
"Drag_Here_To_Delete": "Ziehen zum Löschen",
"Select_File": "Datei auswählen",
"Image": "Bild",
"Planner": "Planer",

View File

@@ -190,5 +190,7 @@
"Hide_as_header": "Cacher comme entête",
"Copy_template_reference": "Copier le modèle de référence",
"Edit_Recipe": "Modifier une Recette",
"Move_Up": "Monter"
"Move_Up": "Monter",
"Time": "Temps",
"Coming_Soon": "Bientôt disponible"
}

View File

@@ -1,8 +1,8 @@
{
"err_fetching_resource": "Si è verificato un errore nel recupero della risorsa!",
"err_creating_resource": "Si è verificato un errore durante la creazione di una risorsa!",
"err_updating_resource": "Si è verificato un errore nell'aggiornamento della risorsa!",
"err_deleting_resource": "Si è verificato un errore nella cancellazione della risorsa!",
"err_updating_resource": "Si è verificato un errore durante l'aggiornamento della risorsa!",
"err_deleting_resource": "Si è verificato un errore durante la cancellazione della risorsa!",
"success_fetching_resource": "Risorsa recuperata con successo!",
"success_creating_resource": "Risorsa creata con successo!",
"success_updating_resource": "Risorsa aggiornata con successo!",
@@ -29,7 +29,7 @@
"New_Recipe": "Nuova Ricetta",
"Url_Import": "Importa da URL",
"Reset_Search": "Ripristina Ricerca",
"Recently_Viewed": "Visualizzati di recente",
"Recently_Viewed": "Visualizzato di recente",
"Load_More": "Carica di più",
"New_Keyword": "Nuova parola chiave",
"Delete_Keyword": "Elimina parola chiave",
@@ -44,7 +44,7 @@
"Fats": "Grassi",
"Carbohydrates": "Carboidrati",
"Calories": "Calorie",
"Energy": "",
"Energy": "Energia",
"Nutrition": "Nutrienti",
"Date": "Data",
"Share": "Condividi",
@@ -125,7 +125,7 @@
"Disable_Amount": "Disabilita Quantità",
"Key_Ctrl": "Ctrl",
"No_Results": "Nessun risultato",
"Create_New_Shopping Category": "Crea nuova categoria di spesa",
"Create_New_Shopping Category": "Crea nuova categoria della spesa",
"Create_New_Keyword": "Aggiungi nuova parola chiave",
"and_up": "& Su",
"step_time_minutes": "Tempo dello step in minuti",
@@ -149,7 +149,7 @@
"Create_New_Unit": "Aggiungi nuova unità",
"Instructions": "Istruzioni",
"Time": "Tempo",
"Shopping_Category": "Categoria di spesa",
"Shopping_Category": "Categoria Spesa",
"Meal_Plan_Days": "Piani alimentari futuri",
"tree_root": "Radice dell'albero",
"Automation": "Automazione",
@@ -202,5 +202,11 @@
"Next_Day": "Giorno successivo",
"Previous_Day": "Giorno precedente",
"Add_nutrition_recipe": "Aggiungi nutrienti alla ricetta",
"Remove_nutrition_recipe": "Elimina nutrienti dalla ricetta"
"Remove_nutrition_recipe": "Elimina nutrienti dalla ricetta",
"Coming_Soon": "In-Arrivo",
"Auto_Planner": "Pianificazione automatica",
"New_Cookbook": "Nuovo libro di ricette",
"Hide_Keyword": "Nascondi parole chiave",
"Clear": "Pulisci",
"Shopping_List_Empty": "La tua lista della spesa è vuota, puoi aggiungere elementi dal menù contestuale di una voce nel piano alimentare (clicca con il tasto destro sulla scheda o clicca con il tasto sinistro sull'icona del menù)"
}

View File

@@ -17,7 +17,7 @@
"Fats": "Vetten",
"Carbohydrates": "Koolhydraten",
"Calories": "Calorieën",
"Energy": "",
"Energy": "Energie",
"Nutrition": "Voedingswaarde",
"Date": "Datum",
"Share": "Deel",
@@ -112,8 +112,8 @@
"Step_Type": "Stap Type",
"Make_Header": "Maak_Koptekst",
"Make_Ingredient": "Maak_Ingrediënt",
"Enable_Amount": "Schakel Hoeveelheid in",
"Disable_Amount": "Schakel Hoeveelheid uit",
"Enable_Amount": "Schakel hoeveelheid in",
"Disable_Amount": "Schakel hoeveelheid uit",
"Add_Step": "Voeg Stap toe",
"Note": "Notitie",
"delete_confirmation": "Weet je zeker dat je {source} wil verwijderen?",
@@ -171,7 +171,7 @@
"Title": "Titel",
"Week": "Week",
"Month": "Maand",
"Make_header": "Maak_Koptekst",
"Make_header": "Maak dit de koptekst",
"Color": "Kleur",
"New_Meal_Type": "Nieuw Maaltype",
"Image": "Afbeelding",
@@ -204,5 +204,10 @@
"Previous_Day": "Vorige dag",
"Cannot_Add_Notes_To_Shopping": "Notities kunnen niet aan de boodschappenlijst toegevoegd worden",
"Remove_nutrition_recipe": "Verwijder voedingswaarde van recept",
"Add_nutrition_recipe": "Voeg voedingswaarde toe aan recept"
"Add_nutrition_recipe": "Voeg voedingswaarde toe aan recept",
"Coming_Soon": "Binnenkort beschikbaar",
"Auto_Planner": "Autoplanner",
"New_Cookbook": "Nieuw kookboek",
"Hide_Keyword": "Verberg etiketten",
"Clear": "Maak leeg"
}

210
vue/src/locales/ro.json Normal file
View File

@@ -0,0 +1,210 @@
{
"warning_feature_beta": "Momentan această funcționalitate este în fază de testare (BETA). Vă rugăm să vă așteptați la erori și, eventual, modificări de întrerupere în viitor atunci când utilizați această caracteristică (cu posibila pierdere a datelor legate de funcționalitate).",
"err_fetching_resource": "A apărut o eroare la apelarea unei resurse!",
"err_creating_resource": "A apărut o eroare la crearea unei resurse!",
"err_updating_resource": "A apărut o eroare la actualizarea unei resurse!",
"err_deleting_resource": "A apărut o eroare la ștergerea unei resurse!",
"success_fetching_resource": "Apelare cu succes a unei resurse!",
"success_creating_resource": "Creare cu succes a unei resurse!",
"success_updating_resource": "Actualizare cu succes a unei resurse!",
"success_deleting_resource": "Ștergere cu succes a unei resurse!",
"file_upload_disabled": "Încărcarea fișierelor nu este activată pentru spațiul dvs.",
"step_time_minutes": "Timpul pasului în minute",
"confirm_delete": "Sunteți sigur că vreți să ștergeți acest {object}?",
"import_running": "Import în desfășurare, așteptați!",
"all_fields_optional": "Toate câmpurile sunt opționale și pot fi lăsate necompletate.",
"convert_internal": "Transformați în rețetă internă",
"show_only_internal": "Arătați doar rețetele interne",
"show_split_screen": "Vedere divizată",
"Log_Recipe_Cooking": "",
"External_Recipe_Image": "",
"Add_to_Shopping": "",
"Add_to_Plan": "",
"Step_start_time": "",
"Sort_by_new": "",
"Table_of_Contents": "",
"Recipes_per_page": "",
"Show_as_header": "",
"Hide_as_header": "",
"Add_nutrition_recipe": "",
"Remove_nutrition_recipe": "",
"Copy_template_reference": "",
"Save_and_View": "",
"Manage_Books": "",
"Meal_Plan": "",
"Select_Book": "",
"Select_File": "",
"Recipe_Image": "",
"Import_finished": "",
"View_Recipes": "",
"Log_Cooking": "",
"New_Recipe": "",
"Url_Import": "",
"Reset_Search": "",
"Recently_Viewed": "",
"Load_More": "",
"New_Keyword": "",
"Delete_Keyword": "",
"Edit_Keyword": "",
"Edit_Recipe": "",
"Move_Keyword": "",
"Merge_Keyword": "",
"Hide_Keywords": "",
"Hide_Recipes": "",
"Move_Up": "",
"Move_Down": "",
"Step_Name": "",
"Step_Type": "",
"Make_header": "",
"Make_Ingredient": "",
"Enable_Amount": "",
"Disable_Amount": "",
"Add_Step": "",
"Keywords": "",
"Books": "",
"Proteins": "",
"Fats": "",
"Carbohydrates": "",
"Calories": "",
"Energy": "",
"Nutrition": "",
"Date": "",
"Share": "",
"Automation": "",
"Parameter": "",
"Export": "",
"Copy": "",
"Rating": "",
"Close": "",
"Cancel": "",
"Link": "",
"Add": "",
"New": "",
"Note": "",
"Success": "",
"Failure": "",
"Ingredients": "",
"Supermarket": "",
"Categories": "",
"Category": "",
"Selected": "",
"min": "",
"Servings": "",
"Waiting": "",
"Preparation": "",
"External": "",
"Size": "",
"Files": "",
"File": "",
"Edit": "",
"Image": "",
"Delete": "",
"Open": "",
"Ok": "",
"Save": "",
"Step": "",
"Search": "",
"Import": "",
"Print": "",
"Settings": "",
"or": "",
"and": "",
"Information": "",
"Download": "",
"Create": "",
"Advanced Search Settings": "",
"View": "",
"Recipes": "",
"Move": "",
"Merge": "",
"Parent": "",
"delete_confirmation": "",
"move_confirmation": "",
"merge_confirmation": "",
"create_rule": "",
"move_selection": "",
"merge_selection": "",
"Root": "",
"Ignore_Shopping": "",
"Shopping_Category": "",
"Edit_Food": "",
"Move_Food": "",
"New_Food": "",
"Hide_Food": "",
"Food_Alias": "",
"Unit_Alias": "",
"Keyword_Alias": "",
"Delete_Food": "",
"No_ID": "",
"Meal_Plan_Days": "",
"merge_title": "",
"move_title": "",
"Food": "",
"Recipe_Book": "",
"del_confirmation_tree": "",
"delete_title": "",
"create_title": "",
"edit_title": "",
"Name": "",
"Type": "",
"Description": "",
"Recipe": "",
"tree_root": "",
"Icon": "",
"Unit": "",
"No_Results": "",
"New_Unit": "",
"Create_New_Shopping Category": "",
"Create_New_Food": "",
"Create_New_Keyword": "",
"Create_New_Unit": "",
"Create_New_Meal_Type": "",
"and_up": "",
"Instructions": "",
"Unrated": "",
"Automate": "",
"Empty": "",
"Key_Ctrl": "",
"Key_Shift": "",
"Time": "",
"Text": "",
"Shopping_list": "",
"Create_Meal_Plan_Entry": "",
"Edit_Meal_Plan_Entry": "",
"Title": "",
"Week": "",
"Month": "",
"Year": "",
"Planner": "",
"Planner_Settings": "",
"Period": "",
"Plan_Period_To_Show": "",
"Periods": "",
"Plan_Show_How_Many_Periods": "",
"Starting_Day": "",
"Meal_Types": "",
"Meal_Type": "",
"Clone": "",
"Drag_Here_To_Delete": "",
"Meal_Type_Required": "",
"Title_or_Recipe_Required": "",
"Color": "",
"New_Meal_Type": "",
"Week_Numbers": "",
"Show_Week_Numbers": "",
"Export_As_ICal": "",
"Export_To_ICal": "",
"Cannot_Add_Notes_To_Shopping": "",
"Added_To_Shopping_List": "",
"Shopping_List_Empty": "",
"Next_Period": "",
"Previous_Period": "",
"Current_Period": "",
"Next_Day": "",
"Previous_Day": "",
"Coming_Soon": "",
"Auto_Planner": "",
"New_Cookbook": "",
"Hide_Keyword": "",
"Clear": ""
}

210
vue/src/locales/sl.json Normal file
View File

@@ -0,0 +1,210 @@
{
"warning_feature_beta": "Ta funkcija je trenutno v stanju BETA (testiranje). Pri uporabi te funkcije pričakujte napake in morebitne prelomne spremembe v prihodnosti (morda izgubite podatke, povezane s to funkcijo).",
"err_fetching_resource": "",
"err_creating_resource": "",
"err_updating_resource": "",
"err_deleting_resource": "",
"success_fetching_resource": "",
"success_creating_resource": "",
"success_updating_resource": "",
"success_deleting_resource": "",
"file_upload_disabled": "",
"step_time_minutes": "",
"confirm_delete": "",
"import_running": "",
"all_fields_optional": "",
"convert_internal": "",
"show_only_internal": "",
"show_split_screen": "",
"Log_Recipe_Cooking": "",
"External_Recipe_Image": "",
"Add_to_Shopping": "",
"Add_to_Plan": "",
"Step_start_time": "",
"Sort_by_new": "",
"Table_of_Contents": "",
"Recipes_per_page": "",
"Show_as_header": "",
"Hide_as_header": "",
"Add_nutrition_recipe": "",
"Remove_nutrition_recipe": "",
"Copy_template_reference": "",
"Save_and_View": "",
"Manage_Books": "",
"Meal_Plan": "",
"Select_Book": "",
"Select_File": "",
"Recipe_Image": "",
"Import_finished": "",
"View_Recipes": "",
"Log_Cooking": "",
"New_Recipe": "Nov Recept",
"Url_Import": "",
"Reset_Search": "",
"Recently_Viewed": "",
"Load_More": "",
"New_Keyword": "",
"Delete_Keyword": "",
"Edit_Keyword": "",
"Edit_Recipe": "Uredi Recept",
"Move_Keyword": "",
"Merge_Keyword": "",
"Hide_Keywords": "",
"Hide_Recipes": "",
"Move_Up": "",
"Move_Down": "",
"Step_Name": "",
"Step_Type": "",
"Make_header": "",
"Make_Ingredient": "",
"Enable_Amount": "",
"Disable_Amount": "",
"Add_Step": "",
"Keywords": "",
"Books": "Knjige",
"Proteins": "",
"Fats": "",
"Carbohydrates": "",
"Calories": "",
"Energy": "",
"Nutrition": "",
"Date": "Datum",
"Share": "Deli",
"Automation": "",
"Parameter": "",
"Export": "",
"Copy": "",
"Rating": "",
"Close": "",
"Cancel": "",
"Link": "",
"Add": "",
"New": "",
"Note": "",
"Success": "",
"Failure": "",
"Ingredients": "",
"Supermarket": "",
"Categories": "",
"Category": "",
"Selected": "",
"min": "",
"Servings": "",
"Waiting": "",
"Preparation": "",
"External": "",
"Size": "",
"Files": "",
"File": "",
"Edit": "",
"Image": "",
"Delete": "Izbriši",
"Open": "Odpri",
"Ok": "Odpri",
"Save": "Shrani",
"Step": "",
"Search": "Iskanje",
"Import": "Uvozi",
"Print": "Natisni",
"Settings": "",
"or": "",
"and": "",
"Information": "",
"Download": "Prenesi",
"Create": "",
"Advanced Search Settings": "",
"View": "",
"Recipes": "Recepti",
"Move": "",
"Merge": "",
"Parent": "",
"delete_confirmation": "",
"move_confirmation": "",
"merge_confirmation": "",
"create_rule": "",
"move_selection": "",
"merge_selection": "",
"Root": "",
"Ignore_Shopping": "",
"Shopping_Category": "",
"Edit_Food": "",
"Move_Food": "",
"New_Food": "",
"Hide_Food": "",
"Food_Alias": "",
"Unit_Alias": "",
"Keyword_Alias": "",
"Delete_Food": "",
"No_ID": "",
"Meal_Plan_Days": "",
"merge_title": "",
"move_title": "",
"Food": "Hrana",
"Recipe_Book": "",
"del_confirmation_tree": "",
"delete_title": "",
"create_title": "",
"edit_title": "",
"Name": "",
"Type": "",
"Description": "",
"Recipe": "",
"tree_root": "",
"Icon": "",
"Unit": "",
"No_Results": "",
"New_Unit": "",
"Create_New_Shopping Category": "",
"Create_New_Food": "Dodaj Novo Hrano",
"Create_New_Keyword": "",
"Create_New_Unit": "",
"Create_New_Meal_Type": "",
"and_up": "",
"Instructions": "",
"Unrated": "",
"Automate": "",
"Empty": "",
"Key_Ctrl": "",
"Key_Shift": "",
"Time": "",
"Text": "",
"Shopping_list": "Nakupovalni Seznam",
"Create_Meal_Plan_Entry": "",
"Edit_Meal_Plan_Entry": "",
"Title": "",
"Week": "Teden",
"Month": "Mesec",
"Year": "Leto",
"Planner": "",
"Planner_Settings": "",
"Period": "",
"Plan_Period_To_Show": "",
"Periods": "",
"Plan_Show_How_Many_Periods": "",
"Starting_Day": "",
"Meal_Types": "",
"Meal_Type": "",
"Clone": "",
"Drag_Here_To_Delete": "",
"Meal_Type_Required": "",
"Title_or_Recipe_Required": "",
"Color": "Barva",
"New_Meal_Type": "",
"Week_Numbers": "",
"Show_Week_Numbers": "",
"Export_As_ICal": "",
"Export_To_ICal": "",
"Cannot_Add_Notes_To_Shopping": "",
"Added_To_Shopping_List": "",
"Shopping_List_Empty": "",
"Next_Period": "",
"Previous_Period": "",
"Current_Period": "",
"Next_Day": "Naslednji Dan",
"Previous_Day": "Prejšnji Dan",
"Coming_Soon": "",
"Auto_Planner": "",
"New_Cookbook": "",
"Hide_Keyword": "",
"Clear": ""
}

View File

@@ -371,14 +371,25 @@ export class Models {
'name': i18n.t('Recipe'),
'apiName': 'Recipe',
'list': {
'params': ['query', 'keywords', 'foods', 'units', 'rating', 'books', 'keywordsOr', 'foodsOr', 'booksOr', 'internal', 'random', '_new', 'page', 'pageSize', 'options'],
'params': ['query', 'keywords', 'foods', 'units', 'rating', 'books', 'steps', 'keywordsOr', 'foodsOr', 'booksOr', 'internal', 'random', '_new', 'page', 'pageSize', 'options'],
'config': {
'foods': {'type': 'string'},
'keywords': {'type': 'string'},
'books': {'type': 'string'},
}
},
}
static STEP = {
'name': i18n.t('Step'),
'apiName': 'Step',
'paginated': true,
'list': {
'header_component': {
'name': 'BetaWarning'
},
'params': ['query', 'page', 'pageSize', 'options'],
},
}
static USER_NAME = {

View File

@@ -215,12 +215,6 @@ export interface Food {
* @memberof Food
*/
supermarket_category?: FoodSupermarketCategory | null;
/**
*
* @type {string}
* @memberof Food
*/
image?: string;
/**
*
* @type {string}
@@ -233,12 +227,6 @@ export interface Food {
* @memberof Food
*/
numchild?: number;
/**
*
* @type {string}
* @memberof Food
*/
numrecipe?: string;
}
/**
*
@@ -387,12 +375,6 @@ export interface ImportLogKeyword {
* @memberof ImportLogKeyword
*/
description?: string;
/**
*
* @type {string}
* @memberof ImportLogKeyword
*/
image?: string;
/**
*
* @type {string}
@@ -405,12 +387,6 @@ export interface ImportLogKeyword {
* @memberof ImportLogKeyword
*/
numchild?: number;
/**
*
* @type {string}
* @memberof ImportLogKeyword
*/
numrecipe?: string;
/**
*
* @type {string}
@@ -444,10 +420,10 @@ export interface Ingredient {
food: StepFood | null;
/**
*
* @type {StepUnit}
* @type {FoodSupermarketCategory}
* @memberof Ingredient
*/
unit: StepUnit | null;
unit: FoodSupermarketCategory | null;
/**
*
* @type {string}
@@ -629,10 +605,10 @@ export interface InlineResponse2004 {
previous?: string | null;
/**
*
* @type {Array<RecipeOverview>}
* @type {Array<Step>}
* @memberof InlineResponse2004
*/
results?: Array<RecipeOverview>;
results?: Array<Step>;
}
/**
*
@@ -660,10 +636,10 @@ export interface InlineResponse2005 {
previous?: string | null;
/**
*
* @type {Array<ViewLog>}
* @type {Array<RecipeOverview>}
* @memberof InlineResponse2005
*/
results?: Array<ViewLog>;
results?: Array<RecipeOverview>;
}
/**
*
@@ -691,10 +667,10 @@ export interface InlineResponse2006 {
previous?: string | null;
/**
*
* @type {Array<CookLog>}
* @type {Array<ViewLog>}
* @memberof InlineResponse2006
*/
results?: Array<CookLog>;
results?: Array<ViewLog>;
}
/**
*
@@ -722,10 +698,10 @@ export interface InlineResponse2007 {
previous?: string | null;
/**
*
* @type {Array<SupermarketCategoryRelation>}
* @type {Array<CookLog>}
* @memberof InlineResponse2007
*/
results?: Array<SupermarketCategoryRelation>;
results?: Array<CookLog>;
}
/**
*
@@ -753,9 +729,40 @@ export interface InlineResponse2008 {
previous?: string | null;
/**
*
* @type {Array<ImportLog>}
* @type {Array<SupermarketCategoryRelation>}
* @memberof InlineResponse2008
*/
results?: Array<SupermarketCategoryRelation>;
}
/**
*
* @export
* @interface InlineResponse2009
*/
export interface InlineResponse2009 {
/**
*
* @type {number}
* @memberof InlineResponse2009
*/
count?: number;
/**
*
* @type {string}
* @memberof InlineResponse2009
*/
next?: string | null;
/**
*
* @type {string}
* @memberof InlineResponse2009
*/
previous?: string | null;
/**
*
* @type {Array<ImportLog>}
* @memberof InlineResponse2009
*/
results?: Array<ImportLog>;
}
/**
@@ -794,12 +801,6 @@ export interface Keyword {
* @memberof Keyword
*/
description?: string;
/**
*
* @type {string}
* @memberof Keyword
*/
image?: string;
/**
*
* @type {string}
@@ -812,12 +813,6 @@ export interface Keyword {
* @memberof Keyword
*/
numchild?: number;
/**
*
* @type {string}
* @memberof Keyword
*/
numrecipe?: string;
/**
*
* @type {string}
@@ -881,10 +876,10 @@ export interface MealPlan {
date: string;
/**
*
* @type {number}
* @type {MealPlanMealType}
* @memberof MealPlan
*/
meal_type: number;
meal_type: MealPlanMealType;
/**
*
* @type {string}
@@ -910,6 +905,55 @@ export interface MealPlan {
*/
meal_type_name?: string;
}
/**
*
* @export
* @interface MealPlanMealType
*/
export interface MealPlanMealType {
/**
*
* @type {number}
* @memberof MealPlanMealType
*/
id?: number;
/**
*
* @type {string}
* @memberof MealPlanMealType
*/
name: string;
/**
*
* @type {number}
* @memberof MealPlanMealType
*/
order?: number;
/**
*
* @type {string}
* @memberof MealPlanMealType
*/
icon?: string | null;
/**
*
* @type {string}
* @memberof MealPlanMealType
*/
color?: string | null;
/**
*
* @type {boolean}
* @memberof MealPlanMealType
*/
_default?: boolean;
/**
*
* @type {string}
* @memberof MealPlanMealType
*/
created_by?: string;
}
/**
*
* @export
@@ -1037,6 +1081,24 @@ export interface MealType {
* @memberof MealType
*/
order?: number;
/**
*
* @type {string}
* @memberof MealType
*/
icon?: string | null;
/**
*
* @type {string}
* @memberof MealType
*/
color?: string | null;
/**
*
* @type {boolean}
* @memberof MealType
*/
_default?: boolean;
/**
*
* @type {string}
@@ -1288,12 +1350,6 @@ export interface RecipeKeywords {
* @memberof RecipeKeywords
*/
description?: string;
/**
*
* @type {string}
* @memberof RecipeKeywords
*/
image?: string;
/**
*
* @type {string}
@@ -1306,12 +1362,6 @@ export interface RecipeKeywords {
* @memberof RecipeKeywords
*/
numchild?: number;
/**
*
* @type {string}
* @memberof RecipeKeywords
*/
numrecipe?: string;
/**
*
* @type {string}
@@ -1574,6 +1624,12 @@ export interface RecipeSteps {
* @memberof RecipeSteps
*/
step_recipe_data?: string;
/**
*
* @type {string}
* @memberof RecipeSteps
*/
numrecipe?: string;
}
/**
@@ -1680,10 +1736,10 @@ export interface ShoppingListEntries {
food: StepFood | null;
/**
*
* @type {StepUnit}
* @type {FoodSupermarketCategory}
* @memberof ShoppingListEntries
*/
unit?: StepUnit | null;
unit?: FoodSupermarketCategory | null;
/**
*
* @type {string}
@@ -1729,10 +1785,10 @@ export interface ShoppingListEntry {
food: StepFood | null;
/**
*
* @type {StepUnit}
* @type {FoodSupermarketCategory}
* @memberof ShoppingListEntry
*/
unit?: StepUnit | null;
unit?: FoodSupermarketCategory | null;
/**
*
* @type {string}
@@ -2004,6 +2060,12 @@ export interface Step {
* @memberof Step
*/
step_recipe_data?: string;
/**
*
* @type {string}
* @memberof Step
*/
numrecipe?: string;
}
/**
@@ -2084,12 +2146,6 @@ export interface StepFood {
* @memberof StepFood
*/
supermarket_category?: FoodSupermarketCategory | null;
/**
*
* @type {string}
* @memberof StepFood
*/
image?: string;
/**
*
* @type {string}
@@ -2102,12 +2158,6 @@ export interface StepFood {
* @memberof StepFood
*/
numchild?: number;
/**
*
* @type {string}
* @memberof StepFood
*/
numrecipe?: string;
}
/**
*
@@ -2129,10 +2179,10 @@ export interface StepIngredients {
food: StepFood | null;
/**
*
* @type {StepUnit}
* @type {FoodSupermarketCategory}
* @memberof StepIngredients
*/
unit: StepUnit | null;
unit: FoodSupermarketCategory | null;
/**
*
* @type {string}
@@ -2164,43 +2214,6 @@ export interface StepIngredients {
*/
no_amount?: boolean;
}
/**
*
* @export
* @interface StepUnit
*/
export interface StepUnit {
/**
*
* @type {number}
* @memberof StepUnit
*/
id?: number;
/**
*
* @type {string}
* @memberof StepUnit
*/
name: string;
/**
*
* @type {string}
* @memberof StepUnit
*/
description?: string | null;
/**
*
* @type {string}
* @memberof StepUnit
*/
numrecipe?: string;
/**
*
* @type {string}
* @memberof StepUnit
*/
image?: string;
}
/**
*
* @export
@@ -2458,18 +2471,6 @@ export interface Unit {
* @memberof Unit
*/
description?: string | null;
/**
*
* @type {string}
* @memberof Unit
*/
numrecipe?: string;
/**
*
* @type {string}
* @memberof Unit
*/
image?: string;
}
/**
*
@@ -4782,6 +4783,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
* @param {number} [units] Id of unit a recipe should have.
* @param {number} [rating] Id of unit a recipe should have.
* @param {string} [books] Id of book a recipe should have. For multiple repeat parameter.
* @param {string} [steps] Id of a step a recipe should have. For multiple repeat parameter.
* @param {string} [keywordsOr] If recipe should have all (AND) or any (OR) of the provided keywords.
* @param {string} [foodsOr] If recipe should have all (AND) or any (OR) any of the provided foods.
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
@@ -4793,7 +4795,7 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listRecipes: async (query?: string, keywords?: string, foods?: string, units?: number, rating?: number, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
listRecipes: async (query?: string, keywords?: string, foods?: string, units?: number, rating?: number, books?: string, steps?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
const localVarPath = `/api/recipe/`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@@ -4830,6 +4832,10 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
localVarQueryParameter['books'] = books;
}
if (steps !== undefined) {
localVarQueryParameter['steps'] = steps;
}
if (keywordsOr !== undefined) {
localVarQueryParameter['keywords_or'] = keywordsOr;
}
@@ -4962,10 +4968,13 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
},
/**
*
* @param {string} [query] Query string matched (fuzzy) against object name.
* @param {number} [page] A page number within the paginated result set.
* @param {number} [pageSize] Number of results to return per page.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listSteps: async (options: any = {}): Promise<RequestArgs> => {
listSteps: async (query?: string, page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
const localVarPath = `/api/step/`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@@ -4978,6 +4987,18 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
if (query !== undefined) {
localVarQueryParameter['query'] = query;
}
if (page !== undefined) {
localVarQueryParameter['page'] = page;
}
if (pageSize !== undefined) {
localVarQueryParameter['page_size'] = pageSize;
}
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
@@ -8892,7 +8913,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listCookLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2006>> {
async listCookLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2007>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listCookLogs(page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
@@ -8917,7 +8938,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listImportLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2008>> {
async listImportLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2009>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listImportLogs(page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
@@ -8988,6 +9009,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {number} [units] Id of unit a recipe should have.
* @param {number} [rating] Id of unit a recipe should have.
* @param {string} [books] Id of book a recipe should have. For multiple repeat parameter.
* @param {string} [steps] Id of a step a recipe should have. For multiple repeat parameter.
* @param {string} [keywordsOr] If recipe should have all (AND) or any (OR) of the provided keywords.
* @param {string} [foodsOr] If recipe should have all (AND) or any (OR) any of the provided foods.
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
@@ -8999,8 +9021,8 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listRecipes(query?: string, keywords?: string, foods?: string, units?: number, rating?: number, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2004>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(query, keywords, foods, units, rating, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options);
async listRecipes(query?: string, keywords?: string, foods?: string, units?: number, rating?: number, books?: string, steps?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2005>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(query, keywords, foods, units, rating, books, steps, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@@ -9032,11 +9054,14 @@ export const ApiApiFp = function(configuration?: Configuration) {
},
/**
*
* @param {string} [query] Query string matched (fuzzy) against object name.
* @param {number} [page] A page number within the paginated result set.
* @param {number} [pageSize] Number of results to return per page.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listSteps(options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<Step>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listSteps(options);
async listSteps(query?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2004>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listSteps(query, page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@@ -9055,7 +9080,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listSupermarketCategoryRelations(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2007>> {
async listSupermarketCategoryRelations(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2008>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listSupermarketCategoryRelations(page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
@@ -9143,7 +9168,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listViewLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2005>> {
async listViewLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2006>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listViewLogs(page, pageSize, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
@@ -10529,7 +10554,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listCookLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2006> {
listCookLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2007> {
return localVarFp.listCookLogs(page, pageSize, options).then((request) => request(axios, basePath));
},
/**
@@ -10552,7 +10577,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listImportLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2008> {
listImportLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2009> {
return localVarFp.listImportLogs(page, pageSize, options).then((request) => request(axios, basePath));
},
/**
@@ -10616,6 +10641,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {number} [units] Id of unit a recipe should have.
* @param {number} [rating] Id of unit a recipe should have.
* @param {string} [books] Id of book a recipe should have. For multiple repeat parameter.
* @param {string} [steps] Id of a step a recipe should have. For multiple repeat parameter.
* @param {string} [keywordsOr] If recipe should have all (AND) or any (OR) of the provided keywords.
* @param {string} [foodsOr] If recipe should have all (AND) or any (OR) any of the provided foods.
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
@@ -10627,8 +10653,8 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listRecipes(query?: string, keywords?: string, foods?: string, units?: number, rating?: number, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2004> {
return localVarFp.listRecipes(query, keywords, foods, units, rating, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(axios, basePath));
listRecipes(query?: string, keywords?: string, foods?: string, units?: number, rating?: number, books?: string, steps?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2005> {
return localVarFp.listRecipes(query, keywords, foods, units, rating, books, steps, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(axios, basePath));
},
/**
*
@@ -10656,11 +10682,14 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
},
/**
*
* @param {string} [query] Query string matched (fuzzy) against object name.
* @param {number} [page] A page number within the paginated result set.
* @param {number} [pageSize] Number of results to return per page.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listSteps(options?: any): AxiosPromise<Array<Step>> {
return localVarFp.listSteps(options).then((request) => request(axios, basePath));
listSteps(query?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2004> {
return localVarFp.listSteps(query, page, pageSize, options).then((request) => request(axios, basePath));
},
/**
*
@@ -10677,7 +10706,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listSupermarketCategoryRelations(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2007> {
listSupermarketCategoryRelations(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2008> {
return localVarFp.listSupermarketCategoryRelations(page, pageSize, options).then((request) => request(axios, basePath));
},
/**
@@ -10756,7 +10785,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listViewLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2005> {
listViewLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2006> {
return localVarFp.listViewLogs(page, pageSize, options).then((request) => request(axios, basePath));
},
/**
@@ -12270,6 +12299,7 @@ export class ApiApi extends BaseAPI {
* @param {number} [units] Id of unit a recipe should have.
* @param {number} [rating] Id of unit a recipe should have.
* @param {string} [books] Id of book a recipe should have. For multiple repeat parameter.
* @param {string} [steps] Id of a step a recipe should have. For multiple repeat parameter.
* @param {string} [keywordsOr] If recipe should have all (AND) or any (OR) of the provided keywords.
* @param {string} [foodsOr] If recipe should have all (AND) or any (OR) any of the provided foods.
* @param {string} [booksOr] If recipe should be in all (AND) or any (OR) any of the provided books.
@@ -12282,8 +12312,8 @@ export class ApiApi extends BaseAPI {
* @throws {RequiredError}
* @memberof ApiApi
*/
public listRecipes(query?: string, keywords?: string, foods?: string, units?: number, rating?: number, books?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listRecipes(query, keywords, foods, units, rating, books, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(this.axios, this.basePath));
public listRecipes(query?: string, keywords?: string, foods?: string, units?: number, rating?: number, books?: string, steps?: string, keywordsOr?: string, foodsOr?: string, booksOr?: string, internal?: string, random?: string, _new?: string, page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listRecipes(query, keywords, foods, units, rating, books, steps, keywordsOr, foodsOr, booksOr, internal, random, _new, page, pageSize, options).then((request) => request(this.axios, this.basePath));
}
/**
@@ -12318,12 +12348,15 @@ export class ApiApi extends BaseAPI {
/**
*
* @param {string} [query] Query string matched (fuzzy) against object name.
* @param {number} [page] A page number within the paginated result set.
* @param {number} [pageSize] Number of results to return per page.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiApi
*/
public listSteps(options?: any) {
return ApiApiFp(this.configuration).listSteps(options).then((request) => request(this.axios, this.basePath));
public listSteps(query?: string, page?: number, pageSize?: number, options?: any) {
return ApiApiFp(this.configuration).listSteps(query, page, pageSize, options).then((request) => request(this.axios, this.basePath));
}
/**