mirror of
https://github.com/wagtail/wagtail.git
synced 2024-12-01 11:41:20 +01:00
Prevent multiple TaskState approvals/rejections. Allow TaskState to be passed through to workflow_action to prevent race conditions: ie reviewer approving while in the meantime edits have been made. Add a new task preview view to allow preview of the revision in moderation in a specific task.
This commit is contained in:
parent
4c66ebe36d
commit
3a361c9665
@ -3,6 +3,5 @@
|
||||
|
||||
{% block content %}
|
||||
<p>{% blocktrans with title=page.get_admin_display_title task=task.name %}The page "{{ title }}" has been approved in moderation stage "{{ task }}".{% endblocktrans %}</p>
|
||||
<p>{% trans "You can preview the page here:" %} <a href="{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}">{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}</a><br/></p>
|
||||
<p>{% trans "You can edit the page here:"%} <a href="{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}">{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}</a></p>
|
||||
{% endblock %}
|
||||
|
@ -3,6 +3,5 @@
|
||||
|
||||
{% block content %}
|
||||
{% blocktrans with title=page.get_admin_display_title|safe task=task.name %}The page "{{ title }}" has been approved in moderation stage "{{ task }}".{% endblocktrans %}
|
||||
{% trans "You can preview the page here:" %} {{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}
|
||||
{% trans "You can edit the page here:"%} {{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}
|
||||
{% endblock %}
|
||||
|
@ -3,6 +3,5 @@
|
||||
|
||||
{% block content %}
|
||||
{% blocktrans with title=page.get_admin_display_title|safe task=task.name %}The page "{{ title }}" has been rejected in moderation stage "{{ task }}".{% endblocktrans %}
|
||||
|
||||
{% trans "You can edit the page here:"%} {{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}
|
||||
{% endblock %}
|
||||
|
@ -6,7 +6,7 @@
|
||||
<p>{% blocktrans with task=task.name title=page.get_admin_display_title %}The page "{{ title }}" has been submitted for approval in moderation stage "{{ task }}".{% endblocktrans %}</p>
|
||||
|
||||
<p>
|
||||
{% trans "You can preview the page here:" %} <a href="{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}">{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}</a><br/>
|
||||
{% trans "You can preview the page here:" %} <a href="{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:workflow_preview' page.id task.id %}">{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:workflow_preview' page.id task.id %}</a><br/>
|
||||
{% trans "You can edit the page here:" %} <a href="{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}">{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
@ -6,7 +6,7 @@
|
||||
{% blocktrans with task=task.name title=page.get_admin_display_title %}The page "{{ title }}" has been submitted for approval to moderation stage "{{ task }}".{% endblocktrans %}
|
||||
|
||||
|
||||
{% trans "You can preview the page here:" %} {{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}
|
||||
{% trans "You can preview the page here:" %} {{ settings.BASE_URL }}{% url 'wagtailadmin_pages:workflow_preview' page.id task.id %}
|
||||
{% trans "You can edit the page here:" %} {{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -6,7 +6,6 @@
|
||||
<p>{% blocktrans with workflow=workflow.name title=page.get_admin_display_title %}The page "{{ title }}" has been submitted for moderation to workflow "{{ workflow }}".{% endblocktrans %}</p>
|
||||
|
||||
<p>
|
||||
{% trans "You can preview the page here:" %} <a href="{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}">{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}</a><br/>
|
||||
{% trans "You can edit the page here:" %} <a href="{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}">{{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
@ -6,7 +6,6 @@
|
||||
{% blocktrans with workflow=workflow.name title=page.get_admin_display_title %}The page "{{ title }}" has been submitted for moderation to workflow "{{ workflow }}".{% endblocktrans %}
|
||||
|
||||
|
||||
{% trans "You can preview the page here:" %} {{ settings.BASE_URL }}{% url 'wagtailadmin_pages:preview_on_edit' page.id %}
|
||||
{% trans "You can edit the page here:" %} {{ settings.BASE_URL }}{% url 'wagtailadmin_pages:edit' page.id %}
|
||||
|
||||
{% endblock %}
|
||||
|
@ -174,12 +174,11 @@
|
||||
actionFieldElement.value = buttonElement.dataset.workflowAction;
|
||||
formElement.appendChild(actionFieldElement);
|
||||
|
||||
var nextFieldElement = document.createElement('input');
|
||||
nextFieldElement.type = 'hidden';
|
||||
nextFieldElement.name = 'next';
|
||||
{% url 'wagtailadmin_home' as dashboard_url %}
|
||||
nextFieldElement.value = '{{ dashboard_url|escapejs }}';
|
||||
formElement.appendChild(nextFieldElement);
|
||||
var taskFieldElement = document.createElement('input');
|
||||
taskFieldElement.type = 'hidden';
|
||||
taskFieldElement.name = 'task_id';
|
||||
taskFieldElement.value = {{ current_task_state.id }};
|
||||
formElement.appendChild(taskFieldElement);
|
||||
|
||||
document.body.appendChild(formElement);
|
||||
formElement.submit();
|
||||
|
@ -26,6 +26,7 @@ urlpatterns = [
|
||||
path('<int:page_id>/copy/', pages.copy, name='copy'),
|
||||
|
||||
path('workflow/action/<int:page_id>/', pages.workflow_action, name='workflow_action'),
|
||||
path('workflow/preview/<int:page_id>/<int:task_id>/', pages.preview_revision_for_task, name='workflow_preview'),
|
||||
|
||||
path('moderation/<int:revision_id>/approve/', pages.approve_moderation, name='approve_moderation'),
|
||||
path('moderation/<int:revision_id>/reject/', pages.reject_moderation, name='reject_moderation'),
|
||||
|
@ -651,11 +651,7 @@ def edit(request, page_id):
|
||||
'has_unsaved_changes': has_unsaved_changes,
|
||||
'page_locked': page_perms.page_locked(),
|
||||
'workflow_actions': page.current_workflow_task.get_actions(page, request.user) if page.current_workflow_task else [],
|
||||
'task_statuses': task_statuses,
|
||||
'current_task_number': current_task_number,
|
||||
'task_name': task_name,
|
||||
'workflow_name': workflow_name,
|
||||
'total_tasks': total_tasks
|
||||
'current_task_state': page.current_workflow_task_state
|
||||
})
|
||||
|
||||
|
||||
@ -1196,20 +1192,27 @@ def workflow_action(request, page_id):
|
||||
|
||||
redirect_to = request.POST.get('next', None)
|
||||
if not redirect_to or not is_safe_url(url=redirect_to, allowed_hosts={request.get_host()}):
|
||||
redirect_to = reverse('wagtailadmin_explore', args=[page.get_parent().id])
|
||||
redirect_to = reverse('wagtailadmin_pages:edit', args=[page_id])
|
||||
|
||||
if not page.workflow_in_progress():
|
||||
messages.error(request, _("The page '{0}' is not currently awaiting moderation.").format(page.get_admin_display_title()))
|
||||
return redirect(redirect_to)
|
||||
|
||||
actions = page.current_workflow_task.get_actions(page, request.user)
|
||||
task_state_id = request.POST.get('task_state_id', None)
|
||||
|
||||
task_state = TaskState.objects.get(id=task_state_id) if task_state_id else page.current_workflow_task_state
|
||||
task_state = task_state.specific
|
||||
|
||||
task = task_state.task.specific
|
||||
|
||||
actions = task.get_actions(page, request.user)
|
||||
|
||||
action_name = request.POST.get('action')
|
||||
|
||||
if action_name not in set(action[0] for action in actions):
|
||||
raise PermissionDenied
|
||||
|
||||
page.current_workflow_task.on_action(page.current_workflow_task_state, request.user, action_name)
|
||||
task.on_action(task_state, request.user, action_name)
|
||||
|
||||
return redirect(redirect_to)
|
||||
|
||||
@ -1236,6 +1239,33 @@ def preview_for_moderation(request, revision_id):
|
||||
})
|
||||
|
||||
|
||||
@require_GET
|
||||
def preview_revision_for_task(request, page_id, task_id):
|
||||
"""Preview the revision linked to the in-progress TaskState of a specified Task. This enables pages in moderation
|
||||
to be edited and new TaskStates linked to the new revisions created, with preview links remaining valid"""
|
||||
|
||||
page = Page.objects.get(id=page_id)
|
||||
task = Task.objects.get(id=task_id).specific
|
||||
try:
|
||||
task_state = TaskState.objects.get(page_revision__page=page, task=task, status=TaskState.STATUS_IN_PROGRESS)
|
||||
except TaskState.DoesNotExist:
|
||||
messages.error(request, _("The page '{0}' is not currently awaiting moderation in task '{1}'.").format(page.get_admin_display_title(), task.name))
|
||||
return redirect('wagtailadmin_home')
|
||||
|
||||
revision = task_state.page_revision
|
||||
|
||||
if not task.get_actions(page, request.user):
|
||||
raise PermissionDenied
|
||||
|
||||
page_to_view = revision.as_page_object()
|
||||
|
||||
# TODO: provide workflow actions within this view
|
||||
|
||||
return page_to_view.make_preview_request(request, page.default_preview_mode, extra_request_attrs={
|
||||
'revision_id': revision.id
|
||||
})
|
||||
|
||||
|
||||
@require_POST
|
||||
def lock(request, page_id):
|
||||
# Get the page
|
||||
|
@ -9,7 +9,7 @@ from django.contrib.auth.models import Group, Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core import checks
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.exceptions import ValidationError, PermissionDenied
|
||||
from django.core.handlers.base import BaseHandler
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.db import models, transaction
|
||||
@ -2742,12 +2742,16 @@ class WorkflowState(models.Model):
|
||||
return Task.objects.filter(workflow_tasks__workflow=self.workflow, active=True).exclude(Q(task_states__page_revision=self.page.get_latest_revision()), Q(task_states__status=TaskState.STATUS_APPROVED) | Q(task_states__status=TaskState.STATUS_SKIPPED)).order_by('workflow_tasks__sort_order').first()
|
||||
|
||||
def cancel(self, user=None):
|
||||
if self.status != self.STATUS_IN_PROGRESS:
|
||||
raise PermissionDenied
|
||||
self.status = 'cancelled'
|
||||
self.save()
|
||||
workflow_cancelled.send(sender=self.__class__, instance=self, user=user)
|
||||
|
||||
@transaction.atomic
|
||||
def finish(self, user=None):
|
||||
if self.status != self.STATUS_IN_PROGRESS:
|
||||
raise PermissionDenied
|
||||
self.status = 'approved'
|
||||
self.save()
|
||||
self.on_finish()
|
||||
@ -2827,6 +2831,8 @@ class TaskState(models.Model):
|
||||
|
||||
@transaction.atomic
|
||||
def approve(self, user=None):
|
||||
if self.status != self.STATUS_IN_PROGRESS:
|
||||
raise PermissionDenied
|
||||
self.status = 'approved'
|
||||
self.finished_at = timezone.now()
|
||||
self.save()
|
||||
@ -2836,6 +2842,8 @@ class TaskState(models.Model):
|
||||
|
||||
@transaction.atomic
|
||||
def reject(self, user=None):
|
||||
if self.status != self.STATUS_IN_PROGRESS:
|
||||
raise PermissionDenied
|
||||
self.status = 'rejected'
|
||||
self.finished_at = timezone.now()
|
||||
self.save()
|
||||
|
Loading…
Reference in New Issue
Block a user