direct editing
This commit is contained in:
parent
df19daf501
commit
1caa730fc4
4 changed files with 67 additions and 9 deletions
|
@ -9,7 +9,7 @@ from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import FieldDoesNotExist
|
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.db.models import Q
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.http import int_to_base36
|
from django.utils.http import int_to_base36
|
||||||
|
@ -69,6 +69,8 @@ class ChangeSet(models.Model):
|
||||||
self._request = None
|
self._request = None
|
||||||
self._original_state = self.state
|
self._original_state = self.state
|
||||||
|
|
||||||
|
self.direct_editing = False
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Get Changesets for Request/Session/User
|
Get Changesets for Request/Session/User
|
||||||
"""
|
"""
|
||||||
|
@ -111,6 +113,8 @@ class ChangeSet(models.Model):
|
||||||
|
|
||||||
changeset = ChangeSet()
|
changeset = ChangeSet()
|
||||||
changeset._request = request
|
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:
|
if request.user.is_authenticated:
|
||||||
changeset.author = request.user
|
changeset.author = request.user
|
||||||
|
@ -124,10 +128,15 @@ class ChangeSet(models.Model):
|
||||||
if isinstance(model, str):
|
if isinstance(model, str):
|
||||||
model = apps.get_model('mapdata', model)
|
model = apps.get_model('mapdata', model)
|
||||||
assert isinstance(model, type) and issubclass(model, models.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)
|
return ModelWrapper(self, model)
|
||||||
|
|
||||||
def wrap_instance(self, instance):
|
def wrap_instance(self, instance):
|
||||||
assert isinstance(instance, models.Model)
|
assert isinstance(instance, models.Model)
|
||||||
|
if self.direct_editing:
|
||||||
|
return instance
|
||||||
return self.wrap_model(instance.__class__).create_wrapped_model_class()(self, instance)
|
return self.wrap_model(instance.__class__).create_wrapped_model_class()(self, instance)
|
||||||
|
|
||||||
def relevant_changed_objects(self) -> typing.Iterable[ChangedObject]:
|
def relevant_changed_objects(self) -> typing.Iterable[ChangedObject]:
|
||||||
|
@ -399,17 +408,24 @@ class ChangeSet(models.Model):
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def lock_to_edit(self, request=None):
|
def lock_to_edit(self, request=None):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
user = request.user if request is not None and request.user.is_authenticated else None
|
||||||
if self.pk is not None:
|
if self.pk is not None:
|
||||||
changeset = ChangeSet.objects.select_for_update().get(pk=self.pk)
|
changeset = ChangeSet.objects.select_for_update().get(pk=self.pk)
|
||||||
|
|
||||||
self._object_changed = False
|
self._object_changed = False
|
||||||
yield changeset
|
yield changeset
|
||||||
user = request.user if request is not None and request.user.is_authenticated else None
|
|
||||||
if self._object_changed:
|
if self._object_changed:
|
||||||
update = changeset.updates.create(user=user, objects_changed=True)
|
update = changeset.updates.create(user=user, objects_changed=True)
|
||||||
changeset.last_update = update
|
changeset.last_update = update
|
||||||
changeset.last_change = update
|
changeset.last_change = update
|
||||||
changeset.save()
|
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:
|
else:
|
||||||
yield self
|
yield self
|
||||||
|
|
||||||
|
@ -433,6 +449,11 @@ class ChangeSet(models.Model):
|
||||||
# todo implement permissions
|
# todo implement permissions
|
||||||
return self.is_author(request)
|
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):
|
def can_start_review(self, request):
|
||||||
return self.can_review(request) and self.state in ('proposed', 'reproposed')
|
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.
|
Get “%d changed objects” display text.
|
||||||
"""
|
"""
|
||||||
if self.pk is None:
|
if self.pk is None:
|
||||||
|
if self.direct_editing:
|
||||||
|
return _('Direct editing active')
|
||||||
return _('No objects changed')
|
return _('No objects changed')
|
||||||
return (ungettext_lazy('%(num)d object changed', '%(num)d objects changed', 'num') %
|
return (ungettext_lazy('%(num)d object changed', '%(num)d objects changed', 'num') %
|
||||||
{'num': self.changed_objects_count})
|
{'num': self.changed_objects_count})
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<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 %}
|
{% if request.user.is_authenticated %}
|
||||||
<li class="logged_in_user">
|
<li class="logged_in_user">
|
||||||
<a href="{% url 'editor.users.detail' pk=request.user.pk %}">{{ request.user.username }}</a>
|
<a href="{% url 'editor.users.detail' pk=request.user.pk %}">{{ request.user.username }}</a>
|
||||||
|
|
|
@ -23,9 +23,26 @@
|
||||||
<button type="submit" class="btn btn-xs btn-default" name="deactivate_changeset" value="1">{% trans 'Deactivate change set' %}</button>
|
<button type="submit" class="btn btn-xs btn-default" name="deactivate_changeset" value="1">{% trans 'Deactivate change set' %}</button>
|
||||||
</form>
|
</form>
|
||||||
{% endwith %}
|
{% 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 %}
|
{% else %}
|
||||||
|
<p>
|
||||||
{% trans 'You have currently no active change set.' %}<br>
|
{% trans 'You have currently no active change set.' %}<br>
|
||||||
{% trans 'Just edit something to create one.' %}
|
{% 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 %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,25 @@ def user_detail(request, pk):
|
||||||
user = get_object_or_404(User, pk=pk)
|
user = get_object_or_404(User, pk=pk)
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
if request.POST.get('deactivate_changeset') == '1' and request.user == user and 'changeset' in request.session:
|
if request.user == user and 'changeset' in request.session:
|
||||||
|
if request.POST.get('deactivate_changeset') == '1':
|
||||||
request.session.pop('changeset', None)
|
request.session.pop('changeset', None)
|
||||||
messages.success(request, _('You deactivated your current changeset.'))
|
messages.success(request, _('You deactivated your current changeset.'))
|
||||||
return redirect(request.path)
|
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 = {
|
ctx = {
|
||||||
'user': user,
|
'user': user,
|
||||||
|
'can_direct_edit': ChangeSet.can_direct_edit(request),
|
||||||
'recent_changesets': ChangeSet.objects.filter(author=user).order_by('-last_update')[:10],
|
'recent_changesets': ChangeSet.objects.filter(author=user).order_by('-last_update')[:10],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue