diff --git a/HISTORY.rst b/HISTORY.rst index 148435acb5..b9a6b71219 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -129,6 +129,10 @@ - Add custom AJAX spinner. - Complete refactor of the compress archive class support. Closes GitLab issue #7. +- Add support for preserving the extension of document files when + using the quick label feature. Added to the document properties + edit view and the document upload view. Closes GitLab issue + #360. 3.0.3 (2018-08-17) ================== diff --git a/docs/releases/3.1.rst b/docs/releases/3.1.rst index 00b37a8801..af1fd17ada 100644 --- a/docs/releases/3.1.rst +++ b/docs/releases/3.1.rst @@ -343,6 +343,12 @@ classes beyond the provide line chart. - Remove the duplicated setting pdftotext_path from the OCR path. This is now handled by the document parsing app. - Implement partial refresh of the main menu. +- Complete refactor of the compress archive class support. Closes + GitLab issue #7. +- Add support for preserving the extension of document files when + using the quick label feature. Added to the document properties + edit view and the document upload view. Closes GitLab issue + #360. Removals @@ -426,5 +432,6 @@ Bugs fixed or issues closed * `GitLab issue #7 `_ Feature: other compressors than zip for compressed documents * `GitLab issue #259 `_ Thumbnails: why are they created on the fly (therefore: not cached) - +* `GitLab issue #360 `_ Should quick rename (optionally) retain original file type extension? + .. _PyPI: https://pypi.python.org/pypi/mayan-edms/ diff --git a/mayan/apps/document_parsing/tests/test_models.py b/mayan/apps/document_parsing/tests/test_models.py index 4856676b6d..887f00cbf3 100644 --- a/mayan/apps/document_parsing/tests/test_models.py +++ b/mayan/apps/document_parsing/tests/test_models.py @@ -11,13 +11,13 @@ class DocumentAutoParsingTestCase(GenericDocumentTestCase): @override_settings(DOCUMENT_PARSING_AUTO_PARSING=False) def test_disable_auto_parsing(self): - self.create_document_type() + self._create_document_type() self.document = self.upload_document() with self.assertRaises(StopIteration): self.document.latest_version.content().next() @override_settings(DOCUMENT_PARSING_AUTO_PARSING=True) def test_enabled_auto_parsing(self): - self.create_document_type() + self._create_document_type() self.document = self.upload_document() self.assertTrue('Mayan' in self.document.content().next()) diff --git a/mayan/apps/documents/forms.py b/mayan/apps/documents/forms.py index a1e1af47bf..0e1254dd84 100644 --- a/mayan/apps/documents/forms.py +++ b/mayan/apps/documents/forms.py @@ -1,6 +1,7 @@ from __future__ import absolute_import, unicode_literals import logging +import os from django import forms from django.template.defaultfilters import filesizeformat @@ -99,16 +100,42 @@ class DocumentForm(forms.ModelForm): } ) ) + self.fields['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 document correctly.' + ) + ) def clean(self): - if 'document_type_available_filenames' in self.cleaned_data: - if self.cleaned_data['document_type_available_filenames']: - self.cleaned_data['label'] = self.cleaned_data[ - 'document_type_available_filenames' - ] + self.cleaned_data['label'] = self.get_final_label( + # Fallback to the instance label if there is no label key or + # there is a label key and is an empty string + filename=self.cleaned_data.get('label') or self.instance.label + ) return self.cleaned_data + def get_final_label(self, filename): + if 'document_type_available_filenames' in self.cleaned_data: + if self.cleaned_data['document_type_available_filenames']: + if self.cleaned_data['preserve_extension']: + filename, extension = os.path.splitext(filename) + + filename = '{}{}'.format( + self.cleaned_data[ + 'document_type_available_filenames' + ].filename, extension + ) + else: + filename = self.cleaned_data[ + 'document_type_available_filenames' + ].filename + + return filename + class DocumentPropertiesForm(DetailForm): """ diff --git a/mayan/apps/documents/tests/mixins.py b/mayan/apps/documents/tests/mixins.py index e56b0d5577..c334780738 100644 --- a/mayan/apps/documents/tests/mixins.py +++ b/mayan/apps/documents/tests/mixins.py @@ -6,7 +6,10 @@ from django.conf import settings from ..models import DocumentType -from .literals import TEST_DOCUMENT_TYPE_LABEL, TEST_SMALL_DOCUMENT_FILENAME +from .literals import ( + TEST_DOCUMENT_TYPE_LABEL, TEST_SMALL_DOCUMENT_FILENAME, + TEST_DOCUMENT_TYPE_QUICK_LABEL +) __all__ = ('DocumentTestMixin',) @@ -16,7 +19,7 @@ class DocumentTestMixin(object): auto_upload_document = True test_document_filename = TEST_SMALL_DOCUMENT_FILENAME - def create_document_type(self): + def _create_document_type(self): self.document_type = DocumentType.objects.create( label=TEST_DOCUMENT_TYPE_LABEL ) @@ -36,7 +39,7 @@ class DocumentTestMixin(object): ) if self.auto_create_document_type: - self.create_document_type() + self._create_document_type() if self.auto_upload_document: self.document = self.upload_document() @@ -45,3 +48,10 @@ class DocumentTestMixin(object): for document_type in DocumentType.objects.all(): document_type.delete() super(DocumentTestMixin, self).tearDown() + + +class DocumentTypeQuickLabelTestMixin(object): + def _create_quick_label(self): + self.document_type_filename = self.document_type.filenames.create( + filename=TEST_DOCUMENT_TYPE_QUICK_LABEL + ) diff --git a/mayan/apps/documents/tests/test_document_type_views.py b/mayan/apps/documents/tests/test_document_type_views.py index 3794123c50..3c499f2a2e 100644 --- a/mayan/apps/documents/tests/test_document_type_views.py +++ b/mayan/apps/documents/tests/test_document_type_views.py @@ -14,6 +14,7 @@ from .literals import ( TEST_DOCUMENT_TYPE_LABEL, TEST_DOCUMENT_TYPE_LABEL_EDITED, TEST_DOCUMENT_TYPE_QUICK_LABEL, TEST_DOCUMENT_TYPE_QUICK_LABEL_EDITED ) +from .mixins import DocumentTypeQuickLabelTestMixin class DocumentTypeViewsTestCase(GenericDocumentViewTestCase): @@ -98,7 +99,7 @@ class DocumentTypeViewsTestCase(GenericDocumentViewTestCase): ) -class DocumentTypeQuickLabelViewsTestCase(GenericDocumentViewTestCase): +class DocumentTypeQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericDocumentViewTestCase): def setUp(self): super(DocumentTypeQuickLabelViewsTestCase, self).setUp() self.login_user() @@ -130,11 +131,6 @@ class DocumentTypeQuickLabelViewsTestCase(GenericDocumentViewTestCase): self.assertEqual(self.document_type.filenames.count(), 1) - def _create_quick_label(self): - self.document_type_filename = self.document_type.filenames.create( - filename=TEST_DOCUMENT_TYPE_QUICK_LABEL - ) - def _request_quick_label_delete(self): return self.post( viewname='documents:document_type_filename_delete', diff --git a/mayan/apps/documents/tests/test_document_views.py b/mayan/apps/documents/tests/test_document_views.py index 91922a3865..8f6fd12ed8 100644 --- a/mayan/apps/documents/tests/test_document_views.py +++ b/mayan/apps/documents/tests/test_document_views.py @@ -2,6 +2,8 @@ from __future__ import unicode_literals +import os + from django.contrib.contenttypes.models import ContentType from django.utils.encoding import force_text @@ -22,6 +24,7 @@ from .literals import ( TEST_DOCUMENT_TYPE_2_LABEL, TEST_SMALL_DOCUMENT_FILENAME, TEST_TRANSFORMATION_ARGUMENT, TEST_TRANSFORMATION_NAME, ) +from .mixins import DocumentTypeQuickLabelTestMixin class DocumentsViewsTestCase(GenericDocumentViewTestCase): @@ -558,3 +561,74 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase): ) response = self._request_print_view() self.assertEqual(response.status_code, 200) + + +class DocumentsQuickLabelViewsTestCase(DocumentTypeQuickLabelTestMixin, GenericDocumentViewTestCase): + def setUp(self): + super(DocumentsQuickLabelViewsTestCase, self).setUp() + self.login_user() + + def _request_document_quick_label_edit_view(self, extra_data=None): + data = { + 'document_type_available_filenames': self.document_type_filename.pk, + 'label': '' # View needs at least an empty label for quick + # label to work. Cause is unknown. + } + data.update(extra_data or {}) + + return self.post( + viewname='documents:document_edit', args=(self.document.pk,), + data=data + ) + + def test_document_quick_label_no_permission(self): + self._create_quick_label() + response = self._request_document_quick_label_edit_view() + self.assertEqual(response.status_code, 403) + self.document.refresh_from_db() + + def test_document_quick_label_with_access(self): + self._create_quick_label() + self.grant_access( + permission=permission_document_properties_edit, obj=self.document + ) + response = self._request_document_quick_label_edit_view() + self.assertEqual(response.status_code, 302) + self.document.refresh_from_db() + self.assertEqual( + self.document.label, self.document_type_filename.filename + ) + + def test_document_quick_label_preserve_extension_with_access(self): + self._create_quick_label() + self.grant_access( + permission=permission_document_properties_edit, obj=self.document + ) + filename, extension = os.path.splitext(self.document.label) + response = self._request_document_quick_label_edit_view( + extra_data={'preserve_extension': True} + ) + self.assertEqual(response.status_code, 302) + self.document.refresh_from_db() + + self.assertEqual( + self.document.label, '{}{}'.format( + self.document_type_filename.filename, extension + ) + ) + + def test_document_quick_label_no_preserve_extension_with_access(self): + self._create_quick_label() + self.grant_access( + permission=permission_document_properties_edit, obj=self.document + ) + filename, extension = os.path.splitext(self.document.label) + response = self._request_document_quick_label_edit_view( + extra_data={'preserve_extension': False} + ) + self.assertEqual(response.status_code, 302) + self.document.refresh_from_db() + + self.assertEqual( + self.document.label, self.document_type_filename.filename + ) diff --git a/mayan/apps/documents/views/document_version_views.py b/mayan/apps/documents/views/document_version_views.py index a0d0d0982a..f54471c3e8 100644 --- a/mayan/apps/documents/views/document_version_views.py +++ b/mayan/apps/documents/views/document_version_views.py @@ -95,7 +95,9 @@ class DocumentVersionDownloadFormView(DocumentDownloadFormView): DocumentVersionDownloadFormView, self ).get_extra_context() - result['title'] = _('Download document version') + result.update({ + 'title': _('Download document version'), + }) return result diff --git a/mayan/apps/metadata/tests/test_views.py b/mayan/apps/metadata/tests/test_views.py index 44d5fa7963..4bb9cf4bcf 100644 --- a/mayan/apps/metadata/tests/test_views.py +++ b/mayan/apps/metadata/tests/test_views.py @@ -428,7 +428,7 @@ class MetadataTypeViewTestCase(DocumentTestMixin, MetadataTestsMixin, GenericVie def test_metadata_type_relationship_view_no_permission(self): self.login_user() self._create_metadata_type() - self.create_document_type() + self._create_document_type() self.upload_document() response = self._request_metadata_type_relationship_edit_view() @@ -442,7 +442,7 @@ class MetadataTypeViewTestCase(DocumentTestMixin, MetadataTestsMixin, GenericVie def test_metadata_type_relationship_view_with_document_type_access(self): self.login_user() self._create_metadata_type() - self.create_document_type() + self._create_document_type() self.upload_document() self.grant_access( @@ -460,7 +460,7 @@ class MetadataTypeViewTestCase(DocumentTestMixin, MetadataTestsMixin, GenericVie def test_metadata_type_relationship_view_with_metadata_type_access(self): self.login_user() self._create_metadata_type() - self.create_document_type() + self._create_document_type() self.upload_document() self.grant_access( @@ -478,7 +478,7 @@ class MetadataTypeViewTestCase(DocumentTestMixin, MetadataTestsMixin, GenericVie def test_metadata_type_relationship_view_with_metadata_type_and_document_type_access(self): self.login_user() self._create_metadata_type() - self.create_document_type() + self._create_document_type() self.upload_document() self.grant_access( diff --git a/mayan/apps/sources/views.py b/mayan/apps/sources/views.py index c927dc5642..565abf52e9 100644 --- a/mayan/apps/sources/views.py +++ b/mayan/apps/sources/views.py @@ -243,12 +243,6 @@ class UploadInteractiveView(UploadBaseView): file=uploaded_file.file ) - label = None - - if 'document_type_available_filenames' in forms['document_form'].cleaned_data: - if forms['document_form'].cleaned_data['document_type_available_filenames']: - label = forms['document_form'].cleaned_data['document_type_available_filenames'].filename - if not self.request.user.is_anonymous: user_id = self.request.user.pk else: @@ -265,7 +259,9 @@ class UploadInteractiveView(UploadBaseView): description=forms['document_form'].cleaned_data.get('description'), document_type_id=self.document_type.pk, expand=expand, - label=label, + label=forms['document_form'].get_final_label( + filename=force_text(shared_uploaded_file) + ), language=forms['document_form'].cleaned_data.get('language'), querystring=uri_to_iri( '?{}&{}'.format(