diff --git a/HISTORY.rst b/HISTORY.rst index 70e2229b78..f28c16d506 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -25,6 +25,8 @@ - Convert document version view to item list view. - Add support for browsing individual document versions. - Add support for dropdown menus to the item list view template. +- Add support for preserving the file extenstion when downloading a document + version. GitLab #415. 2.6.4 (2017-07-26) ================== diff --git a/mayan/apps/documents/forms.py b/mayan/apps/documents/forms.py index 702c65913a..c8c5531853 100644 --- a/mayan/apps/documents/forms.py +++ b/mayan/apps/documents/forms.py @@ -233,6 +233,17 @@ class DocumentDownloadForm(forms.Form): self.fields['compressed'].widget.attrs.update({'disabled': True}) +class DocumentVersionDownloadForm(DocumentDownloadForm): + preserve_extension = forms.BooleanField( + label=_('Preserve extension'), required=False, + help_text=_( + 'Takes the file extension and moves it to the end of the ' + 'filename allowing operating systems that rely on file ' + 'extensions to open the downloaded document version correctly.' + ) + ) + + class DocumentPrintForm(forms.Form): page_group = forms.ChoiceField( choices=PAGE_RANGE_CHOICES, initial=PAGE_RANGE_ALL, diff --git a/mayan/apps/documents/models.py b/mayan/apps/documents/models.py index 02621fb0f9..1f3f487e3c 100644 --- a/mayan/apps/documents/models.py +++ b/mayan/apps/documents/models.py @@ -396,9 +396,7 @@ class DocumentVersion(models.Model): verbose_name_plural = _('Document version') def __str__(self): - return Template( - '{{ instance.document }} - {{ instance.timestamp }}' - ).render(context=Context({'instance': self})) + return self.get_rendered_string() def delete(self, *args, **kwargs): for page in self.pages.all(): @@ -411,6 +409,16 @@ class DocumentVersion(models.Model): def get_absolute_url(self): return reverse('documents:document_version_view', args=(self.pk,)) + def get_rendered_string(self): + return Template( + '{{ instance.document }} - {{ instance.timestamp }}' + ).render(context=Context({'instance': self})) + + def get_rendered_timestamp(self): + return Template('{{ instance.timestamp }}').render( + context=Context({'instance': self}) + ) + def save(self, *args, **kwargs): """ Overloaded save method that updates the document version's checksum, diff --git a/mayan/apps/documents/views/document_version_views.py b/mayan/apps/documents/views/document_version_views.py index 83e909d96b..4c72d36012 100644 --- a/mayan/apps/documents/views/document_version_views.py +++ b/mayan/apps/documents/views/document_version_views.py @@ -1,9 +1,11 @@ from __future__ import absolute_import, unicode_literals import logging +import os from django.contrib import messages from django.shortcuts import get_object_or_404 +from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _ from acls.models import AccessControlList @@ -12,7 +14,7 @@ from common.generics import ( ) from ..events import event_document_view -from ..forms import DocumentVersionPreviewForm +from ..forms import DocumentVersionDownloadForm, DocumentVersionPreviewForm from ..models import Document, DocumentVersion from ..permissions import ( permission_document_download, permission_document_version_revert, @@ -81,10 +83,23 @@ class DocumentVersionRevertView(ConfirmView): class DocumentVersionDownloadFormView(DocumentDownloadFormView): + form_class = DocumentVersionDownloadForm model = DocumentVersion multiple_download_view = None + querystring_form_fields = ( + 'compressed', 'zip_filename', 'preserve_extension' + ) single_download_view = 'documents:document_version_download' + def get_extra_context(self): + result = super( + DocumentVersionDownloadFormView, self + ).get_extra_context() + + result['title'] = _('Download document version') + + return result + def get_document_queryset(self): id_list = self.request.GET.get( 'id_list', self.request.POST.get('id_list', '') @@ -102,6 +117,25 @@ class DocumentVersionDownloadView(DocumentDownloadView): model = DocumentVersion object_permission = permission_document_download + @staticmethod + def get_item_file(item): + return item.file + + def get_item_label(self, item): + preserve_extension = self.request.GET.get( + 'preserve_extension', self.request.POST.get( + 'preserve_extension', False + ) + ) + + if preserve_extension: + filename, extension = os.path.splitext(item.document.label) + return '{} ({}){}'.format( + filename, item.get_rendered_timestamp(), extension + ) + else: + return force_text(item) + class DocumentVersionView(SingleObjectDetailView): form_class = DocumentVersionPreviewForm diff --git a/mayan/apps/documents/views/document_views.py b/mayan/apps/documents/views/document_views.py index 01c8c66f44..ac1cc3ea14 100644 --- a/mayan/apps/documents/views/document_views.py +++ b/mayan/apps/documents/views/document_views.py @@ -402,6 +402,7 @@ class DocumentDownloadFormView(FormView): form_class = DocumentDownloadForm model = Document multiple_download_view = 'documents:document_multiple_download' + querystring_form_fields = ('compressed', 'zip_filename') single_download_view = 'documents:document_download' def get_document_queryset(self): @@ -447,16 +448,23 @@ class DocumentDownloadFormView(FormView): return kwargs def form_valid(self, form): - querystring = urlencode( + querystring_dictionary = {} + + for field in self.querystring_form_fields: + data = form.cleaned_data[field] + if data: + querystring_dictionary[field] = data + + querystring_dictionary.update( { - 'compressed': form.cleaned_data['compressed'], - 'zip_filename': form.cleaned_data['zip_filename'], 'id_list': ','.join( map(str, self.queryset.values_list('pk', flat=True)) ) - }, doseq=True + } ) + querystring = urlencode(querystring_dictionary, doseq=True) + if self.queryset.count() > 1: url = reverse(self.multiple_download_view) else: @@ -497,17 +505,7 @@ class DocumentDownloadView(SingleObjectDownloadView): @staticmethod def get_item_file(item): - if isinstance(item, Document): - return item.open() - else: - return item.file - - @staticmethod - def get_item_label(item): - if isinstance(item, Document): - return item.label - else: - return force_text(item) + return item.open() def get_document_queryset(self): id_list = self.request.GET.get( @@ -532,10 +530,9 @@ class DocumentDownloadView(SingleObjectDownloadView): if self.request.GET.get('compressed') == 'True' or queryset.count() > 1: compressed_file = CompressedFile() for item in queryset: - descriptor = item.open() + descriptor = DocumentDownloadView.get_item_file(item=item) compressed_file.add_file( - descriptor, - arcname=DocumentDownloadView.get_item_label(item=item) + descriptor, arcname=self.get_item_label(item=item) ) descriptor.close() DocumentDownloadView.commit_event( @@ -559,11 +556,12 @@ class DocumentDownloadView(SingleObjectDownloadView): return DocumentDownloadView.VirtualFile( DocumentDownloadView.get_item_file(item=item), - name=DocumentDownloadView.get_item_label( - item=item - ) + name=self.get_item_label(item=item) ) + def get_item_label(self, item): + return item.label + class DocumentUpdatePageCountView(MultipleObjectConfirmActionView): model = Document