diff --git a/cookbook/helper/recipe_html_import.py b/cookbook/helper/recipe_html_import.py index d3a79d4d..f9882778 100644 --- a/cookbook/helper/recipe_html_import.py +++ b/cookbook/helper/recipe_html_import.py @@ -72,6 +72,7 @@ def get_recipe_from_source(text, url, space): html_data = [] images = [] + text = normalize_string(text) try: parse_list.append(remove_graph(json.loads(text))) except JSONDecodeError: @@ -83,13 +84,12 @@ def get_recipe_from_source(text, url, space): for el in soup.find_all(type='application/json'): parse_list.append(remove_graph(el)) - # if a url was not provided, try to find one in the first document - if not url: - if 'url' in parse_list[0]: - url = parse_list[0]['url'] - # first try finding ld+json as its most common for el in parse_list: + # if a url was not provided, try to find one in the first document + if not url: + if 'url' in el: + url = el['url'] if isinstance(el, Tag): try: diff --git a/cookbook/static/js/bookmarklet.js b/cookbook/static/js/bookmarklet.js index 8558f584..0d2e4f1b 100644 --- a/cookbook/static/js/bookmarklet.js +++ b/cookbook/static/js/bookmarklet.js @@ -18,19 +18,28 @@ } function initBookmarklet() { (window.bookmarkletTandoor = function() { - r = confirm('Click OK to import recipe automatically, click Cancel to import the recipe manually.'); - if (r) { - auto=true - } else { - auto=false - } + var recipe = document.documentElement.innerHTML + var form = document.createElement("form"); + var windowName = "ImportRecipe" + form.setAttribute("method", "post"); + form.setAttribute("action", localStorage.getItem('importURL')); + form.setAttribute("target",'importRecipe'); + var params = { 'recipe' : recipe,'url': window.location}; - var newIframe = document.createElement('iframe'); - newIframe.width = '200';newIframe.height = '200'; - newIframe.src = localStorage.getItem('importURL'); - document.body.appendChild(newIframe); - - + for (var i in params) { + if (params.hasOwnProperty(i)) { + var input = document.createElement('input'); + input.type = 'hidden'; + input.name = i; + input.value = params[i]; + form.appendChild(input); + } + } + document.body.appendChild(form); + window.open('', windowName); + form.target = windowName; + form.submit(); + document.body.removeChild(form); } )(); } diff --git a/cookbook/templates/import_json_working.html b/cookbook/templates/import_json_working.html new file mode 100644 index 00000000..6c2d6fce --- /dev/null +++ b/cookbook/templates/import_json_working.html @@ -0,0 +1,385 @@ + +{% extends "base.html" %} +{% load crispy_forms_filters %} +{% load i18n %} +{% load static %} + +{% block title %}{% trans 'Import Recipe' %}{% endblock %} + +{% block extra_head %} + {% include 'include/vue_base.html' %} + + + + + +{% endblock %} + + +{% block content %} +
+
+

{% trans 'Import From Source' %}

+
+ +
+ Simply paste a web page source or JSON document into this textarea and click import. +
+ +
+ +
+ +
+
+ +
+ + +
+ + + + +
+ +
+ +{% endblock %} + +{% block script %} + + + + +{% endblock %} \ No newline at end of file diff --git a/cookbook/templates/url_import.html b/cookbook/templates/url_import.html index dbc5c25a..63a819bc 100644 --- a/cookbook/templates/url_import.html +++ b/cookbook/templates/url_import.html @@ -23,7 +23,7 @@ {% block content %}
-

{% trans 'Import' %}

+

{% trans 'Import' %}

let csrftoken = Cookies.get('csrftoken'); Vue.http.headers.common['X-CSRFToken'] = csrftoken; - Vue.component('vue-multiselect', window.VueMultiselect.default) let app = new Vue({ @@ -626,13 +625,13 @@ recipe_data: undefined, error: undefined, loading: false, - preview: false, + preview: {{preview}}, preview_type: 'json', all_keywords: false, importing_recipe: false, - recipe_json: undefined, - recipe_tree: undefined, - recipe_html: undefined, + recipe_json: {{recipe_json|safe}}, + recipe_tree: {{recipe_tree|safe}}, + recipe_html: {{recipe_html|safe}}, automatic: true, show_blank: false, blank_field: '', diff --git a/cookbook/templatetags/custom_tags.py b/cookbook/templatetags/custom_tags.py index 5ce3c67f..ab53919b 100644 --- a/cookbook/templatetags/custom_tags.py +++ b/cookbook/templatetags/custom_tags.py @@ -122,7 +122,7 @@ def bookmarklet(host, secure): if(window.bookmarkletTandoor!==undefined){ \ bookmarkletTandoor(); \ } else { \ - localStorage.setItem('importURL', '"+ prefix + host + reverse('api_bookmarklet') +"'); \ + localStorage.setItem('importURL', '" + prefix + host + reverse('api_bookmarklet') + "'); \ document.body.appendChild(document.createElement(\'script\')).src=\'" \ + prefix + host + static('js/bookmarklet.js') + "? \ r=\'+Math.floor(Math.random()*999999999);}})();" diff --git a/cookbook/urls.py b/cookbook/urls.py index 39d7cb6d..8bbf1ef6 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -96,6 +96,7 @@ urlpatterns = [ path('api/recipe-from-source/', api.recipe_from_source, name='api_recipe_from_source'), path('api/backup/', api.get_backup, name='api_backup'), path('api/ingredient-from-string/', api.ingredient_from_string, name='api_ingredient_from_string'), + path('api/bookmarklet/', api.bookmarklet, name='api_bookmarklet'), path('dal/keyword/', dal.KeywordAutocomplete.as_view(), name='dal_keyword'), path('dal/food/', dal.IngredientsAutocomplete.as_view(), name='dal_food'), diff --git a/cookbook/views/api.py b/cookbook/views/api.py index a1d1f390..334e51f6 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -13,9 +13,11 @@ from django.core import management from django.core.exceptions import FieldError, ValidationError from django.core.files import File from django.db.models import Q -from django.http import FileResponse, HttpResponse, JsonResponse -from django.shortcuts import redirect, get_object_or_404 +from django.http import FileResponse, HttpResponse, JsonResponse, HttpResponseRedirect +from django.shortcuts import redirect, render, get_object_or_404 +from django.urls import reverse from django.utils.translation import gettext as _ +from django.views.decorators.csrf import csrf_exempt from icalendar import Calendar, Event from rest_framework import decorators, viewsets, status from rest_framework.exceptions import APIException, PermissionDenied, NotFound, MethodNotAllowed @@ -29,7 +31,7 @@ from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsGuest, CustomIsShared, CustomIsUser, group_required) from cookbook.helper.recipe_html_import import get_recipe_from_source -from cookbook.helper.recipe_url_import import get_from_scraper, find_recipe_json +from cookbook.helper.recipe_url_import import get_from_scraper from cookbook.models import (CookLog, Food, Ingredient, Keyword, MealPlan, MealType, Recipe, RecipeBook, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Step, @@ -655,3 +657,13 @@ def ingredient_from_string(request): }, status=200 ) + + +@group_required('user') +@csrf_exempt +def bookmarklet(request): + if request.method == "POST": + if 'recipe' in request.POST: + recipe_json, recipe_tree, recipe_html, images = get_recipe_from_source(request.POST['recipe'], request.POST['url'], request.space) + return render(request, 'url_import.html', {'recipe_json': recipe_json, 'recipe_tree': recipe_tree, 'recipe_html': recipe_html, 'preview': 'true'}) + return HttpResponseRedirect(reverse('view_search')) diff --git a/cookbook/views/data.py b/cookbook/views/data.py index 1b91bfd9..1820ac7c 100644 --- a/cookbook/views/data.py +++ b/cookbook/views/data.py @@ -186,7 +186,7 @@ def import_url(request): return HttpResponse(reverse('view_recipe', args=[recipe.pk])) - return render(request, 'url_import.html', {}) + return render(request, 'url_import.html', {'recipe_json': 'undefined', 'recipe_tree': 'undefined', 'recipe_html': 'undefined', 'preview': 'false'}) class Object(object):