Skip to content

Commit

Permalink
Add unpublish_selected among actions
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathan-s committed Oct 14, 2019
1 parent 8a35cc6 commit cf82b7f
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 48 deletions.
112 changes: 66 additions & 46 deletions djangocms_moderation/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -119,6 +120,7 @@ class Media:

actions = [ # filtered out in `self.get_actions`
delete_selected,
unpublish_selected,
publish_selected,
approve_selected,
reject_selected,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -495,39 +516,37 @@ 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',
context
)
else:
resubmitted_requests = []

for node in treenodes.all():
mr = node.moderation_request
if mr.user_can_resubmit(request.user):
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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",
Expand All @@ -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):
Expand Down Expand Up @@ -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",
Expand All @@ -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
Expand Down
9 changes: 8 additions & 1 deletion djangocms_moderation/admin_actions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from collections import defaultdict
from functools import partial

from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
Expand Down Expand Up @@ -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

Expand All @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
<h3>{% trans "Are you sure you want to unpublish these items?" %}</h3>
{% else %}
<h3>{% trans "Are you sure you want to publish these items?" %}</h3>
{% endif %}
<div class="results">
<table id="result_list">
<thead>
Expand Down
19 changes: 18 additions & 1 deletion tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def test_publish_selected_action_visibility(self):
# mr1 request is approved, so user1 can see the publish selected option
self.assertIn("publish_selected", actions)

# user2 should not be able to see it
# user2 should not be able to see it as user2 is not the author
mock_request.user = self.user2
actions = self.mr_tree_admin.get_actions(request=mock_request)
self.assertNotIn("publish_selected", actions)
Expand All @@ -124,6 +124,23 @@ def test_publish_selected_action_visibility(self):
actions = self.mr_tree_admin.get_actions(request=mock_request)
self.assertNotIn("publish_selected", actions)

def test_unpublish_selected_action_visibility(self):
self.collection.workflow.is_unpublishing = True
self.collection.workflow.save()
self.mr1.version.publish(self.user)
mock_request = MockRequest()
mock_request.user = self.user
mock_request._collection = self.collection
actions = self.mr_tree_admin.get_actions(request=mock_request)
# mr1 request is approved, so user1 can see the unpublish selected option
self.assertIn("unpublish_selected", actions)

# if there are no approved requests, user can't see the button either
mock_request.user = self.user
self.mr1.get_last_action().delete()
actions = self.mr_tree_admin.get_actions(request=mock_request)
self.assertNotIn("unpublish_selected", actions)

def test_approve_and_reject_selected_action_visibility(self):
mock_request = MockRequest()
mock_request.user = self.user
Expand Down

0 comments on commit cf82b7f

Please sign in to comment.