issue submission forms

This commit is contained in:
Laura Klünder 2019-12-24 17:28:41 +01:00
parent e7fc0f24ae
commit 52c02a4101
18 changed files with 652 additions and 79 deletions

16
src/c3nav/site/forms.py Normal file
View file

@ -0,0 +1,16 @@
from django.forms import ModelForm
from c3nav.mapdata.forms import I18nModelFormMixin
from c3nav.mapdata.models.report import Report
class ReportIssueForm(I18nModelFormMixin, ModelForm):
class Meta:
model = Report
fields = ['title', 'description']
class ReportMissingLocationForm(I18nModelFormMixin, ModelForm):
class Meta:
model = Report
fields = ['title', 'description', 'created_title', 'created_groups']

View file

@ -547,6 +547,9 @@ main.show-options #resultswrapper #route-options {
padding: 5px 10px 5px 53px;
height: 55px;
}
.location.location-form-value {
margin: -10px -10px 5px -10px;
}
.location .icon {
font-size: 36px;
position: absolute;
@ -1256,6 +1259,25 @@ main .narrow p, main .narrow form, main .narrow button {
main .narrow form button {
width: 100%;
}
main form > p, #modal form > p {
margin-bottom: 15px;
> :last-child {
margin-bottom: 0;
}
.helptext {
display: block;
margin-top: -15px;
font-style: italic;
color: #999999;
}
textarea {
resize: none;
height: 100px;
}
select {
height: 100px;
}
}
.user-permissions-form label {
font-weight: 400;

View file

@ -14,7 +14,7 @@
<form method="post" action="{{ request.path_info }}?{{ request.META.QUERY_STRING }}">
{% csrf_token %}
{{ form }}
{{ form.as_p }}
<button type="submit">{{ title }}</button>
{% if bottom_link_url %}
<a href="{{ bottom_link_url }}?{{ request.META.QUERY_STRING }}">{{ bottom_link_text }}</a>

View file

@ -0,0 +1,5 @@
<div class="location{% if form_value %} location-form-value{% endif %}">
<i class="icon material-icons">{% if location.get_icon %}{{ location.get_icon }}{% else %}place{% endif %}</i>
<span>{{ location.title }}</span>
<small>{% if add_subtitle %}{{ add_subtitle }}, {% endif %}{{ location.subtitle }}</small>
</div>

View file

@ -0,0 +1,22 @@
{% load i18n %}
{% if report.category == 'location-issue' %}
<p><strong>{% trans 'You are reporting an issue with the following location:' %}</strong></p>
{% include 'site/fragment_location.html' with form_value=1 location=report.location %}
{% elif report.category == 'missing-location' %}
<p><strong>{% trans 'You are reporting an missing location at the following position:' %}</strong></p>
{% include 'site/fragment_location.html' with form_value=1 location=report.coordinates add_subtitle=report.coordinates_id %}
{% elif report.category == 'route-issue' %}
<p><strong>{% trans 'You are reporting an issue with the following route:' %}</strong></p>
<label>{% trans 'Origin' %}:</label>
{% include 'site/fragment_location.html' with form_value=1 location=report.origin %}
<label>{% trans 'Destination' %}:</label>
{% include 'site/fragment_location.html' with form_value=1 location=report.destination %}
<label>{% trans 'Route options' %}:</label>
{% for option in options.serialize %}
{{ option.label }}: {{ option.value_display }}<br>
{% endfor %}
</p>
{% endif %}

View file

@ -1,10 +0,0 @@
{% extends 'site/base.html' %}
{% load i18n %}
{% block content %}
<main class="account">
<h2>{% trans 'Coming soon' %}</h2>
{% include 'site/fragment_messages.html' %}
</main>
{% endblock %}

View file

@ -0,0 +1,16 @@
{% extends 'site/base.html' %}
{% load i18n %}
{% block content %}
<main class="account">
<h2>{% trans 'Report issue' %}</h2>
{% include 'site/fragment_messages.html' %}
<form method="post" action="{{ request.path_info }}?{{ request.META.QUERY_STRING }}">
{% csrf_token %}
{% include 'site/fragment_report_meta.html' %}
{{ form.as_p }}
<button type="submit">{% trans 'Submit' %}</button>
</form>
</main>
{% endblock %}

View file

@ -0,0 +1,44 @@
{% extends 'site/base.html' %}
{% load i18n %}
{% block content %}
<main class="account">
<h2>{% trans 'Report' %}: {{ report.title }}</h2>
<p><em>
{% if report.open %}
<strong class="green">{% trans 'open' %}</strong>
{% else %}
<strong class="red">{% trans 'closed' %}</strong>
{% endif %}
{% if report.author %}
{% trans 'anonymous submission' %}
{% else %}
{% trans 'by' %} {{ request.author.username }}
{% endif %}
{{ report.created }}
</em></p>
{% include 'site/fragment_messages.html' %}
{% include 'site/fragment_report_meta.html' %}
{% for field in form %}
{% if field.name != 'title' %}
<p>
<strong>{{ field.label }}:</strong><br>
{% if field.name == 'description' %}
{{ report.description | linebreaksbr }}
{% elif field.name == 'created_groups' %}
{% for group in report.created_groups.all %}
{{ group.title }}<br>
{% empty %}
<em>{% trans '(none)' %}</em>
{% endfor %}
{% else %}
{{ field.value }}
{% endif %}
</p>
{% endif %}
{% endfor %}
</main>
{% endblock %}

View file

@ -1,7 +1,7 @@
from django.conf.urls import url
from c3nav.site.views import (about_view, access_redeem_view, account_view, change_password_view, choose_language,
login_view, logout_view, map_index, qr_code, register_view, report_view)
login_view, logout_view, map_index, qr_code, register_view, report_create, report_detail)
slug = r'(?P<slug>[a-z0-9-_.:]+)'
coordinates = r'(?P<coordinates>[a-z0-9-_:]+:-?\d+(\.\d+)?:-?\d+(\.\d+)?)'
@ -27,7 +27,10 @@ urlpatterns = [
url(r'^lang/$', choose_language, name='site.language'),
url(r'^about/$', about_view, name='site.about'),
url(r'^report/$', about_view, name='site.about'),
url(r'^report/l/%s/$' % coordinates, report_view, name='site.report'),
url(r'^report/l/(?P<location>\d+)/$', report_view, name='site.report'),
url(r'^report/r/(?P<origin>[^/]+)/(?P<destination>[^/]+)/(?P<options>[^/]+)/$', report_view, name='site.report'),
url(r'^report/(?P<pk>\d+)/$', report_detail, name='site.report_detail'),
url(r'^report/(?P<pk>\d+)/(?P<secret>[^/]+)/$', report_detail, name='site.report_detail'),
url(r'^report/l/%s/$' % coordinates, report_create, name='site.report_create'),
url(r'^report/l/(?P<location>\d+)/$', report_create, name='site.report_create'),
url(r'^report/r/(?P<origin>[^/]+)/(?P<destination>[^/]+)/(?P<options>[^/]+)/$',
report_create, name='site.report_create'),
]

View file

@ -9,11 +9,12 @@ from django.contrib.auth import login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm, UserCreationForm
from django.contrib.auth.views import redirect_to_login
from django.core.exceptions import ObjectDoesNotExist, SuspiciousOperation
from django.core.serializers.json import DjangoJSONEncoder
from django.db import transaction
from django.http import HttpResponse, HttpResponseBadRequest
from django.http import Http404, HttpResponse, HttpResponseBadRequest
from django.middleware import csrf
from django.shortcuts import redirect, render
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
@ -27,9 +28,12 @@ from c3nav.mapdata.grid import grid
from c3nav.mapdata.models import Location, Source
from c3nav.mapdata.models.access import AccessPermissionToken
from c3nav.mapdata.models.locations import LocationRedirect, SpecificLocation
from c3nav.mapdata.utils.locations import get_location_by_slug_for_request, levels_by_short_label_for_request
from c3nav.mapdata.models.report import Report
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request,
levels_by_short_label_for_request)
from c3nav.mapdata.utils.user import can_access_editor, get_user_data
from c3nav.mapdata.views import set_tile_access_cookie
from c3nav.routing.models import RouteOptions
from c3nav.site.models import Announcement, SiteUpdate
@ -350,6 +354,86 @@ def about_view(request):
})
def get_report_location_for_request(pk, request):
location = get_location_by_id_for_request(pk, request)
if location is None:
raise Http404
return location
@never_cache
def report_view(request, coordinates=None, location=None, origin=None, destination=None, options=None):
return render(request, 'site/report.html', {})
def report_create(request, coordinates=None, location=None, origin=None, destination=None, options=None):
report = Report()
report.request = request
if coordinates:
report.category = 'missing-location'
report.coordinates_id = coordinates
try:
report.coordinates
except ObjectDoesNotExist:
raise Http404
elif location:
report.category = 'location-issue'
report.location = get_report_location_for_request(location, request)
if report.location is None:
raise Http404
report.location = location
elif origin:
report.category = 'route-issue'
report.origin_id = origin
report.destination_id = destination
try:
# noinspection PyStatementEffect
report.origin
# noinspection PyStatementEffect
report.destination
except ObjectDoesNotExist:
raise Http404
try:
options = RouteOptions.unserialize_string(options)
except Exception:
raise SuspiciousOperation
report.options = options.serialize_string()
if request.method == 'POST':
form = report.form_cls(instance=report, data=request.POST)
if form.is_valid():
report = form.instance
if request.user.is_authenticated:
report.author = request.user
report.save()
success_messages = [_('Your report was submitted.')]
success_kwargs = {'pk': report.pk}
if request.user.is_authenticated:
success_messages.append(_('You can keep track of it from your user dashboard.'))
else:
success_messages.append(_('You can keep track of it by revisiting the public URL mentioned below.'))
success_kwargs = {'secret': report.secret}
messages.success(request, ' '.join(str(s) for s in success_messages))
return redirect(reverse('site.report_detail', kwargs=success_kwargs))
else:
form = report.form_cls(instance=report)
return render(request, 'site/report_create.html', {
'report': report,
'options': options,
'form': form,
})
def report_detail(request, pk, secret=None):
if secret:
qs = Report.objects.filter(secret=secret)
else:
qs = Report.qs_for_request(request)
report = get_object_or_404(qs, pk=pk)
report.request = request
form = report.form_cls(instance=report)
return render(request, 'site/report_detail.html', {
'report': report,
'form': form,
})