diff --git a/djangocms_moderation/admin.py b/djangocms_moderation/admin.py index 902b45cf..194da776 100644 --- a/djangocms_moderation/admin.py +++ b/djangocms_moderation/admin.py @@ -29,6 +29,7 @@ publish_selected, reject_selected, resubmit_selected, + unpublish_selected, ) from .emails import notify_collection_author, notify_collection_moderators from .filters import ModeratorFilter, ReviewerFilter @@ -119,6 +120,7 @@ class Media: actions = [ # filtered out in `self.get_actions` delete_selected, + unpublish_selected, publish_selected, approve_selected, reject_selected, @@ -289,31 +291,50 @@ def get_actions(self, request): ) # publish_selected, approve_selected, reject_selected, resubmit_selected else: # If the collection is archived, then no other action than - # `publish_selected` is possible. + # `publish_selected` or `unpublish_selected` is possible. _max_to_keep = 1 # publish_selected for mr in collection.moderation_requests.all().select_related("version"): if len(actions_to_keep) == _max_to_keep: break # We have found all the actions, so no need to loop anymore - if "publish_selected" not in actions_to_keep: - if ( - request.user == collection.author - and mr.version_can_be_published() - ): - actions_to_keep.append("publish_selected") - if ( - collection.status == constants.IN_REVIEW - and "approve_selected" not in actions_to_keep - ): - if mr.user_can_take_moderation_action(request.user): - actions_to_keep.append("approve_selected") - actions_to_keep.append("reject_selected") - if ( - collection.status == constants.IN_REVIEW - and "resubmit_selected" not in actions_to_keep - ): - if mr.user_can_resubmit(request.user): - actions_to_keep.append("resubmit_selected") + + publish_condition = all([ + "publish_selected" not in actions_to_keep, + request.user == collection.author, + collection.workflow.is_unpublishing is False, + mr.version_can_be_published() + ]) + + unpublish_condition = all([ + "unpublish_selected" not in actions_to_keep, + collection.workflow.is_unpublishing is True, + mr.version_can_be_unpublished() + ]) + + approve_condition = all([ + "approve_selected" not in actions_to_keep, + collection.status == constants.IN_REVIEW, + mr.user_can_take_moderation_action(request.user) + ]) + + resubmit_condition = all([ + "resubmit_selected" not in actions_to_keep, + collection.status == constants.IN_REVIEW, + mr.user_can_resubmit(request.user) + ]) + + if unpublish_condition: + actions_to_keep.append("unpublish_selected") + + if publish_condition: + actions_to_keep.append("publish_selected") + + if approve_condition: + actions_to_keep.append("approve_selected") + actions_to_keep.append("reject_selected") + + if resubmit_condition: + actions_to_keep.append("resubmit_selected") # Only collection author can delete moderation requests if collection.author == request.user: @@ -495,31 +516,30 @@ def _get_selected_tree_nodes(self, request): ).select_related('moderation_request') return treenodes - def _custom_view_context(self, request): + def _custom_view_context(self, request, collection): treenodes = self._get_selected_tree_nodes(request) - collection_id = request.GET.get('collection_id') - redirect_url = self._redirect_to_changeview_url(collection_id) + redirect_url = self._redirect_to_changeview_url(collection.pk) return dict( ids=request.GET.getlist("ids"), back_url=redirect_url, - queryset=[n.moderation_request for n in treenodes] + queryset=[n.moderation_request for n in treenodes], + collection=collection ) def resubmit_view(self, request): collection_id = request.GET.get('collection_id') - treenodes = self._get_selected_tree_nodes(request) - redirect_url = self._redirect_to_changeview_url(collection_id) - try: collection = ModerationCollection.objects.get(id=int(collection_id)) except (ValueError, ModerationCollection.DoesNotExist): raise Http404 + treenodes = self._get_selected_tree_nodes(request) + redirect_url = self._redirect_to_changeview_url(collection_id) if collection.author != request.user: raise PermissionDenied if request.method != 'POST': - context = self._custom_view_context(request) + context = self._custom_view_context(request, collection) return render( request, 'admin/djangocms_moderation/moderationrequest/resubmit_confirmation.html', @@ -527,7 +547,6 @@ def resubmit_view(self, request): ) else: resubmitted_requests = [] - for node in treenodes.all(): mr = node.moderation_request if mr.user_can_resubmit(request.user): @@ -568,7 +587,8 @@ def resubmit_view(self, request): def _publish_flow(self, request, queryset): """Handles the published workflow""" published_moderation_requests = [] - for mr in queryset.all(): + for node in queryset.all(): + mr = node.moderation_request if mr.version_can_be_published(): mr.version.publish(request.user) published_moderation_requests.append(mr) @@ -589,7 +609,8 @@ def _publish_flow(self, request, queryset): def _unpublish_flow(self, request, queryset): unpublished_moderation_requests = [] - for mr in queryset.all(): + for node in queryset.all(): + mr = node.moderation_request if mr.version_can_be_unpublished(): mr.version.unpublish(request.user) unpublished_moderation_requests.append(mr) @@ -610,13 +631,12 @@ def _unpublish_flow(self, request, queryset): def published_view(self, request): collection_id = request.GET.get('collection_id') - treenodes = self._get_selected_tree_nodes(request) - redirect_url = self._redirect_to_changeview_url(collection_id) - try: collection = ModerationCollection.objects.get(id=int(collection_id)) except (ValueError, ModerationCollection.DoesNotExist): raise Http404 + treenodes = self._get_selected_tree_nodes(request) + redirect_url = self._redirect_to_changeview_url(collection_id) if request.user != collection.author: raise PermissionDenied @@ -625,7 +645,7 @@ def published_view(self, request): return HttpResponseNotAllowed if request.method == 'GET': - context = self._custom_view_context(request) + context = self._custom_view_context(request, collection) return render( request, "admin/djangocms_moderation/moderationrequest/publish_confirmation.html", @@ -649,24 +669,24 @@ def published_view(self, request): def rework_view(self, request): collection_id = request.GET.get('collection_id') + try: + collection = ModerationCollection.objects.get(id=int(collection_id)) + except (ValueError, ModerationCollection.DoesNotExist): + raise Http404 + treenodes = self._get_selected_tree_nodes(request) redirect_url = self._redirect_to_changeview_url(collection_id) if request.method != 'POST': - context = self._custom_view_context(request) + context = self._custom_view_context(request, collection) return render( request, "admin/djangocms_moderation/moderationrequest/rework_confirmation.html", context, ) else: - try: - collection = ModerationCollection.objects.get(id=int(collection_id)) - except (ValueError, ModerationCollection.DoesNotExist): - raise Http404 rejected_requests = [] - for node in treenodes.all(): moderation_request = node.moderation_request if moderation_request.user_can_take_moderation_action(request.user): @@ -698,11 +718,15 @@ def rework_view(self, request): def approved_view(self, request): collection_id = request.GET.get('collection_id') + try: + collection = ModerationCollection.objects.get(id=int(collection_id)) + except (ValueError, ModerationCollection.DoesNotExist): + raise Http404 treenodes = self._get_selected_tree_nodes(request) redirect_url = self._redirect_to_changeview_url(collection_id) if request.method != 'POST': - context = self._custom_view_context(request) + context = self._custom_view_context(request, collection) return render( request, "admin/djangocms_moderation/moderationrequest/approve_confirmation.html", @@ -723,10 +747,6 @@ def approved_view(self, request): and some in the second, then the reviewers we need to notify are different per request, depending on which stage the request is in """ - try: - collection = ModerationCollection.objects.get(id=int(collection_id)) - except (ValueError, ModerationCollection.DoesNotExist): - raise Http404 approved_requests = [] # Variable we are using to group the requests by action.step_approved diff --git a/djangocms_moderation/admin_actions.py b/djangocms_moderation/admin_actions.py index a8044538..0eaaa519 100644 --- a/djangocms_moderation/admin_actions.py +++ b/djangocms_moderation/admin_actions.py @@ -1,4 +1,5 @@ from collections import defaultdict +from functools import partial from django.contrib import admin from django.contrib.contenttypes.models import ContentType @@ -77,7 +78,7 @@ def delete_selected(modeladmin, request, queryset): delete_selected.short_description = _("Remove selected") -def publish_selected(modeladmin, request, queryset): +def base_publish(modeladmin, request, queryset): if request.user != request._collection.author: raise PermissionDenied @@ -90,8 +91,14 @@ def publish_selected(modeladmin, request, queryset): return HttpResponseRedirect(url) +publish_selected = partial(base_publish) +publish_selected.__name__ = 'publish_selected' publish_selected.short_description = _("Publish selected requests") +unpublish_selected = partial(base_publish) +unpublish_selected.__name__ = 'unpublish_selected' +unpublish_selected.short_description = _("Unpublish selected requests") + def convert_queryset_to_version_queryset(queryset): if not queryset: diff --git a/djangocms_moderation/templates/admin/djangocms_moderation/moderationrequest/publish_confirmation.html b/djangocms_moderation/templates/admin/djangocms_moderation/moderationrequest/publish_confirmation.html index c7b3122c..331a6281 100644 --- a/djangocms_moderation/templates/admin/djangocms_moderation/moderationrequest/publish_confirmation.html +++ b/djangocms_moderation/templates/admin/djangocms_moderation/moderationrequest/publish_confirmation.html @@ -11,7 +11,11 @@ {% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} delete-confirmation{% endblock %} {% block content %} +{% if collection.workflow.is_unpublishing %} +