start review and reject changesets
This commit is contained in:
parent
093b55923e
commit
2aa163e6ed
6 changed files with 128 additions and 4 deletions
|
@ -2,12 +2,12 @@ import json
|
|||
from collections import OrderedDict
|
||||
|
||||
from django.conf import settings
|
||||
from django.forms import CharField, ModelForm, ValidationError
|
||||
from django.forms import BooleanField, CharField, ModelForm, ValidationError
|
||||
from django.forms.widgets import HiddenInput
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from shapely.geometry.geo import mapping
|
||||
|
||||
from c3nav.editor.models import ChangeSet
|
||||
from c3nav.editor.models import ChangeSet, ChangeSetUpdate
|
||||
|
||||
|
||||
class MapitemFormMixin(ModelForm):
|
||||
|
@ -112,3 +112,11 @@ class ChangeSetForm(ModelForm):
|
|||
class Meta:
|
||||
model = ChangeSet
|
||||
fields = ('title', 'description')
|
||||
|
||||
|
||||
class RejectForm(ModelForm):
|
||||
final = BooleanField(label=_('Final rejection'), required=False)
|
||||
|
||||
class Meta:
|
||||
model = ChangeSetUpdate
|
||||
fields = ('comment', )
|
||||
|
|
|
@ -297,6 +297,20 @@ class ChangeSet(models.Model):
|
|||
def can_unpropose(self, request):
|
||||
return self.author_id == request.user.pk and self.state in ('proposed', 'reproposed')
|
||||
|
||||
def can_review(self, request):
|
||||
# todo implement permissions
|
||||
return self.is_author(request)
|
||||
|
||||
def can_start_review(self, request):
|
||||
return self.can_review(request) and self.state in ('proposed', 'reproposed')
|
||||
|
||||
def can_end_review(self, request):
|
||||
return self.can_review(request) and self.state == 'review' and self.assigned_to == request.user
|
||||
|
||||
def can_unreject(self, request):
|
||||
return (self.can_review(request) and self.state in ('rejected', 'finallyrejected') and
|
||||
self.assigned_to == request.user)
|
||||
|
||||
"""
|
||||
Update methods
|
||||
"""
|
||||
|
@ -316,6 +330,43 @@ class ChangeSet(models.Model):
|
|||
self.last_state_update = update
|
||||
self.save()
|
||||
|
||||
def start_review(self, user):
|
||||
assign_to = user
|
||||
if self.assigned_to == user:
|
||||
assign_to = None
|
||||
else:
|
||||
self.assigned_to = user
|
||||
|
||||
if self.state != 'review':
|
||||
update = self.updates.create(user=user, state='review', assigned_to=assign_to)
|
||||
self.state = 'review'
|
||||
self.last_state_update = update
|
||||
elif assign_to is None:
|
||||
return
|
||||
else:
|
||||
update = self.updates.create(user=user, assigned_to=assign_to)
|
||||
|
||||
self.last_update = update
|
||||
self.save()
|
||||
|
||||
def reject(self, user, comment: str, final: bool):
|
||||
state = 'finallyrejected' if final else 'rejected'
|
||||
update = self.updates.create(user=user, state=state, comment=comment)
|
||||
self.state = state
|
||||
self.last_state_change = update
|
||||
self.last_update = update
|
||||
self.save()
|
||||
|
||||
def unreject(self, user):
|
||||
update = self.updates.create(user=user, state='review')
|
||||
self.state = 'review'
|
||||
self.last_state_change = update
|
||||
self.last_update = update
|
||||
self.save()
|
||||
|
||||
def apply(self, user):
|
||||
pass
|
||||
|
||||
def activate(self, request):
|
||||
request.session['changeset'] = self.pk
|
||||
|
||||
|
|
|
@ -127,9 +127,19 @@
|
|||
{% if can_edit %}
|
||||
<a href="{% url 'editor.changesets.edit' pk=changeset.pk %}" class="btn btn-default">{% trans 'Edit' %}</a>
|
||||
{% endif %}
|
||||
{% if can_edit and not changeset.proposed and active %}
|
||||
{% if can_edit and not changeset.proposed %}
|
||||
<button type="submit" class="btn btn-primary" name="propose" value="1">{% trans 'Propose' %}</button>
|
||||
{% endif %}
|
||||
{% if can_start_review %}
|
||||
<button type="submit" class="btn btn-primary" name="review" value="1">{% trans 'Review' %}</button>
|
||||
{% endif %}
|
||||
{% if can_end_review %}
|
||||
<button type="submit" class="btn btn-danger" name="reject" value="1">{% trans 'Reject' %}</button>
|
||||
<button type="submit" class="btn btn-success" name="apply" value="1">{% trans 'Apply' %}</button>
|
||||
{% endif %}
|
||||
{% if can_unreject %}
|
||||
<button type="submit" class="btn btn-default" name="reject" value="1">{% trans 'Unreject' %}</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if not active and not changeset.closed %}
|
||||
<button type="submit" class="btn btn-info" name="activate" value="1">{% trans 'Activate' %}</button>
|
||||
|
|
20
src/c3nav/editor/templates/editor/changeset_reject.html
Normal file
20
src/c3nav/editor/templates/editor/changeset_reject.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% include 'editor/fragment_modal_close.html' %}
|
||||
<h3>{% trans 'Reject changes' %}</h3>
|
||||
<form action="{{ request.path }}" method="post">
|
||||
{% csrf_token %}
|
||||
<p>{% trans 'Please explain why you reject these changes.' %}</p>
|
||||
{% bootstrap_form form %}
|
||||
<input type="hidden" name="reject" value="1">
|
||||
{% buttons %}
|
||||
<button class="invisiblesubmit" type="submit"></button>
|
||||
<a class="btn btn-default" href="{{ request.path }}">
|
||||
{% trans 'Cancel' %}
|
||||
</a>
|
||||
<button type="submit" name="reject_confirm" value="1" class="btn btn-danger pull-right">
|
||||
{% trans 'Reject' %}
|
||||
</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
|
@ -9,7 +9,7 @@ from django.shortcuts import get_object_or_404, redirect, render
|
|||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from c3nav.editor.forms import ChangeSetForm
|
||||
from c3nav.editor.forms import ChangeSetForm, RejectForm
|
||||
from c3nav.editor.models import ChangeSet
|
||||
from c3nav.editor.utils import is_created_pk
|
||||
from c3nav.editor.views.base import sidebar_view
|
||||
|
@ -83,6 +83,38 @@ def changeset_detail(request, pk):
|
|||
|
||||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
||||
elif request.POST.get('review') == '1':
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if changeset.can_start_review(request):
|
||||
changeset.start_review(request.user)
|
||||
messages.success(request, _('You are not reviewing these changes.'))
|
||||
else:
|
||||
messages.error(request, _('You cannot review these changes.'))
|
||||
|
||||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
||||
elif request.POST.get('reject') == '1':
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if not changeset.can_end_review(request):
|
||||
messages.error(request, _('You cannot reject these changes.'))
|
||||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
||||
if request.POST.get('reject_confirm') == '1':
|
||||
form = RejectForm(data=request.POST)
|
||||
if form.is_valid():
|
||||
changeset.reject(request.user, form.cleaned_data['comment'], form.cleaned_data['final'])
|
||||
messages.success(request, _('You rejected these changes.'))
|
||||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
else:
|
||||
form = RejectForm()
|
||||
|
||||
return render(request, 'editor/changeset_reject.html', {
|
||||
'changeset': changeset,
|
||||
'form': form,
|
||||
})
|
||||
|
||||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
||||
elif request.POST.get('delete') == '1':
|
||||
if not changeset.can_delete(request):
|
||||
raise PermissionDenied
|
||||
|
@ -263,6 +295,9 @@ def changeset_detail(request, pk):
|
|||
'can_edit': can_edit,
|
||||
'can_delete': can_delete,
|
||||
'can_unpropose': changeset.can_unpropose(request),
|
||||
'can_start_review': changeset.can_start_review(request),
|
||||
'can_end_review': changeset.can_end_review(request),
|
||||
'can_unreject': changeset.can_unreject(request),
|
||||
'active': active,
|
||||
'changed_objects': changed_objects_data,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue