quests can now be done!
This commit is contained in:
parent
df777ecc05
commit
d811170716
14 changed files with 219 additions and 63 deletions
20
src/c3nav/editor/templates/editor/quest_form.html
Normal file
20
src/c3nav/editor/templates/editor/quest_form.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
{% extends 'site/base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<main class="account">
|
||||
<h3>{{ title }}</h3>
|
||||
|
||||
{% if back_url %}
|
||||
<p>
|
||||
<a href="{{ back_url }}">« {% trans 'back' %}</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{{ request.path_info }}">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<button type="submit">{% trans 'Submit answer' %}</button>
|
||||
</form>
|
||||
</main>
|
||||
{% endblock %}
|
10
src/c3nav/editor/templates/editor/thanks.html
Normal file
10
src/c3nav/editor/templates/editor/thanks.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% extends 'site/base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<main class="account">
|
||||
<h3>{% trans 'Thank you!' %}</h3>
|
||||
|
||||
<p>{% trans 'Have a cookie <3 🍪' %}</p>
|
||||
</main>
|
||||
{% endblock %}
|
|
@ -1,10 +1,12 @@
|
|||
from django.apps import apps
|
||||
from django.urls import path
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from c3nav.editor.views.account import change_password_view, login_view, logout_view, register_view
|
||||
from c3nav.editor.views.changes import changeset_detail, changeset_edit, changeset_redirect
|
||||
from c3nav.editor.views.edit import edit, graph_edit, level_detail, list_objects, main_index, sourceimage, space_detail
|
||||
from c3nav.editor.views.overlays import overlays_list, overlay_features, overlay_feature_edit
|
||||
from c3nav.editor.views.quest import QuestFormView
|
||||
from c3nav.editor.views.users import user_detail, user_redirect
|
||||
|
||||
|
||||
|
@ -55,6 +57,8 @@ urlpatterns = [
|
|||
path('logout', logout_view, name='editor.logout'),
|
||||
path('register', register_view, name='editor.register'),
|
||||
path('change_password', change_password_view, name='editor.change_password'),
|
||||
path('quests/<str:quest_type>/<str:identifier>/', QuestFormView.as_view(), name='editor.quest'),
|
||||
path('thanks/', TemplateView.as_view(template_name="editor/thanks.html"), name='editor.thanks'),
|
||||
path('', main_index, name='editor.index'),
|
||||
]
|
||||
urlpatterns.extend(add_editor_urls('Level', with_list=False, explicit_edit=True))
|
||||
|
|
|
@ -26,14 +26,35 @@ from c3nav.mapdata.utils.user import can_access_editor
|
|||
|
||||
|
||||
@contextmanager
|
||||
def maybe_lock_changeset_to_edit(request):
|
||||
def maybe_lock_changeset_to_edit(changeset):
|
||||
""" Lock the changeset of the given request, if it can be locked (= has ever been saved to the database)"""
|
||||
if request.changeset.pk:
|
||||
with request.changeset.lock_to_edit(request=request) as changeset:
|
||||
request.changeset = changeset
|
||||
yield
|
||||
if changeset.pk:
|
||||
with changeset.lock_to_edit() as locked_changeset:
|
||||
yield locked_changeset
|
||||
else:
|
||||
yield
|
||||
yield changeset
|
||||
|
||||
|
||||
@contextmanager
|
||||
def within_changeset(changeset, user):
|
||||
with maybe_lock_changeset_to_edit(changeset=changeset) as locked_changeset:
|
||||
# Turn the changes from the changeset into a list of operations
|
||||
operations = locked_changeset.as_operations
|
||||
|
||||
# Enable the overlay manager, temporarily applying the changeset changes
|
||||
# commit is set to false, meaning all changes will be reset once we leave the manager
|
||||
with DatabaseOverlayManager.enable(operations=operations, commit=False) as manager:
|
||||
yield locked_changeset
|
||||
if manager.operations:
|
||||
# Add new operations to changeset
|
||||
locked_changeset.changes.add_operations(manager.operations)
|
||||
locked_changeset.save()
|
||||
|
||||
# Add new changeset update
|
||||
update = locked_changeset.updates.create(user=user, objects_changed=True)
|
||||
locked_changeset.last_update = update
|
||||
locked_changeset.last_change = update
|
||||
locked_changeset.save()
|
||||
|
||||
|
||||
@contextmanager
|
||||
|
@ -71,24 +92,9 @@ def accesses_mapdata(func):
|
|||
raise ValueError # todo: good error message, but this shouldn't happen
|
||||
else:
|
||||
# For non-direct editing, we will interact with the changeset
|
||||
with maybe_lock_changeset_to_edit(request=request):
|
||||
# Turn the changes from the changeset into a list of operations
|
||||
operations = request.changeset.as_operations
|
||||
|
||||
# Enable the overlay manager, temporarily applying the changeset changes
|
||||
# commit is set to false, meaning all changes will be reset once we leave the manager
|
||||
with DatabaseOverlayManager.enable(operations=operations, commit=False) as manager:
|
||||
result = func(request, *args, **kwargs)
|
||||
if manager.operations:
|
||||
# Add new operations to changeset
|
||||
request.changeset.changes.add_operations(manager.operations)
|
||||
request.changeset.save()
|
||||
|
||||
# Add new changeset update
|
||||
update = request.changeset.updates.create(user=request.user, objects_changed=True)
|
||||
request.changeset.last_update = update
|
||||
request.changeset.last_change = update
|
||||
request.changeset.save()
|
||||
with within_changeset(changeset=request.changeset, user=request.user) as locked_changeset:
|
||||
request.changeset = locked_changeset
|
||||
return func(request, *args, **kwargs)
|
||||
return result
|
||||
|
||||
return wrapped
|
||||
|
|
|
@ -62,7 +62,7 @@ def changeset_detail(request, pk):
|
|||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
||||
elif request.POST.get('activate') == '1':
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if changeset.can_activate(request):
|
||||
changeset.activate(request)
|
||||
messages.success(request, _('You activated this change set.'))
|
||||
|
@ -76,7 +76,7 @@ def changeset_detail(request, pk):
|
|||
messages.info(request, _('You need to log in to propose changes.'))
|
||||
return redirect(reverse('editor.login') + '?r=' + request.path)
|
||||
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if not changeset.title:
|
||||
form = ChangeSetForm(instance=changeset, data=request.POST)
|
||||
if not form.is_valid():
|
||||
|
@ -108,7 +108,7 @@ def changeset_detail(request, pk):
|
|||
messages.info(request, _('You need to log in to apply changes.'))
|
||||
return redirect(reverse('editor.login') + '?r=' + request.path)
|
||||
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if not changeset.title:
|
||||
form = ChangeSetForm(instance=changeset, data=request.POST)
|
||||
if not form.is_valid():
|
||||
|
@ -136,7 +136,7 @@ def changeset_detail(request, pk):
|
|||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
||||
elif request.POST.get('unpropose') == '1':
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if changeset.can_unpropose(request):
|
||||
changeset.unpropose(request.user)
|
||||
messages.success(request, _('You unproposed your changes.'))
|
||||
|
@ -146,7 +146,7 @@ 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(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if changeset.can_start_review(request):
|
||||
changeset.start_review(request.user)
|
||||
messages.success(request, _('You are now reviewing these changes.'))
|
||||
|
@ -156,7 +156,7 @@ def changeset_detail(request, pk):
|
|||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
||||
elif request.POST.get('reject') == '1':
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
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}))
|
||||
|
@ -176,7 +176,7 @@ def changeset_detail(request, pk):
|
|||
})
|
||||
|
||||
elif request.POST.get('unreject') == '1':
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if not changeset.can_unreject(request):
|
||||
messages.error(request, _('You cannot unreject these changes.'))
|
||||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
@ -187,7 +187,7 @@ def changeset_detail(request, pk):
|
|||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
||||
elif request.POST.get('apply') == '1':
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if not changeset.can_end_review(request):
|
||||
messages.error(request, _('You cannot accept and apply these changes.'))
|
||||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
@ -204,7 +204,7 @@ def changeset_detail(request, pk):
|
|||
return render(request, 'editor/changeset_apply.html', {})
|
||||
|
||||
elif request.POST.get('delete') == '1':
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if not changeset.can_delete(request):
|
||||
messages.error(request, _('You cannot delete this change set.'))
|
||||
|
||||
|
@ -502,7 +502,7 @@ def changeset_edit(request, pk):
|
|||
if str(pk) != str(request.changeset.pk):
|
||||
changeset = get_object_or_404(ChangeSet.qs_for_request(request), pk=pk)
|
||||
|
||||
with changeset.lock_to_edit(request) as changeset:
|
||||
with changeset.lock_to_edit() as changeset:
|
||||
if not changeset.can_edit(request):
|
||||
messages.error(request, _('You cannot edit this change set.'))
|
||||
return redirect(reverse('editor.changesets.detail', kwargs={'pk': changeset.pk}))
|
||||
|
|
|
@ -179,7 +179,7 @@ def overlay_feature_edit(request, level=None, overlay=None, pk=None):
|
|||
if not new and ((request.POST.get('delete') == '1' and delete is not False) or delete):
|
||||
# Delete this mapitem!
|
||||
if request.POST.get('delete_confirm') == '1' or delete:
|
||||
with request.changeset.lock_to_edit(request) as changeset:
|
||||
with request.changeset.lock_to_edit() as changeset:
|
||||
if changeset.can_edit(request):
|
||||
obj.delete()
|
||||
else:
|
||||
|
@ -210,7 +210,7 @@ def overlay_feature_edit(request, level=None, overlay=None, pk=None):
|
|||
obj.level = level
|
||||
obj.overlay = overlay
|
||||
|
||||
with request.changeset.lock_to_edit(request) as changeset:
|
||||
with request.changeset.lock_to_edit() as changeset:
|
||||
if changeset.can_edit(request):
|
||||
try:
|
||||
obj.save()
|
||||
|
|
41
src/c3nav/editor/views/quest.py
Normal file
41
src/c3nav/editor/views/quest.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
from functools import cached_property
|
||||
|
||||
from django.http import Http404
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic.edit import FormView
|
||||
|
||||
from c3nav.mapdata.quests.base import get_quest_for_request
|
||||
|
||||
|
||||
class QuestFormView(FormView):
|
||||
template_name = "editor/quest_form.html"
|
||||
success_url = reverse_lazy("editor.thanks")
|
||||
|
||||
@cached_property
|
||||
def quest(self):
|
||||
quest = get_quest_for_request(request=self.request,
|
||||
quest_type=self.kwargs["quest_type"],
|
||||
identifier=self.kwargs["identifier"])
|
||||
if quest is None:
|
||||
raise Http404
|
||||
return quest
|
||||
|
||||
def get_form_class(self):
|
||||
return self.quest.get_form_class()
|
||||
|
||||
def get_form_kwargs(self):
|
||||
return {
|
||||
"request": self.request,
|
||||
**super().get_form_kwargs(),
|
||||
**self.quest.get_form_kwargs(request=self.request),
|
||||
}
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
return {
|
||||
**super().get_context_data(**kwargs),
|
||||
"title": self.quest.quest_type_label,
|
||||
}
|
||||
|
||||
def form_valid(self, form):
|
||||
form.save()
|
||||
return super().form_valid(form)
|
Loading…
Add table
Add a link
Reference in a new issue