Merge branch 'develop' into feature/custom_filters
# Conflicts: # cookbook/serializer.py # cookbook/views/api.py # vue/src/utils/openapi/api.ts
This commit is contained in:
@ -151,3 +151,7 @@ REVERSE_PROXY_AUTH=0
|
||||
# Enables exporting PDF (see export docs)
|
||||
# Disabled by default, uncomment to enable
|
||||
# ENABLE_PDF_EXPORT=1
|
||||
|
||||
# Recipe exports are cached for a certain time by default, adjust time if needed
|
||||
# EXPORT_FILE_CACHE_DURATION=600
|
||||
|
||||
|
@ -32,11 +32,12 @@ class Default(Integration):
|
||||
return None
|
||||
|
||||
def get_file_from_recipe(self, recipe):
|
||||
|
||||
export = RecipeExportSerializer(recipe).data
|
||||
|
||||
return 'recipe.json', JSONRenderer().render(export).decode("utf-8")
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
export_zip_stream = BytesIO()
|
||||
export_zip_obj = ZipFile(export_zip_stream, 'w')
|
||||
|
||||
@ -50,13 +51,20 @@ class Default(Integration):
|
||||
recipe_stream.write(data)
|
||||
recipe_zip_obj.writestr(filename, recipe_stream.getvalue())
|
||||
recipe_stream.close()
|
||||
|
||||
try:
|
||||
recipe_zip_obj.writestr(f'image{get_filetype(r.image.file.name)}', r.image.file.read())
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
recipe_zip_obj.close()
|
||||
|
||||
export_zip_obj.writestr(str(r.pk) + '.zip', recipe_zip_stream.getvalue())
|
||||
|
||||
el.exported_recipes += 1
|
||||
el.msg += self.get_recipe_processed_msg(r)
|
||||
el.save()
|
||||
|
||||
export_zip_obj.close()
|
||||
|
||||
return [[ 'export.zip', export_zip_stream.getvalue() ]]
|
||||
return [[ self.get_export_file_name(), export_zip_stream.getvalue() ]]
|
@ -1,9 +1,12 @@
|
||||
import time
|
||||
import datetime
|
||||
import json
|
||||
import traceback
|
||||
import uuid
|
||||
from io import BytesIO, StringIO
|
||||
from zipfile import BadZipFile, ZipFile
|
||||
from django.core.cache import cache
|
||||
import datetime
|
||||
|
||||
from bs4 import Tag
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
@ -18,6 +21,7 @@ from cookbook.forms import ImportExportBase
|
||||
from cookbook.helper.image_processing import get_filetype, handle_image
|
||||
from cookbook.models import Keyword, Recipe
|
||||
from recipes.settings import DEBUG
|
||||
from recipes.settings import EXPORT_FILE_CACHE_DURATION
|
||||
|
||||
|
||||
class Integration:
|
||||
@ -61,14 +65,16 @@ class Integration:
|
||||
space=request.space
|
||||
)
|
||||
|
||||
def do_export(self, recipes):
|
||||
"""
|
||||
Perform the export based on a list of recipes
|
||||
:param recipes: list of recipe objects
|
||||
:return: HttpResponse with the file of the requested export format that is directly downloaded (When that format involve multiple files they are zipped together)
|
||||
"""
|
||||
|
||||
files = self.get_files_from_recipes(recipes, self.request.COOKIES)
|
||||
|
||||
def do_export(self, recipes, el):
|
||||
|
||||
with scope(space=self.request.space):
|
||||
el.total_recipes = len(recipes)
|
||||
el.cache_duration = EXPORT_FILE_CACHE_DURATION
|
||||
el.save()
|
||||
|
||||
files = self.get_files_from_recipes(recipes, el, self.request.COOKIES)
|
||||
|
||||
if len(files) == 1:
|
||||
filename, file = files[0]
|
||||
@ -76,7 +82,8 @@ class Integration:
|
||||
export_file = file
|
||||
|
||||
else:
|
||||
export_filename = "export.zip"
|
||||
#zip the files if there is more then one file
|
||||
export_filename = self.get_export_file_name()
|
||||
export_stream = BytesIO()
|
||||
export_obj = ZipFile(export_stream, 'w')
|
||||
|
||||
@ -86,10 +93,16 @@ class Integration:
|
||||
export_obj.close()
|
||||
export_file = export_stream.getvalue()
|
||||
|
||||
|
||||
cache.set('export_file_'+str(el.pk), {'filename': export_filename, 'file': export_file}, EXPORT_FILE_CACHE_DURATION)
|
||||
el.running = False
|
||||
el.save()
|
||||
|
||||
response = HttpResponse(export_file, content_type='application/force-download')
|
||||
response['Content-Disposition'] = 'attachment; filename="' + export_filename + '"'
|
||||
return response
|
||||
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
"""
|
||||
Since zipfile.namelist() returns all files in all subdirectories this function allows filtering of files
|
||||
@ -126,7 +139,7 @@ class Integration:
|
||||
for d in data_list:
|
||||
recipe = self.get_recipe_from_file(d)
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
il.imported_recipes += 1
|
||||
il.save()
|
||||
@ -151,7 +164,7 @@ class Integration:
|
||||
else:
|
||||
recipe = self.get_recipe_from_file(BytesIO(import_zip.read(z.filename)))
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
il.imported_recipes += 1
|
||||
il.save()
|
||||
@ -166,7 +179,7 @@ class Integration:
|
||||
try:
|
||||
recipe = self.get_recipe_from_file(d)
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
il.imported_recipes += 1
|
||||
il.save()
|
||||
@ -183,7 +196,7 @@ class Integration:
|
||||
try:
|
||||
recipe = self.get_recipe_from_file(d)
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
il.imported_recipes += 1
|
||||
il.save()
|
||||
@ -193,7 +206,7 @@ class Integration:
|
||||
else:
|
||||
recipe = self.get_recipe_from_file(f['file'])
|
||||
recipe.keywords.add(self.keyword)
|
||||
il.msg += f'{recipe.pk} - {recipe.name} \n'
|
||||
il.msg += self.get_recipe_processed_msg(recipe)
|
||||
self.handle_duplicates(recipe, import_duplicates)
|
||||
except BadZipFile:
|
||||
il.msg += 'ERROR ' + _(
|
||||
@ -260,7 +273,7 @@ class Integration:
|
||||
"""
|
||||
raise NotImplementedError('Method not implemented in integration')
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
"""
|
||||
Takes a list of recipe object and converts it to a array containing each file.
|
||||
Each file is represented as an array [filename, data] where data is a string of the content of the file.
|
||||
@ -279,3 +292,10 @@ class Integration:
|
||||
log.msg += exception.msg
|
||||
if DEBUG:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def get_export_file_name(self, format='zip'):
|
||||
return "export_{}.{}".format(datetime.datetime.now().strftime("%Y-%m-%d"), format)
|
||||
|
||||
def get_recipe_processed_msg(self, recipe):
|
||||
return f'{recipe.pk} - {recipe.name} \n'
|
||||
|
@ -11,22 +11,25 @@ from cookbook.helper.image_processing import get_filetype
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.serializer import RecipeExportSerializer
|
||||
|
||||
import django.core.management.commands.runserver as runserver
|
||||
from cookbook.models import ExportLog
|
||||
from asgiref.sync import sync_to_async
|
||||
|
||||
import django.core.management.commands.runserver as runserver
|
||||
import logging
|
||||
|
||||
class PDFexport(Integration):
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
raise NotImplementedError('Method not implemented in storage integration')
|
||||
|
||||
async def get_files_from_recipes_async(self, recipes, cookie):
|
||||
async def get_files_from_recipes_async(self, recipes, el, cookie):
|
||||
cmd = runserver.Command()
|
||||
|
||||
browser = await launch(
|
||||
handleSIGINT=False,
|
||||
handleSIGTERM=False,
|
||||
handleSIGHUP=False,
|
||||
ignoreHTTPSErrors=True
|
||||
ignoreHTTPSErrors=True,
|
||||
)
|
||||
|
||||
cookies = {'domain': cmd.default_addr, 'name': 'sessionid', 'value': cookie['sessionid'], }
|
||||
@ -39,17 +42,28 @@ class PDFexport(Integration):
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
files = []
|
||||
for recipe in recipes:
|
||||
|
||||
page = await browser.newPage()
|
||||
await page.emulateMedia('print')
|
||||
await page.setCookie(cookies)
|
||||
|
||||
files = []
|
||||
for recipe in recipes:
|
||||
await page.goto('http://' + cmd.default_addr + ':' + cmd.default_port + '/view/recipe/' + str(recipe.id), {'waitUntil': 'networkidle0', })
|
||||
await page.goto('http://'+cmd.default_addr+':'+cmd.default_port+'/view/recipe/'+str(recipe.id), {'waitUntil': 'domcontentloaded'})
|
||||
await page.waitForSelector('#printReady');
|
||||
|
||||
files.append([recipe.name + '.pdf', await page.pdf(options)])
|
||||
await page.close();
|
||||
|
||||
el.exported_recipes += 1
|
||||
el.msg += self.get_recipe_processed_msg(recipe)
|
||||
await sync_to_async(el.save, thread_sensitive=True)()
|
||||
|
||||
|
||||
await browser.close()
|
||||
return files
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
return asyncio.run(self.get_files_from_recipes_async(recipes, cookie))
|
||||
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
return asyncio.run(self.get_files_from_recipes_async(recipes, el, cookie))
|
||||
|
@ -88,12 +88,16 @@ class RecipeSage(Integration):
|
||||
|
||||
return data
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
json_list = []
|
||||
for r in recipes:
|
||||
json_list.append(self.get_file_from_recipe(r))
|
||||
|
||||
return [['export.json', json.dumps(json_list)]]
|
||||
el.exported_recipes += 1
|
||||
el.msg += self.get_recipe_processed_msg(r)
|
||||
el.save()
|
||||
|
||||
return [[self.get_export_file_name('json'), json.dumps(json_list)]]
|
||||
|
||||
def split_recipe_file(self, file):
|
||||
return json.loads(file.read().decode("utf-8"))
|
||||
|
@ -87,10 +87,14 @@ class Saffron(Integration):
|
||||
|
||||
return recipe.name+'.txt', data
|
||||
|
||||
def get_files_from_recipes(self, recipes, cookie):
|
||||
def get_files_from_recipes(self, recipes, el, cookie):
|
||||
files = []
|
||||
for r in recipes:
|
||||
filename, data = self.get_file_from_recipe(r)
|
||||
files.append([ filename, data ])
|
||||
|
||||
el.exported_recipes += 1
|
||||
el.msg += self.get_recipe_processed_msg(r)
|
||||
el.save()
|
||||
|
||||
return files
|
Binary file not shown.
@ -15,8 +15,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"PO-Revision-Date: 2022-02-02 15:31+0000\n"
|
||||
"Last-Translator: Sven <tr@sutikal.de>\n"
|
||||
"PO-Revision-Date: 2022-02-06 21:31+0000\n"
|
||||
"Last-Translator: David Laukamp <dlkmp@live.de>\n"
|
||||
"Language-Team: German <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/de/>\n"
|
||||
"Language: de\n"
|
||||
@ -415,6 +415,7 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:501
|
||||
msgid "Days of recent shopping list entries to display."
|
||||
msgstr ""
|
||||
"Tage der letzten Einträge in der Einkaufsliste, die angezeigt werden sollen."
|
||||
|
||||
#: .\cookbook\forms.py:502
|
||||
msgid "Mark food 'On Hand' when checked off shopping list."
|
||||
@ -478,11 +479,12 @@ msgstr "Automatisch als vorrätig markieren"
|
||||
|
||||
#: .\cookbook\forms.py:528
|
||||
msgid "Reset Food Inheritance"
|
||||
msgstr ""
|
||||
msgstr "Lebensmittelvererbung zurücksetzen"
|
||||
|
||||
#: .\cookbook\forms.py:529
|
||||
msgid "Reset all food to inherit the fields configured."
|
||||
msgstr ""
|
||||
"Alle Lebensmittel zurücksetzen, um die konfigurierten Felder zu übernehmen."
|
||||
|
||||
#: .\cookbook\forms.py:541
|
||||
msgid "Fields on food that should be inherited by default."
|
||||
|
Binary file not shown.
@ -14,16 +14,16 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-01-18 14:52+0100\n"
|
||||
"PO-Revision-Date: 2022-01-16 07:06+0000\n"
|
||||
"Last-Translator: Josselin du PLESSIS <josse@du-plessis.fr>\n"
|
||||
"Language-Team: French <http://translate.tandoor.dev/projects/tandoor/recipes-"
|
||||
"backend/fr/>\n"
|
||||
"PO-Revision-Date: 2022-02-06 21:31+0000\n"
|
||||
"Last-Translator: Marion Kämpfer <marion@murphyslantech.de>\n"
|
||||
"Language-Team: French <http://translate.tandoor.dev/projects/tandoor/"
|
||||
"recipes-backend/fr/>\n"
|
||||
"Language: fr\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"
|
||||
"X-Generator: Weblate 4.10.1\n"
|
||||
|
||||
#: .\cookbook\filters.py:23 .\cookbook\templates\forms\ingredients.html:34
|
||||
#: .\cookbook\templates\space.html:50 .\cookbook\templates\stats.html:28
|
||||
@ -123,10 +123,8 @@ msgstr ""
|
||||
"nouvellement créés seront partagés par défaut."
|
||||
|
||||
#: .\cookbook\forms.py:80
|
||||
#, fuzzy
|
||||
#| msgid "Try the new shopping list"
|
||||
msgid "Users with whom to share shopping lists."
|
||||
msgstr "Essayer la nouvelle liste de courses"
|
||||
msgstr "Utilisateurs avec lesquels partager des listes de courses."
|
||||
|
||||
#: .\cookbook\forms.py:82
|
||||
msgid "Show recently viewed recipes on search page."
|
||||
@ -419,6 +417,8 @@ msgstr ""
|
||||
#: .\cookbook\forms.py:500
|
||||
msgid "Filter shopping list to only include supermarket categories."
|
||||
msgstr ""
|
||||
"Filtrer la liste de courses pour n’inclure que des catégories de "
|
||||
"supermarchés."
|
||||
|
||||
#: .\cookbook\forms.py:501
|
||||
msgid "Days of recent shopping list entries to display."
|
||||
@ -430,17 +430,15 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:503
|
||||
msgid "Delimiter to use for CSV exports."
|
||||
msgstr ""
|
||||
msgstr "Caractère de séparation à utiliser pour les exportations CSV."
|
||||
|
||||
#: .\cookbook\forms.py:504
|
||||
msgid "Prefix to add when copying list to the clipboard."
|
||||
msgstr ""
|
||||
msgstr "Préfixe à utiliser pour copier la liste dans le presse-papiers."
|
||||
|
||||
#: .\cookbook\forms.py:508
|
||||
#, fuzzy
|
||||
#| msgid "New Shopping List"
|
||||
msgid "Share Shopping List"
|
||||
msgstr "Nouvelle liste de courses"
|
||||
msgstr "Partager la liste de courses"
|
||||
|
||||
#: .\cookbook\forms.py:509
|
||||
msgid "Autosync"
|
||||
@ -448,7 +446,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:510
|
||||
msgid "Auto Add Meal Plan"
|
||||
msgstr ""
|
||||
msgstr "Ajouter le menu de la semaine automatiquement"
|
||||
|
||||
#: .\cookbook\forms.py:511
|
||||
msgid "Exclude On Hand"
|
||||
@ -474,7 +472,7 @@ msgstr ""
|
||||
|
||||
#: .\cookbook\forms.py:516
|
||||
msgid "CSV Delimiter"
|
||||
msgstr ""
|
||||
msgstr "Caractère de séparation CSV"
|
||||
|
||||
#: .\cookbook\forms.py:517 .\cookbook\templates\shopping_list.html:322
|
||||
msgid "List Prefix"
|
||||
@ -742,7 +740,7 @@ msgstr "Alias de mot-clé"
|
||||
|
||||
#: .\cookbook\serializer.py:175
|
||||
msgid "A user is required"
|
||||
msgstr ""
|
||||
msgstr "Un utilisateur est requis"
|
||||
|
||||
#: .\cookbook\serializer.py:195
|
||||
msgid "File uploads are not enabled for this Space."
|
||||
@ -754,7 +752,7 @@ msgstr "Vous avez atteint votre limite de téléversement de fichiers."
|
||||
|
||||
#: .\cookbook\serializer.py:962
|
||||
msgid "Existing shopping list to update"
|
||||
msgstr ""
|
||||
msgstr "Liste de courses existante à mettre à jour"
|
||||
|
||||
#: .\cookbook\serializer.py:964
|
||||
msgid ""
|
||||
|
Binary file not shown.
34
cookbook/migrations/0169_exportlog.py
Normal file
34
cookbook/migrations/0169_exportlog.py
Normal file
@ -0,0 +1,34 @@
|
||||
# Generated by Django 3.2.11 on 2022-02-03 15:03
|
||||
|
||||
import cookbook.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cookbook', '0168_add_unit_searchfields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ExportLog',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('type', models.CharField(max_length=32)),
|
||||
('running', models.BooleanField(default=True)),
|
||||
('msg', models.TextField(default='')),
|
||||
('total_recipes', models.IntegerField(default=0)),
|
||||
('exported_recipes', models.IntegerField(default=0)),
|
||||
('cache_duration', models.IntegerField(default=0)),
|
||||
('possibly_not_expired', models.BooleanField(default=True)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')),
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# Generated by Django 3.2.11 on 2022-02-02 19:36
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0169_auto_20220121_1427'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='ingredient',
|
||||
name='unit',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.unit'),
|
||||
),
|
||||
]
|
@ -1,20 +1,44 @@
|
||||
# Generated by Django 3.2.11 on 2022-01-21 20:27
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
# Generated by Django 3.2.11 on 2022-02-07 17:48
|
||||
|
||||
import cookbook.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('cookbook', '0168_add_unit_searchfields'),
|
||||
('cookbook', '0169_exportlog'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='child_inherit_fields',
|
||||
field=models.ManyToManyField(blank=True, related_name='child_inherit', to='cookbook.FoodInheritField'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute',
|
||||
field=models.ManyToManyField(blank=True, related_name='_cookbook_food_substitute_+', to='cookbook.Food'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute_children',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute_siblings',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ingredient',
|
||||
name='unit',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.unit'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='CustomFilter',
|
||||
fields=[
|
||||
@ -29,13 +53,13 @@ class Migration(migrations.Migration):
|
||||
],
|
||||
bases=(models.Model, cookbook.models.PermissionModelMixin),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='customfilter',
|
||||
constraint=models.UniqueConstraint(fields=('space', 'name'), name='cf_unique_name_per_space'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='recipebook',
|
||||
name='filter',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.customfilter'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='customfilter',
|
||||
constraint=models.UniqueConstraint(fields=('space', 'name'), name='cf_unique_name_per_space'),
|
||||
),
|
||||
]
|
@ -1,34 +0,0 @@
|
||||
# Generated by Django 3.2.11 on 2022-02-02 19:40
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0170_alter_ingredient_unit'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute',
|
||||
field=models.ManyToManyField(blank=True, related_name='_cookbook_food_substitute_+', to='cookbook.Food'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute_children',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='substitute_siblings',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ingredient',
|
||||
name='unit',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='cookbook.unit'),
|
||||
),
|
||||
]
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.2.11 on 2022-02-04 17:11
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cookbook', '0171_auto_20220202_1340'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='food',
|
||||
name='child_inherit_fields',
|
||||
field=models.ManyToManyField(blank=True, related_name='child_inherit', to='cookbook.FoodInheritField'),
|
||||
),
|
||||
]
|
@ -1028,6 +1028,25 @@ class ImportLog(models.Model, PermissionModelMixin):
|
||||
def __str__(self):
|
||||
return f"{self.created_at}:{self.type}"
|
||||
|
||||
class ExportLog(models.Model, PermissionModelMixin):
|
||||
type = models.CharField(max_length=32)
|
||||
running = models.BooleanField(default=True)
|
||||
msg = models.TextField(default="")
|
||||
|
||||
total_recipes = models.IntegerField(default=0)
|
||||
exported_recipes = models.IntegerField(default=0)
|
||||
cache_duration = models.IntegerField(default=0)
|
||||
possibly_not_expired = models.BooleanField(default=True)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
|
||||
objects = ScopedManager(space='space')
|
||||
space = models.ForeignKey(Space, on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.created_at}:{self.type}"
|
||||
|
||||
|
||||
class BookmarkletImport(ExportModelOperationsMixin('bookmarklet_import'), models.Model, PermissionModelMixin):
|
||||
html = models.TextField()
|
||||
|
@ -1,17 +1,14 @@
|
||||
import random
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import Avg, Q, QuerySet, Sum, Value
|
||||
from django.db.models.functions import Substr
|
||||
from django.db.models import Avg, Q, QuerySet, Sum
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from drf_writable_nested import UniqueFieldsMixin, WritableNestedModelSerializer
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import NotFound, ValidationError
|
||||
from rest_framework.fields import empty
|
||||
|
||||
from cookbook.helper.HelperFunctions import str2bool
|
||||
from cookbook.helper.shopping_helper import RecipeShoppingEditor
|
||||
@ -21,7 +18,7 @@ from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Cu
|
||||
RecipeImport, ShareLink, ShoppingList, ShoppingListEntry,
|
||||
ShoppingListRecipe, Step, Storage, Supermarket, SupermarketCategory,
|
||||
SupermarketCategoryRelation, Sync, SyncLog, Unit, UserFile,
|
||||
UserPreference, ViewLog)
|
||||
UserPreference, ViewLog, ExportLog)
|
||||
from cookbook.templatetags.custom_tags import markdown
|
||||
from recipes.settings import MEDIA_URL
|
||||
|
||||
@ -92,7 +89,10 @@ class CustomOnHandField(serializers.Field):
|
||||
if request := self.context.get('request', None):
|
||||
shared_users = getattr(request, '_shared_users', None)
|
||||
if shared_users is None:
|
||||
try:
|
||||
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [self.context['request'].user.id]
|
||||
except AttributeError: # Anonymous users (using share links) don't have shared users
|
||||
shared_users = []
|
||||
return obj.onhand_users.filter(id__in=shared_users).exists()
|
||||
|
||||
def to_internal_value(self, data):
|
||||
@ -895,6 +895,19 @@ class ImportLogSerializer(serializers.ModelSerializer):
|
||||
read_only_fields = ('created_by',)
|
||||
|
||||
|
||||
class ExportLogSerializer(serializers.ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['created_by'] = self.context['request'].user
|
||||
validated_data['space'] = self.context['request'].space
|
||||
return super().create(validated_data)
|
||||
|
||||
class Meta:
|
||||
model = ExportLog
|
||||
fields = ('id', 'type', 'msg', 'running', 'total_recipes', 'exported_recipes', 'cache_duration', 'possibly_not_expired', 'created_by', 'created_at')
|
||||
read_only_fields = ('created_by',)
|
||||
|
||||
|
||||
class AutomationSerializer(serializers.ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
|
7
cookbook/static/css/app.min.css
vendored
7
cookbook/static/css/app.min.css
vendored
@ -1140,3 +1140,10 @@
|
||||
min-width: 28rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media print{
|
||||
#switcher{
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
@ -1,25 +1,33 @@
|
||||
{% extends "base.html" %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% load i18n %}
|
||||
{% load render_bundle from webpack_loader %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
|
||||
|
||||
{% block title %}{% trans 'Export Recipes' %}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
{{ form.media }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<h2>{% trans 'Export' %}</h2>
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
<form action="." method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button class="btn btn-success" type="submit"><i class="fas fa-file-export"></i> {% trans 'Export' %}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="app">
|
||||
<export-view></export-view>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block script %}
|
||||
{% if debug %}
|
||||
<script src="{% url 'js_reverse' %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static 'django_js_reverse/reverse.js' %}"></script>
|
||||
{% endif %}
|
||||
|
||||
<script type="application/javascript">
|
||||
window.EXPORT_ID = {{pk}};
|
||||
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}';
|
||||
</script>
|
||||
|
||||
{% render_bundle 'export_view' %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
32
cookbook/templates/export_response.html
Normal file
32
cookbook/templates/export_response.html
Normal file
@ -0,0 +1,32 @@
|
||||
{% extends "base.html" %}
|
||||
{% load render_bundle from webpack_loader %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
|
||||
{% block title %}{% trans 'Export' %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id="app">
|
||||
<export-response-view></export-response-view>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block script %}
|
||||
{% if debug %}
|
||||
<script src="{% url 'js_reverse' %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static 'django_js_reverse/reverse.js' %}"></script>
|
||||
{% endif %}
|
||||
|
||||
<script type="application/javascript">
|
||||
window.EXPORT_ID = {{pk}};
|
||||
window.CUSTOM_LOCALE = '{{ request.LANGUAGE_CODE }}'
|
||||
</script>
|
||||
|
||||
{% render_bundle 'export_response_view' %}
|
||||
{% endblock %}
|
@ -26,7 +26,7 @@
|
||||
<small class="card-title">{{ c.updated_at }} {% trans 'by' %} {{ c.created_by.username }}</small> <a
|
||||
href="{% url 'edit_comment' c.pk %}" class="d-print-none"><i
|
||||
class="fas fa-pencil-alt"></i></a><br/>
|
||||
{{ c.text }}
|
||||
{{ c.text | urlize |linebreaks }}
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
|
@ -219,11 +219,11 @@
|
||||
<script type="application/javascript">
|
||||
$(function() {
|
||||
$('#id_search-trigram_threshold').get(0).type = 'range';
|
||||
})
|
||||
});
|
||||
|
||||
function applyPreset(preset) {
|
||||
$('#id_search-preset').val(preset)
|
||||
$('#search_form_button').click()
|
||||
$('#id_search-preset').val(preset);
|
||||
$('#search_form_button').click();
|
||||
}
|
||||
|
||||
function copyToken() {
|
||||
@ -242,26 +242,27 @@
|
||||
$('.nav-tabs a').on('shown.bs.tab', function(e) {
|
||||
window.location.hash = e.target.hash;
|
||||
})
|
||||
|
||||
{% comment %}
|
||||
// listen for events
|
||||
{% comment %} $(document).ready(function(){
|
||||
$(document).ready(function() {
|
||||
hideShow()
|
||||
// call hideShow when the user clicks on the mealplan_autoadd checkbox
|
||||
$("#id_shopping-mealplan_autoadd_shopping").click(function(event) {
|
||||
hideShow()
|
||||
hideShow();
|
||||
});
|
||||
})
|
||||
|
||||
function hideShow() {
|
||||
if(document.getElementById('id_shopping-mealplan_autoadd_shopping').checked == true)
|
||||
{
|
||||
if(document.getElementById('id_shopping-mealplan_autoadd_shopping').checked == true) {
|
||||
$('#div_id_shopping-mealplan_autoexclude_onhand').show();
|
||||
$('#div_id_shopping-mealplan_autoinclude_related').show();
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
$('#div_id_shopping-mealplan_autoexclude_onhand').hide();
|
||||
$('#div_id_shopping-mealplan_autoinclude_related').hide();
|
||||
} {% endcomment %}
|
||||
}
|
||||
}
|
||||
{% endcomment %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -4,7 +4,7 @@ import pytest
|
||||
from django.urls import reverse
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
from cookbook.models import Recipe
|
||||
from cookbook.models import Recipe, ShareLink
|
||||
from cookbook.tests.conftest import get_random_json_recipe, validate_recipe
|
||||
|
||||
LIST_URL = 'api:recipe-list'
|
||||
@ -38,6 +38,21 @@ def test_list_space(recipe_1_s1, u1_s1, u1_s2, space_2):
|
||||
assert len(json.loads(u1_s2.get(reverse(LIST_URL)).content)['results']) == 1
|
||||
|
||||
|
||||
def test_share_permission(recipe_1_s1, u1_s1, u1_s2, a_u):
|
||||
assert u1_s1.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk])).status_code == 200
|
||||
assert u1_s2.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk])).status_code == 404
|
||||
|
||||
with scopes_disabled():
|
||||
r = u1_s1.get(reverse('new_share_link', kwargs={'pk': recipe_1_s1.pk}))
|
||||
assert r.status_code == 302
|
||||
r = u1_s2.get(reverse('new_share_link', kwargs={'pk': recipe_1_s1.pk}))
|
||||
assert r.status_code == 404
|
||||
share = ShareLink.objects.filter(recipe=recipe_1_s1).first()
|
||||
assert a_u.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 200
|
||||
assert u1_s1.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 200
|
||||
assert u1_s2.get(reverse(DETAIL_URL, args=[recipe_1_s1.pk]) + f'?share={share.uuid}').status_code == 404 # TODO fix in https://github.com/TandoorRecipes/recipes/issues/1238
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arg", [
|
||||
['a_u', 403],
|
||||
['g1_s1', 200],
|
||||
|
25
cookbook/tests/other/test_export.py
Normal file
25
cookbook/tests/other/test_export.py
Normal file
@ -0,0 +1,25 @@
|
||||
import pytest
|
||||
from django.contrib import auth
|
||||
from django.urls import reverse
|
||||
|
||||
from cookbook.forms import ImportExportBase
|
||||
from cookbook.helper.ingredient_parser import IngredientParser
|
||||
from cookbook.models import ExportLog
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def obj_1(space_1, u1_s1):
|
||||
return ExportLog.objects.create(type=ImportExportBase.DEFAULT, running=False, created_by=auth.get_user(u1_s1), space=space_1, exported_recipes=10, total_recipes=10)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arg", [
|
||||
['a_u', 302],
|
||||
['g1_s1', 302],
|
||||
['u1_s1', 200],
|
||||
['a1_s1', 200],
|
||||
['u1_s2', 404],
|
||||
['a1_s2', 404],
|
||||
])
|
||||
def test_export_file_cache(arg, request, obj_1):
|
||||
c = request.getfixturevalue(arg[0])
|
||||
assert c.get(reverse('view_export_file', args=[obj_1.pk])).status_code == arg[1]
|
@ -81,7 +81,7 @@ def test_history(arg, request, ext_recipe_1_s1):
|
||||
['a_u', 302],
|
||||
['g1_s1', 302],
|
||||
['u1_s1', 302],
|
||||
['a1_s1', 200],
|
||||
['a1_s1', 302],
|
||||
])
|
||||
def test_system(arg, request, ext_recipe_1_s1):
|
||||
c = request.getfixturevalue(arg[0])
|
||||
|
@ -23,6 +23,7 @@ router.register(r'custom-filter', api.CustomFilterViewSet)
|
||||
router.register(r'food', api.FoodViewSet)
|
||||
router.register(r'food-inherit-field', api.FoodInheritFieldViewSet)
|
||||
router.register(r'import-log', api.ImportLogViewSet)
|
||||
router.register(r'export-log', api.ExportLogViewSet)
|
||||
router.register(r'ingredient', api.IngredientViewSet)
|
||||
router.register(r'keyword', api.KeywordViewSet)
|
||||
router.register(r'meal-plan', api.MealPlanViewSet)
|
||||
@ -76,6 +77,8 @@ urlpatterns = [
|
||||
path('import/', import_export.import_recipe, name='view_import'),
|
||||
path('import-response/<int:pk>/', import_export.import_response, name='view_import_response'),
|
||||
path('export/', import_export.export_recipe, name='view_export'),
|
||||
path('export-response/<int:pk>/', import_export.export_response, name='view_export_response'),
|
||||
path('export-file/<int:pk>/', import_export.export_file, name='view_export_file'),
|
||||
|
||||
path('view/recipe/<int:pk>', views.recipe_view, name='view_recipe'),
|
||||
path('view/recipe/<int:pk>/<slug:share>', views.recipe_view, name='view_recipe'),
|
||||
|
@ -48,11 +48,13 @@ from cookbook.models import (Automation, BookmarkletImport, CookLog, CustomFilte
|
||||
ShoppingListEntry, ShoppingListRecipe, Step, Storage, Supermarket,
|
||||
SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, Unit,
|
||||
UserFile, UserPreference, ViewLog)
|
||||
from cookbook.models import (ExportLog)
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
from cookbook.provider.nextcloud import Nextcloud
|
||||
from cookbook.schemas import FilterSchema, QueryParam, QueryParamAutoSchema, TreeSchema
|
||||
from cookbook.serializer import (AutomationSerializer, BookmarkletImportSerializer,
|
||||
ExportLogSerializer,
|
||||
CookLogSerializer, CustomFilterSerializer,
|
||||
FoodInheritFieldSerializer, FoodSerializer,
|
||||
FoodShoppingUpdateSerializer, ImportLogSerializer,
|
||||
@ -660,11 +662,13 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
||||
schema = QueryParamAutoSchema()
|
||||
|
||||
def get_queryset(self):
|
||||
share = self.request.query_params.get('share', None)
|
||||
|
||||
if self.detail:
|
||||
if not share:
|
||||
self.queryset = self.queryset.filter(space=self.request.space)
|
||||
return super().get_queryset()
|
||||
|
||||
share = self.request.query_params.get('share', None)
|
||||
if not (share and self.detail):
|
||||
self.queryset = self.queryset.filter(space=self.request.space)
|
||||
|
||||
@ -872,6 +876,17 @@ class ImportLogViewSet(viewsets.ModelViewSet):
|
||||
return self.queryset.filter(space=self.request.space)
|
||||
|
||||
|
||||
class ExportLogViewSet(viewsets.ModelViewSet):
|
||||
queryset = ExportLog.objects
|
||||
serializer_class = ExportLogSerializer
|
||||
permission_classes = [CustomIsUser]
|
||||
pagination_class = DefaultPagination
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(space=self.request.space)
|
||||
|
||||
|
||||
|
||||
class BookmarkletImportViewSet(viewsets.ModelViewSet):
|
||||
queryset = BookmarkletImport.objects
|
||||
serializer_class = BookmarkletImportSerializer
|
||||
|
@ -1,10 +1,11 @@
|
||||
import re
|
||||
import threading
|
||||
from io import BytesIO
|
||||
from django.core.cache import cache
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponseRedirect, JsonResponse
|
||||
from django.shortcuts import render
|
||||
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
@ -29,7 +30,7 @@ from cookbook.integration.recipesage import RecipeSage
|
||||
from cookbook.integration.rezkonv import RezKonv
|
||||
from cookbook.integration.saffron import Saffron
|
||||
from cookbook.integration.pdfexport import PDFexport
|
||||
from cookbook.models import Recipe, ImportLog, UserPreference
|
||||
from cookbook.models import Recipe, ImportLog, ExportLog, UserPreference
|
||||
from recipes import settings
|
||||
|
||||
|
||||
@ -123,25 +124,57 @@ def export_recipe(request):
|
||||
if form.cleaned_data['all']:
|
||||
recipes = Recipe.objects.filter(space=request.space, internal=True).all()
|
||||
|
||||
if form.cleaned_data['type'] == ImportExportBase.PDF and not settings.ENABLE_PDF_EXPORT:
|
||||
messages.add_message(request, messages.ERROR, _('The PDF Exporter is not enabled on this instance as it is still in an experimental state.'))
|
||||
return render(request, 'export.html', {'form': form})
|
||||
integration = get_integration(request, form.cleaned_data['type'])
|
||||
return integration.do_export(recipes)
|
||||
except NotImplementedError:
|
||||
messages.add_message(request, messages.ERROR, _('Exporting is not implemented for this provider'))
|
||||
|
||||
if form.cleaned_data['type'] == ImportExportBase.PDF and not settings.ENABLE_PDF_EXPORT:
|
||||
return JsonResponse({'error': _('The PDF Exporter is not enabled on this instance as it is still in an experimental state.')})
|
||||
|
||||
el = ExportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space)
|
||||
|
||||
t = threading.Thread(target=integration.do_export, args=[recipes, el])
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
return JsonResponse({'export_id': el.pk})
|
||||
except NotImplementedError:
|
||||
return JsonResponse(
|
||||
{
|
||||
'error': True,
|
||||
'msg': _('Importing is not implemented for this provider')
|
||||
},
|
||||
status=400
|
||||
)
|
||||
else:
|
||||
form = ExportForm(space=request.space)
|
||||
pk = ''
|
||||
recipe = request.GET.get('r')
|
||||
if recipe:
|
||||
if re.match(r'^([0-9])+$', recipe):
|
||||
if recipe := Recipe.objects.filter(pk=int(recipe), space=request.space).first():
|
||||
form = ExportForm(initial={'recipes': recipe}, space=request.space)
|
||||
pk = Recipe.objects.filter(pk=int(recipe), space=request.space).first().pk
|
||||
|
||||
return render(request, 'export.html', {'form': form})
|
||||
return render(request, 'export.html', {'pk': pk})
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def import_response(request, pk):
|
||||
return render(request, 'import_response.html', {'pk': pk})
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def export_response(request, pk):
|
||||
return render(request, 'export_response.html', {'pk': pk})
|
||||
|
||||
|
||||
@group_required('user')
|
||||
def export_file(request, pk):
|
||||
el = get_object_or_404(ExportLog, pk=pk, space=request.space)
|
||||
|
||||
cacheData = cache.get(f'export_file_{el.pk}')
|
||||
|
||||
if cacheData is None:
|
||||
el.possibly_not_expired = False
|
||||
el.save()
|
||||
return render(request, 'export_response.html', {'pk': pk})
|
||||
|
||||
response = HttpResponse(cacheData['file'], content_type='application/force-download')
|
||||
response['Content-Disposition'] = 'attachment; filename="' + cacheData['filename'] + '"'
|
||||
return response
|
||||
|
@ -446,6 +446,9 @@ def history(request):
|
||||
|
||||
@group_required('admin')
|
||||
def system(request):
|
||||
if not request.user.is_superuser:
|
||||
return HttpResponseRedirect(reverse('index'))
|
||||
|
||||
postgres = False if (
|
||||
settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2' # noqa: E501
|
||||
or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql' # noqa: E501
|
||||
|
@ -10,6 +10,9 @@ Tandoor can be installed as a progressive web app (PWA) on mobile and desktop de
|
||||
#### Safari (iPhone/iPad)
|
||||
Open Tandoor, click Safari's share button, select `Add to Home Screen`
|
||||
|
||||
### Chrome/Chromium
|
||||
Open Tandoor, click the `add Tandoor to the home screen` message that pops up at the bottom of the screen
|
||||
|
||||
### Desktop browsers
|
||||
|
||||
#### Google Chrome
|
||||
|
@ -21,12 +21,12 @@ if your favorite one is missing.
|
||||
Overview of the capabilities of the different integrations.
|
||||
|
||||
| Integration | Import | Export | Images |
|
||||
|--------------------| ------ | ------ | ------ |
|
||||
|--------------------| ------ | -- | ------ |
|
||||
| Default | ✔️ | ✔️ | ✔️ |
|
||||
| Nextcloud | ✔️ | ⌚ | ✔️ |
|
||||
| Mealie | ✔️ | ⌚ | ✔️ |
|
||||
| Chowdown | ✔️ | ⌚ | ✔️ |
|
||||
| Safron | ✔️ | ✔ | ❌ |
|
||||
| Safron | ✔️ | ✔️ | ❌ |
|
||||
| Paprika | ✔️ | ⌚ | ✔️ |
|
||||
| ChefTap | ✔️ | ❌ | ❌ |
|
||||
| Pepperplate | ✔️ | ⌚ | ❌ |
|
||||
@ -38,9 +38,9 @@ Overview of the capabilities of the different integrations.
|
||||
| Plantoeat | ✔️ | ❌ | ✔ |
|
||||
| CookBookApp | ✔️ | ⌚ | ✔️ |
|
||||
| CopyMeThat | ✔️ | ❌ | ✔️ |
|
||||
| PDF (experimental) | ⌚️ | ✔ | ✔️ |
|
||||
| PDF (experimental) | ⌚️ | ✔️ | ✔️ |
|
||||
|
||||
✔ = implemented, ❌ = not implemented and not possible/planned, ⌚ = not yet implemented
|
||||
✔️ = implemented, ❌ = not implemented and not possible/planned, ⌚ = not yet implemented
|
||||
|
||||
## Default
|
||||
The default integration is the built in (and preferred) way to import and export recipes.
|
||||
|
62
docs/install/docker/ipv6_plain/docker-compose.yml
Normal file
62
docs/install/docker/ipv6_plain/docker-compose.yml
Normal file
@ -0,0 +1,62 @@
|
||||
version: "2.4"
|
||||
services:
|
||||
db_recipes:
|
||||
restart: always
|
||||
image: postgres:11-alpine
|
||||
volumes:
|
||||
- ${POSTGRES_DATA_DIR:-./postgresql}:/var/lib/postgresql/data
|
||||
env_file:
|
||||
- ./.env
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "psql -U $$POSTGRES_USER -d $$POSTGRES_DB --list || exit 1"]
|
||||
interval: 4s
|
||||
timeout: 1s
|
||||
retries: 12
|
||||
networks:
|
||||
tandoor:
|
||||
ipv6_address: ${IPV6_PREFIX:?NO_IPV6_PREFIX}::2
|
||||
web_recipes:
|
||||
image: vabene1111/recipes
|
||||
restart: always
|
||||
env_file:
|
||||
- ./.env
|
||||
volumes:
|
||||
- staticfiles:/opt/recipes/staticfiles
|
||||
- nginx_config:/opt/recipes/nginx/conf.d
|
||||
- ${MEDIA_FILES_DIR:-./mediafiles}:/opt/recipes/mediafiles
|
||||
depends_on:
|
||||
db_recipes:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
tandoor:
|
||||
ipv6_address: ${IPV6_PREFIX:?NO_IPV6_PREFIX}::3
|
||||
|
||||
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
|
||||
- ${MEDIA_FILES_DIR:-./mediafiles}:/media
|
||||
networks:
|
||||
tandoor:
|
||||
ipv6_address: ${IPV6_PREFIX:?NO_IPV6_PREFIX}::4
|
||||
volumes:
|
||||
nginx_config:
|
||||
staticfiles:
|
||||
|
||||
networks:
|
||||
tandoor:
|
||||
enable_ipv6: true
|
||||
name: ${NETWORK_NAME:-tandoor}
|
||||
driver: bridge
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
- subnet: ${IPV6_PREFIX:?NO_IPV6_PREFIX}::/${IPV6_PREFIX_LENGTH:?NO_IPV6_PREFIX_LENGTH}
|
@ -138,6 +138,7 @@ ENABLE_SIGNUP = bool(int(os.getenv('ENABLE_SIGNUP', False)))
|
||||
ENABLE_METRICS = bool(int(os.getenv('ENABLE_METRICS', False)))
|
||||
|
||||
ENABLE_PDF_EXPORT = bool(int(os.getenv('ENABLE_PDF_EXPORT', False)))
|
||||
EXPORT_FILE_CACHE_DURATION = int(os.getenv('EXPORT_FILE_CACHE_DURATION', 600))
|
||||
|
||||
MIDDLEWARE = [
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
@ -427,3 +428,4 @@ EMAIL_USE_TLS = bool(int(os.getenv('EMAIL_USE_TLS', False)))
|
||||
EMAIL_USE_SSL = bool(int(os.getenv('EMAIL_USE_SSL', False)))
|
||||
DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', 'webmaster@localhost')
|
||||
ACCOUNT_EMAIL_SUBJECT_PREFIX = os.getenv('ACCOUNT_EMAIL_SUBJECT_PREFIX', '[Tandoor Recipes] ') # allauth sender prefix
|
||||
|
||||
|
145
vue/src/apps/ExportResponseView/ExportResponseView.vue
Normal file
145
vue/src/apps/ExportResponseView/ExportResponseView.vue
Normal file
@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<br/>
|
||||
|
||||
<template v-if="export_info !== undefined">
|
||||
|
||||
<template v-if="export_info.running">
|
||||
<h5 style="text-align: center">{{ $t('Exporting') }}...</h5>
|
||||
|
||||
<b-progress :max="export_info.total_recipes">
|
||||
<b-progress-bar :value="export_info.exported_recipes" :label="`${export_info.exported_recipes}/${export_info.total_recipes}`"></b-progress-bar>
|
||||
</b-progress>
|
||||
|
||||
<loading-spinner :size="25"></loading-spinner>
|
||||
</template>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-md-12" v-if="!export_info.running">
|
||||
<span>{{ $t('Export_finished') }}! </span> <a :href="`${resolveDjangoUrl('viewExport') }`">{{ $t('Return to export') }} </a><br><br>
|
||||
|
||||
{{ $t('If download did not start automatically: ') }}
|
||||
|
||||
<template v-if="export_info.expired">
|
||||
<a disabled><del>{{ $t('Download') }}</del></a> ({{ $t('Expired') }})
|
||||
</template>
|
||||
<a v-else :href="`/export-file/${export_id}/`" ref="downloadAnchor" >{{ $t('Download') }}</a>
|
||||
|
||||
<br>
|
||||
{{ $t('The link will remain active for') }}
|
||||
|
||||
<template v-if="export_info.cache_duration > 3600">
|
||||
{{ export_info.cache_duration/3600 }}{{ $t('hr') }}
|
||||
</template>
|
||||
<template v-else-if="export_info.cache_duration > 60">
|
||||
{{ export_info.cache_duration/60 }}{{ $t('min') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ export_info.cache_duration }}{{ $t('sec') }}
|
||||
</template>
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
<label for="id_textarea">{{ $t('Information') }}</label>
|
||||
<textarea id="id_textarea" ref="output_text" class="form-control" style="height: 50vh"
|
||||
v-html="export_info.msg"
|
||||
disabled></textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import {BootstrapVue} from 'bootstrap-vue'
|
||||
|
||||
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||
|
||||
import {ResolveUrlMixin, makeToast, ToastMixin} from "@/utils/utils";
|
||||
|
||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||
|
||||
import {ApiApiFactory} from "@/utils/openapi/api.ts";
|
||||
|
||||
Vue.use(BootstrapVue)
|
||||
|
||||
export default {
|
||||
name: 'ExportResponseView',
|
||||
mixins: [
|
||||
ResolveUrlMixin,
|
||||
ToastMixin,
|
||||
],
|
||||
components: {
|
||||
LoadingSpinner
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
export_id: window.EXPORT_ID,
|
||||
export_info: undefined,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.refreshData()
|
||||
this.$i18n.locale = window.CUSTOM_LOCALE
|
||||
|
||||
this.dynamicIntervalTimeout = 250 //initial refresh rate
|
||||
this.run = setTimeout(this.dynamicInterval.bind(this), this.dynamicIntervalTimeout)
|
||||
},
|
||||
methods: {
|
||||
dynamicInterval: function(){
|
||||
|
||||
//update frequently at start but slowdown as it takes longer
|
||||
this.dynamicIntervalTimeout = Math.round(this.dynamicIntervalTimeout*((1+Math.sqrt(5))/2))
|
||||
if(this.dynamicIntervalTimeout > 5000) this.dynamicIntervalTimeout = 5000
|
||||
clearInterval(this.run);
|
||||
this.run = setInterval(this.dynamicInterval.bind(this), this.dynamicIntervalTimeout);
|
||||
|
||||
if ((this.export_id !== null) && window.navigator.onLine && this.export_info.running) {
|
||||
this.refreshData()
|
||||
let el = this.$refs.output_text
|
||||
el.scrollTop = el.scrollHeight;
|
||||
|
||||
if(this.export_info.expired)
|
||||
makeToast(this.$t("Error"), this.$t("The download link is expired!"), "danger")
|
||||
}
|
||||
},
|
||||
|
||||
startDownload: function(){
|
||||
this.$refs['downloadAnchor'].click()
|
||||
},
|
||||
|
||||
refreshData: function () {
|
||||
let apiClient = new ApiApiFactory()
|
||||
|
||||
apiClient.retrieveExportLog(this.export_id).then(result => {
|
||||
this.export_info = result.data
|
||||
this.export_info.expired = !this.export_info.possibly_not_expired
|
||||
|
||||
if(!this.export_info.running)
|
||||
this.$nextTick(()=>{ this.startDownload(); } )
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
</style>
|
18
vue/src/apps/ExportResponseView/main.js
Normal file
18
vue/src/apps/ExportResponseView/main.js
Normal file
@ -0,0 +1,18 @@
|
||||
import Vue from 'vue'
|
||||
import App from './ExportResponseView.vue'
|
||||
import i18n from '@/i18n'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
|
||||
let publicPath = localStorage.STATIC_URL + 'vue/'
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
publicPath = 'http://localhost:8080/'
|
||||
}
|
||||
export default __webpack_public_path__ = publicPath // eslint-disable-line
|
||||
|
||||
|
||||
new Vue({
|
||||
i18n,
|
||||
render: h => h(App),
|
||||
}).$mount('#app')
|
174
vue/src/apps/ExportView/ExportView.vue
Normal file
174
vue/src/apps/ExportView/ExportView.vue
Normal file
@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
|
||||
<h2>{{ $t('Export') }}</h2>
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
|
||||
<br/>
|
||||
<!-- TODO get option dynamicaly -->
|
||||
<select class="form-control" v-model="recipe_app">
|
||||
<option value="DEFAULT">Default</option>
|
||||
<option value="SAFFRON">Saffron</option>
|
||||
<option value="RECIPESAGE">Recipe Sage</option>
|
||||
<option value="PDF">PDF (experimental)</option>
|
||||
</select>
|
||||
|
||||
<br/>
|
||||
<b-form-checkbox v-model="export_all" @change="disabled_multiselect=$event" name="check-button" switch style="margin-top: 1vh">
|
||||
{{ $t('All recipes') }}
|
||||
</b-form-checkbox>
|
||||
|
||||
<multiselect
|
||||
:searchable="true"
|
||||
:disabled="disabled_multiselect"
|
||||
v-model="recipe_list"
|
||||
:options="recipes"
|
||||
:close-on-select="false"
|
||||
:clear-on-select="true"
|
||||
:hide-selected="true"
|
||||
:preserve-search="true"
|
||||
placeholder="Select Recipes"
|
||||
:taggable="false"
|
||||
label="name"
|
||||
track-by="id"
|
||||
id="id_recipes"
|
||||
:multiple="true"
|
||||
:loading="recipes_loading"
|
||||
@search-change="searchRecipes">
|
||||
</multiselect>
|
||||
|
||||
<br/>
|
||||
<button @click="exportRecipe()" class="btn btn-primary shadow-none"><i class="fas fa-file-export"></i> {{ $t('Export') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import {BootstrapVue} from 'bootstrap-vue'
|
||||
|
||||
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||
|
||||
|
||||
import LoadingSpinner from "@/components/LoadingSpinner";
|
||||
|
||||
import {StandardToasts, makeToast, resolveDjangoUrl} from "@/utils/utils";
|
||||
import Multiselect from "vue-multiselect";
|
||||
import {ApiApiFactory} from "@/utils/openapi/api.ts";
|
||||
import axios from "axios";
|
||||
|
||||
|
||||
Vue.use(BootstrapVue)
|
||||
|
||||
|
||||
export default {
|
||||
name: 'ExportView',
|
||||
/*mixins: [
|
||||
ResolveUrlMixin,
|
||||
ToastMixin,
|
||||
],*/
|
||||
components: {Multiselect},
|
||||
data() {
|
||||
return {
|
||||
export_id: window.EXPORT_ID,
|
||||
loading: false,
|
||||
disabled_multiselect: false,
|
||||
|
||||
recipe_app: 'DEFAULT',
|
||||
recipe_list: [],
|
||||
recipes_loading: false,
|
||||
recipes: [],
|
||||
export_all: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if(this.export_id)
|
||||
this.insertRequested()
|
||||
else
|
||||
this.searchRecipes('')
|
||||
},
|
||||
methods: {
|
||||
|
||||
insertRequested: function(){
|
||||
|
||||
let apiFactory = new ApiApiFactory()
|
||||
|
||||
this.recipes_loading = true
|
||||
|
||||
apiFactory.retrieveRecipe(this.export_id).then((response) => {
|
||||
this.recipes_loading = false
|
||||
this.recipe_list.push(response.data)
|
||||
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
StandardToasts.makeStandardToast(StandardToasts.FAIL_FETCH)
|
||||
}).then(e => this.searchRecipes(''))
|
||||
},
|
||||
|
||||
searchRecipes: function (query) {
|
||||
|
||||
let apiFactory = new ApiApiFactory()
|
||||
|
||||
this.recipes_loading = true
|
||||
|
||||
let maxResultLenght = 1000
|
||||
apiFactory.listRecipes(query, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 1, maxResultLenght).then((response) => {
|
||||
this.recipes = response.data.results;
|
||||
this.recipes_loading = false
|
||||
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
StandardToasts.makeStandardToast(StandardToasts.FAIL_FETCH)
|
||||
})
|
||||
},
|
||||
|
||||
exportRecipe: function () {
|
||||
|
||||
if (this.recipe_list.length < 1 && this.export_all == false) {
|
||||
makeToast(this.$t("Error"), this.$t("Select at least one recipe"), "danger")
|
||||
return;
|
||||
}
|
||||
|
||||
this.error = undefined
|
||||
this.loading = true
|
||||
let formData = new FormData();
|
||||
formData.append('type', this.recipe_app);
|
||||
formData.append('all', this.export_all)
|
||||
|
||||
for (var i = 0; i < this.recipe_list.length; i++) {
|
||||
formData.append('recipes', this.recipe_list[i].id);
|
||||
}
|
||||
|
||||
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
axios.post(resolveDjangoUrl('view_export',), formData).then((response) => {
|
||||
if (response.data['error'] !== undefined){
|
||||
makeToast(this.$t("Error"), response.data['error'],"warning")
|
||||
}else{
|
||||
window.location.href = resolveDjangoUrl('view_export_response', response.data['export_id'])
|
||||
}
|
||||
|
||||
}).catch((err) => {
|
||||
this.error = err.data
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
makeToast(this.$t("Error"), this.$t("There was an error loading a resource!"), "warning")
|
||||
})
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
</style>
|
18
vue/src/apps/ExportView/main.js
Normal file
18
vue/src/apps/ExportView/main.js
Normal file
@ -0,0 +1,18 @@
|
||||
import Vue from 'vue'
|
||||
import App from './ExportView.vue'
|
||||
import i18n from '@/i18n'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
// TODO move this and other default stuff to centralized JS file (verify nothing breaks)
|
||||
let publicPath = localStorage.STATIC_URL + 'vue/'
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
publicPath = 'http://localhost:8080/'
|
||||
}
|
||||
export default __webpack_public_path__ = publicPath // eslint-disable-line
|
||||
|
||||
|
||||
new Vue({
|
||||
i18n,
|
||||
render: h => h(App),
|
||||
}).$mount('#app')
|
@ -736,8 +736,8 @@ export default {
|
||||
}
|
||||
|
||||
this.recipe.servings = Math.floor(this.recipe.servings) // temporary fix until a proper framework for frontend input validation is established
|
||||
if (this.recipe.servings === "" || isNaN(this.recipe.servings)) {
|
||||
this.recipe.servings = 0
|
||||
if (this.recipe.servings === "" || isNaN(this.recipe.servings) || this.recipe.servings===0 ) {
|
||||
this.recipe.servings = 1
|
||||
}
|
||||
|
||||
apiFactory
|
||||
@ -791,7 +791,7 @@ export default {
|
||||
let empty_step = {
|
||||
instruction: "",
|
||||
ingredients: [],
|
||||
show_as_header: true,
|
||||
show_as_header: false,
|
||||
time_visible: false,
|
||||
ingredients_visible: true,
|
||||
instruction_visible: true,
|
||||
|
@ -100,7 +100,7 @@
|
||||
<div class="col-12 order-1 col-sm-12 order-sm-1 col-md-6 order-md-2">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<img class="img img-fluid rounded" :src="recipe.image" style="max-height: 30vh" :alt="$t('Recipe_Image')" v-if="recipe.image !== null" />
|
||||
<img class="img img-fluid rounded" :src="recipe.image" style="max-height: 30vh" :alt="$t('Recipe_Image')" v-if="recipe.image !== null" @load="onImgLoad" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -208,6 +208,7 @@ export default {
|
||||
servings_cache: {},
|
||||
start_time: "",
|
||||
share_uid: window.SHARE_UID,
|
||||
wake_lock: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -218,8 +219,37 @@ export default {
|
||||
mounted() {
|
||||
this.loadRecipe(window.RECIPE_ID)
|
||||
this.$i18n.locale = window.CUSTOM_LOCALE
|
||||
this.requestWakeLock()
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.destroyWakeLock()
|
||||
},
|
||||
methods: {
|
||||
requestWakeLock: async function() {
|
||||
if ('wakeLock' in navigator) {
|
||||
try {
|
||||
this.wake_lock = await navigator.wakeLock.request('screen')
|
||||
document.addEventListener('visibilitychange', this.visibilityChange)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
destroyWakeLock: function() {
|
||||
if (this.wake_lock != null) {
|
||||
this.wake_lock.release()
|
||||
.then(() => {
|
||||
this.wake_lock = null
|
||||
});
|
||||
}
|
||||
|
||||
document.removeEventListener('visibilitychange', this.visibilityChange)
|
||||
},
|
||||
visibilityChange: async function() {
|
||||
if (this.wake_lock != null && document.visibilityState === 'visible') {
|
||||
await this.requestWakeLock()
|
||||
}
|
||||
},
|
||||
loadRecipe: function (recipe_id) {
|
||||
apiLoadRecipe(recipe_id).then((recipe) => {
|
||||
if (window.USER_SERVINGS !== 0) {
|
||||
@ -241,6 +271,9 @@ export default {
|
||||
this.start_time = moment().format("yyyy-MM-DDTHH:mm")
|
||||
}
|
||||
|
||||
|
||||
if(recipe.image === null) this.printReady()
|
||||
|
||||
this.recipe = this.rootrecipe = recipe
|
||||
this.servings = this.servings_cache[this.rootrecipe.id] = recipe.servings
|
||||
this.loading = false
|
||||
@ -267,6 +300,14 @@ export default {
|
||||
this.servings = this.servings_cache?.[e.id] ?? e.servings
|
||||
}
|
||||
},
|
||||
printReady: function(){
|
||||
const template = document.createElement("template");
|
||||
template.id = "printReady";
|
||||
document.body.appendChild(template);
|
||||
},
|
||||
onImgLoad: function(){
|
||||
this.printReady()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@ -131,6 +131,7 @@ export default {
|
||||
let ingredient_list = this.steps
|
||||
.map((x) => x.ingredients)
|
||||
.flat()
|
||||
.filter((x) => (x.food !== null && x.food !== undefined))
|
||||
.map((x) => x.food.id)
|
||||
|
||||
let params = {
|
||||
@ -230,7 +231,7 @@ export default {
|
||||
...i,
|
||||
shop: checked,
|
||||
shopping_status: shopping_status, // possible values: true, false, null
|
||||
category: i.food.supermarket_category?.name,
|
||||
category: i.food?.supermarket_category?.name,
|
||||
shopping_list: shopping.map((x) => {
|
||||
return {
|
||||
mealplan: x?.recipe_mealplan?.name,
|
||||
|
@ -1,19 +1,19 @@
|
||||
{
|
||||
"Import": "Importieren",
|
||||
"import_running": "Import läuft, bitte warten!",
|
||||
"Import_finished": "Import fertig",
|
||||
"Import_finished": "Import abgeschlossen",
|
||||
"View_Recipes": "Rezepte Ansehen",
|
||||
"Information": "Information",
|
||||
"all_fields_optional": "Alle Felder sind optional und können leer gelassen werden.",
|
||||
"convert_internal": "Zu internem Rezept wandeln",
|
||||
"convert_internal": "Zu internem Rezept umwandeln",
|
||||
"Log_Recipe_Cooking": "Kochen protokollieren",
|
||||
"External_Recipe_Image": "Externes Rezept Bild",
|
||||
"External_Recipe_Image": "Externes Rezeptbild",
|
||||
"Add_to_Book": "Zu Buch hinzufügen",
|
||||
"Add_to_Shopping": "Zu Einkaufsliste hinzufügen",
|
||||
"Add_to_Plan": "Zu Plan hinzufügen",
|
||||
"Add_to_Plan": "Zur Planung hinzufügen",
|
||||
"Step_start_time": "Schritt Startzeit",
|
||||
"Select_Book": "Buch wählen",
|
||||
"Recipe_Image": "Rezept Bild",
|
||||
"Select_Book": "Buch auswählen",
|
||||
"Recipe_Image": "Rezeptbild",
|
||||
"Log_Cooking": "Kochen protokollieren",
|
||||
"Proteins": "Proteine",
|
||||
"Fats": "Fette",
|
||||
@ -61,63 +61,63 @@
|
||||
"success_fetching_resource": "Ressource erfolgreich abgerufen!",
|
||||
"Download": "Herunterladen",
|
||||
"Success": "Erfolgreich",
|
||||
"err_fetching_resource": "Ein Fehler trat während dem Abrufen einer Ressource auf!",
|
||||
"err_creating_resource": "Ein Fehler trat während dem Erstellen einer Ressource auf!",
|
||||
"err_updating_resource": "Ein Fehler trat während dem Aktualisieren einer Ressource auf!",
|
||||
"err_fetching_resource": "Beim Abrufen einer Ressource ist ein Fehler aufgetreten!",
|
||||
"err_creating_resource": "Beim Erstellen einer Ressource ist ein Fehler aufgetreten!",
|
||||
"err_updating_resource": "Beim Aktualisieren einer Ressource ist ein Fehler aufgetreten!",
|
||||
"success_creating_resource": "Ressource erfolgreich erstellt!",
|
||||
"success_updating_resource": "Ressource erfolgreich aktualisiert!",
|
||||
"File": "Datei",
|
||||
"Delete": "Löschen",
|
||||
"err_deleting_resource": "Ein Fehler trat während dem Löschen einer Ressource auf!",
|
||||
"err_deleting_resource": "Beim Löschen einer Ressource ist ein Fehler aufgetreten!",
|
||||
"Cancel": "Abbrechen",
|
||||
"success_deleting_resource": "Ressource erfolgreich gelöscht!",
|
||||
"Load_More": "Mehr laden",
|
||||
"Load_More": "Weitere laden",
|
||||
"Ok": "Öffnen",
|
||||
"Link": "Link",
|
||||
"Key_Ctrl": "Strg",
|
||||
"move_title": "Verschieben {type}",
|
||||
"Food": "Essen",
|
||||
"move_title": "{type} verschieben",
|
||||
"Food": "Lebensmittel",
|
||||
"Recipe_Book": "Kochbuch",
|
||||
"delete_title": "Löschen {type}",
|
||||
"create_title": "Neu {type}",
|
||||
"edit_title": "Bearbeiten {type}",
|
||||
"delete_title": "Lösche {type}",
|
||||
"create_title": "{type} erstellen",
|
||||
"edit_title": "{type} bearbeiten",
|
||||
"Name": "Name",
|
||||
"Empty": "Leer",
|
||||
"Key_Shift": "Umschalttaste",
|
||||
"Text": "Text",
|
||||
"Icon": "Icon",
|
||||
"Automation": "Automatisierung",
|
||||
"Ignore_Shopping": "Einkauf Ignorieren",
|
||||
"Ignore_Shopping": "Einkauf ignorieren",
|
||||
"Parameter": "Parameter",
|
||||
"Sort_by_new": "Sortieren nach neueste",
|
||||
"Shopping_Category": "Einkauf Kategorie",
|
||||
"Edit_Food": "Essen bearbeiten",
|
||||
"Move_Food": "Essen verschieben",
|
||||
"New_Food": "Neues Essen",
|
||||
"Hide_Food": "Essen verbergen",
|
||||
"Food_Alias": "Essen Alias",
|
||||
"Sort_by_new": "Nach Neueste sortieren",
|
||||
"Shopping_Category": "Einkaufskategorie",
|
||||
"Edit_Food": "Lebensmittel bearbeiten",
|
||||
"Move_Food": "Lebensmittel verschieben",
|
||||
"New_Food": "Neues Lebensmittel",
|
||||
"Hide_Food": "Lebensmittel verbergen",
|
||||
"Food_Alias": "Lebensmittel Alias",
|
||||
"Unit_Alias": "Einheit Alias",
|
||||
"Keyword_Alias": "Schlagwort Alias",
|
||||
"Delete_Food": "Essen löschen",
|
||||
"No_ID": "Nr. nicht gefunden, Objekt kann nicht gelöscht werden",
|
||||
"Delete_Food": "Lebensmittel löschen",
|
||||
"No_ID": "ID nicht gefunden und kann nicht gelöscht werden.",
|
||||
"create_rule": "und erstelle Automatisierung",
|
||||
"Table_of_Contents": "Inhaltsverzeichnis",
|
||||
"merge_title": "Zusammenführen {type}",
|
||||
"del_confirmation_tree": "Sicher das {source} und alle untergeordneten Objekte gelöscht werden soll?",
|
||||
"warning_feature_beta": "Diese Funktion ist aktuell in einer BETA (Test) Phase. Fehler sind zu erwarten und Änderungen in der Zukunft können die Funktionsweise möglicherweise Verändern oder Daten die mit dieser Funktion zusammen hängen entfernen.",
|
||||
"merge_title": "{type} zusammenführen",
|
||||
"del_confirmation_tree": "Sicher, dass {source} und alle untergeordneten Objekte gelöscht werden sollen?",
|
||||
"warning_feature_beta": "Diese Funktion ist aktuell in einer BETA (Test) Phase. Es ist sowohl mit Fehlern, als auch mit zukünftigen Änderungen der Funktionsweise zu rechnen, wodurch es bei Verwendung entsprechender Funktionen zu Datenverlust kommen kann.",
|
||||
"Edit_Keyword": "Schlagwort bearbeiten",
|
||||
"Move_Keyword": "Schlagwort verschieben",
|
||||
"Merge_Keyword": "Schlagworte zusammenführen",
|
||||
"Hide_Keywords": "Schlagworte verstecken",
|
||||
"Meal_Plan_Days": "Zukünftige Pläne",
|
||||
"Hide_Keywords": "Schlagwort verstecken",
|
||||
"Meal_Plan_Days": "Zukünftige Essenspläne",
|
||||
"Description": "Beschreibung",
|
||||
"Create_New_Shopping Category": "Erstelle neue Einkaufs Kategorie",
|
||||
"Create_New_Shopping Category": "Neue Einkaufskategorie erstellen",
|
||||
"Automate": "Automatisieren",
|
||||
"Type": "Typ",
|
||||
"and_up": "& Hoch",
|
||||
"Unrated": "Unbewertet",
|
||||
"Shopping_list": "Einkaufsliste",
|
||||
"step_time_minutes": "Schritt Zeit in Minuten",
|
||||
"step_time_minutes": "Schritt Dauer in Minuten",
|
||||
"Save_and_View": "Speichern & Ansehen",
|
||||
"Edit_Recipe": "Rezept bearbeiten",
|
||||
"Hide_Recipes": "Rezepte verstecken",
|
||||
@ -128,7 +128,7 @@
|
||||
"Copy_template_reference": "Template Referenz kopieren",
|
||||
"Step_Type": "Schritt Typ",
|
||||
"Make_Header": "In Überschrift wandeln",
|
||||
"Make_Ingredient": "In Zutat wandeln",
|
||||
"Make_Ingredient": "In Zutat umwandeln",
|
||||
"Enable_Amount": "Menge aktivieren",
|
||||
"Disable_Amount": "Menge deaktivieren",
|
||||
"Add_Step": "Schritt hinzufügen",
|
||||
@ -152,9 +152,9 @@
|
||||
"Unit": "Einheit",
|
||||
"No_Results": "Keine Ergebnisse",
|
||||
"New_Unit": "Neue Einheit",
|
||||
"Create_New_Food": "Neues Essen",
|
||||
"Create_New_Keyword": "Neues Schlagwort",
|
||||
"Create_New_Unit": "Neue Einheit",
|
||||
"Create_New_Food": "Neues Lebensmittel hinzufügen",
|
||||
"Create_New_Keyword": "Neues Schlagwort hinzufügen",
|
||||
"Create_New_Unit": "Neue Einheit hinzufügen",
|
||||
"Instructions": "Anleitung",
|
||||
"Time": "Zeit",
|
||||
"New_Keyword": "Neues Schlagwort",
|
||||
@ -169,7 +169,7 @@
|
||||
"Week": "Woche",
|
||||
"Month": "Monat",
|
||||
"Year": "Jahr",
|
||||
"Drag_Here_To_Delete": "Ziehen zum Löschen",
|
||||
"Drag_Here_To_Delete": "Hierher ziehen zum Löschen",
|
||||
"Select_File": "Datei auswählen",
|
||||
"Image": "Bild",
|
||||
"Planner": "Planer",
|
||||
@ -180,7 +180,7 @@
|
||||
"Meal_Type_Required": "Mahlzeitentyp ist erforderlich",
|
||||
"Remove_nutrition_recipe": "Nährwerte aus Rezept löschen",
|
||||
"Add_nutrition_recipe": "Nährwerte zu Rezept hinzufügen",
|
||||
"Title_or_Recipe_Required": "Titel oder Rezept benötigt",
|
||||
"Title_or_Recipe_Required": "Auswahl von Titel oder Rezept erforderlich",
|
||||
"Next_Day": "Tag vor",
|
||||
"Previous_Day": "Tag zurück",
|
||||
"Edit_Meal_Plan_Entry": "Eintrag bearbeiten",
|
||||
@ -189,7 +189,7 @@
|
||||
"Color": "Farbe",
|
||||
"New_Meal_Type": "Neue Mahlzeit",
|
||||
"Periods": "Zeiträume",
|
||||
"Plan_Show_How_Many_Periods": "Wie viele Zeiträume angezeigt werden",
|
||||
"Plan_Show_How_Many_Periods": "Anzahl der anzuzeigenden Zeiträume",
|
||||
"Starting_Day": "Wochenbeginn am",
|
||||
"Meal_Type": "Mahlzeit",
|
||||
"Meal_Types": "Mahlzeiten",
|
||||
@ -199,9 +199,9 @@
|
||||
"Added_To_Shopping_List": "Zur Einkaufsliste hinzugefügt",
|
||||
"Export_To_ICal": "Export als .ics",
|
||||
"Cannot_Add_Notes_To_Shopping": "Notizen können nicht auf die Einkaufsliste gesetzt werden",
|
||||
"Shopping_List_Empty": "Deine Einkaufsliste ist aktuell leer, Einträge können via dem Kontextmenü hinzugefügt werden (Rechtsklick auf einen Eintrag oder Klick auf das Menü-Icon)",
|
||||
"Next_Period": "Zeitraum vor",
|
||||
"Previous_Period": "Zeitraum zurück",
|
||||
"Shopping_List_Empty": "Deine Einkaufsliste ist aktuell leer. Einträge können über das Kontextmenü hinzugefügt werden (Rechtsklick auf einen Eintrag oder Klick auf das Menü-Icon)",
|
||||
"Next_Period": "nächster Zeitraum",
|
||||
"Previous_Period": "voriger Zeitraum",
|
||||
"Current_Period": "Aktueller Zeitraum",
|
||||
"New_Cookbook": "Neues Kochbuch",
|
||||
"Coming_Soon": "Bald verfügbar",
|
||||
@ -212,7 +212,7 @@
|
||||
"IgnoreThis": "{food} nicht automatisch zur Einkaufsliste hinzufügen",
|
||||
"shopping_auto_sync": "Automatische Synchronisierung",
|
||||
"shopping_share_desc": "Benutzer sehen all Einträge, die du zur Einkaufsliste hinzufügst. Sie müssen dich hinzufügen, damit du Ihre Einträge sehen kannst.",
|
||||
"IgnoredFood": "{food} beim nächsten Einkauf ignorieren.",
|
||||
"IgnoredFood": "{food} nicht für Einkauf geplant.",
|
||||
"Add_Servings_to_Shopping": "{servings} Portionen zum Einkauf hinzufügen",
|
||||
"Inherit": "Vererben",
|
||||
"InheritFields": "Feldwerte vererben",
|
||||
@ -228,23 +228,23 @@
|
||||
"mealplan_autoexclude_onhand": "Ignoriere vorhandene Zutaten",
|
||||
"mealplan_autoinclude_related": "Füge verwandte Rezepte hinzu",
|
||||
"default_delay": "Standard Zeit des Verzögerns",
|
||||
"Added_by": "Hinzugefügt von",
|
||||
"Added_by": "Hinzugefügt durch",
|
||||
"AddToShopping": "Zur Einkaufsliste hinzufügen",
|
||||
"FoodOnHand": "Sie haben {food} vorrätig.",
|
||||
"DeleteShoppingConfirm": "Möchten Sie wirklich alle {food} von der Einkaufsliste zu entfernen?",
|
||||
"err_moving_resource": "Während des Verschiebens einer Resource ist ein Fehler aufgetreten!",
|
||||
"err_merging_resource": "Beim Zusammenführen einer Ressource ist ein Fehler aufgetreten!",
|
||||
"DeleteShoppingConfirm": "Möchten Sie wirklich alle {food} von der Einkaufsliste entfernen?",
|
||||
"err_moving_resource": "Beim Verschieben einer Resource ist ein Fehler aufgetreten!",
|
||||
"err_merging_resource": "Beim Zusammenführen einer Ressource trat ein Fehler auf!",
|
||||
"success_moving_resource": "Ressource wurde erfolgreich verschoben!",
|
||||
"success_merging_resource": "Ressource wurde erfolgreich zusammengeführt!",
|
||||
"success_merging_resource": "Zusammenführung einer Ressource war erfolgreich!",
|
||||
"Shopping_Categories": "Einkaufskategorien",
|
||||
"Added_on": "Hinzugefügt am",
|
||||
"IngredientInShopping": "Diese Zutat befindet sich in Ihrer Einkaufsliste.",
|
||||
"NotInShopping": "{food} ist nicht in Ihrer Einkaufsliste.",
|
||||
"IngredientInShopping": "Diese Zutat befindet sich auf Ihrer Einkaufsliste.",
|
||||
"NotInShopping": "{food} befindet sich nicht auf Ihrer Einkaufsliste.",
|
||||
"OnHand": "Aktuell vorrätig",
|
||||
"FoodNotOnHand": "Sie haben kein {food} vorrätig.",
|
||||
"Undefined": "nicht definiert",
|
||||
"AddFoodToShopping": "{food} zur Einkaufsliste hinzufügen",
|
||||
"RemoveFoodFromShopping": "{food} von der Einkaufsliste entfernen",
|
||||
"FoodNotOnHand": "Sie habe {food} nicht vorrätig.",
|
||||
"Undefined": "undefiniert",
|
||||
"AddFoodToShopping": "Fügen Sie {food} zur Einkaufsliste hinzu",
|
||||
"RemoveFoodFromShopping": "{food} von der Einkaufsliste löschen",
|
||||
"Search Settings": "Sucheinstellungen",
|
||||
"shopping_auto_sync_desc": "Bei 0 wird Auto-Sync deaktiviert. Beim Betrachten einer Einkaufsliste wird die Liste alle gesetzten Sekunden aktualisiert, um mögliche Änderungen anderer zu zeigen. Nützlich, wenn mehrere Personen einkaufen und mobile Daten nutzen.",
|
||||
"MoveCategory": "Verschieben nach: ",
|
||||
@ -252,7 +252,7 @@
|
||||
"Pin": "Pin",
|
||||
"mark_complete": "Vollständig markieren",
|
||||
"shopping_add_onhand_desc": "Markiere Lebensmittel als \"Vorrätig\", wenn von der Einkaufsliste abgehakt wurden.",
|
||||
"left_handed": "Linkshändermodus",
|
||||
"left_handed": "Linkshänder-Modus",
|
||||
"left_handed_help": "Optimiert die Benutzeroberfläche für die Bedienung mit der linken Hand.",
|
||||
"FoodInherit": "Lebensmittel vererbbare Felder",
|
||||
"SupermarketCategoriesOnly": "Nur Supermarkt Kategorien",
|
||||
@ -291,5 +291,12 @@
|
||||
"remember_search": "Suchbegriff merken",
|
||||
"remember_hours": "Stunden zu erinnern",
|
||||
"tree_select": "Baum-Auswahl verwenden",
|
||||
"CountMore": "...+{count} weitere"
|
||||
"CountMore": "...+{count} weitere",
|
||||
"ignore_shopping_help": "Füge Zutat nie zur Einkaufsliste hinzu (z.B. Wasser)",
|
||||
"OnHand_help": "Lebensmittel ist \"Vorrätig\" und wird nicht automatisch zur Einkaufsliste hinzugefügt.",
|
||||
"shopping_category_help": "Supermärkte können nach Einkaufskategorien geordnet und gefiltert werden, je nachdem, wie die Gänge angeordnet sind.",
|
||||
"Foods": "Lebensmittel",
|
||||
"food_recipe_help": "Wird ein Rezept hier verknüpft, wird diese Verknüpfung in allen anderen Rezepten übernommen, die dieses Lebensmittel beinhaltet",
|
||||
"review_shopping": "Überprüfe die Einkaufsliste vor dem Speichern",
|
||||
"view_recipe": "Rezept anschauen"
|
||||
}
|
||||
|
@ -284,5 +284,18 @@
|
||||
"related_recipes": "Powiązane przepisy",
|
||||
"today_recipes": "Dzisiejsze przepisy",
|
||||
"Search Settings": "Ustawienia wyszukiwania",
|
||||
"Pin": "Pin"
|
||||
"Pin": "Pin",
|
||||
"left_handed_help": "Zoptymalizuje interfejs użytkownika do użytku lewą ręką.",
|
||||
"food_recipe_help": "Powiązanie tutaj przepisu będzie skutkowało połączenie przepisu z każdym innym przepisem, który używa tego jedzenia",
|
||||
"Foods": "Żywność",
|
||||
"view_recipe": "Zobacz przepis",
|
||||
"left_handed": "Tryb dla leworęcznych",
|
||||
"OnHand_help": "Żywność jest w spiżarni i nie zostanie automatycznie dodana do listy zakupów.",
|
||||
"ignore_shopping_help": "Nigdy nie dodawaj żywności do listy zakupów (np. wody)",
|
||||
"shopping_category_help": "Z supermarketów można zamawiać i filtrować według kategorii zakupów zgodnie z układem alejek.",
|
||||
"review_shopping": "Przejrzyj wpisy zakupów przed zapisaniem",
|
||||
"sql_debug": "Debugowanie SQL",
|
||||
"remember_search": "Zapamiętaj wyszukiwanie",
|
||||
"remember_hours": "Godziny do zapamiętania",
|
||||
"tree_select": "Użyj drzewa wyboru"
|
||||
}
|
||||
|
@ -229,6 +229,73 @@ export interface CustomFilterShared {
|
||||
*/
|
||||
username?: string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ExportLog
|
||||
*/
|
||||
export interface ExportLog {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
id?: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
type: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
msg?: string;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
running?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
total_recipes?: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
exported_recipes?: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
cache_duration?: number;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
possibly_not_expired?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
created_by?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof ExportLog
|
||||
*/
|
||||
created_at?: string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
@ -331,6 +398,12 @@ export interface Food {
|
||||
* @memberof Food
|
||||
*/
|
||||
substitute_onhand?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Array<FoodInheritFields>}
|
||||
* @memberof Food
|
||||
*/
|
||||
child_inherit_fields?: Array<FoodInheritFields> | null;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -776,6 +849,12 @@ export interface IngredientFood {
|
||||
* @memberof IngredientFood
|
||||
*/
|
||||
substitute_onhand?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Array<FoodInheritFields>}
|
||||
* @memberof IngredientFood
|
||||
*/
|
||||
child_inherit_fields?: Array<FoodInheritFields> | null;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -839,6 +918,37 @@ export interface InlineResponse2001 {
|
||||
*/
|
||||
results?: Array<Food>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface InlineResponse20010
|
||||
*/
|
||||
export interface InlineResponse20010 {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof InlineResponse20010
|
||||
*/
|
||||
count?: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof InlineResponse20010
|
||||
*/
|
||||
next?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof InlineResponse20010
|
||||
*/
|
||||
previous?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<ViewLog>}
|
||||
* @memberof InlineResponse20010
|
||||
*/
|
||||
results?: Array<ViewLog>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
@ -896,10 +1006,10 @@ export interface InlineResponse2003 {
|
||||
previous?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<Keyword>}
|
||||
* @type {Array<ExportLog>}
|
||||
* @memberof InlineResponse2003
|
||||
*/
|
||||
results?: Array<Keyword>;
|
||||
results?: Array<ExportLog>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -927,10 +1037,10 @@ export interface InlineResponse2004 {
|
||||
previous?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<RecipeOverview>}
|
||||
* @type {Array<Keyword>}
|
||||
* @memberof InlineResponse2004
|
||||
*/
|
||||
results?: Array<RecipeOverview>;
|
||||
results?: Array<Keyword>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -958,10 +1068,10 @@ export interface InlineResponse2005 {
|
||||
previous?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<Step>}
|
||||
* @type {Array<RecipeOverview>}
|
||||
* @memberof InlineResponse2005
|
||||
*/
|
||||
results?: Array<Step>;
|
||||
results?: Array<RecipeOverview>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -989,10 +1099,10 @@ export interface InlineResponse2006 {
|
||||
previous?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<SupermarketCategoryRelation>}
|
||||
* @type {Array<Step>}
|
||||
* @memberof InlineResponse2006
|
||||
*/
|
||||
results?: Array<SupermarketCategoryRelation>;
|
||||
results?: Array<Step>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -1020,10 +1130,10 @@ export interface InlineResponse2007 {
|
||||
previous?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<SyncLog>}
|
||||
* @type {Array<SupermarketCategoryRelation>}
|
||||
* @memberof InlineResponse2007
|
||||
*/
|
||||
results?: Array<SyncLog>;
|
||||
results?: Array<SupermarketCategoryRelation>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -1051,10 +1161,10 @@ export interface InlineResponse2008 {
|
||||
previous?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<Unit>}
|
||||
* @type {Array<SyncLog>}
|
||||
* @memberof InlineResponse2008
|
||||
*/
|
||||
results?: Array<Unit>;
|
||||
results?: Array<SyncLog>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -1082,10 +1192,10 @@ export interface InlineResponse2009 {
|
||||
previous?: string | null;
|
||||
/**
|
||||
*
|
||||
* @type {Array<ViewLog>}
|
||||
* @type {Array<Unit>}
|
||||
* @memberof InlineResponse2009
|
||||
*/
|
||||
results?: Array<ViewLog>;
|
||||
results?: Array<Unit>;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@ -3429,6 +3539,39 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
createExportLog: async (exportLog?: ExportLog, options: any = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/export-log/`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(exportLog, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {Food} [food]
|
||||
@ -4300,6 +4443,39 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
destroyExportLog: async (id: string, options: any = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'id' is not null or undefined
|
||||
assertParamExists('destroyExportLog', 'id', id)
|
||||
const localVarPath = `/api/export-log/{id}/`
|
||||
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'DELETE', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
@ -5194,6 +5370,45 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @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}
|
||||
*/
|
||||
listExportLogs: async (page?: number, pageSize?: number, options: any = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/api/export-log/`;
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
if (page !== undefined) {
|
||||
localVarQueryParameter['page'] = page;
|
||||
}
|
||||
|
||||
if (pageSize !== undefined) {
|
||||
localVarQueryParameter['page_size'] = pageSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
@ -6551,6 +6766,43 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
partialUpdateExportLog: async (id: string, exportLog?: ExportLog, options: any = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'id' is not null or undefined
|
||||
assertParamExists('partialUpdateExportLog', 'id', id)
|
||||
const localVarPath = `/api/export-log/{id}/`
|
||||
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'PATCH', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(exportLog, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -7543,6 +7795,39 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
retrieveExportLog: async (id: string, options: any = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'id' is not null or undefined
|
||||
assertParamExists('retrieveExportLog', 'id', id)
|
||||
const localVarPath = `/api/export-log/{id}/`
|
||||
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
@ -8599,6 +8884,43 @@ export const ApiApiAxiosParamCreator = function (configuration?: Configuration)
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
updateExportLog: async (id: string, exportLog?: ExportLog, options: any = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'id' is not null or undefined
|
||||
assertParamExists('updateExportLog', 'id', id)
|
||||
const localVarPath = `/api/export-log/{id}/`
|
||||
.replace(`{${"id"}}`, encodeURIComponent(String(id)));
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||
let baseOptions;
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions;
|
||||
}
|
||||
|
||||
const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
|
||||
const localVarHeaderParameter = {} as any;
|
||||
const localVarQueryParameter = {} as any;
|
||||
|
||||
|
||||
|
||||
localVarHeaderParameter['Content-Type'] = 'application/json';
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter, options.query);
|
||||
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(exportLog, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -9485,6 +9807,16 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.createCustomFilter(customFilter, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async createExportLog(exportLog?: ExportLog, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ExportLog>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.createExportLog(exportLog, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {Food} [food]
|
||||
@ -9748,6 +10080,16 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.destroyCustomFilter(id, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async destroyExportLog(id: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.destroyExportLog(id, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -10017,6 +10359,17 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listCustomFilters(options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @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 listExportLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2003>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listExportLogs(page, pageSize, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {*} [options] Override http request option.
|
||||
@ -10070,7 +10423,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async listKeywords(query?: string, root?: number, tree?: number, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2003>> {
|
||||
async listKeywords(query?: string, root?: number, tree?: number, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2004>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listKeywords(query, root, tree, page, pageSize, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
@ -10141,7 +10494,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async listRecipes(query?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2004>> {
|
||||
async listRecipes(query?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2005>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listRecipes(query, keywords, keywordsOr, keywordsAnd, keywordsOrNot, keywordsAndNot, foods, foodsOr, foodsAnd, foodsOrNot, foodsAndNot, units, rating, books, booksOr, booksAnd, booksOrNot, booksAndNot, internal, random, _new, timescooked, lastcooked, makenow, page, pageSize, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
@ -10184,7 +10537,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async listSteps(recipe?: number, query?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2005>> {
|
||||
async listSteps(recipe?: number, query?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2006>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listSteps(recipe, query, page, pageSize, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
@ -10204,7 +10557,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<InlineResponse2006>> {
|
||||
async listSupermarketCategoryRelations(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2007>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listSupermarketCategoryRelations(page, pageSize, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
@ -10233,7 +10586,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async listSyncLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2007>> {
|
||||
async listSyncLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2008>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listSyncLogs(page, pageSize, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
@ -10254,7 +10607,7 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async listUnits(query?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2008>> {
|
||||
async listUnits(query?: string, page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse2009>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listUnits(query, page, pageSize, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
@ -10292,7 +10645,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<InlineResponse2009>> {
|
||||
async listViewLogs(page?: number, pageSize?: number, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<InlineResponse20010>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.listViewLogs(page, pageSize, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
@ -10400,6 +10753,17 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.partialUpdateCustomFilter(id, customFilter, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async partialUpdateExportLog(id: string, exportLog?: ExportLog, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ExportLog>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.partialUpdateExportLog(id, exportLog, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -10695,6 +11059,16 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.retrieveCustomFilter(id, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async retrieveExportLog(id: string, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ExportLog>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.retrieveExportLog(id, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -11011,6 +11385,17 @@ export const ApiApiFp = function(configuration?: Configuration) {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.updateCustomFilter(id, customFilter, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async updateExportLog(id: string, exportLog?: ExportLog, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ExportLog>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.updateExportLog(id, exportLog, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -11302,6 +11687,15 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
createCustomFilter(customFilter?: CustomFilter, options?: any): AxiosPromise<CustomFilter> {
|
||||
return localVarFp.createCustomFilter(customFilter, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
createExportLog(exportLog?: ExportLog, options?: any): AxiosPromise<ExportLog> {
|
||||
return localVarFp.createExportLog(exportLog, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {Food} [food]
|
||||
@ -11539,6 +11933,15 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
destroyCustomFilter(id: string, options?: any): AxiosPromise<void> {
|
||||
return localVarFp.destroyCustomFilter(id, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
destroyExportLog(id: string, options?: any): AxiosPromise<void> {
|
||||
return localVarFp.destroyExportLog(id, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -11781,6 +12184,16 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
listCustomFilters(options?: any): AxiosPromise<Array<CustomFilter>> {
|
||||
return localVarFp.listCustomFilters(options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @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}
|
||||
*/
|
||||
listExportLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2003> {
|
||||
return localVarFp.listExportLogs(page, pageSize, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {*} [options] Override http request option.
|
||||
@ -11830,7 +12243,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listKeywords(query?: string, root?: number, tree?: number, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2003> {
|
||||
listKeywords(query?: string, root?: number, tree?: number, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2004> {
|
||||
return localVarFp.listKeywords(query, root, tree, page, pageSize, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
@ -11896,7 +12309,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listRecipes(query?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2004> {
|
||||
listRecipes(query?: string, keywords?: number, keywordsOr?: number, keywordsAnd?: number, keywordsOrNot?: number, keywordsAndNot?: number, foods?: number, foodsOr?: number, foodsAnd?: number, foodsOrNot?: number, foodsAndNot?: number, units?: number, rating?: number, books?: string, booksOr?: number, booksAnd?: number, booksOrNot?: number, booksAndNot?: number, internal?: string, random?: string, _new?: string, timescooked?: number, lastcooked?: string, makenow?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2005> {
|
||||
return localVarFp.listRecipes(query, keywords, keywordsOr, keywordsAnd, keywordsOrNot, keywordsAndNot, foods, foodsOr, foodsAnd, foodsOrNot, foodsAndNot, units, rating, books, booksOr, booksAnd, booksOrNot, booksAndNot, internal, random, _new, timescooked, lastcooked, makenow, page, pageSize, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
@ -11935,7 +12348,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listSteps(recipe?: number, query?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2005> {
|
||||
listSteps(recipe?: number, query?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2006> {
|
||||
return localVarFp.listSteps(recipe, query, page, pageSize, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
@ -11953,7 +12366,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listSupermarketCategoryRelations(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2006> {
|
||||
listSupermarketCategoryRelations(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2007> {
|
||||
return localVarFp.listSupermarketCategoryRelations(page, pageSize, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
@ -11979,7 +12392,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listSyncLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2007> {
|
||||
listSyncLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2008> {
|
||||
return localVarFp.listSyncLogs(page, pageSize, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
@ -11998,7 +12411,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listUnits(query?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2008> {
|
||||
listUnits(query?: string, page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2009> {
|
||||
return localVarFp.listUnits(query, page, pageSize, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
@ -12032,7 +12445,7 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
listViewLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse2009> {
|
||||
listViewLogs(page?: number, pageSize?: number, options?: any): AxiosPromise<InlineResponse20010> {
|
||||
return localVarFp.listViewLogs(page, pageSize, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
@ -12130,6 +12543,16 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
partialUpdateCustomFilter(id: string, customFilter?: CustomFilter, options?: any): AxiosPromise<CustomFilter> {
|
||||
return localVarFp.partialUpdateCustomFilter(id, customFilter, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
partialUpdateExportLog(id: string, exportLog?: ExportLog, options?: any): AxiosPromise<ExportLog> {
|
||||
return localVarFp.partialUpdateExportLog(id, exportLog, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -12398,6 +12821,15 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
retrieveCustomFilter(id: string, options?: any): AxiosPromise<CustomFilter> {
|
||||
return localVarFp.retrieveCustomFilter(id, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
retrieveExportLog(id: string, options?: any): AxiosPromise<ExportLog> {
|
||||
return localVarFp.retrieveExportLog(id, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -12683,6 +13115,16 @@ export const ApiApiFactory = function (configuration?: Configuration, basePath?:
|
||||
updateCustomFilter(id: string, customFilter?: CustomFilter, options?: any): AxiosPromise<CustomFilter> {
|
||||
return localVarFp.updateCustomFilter(id, customFilter, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
updateExportLog(id: string, exportLog?: ExportLog, options?: any): AxiosPromise<ExportLog> {
|
||||
return localVarFp.updateExportLog(id, exportLog, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -12960,6 +13402,17 @@ export class ApiApi extends BaseAPI {
|
||||
return ApiApiFp(this.configuration).createCustomFilter(customFilter, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof ApiApi
|
||||
*/
|
||||
public createExportLog(exportLog?: ExportLog, options?: any) {
|
||||
return ApiApiFp(this.configuration).createExportLog(exportLog, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Food} [food]
|
||||
@ -13249,6 +13702,17 @@ export class ApiApi extends BaseAPI {
|
||||
return ApiApiFp(this.configuration).destroyCustomFilter(id, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof ApiApi
|
||||
*/
|
||||
public destroyExportLog(id: string, options?: any) {
|
||||
return ApiApiFp(this.configuration).destroyExportLog(id, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -13545,6 +14009,18 @@ export class ApiApi extends BaseAPI {
|
||||
return ApiApiFp(this.configuration).listCustomFilters(options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @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 listExportLogs(page?: number, pageSize?: number, options?: any) {
|
||||
return ApiApiFp(this.configuration).listExportLogs(page, pageSize, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} [options] Override http request option.
|
||||
@ -13962,6 +14438,18 @@ export class ApiApi extends BaseAPI {
|
||||
return ApiApiFp(this.configuration).partialUpdateCustomFilter(id, customFilter, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof ApiApi
|
||||
*/
|
||||
public partialUpdateExportLog(id: string, exportLog?: ExportLog, options?: any) {
|
||||
return ApiApiFp(this.configuration).partialUpdateExportLog(id, exportLog, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -14284,6 +14772,17 @@ export class ApiApi extends BaseAPI {
|
||||
return ApiApiFp(this.configuration).retrieveCustomFilter(id, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof ApiApi
|
||||
*/
|
||||
public retrieveExportLog(id: string, options?: any) {
|
||||
return ApiApiFp(this.configuration).retrieveExportLog(id, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
@ -14631,6 +15130,18 @@ export class ApiApi extends BaseAPI {
|
||||
return ApiApiFp(this.configuration).updateCustomFilter(id, customFilter, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this export log.
|
||||
* @param {ExportLog} [exportLog]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof ApiApi
|
||||
*/
|
||||
public updateExportLog(id: string, exportLog?: ExportLog, options?: any) {
|
||||
return ApiApiFp(this.configuration).updateExportLog(id, exportLog, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} id A unique integer value identifying this food.
|
||||
|
@ -17,6 +17,14 @@ const pages = {
|
||||
entry: "./src/apps/ImportResponseView/main.js",
|
||||
chunks: ["chunk-vendors"],
|
||||
},
|
||||
export_response_view: {
|
||||
entry: "./src/apps/ExportResponseView/main.js",
|
||||
chunks: ["chunk-vendors"],
|
||||
},
|
||||
export_view: {
|
||||
entry: "./src/apps/ExportView/main.js",
|
||||
chunks: ["chunk-vendors"],
|
||||
},
|
||||
supermarket_view: {
|
||||
entry: "./src/apps/SupermarketView/main.js",
|
||||
chunks: ["chunk-vendors"],
|
||||
|
Reference in New Issue
Block a user