Skip to content

Commit

Permalink
[Fixes #3621] Improve Documents Thumbnail generation...
Browse files Browse the repository at this point in the history
  • Loading branch information
Alessio Fabiani committed Feb 14, 2018
1 parent 459c0ce commit c5d7ea5
Show file tree
Hide file tree
Showing 16 changed files with 326 additions and 32 deletions.
14 changes: 7 additions & 7 deletions docs/tutorials/devel/devel_debug/geoexplorer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Debugging GeoExplorer
=====================

In case you want to debug the GeoExplorer behaviour in your browser with
In case you want to debug the GeoExplorer behaviour in your browser with
Firebug of Chromium Developer toolbar, you may do the following:

Install Boundless Suite::
Expand All @@ -13,17 +13,17 @@ Install Boundless Suite::
$ git submodule update --init --recursive

Run GeoExplorer in debug mode::

$ cd geoexplorer
$ ant debug

Check if GeoExplorer is running at this URL: http://localhost:9080

Edit the ``layers/templates/layers/layer_geoext_map.html`` file and replace this
Edit the ``layers/templates/layers/layer_geoext_map.html`` file and replace this
line::

{% include "geonode/geo_header.html" %}
{% include "geoext/geo_header.html" %}

with this one::

{% include "geonode/geo_header_debug.html" %}
{% include "geoext/geo_header_debug.html" %}
33 changes: 25 additions & 8 deletions geonode/documents/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
#########################################################################

import subprocess
import traceback

from django.conf import settings
from threading import Timer
from mimetypes import guess_type
from urllib import pathname2url
from tempfile import NamedTemporaryFile
Expand Down Expand Up @@ -62,14 +65,28 @@ def render_document(document_path, extension="png"):
temp_path = temp.name

# spawn subprocess and render the document
output = NamedTemporaryFile(suffix='.{}'.format(extension))
try:
subprocess.check_call(
["unoconv", "-f", extension, "-o", output.name, temp_path])
except subprocess.CalledProcessError as e:
raise ConversionError(str(e))
except OSError as e:
raise ConversionError(str(e))
output = None
if settings.UNOCONV_ENABLE:
output = NamedTemporaryFile(suffix='.{}'.format(extension))
timeout = None
try:
def kill(process):
return process.kill()

unoconv = subprocess.Popen(
[settings.UNOCONV_EXECUTABLE, "-v", "-e", "PageRange=1-2",
"-f", extension, "-o", output.name, temp_path],
stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
timeout = Timer(settings.UNOCONV_TIMEOUT, kill, [unoconv])
timeout.start()
stdout, stderr = unoconv.communicate()
except Exception as e:
traceback.print_exc()
raise ConversionError(str(e))
finally:
if timeout:
timeout.cancel()

return output

Expand Down
7 changes: 7 additions & 0 deletions geonode/documents/templates/documents/document_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ <h4>{% trans "Metadata" %}</h4>
<a class="btn btn-default btn-block btn-xs" href="{% url "document_metadata_advanced" resource.id %}">{% trans "Advanced Edit" %}</a>
</div>
{% endif %}
{% if "change_resourcebase" in perms_list %}
<div class="col-sm-3">
<i class="fa fa-photo fa-3x"></i>
<h4>{% trans "Thumbnail" %}</h4>
<a class="btn btn-default btn-block btn-xs" href="{% url "document_thumb_upload" resource.id %}" id="set_thumbnail">{% trans "Set" %}</a>
</div>
{% endif %}
{% if "change_resourcebase" in perms_list or "delete_resourcebase" in perms_list %}
<div class="col-sm-3">
<i class="fa fa-file-text-o fa-3x"></i>
Expand Down
5 changes: 0 additions & 5 deletions geonode/documents/templates/documents/document_metadata.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@

{% block title %}{{ document.title }} — {{ block.super }}{% endblock %}

{% block head %}
{% include "geonode/ext_header.html" %}
{{ block.super }}
{% endblock head %}

{% block body_class %}data{% endblock body_class %}

{% block body_outer %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@
{% load base_tags %}
{% load guardian_tags %}

{% block head %}
{% include "geonode/ext_header.html" %}
{{ block.super }}
{% endblock %}

{% block title %}{{ document.alternate }} — {{ block.super }}{% endblock %}

{% block body_class %}data{% endblock %}
Expand Down
112 changes: 112 additions & 0 deletions geonode/documents/templates/documents/document_thumb_upload.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{% extends "documents/document_upload_base.html" %}
{% load staticfiles %}
{% load bootstrap_tags %}
{% load i18n %}

{% block title %} {% trans "Upload Document's Thumbnail" %} - {{ block.super }} {% endblock %}

{% block body_class %}data documents upload{% endblock body_class %}

{% block head %}
{% include "geoext/ext_header.html" %}
{% include "geoext/app_header.html" %}
{{ block.super }}
{% endblock %}

{% block body_outer %}
<div class="page-header">
<a href="{% url "document_browse" %}?limit={{ CLIENT_RESULTS_LIMIT }}" class="btn btn-primary pull-right">{% trans "Explore Documents" %}</a>
<h2 class="page-title">{% trans "Upload Document's Thumbnail" %}</h2>
</div>

<div class="row">
{% block body %}
<div class="col-md-8">
{% block additional_info %}{% endblock %}

{% if errors %}
<div id="errors" class="alert alert-danger">
{% for error in errors %}
<p>{{ error }}</p>
{% endfor %}
</div>
{% endif %}

<div id="upload-status"></div>

<section id="drop-zone">
<h3><i class="fa fa-cloud-upload"></i><br />{% trans "Drop files here" %}</h3>
</section>

<p>{% trans " or select them one by one:" %}</p>

<form id="file-uploader" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
<!-- UI change to hide the list of previously uploaded files from the user -->
<input type="file" id="file-input" style="display: none;" multiple>
<input class="btn btn-default" type="button" value="Choose Files" onclick="document.getElementById('file-input').click();">
</form>

<section class="widget">
<ul id="global-errors"></ul>
<h4>{% trans "Files to be uploaded" %}</h4>
<div id="file-queue"></div>
<div class="checkbox" style="display:none;" id="style_upload_form_check">
Is Upload Metadata XML Form <input type="checkbox" name="style_upload_form" id="id_style_upload_form" checked="true"/>
<input type="text" name="layer_title" id="id_layer_title" value="{{ resource.alternate }}"/>
</div>
</section>

<section>
<a href="{% url "document_thumb_upload" resource.id %}" id="clear-button" class="btn btn-default">{% trans "Clear" %}</a>
<a href="#" id="upload-button" class="btn btn-danger">{% trans "Upload files" %}</a>
</section>
</div>

{% endblock %}

{% block sidebar %}
<div class="col-md-4">
<h3>{% trans "Permissions" %}</h3>
<form id="permission_form">
{% include "_permissions.html" %}
</form>
</div>
{% endblock %}
</div>
</div>
{% endblock body_outer %}

{% block extra_script %}
{{ block.super }}
<script data-main="{% static 'geonode/js/upload/main' %}"
src="{% static 'lib/js/require.js' %}">
</script>
<script type="text/javascript">
{% autoescape off %}
csrf_token = "{{ csrf_token }}",
form_target = "{% url "document_thumb_upload" docid=resource.id %}",
geogig_enabled = {{ GEOGIG_ENABLED|lower }},
time_enabled = false,
mosaic_enabled = false,
userLookup = "{% url "geonode.views.ajax_lookup" %}"
{% endautoescape %}
</script>
{% if GEONODE_SECURITY_ENABLED %}
{% include "_permissions_form_js.html" %}
{% endif %}

<script type="text/javascript">
$('#id_doc_file').on('change', function(){
if($('#id_title').val() == ''){
$('#id_title').val($('#id_doc_file').val().replace("C:\\fakepath\\", ""));
}
});
$("#id_links").select2({
width: '100%'
});
$('#upload_form').submit(function(){
$('#permissions').val(JSON.stringify(permissionsString($('#permission_form'),'base')));
});
</script>
{% endblock extra_script %}
4 changes: 4 additions & 0 deletions geonode/documents/templates/documents/document_upload.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,9 @@ <h3>{% trans "Permissions" %}</h3>
$('#upload_form').submit(function(){
$('#permissions').val(JSON.stringify(permissionsString($('#permission_form'),'base')));
});

$('#upload-button').click(function(){
$('#_resource_uploading').modal('toggle');
});
</script>
{% endblock extra_script %}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{% extends "geonode_base.html" %}
{% load i18n %}
{% load pagination_tags %}
{% load url from future %}
{% load base_tags %}
{% load guardian_tags %}

{% block title %} {{ block.super }} {% endblock %}

Expand Down
1 change: 1 addition & 0 deletions geonode/documents/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@
name='document_batch_metadata'),
url(r'^(?P<docid>\d+)/metadata_advanced$', 'document_metadata_advanced',
name='document_metadata_advanced'),
url(r'^(?P<docid>[^/]*)/thumb_upload$', 'document_thumb_upload', name='document_thumb_upload'),
)
81 changes: 81 additions & 0 deletions geonode/documents/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#
#########################################################################

import os
import json
import logging
from itertools import chain
Expand All @@ -32,6 +33,8 @@
from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.exceptions import PermissionDenied
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django_downloadview.response import DownloadResponse
from django.views.generic.edit import UpdateView, CreateView
from django.db.models import F
Expand All @@ -45,6 +48,7 @@
from geonode.documents.models import Document, get_related_resources
from geonode.documents.forms import DocumentForm, DocumentCreateForm, DocumentReplaceForm
from geonode.documents.models import IMGTYPES
from geonode.documents.renderers import generate_thumbnail_content, MissingPILError
from geonode.utils import build_social_links
from geonode.groups.models import GroupProfile
from geonode.base.views import batch_modify
Expand Down Expand Up @@ -517,6 +521,83 @@ def document_metadata_advanced(request, docid):
template='documents/document_metadata_advanced.html')


@login_required
def document_thumb_upload(
request,
docid,
template='documents/document_thumb_upload.html'):
document = None
try:
document = _resolve_document(
request,
docid,
'base.change_resourcebase',
_PERMISSION_MSG_MODIFY)

except Http404:
return HttpResponse(
loader.render_to_string(
'404.html', RequestContext(
request, {
})), status=404)

except PermissionDenied:
return HttpResponse(
loader.render_to_string(
'401.html', RequestContext(
request, {
'error_message': _("You are not allowed to edit this document.")})), status=403)

if document is None:
return HttpResponse(
'An unknown error has occured.',
content_type="text/plain",
status=401
)

if request.method == 'GET':
return render_to_response(template, RequestContext(request, {
"resource": document,
"docid": docid,
'SITEURL': settings.SITEURL[:-1]
}))
elif request.method == 'POST':
status_code = 401
out = {'success': False}
if docid and request.FILES:
data = request.FILES.get('base_file')
if data:
filename = 'document-{}-thumb.png'.format(document.uuid)
path = default_storage.save('tmp/' + filename, ContentFile(data.read()))
f = os.path.join(settings.MEDIA_ROOT, path)
try:
image_path = f
except:
image_path = document.find_placeholder()

thumbnail_content = None
try:
thumbnail_content = generate_thumbnail_content(image_path)
except MissingPILError:
logger.error('Pillow not installed, could not generate thumbnail.')

document.save_thumbnail(filename, thumbnail_content)
logger.debug("Thumbnail for document #{} created.".format(docid))
status_code = 200
out['success'] = True
out['resource'] = docid
else:
out['success'] = False
out['errors'] = 'An unknown error has occured.'
out['url'] = reverse(
'document_detail', args=[
docid])
return HttpResponse(
json.dumps(out),
content_type='application/json',
status=status_code)


def document_search_page(request):
# for non-ajax requests, render a generic search page

Expand Down
6 changes: 6 additions & 0 deletions geonode/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,12 @@
# DOCUMENT_TYPE_MAP = {}
# DOCUMENT_MIMETYPE_MAP = {}

UNOCONV_ENABLE = strtobool(os.getenv('UNOCONV_ENABLE', 'False'))

if UNOCONV_ENABLE:
UNOCONV_EXECUTABLE = os.getenv('UNOCONV_EXECUTABLE', '/usr/bin/unoconv')
UNOCONV_TIMEOUT = os.getenv('UNOCONV_TIMEOUT', 30) # seconds

GEONODE_APPS = (
# GeoNode internal apps
'geonode.people',
Expand Down
Loading

0 comments on commit c5d7ea5

Please sign in to comment.