converted ingredient parser to class and added automation beta hint
This commit is contained in:
parent
ecd300d2db
commit
a7dc23194e
@ -5,7 +5,26 @@ import unicodedata
|
|||||||
from cookbook.models import Unit, Food
|
from cookbook.models import Unit, Food
|
||||||
|
|
||||||
|
|
||||||
def parse_fraction(x):
|
class IngredientParser:
|
||||||
|
request = None
|
||||||
|
ignore_rules = False
|
||||||
|
food_aliases = []
|
||||||
|
unit_aliases = []
|
||||||
|
|
||||||
|
def __init__(self, request, cache_mode, ignore_automations=False):
|
||||||
|
"""
|
||||||
|
Initialize ingredient parser
|
||||||
|
:param request: request context (to control caching, rule ownership, etc.)
|
||||||
|
:param cache_mode: defines if all rules should be loaded on initialization (good when parser is used many times) or if they should be retrieved every time (good when parser is not used many times in a row)
|
||||||
|
:param ignore_automations: ignore automation rules, allows to use ingredient parser without database access/request (request can be None)
|
||||||
|
"""
|
||||||
|
self.request = request
|
||||||
|
self.ignore_rules = ignore_automations
|
||||||
|
if cache_mode:
|
||||||
|
self.food_aliases = []
|
||||||
|
self.unit_aliases = []
|
||||||
|
|
||||||
|
def parse_fraction(self, x):
|
||||||
if len(x) == 1 and 'fraction' in unicodedata.decomposition(x):
|
if len(x) == 1 and 'fraction' in unicodedata.decomposition(x):
|
||||||
frac_split = unicodedata.decomposition(x[-1:]).split()
|
frac_split = unicodedata.decomposition(x[-1:]).split()
|
||||||
return (float((frac_split[1]).replace('003', ''))
|
return (float((frac_split[1]).replace('003', ''))
|
||||||
@ -19,8 +38,7 @@ def parse_fraction(x):
|
|||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
def parse_amount(self, x):
|
||||||
def parse_amount(x):
|
|
||||||
amount = 0
|
amount = 0
|
||||||
unit = ''
|
unit = ''
|
||||||
note = ''
|
note = ''
|
||||||
@ -36,11 +54,11 @@ def parse_amount(x):
|
|||||||
end += 1
|
end += 1
|
||||||
if end > 0:
|
if end > 0:
|
||||||
if "/" in x[:end]:
|
if "/" in x[:end]:
|
||||||
amount = parse_fraction(x[:end])
|
amount = self.parse_fraction(x[:end])
|
||||||
else:
|
else:
|
||||||
amount = float(x[:end].replace(',', '.'))
|
amount = float(x[:end].replace(',', '.'))
|
||||||
else:
|
else:
|
||||||
amount = parse_fraction(x[0])
|
amount = self.parse_fraction(x[0])
|
||||||
end += 1
|
end += 1
|
||||||
did_check_frac = True
|
did_check_frac = True
|
||||||
if end < len(x):
|
if end < len(x):
|
||||||
@ -48,7 +66,7 @@ def parse_amount(x):
|
|||||||
unit = x[end:]
|
unit = x[end:]
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
amount += parse_fraction(x[end])
|
amount += self.parse_fraction(x[end])
|
||||||
unit = x[end + 1:]
|
unit = x[end + 1:]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
unit = x[end:]
|
unit = x[end:]
|
||||||
@ -58,8 +76,7 @@ def parse_amount(x):
|
|||||||
note = x
|
note = x
|
||||||
return amount, unit, note
|
return amount, unit, note
|
||||||
|
|
||||||
|
def parse_ingredient_with_comma(self, tokens):
|
||||||
def parse_ingredient_with_comma(tokens):
|
|
||||||
ingredient = ''
|
ingredient = ''
|
||||||
note = ''
|
note = ''
|
||||||
start = 0
|
start = 0
|
||||||
@ -74,14 +91,13 @@ def parse_ingredient_with_comma(tokens):
|
|||||||
note = ' '.join(tokens[start + 1:])
|
note = ' '.join(tokens[start + 1:])
|
||||||
return ingredient, note
|
return ingredient, note
|
||||||
|
|
||||||
|
def parse_ingredient(self, tokens):
|
||||||
def parse_ingredient(tokens):
|
|
||||||
ingredient = ''
|
ingredient = ''
|
||||||
note = ''
|
note = ''
|
||||||
if tokens[-1].endswith(')'):
|
if tokens[-1].endswith(')'):
|
||||||
# Check if the matching opening bracket is in the same token
|
# Check if the matching opening bracket is in the same token
|
||||||
if (not tokens[-1].startswith('(')) and ('(' in tokens[-1]):
|
if (not tokens[-1].startswith('(')) and ('(' in tokens[-1]):
|
||||||
return parse_ingredient_with_comma(tokens)
|
return self.parse_ingredient_with_comma(tokens)
|
||||||
# last argument ends with closing bracket -> look for opening bracket
|
# last argument ends with closing bracket -> look for opening bracket
|
||||||
start = len(tokens) - 1
|
start = len(tokens) - 1
|
||||||
while not tokens[start].startswith('(') and not start == 0:
|
while not tokens[start].startswith('(') and not start == 0:
|
||||||
@ -91,17 +107,16 @@ def parse_ingredient(tokens):
|
|||||||
raise ValueError
|
raise ValueError
|
||||||
elif start < 0:
|
elif start < 0:
|
||||||
# no opening bracket anywhere -> just ignore the last bracket
|
# no opening bracket anywhere -> just ignore the last bracket
|
||||||
ingredient, note = parse_ingredient_with_comma(tokens)
|
ingredient, note = self.parse_ingredient_with_comma(tokens)
|
||||||
else:
|
else:
|
||||||
# opening bracket found -> split in ingredient and note, remove brackets from note # noqa: E501
|
# opening bracket found -> split in ingredient and note, remove brackets from note # noqa: E501
|
||||||
note = ' '.join(tokens[start:])[1:-1]
|
note = ' '.join(tokens[start:])[1:-1]
|
||||||
ingredient = ' '.join(tokens[:start])
|
ingredient = ' '.join(tokens[:start])
|
||||||
else:
|
else:
|
||||||
ingredient, note = parse_ingredient_with_comma(tokens)
|
ingredient, note = self.parse_ingredient_with_comma(tokens)
|
||||||
return ingredient, note
|
return ingredient, note
|
||||||
|
|
||||||
|
def parse(self, x):
|
||||||
def parse(x):
|
|
||||||
# initialize default values
|
# initialize default values
|
||||||
amount = 0
|
amount = 0
|
||||||
unit = ''
|
unit = ''
|
||||||
@ -122,7 +137,7 @@ def parse(x):
|
|||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
# try to parse first argument as amount
|
# try to parse first argument as amount
|
||||||
amount, unit, unit_note = parse_amount(tokens[0])
|
amount, unit, unit_note = self.parse_amount(tokens[0])
|
||||||
# only try to parse second argument as amount if there are at least
|
# only try to parse second argument as amount if there are at least
|
||||||
# three arguments if it already has a unit there can't be
|
# three arguments if it already has a unit there can't be
|
||||||
# a fraction for the amount
|
# a fraction for the amount
|
||||||
@ -133,31 +148,31 @@ def parse(x):
|
|||||||
# probably not the best method to do it, but I didn't want to make an if check and paste the exact same thing in the else as already is in the except # noqa: E501
|
# probably not the best method to do it, but I didn't want to make an if check and paste the exact same thing in the else as already is in the except # noqa: E501
|
||||||
raise ValueError
|
raise ValueError
|
||||||
# try to parse second argument as amount and add that, in case of '2 1/2' or '2 ½'
|
# try to parse second argument as amount and add that, in case of '2 1/2' or '2 ½'
|
||||||
amount += parse_fraction(tokens[1])
|
amount += self.parse_fraction(tokens[1])
|
||||||
# assume that units can't end with a comma
|
# assume that units can't end with a comma
|
||||||
if len(tokens) > 3 and not tokens[2].endswith(','):
|
if len(tokens) > 3 and not tokens[2].endswith(','):
|
||||||
# try to use third argument as unit and everything else as ingredient, use everything as ingredient if it fails # noqa: E501
|
# try to use third argument as unit and everything else as ingredient, use everything as ingredient if it fails # noqa: E501
|
||||||
try:
|
try:
|
||||||
ingredient, note = parse_ingredient(tokens[3:])
|
ingredient, note = self.parse_ingredient(tokens[3:])
|
||||||
unit = tokens[2]
|
unit = tokens[2]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
ingredient, note = parse_ingredient(tokens[2:])
|
ingredient, note = self.parse_ingredient(tokens[2:])
|
||||||
else:
|
else:
|
||||||
ingredient, note = parse_ingredient(tokens[2:])
|
ingredient, note = self.parse_ingredient(tokens[2:])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# assume that units can't end with a comma
|
# assume that units can't end with a comma
|
||||||
if not tokens[1].endswith(','):
|
if not tokens[1].endswith(','):
|
||||||
# try to use second argument as unit and everything else as ingredient, use everything as ingredient if it fails # noqa: E501
|
# try to use second argument as unit and everything else as ingredient, use everything as ingredient if it fails # noqa: E501
|
||||||
try:
|
try:
|
||||||
ingredient, note = parse_ingredient(tokens[2:])
|
ingredient, note = self.parse_ingredient(tokens[2:])
|
||||||
if unit == '':
|
if unit == '':
|
||||||
unit = tokens[1]
|
unit = tokens[1]
|
||||||
else:
|
else:
|
||||||
note = tokens[1]
|
note = tokens[1]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
ingredient, note = parse_ingredient(tokens[1:])
|
ingredient, note = self.parse_ingredient(tokens[1:])
|
||||||
else:
|
else:
|
||||||
ingredient, note = parse_ingredient(tokens[1:])
|
ingredient, note = self.parse_ingredient(tokens[1:])
|
||||||
else:
|
else:
|
||||||
# only two arguments, first one is the amount
|
# only two arguments, first one is the amount
|
||||||
# which means this is the ingredient
|
# which means this is the ingredient
|
||||||
@ -166,7 +181,7 @@ def parse(x):
|
|||||||
try:
|
try:
|
||||||
# can't parse first argument as amount
|
# can't parse first argument as amount
|
||||||
# -> no unit -> parse everything as ingredient
|
# -> no unit -> parse everything as ingredient
|
||||||
ingredient, note = parse_ingredient(tokens)
|
ingredient, note = self.parse_ingredient(tokens)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
ingredient = ' '.join(tokens[1:])
|
ingredient = ' '.join(tokens[1:])
|
||||||
|
|
||||||
@ -174,21 +189,28 @@ def parse(x):
|
|||||||
note += ' ' + unit_note
|
note += ' ' + unit_note
|
||||||
return amount, unit.strip(), ingredient.strip(), note.strip()
|
return amount, unit.strip(), ingredient.strip(), note.strip()
|
||||||
|
|
||||||
|
def get_unit(self, unit):
|
||||||
# small utility functions to prevent emtpy unit/food creation
|
"""
|
||||||
def get_unit(unit, space):
|
Get or create a unit for given space respecting possible automations
|
||||||
|
:param unit: string unit
|
||||||
|
:return: None if unit passed is invalid, Unit object otherwise
|
||||||
|
"""
|
||||||
if not unit:
|
if not unit:
|
||||||
return None
|
return None
|
||||||
if len(unit) > 0:
|
if len(unit) > 0:
|
||||||
u, created = Unit.objects.get_or_create(name=unit, space=space)
|
u, created = Unit.objects.get_or_create(name=unit, space=self.request.space)
|
||||||
return u
|
return u
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_food(self, food):
|
||||||
def get_food(food, space):
|
"""
|
||||||
|
Get or create a food for given space respecting possible automations
|
||||||
|
:param food: string food
|
||||||
|
:return: None if food passed is invalid, Food object otherwise
|
||||||
|
"""
|
||||||
if not food:
|
if not food:
|
||||||
return None
|
return None
|
||||||
if len(food) > 0:
|
if len(food) > 0:
|
||||||
f, created = Food.objects.get_or_create(name=food, space=space)
|
f, created = Food.objects.get_or_create(name=food, space=self.request.space)
|
||||||
return f
|
return f
|
||||||
return None
|
return None
|
||||||
|
@ -10,7 +10,7 @@ from recipe_scrapers._utils import get_host_name, normalize_string
|
|||||||
from urllib.parse import unquote
|
from urllib.parse import unquote
|
||||||
|
|
||||||
|
|
||||||
def get_recipe_from_source(text, url, space):
|
def get_recipe_from_source(text, url, request):
|
||||||
def build_node(k, v):
|
def build_node(k, v):
|
||||||
if isinstance(v, dict):
|
if isinstance(v, dict):
|
||||||
node = {
|
node = {
|
||||||
@ -103,7 +103,7 @@ def get_recipe_from_source(text, url, space):
|
|||||||
parse_list.append(el)
|
parse_list.append(el)
|
||||||
scrape = text_scraper(text, url=url)
|
scrape = text_scraper(text, url=url)
|
||||||
|
|
||||||
recipe_json = helper.get_from_scraper(scrape, space)
|
recipe_json = helper.get_from_scraper(scrape, request)
|
||||||
|
|
||||||
for el in parse_list:
|
for el in parse_list:
|
||||||
temp_tree = []
|
temp_tree = []
|
||||||
|
@ -3,14 +3,14 @@ import re
|
|||||||
from isodate import parse_duration as iso_parse_duration
|
from isodate import parse_duration as iso_parse_duration
|
||||||
from isodate.isoerror import ISO8601Error
|
from isodate.isoerror import ISO8601Error
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse as parse_single_ingredient
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.models import Keyword
|
from cookbook.models import Keyword
|
||||||
from django.utils.dateparse import parse_duration
|
from django.utils.dateparse import parse_duration
|
||||||
from html import unescape
|
from html import unescape
|
||||||
from recipe_scrapers._utils import get_minutes
|
from recipe_scrapers._utils import get_minutes
|
||||||
|
|
||||||
|
|
||||||
def get_from_scraper(scrape, space):
|
def get_from_scraper(scrape, request):
|
||||||
# converting the scrape_me object to the existing json format based on ld+json
|
# converting the scrape_me object to the existing json format based on ld+json
|
||||||
recipe_json = {}
|
recipe_json = {}
|
||||||
try:
|
try:
|
||||||
@ -91,15 +91,16 @@ def get_from_scraper(scrape, space):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
recipe_json['keywords'] = parse_keywords(list(set(map(str.casefold, keywords))), space)
|
recipe_json['keywords'] = parse_keywords(list(set(map(str.casefold, keywords))), request.space)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
recipe_json['keywords'] = keywords
|
recipe_json['keywords'] = keywords
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(request, True)
|
||||||
try:
|
try:
|
||||||
ingredients = []
|
ingredients = []
|
||||||
for x in scrape.ingredients():
|
for x in scrape.ingredients():
|
||||||
try:
|
try:
|
||||||
amount, unit, ingredient, note = parse_single_ingredient(x)
|
amount, unit, ingredient, note = ingredient_parser.parse(x)
|
||||||
ingredients.append(
|
ingredients.append(
|
||||||
{
|
{
|
||||||
'amount': amount,
|
'amount': amount,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient
|
from cookbook.models import Recipe, Step, Ingredient
|
||||||
|
|
||||||
@ -42,11 +42,12 @@ class ChefTap(Integration):
|
|||||||
step.instruction += '\n' + source_url
|
step.instruction += '\n' + source_url
|
||||||
step.save()
|
step.save()
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in ingredients:
|
for ingredient in ingredients:
|
||||||
if len(ingredient.strip()) > 0:
|
if len(ingredient.strip()) > 0:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -3,7 +3,7 @@ from io import BytesIO
|
|||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from cookbook.helper.image_processing import get_filetype
|
from cookbook.helper.image_processing import get_filetype
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||||
|
|
||||||
@ -58,10 +58,11 @@ class Chowdown(Integration):
|
|||||||
instruction='\n'.join(directions) + '\n\n' + '\n'.join(descriptions), space=self.request.space,
|
instruction='\n'.join(directions) + '\n\n' + '\n'.join(descriptions), space=self.request.space,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in ingredients:
|
for ingredient in ingredients:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -6,7 +6,7 @@ from io import BytesIO
|
|||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
@ -53,11 +53,12 @@ class CookBookApp(Integration):
|
|||||||
step.save()
|
step.save()
|
||||||
recipe.steps.add(step)
|
recipe.steps.add(step)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in recipe_yml['ingredients'].split('\n'):
|
for ingredient in recipe_yml['ingredients'].split('\n'):
|
||||||
if ingredient.strip() != '':
|
if ingredient.strip() != '':
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -2,7 +2,7 @@ import base64
|
|||||||
import json
|
import json
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient
|
from cookbook.models import Recipe, Step, Ingredient
|
||||||
|
|
||||||
@ -34,11 +34,12 @@ class Domestica(Integration):
|
|||||||
if file['source'] != '':
|
if file['source'] != '':
|
||||||
step.instruction += '\n' + file['source']
|
step.instruction += '\n' + file['source']
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in file['ingredients'].split('\n'):
|
for ingredient in file['ingredients'].split('\n'):
|
||||||
if len(ingredient.strip()) > 0:
|
if len(ingredient.strip()) > 0:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -4,7 +4,7 @@ from io import BytesIO
|
|||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from cookbook.helper.image_processing import get_filetype
|
from cookbook.helper.image_processing import get_filetype
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient
|
from cookbook.models import Recipe, Step, Ingredient
|
||||||
|
|
||||||
@ -37,17 +37,18 @@ class Mealie(Integration):
|
|||||||
if len(recipe_json['description'].strip()) > 500:
|
if len(recipe_json['description'].strip()) > 500:
|
||||||
step.instruction = recipe_json['description'].strip() + '\n\n' + step.instruction
|
step.instruction = recipe_json['description'].strip() + '\n\n' + step.instruction
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in recipe_json['recipe_ingredient']:
|
for ingredient in recipe_json['recipe_ingredient']:
|
||||||
try:
|
try:
|
||||||
if ingredient['food']:
|
if ingredient['food']:
|
||||||
f = get_food(ingredient['food'], self.request.space)
|
f = ingredient_parser.get_food(ingredient['food'])
|
||||||
u = get_unit(ingredient['unit'], self.request.space)
|
u = ingredient_parser.get_unit(ingredient['unit'])
|
||||||
amount = ingredient['quantity']
|
amount = ingredient['quantity']
|
||||||
note = ingredient['note']
|
note = ingredient['note']
|
||||||
else:
|
else:
|
||||||
amount, unit, ingredient, note = parse(ingredient['note'])
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient['note'])
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||||
|
|
||||||
@ -42,11 +42,12 @@ class MealMaster(Integration):
|
|||||||
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
|
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in ingredients:
|
for ingredient in ingredients:
|
||||||
if len(ingredient.strip()) > 0:
|
if len(ingredient.strip()) > 0:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -4,7 +4,7 @@ from io import BytesIO
|
|||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from cookbook.helper.image_processing import get_filetype
|
from cookbook.helper.image_processing import get_filetype
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient
|
from cookbook.models import Recipe, Step, Ingredient
|
||||||
|
|
||||||
@ -39,6 +39,7 @@ class NextcloudCookbook(Integration):
|
|||||||
|
|
||||||
ingredients_added = True
|
ingredients_added = True
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in recipe_json['recipeIngredient']:
|
for ingredient in recipe_json['recipeIngredient']:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = get_food(ingredient, self.request.space)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient
|
from cookbook.models import Recipe, Step, Ingredient
|
||||||
|
|
||||||
@ -23,9 +23,10 @@ class OpenEats(Integration):
|
|||||||
|
|
||||||
step = Step.objects.create(instruction=instructions, space=self.request.space,)
|
step = Step.objects.create(instruction=instructions, space=self.request.space,)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in file['ingredients']:
|
for ingredient in file['ingredients']:
|
||||||
f = get_food(ingredient['food'], self.request.space)
|
f = ingredient_parser.get_food(ingredient['food'])
|
||||||
u = get_unit(ingredient['unit'], self.request.space)
|
u = ingredient_parser.get_unit(ingredient['unit'])
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=ingredient['amount'], space=self.request.space,
|
food=f, unit=u, amount=ingredient['amount'], space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -4,7 +4,7 @@ import json
|
|||||||
import re
|
import re
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
@ -66,12 +66,13 @@ class Paprika(Integration):
|
|||||||
keyword, created = Keyword.objects.get_or_create(name=c.strip(), space=self.request.space)
|
keyword, created = Keyword.objects.get_or_create(name=c.strip(), space=self.request.space)
|
||||||
recipe.keywords.add(keyword)
|
recipe.keywords.add(keyword)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
try:
|
try:
|
||||||
for ingredient in recipe_json['ingredients'].split('\n'):
|
for ingredient in recipe_json['ingredients'].split('\n'):
|
||||||
if len(ingredient.strip()) > 0:
|
if len(ingredient.strip()) > 0:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient
|
from cookbook.models import Recipe, Step, Ingredient
|
||||||
|
|
||||||
@ -38,11 +38,12 @@ class Pepperplate(Integration):
|
|||||||
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
|
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in ingredients:
|
for ingredient in ingredients:
|
||||||
if len(ingredient.strip()) > 0:
|
if len(ingredient.strip()) > 0:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -2,7 +2,7 @@ from io import BytesIO
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||||
|
|
||||||
@ -53,11 +53,12 @@ class Plantoeat(Integration):
|
|||||||
keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space)
|
keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space)
|
||||||
recipe.keywords.add(keyword)
|
recipe.keywords.add(keyword)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in ingredients:
|
for ingredient in ingredients:
|
||||||
if len(ingredient.strip()) > 0:
|
if len(ingredient.strip()) > 0:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -6,7 +6,7 @@ from zipfile import ZipFile
|
|||||||
import imghdr
|
import imghdr
|
||||||
|
|
||||||
from cookbook.helper.image_processing import get_filetype
|
from cookbook.helper.image_processing import get_filetype
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||||
|
|
||||||
@ -55,11 +55,12 @@ class RecetteTek(Integration):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Process the ingredients. Assumes 1 ingredient per line.
|
# Process the ingredients. Assumes 1 ingredient per line.
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in file['ingredients'].split('\n'):
|
for ingredient in file['ingredients'].split('\n'):
|
||||||
if len(ingredient.strip()) > 0:
|
if len(ingredient.strip()) > 0:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -3,7 +3,7 @@ from bs4 import BeautifulSoup
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.helper.recipe_url_import import parse_servings, iso_duration_to_minutes
|
from cookbook.helper.recipe_url_import import parse_servings, iso_duration_to_minutes
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||||
@ -41,12 +41,13 @@ class RecipeKeeper(Integration):
|
|||||||
|
|
||||||
step = Step.objects.create(instruction='', space=self.request.space,)
|
step = Step.objects.create(instruction='', space=self.request.space,)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):
|
for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):
|
||||||
if ingredient.text == "":
|
if ingredient.text == "":
|
||||||
continue
|
continue
|
||||||
amount, unit, ingredient, note = parse(ingredient.text.strip())
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient.text.strip())
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -3,7 +3,7 @@ from io import BytesIO
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient
|
from cookbook.models import Recipe, Step, Ingredient
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ class RecipeSage(Integration):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('failed to parse yield or time ', str(e))
|
print('failed to parse yield or time ', str(e))
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request,True)
|
||||||
ingredients_added = False
|
ingredients_added = False
|
||||||
for s in file['recipeInstructions']:
|
for s in file['recipeInstructions']:
|
||||||
step = Step.objects.create(
|
step = Step.objects.create(
|
||||||
@ -40,9 +41,9 @@ class RecipeSage(Integration):
|
|||||||
ingredients_added = True
|
ingredients_added = True
|
||||||
|
|
||||||
for ingredient in file['recipeIngredient']:
|
for ingredient in file['recipeIngredient']:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
from cookbook.models import Recipe, Step, Ingredient, Keyword
|
||||||
|
|
||||||
@ -41,11 +41,12 @@ class RezKonv(Integration):
|
|||||||
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
|
instruction='\n'.join(directions) + '\n\n', space=self.request.space,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in ingredients:
|
for ingredient in ingredients:
|
||||||
if len(ingredient.strip()) > 0:
|
if len(ingredient.strip()) > 0:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Ingredient
|
from cookbook.models import Recipe, Step, Ingredient
|
||||||
|
|
||||||
@ -45,10 +45,11 @@ class Safron(Integration):
|
|||||||
|
|
||||||
step = Step.objects.create(instruction='\n'.join(directions), space=self.request.space, )
|
step = Step.objects.create(instruction='\n'.join(directions), space=self.request.space, )
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(self.request, True)
|
||||||
for ingredient in ingredients:
|
for ingredient in ingredients:
|
||||||
amount, unit, ingredient, note = parse(ingredient)
|
amount, unit, ingredient, note = ingredient_parser.parse(ingredient)
|
||||||
f = get_food(ingredient, self.request.space)
|
f = ingredient_parser.get_food(ingredient)
|
||||||
u = get_unit(unit, self.request.space)
|
u = ingredient_parser.get_unit(unit)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
food=f, unit=u, amount=amount, note=note, space=self.request.space,
|
||||||
))
|
))
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from cookbook.helper.ingredient_parser import parse
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
|
|
||||||
|
|
||||||
def test_ingredient_parser():
|
def test_ingredient_parser():
|
||||||
@ -64,8 +64,10 @@ def test_ingredient_parser():
|
|||||||
# an amount # and it starts with a lowercase letter, then that
|
# an amount # and it starts with a lowercase letter, then that
|
||||||
# is a unit ("etwas", "evtl.") does not apply to English tho
|
# is a unit ("etwas", "evtl.") does not apply to English tho
|
||||||
|
|
||||||
|
ingredient_parser = IngredientParser(None, False, ignore_automations=True)
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
for key, val in expectations.items():
|
for key, val in expectations.items():
|
||||||
count += 1
|
count += 1
|
||||||
parsed = parse(key)
|
parsed = ingredient_parser.parse(key)
|
||||||
assert val == parsed
|
assert val == parsed
|
||||||
|
@ -31,7 +31,7 @@ from rest_framework.viewsets import ViewSetMixin
|
|||||||
from treebeard.exceptions import PathOverflow, InvalidMoveToDescendant, InvalidPosition
|
from treebeard.exceptions import PathOverflow, InvalidMoveToDescendant, InvalidPosition
|
||||||
|
|
||||||
from cookbook.helper.image_processing import handle_image
|
from cookbook.helper.image_processing import handle_image
|
||||||
from cookbook.helper.ingredient_parser import parse
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest,
|
from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest,
|
||||||
CustomIsOwner, CustomIsShare,
|
CustomIsOwner, CustomIsShare,
|
||||||
CustomIsShared, CustomIsUser,
|
CustomIsShared, CustomIsUser,
|
||||||
@ -853,11 +853,11 @@ def recipe_from_source(request):
|
|||||||
},
|
},
|
||||||
status=400)
|
status=400)
|
||||||
else:
|
else:
|
||||||
return JsonResponse({"recipe_json": get_from_scraper(scrape, request.space)})
|
return JsonResponse({"recipe_json": get_from_scraper(scrape, request)})
|
||||||
elif (mode == 'source') or (mode == 'url' and auto == 'false'):
|
elif (mode == 'source') or (mode == 'url' and auto == 'false'):
|
||||||
if not data or data == 'undefined':
|
if not data or data == 'undefined':
|
||||||
data = requests.get(url, headers=HEADERS).content
|
data = requests.get(url, headers=HEADERS).content
|
||||||
recipe_json, recipe_tree, recipe_html, images = get_recipe_from_source(data, url, request.space)
|
recipe_json, recipe_tree, recipe_html, images = get_recipe_from_source(data, url, request)
|
||||||
if len(recipe_tree) == 0 and len(recipe_json) == 0:
|
if len(recipe_tree) == 0 and len(recipe_json) == 0:
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
{
|
{
|
||||||
@ -893,7 +893,9 @@ def get_backup(request):
|
|||||||
@group_required('user')
|
@group_required('user')
|
||||||
def ingredient_from_string(request):
|
def ingredient_from_string(request):
|
||||||
text = request.POST['text']
|
text = request.POST['text']
|
||||||
amount, unit, food, note = parse(text)
|
|
||||||
|
ingredient_parser = IngredientParser(request, False)
|
||||||
|
amount, unit, food, note = ingredient_parser.parse(text)
|
||||||
|
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@ from django.http import JsonResponse
|
|||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
from cookbook.helper.ingredient_parser import parse, get_unit, get_food
|
from cookbook.helper.ingredient_parser import IngredientParser
|
||||||
from cookbook.helper.permission_helper import group_required
|
from cookbook.helper.permission_helper import group_required
|
||||||
from cookbook.models import TelegramBot, ShoppingList, ShoppingListEntry
|
from cookbook.models import TelegramBot, ShoppingList, ShoppingListEntry
|
||||||
|
|
||||||
@ -49,9 +49,12 @@ def hook(request, token):
|
|||||||
if not sl:
|
if not sl:
|
||||||
sl = ShoppingList.objects.create(created_by=tb.created_by, space=tb.space)
|
sl = ShoppingList.objects.create(created_by=tb.created_by, space=tb.space)
|
||||||
|
|
||||||
amount, unit, ingredient, note = parse(data['message']['text'])
|
request.space = tb.space # TODO this is likely a bad idea. Verify and test
|
||||||
f = get_food(ingredient, tb.space)
|
request.user = tb.created_by
|
||||||
u = get_unit(unit, tb.space)
|
ingredient_parser = IngredientParser(request, False)
|
||||||
|
amount, unit, ingredient, note = ingredient_parser.parse(data['message']['text'])
|
||||||
|
f = ingredient_parser.get_food(ingredient)
|
||||||
|
u = ingredient_parser.get_unit(unit)
|
||||||
sl.entries.add(
|
sl.entries.add(
|
||||||
ShoppingListEntry.objects.create(
|
ShoppingListEntry.objects.create(
|
||||||
food=f, unit=u, amount=amount
|
food=f, unit=u, amount=amount
|
||||||
|
@ -26,10 +26,9 @@ from cookbook.forms import (CommentForm, Recipe, User,
|
|||||||
UserCreateForm, UserNameForm, UserPreference,
|
UserCreateForm, UserNameForm, UserPreference,
|
||||||
UserPreferenceForm, SpaceJoinForm, SpaceCreateForm,
|
UserPreferenceForm, SpaceJoinForm, SpaceCreateForm,
|
||||||
SearchPreferenceForm)
|
SearchPreferenceForm)
|
||||||
from cookbook.helper.ingredient_parser import parse
|
|
||||||
from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission
|
from cookbook.helper.permission_helper import group_required, share_link_valid, has_group_permission
|
||||||
from cookbook.models import (Comment, CookLog, InviteLink, MealPlan,
|
from cookbook.models import (Comment, CookLog, InviteLink, MealPlan,
|
||||||
RecipeBook, RecipeBookEntry, ViewLog, ShoppingList, Space, Keyword, RecipeImport, Unit,
|
ViewLog, ShoppingList, Space, Keyword, RecipeImport, Unit,
|
||||||
Food, UserFile, ShareLink)
|
Food, UserFile, ShareLink)
|
||||||
from cookbook.tables import (CookLogTable, RecipeTable, RecipeTableSmall,
|
from cookbook.tables import (CookLogTable, RecipeTable, RecipeTableSmall,
|
||||||
ViewLogTable, InviteLinkTable)
|
ViewLogTable, InviteLinkTable)
|
||||||
|
@ -8,11 +8,22 @@
|
|||||||
:show="show_modal"
|
:show="show_modal"
|
||||||
@finish-action="finishAction"/>
|
@finish-action="finishAction"/>
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-2 d-none d-md-block">
|
<div class="col-md-2 d-none d-md-block">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-8 col-12">
|
<div class="col-xl-8 col-12">
|
||||||
<div class="container-fluid d-flex flex-column flex-grow-1">
|
<div class="container-fluid d-flex flex-column flex-grow-1">
|
||||||
|
|
||||||
|
<div class="row" v-if="this_model === Models.AUTOMATION">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<b-alert show variant="warning">
|
||||||
|
<b-badge>BETA</b-badge>
|
||||||
|
{{ $t('warning_feature_beta') }}
|
||||||
|
</b-alert>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6" style="margin-top: 1vh">
|
<div class="col-md-6" style="margin-top: 1vh">
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
</b-dropdown-item>
|
</b-dropdown-item>
|
||||||
|
|
||||||
<b-dropdown-item v-if="show_merge" v-on:click="$emit('item-action', 'merge-automate')">
|
<b-dropdown-item v-if="show_merge" v-on:click="$emit('item-action', 'merge-automate')">
|
||||||
<i class="fas fa-robot fa-fw"></i> {{$t('Merge')}} & {{$t('Automate')}}
|
<i class="fas fa-robot fa-fw"></i> {{$t('Merge')}} & {{$t('Automate')}} <b-badge v-b-tooltip.hover :title="$t('warning_feature_beta')">BETA</b-badge>
|
||||||
</b-dropdown-item>
|
</b-dropdown-item>
|
||||||
|
|
||||||
</b-dropdown>
|
</b-dropdown>
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
<i class="fas fa-compress-arrows-alt fa-fw"></i> <b>{{$t('Merge')}}</b>: <span v-html="$t('merge_confirmation', {'source': source.name,'target':item.name})"></span>
|
<i class="fas fa-compress-arrows-alt fa-fw"></i> <b>{{$t('Merge')}}</b>: <span v-html="$t('merge_confirmation', {'source': source.name,'target':item.name})"></span>
|
||||||
</b-list-group-item>
|
</b-list-group-item>
|
||||||
<b-list-group-item v-if="useMerge" action v-on:click="$emit('item-action',{'action': 'merge-automate', 'target': item, 'source': source}); closeMenu()">
|
<b-list-group-item v-if="useMerge" action v-on:click="$emit('item-action',{'action': 'merge-automate', 'target': item, 'source': source}); closeMenu()">
|
||||||
<i class="fas fa-robot fa-fw"></i> <b>{{$t('Merge')}} & {{$t('Automate')}}</b>: <span v-html="$t('merge_confirmation', {'source': source.name,'target':item.name})"></span> {{$t('create_rule')}}
|
<i class="fas fa-robot fa-fw"></i> <b>{{$t('Merge')}} & {{$t('Automate')}}</b>: <span v-html="$t('merge_confirmation', {'source': source.name,'target':item.name})"></span> {{$t('create_rule')}} <b-badge v-b-tooltip.hover :title="$t('warning_feature_beta')" >BETA</b-badge>
|
||||||
</b-list-group-item>
|
</b-list-group-item>
|
||||||
<b-list-group-item action v-on:click="closeMenu()">
|
<b-list-group-item action v-on:click="closeMenu()">
|
||||||
<i class="fas fa-times fa-fw"></i> <b>{{$t('Cancel')}}</b>
|
<i class="fas fa-times fa-fw"></i> <b>{{$t('Cancel')}}</b>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"warning_feature_beta": "This feature is currently in a BETA (testing) state. Please expect bugs and possibly breaking changes in the future (possibly loosing feature related data) when using this feature.",
|
||||||
"err_fetching_resource": "There was an error fetching a resource!",
|
"err_fetching_resource": "There was an error fetching a resource!",
|
||||||
"err_creating_resource": "There was an error creating a resource!",
|
"err_creating_resource": "There was an error creating a resource!",
|
||||||
"err_updating_resource": "There was an error updating a resource!",
|
"err_updating_resource": "There was an error updating a resource!",
|
||||||
|
@ -1,183 +1,294 @@
|
|||||||
{
|
{
|
||||||
"status": "done",
|
"status": "done",
|
||||||
"assets": {
|
"assets": {
|
||||||
"../../templates/sw.js": {
|
|
||||||
"name": "../../templates/sw.js",
|
|
||||||
"path": "..\\..\\templates\\sw.js"
|
|
||||||
},
|
|
||||||
"css/chunk-vendors.css": {
|
|
||||||
"name": "css/chunk-vendors.css",
|
|
||||||
"path": "css\\chunk-vendors.css"
|
|
||||||
},
|
|
||||||
"js/chunk-vendors.js": {
|
"js/chunk-vendors.js": {
|
||||||
"name": "js/chunk-vendors.js",
|
"name": "js/chunk-vendors.js",
|
||||||
"path": "js\\chunk-vendors.js"
|
"path": "js\\chunk-vendors.js",
|
||||||
},
|
"publicPath": "http://localhost:8080/js/chunk-vendors.js"
|
||||||
"css/cookbook_view.css": {
|
|
||||||
"name": "css/cookbook_view.css",
|
|
||||||
"path": "css\\cookbook_view.css"
|
|
||||||
},
|
},
|
||||||
"js/cookbook_view.js": {
|
"js/cookbook_view.js": {
|
||||||
"name": "js/cookbook_view.js",
|
"name": "js/cookbook_view.js",
|
||||||
"path": "js\\cookbook_view.js"
|
"path": "js\\cookbook_view.js",
|
||||||
},
|
"publicPath": "http://localhost:8080/js/cookbook_view.js"
|
||||||
"css/edit_internal_recipe.css": {
|
|
||||||
"name": "css/edit_internal_recipe.css",
|
|
||||||
"path": "css\\edit_internal_recipe.css"
|
|
||||||
},
|
},
|
||||||
"js/edit_internal_recipe.js": {
|
"js/edit_internal_recipe.js": {
|
||||||
"name": "js/edit_internal_recipe.js",
|
"name": "js/edit_internal_recipe.js",
|
||||||
"path": "js\\edit_internal_recipe.js"
|
"path": "js\\edit_internal_recipe.js",
|
||||||
|
"publicPath": "http://localhost:8080/js/edit_internal_recipe.js"
|
||||||
},
|
},
|
||||||
"js/import_response_view.js": {
|
"js/import_response_view.js": {
|
||||||
"name": "js/import_response_view.js",
|
"name": "js/import_response_view.js",
|
||||||
"path": "js\\import_response_view.js"
|
"path": "js\\import_response_view.js",
|
||||||
},
|
"publicPath": "http://localhost:8080/js/import_response_view.js"
|
||||||
"css/meal_plan_view.css": {
|
|
||||||
"name": "css/meal_plan_view.css",
|
|
||||||
"path": "css\\meal_plan_view.css"
|
|
||||||
},
|
},
|
||||||
"js/meal_plan_view.js": {
|
"js/meal_plan_view.js": {
|
||||||
"name": "js/meal_plan_view.js",
|
"name": "js/meal_plan_view.js",
|
||||||
"path": "js\\meal_plan_view.js"
|
"path": "js\\meal_plan_view.js",
|
||||||
},
|
"publicPath": "http://localhost:8080/js/meal_plan_view.js"
|
||||||
"css/model_list_view.css": {
|
|
||||||
"name": "css/model_list_view.css",
|
|
||||||
"path": "css\\model_list_view.css"
|
|
||||||
},
|
},
|
||||||
"js/model_list_view.js": {
|
"js/model_list_view.js": {
|
||||||
"name": "js/model_list_view.js",
|
"name": "js/model_list_view.js",
|
||||||
"path": "js\\model_list_view.js"
|
"path": "js\\model_list_view.js",
|
||||||
|
"publicPath": "http://localhost:8080/js/model_list_view.js"
|
||||||
},
|
},
|
||||||
"js/offline_view.js": {
|
"js/offline_view.js": {
|
||||||
"name": "js/offline_view.js",
|
"name": "js/offline_view.js",
|
||||||
"path": "js\\offline_view.js"
|
"path": "js\\offline_view.js",
|
||||||
},
|
"publicPath": "http://localhost:8080/js/offline_view.js"
|
||||||
"css/recipe_search_view.css": {
|
|
||||||
"name": "css/recipe_search_view.css",
|
|
||||||
"path": "css\\recipe_search_view.css"
|
|
||||||
},
|
},
|
||||||
"js/recipe_search_view.js": {
|
"js/recipe_search_view.js": {
|
||||||
"name": "js/recipe_search_view.js",
|
"name": "js/recipe_search_view.js",
|
||||||
"path": "js\\recipe_search_view.js"
|
"path": "js\\recipe_search_view.js",
|
||||||
},
|
"publicPath": "http://localhost:8080/js/recipe_search_view.js"
|
||||||
"css/recipe_view.css": {
|
|
||||||
"name": "css/recipe_view.css",
|
|
||||||
"path": "css\\recipe_view.css"
|
|
||||||
},
|
},
|
||||||
"js/recipe_view.js": {
|
"js/recipe_view.js": {
|
||||||
"name": "js/recipe_view.js",
|
"name": "js/recipe_view.js",
|
||||||
"path": "js\\recipe_view.js"
|
"path": "js\\recipe_view.js",
|
||||||
|
"publicPath": "http://localhost:8080/js/recipe_view.js"
|
||||||
},
|
},
|
||||||
"js/supermarket_view.js": {
|
"js/supermarket_view.js": {
|
||||||
"name": "js/supermarket_view.js",
|
"name": "js/supermarket_view.js",
|
||||||
"path": "js\\supermarket_view.js"
|
"path": "js\\supermarket_view.js",
|
||||||
|
"publicPath": "http://localhost:8080/js/supermarket_view.js"
|
||||||
},
|
},
|
||||||
"js/user_file_view.js": {
|
"js/user_file_view.js": {
|
||||||
"name": "js/user_file_view.js",
|
"name": "js/user_file_view.js",
|
||||||
"path": "js\\user_file_view.js"
|
"path": "js\\user_file_view.js",
|
||||||
|
"publicPath": "http://localhost:8080/js/user_file_view.js"
|
||||||
},
|
},
|
||||||
"recipe_search_view.html": {
|
"recipe_search_view.html": {
|
||||||
"name": "recipe_search_view.html",
|
"name": "recipe_search_view.html",
|
||||||
"path": "recipe_search_view.html"
|
"path": "recipe_search_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/recipe_search_view.html"
|
||||||
},
|
},
|
||||||
"recipe_view.html": {
|
"recipe_view.html": {
|
||||||
"name": "recipe_view.html",
|
"name": "recipe_view.html",
|
||||||
"path": "recipe_view.html"
|
"path": "recipe_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/recipe_view.html"
|
||||||
},
|
},
|
||||||
"offline_view.html": {
|
"offline_view.html": {
|
||||||
"name": "offline_view.html",
|
"name": "offline_view.html",
|
||||||
"path": "offline_view.html"
|
"path": "offline_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/offline_view.html"
|
||||||
},
|
},
|
||||||
"import_response_view.html": {
|
"import_response_view.html": {
|
||||||
"name": "import_response_view.html",
|
"name": "import_response_view.html",
|
||||||
"path": "import_response_view.html"
|
"path": "import_response_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/import_response_view.html"
|
||||||
},
|
},
|
||||||
"supermarket_view.html": {
|
"supermarket_view.html": {
|
||||||
"name": "supermarket_view.html",
|
"name": "supermarket_view.html",
|
||||||
"path": "supermarket_view.html"
|
"path": "supermarket_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/supermarket_view.html"
|
||||||
},
|
},
|
||||||
"user_file_view.html": {
|
"user_file_view.html": {
|
||||||
"name": "user_file_view.html",
|
"name": "user_file_view.html",
|
||||||
"path": "user_file_view.html"
|
"path": "user_file_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/user_file_view.html"
|
||||||
},
|
},
|
||||||
"model_list_view.html": {
|
"model_list_view.html": {
|
||||||
"name": "model_list_view.html",
|
"name": "model_list_view.html",
|
||||||
"path": "model_list_view.html"
|
"path": "model_list_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.html"
|
||||||
},
|
},
|
||||||
"edit_internal_recipe.html": {
|
"edit_internal_recipe.html": {
|
||||||
"name": "edit_internal_recipe.html",
|
"name": "edit_internal_recipe.html",
|
||||||
"path": "edit_internal_recipe.html"
|
"path": "edit_internal_recipe.html",
|
||||||
|
"publicPath": "http://localhost:8080/edit_internal_recipe.html"
|
||||||
},
|
},
|
||||||
"cookbook_view.html": {
|
"cookbook_view.html": {
|
||||||
"name": "cookbook_view.html",
|
"name": "cookbook_view.html",
|
||||||
"path": "cookbook_view.html"
|
"path": "cookbook_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/cookbook_view.html"
|
||||||
},
|
},
|
||||||
"meal_plan_view.html": {
|
"meal_plan_view.html": {
|
||||||
"name": "meal_plan_view.html",
|
"name": "meal_plan_view.html",
|
||||||
"path": "meal_plan_view.html"
|
"path": "meal_plan_view.html",
|
||||||
|
"publicPath": "http://localhost:8080/meal_plan_view.html"
|
||||||
},
|
},
|
||||||
"manifest.json": {
|
"manifest.json": {
|
||||||
"name": "manifest.json",
|
"name": "manifest.json",
|
||||||
"path": "manifest.json"
|
"path": "manifest.json",
|
||||||
|
"publicPath": "http://localhost:8080/manifest.json"
|
||||||
|
},
|
||||||
|
"model_list_view.7cf8cfb04383ac21dae2.hot-update.js": {
|
||||||
|
"name": "model_list_view.7cf8cfb04383ac21dae2.hot-update.js",
|
||||||
|
"path": "model_list_view.7cf8cfb04383ac21dae2.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.7cf8cfb04383ac21dae2.hot-update.js"
|
||||||
|
},
|
||||||
|
"7cf8cfb04383ac21dae2.hot-update.json": {
|
||||||
|
"name": "7cf8cfb04383ac21dae2.hot-update.json",
|
||||||
|
"path": "7cf8cfb04383ac21dae2.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/7cf8cfb04383ac21dae2.hot-update.json"
|
||||||
|
},
|
||||||
|
"model_list_view.65f25fe27091809f7fcf.hot-update.js": {
|
||||||
|
"name": "model_list_view.65f25fe27091809f7fcf.hot-update.js",
|
||||||
|
"path": "model_list_view.65f25fe27091809f7fcf.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.65f25fe27091809f7fcf.hot-update.js"
|
||||||
|
},
|
||||||
|
"65f25fe27091809f7fcf.hot-update.json": {
|
||||||
|
"name": "65f25fe27091809f7fcf.hot-update.json",
|
||||||
|
"path": "65f25fe27091809f7fcf.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/65f25fe27091809f7fcf.hot-update.json"
|
||||||
|
},
|
||||||
|
"model_list_view.032182ad6990812f8035.hot-update.js": {
|
||||||
|
"name": "model_list_view.032182ad6990812f8035.hot-update.js",
|
||||||
|
"path": "model_list_view.032182ad6990812f8035.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.032182ad6990812f8035.hot-update.js"
|
||||||
|
},
|
||||||
|
"032182ad6990812f8035.hot-update.json": {
|
||||||
|
"name": "032182ad6990812f8035.hot-update.json",
|
||||||
|
"path": "032182ad6990812f8035.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/032182ad6990812f8035.hot-update.json"
|
||||||
|
},
|
||||||
|
"model_list_view.cbedf3e2489989eec8dd.hot-update.js": {
|
||||||
|
"name": "model_list_view.cbedf3e2489989eec8dd.hot-update.js",
|
||||||
|
"path": "model_list_view.cbedf3e2489989eec8dd.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.cbedf3e2489989eec8dd.hot-update.js"
|
||||||
|
},
|
||||||
|
"cbedf3e2489989eec8dd.hot-update.json": {
|
||||||
|
"name": "cbedf3e2489989eec8dd.hot-update.json",
|
||||||
|
"path": "cbedf3e2489989eec8dd.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/cbedf3e2489989eec8dd.hot-update.json"
|
||||||
|
},
|
||||||
|
"model_list_view.87a9208c092e31885f51.hot-update.js": {
|
||||||
|
"name": "model_list_view.87a9208c092e31885f51.hot-update.js",
|
||||||
|
"path": "model_list_view.87a9208c092e31885f51.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.87a9208c092e31885f51.hot-update.js"
|
||||||
|
},
|
||||||
|
"87a9208c092e31885f51.hot-update.json": {
|
||||||
|
"name": "87a9208c092e31885f51.hot-update.json",
|
||||||
|
"path": "87a9208c092e31885f51.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/87a9208c092e31885f51.hot-update.json"
|
||||||
|
},
|
||||||
|
"cookbook_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "cookbook_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "cookbook_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/cookbook_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"edit_internal_recipe.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "edit_internal_recipe.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "edit_internal_recipe.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/edit_internal_recipe.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"import_response_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "import_response_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "import_response_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/import_response_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"meal_plan_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "meal_plan_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "meal_plan_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/meal_plan_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"model_list_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "model_list_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "model_list_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"offline_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "offline_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "offline_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/offline_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"recipe_search_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "recipe_search_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "recipe_search_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/recipe_search_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"recipe_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "recipe_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "recipe_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/recipe_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"supermarket_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "supermarket_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "supermarket_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/supermarket_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"user_file_view.307bb5ac629ff8f5dba5.hot-update.js": {
|
||||||
|
"name": "user_file_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"path": "user_file_view.307bb5ac629ff8f5dba5.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/user_file_view.307bb5ac629ff8f5dba5.hot-update.js"
|
||||||
|
},
|
||||||
|
"307bb5ac629ff8f5dba5.hot-update.json": {
|
||||||
|
"name": "307bb5ac629ff8f5dba5.hot-update.json",
|
||||||
|
"path": "307bb5ac629ff8f5dba5.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/307bb5ac629ff8f5dba5.hot-update.json"
|
||||||
|
},
|
||||||
|
"model_list_view.e2073a90ad8ff66f374c.hot-update.js": {
|
||||||
|
"name": "model_list_view.e2073a90ad8ff66f374c.hot-update.js",
|
||||||
|
"path": "model_list_view.e2073a90ad8ff66f374c.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.e2073a90ad8ff66f374c.hot-update.js"
|
||||||
|
},
|
||||||
|
"e2073a90ad8ff66f374c.hot-update.json": {
|
||||||
|
"name": "e2073a90ad8ff66f374c.hot-update.json",
|
||||||
|
"path": "e2073a90ad8ff66f374c.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/e2073a90ad8ff66f374c.hot-update.json"
|
||||||
|
},
|
||||||
|
"model_list_view.1b14899ea7152cc46f4e.hot-update.js": {
|
||||||
|
"name": "model_list_view.1b14899ea7152cc46f4e.hot-update.js",
|
||||||
|
"path": "model_list_view.1b14899ea7152cc46f4e.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.1b14899ea7152cc46f4e.hot-update.js"
|
||||||
|
},
|
||||||
|
"1b14899ea7152cc46f4e.hot-update.json": {
|
||||||
|
"name": "1b14899ea7152cc46f4e.hot-update.json",
|
||||||
|
"path": "1b14899ea7152cc46f4e.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/1b14899ea7152cc46f4e.hot-update.json"
|
||||||
|
},
|
||||||
|
"model_list_view.7a2ce4182c97623ab7e8.hot-update.js": {
|
||||||
|
"name": "model_list_view.7a2ce4182c97623ab7e8.hot-update.js",
|
||||||
|
"path": "model_list_view.7a2ce4182c97623ab7e8.hot-update.js",
|
||||||
|
"publicPath": "http://localhost:8080/model_list_view.7a2ce4182c97623ab7e8.hot-update.js"
|
||||||
|
},
|
||||||
|
"7a2ce4182c97623ab7e8.hot-update.json": {
|
||||||
|
"name": "7a2ce4182c97623ab7e8.hot-update.json",
|
||||||
|
"path": "7a2ce4182c97623ab7e8.hot-update.json",
|
||||||
|
"publicPath": "http://localhost:8080/7a2ce4182c97623ab7e8.hot-update.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chunks": {
|
"chunks": {
|
||||||
"recipe_search_view": [
|
"recipe_search_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"css/recipe_search_view.css",
|
|
||||||
"js/recipe_search_view.js"
|
"js/recipe_search_view.js"
|
||||||
],
|
],
|
||||||
"recipe_view": [
|
"recipe_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"css/recipe_view.css",
|
|
||||||
"js/recipe_view.js"
|
"js/recipe_view.js"
|
||||||
],
|
],
|
||||||
"offline_view": [
|
"offline_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"js/offline_view.js"
|
"js/offline_view.js"
|
||||||
],
|
],
|
||||||
"import_response_view": [
|
"import_response_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"js/import_response_view.js"
|
"js/import_response_view.js"
|
||||||
],
|
],
|
||||||
"supermarket_view": [
|
"supermarket_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"js/supermarket_view.js"
|
"js/supermarket_view.js"
|
||||||
],
|
],
|
||||||
"user_file_view": [
|
"user_file_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"js/user_file_view.js"
|
"js/user_file_view.js"
|
||||||
],
|
],
|
||||||
"model_list_view": [
|
"model_list_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"css/model_list_view.css",
|
"js/model_list_view.js",
|
||||||
"js/model_list_view.js"
|
"model_list_view.7a2ce4182c97623ab7e8.hot-update.js"
|
||||||
],
|
],
|
||||||
"edit_internal_recipe": [
|
"edit_internal_recipe": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"css/edit_internal_recipe.css",
|
|
||||||
"js/edit_internal_recipe.js"
|
"js/edit_internal_recipe.js"
|
||||||
],
|
],
|
||||||
"cookbook_view": [
|
"cookbook_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"css/cookbook_view.css",
|
|
||||||
"js/cookbook_view.js"
|
"js/cookbook_view.js"
|
||||||
],
|
],
|
||||||
"meal_plan_view": [
|
"meal_plan_view": [
|
||||||
"css/chunk-vendors.css",
|
|
||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"css/meal_plan_view.css",
|
|
||||||
"js/meal_plan_view.js"
|
"js/meal_plan_view.js"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"publicPath": "http://localhost:8080/"
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user