diff --git a/HISTORY.rst b/HISTORY.rst index eadb8c7e22..c738f495c2 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -33,7 +33,12 @@ Next (2018-XX-XX) - Documents without at least a version are not scanned for duplicates. - Use a SHA256 hex digest of the secret key at the name of the lockfile. This makes the generation of the name repeatable while unique between installations. - Squashed apps migrations. - +- Convert document thumbnails, preview, image preview and staging files to template base widgets. +- Unify all document widgets. +- Display resolution settings are now specified as width and height and not a single resolution value. +- Printed pages are now full width. +- Move the invalid document markup to a separate HTML template. + 2.8 (2018-02-27) ================ - Rename the role groups link label from "Members" to "Groups". diff --git a/mayan/apps/appearance/classes.py b/mayan/apps/appearance/classes.py index 36e0c7ea02..aa7503b22a 100644 --- a/mayan/apps/appearance/classes.py +++ b/mayan/apps/appearance/classes.py @@ -27,4 +27,3 @@ class Icon(object): } ) ) - diff --git a/mayan/apps/appearance/static/appearance/css/base.css b/mayan/apps/appearance/static/appearance/css/base.css index f654e26709..65416dab44 100644 --- a/mayan/apps/appearance/static/appearance/css/base.css +++ b/mayan/apps/appearance/static/appearance/css/base.css @@ -120,6 +120,7 @@ img.lazy-load-carousel { .instance-image-widget { text-align: center; + height: 100%; } hr { @@ -700,3 +701,9 @@ a i { border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid #be2626; } + + +.staging-file-thumbnail-container { + width: 150px; + margin: auto; +} diff --git a/mayan/apps/common/utils.py b/mayan/apps/common/utils.py index 752df8a12e..ae924e9051 100644 --- a/mayan/apps/common/utils.py +++ b/mayan/apps/common/utils.py @@ -98,13 +98,6 @@ def get_descriptor(file_input, read=True): return file_input -def index_or_default(instance, index, default): - try: - return instance[index] - except IndexError: - return default - - def TemporaryFile(*args, **kwargs): kwargs.update({'dir': setting_temporary_directory.value}) return tempfile.TemporaryFile(*args, **kwargs) diff --git a/mayan/apps/converter/literals.py b/mayan/apps/converter/literals.py index e98261b80c..3687bf000d 100644 --- a/mayan/apps/converter/literals.py +++ b/mayan/apps/converter/literals.py @@ -10,5 +10,3 @@ DEFAULT_PDFTOPPM_DPI = 300 DEFAULT_PDFTOPPM_FORMAT = 'jpeg' # Possible values jpeg, png, tiff DEFAULT_PDFTOPPM_PATH = '/usr/bin/pdftoppm' DEFAULT_PDFINFO_PATH = '/usr/bin/pdfinfo' - -DIMENSION_SEPARATOR = 'x' diff --git a/mayan/apps/documents/api_views.py b/mayan/apps/documents/api_views.py index 1839ac95b5..e7d755dde8 100644 --- a/mayan/apps/documents/api_views.py +++ b/mayan/apps/documents/api_views.py @@ -337,8 +337,12 @@ class APIDocumentPageImageView(generics.RetrieveAPIView): GET: omit_serializer: true parameters: - - name: size - description: 'x' seprated width and height of the desired image representation. + - name: width + description: Width of the desired image representation. + paramType: query + type: number + - name: height + description: Height of the desired image representation. paramType: query type: number - name: zoom @@ -377,7 +381,8 @@ class APIDocumentPageImageView(generics.RetrieveAPIView): return None def retrieve(self, request, *args, **kwargs): - size = request.GET.get('size') + width = request.GET.get('width') + height = request.GET.get('height') zoom = request.GET.get('zoom') if zoom: @@ -390,8 +395,8 @@ class APIDocumentPageImageView(generics.RetrieveAPIView): task = task_generate_document_page_image.apply_async( kwargs=dict( - document_page_id=self.get_object().pk, size=size, zoom=zoom, - rotation=rotation + document_page_id=self.get_object().pk, width=width, + height=height, zoom=zoom, rotation=rotation ) ) diff --git a/mayan/apps/documents/apps.py b/mayan/apps/documents/apps.py index c1cee010d9..4f68dd4217 100644 --- a/mayan/apps/documents/apps.py +++ b/mayan/apps/documents/apps.py @@ -101,8 +101,7 @@ from .statistics import ( total_document_page_per_month, total_document_version_per_month ) from .widgets import ( - DocumentThumbnailWidget, DocumentPageThumbnailWidget, - DocumentVersionThumbnailWidget, widget_document_page_number, + DocumentPageThumbnailWidget, widget_document_page_number, widget_document_version_page_number ) @@ -207,13 +206,11 @@ class DocumentsApp(MayanAppConfig): # Document and document page thumbnail widget document_page_thumbnail_widget = DocumentPageThumbnailWidget() - document_thumbnail_widget = DocumentThumbnailWidget() - document_version_thumbnail_widget = DocumentVersionThumbnailWidget() # Document SourceColumn( source=Document, label=_('Thumbnail'), - func=lambda context: document_thumbnail_widget.render( + func=lambda context: document_page_thumbnail_widget.render( instance=context['object'] ) ) @@ -263,7 +260,7 @@ class DocumentsApp(MayanAppConfig): # DeletedDocument SourceColumn( source=DeletedDocument, label=_('Thumbnail'), - func=lambda context: document_thumbnail_widget.render( + func=lambda context: document_page_thumbnail_widget.render( instance=context['object'] ) ) @@ -279,7 +276,7 @@ class DocumentsApp(MayanAppConfig): # DocumentVersion SourceColumn( source=DocumentVersion, label=_('Thumbnail'), - func=lambda context: document_version_thumbnail_widget.render( + func=lambda context: document_page_thumbnail_widget.render( instance=context['object'] ) ) @@ -309,7 +306,7 @@ class DocumentsApp(MayanAppConfig): # DuplicatedDocument SourceColumn( source=DuplicatedDocument, label=_('Thumbnail'), - func=lambda context: document_thumbnail_widget.render( + func=lambda context: document_page_thumbnail_widget.render( instance=context['object'].document ) ) diff --git a/mayan/apps/documents/fields.py b/mayan/apps/documents/fields.py new file mode 100644 index 0000000000..ed18c4bafc --- /dev/null +++ b/mayan/apps/documents/fields.py @@ -0,0 +1,17 @@ +from __future__ import absolute_import, unicode_literals + +from django import forms + +from .widgets import DocumentPagesCarouselWidget, DocumentPageImageWidget + + +class DocumentField(forms.fields.Field): + widget = DocumentPagesCarouselWidget + + +class DocumentPageField(forms.fields.Field): + widget = DocumentPageImageWidget + + +class DocumentVersionField(forms.fields.Field): + widget = DocumentPagesCarouselWidget diff --git a/mayan/apps/documents/forms.py b/mayan/apps/documents/forms.py index c8c5531853..9d71b8d881 100644 --- a/mayan/apps/documents/forms.py +++ b/mayan/apps/documents/forms.py @@ -9,35 +9,34 @@ from django.utils.translation import ugettext_lazy as _ from acls.models import AccessControlList from common.forms import DetailForm +from .fields import ( + DocumentField, DocumentPageField, DocumentVersionField +) from .models import ( - Document, DocumentType, DocumentPage, DocumentTypeFilename + Document, DocumentType, DocumentTypeFilename ) from .literals import DEFAULT_ZIP_FILENAME, PAGE_RANGE_ALL, PAGE_RANGE_CHOICES from .permissions import permission_document_create from .settings import setting_language_choices -from .widgets import DocumentPagesCarouselWidget, DocumentPageImageWidget + logger = logging.getLogger(__name__) - # Document page forms -class DocumentPageForm(DetailForm): - class Meta: - fields = () - model = DocumentPage + +class DocumentPageForm(forms.Form): def __init__(self, *args, **kwargs): - zoom = kwargs.pop('zoom', None) + instance = kwargs.pop('instance', None) rotation = kwargs.pop('rotation', None) + zoom = kwargs.pop('zoom', None) super(DocumentPageForm, self).__init__(*args, **kwargs) - self.fields['page_image'].initial = self.instance - self.fields['page_image'].widget.attrs.update({ + self.fields['document_page'].initial = instance + self.fields['document_page'].widget.attrs.update({ 'zoom': zoom, - 'rotation': rotation + 'rotation': rotation, }) - page_image = forms.CharField( - label=_('Page image'), widget=DocumentPageImageWidget() - ) + document_page = DocumentPageField() # Document forms @@ -45,31 +44,18 @@ class DocumentPreviewForm(forms.Form): def __init__(self, *args, **kwargs): document = kwargs.pop('instance', None) super(DocumentPreviewForm, self).__init__(*args, **kwargs) - self.fields['preview'].initial = document - try: - self.fields['preview'].label = _( - 'Document pages (%d)' - ) % document.page_count - except AttributeError: - self.fields['preview'].label = _('Document pages (%d)') % 0 + self.fields['document'].initial = document - preview = forms.CharField(widget=DocumentPagesCarouselWidget()) + document = DocumentField() class DocumentVersionPreviewForm(forms.Form): def __init__(self, *args, **kwargs): document_version = kwargs.pop('instance', None) super(DocumentVersionPreviewForm, self).__init__(*args, **kwargs) + self.fields['document_version'].initial = document_version - self.fields['preview'].initial = document_version - try: - self.fields['preview'].label = _( - 'Document pages (%d)' - ) % document_version.pages.count() - except AttributeError: - self.fields['preview'].label = _('Document version pages (%d)') % 0 - - preview = forms.CharField(widget=DocumentPagesCarouselWidget()) + document_version = DocumentVersionField() class DocumentForm(forms.ModelForm): diff --git a/mayan/apps/documents/models.py b/mayan/apps/documents/models.py index 7146cb56a0..f9a0ce987a 100644 --- a/mayan/apps/documents/models.py +++ b/mayan/apps/documents/models.py @@ -39,8 +39,8 @@ from .permissions import permission_document_view from .runtime import cache_storage_backend, storage_backend from .settings import ( setting_disable_base_image_cache, setting_disable_transformed_image_cache, - setting_display_size, setting_language, setting_zoom_max_level, - setting_zoom_min_level + setting_display_width, setting_display_height, setting_language, + setting_zoom_max_level, setting_zoom_min_level ) from .signals import ( post_document_created, post_document_type_change, post_version_upload @@ -195,6 +195,11 @@ class Document(models.Model): passthrough = PassthroughManager() trash = TrashCanManager() + class Meta: + verbose_name = _('Document') + verbose_name_plural = _('Documents') + ordering = ('-date_added',) + def __str__(self): return self.label or ugettext('Document stub, id: %d') % self.pk @@ -238,11 +243,6 @@ class Document(models.Model): if _commit_events: event_document_properties_edit.commit(actor=user, target=self) - class Meta: - verbose_name = _('Document') - verbose_name_plural = _('Documents') - ordering = ('-date_added',) - def add_as_recent_document_for_user(self, user): return RecentDocument.objects.add_document_for_user(user, self) @@ -257,6 +257,11 @@ class Document(models.Model): else: return False + def get_api_image_url(self): + latest_version = self.latest_version + if latest_version: + return latest_version.get_api_image_url() + def invalidate_cache(self): for document_version in self.versions.all(): document_version.invalidate_cache() @@ -421,6 +426,11 @@ class DocumentVersion(models.Model): def get_absolute_url(self): return reverse('documents:document_version_view', args=(self.pk,)) + def get_api_image_url(self): + first_page = self.pages.first() + if first_page: + return first_page.get_api_image_url() + def get_rendered_string(self, preserve_extension=False): if preserve_extension: filename, extension = os.path.splitext(self.document.label) @@ -758,7 +768,8 @@ class DocumentPage(models.Model): # Set sensible defaults if the argument is not specified or if the # argument is None - size = kwargs.get('size', setting_display_size.value) or setting_display_size.value + width = kwargs.get('width', setting_display_width.value) or setting_display_width.value + height = kwargs.get('height', setting_display_height.value) or setting_display_height.value rotation = kwargs.get('rotation', DEFAULT_ROTATION) or DEFAULT_ROTATION zoom_level = kwargs.get('zoom', DEFAULT_ZOOM_LEVEL) or DEFAULT_ZOOM_LEVEL @@ -785,11 +796,9 @@ class DocumentPage(models.Model): TransformationRotate(degrees=rotation) ) - if size: + if width: transformation_list.append( - TransformationResize( - **dict(zip(('width', 'height'), (size.split('x')))) - ) + TransformationResize(width=width, height=height) ) if zoom_level: @@ -875,6 +884,13 @@ class DocumentPage(models.Model): """ return '{}-{}'.format(self.document_version.uuid, self.pk) + def get_api_image_url(self): + return reverse( + 'rest_api:documentpage-image', args=( + self.document.pk, self.document_version.pk, self.pk + ) + ) + class DocumentPageCachedImage(models.Model): document_page = models.ForeignKey( diff --git a/mayan/apps/documents/settings.py b/mayan/apps/documents/settings.py index 273bc52253..1dd5f01ace 100644 --- a/mayan/apps/documents/settings.py +++ b/mayan/apps/documents/settings.py @@ -10,18 +10,31 @@ LANGUAGE_CHOICES = [ (i.iso639_3_code, i.name) for i in list(pycountry.languages) ] + namespace = Namespace(name='documents', label=_('Documents')) -setting_display_size = namespace.add_setting( - global_name='DOCUMENTS_DISPLAY_SIZE', default='3600' +setting_display_width = namespace.add_setting( + global_name='DOCUMENTS_DISPLAY_WIDTH', default='3600' ) -setting_preview_size = namespace.add_setting( - global_name='DOCUMENTS_PREVIEW_SIZE', default='800' +setting_display_height = namespace.add_setting( + global_name='DOCUMENTS_DISPLAY_HEIGHT', default='' ) -setting_print_size = namespace.add_setting( - global_name='DOCUMENTS_PRINT_SIZE', default='3600' +setting_preview_width = namespace.add_setting( + global_name='DOCUMENTS_PREVIEW_WIDTH', default='800' ) -setting_thumbnail_size = namespace.add_setting( - global_name='DOCUMENTS_THUMBNAIL_SIZE', default='800' +setting_preview_height = namespace.add_setting( + global_name='DOCUMENTS_PREVIEW_HEIGHT', default='' +) +setting_print_width = namespace.add_setting( + global_name='DOCUMENTS_PRINT_WIDTH', default='3600' +) +setting_print_height = namespace.add_setting( + global_name='DOCUMENTS_PRINT_HEIGHT', default='' +) +setting_thumbnail_width = namespace.add_setting( + global_name='DOCUMENTS_THUMBNAIL_WIDTH', default='800' +) +setting_thumbnail_height = namespace.add_setting( + global_name='DOCUMENTS_THUMBNAIL_HEIGHT', default='' ) setting_recent_count = namespace.add_setting( global_name='DOCUMENTS_RECENT_COUNT', default=40, diff --git a/mayan/apps/documents/templates/documents/forms/widgets/document_page_carousel.html b/mayan/apps/documents/templates/documents/forms/widgets/document_page_carousel.html new file mode 100644 index 0000000000..b3def300d8 --- /dev/null +++ b/mayan/apps/documents/templates/documents/forms/widgets/document_page_carousel.html @@ -0,0 +1,26 @@ +{% load i18n %} + +
{% trans 'No pages to display' %}
+ {% endfor %} +No pages to display
') - - output.append('