direct editing

This commit is contained in:
Laura Klünder 2017-07-08 15:42:06 +02:00
parent df19daf501
commit 1caa730fc4
4 changed files with 67 additions and 9 deletions

View file

@ -9,7 +9,7 @@ from django.apps import apps
from django.conf import settings
from django.core.cache import cache
from django.core.exceptions import FieldDoesNotExist
from django.db import models, transaction
from django.db import connection, models, transaction
from django.db.models import Q
from django.urls import reverse
from django.utils.http import int_to_base36
@ -69,6 +69,8 @@ class ChangeSet(models.Model):
self._request = None
self._original_state = self.state
self.direct_editing = False
"""
Get Changesets for Request/Session/User
"""
@ -111,6 +113,8 @@ class ChangeSet(models.Model):
changeset = ChangeSet()
changeset._request = request
if request.session.get('direct_editing', False) and ChangeSet.can_direct_edit(request):
changeset.direct_editing = True
if request.user.is_authenticated:
changeset.author = request.user
@ -124,10 +128,15 @@ class ChangeSet(models.Model):
if isinstance(model, str):
model = apps.get_model('mapdata', model)
assert isinstance(model, type) and issubclass(model, models.Model)
if self.direct_editing:
model.EditorForm = ModelWrapper(self, model).EditorForm
return model
return ModelWrapper(self, model)
def wrap_instance(self, instance):
assert isinstance(instance, models.Model)
if self.direct_editing:
return instance
return self.wrap_model(instance.__class__).create_wrapped_model_class()(self, instance)
def relevant_changed_objects(self) -> typing.Iterable[ChangedObject]:
@ -399,17 +408,24 @@ class ChangeSet(models.Model):
@contextmanager
def lock_to_edit(self, request=None):
with transaction.atomic():
user = request.user if request is not None and request.user.is_authenticated else None
if self.pk is not None:
changeset = ChangeSet.objects.select_for_update().get(pk=self.pk)
self._object_changed = False
yield changeset
user = request.user if request is not None and request.user.is_authenticated else None
if self._object_changed:
update = changeset.updates.create(user=user, objects_changed=True)
changeset.last_update = update
changeset.last_change = update
changeset.save()
elif self.direct_editing:
with MapUpdate.lock():
queries_before = len(connection.queries)
yield self
if any((q['sql'].startswith('UPDATE') or q['sql'].startswith('INSERT') or
q['sql'].startswith('DELETE')) for q in connection.queries[queries_before:]):
MapUpdate.objects.create(user=user, type='direct_edit')
else:
yield self
@ -433,6 +449,11 @@ class ChangeSet(models.Model):
# todo implement permissions
return self.is_author(request)
@classmethod
def can_direct_edit(self, request):
# todo implement permissions
return request.user.is_authenticated
def can_start_review(self, request):
return self.can_review(request) and self.state in ('proposed', 'reproposed')
@ -609,6 +630,8 @@ class ChangeSet(models.Model):
Get %d changed objects display text.
"""
if self.pk is None:
if self.direct_editing:
return _('Direct editing active')
return _('No objects changed')
return (ungettext_lazy('%(num)d object changed', '%(num)d objects changed', 'num') %
{'num': self.changed_objects_count})

View file

@ -1,7 +1,13 @@
{% load i18n %}
<ul class="nav navbar-nav navbar-right">
<li><a href="{{ request.changeset.get_absolute_url }}">{{ request.changeset.count_display }}</a></li>
<li><a href="{{ request.changeset.get_absolute_url }}">
{% if request.changeset.direct_editing %}
<span class="text-warning">{{ request.changeset.count_display }}</span>
{% else %}
{{ request.changeset.count_display }}
{% endif %}
</a></li>
{% if request.user.is_authenticated %}
<li class="logged_in_user">
<a href="{% url 'editor.users.detail' pk=request.user.pk %}">{{ request.user.username }}</a>

View file

@ -23,9 +23,26 @@
<button type="submit" class="btn btn-xs btn-default" name="deactivate_changeset" value="1">{% trans 'Deactivate change set' %}</button>
</form>
{% endwith %}
{% elif request.changeset.direct_editing %}
<p>
{% trans 'Direct editing is activated.' %}<br>
{% trans 'Everything you do will be applied immediately.' %}
</p>
<form method="post" action="{{ request.path }}">
{% csrf_token %}
<button type="submit" class="btn btn-xs btn-warning" name="direct_editing" value="0">{% trans 'Deactivate direct editing' %}</button>
</form>
{% else %}
{% trans 'You have currently no active change set.' %}<br>
{% trans 'Just edit something to create one.' %}
<p>
{% trans 'You have currently no active change set.' %}<br>
{% trans 'Just edit something to create one.' %}
</p>
{% if can_direct_edit %}
<form method="post" action="{{ request.path }}">
{% csrf_token %}
<button type="submit" class="btn btn-xs btn-warning" name="direct_editing" value="1">{% trans 'Activate direct editing' %}</button>
</form>
{% endif %}
{% endif %}
{% endif %}

View file

@ -14,13 +14,25 @@ def user_detail(request, pk):
user = get_object_or_404(User, pk=pk)
if request.method == 'POST':
if request.POST.get('deactivate_changeset') == '1' and request.user == user and 'changeset' in request.session:
request.session.pop('changeset', None)
messages.success(request, _('You deactivated your current changeset.'))
return redirect(request.path)
if request.user == user and 'changeset' in request.session:
if request.POST.get('deactivate_changeset') == '1':
request.session.pop('changeset', None)
messages.success(request, _('You deactivated your current changeset.'))
return redirect(request.path)
if request.changeset.pk is None and ChangeSet.can_direct_edit(request):
if request.POST.get('direct_editing') == '1':
request.session['direct_editing'] = True
messages.success(request, _('You activated direct editing.'))
return redirect(request.path)
elif request.POST.get('direct_editing') == '0':
request.session.pop('direct_editing', None)
messages.success(request, _('You deactivated direct editing.'))
return redirect(request.path)
ctx = {
'user': user,
'can_direct_edit': ChangeSet.can_direct_edit(request),
'recent_changesets': ChangeSet.objects.filter(author=user).order_by('-last_update')[:10],
}