Merge branch 'develop' of https://github.com/vabene1111/recipes into develop
@@ -5,26 +5,26 @@ DEBUG=0
|
||||
# hosts the application can run under e.g. recipes.mydomain.com,cooking.mydomain.com,...
|
||||
ALLOWED_HOSTS=*
|
||||
|
||||
# random secret key, use for example base64 /dev/urandom | head -c50 to generate one
|
||||
# random secret key, use for example `base64 /dev/urandom | head -c50` to generate one
|
||||
SECRET_KEY=
|
||||
|
||||
# your default timezone
|
||||
# your default timezone See https://timezonedb.com/time-zones for a list of timezones
|
||||
TIMEZONE=Europe/Berlin
|
||||
|
||||
# add only a database password if you want to run with the default postgres, otherwise change settings accordingly
|
||||
DB_ENGINE=django.db.backends.postgresql
|
||||
POSTGRES_HOST=db_recipes
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_USER=djangodb
|
||||
POSTGRES_USER=djangouser
|
||||
POSTGRES_PASSWORD=
|
||||
POSTGRES_DB=djangodb
|
||||
|
||||
# the default value for the user preference 'fractions' (enable/disable fraction support)
|
||||
# when unset: 0 (disabled)
|
||||
# default: disabled=0
|
||||
FRACTION_PREF_DEFAULT=0
|
||||
|
||||
# the default value for the user preference 'comments' (enable/disable commenting system)
|
||||
# when unset: 1 (true)
|
||||
# default comments enabled=1
|
||||
COMMENT_PREF_DEFAULT=1
|
||||
|
||||
# Users can set a amount of time after which the shopping list is refreshed when they are in viewing mode
|
||||
@@ -47,13 +47,13 @@ SHOPPING_MIN_AUTOSYNC_INTERVAL=5
|
||||
# when unset: 1 (true) - this is temporary until an appropriate amount of time has passed for everyone to migrate
|
||||
GUNICORN_MEDIA=0
|
||||
|
||||
# allow authentication via reverse proxy (e.g. authelia), leave of if you dont know what you are doing
|
||||
# allow authentication via reverse proxy (e.g. authelia), leave off if you dont know what you are doing
|
||||
# see docs for more information https://vabene1111.github.io/recipes/features/authentication/
|
||||
# when unset: 0 (false)
|
||||
REVERSE_PROXY_AUTH=0
|
||||
|
||||
|
||||
# allows you to setup o auth providers
|
||||
# allows you to setup OAuth providers
|
||||
# see docs for more information https://vabene1111.github.io/recipes/features/authentication/
|
||||
# SOCIAL_PROVIDERS = allauth.socialaccount.providers.github, allauth.socialaccount.providers.nextcloud,
|
||||
|
||||
|
||||
3
.idea/dictionaries/vabene1111_PC.xml
generated
@@ -2,9 +2,12 @@
|
||||
<dictionary name="vabene1111-PC">
|
||||
<words>
|
||||
<w>autosync</w>
|
||||
<w>chowdown</w>
|
||||
<w>csrftoken</w>
|
||||
<w>gunicorn</w>
|
||||
<w>ical</w>
|
||||
<w>mealie</w>
|
||||
<w>safron</w>
|
||||
<w>traefik</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
||||
36
README.md
@@ -1,13 +1,27 @@
|
||||
# Recipes
|
||||

|
||||

|
||||

|
||||

|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://app.tandoor.dev"><img src="https://github.com/vabene1111/recipes/raw/develop/docs/logo_color.svg" height="256px" width="256px"></a>
|
||||
<br>
|
||||
Tandoor Recipes
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
Recipes is a Django application to manage, tag and search recipes using either built-in models or
|
||||
external storage providers hosting PDF's, images or other files.
|
||||
<h4 align="center">The recipe manager that allows you to manage your ever growing collection of digital recipes.</h4>
|
||||
|
||||
[Installation Instructions](https://vabene1111.github.io/recipes/install/docker/) - [Documentation](https://vabene1111.github.io/recipes/) - [More (slightly outdated) Screenshots](https://imgur.com/a/V01151p)
|
||||
<p align="center">
|
||||
|
||||
<img src="https://github.com/vabene1111/recipes/workflows/Continous%20Integration/badge.svg?branch=develop" >
|
||||
<img src="https://img.shields.io/github/stars/vabene1111/recipes" >
|
||||
<img src="https://img.shields.io/github/forks/vabene1111/recipes" >
|
||||
<img src="https://img.shields.io/docker/pulls/vabene1111/recipes" >
|
||||
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://docs.tandoor.dev/install/docker/" target="_blank" rel="noopener noreferrer">Installation</a> •
|
||||
<a href="https://docs.tandoor.dev/" target="_blank" rel="noopener noreferrer">Documentation</a> •
|
||||
<a href="https://app.tandoor.dev/" target="_blank" rel="noopener noreferrer">Demo</a>
|
||||
</p>
|
||||
|
||||

|
||||
|
||||
@@ -32,14 +46,10 @@ external storage providers hosting PDF's, images or other files.
|
||||
This application is meant for people with a collection of recipes they want to share with family and friends or simply
|
||||
store them in a nicely organized way. A basic permission system exists but this application is not meant to be run as
|
||||
a public page.
|
||||
Documentation can be found [here](https://github.com/vabene1111/recipes/wiki).
|
||||
Documentation can be found [here](https://docs.tandoor.dev/).
|
||||
|
||||
While this application has been around for a while and is actively used by many (including myself), it is still considered
|
||||
**beta** software that has a lot of rough edges and unpolished parts.
|
||||
|
||||
## Documentation
|
||||
Please refer to the [documentation](https://vabene1111.github.io/recipes/) for everything you need to know.
|
||||
|
||||
## License
|
||||
|
||||
Beginning with version 0.10.0 the code in this repository is licensed under the [GNU AGPL v3](https://www.gnu.org/licenses/agpl-3.0.de.html) license with an
|
||||
|
||||
@@ -135,8 +135,14 @@ class ImportExportBase(forms.Form):
|
||||
DEFAULT = 'DEFAULT'
|
||||
PAPRIKA = 'PAPRIKA'
|
||||
NEXTCLOUD = 'NEXTCLOUD'
|
||||
MEALIE = 'MEALIE'
|
||||
CHOWDOWN = 'CHOWDOWN'
|
||||
SAFRON = 'SAFRON'
|
||||
|
||||
type = forms.ChoiceField(choices=((DEFAULT, _('Default')), (PAPRIKA, _('Paprika')), (NEXTCLOUD, _('Nextcloud Cookbook')),))
|
||||
type = forms.ChoiceField(choices=(
|
||||
(DEFAULT, _('Default')), (PAPRIKA, 'Paprika'), (NEXTCLOUD, 'Nextcloud Cookbook'),
|
||||
(MEALIE, 'Mealie'), (CHOWDOWN, 'Chowdown'), (SAFRON, 'Safron'),
|
||||
))
|
||||
|
||||
|
||||
class ImportForm(ImportExportBase):
|
||||
|
||||
@@ -28,7 +28,7 @@ def parse_amount(x):
|
||||
and (
|
||||
x[end] in string.digits
|
||||
or (
|
||||
(x[end] == '.' or x[end] == ',')
|
||||
(x[end] == '.' or x[end] == ',' or x[end] == '/')
|
||||
and end + 1 < len(x)
|
||||
and x[end + 1] in string.digits
|
||||
)
|
||||
@@ -36,6 +36,9 @@ def parse_amount(x):
|
||||
):
|
||||
end += 1
|
||||
if end > 0:
|
||||
if "/" in x[:end]:
|
||||
amount = parse_fraction(x[:end])
|
||||
else:
|
||||
amount = float(x[:end].replace(',', '.'))
|
||||
else:
|
||||
amount = parse_fraction(x[0])
|
||||
|
||||
@@ -224,7 +224,7 @@ def find_recipe_json(ld_json, url):
|
||||
ld_json['servings'] = int(re.findall(r'\b\d+\b', ld_json['recipeYield'])[0])
|
||||
except Exception as e:
|
||||
print(e)
|
||||
ld_json['servings'] = 0
|
||||
ld_json['servings'] = 1
|
||||
|
||||
for key in list(ld_json):
|
||||
if key not in [
|
||||
|
||||
79
cookbook/integration/chowdown.py
Normal file
@@ -0,0 +1,79 @@
|
||||
import json
|
||||
import re
|
||||
from io import BytesIO
|
||||
from zipfile import ZipFile
|
||||
|
||||
from cookbook.helper.ingredient_parser import parse
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Food, Unit, Ingredient, Keyword
|
||||
|
||||
|
||||
class Chowdown(Integration):
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
print("testing", zip_info_object.filename)
|
||||
return re.match(r'^_recipes/([A-Za-z\d\s-])+.md$', zip_info_object.filename)
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
ingredient_mode = False
|
||||
direction_mode = False
|
||||
description_mode = False
|
||||
|
||||
ingredients = []
|
||||
directions = []
|
||||
descriptions = []
|
||||
for fl in file.readlines():
|
||||
line = fl.decode("utf-8")
|
||||
if 'title:' in line:
|
||||
title = line.replace('title:', '').replace('"', '').strip()
|
||||
if 'image:' in line:
|
||||
image = line.replace('image:', '').strip()
|
||||
if 'tags:' in line:
|
||||
tags = line.replace('tags:', '').strip()
|
||||
if ingredient_mode:
|
||||
if len(line) > 2 and 'directions:' not in line:
|
||||
ingredients.append(line[2:])
|
||||
if '---' in line and direction_mode:
|
||||
direction_mode = False
|
||||
description_mode = True
|
||||
if direction_mode:
|
||||
if len(line) > 2:
|
||||
directions.append(line[2:])
|
||||
if 'ingredients:' in line:
|
||||
ingredient_mode = True
|
||||
if 'directions:' in line:
|
||||
ingredient_mode = False
|
||||
direction_mode = True
|
||||
if description_mode and len(line) > 3 and '---' not in line:
|
||||
descriptions.append(line)
|
||||
|
||||
recipe = Recipe.objects.create(name=title, created_by=self.request.user, internal=True, )
|
||||
|
||||
for k in tags.split(','):
|
||||
keyword, created = Keyword.objects.get_or_create(name=k.strip())
|
||||
recipe.keywords.add(keyword)
|
||||
|
||||
step = Step.objects.create(
|
||||
instruction='\n'.join(directions) + '\n\n' + '\n'.join(descriptions)
|
||||
)
|
||||
|
||||
for ingredient in ingredients:
|
||||
amount, unit, ingredient, note = parse(ingredient)
|
||||
f, created = Food.objects.get_or_create(name=ingredient)
|
||||
u, created = Unit.objects.get_or_create(name=unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
for f in self.files:
|
||||
if '.zip' in f.name:
|
||||
import_zip = ZipFile(f.file)
|
||||
for z in import_zip.filelist:
|
||||
if re.match(f'^images/{image}$', z.filename):
|
||||
self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename)))
|
||||
|
||||
return recipe
|
||||
|
||||
def get_file_from_recipe(self, recipe):
|
||||
raise NotImplementedError('Method not implemented in storage integration')
|
||||
52
cookbook/integration/mealie.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import json
|
||||
import re
|
||||
from io import BytesIO
|
||||
from zipfile import ZipFile
|
||||
|
||||
from cookbook.helper.ingredient_parser import parse
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Food, Unit, Ingredient
|
||||
|
||||
|
||||
class Mealie(Integration):
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
return re.match(r'^recipes/([A-Za-z\d-])+.json$', zip_info_object.filename)
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
recipe_json = json.loads(file.getvalue().decode("utf-8"))
|
||||
|
||||
recipe = Recipe.objects.create(
|
||||
name=recipe_json['name'].strip(), description=recipe_json['description'].strip(),
|
||||
created_by=self.request.user, internal=True)
|
||||
|
||||
# TODO parse times (given in PT2H3M )
|
||||
|
||||
ingredients_added = False
|
||||
for s in recipe_json['recipeInstructions']:
|
||||
step = Step.objects.create(
|
||||
instruction=s['text']
|
||||
)
|
||||
if not ingredients_added:
|
||||
ingredients_added = True
|
||||
|
||||
for ingredient in recipe_json['recipeIngredient']:
|
||||
amount, unit, ingredient, note = parse(ingredient)
|
||||
f, created = Food.objects.get_or_create(name=ingredient)
|
||||
u, created = Unit.objects.get_or_create(name=unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
for f in self.files:
|
||||
if '.zip' in f.name:
|
||||
import_zip = ZipFile(f.file)
|
||||
for z in import_zip.filelist:
|
||||
if re.match(f'^images/{recipe_json["slug"]}.jpg$', z.filename):
|
||||
self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename)))
|
||||
|
||||
return recipe
|
||||
|
||||
def get_file_from_recipe(self, recipe):
|
||||
raise NotImplementedError('Method not implemented in storage integration')
|
||||
@@ -3,18 +3,14 @@ import re
|
||||
from io import BytesIO
|
||||
from zipfile import ZipFile
|
||||
|
||||
from rest_framework.renderers import JSONRenderer
|
||||
|
||||
from cookbook.helper.ingredient_parser import parse
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Food, Unit, Ingredient
|
||||
from cookbook.serializer import RecipeExportSerializer
|
||||
|
||||
|
||||
class NextcloudCookbook(Integration):
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
print("testing", zip_info_object.filename)
|
||||
return re.match(r'^Recipes/([A-Za-z\d\s])+/recipe.json$', zip_info_object.filename)
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
@@ -26,6 +22,7 @@ class NextcloudCookbook(Integration):
|
||||
servings=recipe_json['recipeYield'])
|
||||
|
||||
# TODO parse times (given in PT2H3M )
|
||||
# TODO parse keywords
|
||||
|
||||
ingredients_added = False
|
||||
for s in recipe_json['recipeInstructions']:
|
||||
@@ -54,6 +51,4 @@ class NextcloudCookbook(Integration):
|
||||
return recipe
|
||||
|
||||
def get_file_from_recipe(self, recipe):
|
||||
export = RecipeExportSerializer(recipe).data
|
||||
|
||||
return 'recipe.json', JSONRenderer().render(export).decode("utf-8")
|
||||
raise NotImplementedError('Method not implemented in storage integration')
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import json
|
||||
import re
|
||||
from io import BytesIO
|
||||
from zipfile import ZipFile
|
||||
|
||||
import microdata
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from cookbook.helper.recipe_url_import import find_recipe_json
|
||||
from cookbook.integration.integration import Integration
|
||||
@@ -9,6 +13,10 @@ from cookbook.models import Recipe, Step, Food, Ingredient, Unit
|
||||
|
||||
class Paprika(Integration):
|
||||
|
||||
def import_file_name_filter(self, zip_info_object):
|
||||
print("testing", zip_info_object.filename)
|
||||
return re.match(r'^Recipes/([A-Za-z\s])+.html$', zip_info_object.filename)
|
||||
|
||||
def get_file_from_recipe(self, recipe):
|
||||
raise NotImplementedError('Method not implemented in storage integration')
|
||||
|
||||
@@ -33,4 +41,16 @@ class Paprika(Integration):
|
||||
))
|
||||
|
||||
recipe.steps.add(step)
|
||||
|
||||
soup = BeautifulSoup(html_text, "html.parser")
|
||||
image = soup.find('img')
|
||||
image_name = image.attrs['src'].strip().replace('Images/', '')
|
||||
|
||||
for f in self.files:
|
||||
if '.zip' in f.name:
|
||||
import_zip = ZipFile(f.file)
|
||||
for z in import_zip.filelist:
|
||||
if re.match(f'^Recipes/Images/{image_name}$', z.filename):
|
||||
self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename)))
|
||||
|
||||
return recipe
|
||||
|
||||
60
cookbook/integration/safron.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from cookbook.helper.ingredient_parser import parse
|
||||
from cookbook.integration.integration import Integration
|
||||
from cookbook.models import Recipe, Step, Food, Unit, Ingredient
|
||||
|
||||
|
||||
class Safron(Integration):
|
||||
|
||||
def get_recipe_from_file(self, file):
|
||||
ingredient_mode = False
|
||||
direction_mode = False
|
||||
|
||||
ingredients = []
|
||||
directions = []
|
||||
for fl in file.readlines():
|
||||
line = fl.decode("utf-8")
|
||||
if 'Title:' in line:
|
||||
title = line.replace('Title:', '').strip()
|
||||
if 'Description:' in line:
|
||||
description = line.replace('Description:', '').strip()
|
||||
if 'Yield:' in line:
|
||||
directions.append(_('Servings') + ' ' + line.replace('Yield:', '').strip() + '\n')
|
||||
if 'Cook:' in line:
|
||||
directions.append(_('Waiting time') + ' ' + line.replace('Cook:', '').strip() + '\n')
|
||||
if 'Prep:' in line:
|
||||
directions.append(_('Preparation Time') + ' ' + line.replace('Prep:', '').strip() + '\n')
|
||||
if 'Cookbook:' in line:
|
||||
directions.append(_('Cookbook') + ' ' + line.replace('Cookbook:', '').strip() + '\n')
|
||||
if 'Section:' in line:
|
||||
directions.append(_('Section') + ' ' + line.replace('Section:', '').strip() + '\n')
|
||||
if ingredient_mode:
|
||||
if len(line) > 2 and 'Instructions:' not in line:
|
||||
ingredients.append(line.strip())
|
||||
if direction_mode:
|
||||
if len(line) > 2:
|
||||
directions.append(line.strip())
|
||||
if 'Ingredients:' in line:
|
||||
ingredient_mode = True
|
||||
if 'Instructions:' in line:
|
||||
ingredient_mode = False
|
||||
direction_mode = True
|
||||
|
||||
recipe = Recipe.objects.create(name=title, description=description, created_by=self.request.user, internal=True, )
|
||||
|
||||
step = Step.objects.create(instruction='\n'.join(directions))
|
||||
|
||||
for ingredient in ingredients:
|
||||
amount, unit, ingredient, note = parse(ingredient)
|
||||
f, created = Food.objects.get_or_create(name=ingredient)
|
||||
u, created = Unit.objects.get_or_create(name=unit)
|
||||
step.ingredients.add(Ingredient.objects.create(
|
||||
food=f, unit=u, amount=amount, note=note
|
||||
))
|
||||
recipe.steps.add(step)
|
||||
|
||||
return recipe
|
||||
|
||||
def get_file_from_recipe(self, recipe):
|
||||
raise NotImplementedError('Method not implemented in storage integration')
|
||||
BIN
cookbook/locale/cs/LC_MESSAGES/django.mo
Normal file
1871
cookbook/locale/cs/LC_MESSAGES/django.po
Normal file
43
cookbook/static/assets/favicon.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="Logo" transform="matrix(0.637323,0,0,0.637323,-243.095,-716.725)">
|
||||
<g id="Kreis" transform="matrix(1.44936,0,0,1.50279,387.258,1039.34)">
|
||||
<ellipse cx="273.123" cy="324.015" rx="259.822" ry="250.584" style="fill:url(#_Linear1);"/>
|
||||
<clipPath id="_clip2">
|
||||
<ellipse cx="273.123" cy="324.015" rx="259.822" ry="250.584"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip2)">
|
||||
<g id="Shadow" transform="matrix(1.10322,0,0,1.064,-5.58287,50.5786)">
|
||||
<path d="M156.285,427.208L389.554,660.477L668.803,495.551L374.012,200.761L156.285,427.208Z" style="fill:rgb(22,22,22);"/>
|
||||
<g transform="matrix(1,0,0,1,-4.22105,0.775864)">
|
||||
<path d="M208.628,178.613L485.935,455.919L590.027,364.63L296.923,71.526L294.175,138.989L208.628,178.613Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,-85.3876,27.8512)">
|
||||
<path d="M310.385,145.641L587.692,422.948L590.392,361.357L297.288,68.253L294.175,138.989L310.385,145.641Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1.471,0,0,1.471,406.537,1149.69)">
|
||||
<path d="M256.049,220C286.222,219.994 312.656,207.31 329.388,194.134C346.35,180.754 370.899,183.406 384.611,200.1C407.129,227.376 420.598,261.944 420.598,299.53C420.598,361.08 382.604,437.101 329.764,463.706C307.035,475.15 283.466,480.586 256.098,480.599L256.098,480.599L256.049,480.599L256,480.599L256,480.599C228.632,480.586 205.063,475.15 182.334,463.706C129.494,437.101 91.5,361.08 91.5,299.53C91.5,261.944 104.969,227.376 127.487,200.1C141.199,183.406 165.748,180.754 182.71,194.134C199.442,207.31 225.876,219.994 256.049,220Z" style="fill:rgb(255,203,118);"/>
|
||||
</g>
|
||||
<g id="Flame-2" serif:id="Flame 2" transform="matrix(0.965725,0,0,0.89175,164.497,436.391)">
|
||||
<path d="M604.408,844.314C601.981,840.845 601.962,836.056 604.362,832.565C606.763,829.074 611.005,827.721 614.769,829.246C633.87,836.869 658.833,848.629 678.207,864.452C718.526,897.381 729.55,919.407 738.552,942.091C749.208,968.943 750.785,996.68 748.515,1016.08C742.018,1071.61 700.355,1117.5 641.034,1117.5C581.713,1117.5 534.493,1072.05 533.553,1016.08C532.986,982.372 543.985,955.443 555.988,936.22C558.982,931.437 564.594,929.469 569.609,931.444C574.623,933.419 577.757,938.831 577.215,944.58C575.493,956.716 574.362,969.372 574.932,979.484C576.863,1013.7 597.171,1022.5 618.083,1022.29C640.371,1022.08 662.925,1003.17 654.797,954.895C647.69,912.681 622.362,870.194 604.408,844.314Z" style="fill:rgb(255,111,0);"/>
|
||||
<clipPath id="_clip3">
|
||||
<path d="M604.408,844.314C601.981,840.845 601.962,836.056 604.362,832.565C606.763,829.074 611.005,827.721 614.769,829.246C633.87,836.869 658.833,848.629 678.207,864.452C718.526,897.381 729.55,919.407 738.552,942.091C749.208,968.943 750.785,996.68 748.515,1016.08C742.018,1071.61 700.355,1117.5 641.034,1117.5C581.713,1117.5 534.493,1072.05 533.553,1016.08C532.986,982.372 543.985,955.443 555.988,936.22C558.982,931.437 564.594,929.469 569.609,931.444C574.623,933.419 577.757,938.831 577.215,944.58C575.493,956.716 574.362,969.372 574.932,979.484C576.863,1013.7 597.171,1022.5 618.083,1022.29C640.371,1022.08 662.925,1003.17 654.797,954.895C647.69,912.681 622.362,870.194 604.408,844.314Z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip3)">
|
||||
<g transform="matrix(1.28784,-0.270602,0.285942,1.59598,247.349,825.209)">
|
||||
<path d="M255.004,46.957C279.547,58.545 306,85.447 313.307,120.161C325.437,177.791 291.571,193.789 262.496,192.403C215.889,190.181 200.194,153.246 231.326,108.9C250.631,81.401 232.663,36.408 255.004,46.957Z" style="fill:rgb(255,209,0);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Hut" transform="matrix(1.521,0,0,1.521,393.566,1149.06)">
|
||||
<path d="M228.197,408.524C222.698,408.524 217.813,406.688 214.024,403.619C211.776,401.794 210.92,398.752 211.888,396.024C212.856,393.295 215.437,391.472 218.332,391.472C232.214,391.4 256.112,391.396 256.112,391.396C256.112,391.396 280.009,391.4 293.891,391.472C296.786,391.472 299.367,393.295 300.335,396.024C301.303,398.752 300.447,401.794 298.199,403.619C294.41,406.688 289.526,408.524 284.027,408.524L228.197,408.524ZM217.24,378.877C214.208,378.877 211.3,377.671 209.158,375.525C207.015,373.379 205.814,370.469 205.82,367.436C205.831,361.119 205.842,354.539 205.842,354.539C205.842,350.423 203.097,346.814 199.131,345.714C185.313,341.841 175.2,329.468 175.2,314.823C175.2,297.07 190.059,282.657 208.362,282.657C208.362,282.657 208.362,282.657 208.362,282.657C215.401,282.657 221.675,278.218 224.017,271.581C227.243,262.39 236.411,252.015 256,251.998L256,251.998L256.223,251.998L256.223,251.998C275.812,252.015 284.98,262.39 288.206,271.581C290.549,278.218 296.822,282.657 303.861,282.657C303.861,282.657 303.861,282.657 303.861,282.657C322.164,282.657 337.023,297.07 337.023,314.823C337.023,329.468 326.911,341.841 313.093,345.714C309.127,346.814 306.382,350.423 306.381,354.539C306.381,354.539 306.386,361.127 306.391,367.447C306.394,370.478 305.191,373.385 303.049,375.529C300.907,377.672 298.001,378.877 294.971,378.877C275.615,378.877 236.604,378.877 217.24,378.877Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2e-06,0,0,2e-06,3755.77,81.7179)"><stop offset="0" style="stop-color:rgb(39,39,39);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(108,108,108);stop-opacity:1"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
43
cookbook/static/assets/logo_color.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="Logo" transform="matrix(0.637323,0,0,0.637323,-243.095,-716.725)">
|
||||
<g id="Kreis" transform="matrix(1.44936,0,0,1.50279,387.258,1039.34)">
|
||||
<ellipse cx="273.123" cy="324.015" rx="259.822" ry="250.584" style="fill:url(#_Linear1);"/>
|
||||
<clipPath id="_clip2">
|
||||
<ellipse cx="273.123" cy="324.015" rx="259.822" ry="250.584"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip2)">
|
||||
<g id="Shadow" transform="matrix(1.10322,0,0,1.064,-5.58287,50.5786)">
|
||||
<path d="M156.285,427.208L389.554,660.477L668.803,495.551L374.012,200.761L156.285,427.208Z" style="fill:rgb(22,22,22);"/>
|
||||
<g transform="matrix(1,0,0,1,-4.22105,0.775864)">
|
||||
<path d="M208.628,178.613L485.935,455.919L590.027,364.63L296.923,71.526L294.175,138.989L208.628,178.613Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,-85.3876,27.8512)">
|
||||
<path d="M310.385,145.641L587.692,422.948L590.392,361.357L297.288,68.253L294.175,138.989L310.385,145.641Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1.471,0,0,1.471,406.537,1149.69)">
|
||||
<path d="M256.049,220C286.222,219.994 312.656,207.31 329.388,194.134C346.35,180.754 370.899,183.406 384.611,200.1C407.129,227.376 420.598,261.944 420.598,299.53C420.598,361.08 382.604,437.101 329.764,463.706C307.035,475.15 283.466,480.586 256.098,480.599L256.098,480.599L256.049,480.599L256,480.599L256,480.599C228.632,480.586 205.063,475.15 182.334,463.706C129.494,437.101 91.5,361.08 91.5,299.53C91.5,261.944 104.969,227.376 127.487,200.1C141.199,183.406 165.748,180.754 182.71,194.134C199.442,207.31 225.876,219.994 256.049,220Z" style="fill:rgb(255,203,118);"/>
|
||||
</g>
|
||||
<g id="Flame-2" serif:id="Flame 2" transform="matrix(0.965725,0,0,0.89175,164.497,436.391)">
|
||||
<path d="M604.408,844.314C601.981,840.845 601.962,836.056 604.362,832.565C606.763,829.074 611.005,827.721 614.769,829.246C633.87,836.869 658.833,848.629 678.207,864.452C718.526,897.381 729.55,919.407 738.552,942.091C749.208,968.943 750.785,996.68 748.515,1016.08C742.018,1071.61 700.355,1117.5 641.034,1117.5C581.713,1117.5 534.493,1072.05 533.553,1016.08C532.986,982.372 543.985,955.443 555.988,936.22C558.982,931.437 564.594,929.469 569.609,931.444C574.623,933.419 577.757,938.831 577.215,944.58C575.493,956.716 574.362,969.372 574.932,979.484C576.863,1013.7 597.171,1022.5 618.083,1022.29C640.371,1022.08 662.925,1003.17 654.797,954.895C647.69,912.681 622.362,870.194 604.408,844.314Z" style="fill:rgb(255,111,0);"/>
|
||||
<clipPath id="_clip3">
|
||||
<path d="M604.408,844.314C601.981,840.845 601.962,836.056 604.362,832.565C606.763,829.074 611.005,827.721 614.769,829.246C633.87,836.869 658.833,848.629 678.207,864.452C718.526,897.381 729.55,919.407 738.552,942.091C749.208,968.943 750.785,996.68 748.515,1016.08C742.018,1071.61 700.355,1117.5 641.034,1117.5C581.713,1117.5 534.493,1072.05 533.553,1016.08C532.986,982.372 543.985,955.443 555.988,936.22C558.982,931.437 564.594,929.469 569.609,931.444C574.623,933.419 577.757,938.831 577.215,944.58C575.493,956.716 574.362,969.372 574.932,979.484C576.863,1013.7 597.171,1022.5 618.083,1022.29C640.371,1022.08 662.925,1003.17 654.797,954.895C647.69,912.681 622.362,870.194 604.408,844.314Z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip3)">
|
||||
<g transform="matrix(1.28784,-0.270602,0.285942,1.59598,247.349,825.209)">
|
||||
<path d="M255.004,46.957C279.547,58.545 306,85.447 313.307,120.161C325.437,177.791 291.571,193.789 262.496,192.403C215.889,190.181 200.194,153.246 231.326,108.9C250.631,81.401 232.663,36.408 255.004,46.957Z" style="fill:rgb(255,209,0);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Hut" transform="matrix(1.521,0,0,1.521,393.566,1149.06)">
|
||||
<path d="M228.197,408.524C222.698,408.524 217.813,406.688 214.024,403.619C211.776,401.794 210.92,398.752 211.888,396.024C212.856,393.295 215.437,391.472 218.332,391.472C232.214,391.4 256.112,391.396 256.112,391.396C256.112,391.396 280.009,391.4 293.891,391.472C296.786,391.472 299.367,393.295 300.335,396.024C301.303,398.752 300.447,401.794 298.199,403.619C294.41,406.688 289.526,408.524 284.027,408.524L228.197,408.524ZM217.24,378.877C214.208,378.877 211.3,377.671 209.158,375.525C207.015,373.379 205.814,370.469 205.82,367.436C205.831,361.119 205.842,354.539 205.842,354.539C205.842,350.423 203.097,346.814 199.131,345.714C185.313,341.841 175.2,329.468 175.2,314.823C175.2,297.07 190.059,282.657 208.362,282.657C208.362,282.657 208.362,282.657 208.362,282.657C215.401,282.657 221.675,278.218 224.017,271.581C227.243,262.39 236.411,252.015 256,251.998L256,251.998L256.223,251.998L256.223,251.998C275.812,252.015 284.98,262.39 288.206,271.581C290.549,278.218 296.822,282.657 303.861,282.657C303.861,282.657 303.861,282.657 303.861,282.657C322.164,282.657 337.023,297.07 337.023,314.823C337.023,329.468 326.911,341.841 313.093,345.714C309.127,346.814 306.382,350.423 306.381,354.539C306.381,354.539 306.386,361.127 306.391,367.447C306.394,370.478 305.191,373.385 303.049,375.529C300.907,377.672 298.001,378.877 294.971,378.877C275.615,378.877 236.604,378.877 217.24,378.877Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2e-06,0,0,2e-06,3755.77,81.7179)"><stop offset="0" style="stop-color:rgb(39,39,39);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(108,108,108);stop-opacity:1"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
BIN
cookbook/static/assets/logo_color144.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
cookbook/static/assets/logo_color512.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
@@ -1 +0,0 @@
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="book" class="svg-inline--fa fa-book fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M128 152v-32c0-4.4 3.6-8 8-8h208c4.4 0 8 3.6 8 8v32c0 4.4-3.6 8-8 8H136c-4.4 0-8-3.6-8-8zm8 88h208c4.4 0 8-3.6 8-8v-32c0-4.4-3.6-8-8-8H136c-4.4 0-8 3.6-8 8v32c0 4.4 3.6 8 8 8zm299.1 159.7c-4.2 13-4.2 51.6 0 64.6 7.3 1.4 12.9 7.9 12.9 15.7v16c0 8.8-7.2 16-16 16H80c-44.2 0-80-35.8-80-80V80C0 35.8 35.8 0 80 0h352c8.8 0 16 7.2 16 16v368c0 7.8-5.5 14.2-12.9 15.7zm-41.1.3H80c-17.6 0-32 14.4-32 32 0 17.7 14.3 32 32 32h314c-2.7-17.3-2.7-46.7 0-64zm6-352H80c-17.7 0-32 14.3-32 32v278.7c9.8-4.3 20.6-6.7 32-6.7h320V48z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 740 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -11,17 +11,17 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
|
||||
<link rel="shortcut icon" type="image/x-icon" href="{% static 'favicon.png' %}">
|
||||
<link rel="shortcut icon" href="{% static 'favicon.png' %}">
|
||||
<link rel="icon" type="image/png" href="{% static 'favicon.png' %}" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="{% static 'favicon.png' %}" sizes="96x96">
|
||||
<link rel="apple-touch-icon" href="{% static 'favicon.png' %}">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'favicon.png' %}">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="{% static 'favicon.png' %}">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'favicon.png' %}">
|
||||
<link rel="apple-touch-icon" sizes="167x167" href="{% static 'favicon.png' %}">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="{% static 'assets/favicon.svg' %}">
|
||||
<link rel="shortcut icon" href="{% static 'assets/favicon.svg' %}">
|
||||
<link rel="icon" type="image/png" href="{% static 'assets/favicon.svg' %}" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="{% static 'assets/favicon.svg' %}" sizes="96x96">
|
||||
<link rel="apple-touch-icon" href="{% static 'assets/favicon.svg' %}">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'assets/favicon.svg' %}">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="{% static 'assets/favicon.svg' %}">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'assets/favicon.svg' %}">
|
||||
<link rel="apple-touch-icon" sizes="167x167" href="{% static 'assets/favicon.svg' %}">
|
||||
|
||||
<link rel="manifest" href="{% static 'manifest/webmanifest' %}">
|
||||
<link rel="manifest" href="{% url 'web_manifest' %}">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
|
||||
|
||||
|
||||
@@ -1,51 +1,48 @@
|
||||
{
|
||||
"name": "Recipes",
|
||||
"name": "Tandoor Recipes",
|
||||
"short_name" : "Tandoor",
|
||||
"description": "Application to manage, tag and search recipes.",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/manifest/icon-192.png",
|
||||
"src": "/static/assets/logo_color144.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
"sizes": "144x144"
|
||||
},
|
||||
{
|
||||
"src": "/static/manifest/icon-512.png",
|
||||
"src": "/static/assets/logo_color512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": "/search",
|
||||
"background_color": "#18BC9C",
|
||||
"background_color": "#ffcb76",
|
||||
"display": "standalone",
|
||||
"scope": "/",
|
||||
"theme_color": "#18BC9C",
|
||||
"theme_color": "#ffcb76",
|
||||
"shortcuts": [
|
||||
{
|
||||
"name": "Plan",
|
||||
"short_name": "Plan",
|
||||
"description": "View your meal Plan",
|
||||
"url": "/plan",
|
||||
"icons": [{ "src": "/static/manifest/icon-192.png", "sizes": "192x192" }]
|
||||
"url": "/plan"
|
||||
},
|
||||
{
|
||||
"name": "Books",
|
||||
"short_name": "Cookbooks",
|
||||
"description": "View your cookbooks",
|
||||
"url": "/books",
|
||||
"icons": [{ "src": "/static/manifest/icon-192.png", "sizes": "192x192" }]
|
||||
"url": "/books"
|
||||
},
|
||||
{
|
||||
"name": "Shopping",
|
||||
"short_name": "Shopping",
|
||||
"description": "View your shopping lists",
|
||||
"url": "/list/shopping-list/",
|
||||
"icons": [{ "src": "/static/manifest/shopping-cart-192.png", "sizes": "192x192" }]
|
||||
"url": "/list/shopping-list/"
|
||||
},
|
||||
{
|
||||
"name": "Latest Shopping List",
|
||||
"short_name": "Shopping List",
|
||||
"description": "View the latest shopping list",
|
||||
"url": "/shopping/latest/",
|
||||
"icons": [{ "src": "/static/manifest/shopping-cart-192.png", "sizes": "192x192" }]
|
||||
"url": "/shopping/latest/"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -129,7 +129,7 @@
|
||||
[](https://github.com/vabene1111/recipes)
|
||||
[GitHub](https://github.com/vabene1111/recipes)
|
||||
|
||||

|
||||

|
||||
</code></pre>
|
||||
|
||||
<div style="text-align: center">
|
||||
@@ -142,7 +142,7 @@
|
||||
<div class="card-body">
|
||||
<a href="https://github.com/vabene1111/recipes">https://github.com/vabene1111/recipes</a> <br/>
|
||||
<a href="https://github.com/vabene1111/recipes">GitHub</a> <br/>
|
||||
<img src="{% static 'favicon.png' %}" class="img-fluid" alt="{% trans 'This will become an image' %}"
|
||||
<img src="{% static 'assets/favicon.svg' %}" class="img-fluid" alt="{% trans 'This will become an image' %}"
|
||||
style="height: 3vw">
|
||||
</div>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<img src=" {{ row.cells.image }}" alt="{% trans 'Recipe Image' %}"
|
||||
class="card-img" style="object-fit: cover;height: 130px">
|
||||
{% else %}
|
||||
<img src="{% static 'recipe_no_image.svg' %}"
|
||||
<img src="{% static 'assets/recipe_no_image.svg' %}"
|
||||
alt="{% trans 'Recipe Image' %}"
|
||||
class="card-img d-none d-md-block"
|
||||
style="object-fit: cover; height: 130px">
|
||||
|
||||
@@ -681,7 +681,7 @@
|
||||
Promise.allSettled(recipe_promises).then(() => {
|
||||
console.log("proceeding to update shopping list", this.shopping_list)
|
||||
|
||||
if (this.shopping_list_id === null) {
|
||||
if (this.shopping_list.id === undefined) {
|
||||
return this.$http.post("{% url 'api:shoppinglist-list' %}", this.shopping_list, {}).then((response) => {
|
||||
console.log(response)
|
||||
this.makeToast(gettext('Updated'), gettext('Object created successfully!'), 'success')
|
||||
@@ -697,7 +697,7 @@
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
return this.$http.put("{% url 'api:shoppinglist-detail' shopping_list_id %}", this.shopping_list, {}).then((response) => {
|
||||
return this.$http.put("{% url 'api:shoppinglist-detail' 123456 %}".replace('123456', this.shopping_list.id), this.shopping_list, {}).then((response) => {
|
||||
console.log(response)
|
||||
this.shopping_list = response.body
|
||||
this.makeToast(gettext('Updated'), gettext('Changes saved successfully!'), 'success')
|
||||
|
||||
@@ -86,6 +86,8 @@ def page_help(page_name):
|
||||
help_pages = {
|
||||
'edit_storage': 'https://vabene1111.github.io/recipes/features/external_recipes/',
|
||||
'view_shopping': 'https://vabene1111.github.io/recipes/features/shopping/',
|
||||
'view_import': 'https://vabene1111.github.io/recipes/features/import_export/',
|
||||
'view_export': 'https://vabene1111.github.io/recipes/features/import_export/',
|
||||
}
|
||||
|
||||
link = help_pages.get(page_name, '')
|
||||
|
||||
@@ -33,6 +33,7 @@ class TestEditsRecipe(TestBase):
|
||||
expectations = {
|
||||
"2¼ l Wasser": (2.25, "l", "Wasser", ""),
|
||||
"2¼l Wasser": (2.25, "l", "Wasser", ""),
|
||||
"¼ l Wasser": (0.25, "l", "Wasser", ""),
|
||||
"3l Wasser": (3, "l", "Wasser", ""),
|
||||
"4 l Wasser": (4, "l", "Wasser", ""),
|
||||
"½l Wasser": (0.5, "l", "Wasser", ""),
|
||||
@@ -43,6 +44,10 @@ class TestEditsRecipe(TestBase):
|
||||
"1 Zwiebel(n)": (1, "", "Zwiebel(n)", ""),
|
||||
"4 1/2 Zwiebeln": (4.5, "", "Zwiebeln", ""),
|
||||
"4 ½ Zwiebeln": (4.5, "", "Zwiebeln", ""),
|
||||
"1/2 EL Mehl": (0.5, "EL", "Mehl", ""),
|
||||
"1/2 Zwiebel": (0.5, "", "Zwiebel", ""),
|
||||
"1/5g Mehl, gesiebt": (0.2, "g", "Mehl", "gesiebt"),
|
||||
"1/2 Zitrone, ausgepresst": (0.5, "", "Zitrone", "ausgepresst"),
|
||||
"etwas Mehl": (0, "", "etwas Mehl", ""),
|
||||
"Öl zum Anbraten": (0, "", "Öl zum Anbraten", ""),
|
||||
"n. B. Knoblauch, zerdrückt": (0, "", "n. B. Knoblauch", "zerdrückt"),
|
||||
|
||||
@@ -105,8 +105,10 @@ urlpatterns = [
|
||||
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||
|
||||
path('offline/', views.offline, name='view_offline'),
|
||||
path('service-worker.js', (TemplateView.as_view(template_name="sw.js", content_type='application/javascript', )), name='service_worker'),
|
||||
|
||||
|
||||
path('service-worker.js', (TemplateView.as_view(template_name="sw.js", content_type='application/javascript', )), name='service_worker'),
|
||||
path('manifest.json', (TemplateView.as_view(template_name="manifest.json", content_type='application/json', )), name='web_manifest'),
|
||||
]
|
||||
|
||||
generic_models = (
|
||||
|
||||
@@ -6,9 +6,12 @@ from django.utils.translation import gettext as _
|
||||
|
||||
from cookbook.forms import ExportForm, ImportForm, ImportExportBase
|
||||
from cookbook.helper.permission_helper import group_required
|
||||
from cookbook.integration.chowdown import Chowdown
|
||||
from cookbook.integration.default import Default
|
||||
from cookbook.integration.mealie import Mealie
|
||||
from cookbook.integration.nextcloud_cookbook import NextcloudCookbook
|
||||
from cookbook.integration.paprika import Paprika
|
||||
from cookbook.integration.safron import Safron
|
||||
from cookbook.models import Recipe
|
||||
|
||||
|
||||
@@ -19,6 +22,12 @@ def get_integration(request, export_type):
|
||||
return Paprika(request)
|
||||
if export_type == ImportExportBase.NEXTCLOUD:
|
||||
return NextcloudCookbook(request)
|
||||
if export_type == ImportExportBase.MEALIE:
|
||||
return Mealie(request)
|
||||
if export_type == ImportExportBase.CHOWDOWN:
|
||||
return Chowdown(request)
|
||||
if export_type == ImportExportBase.SAFRON:
|
||||
return Safron(request)
|
||||
|
||||
|
||||
@group_required('user')
|
||||
|
||||
@@ -30,9 +30,7 @@ def keyword(request):
|
||||
@group_required('admin')
|
||||
def sync_log(request):
|
||||
table = ImportLogTable(
|
||||
SyncLog.objects.all().order_by(
|
||||
Lower('created_at').desc()
|
||||
)
|
||||
SyncLog.objects.all().order_by('-created_at')
|
||||
)
|
||||
RequestConfig(request, paginate={'per_page': 25}).configure(table)
|
||||
|
||||
|
||||
1
docs/CNAME
Normal file
@@ -0,0 +1 @@
|
||||
docs.tandoor.dev
|
||||
@@ -7,12 +7,12 @@ integrations to allow you to both import and export your recipes into whatever f
|
||||
Feel like there is an important integration missing ? Just take a look at the [integration issues](https://github.com/vabene1111/recipes/issues?q=is%3Aissue+is%3Aopen+label%3Aintegration) or open a new one
|
||||
if your favorite one is missing.
|
||||
|
||||
!!! warning "WIP"
|
||||
Please note that this feature is relatively new and many integrations are missing.
|
||||
Additionally, many recipe applications provide formats that are not structured in an easily machine-readable way
|
||||
and thus require a lot of work to integrate even tough the module is very versatile.
|
||||
If you are good at writing parsers feel free to add new integrations for your favorite services.
|
||||
|
||||
!!! info "Export"
|
||||
I strongly believe in everyone's right to use their data as they please and therefore want to give you
|
||||
the most possible flexibility with your recipes.
|
||||
That said for most of the people getting this application running with their recipes is the biggest priority.
|
||||
Because of this importing as many formats as possible is prioritized over exporting.
|
||||
Exporter for the different formats will follow over time.
|
||||
|
||||
## Default
|
||||
The default integration is the build in (and preferred) way to import and export recipes.
|
||||
@@ -36,7 +36,7 @@ You will get a `Recipes.zip` file. Simply upload the file and choose the Nextclo
|
||||
|
||||
!!! warning "Folder Structure"
|
||||
Importing only works if the folder structure is correct. If you do not use the standard path or create the
|
||||
zip file in any other way make sure the strucutre is as follows
|
||||
zip file in any other way make sure the structure is as follows
|
||||
```
|
||||
Recipes.zip/
|
||||
└── Recipes/
|
||||
@@ -48,12 +48,57 @@ You will get a `Recipes.zip` file. Simply upload the file and choose the Nextclo
|
||||
└── full.jpg
|
||||
```
|
||||
|
||||
## Mealie
|
||||
Mealie provides structured data similar to nextcloud.
|
||||
|
||||
To migrate your recipes
|
||||
|
||||
1. Go to you Mealie settings and create a new Backup
|
||||
2. Download the backup by clicking on it and pressing download (this wasn't working for me, so I had to manually pull it from the server)
|
||||
3. Upload the entire `.zip` file to the importer page and import everything
|
||||
|
||||
## Chowdown
|
||||
Chowdown stores all your recipes in plain text markdown files in a directory called `_recipes`.
|
||||
Images are saved in a directory called `images`.
|
||||
|
||||
In order to import your Chowdown recipes simply create a `.zip` file from those two folders and import them.
|
||||
The folder structure should look as follows
|
||||
```
|
||||
Recipes.zip/
|
||||
├── _recipes/
|
||||
│ ├── recipe one.md
|
||||
│ ├── recipe two.md
|
||||
│ └── ...
|
||||
└── images/
|
||||
├── image-name.jpg
|
||||
├── second-image-name.jpg
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Safron
|
||||
Go to you safron settings page and export your recipes.
|
||||
Then simply upload the entire `.zip` file to the importer.
|
||||
|
||||
!!! warning "Images"
|
||||
Safron exports do not contain any images. They will be lost during import.
|
||||
|
||||
## Paprika
|
||||
Paprika can create two types of export. The first is a proprietary `.paprikarecipes` file in some kind of binarized format.
|
||||
The second one is HTML files containing at least a bit of microdata.
|
||||
|
||||
If you want to import your Paprika recipes create a html export. Then import the individual recipes HTML files.
|
||||
Due to the lack of structure not all fields can be imported.
|
||||
Even tough images are present in the export they cannot be imported atm. This is technically possible and might be
|
||||
added in the future.
|
||||
If you want to import your Paprika recipes follow these steps
|
||||
|
||||
1. create a html export
|
||||
2. Create a `.zip` file from the `Recipes` folder (next to the `index.html`) the structure should look like this
|
||||
```
|
||||
Recipes.zip/
|
||||
└── Recipes/
|
||||
├── recipe one.html
|
||||
├── recipe two.thml
|
||||
└── Images/
|
||||
├── 5D5E09CD-8F88-4F61-8121-0727DD3E0E89/
|
||||
│ └── 5D5E09CD-8F88-4F61-8121-0727DD3E0E89.jpg
|
||||
└── 7CEE2AC6-DF60-4464-9B61-4F5E347EB90C/
|
||||
└── 7CEE2AC6-DF60-4464-9B61-4F5E347EB90C.jpg
|
||||
```
|
||||
3. Upload the zip file in the import module and import it
|
||||
@@ -1,6 +1,27 @@
|
||||
# Welcome to Recipes Documentation
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="https://app.tandoor.dev"><img src="https://github.com/vabene1111/recipes/raw/develop/docs/logo_color.svg" height="256px" width="256px"></a>
|
||||
<br>
|
||||
Tandoor Recipes
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
The recipe manager that allows you to manage your ever growing collection of digital recipes.
|
||||
<h4 align="center">The recipe manager that allows you to manage your ever growing collection of digital recipes.</h4>
|
||||
|
||||
<p align="center">
|
||||
|
||||
<img src="https://github.com/vabene1111/recipes/workflows/Continous%20Integration/badge.svg?branch=develop" >
|
||||
<img src="https://img.shields.io/github/stars/vabene1111/recipes" >
|
||||
<img src="https://img.shields.io/github/forks/vabene1111/recipes" >
|
||||
<img src="https://img.shields.io/docker/pulls/vabene1111/recipes" >
|
||||
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://docs.tandoor.dev/install/docker/" target="_blank" rel="noopener noreferrer">Installation</a> •
|
||||
<a href="https://docs.tandoor.dev/" target="_blank" rel="noopener noreferrer">Documentation</a> •
|
||||
<a href="https://app.tandoor.dev/" target="_blank" rel="noopener noreferrer">Demo</a>
|
||||
</p>
|
||||
|
||||

|
||||
|
||||
|
||||
43
docs/logo_color.svg
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g id="Logo" transform="matrix(0.637323,0,0,0.637323,-243.095,-716.725)">
|
||||
<g id="Kreis" transform="matrix(1.44936,0,0,1.50279,387.258,1039.34)">
|
||||
<ellipse cx="273.123" cy="324.015" rx="259.822" ry="250.584" style="fill:url(#_Linear1);"/>
|
||||
<clipPath id="_clip2">
|
||||
<ellipse cx="273.123" cy="324.015" rx="259.822" ry="250.584"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip2)">
|
||||
<g id="Shadow" transform="matrix(1.10322,0,0,1.064,-5.58287,50.5786)">
|
||||
<path d="M156.285,427.208L389.554,660.477L668.803,495.551L374.012,200.761L156.285,427.208Z" style="fill:rgb(22,22,22);"/>
|
||||
<g transform="matrix(1,0,0,1,-4.22105,0.775864)">
|
||||
<path d="M208.628,178.613L485.935,455.919L590.027,364.63L296.923,71.526L294.175,138.989L208.628,178.613Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,-85.3876,27.8512)">
|
||||
<path d="M310.385,145.641L587.692,422.948L590.392,361.357L297.288,68.253L294.175,138.989L310.385,145.641Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1.471,0,0,1.471,406.537,1149.69)">
|
||||
<path d="M256.049,220C286.222,219.994 312.656,207.31 329.388,194.134C346.35,180.754 370.899,183.406 384.611,200.1C407.129,227.376 420.598,261.944 420.598,299.53C420.598,361.08 382.604,437.101 329.764,463.706C307.035,475.15 283.466,480.586 256.098,480.599L256.098,480.599L256.049,480.599L256,480.599L256,480.599C228.632,480.586 205.063,475.15 182.334,463.706C129.494,437.101 91.5,361.08 91.5,299.53C91.5,261.944 104.969,227.376 127.487,200.1C141.199,183.406 165.748,180.754 182.71,194.134C199.442,207.31 225.876,219.994 256.049,220Z" style="fill:rgb(255,203,118);"/>
|
||||
</g>
|
||||
<g id="Flame-2" serif:id="Flame 2" transform="matrix(0.965725,0,0,0.89175,164.497,436.391)">
|
||||
<path d="M604.408,844.314C601.981,840.845 601.962,836.056 604.362,832.565C606.763,829.074 611.005,827.721 614.769,829.246C633.87,836.869 658.833,848.629 678.207,864.452C718.526,897.381 729.55,919.407 738.552,942.091C749.208,968.943 750.785,996.68 748.515,1016.08C742.018,1071.61 700.355,1117.5 641.034,1117.5C581.713,1117.5 534.493,1072.05 533.553,1016.08C532.986,982.372 543.985,955.443 555.988,936.22C558.982,931.437 564.594,929.469 569.609,931.444C574.623,933.419 577.757,938.831 577.215,944.58C575.493,956.716 574.362,969.372 574.932,979.484C576.863,1013.7 597.171,1022.5 618.083,1022.29C640.371,1022.08 662.925,1003.17 654.797,954.895C647.69,912.681 622.362,870.194 604.408,844.314Z" style="fill:rgb(255,111,0);"/>
|
||||
<clipPath id="_clip3">
|
||||
<path d="M604.408,844.314C601.981,840.845 601.962,836.056 604.362,832.565C606.763,829.074 611.005,827.721 614.769,829.246C633.87,836.869 658.833,848.629 678.207,864.452C718.526,897.381 729.55,919.407 738.552,942.091C749.208,968.943 750.785,996.68 748.515,1016.08C742.018,1071.61 700.355,1117.5 641.034,1117.5C581.713,1117.5 534.493,1072.05 533.553,1016.08C532.986,982.372 543.985,955.443 555.988,936.22C558.982,931.437 564.594,929.469 569.609,931.444C574.623,933.419 577.757,938.831 577.215,944.58C575.493,956.716 574.362,969.372 574.932,979.484C576.863,1013.7 597.171,1022.5 618.083,1022.29C640.371,1022.08 662.925,1003.17 654.797,954.895C647.69,912.681 622.362,870.194 604.408,844.314Z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip3)">
|
||||
<g transform="matrix(1.28784,-0.270602,0.285942,1.59598,247.349,825.209)">
|
||||
<path d="M255.004,46.957C279.547,58.545 306,85.447 313.307,120.161C325.437,177.791 291.571,193.789 262.496,192.403C215.889,190.181 200.194,153.246 231.326,108.9C250.631,81.401 232.663,36.408 255.004,46.957Z" style="fill:rgb(255,209,0);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Hut" transform="matrix(1.521,0,0,1.521,393.566,1149.06)">
|
||||
<path d="M228.197,408.524C222.698,408.524 217.813,406.688 214.024,403.619C211.776,401.794 210.92,398.752 211.888,396.024C212.856,393.295 215.437,391.472 218.332,391.472C232.214,391.4 256.112,391.396 256.112,391.396C256.112,391.396 280.009,391.4 293.891,391.472C296.786,391.472 299.367,393.295 300.335,396.024C301.303,398.752 300.447,401.794 298.199,403.619C294.41,406.688 289.526,408.524 284.027,408.524L228.197,408.524ZM217.24,378.877C214.208,378.877 211.3,377.671 209.158,375.525C207.015,373.379 205.814,370.469 205.82,367.436C205.831,361.119 205.842,354.539 205.842,354.539C205.842,350.423 203.097,346.814 199.131,345.714C185.313,341.841 175.2,329.468 175.2,314.823C175.2,297.07 190.059,282.657 208.362,282.657C208.362,282.657 208.362,282.657 208.362,282.657C215.401,282.657 221.675,278.218 224.017,271.581C227.243,262.39 236.411,252.015 256,251.998L256,251.998L256.223,251.998L256.223,251.998C275.812,252.015 284.98,262.39 288.206,271.581C290.549,278.218 296.822,282.657 303.861,282.657C303.861,282.657 303.861,282.657 303.861,282.657C322.164,282.657 337.023,297.07 337.023,314.823C337.023,329.468 326.911,341.841 313.093,345.714C309.127,346.814 306.382,350.423 306.381,354.539C306.381,354.539 306.386,361.127 306.391,367.447C306.394,370.478 305.191,373.385 303.049,375.529C300.907,377.672 298.001,378.877 294.971,378.877C275.615,378.877 236.604,378.877 217.24,378.877Z" style="fill:rgb(22,22,22);"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2e-06,0,0,2e-06,3755.77,81.7179)"><stop offset="0" style="stop-color:rgb(39,39,39);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(108,108,108);stop-opacity:1"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.1 KiB |
BIN
docs/preview.png
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.3 MiB |
BIN
docs/preview.xcf
19
docs/stylesheets/extra.css
Normal file
@@ -0,0 +1,19 @@
|
||||
:root {
|
||||
--md-primary-fg-color: #ffcb76;
|
||||
--md-accent-fg-color: #FF6F00;
|
||||
|
||||
--md-primary-fg-color--light: #ffcb76;
|
||||
|
||||
/* not working part, has no effect */
|
||||
--md-primary-bg-color: #272727;
|
||||
--md-default-bg-color: #272727;
|
||||
--md-default-bg-color--light: #272727;
|
||||
--md-default-bg-color--lighter: #272727;
|
||||
--md-default-bg-color--lightest: #272727;
|
||||
}
|
||||
|
||||
/*
|
||||
flame dark orange #FF6F00
|
||||
background dark #272727
|
||||
tandoor #ffcb76
|
||||
*/
|
||||
@@ -1,3 +1,3 @@
|
||||
CALL venv\Scripts\activate.bat
|
||||
python manage.py makemessages -i venv -a
|
||||
python manage.py makemessages -i venv -l ca -l de -l en -l es -l fr -l hu_HU -l it -l lv -l nl -l pt -l rn -l tr -l zh_CN
|
||||
python manage.py makemessages -i venv -a -l de -d djangojs
|
||||
20
mkdocs.yml
@@ -1,18 +1,20 @@
|
||||
site_name: Recipes
|
||||
site_description: Documentation for Recipes
|
||||
site_name: Tandoor Recipes
|
||||
site_description: Tandoor Recipe Documentation
|
||||
site_author: vabene1111
|
||||
repo_url: https://github.com/vabene1111/recipes
|
||||
edit_uri: https://github.com/vabene1111/recipes/tree/develop/docs
|
||||
extra_css:
|
||||
- stylesheets/extra.css
|
||||
|
||||
theme:
|
||||
name: material
|
||||
repo: fontawesome/brands/github
|
||||
logo: logo_color.svg
|
||||
favicon: logo_color.svg
|
||||
palette:
|
||||
scheme: slate
|
||||
primary: green
|
||||
accent: deep orange
|
||||
logo: cookbook/static/favicon.png
|
||||
favicon: cookbook/static/favicon.ico
|
||||
icon:
|
||||
repo: fontawesome/brands/github
|
||||
|
||||
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
@@ -29,7 +31,7 @@ nav:
|
||||
- Manual: install/manual.md
|
||||
- Other setups: install/other.md
|
||||
- Features:
|
||||
- Tempalating: features/templating.md
|
||||
- Templating: features/templating.md
|
||||
- Shopping: features/shopping.md
|
||||
- Authentication: features/authentication.md
|
||||
- Storages and Sync: features/external_recipes.md
|
||||
|
||||
@@ -10,7 +10,7 @@ server {
|
||||
}
|
||||
# pass requests for dynamic content to gunicorn
|
||||
location / {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_pass http://web_recipes:8080;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,30 +17,35 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
#: recipes/settings.py:175
|
||||
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-01-13 23:31+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,34 +18,34 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: .\recipes\settings.py:196
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr "Englisch"
|
||||
|
||||
#: .\recipes\settings.py:197
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr "Deutsch"
|
||||
|
||||
#: .\recipes\settings.py:198
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:199
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:200
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:201
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:202
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:203
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,30 +18,34 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: recipes/settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,30 +17,35 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
#: recipes/settings.py:175
|
||||
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,30 +18,34 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: recipes/settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,30 +17,34 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: recipes/settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,30 +17,35 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
#: recipes/settings.py:175
|
||||
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-31 18:41+0200\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -19,34 +19,34 @@ msgstr ""
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
|
||||
"2);\n"
|
||||
|
||||
#: .\recipes\settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:182
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,30 +18,34 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: recipes/settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,30 +18,34 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: recipes/settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,30 +17,34 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: recipes/settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -18,30 +18,34 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: recipes/settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-12-26 13:48+0100\n"
|
||||
"POT-Creation-Date: 2021-02-09 18:01+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -17,30 +17,34 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: recipes/settings.py:175
|
||||
#: .\recipes\settings.py:214
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:176
|
||||
#: .\recipes\settings.py:215
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:177
|
||||
#: .\recipes\settings.py:216
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:178
|
||||
#: .\recipes\settings.py:217
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:179
|
||||
#: .\recipes\settings.py:218
|
||||
msgid "Catalan"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:180
|
||||
#: .\recipes\settings.py:219
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: recipes/settings.py:181
|
||||
#: .\recipes\settings.py:220
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: .\recipes\settings.py:221
|
||||
msgid "Latvian"
|
||||
msgstr ""
|
||||
|
||||
@@ -219,14 +219,15 @@ USE_L10N = True
|
||||
USE_TZ = True
|
||||
|
||||
LANGUAGES = [
|
||||
('en', _('English')),
|
||||
('de', _('German')),
|
||||
('nl', _('Dutch')),
|
||||
('fr', _('French')),
|
||||
('ca', _('Catalan')),
|
||||
('es', _('Spanish')),
|
||||
('cs', _('Czech')),
|
||||
('nl', _('Dutch')),
|
||||
('en', _('English')),
|
||||
('fr', _('French')),
|
||||
('de', _('German')),
|
||||
('it', _('Italian')),
|
||||
('lv', _('Latvian')),
|
||||
('es', _('Spanish')),
|
||||
]
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
|
||||