diff --git a/mayan/apps/checkouts/views.py b/mayan/apps/checkouts/views.py index ff4e91b3e4..6f46046568 100644 --- a/mayan/apps/checkouts/views.py +++ b/mayan/apps/checkouts/views.py @@ -77,9 +77,6 @@ class CheckoutDocumentView(SingleObjectCreateView): class CheckoutListView(DocumentListView): - def get_document_queryset(self): - return DocumentCheckout.objects.checked_out_documents() - extra_context = { 'title': _('Documents checked out'), 'hide_links': True, @@ -105,6 +102,9 @@ class CheckoutListView(DocumentListView): ), } + def get_document_queryset(self): + return DocumentCheckout.objects.checked_out_documents() + def checkout_info(request, document_pk): document = get_object_or_404(Document, pk=document_pk) @@ -156,9 +156,6 @@ def checkout_info(request, document_pk): class DocumentCheckinView(ConfirmView): - def get_object(self): - return get_object_or_404(Document, pk=self.kwargs['pk']) - def get_extra_context(self): document = self.get_object() @@ -176,8 +173,14 @@ class DocumentCheckinView(ConfirmView): return context - def object_action(self, request, obj): - document = obj + def get_object(self): + return get_object_or_404(Document, pk=self.kwargs['pk']) + + def get_post_action_redirect(self): + return reverse('checkouts:checkout_info', args=(self.get_object().pk,)) + + def view_action(self, request): + document = self.get_object() if document.checkout_info().user == request.user: try: @@ -210,11 +213,3 @@ class DocumentCheckinView(ConfirmView): messages.success( request, _('Document "%s" checked in successfully.') % document ) - - def get_post_action_redirect(self): - return reverse('checkouts:checkout_info', args=(self.get_object().pk,)) - - def post(self, request, *args, **kwargs): - self.object_action(request=request, obj=self.get_object()) - - return HttpResponseRedirect(self.get_success_url()) diff --git a/mayan/apps/common/generics.py b/mayan/apps/common/generics.py index 5564c34b52..b6b1b545eb 100644 --- a/mayan/apps/common/generics.py +++ b/mayan/apps/common/generics.py @@ -169,6 +169,10 @@ class AssignRemoveView(ExtraContextMixin, ViewPermissionCheckMixin, ObjectPermis class ConfirmView(ObjectListPermissionFilterMixin, ViewPermissionCheckMixin, ExtraContextMixin, RedirectionMixin, TemplateView): template_name = 'appearance/generic_confirm.html' + def post(self, request, *args, **kwargs): + self.view_action() + return HttpResponseRedirect(self.get_success_url()) + class MultiFormView(FormView): prefixes = {} diff --git a/mayan/apps/common/mixins.py b/mayan/apps/common/mixins.py index cb02ade704..f70e0a52c4 100644 --- a/mayan/apps/common/mixins.py +++ b/mayan/apps/common/mixins.py @@ -1,10 +1,12 @@ from __future__ import unicode_literals from django.conf import settings +from django.contrib import messages from django.core.exceptions import PermissionDenied from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 +from django.utils.translation import ungettext from acls.models import AccessControlList from permissions import Permission @@ -42,14 +44,33 @@ class ExtraContextMixin(object): class MultipleInstanceActionMixin(object): model = None + success_message = 'Operation performed on %(count)d object' + success_message_plural = 'Operation performed on %(count)d objects' + + def get_success_message(self, count): + return ungettext( + self.success_message, + self.success_message_plural, + count + ) % { + 'count': count, + } def post(self, request, *args, **kwargs): + count = 0 for pk in request.GET.get('id_list', '').split(','): document = get_object_or_404(self.model, pk=pk) try: - self.object_action(request=request, instance=document) + self.object_action(instance=document) except PermissionDenied: pass + else: + count += 1 + + messages.success( + self.request, + self.get_success_message(count=count) + ) return HttpResponseRedirect(self.get_success_url()) diff --git a/mayan/apps/documents/urls.py b/mayan/apps/documents/urls.py index 0ec00637ba..af9d4af2ca 100644 --- a/mayan/apps/documents/urls.py +++ b/mayan/apps/documents/urls.py @@ -13,10 +13,11 @@ from .api_views import ( ) from .settings import setting_print_size, setting_display_size from .views import ( - DeletedDocumentDeleteView, DeletedDocumentListView, DocumentEditView, - DocumentListView, DocumentManyDeleteView, DocumentManyRestoreView, + DeletedDocumentDeleteView, DeletedDocumentDeleteManyView, + DeletedDocumentListView, DocumentEditView, DocumentListView, DocumentPageView, DocumentPageListView, DocumentPreviewView, - DocumentRestoreView, DocumentTypeCreateView, DocumentTypeDeleteView, + DocumentRestoreView, DocumentRestoreManyView, DocumentTrashView, + DocumentTrashManyView, DocumentTypeCreateView, DocumentTypeDeleteView, DocumentTypeDocumentListView, DocumentTypeFilenameDeleteView, DocumentTypeFilenameEditView, DocumentTypeFilenameListView, DocumentTypeListView, DocumentTypeEditView, DocumentVersionListView, @@ -48,7 +49,7 @@ urlpatterns = patterns( name='document_restore' ), url( - r'^multiple/restore/$', DocumentManyRestoreView.as_view(), + r'^multiple/restore/$', DocumentRestoreManyView.as_view(), name='document_multiple_restore' ), url( @@ -56,7 +57,7 @@ urlpatterns = patterns( name='document_delete' ), url( - r'^multiple/delete/$', DocumentManyDeleteView.as_view(), + r'^multiple/delete/$', DeletedDocumentDeleteManyView.as_view(), name='document_multiple_delete' ), url( @@ -68,11 +69,11 @@ urlpatterns = patterns( name='document_multiple_document_type_edit' ), url( - r'^(?P\d+)/trash/$', 'document_trash', + r'^(?P\d+)/trash/$', DocumentTrashView.as_view(), name='document_trash' ), url( - r'^multiple/trash/$', 'document_multiple_trash', + r'^multiple/trash/$', DocumentTrashManyView.as_view(), name='document_multiple_trash' ), url( diff --git a/mayan/apps/documents/views.py b/mayan/apps/documents/views.py index 09db919f43..20a7fd1a68 100644 --- a/mayan/apps/documents/views.py +++ b/mayan/apps/documents/views.py @@ -112,30 +112,39 @@ class DeletedDocumentDeleteView(ConfirmView): 'title': _('Delete the selected document?') } - def object_action(self, request, instance): + def object_action(self, instance): source_document = get_object_or_404( Document.passthrough, pk=instance.pk ) try: Permission.check_permissions( - request.user, (permission_document_delete,) + self.request.user, (permission_document_delete,) ) except PermissionDenied: AccessControlList.objects.check_access( - permission_document_delete, request.user, source_document + permission_document_delete, self.request.user, source_document ) instance.delete() - messages.success(request, _('Document: %(document)s deleted.') % { - 'document': instance} + + def view_action(self): + instance = get_object_or_404(DeletedDocument, pk=self.kwargs['pk']) + self.object_action(instance=instance) + messages.success( + self.request, _('Document: %(document)s deleted.') % { + 'document': instance + } ) - def post(self, request, *args, **kwargs): - document = get_object_or_404(DeletedDocument, pk=self.kwargs['pk']) - self.object_action(request=request, instance=document) - return HttpResponseRedirect(self.get_success_url()) +class DeletedDocumentDeleteManyView(MultipleInstanceActionMixin, DeletedDocumentDeleteView): + extra_context = { + 'title': _('Delete the selected documents?') + } + model = DeletedDocument + success_message = '%(count)d document deleted.' + success_message_plural = '%(count)d documents deleted.' class DocumentEditView(SingleObjectEditView): @@ -172,46 +181,41 @@ class DocumentRestoreView(ConfirmView): 'title': _('Restore the selected document?') } - def object_action(self, request, instance): + def object_action(self, instance): source_document = get_object_or_404( Document.passthrough, pk=instance.pk ) try: Permission.check_permissions( - request.user, (permission_document_restore,) + self.request.user, (permission_document_restore,) ) except PermissionDenied: AccessControlList.objects.check_access( - permission_document_restore, request.user, source_document + permission_document_restore, self.request.user, source_document ) instance.restore() + + def view_action(self): + instance = get_object_or_404(DeletedDocument, pk=self.kwargs['pk']) + + self.object_action(instance=instance) + messages.success( - request, _('Document: %(document)s restored.') % { + self.request, _('Document: %(document)s restored.') % { 'document': instance } ) - def post(self, request, *args, **kwargs): - document = get_object_or_404(DeletedDocument, pk=self.kwargs['pk']) - self.object_action(request=request, instance=document) - return HttpResponseRedirect(self.get_success_url()) - - -class DocumentManyDeleteView(MultipleInstanceActionMixin, DeletedDocumentDeleteView): - extra_context = { - 'title': _('Delete the selected documents?') - } - model = DeletedDocument - - -class DocumentManyRestoreView(MultipleInstanceActionMixin, DocumentRestoreView): +class DocumentRestoreManyView(MultipleInstanceActionMixin, DocumentRestoreView): extra_context = { 'title': _('Restore the selected documents?') } model = DeletedDocument + success_message = '%(count)d document restored.' + success_message_plural = '%(count)d documents restored.' class DocumentPageListView(SingleObjectListView): @@ -309,6 +313,54 @@ class DocumentPreviewView(SingleObjectDetailView): } +class DocumentTrashView(ConfirmView): + def get_extra_context(self): + return { + 'object': self.get_object(), + 'title': _('Move "%s" to the trash?') % self.get_object() + } + + def get_object(self): + return get_object_or_404(Document, pk=self.kwargs['pk']) + + def get_post_action_redirect(self): + return reverse('documents:document_list_recent') + + def object_action(self, instance): + try: + Permission.check_permissions( + self.request.user, (permission_document_trash,) + ) + except PermissionDenied: + AccessControlList.objects.check_access( + permission_document_trash, self.request.user, instance + ) + + instance.delete() + + def view_action(self): + instance = self.get_object() + + self.object_action(instance=instance) + + messages.success( + self.request, _('Document: %(document)s moved to trash successfully.') % { + 'document': instance + } + ) + + +class DocumentTrashManyView(MultipleInstanceActionMixin, DocumentTrashView): + model = Document + success_message = '%(count)d document moved to the trash.' + success_message_plural = '%(count)d documents moved to the trash.' + + def get_extra_context(self): + return { + 'title': _('Move the selected documents to the trash?') + } + + class DocumentTypeDocumentListView(DocumentListView): def get_document_type(self): return get_object_or_404(DocumentType, pk=self.kwargs['pk']) @@ -405,12 +457,6 @@ class DocumentTypeFilenameEditView(SingleObjectEditView): model = DocumentTypeFilename view_permission = permission_document_type_edit - def get_post_action_redirect(self): - return reverse( - 'documents:document_type_filename_list', - args=(self.get_object().document_type.pk,) - ) - def get_extra_context(self): document_type_filename = self.get_object() @@ -427,6 +473,12 @@ class DocumentTypeFilenameEditView(SingleObjectEditView): }, } + def get_post_action_redirect(self): + return reverse( + 'documents:document_type_filename_list', + args=(self.get_object().document_type.pk,) + ) + class DocumentTypeFilenameDeleteView(SingleObjectDeleteView): model = DocumentTypeFilename @@ -553,13 +605,11 @@ class EmptyTrashCanView(ConfirmView): 'documents:document_list_deleted' ) - def post(self, request, *args, **kwargs): + def view_action(self): for deleted_document in DeletedDocument.objects.all(): deleted_document.delete() - messages.success(request, _('Trash emptied successfully')) - - return HttpResponseRedirect(self.get_success_url()) + messages.success(self.request, _('Trash emptied successfully')) class RecentDocumentListView(DocumentListView): @@ -572,70 +622,6 @@ class RecentDocumentListView(DocumentListView): return RecentDocument.objects.get_for_user(self.request.user) -def document_trash(request, document_id=None, document_id_list=None): - post_action_redirect = None - - if document_id: - documents = [get_object_or_404(Document, pk=document_id)] - post_action_redirect = reverse('documents:document_list_recent') - elif document_id_list: - documents = [ - get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',') - ] - else: - messages.error(request, _('Must provide at least one document.')) - return HttpResponseRedirect( - request.META.get( - 'HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL) - ) - ) - - try: - Permission.check_permissions(request.user, (permission_document_trash,)) - except PermissionDenied: - documents = AccessControlList.objects.filter_by_access( - permission_document_trash, request.user, documents - ) - - previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))) - next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))) - - if request.method == 'POST': - for document in documents: - try: - document.delete() - messages.success(request, _('Document moved to trash successfully.')) - except Exception as exception: - messages.error(request, _('Document: %(document)s error moving to trash: %(error)s') % { - 'document': document, 'error': exception - }) - - return HttpResponseRedirect(next) - - context = { - 'delete_view': True, - 'previous': previous, - 'next': next, - 'title': ungettext( - 'Move the selected document to the trash ?', - 'Move the selected documents to the trash ?', - len(documents) - ) - } - - if len(documents) == 1: - context['object'] = documents[0] - - return render_to_response('appearance/generic_confirm.html', context, - context_instance=RequestContext(request)) - - -def document_multiple_trash(request): - return document_trash( - request, document_id_list=request.GET.get('id_list', []) - ) - - def document_document_type_edit(request, document_id=None, document_id_list=None): post_action_redirect = None diff --git a/mayan/apps/ocr/urls.py b/mayan/apps/ocr/urls.py index 55a0fd3711..760300307d 100644 --- a/mayan/apps/ocr/urls.py +++ b/mayan/apps/ocr/urls.py @@ -4,7 +4,7 @@ from django.conf.urls import patterns, url from .api_views import DocumentVersionOCRView from .views import ( - DocumentSubmitView, DocumentAllSubmitView, DocumentManySubmitView, + DocumentAllSubmitView, DocumentSubmitView, DocumentSubmitManyView, DocumentTypeSettingsEditView, EntryListView ) @@ -23,7 +23,7 @@ urlpatterns = patterns( name='document_submit_all' ), url( - r'^document/multiple/submit/$', DocumentManySubmitView.as_view(), + r'^document/multiple/submit/$', DocumentSubmitManyView.as_view(), name='document_submit_multiple' ), url( diff --git a/mayan/apps/ocr/views.py b/mayan/apps/ocr/views.py index 2337581c93..54f45f1e09 100644 --- a/mayan/apps/ocr/views.py +++ b/mayan/apps/ocr/views.py @@ -13,6 +13,7 @@ from acls.models import AccessControlList from common.generics import ( ConfirmView, SingleObjectEditView, SingleObjectListView ) +from common.mixins import MultipleInstanceActionMixin from documents.models import Document, DocumentType, DocumentVersion from permissions import Permission @@ -24,68 +25,68 @@ from .permissions import ( ) -class DocumentSubmitView(ConfirmView): - def get_extra_context(self): - return { - 'object': Document.objects.get(pk=self.kwargs['pk']), - 'title': _('Submit the selected document for OCR?') - } - - def object_action(self, request, obj): - document = obj - - try: - Permission.check_permissions( - request.user, (permission_ocr_document,) - ) - except PermissionDenied: - AccessControlList.objects.check_access( - permission_ocr_document, request.user, document - ) - - document.submit_for_ocr() - messages.success( - request, - _('Document: %(document)s was added to the OCR queue.') % { - 'document': document - } - ) - - def post(self, request, *args, **kwargs): - document = get_object_or_404(Document, pk=self.kwargs['pk']) - self.object_action(request=request, obj=document) - - return HttpResponseRedirect(self.get_success_url()) - - class DocumentAllSubmitView(ConfirmView): extra_context = {'title': _('Submit all documents for OCR?')} - def post(self, request, *args, **kwargs): + def get_post_action_redirect(self): + return reverse('common:tools_list') + + def view_action(self): count = 0 for document in Document.objects.all(): document.submit_for_ocr() count += 1 messages.success( - request, _('%d documents added to the OCR queue.') % count + self.request, _('%d documents added to the OCR queue.') % count ) - return HttpResponseRedirect(self.get_success_url()) + +class DocumentSubmitView(ConfirmView): + def get_extra_context(self): + return { + 'object': self.get_object(), + 'title': _('Submit "%s" to the OCR queue?') % self.get_object() + } + + def get_object(self): + return Document.objects.get(pk=self.kwargs['pk']) + + def object_action(self, instance): + try: + Permission.check_permissions( + self.request.user, (permission_ocr_document,) + ) + except PermissionDenied: + AccessControlList.objects.check_access( + permission_ocr_document, self.request.user, instance + ) + + instance.submit_for_ocr() + + def view_action(self): + instance = self.get_object() + + self.object_action(instance=instance) + + messages.success( + self.request, + _('Document: %(document)s was added to the OCR queue.') % { + 'document': instance + } + ) -class DocumentManySubmitView(DocumentSubmitView): - extra_context = {'title': _('Submit the selected documents for OCR?')} +class DocumentSubmitManyView(MultipleInstanceActionMixin, DocumentSubmitView): + model = Document + success_message = '%(count)d document submitted to the OCR queue.' + success_message_plural = '%(count)d documents submitted to the OCR queue.' - def post(self, request, *args, **kwargs): - for pk in request.GET.get('id_list', '').split(','): - document = get_object_or_404(Document, pk=pk) - try: - self.object_action(request=request, obj=document) - except PermissionDenied: - pass - - return HttpResponseRedirect(self.get_success_url()) + def get_extra_context(self): + # Override the base class method + return { + 'title': _('Submit the selected documents to the OCR queue?') + } class DocumentTypeSettingsEditView(SingleObjectEditView): diff --git a/mayan/apps/statistics/views.py b/mayan/apps/statistics/views.py index 223308d6b5..845dba5a32 100644 --- a/mayan/apps/statistics/views.py +++ b/mayan/apps/statistics/views.py @@ -90,6 +90,5 @@ class StatisticQueueView(ConfirmView): args=(self.get_object().namespace.slug,) ) - def post(self, request, *args, **kwargs): + def view_action(self): task_execute_statistic.delay(slug=self.get_object().slug) - return HttpResponseRedirect(self.get_post_action_redirect())