responsiveness. Render a document page place holder while the real document page loads. This change avoids "jumping" effect when loading many thumbnails. Increase lazy load thresholds. More thumbnails and document pages will be loaded and visible by default when a view loads. Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
352 lines
11 KiB
Python
352 lines
11 KiB
Python
from __future__ import unicode_literals
|
|
|
|
from django import forms
|
|
from django.core.urlresolvers import reverse
|
|
from django.utils.encoding import force_text
|
|
from django.utils.html import strip_tags
|
|
from django.utils.http import urlencode
|
|
from django.utils.safestring import mark_safe
|
|
from django.utils.translation import ugettext, ugettext_lazy as _
|
|
|
|
from common.utils import index_or_default
|
|
|
|
from .settings import (
|
|
setting_display_size, setting_preview_size, setting_thumbnail_size
|
|
)
|
|
|
|
|
|
class DocumentPageImageWidget(forms.widgets.Widget):
|
|
def render(self, name, value, attrs=None):
|
|
final_attrs = self.build_attrs(attrs)
|
|
zoom = final_attrs.get('zoom')
|
|
rotation = final_attrs.get('rotation')
|
|
|
|
html_widget = InteractiveDocumentPageWidget()
|
|
|
|
if value:
|
|
output = []
|
|
output.append(
|
|
'<div class="full-height scrollable '
|
|
'mayan-page-wrapper-interactive" data-height-difference=230>'
|
|
)
|
|
output.append(
|
|
html_widget.render(
|
|
instance=value, zoom=zoom, rotation=rotation,
|
|
)
|
|
)
|
|
output.append('</div>')
|
|
return mark_safe(''.join(output))
|
|
else:
|
|
return ''
|
|
|
|
|
|
class DocumentPagesCarouselWidget(forms.widgets.Widget):
|
|
"""
|
|
Display many small representations of a document pages
|
|
"""
|
|
def render(self, name, value, attrs=None):
|
|
html_widget = CarouselDocumentPageThumbnailWidget()
|
|
|
|
output = []
|
|
output.append(
|
|
'<div id="carousel-container" class="full-height scrollable" '
|
|
'data-height-difference=200>'
|
|
)
|
|
|
|
document_pages = value.pages.all()
|
|
total_pages = value.pages.count()
|
|
|
|
for document_page in document_pages:
|
|
output.append('<div class="carousel-item">')
|
|
output.append(
|
|
html_widget.render(instance=document_page)
|
|
)
|
|
|
|
output.append(
|
|
'<div class="carousel-item-page-number">%s</div>' % ugettext(
|
|
'Page %(page_number)d of %(total_pages)d'
|
|
) % {
|
|
'page_number': document_page.page_number,
|
|
'total_pages': total_pages
|
|
}
|
|
)
|
|
output.append('</div>')
|
|
|
|
if not total_pages:
|
|
output.append('<p>No pages to display</p>')
|
|
|
|
output.append('</div>')
|
|
|
|
return mark_safe(''.join(output))
|
|
|
|
|
|
def document_link(document):
|
|
return mark_safe('<a href="%s">%s</a>' % (
|
|
document.get_absolute_url(), document)
|
|
)
|
|
|
|
|
|
class InstanceImageWidget(object):
|
|
alt_text = _('Clickable image')
|
|
click_view_name = None
|
|
click_view_query_dict = {}
|
|
destination_view_name = None
|
|
destination_view_query_dict = {}
|
|
disable_title_link = False
|
|
fancybox_class = 'fancybox'
|
|
gallery_name = None
|
|
# TODO: update this to load a disk template
|
|
invalid_image_template = '<p>Invalid image</p>'
|
|
preview_view_name = None
|
|
preview_query_dict = {}
|
|
image_class = 'lazy-load'
|
|
title = None
|
|
width = None
|
|
height = None
|
|
|
|
# Click view
|
|
def get_click_view_kwargs(self, instance):
|
|
"""
|
|
Determine if the view is a template or API view and vary the view
|
|
keyword arguments
|
|
"""
|
|
|
|
if self.click_view_name.startswith('rest_api'):
|
|
return {
|
|
'pk': instance.document.pk,
|
|
'version_pk': instance.document_version.pk,
|
|
'page_pk': instance.pk
|
|
}
|
|
else:
|
|
return {
|
|
'pk': instance.pk,
|
|
}
|
|
|
|
def get_click_view_query_dict(self, instance):
|
|
return self.click_view_query_dict
|
|
|
|
def get_click_view_querystring(self, instance):
|
|
return urlencode(self.get_click_view_query_dict(instance=instance))
|
|
|
|
def get_click_view_url(self, instance):
|
|
return '{}?{}'.format(
|
|
reverse(
|
|
viewname=self.click_view_name,
|
|
kwargs=self.get_click_view_kwargs(instance=instance)
|
|
),
|
|
self.get_click_view_querystring(instance=instance)
|
|
)
|
|
|
|
# Destination view
|
|
def get_destination_view_querystring(self, instance):
|
|
return urlencode(self.get_destination_view_query_dict(instance=instance))
|
|
|
|
def get_destination_url(self, instance):
|
|
return '{}?{}'.format(
|
|
reverse(
|
|
viewname=self.destination_view_name,
|
|
kwargs=self.get_destination_view_kwargs(instance=instance)
|
|
),
|
|
self.get_destination_view_querystring(instance=instance)
|
|
)
|
|
|
|
def get_destination_view_kwargs(self, instance):
|
|
return {
|
|
'pk': instance.pk
|
|
}
|
|
|
|
# Preview view
|
|
def get_preview_view_kwargs(self, instance):
|
|
return {
|
|
'pk': instance.document.pk,
|
|
'version_pk': instance.document_version.pk,
|
|
'page_pk': instance.pk
|
|
}
|
|
|
|
def get_preview_view_query_dict(self, instance):
|
|
return self.preview_view_query_dict
|
|
|
|
def get_preview_view_querystring(self, instance):
|
|
return urlencode(self.get_preview_view_query_dict(instance=instance))
|
|
|
|
def get_preview_view_url(self, instance):
|
|
return '{}?{}'.format(
|
|
reverse(
|
|
viewname=self.preview_view_name,
|
|
kwargs=self.get_preview_view_kwargs(instance=instance)
|
|
),
|
|
self.get_preview_view_querystring(instance=instance)
|
|
)
|
|
|
|
def get_title(self, instance):
|
|
return self.title
|
|
|
|
def is_valid(self, instance):
|
|
return instance
|
|
|
|
def render(self, instance):
|
|
result = []
|
|
|
|
result.append('<div class="instance-image-widget">')
|
|
|
|
if not self.is_valid(instance=instance):
|
|
result.append(self.invalid_image_template)
|
|
else:
|
|
if self.gallery_name:
|
|
gallery_markup = 'rel="%s"' % self.gallery_name
|
|
else:
|
|
gallery_markup = ''
|
|
|
|
if self.click_view_name:
|
|
click_full_url = self.get_click_view_url(instance=instance)
|
|
|
|
title = self.get_title(instance=instance)
|
|
|
|
if title:
|
|
if not self.disable_title_link:
|
|
title_markup = 'data-caption="<a class=\'a-caption\' href=\'{url}\'>{title} <i class=\'fa fa-external-link\'></i></a>"'.format(
|
|
title=strip_tags(title), url=self.get_destination_url(instance=instance) or '#'
|
|
)
|
|
else:
|
|
title_markup = 'data-caption="{title}"'.format(
|
|
title=strip_tags(title),
|
|
)
|
|
else:
|
|
title_markup = ''
|
|
|
|
result.append(
|
|
'<a {gallery_markup} class="{fancybox_class}" '
|
|
'href="{click_full_url}" {title_markup}>'.format(
|
|
gallery_markup=gallery_markup,
|
|
fancybox_class=self.fancybox_class,
|
|
click_full_url=click_full_url,
|
|
title_markup=title_markup
|
|
)
|
|
)
|
|
|
|
result.append(
|
|
'<div class="spinner-container text-primary" style="margin: auto; width: {width}px; height: {height}px; border:1px solid lightgray;">'
|
|
'<span class="fa-stack fa-lg" style="margin-left: 4px; margin-top: 3px;">'
|
|
'<i class="fa fa-file-o fa-stack-2x"></i>'
|
|
'<i class="fa fa-clock-o fa-stack-1x"></i>'
|
|
'</span>'
|
|
'</div>'
|
|
'<img class="thin_border {image_class} pull-left"'
|
|
'data-url="{preview_full_url}" src="#" '
|
|
'/> '.format(
|
|
width=self.width or '32', height=self.height or '32',
|
|
image_class=self.image_class,
|
|
preview_full_url=self.get_preview_view_url(instance=instance),
|
|
alt_text=self.alt_text
|
|
)
|
|
)
|
|
|
|
if self.click_view_name:
|
|
result.append('</a>')
|
|
|
|
result.append('</div>')
|
|
|
|
return mark_safe(''.join(result))
|
|
|
|
|
|
class BaseDocumentThumbnailWidget(InstanceImageWidget):
|
|
alt_text = _('Document page image')
|
|
click_view_name = 'rest_api:documentpage-image'
|
|
click_view_query_dict = {
|
|
'size': setting_preview_size.value
|
|
}
|
|
gallery_name = 'document_list'
|
|
invalid_image_template = """
|
|
<span class="fa-stack fa-lg"><i class="fa fa-file-o fa-stack-2x"></i><i class="fa fa-question fa-stack-1x text-danger"></i></span>
|
|
"""
|
|
preview_view_name = 'rest_api:documentpage-image'
|
|
preview_view_query_dict = {
|
|
'size': setting_thumbnail_size.value
|
|
}
|
|
width = setting_thumbnail_size.value.split('x')[0]
|
|
height = index_or_default(
|
|
instance=setting_thumbnail_size.value.split('x'),
|
|
index=1, default=setting_thumbnail_size.value.split('x')[0]
|
|
)
|
|
|
|
def get_destination_url(self, instance):
|
|
return instance.get_absolute_url()
|
|
|
|
|
|
class CarouselDocumentPageThumbnailWidget(BaseDocumentThumbnailWidget):
|
|
click_view_name = 'documents:document_page_view'
|
|
fancybox_class = ''
|
|
image_class = 'lazy-load-carousel'
|
|
preview_view_query_dict = {
|
|
'size': setting_display_size.value
|
|
}
|
|
width = setting_preview_size.value.split('x')[0]
|
|
height = index_or_default(
|
|
instance=setting_preview_size.value.split('x'),
|
|
index=1, default=setting_preview_size.value.split('x')[0]
|
|
)
|
|
|
|
|
|
class DocumentThumbnailWidget(BaseDocumentThumbnailWidget):
|
|
def get_click_view_kwargs(self, instance):
|
|
return {
|
|
'pk': instance.pk,
|
|
'version_pk': instance.latest_version.pk,
|
|
'page_pk': instance.pages.first().pk
|
|
}
|
|
|
|
def get_click_view_url(self, instance):
|
|
first_page = instance.pages.first()
|
|
if first_page:
|
|
return super(DocumentThumbnailWidget, self).get_click_view_url(
|
|
instance=instance
|
|
)
|
|
else:
|
|
return '#'
|
|
|
|
def get_preview_view_kwargs(self, instance):
|
|
return {
|
|
'pk': instance.pk,
|
|
'version_pk': instance.latest_version.pk,
|
|
'page_pk': instance.pages.first().pk
|
|
}
|
|
|
|
def get_preview_view_url(self, instance):
|
|
first_page = instance.pages.first()
|
|
if first_page:
|
|
return super(DocumentThumbnailWidget, self).get_preview_view_url(
|
|
instance=instance
|
|
)
|
|
else:
|
|
return ''
|
|
|
|
def get_title(self, instance):
|
|
return getattr(instance, 'label', None)
|
|
|
|
def is_valid(self, instance):
|
|
return instance.pages
|
|
|
|
|
|
class DocumentPageThumbnailWidget(BaseDocumentThumbnailWidget):
|
|
def get_title(self, instance):
|
|
return force_text(instance)
|
|
|
|
|
|
class InteractiveDocumentPageWidget(BaseDocumentThumbnailWidget):
|
|
click_view_name = None
|
|
|
|
def get_preview_view_query_dict(self, instance):
|
|
return {
|
|
'zoom': self.zoom,
|
|
'rotation': self.rotation,
|
|
'size': setting_display_size.value,
|
|
}
|
|
|
|
def render(self, instance, *args, **kwargs):
|
|
self.zoom = kwargs.pop('zoom')
|
|
self.rotation = kwargs.pop('rotation')
|
|
|
|
return super(
|
|
InteractiveDocumentPageWidget, self
|
|
).render(instance=instance, *args, **kwargs)
|