overhaul entire report process
This commit is contained in:
parent
482da3b244
commit
0d91a71b9f
12 changed files with 206 additions and 45 deletions
|
@ -29,7 +29,7 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='locationgroup',
|
||||
name='description',
|
||||
field=c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, help_text='to aid with selection in the report form', plural_name='descriptions', verbose_name='description'),
|
||||
field=c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, fallback_value="", help_text='to aid with selection in the report form', plural_name='descriptions', verbose_name='description'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='locationgroup',
|
||||
|
@ -39,7 +39,7 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='locationgroup',
|
||||
name='report_help_text',
|
||||
field=c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, help_text='to explain the report form or rejection', plural_name='report_help_texts', verbose_name='report help text'),
|
||||
field=c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, fallback_value="", help_text='to explain the report form or rejection', plural_name='report_help_texts', verbose_name='report help text'),
|
||||
),
|
||||
migrations.RunPython(forwards_func, backwards_func),
|
||||
migrations.RemoveField(
|
||||
|
|
|
@ -368,9 +368,9 @@ class LocationGroup(Location, models.Model):
|
|||
default=CanReportMissing.DONT_OFFER, max_length=16)
|
||||
|
||||
description = I18nField(_('description'), plural_name='descriptions', blank=True, fallback_any=True,
|
||||
help_text=_('to aid with selection in the report form'))
|
||||
fallback_value="", help_text=_('to aid with selection in the report form'))
|
||||
report_help_text = I18nField(_('report help text'), plural_name='report_help_texts', blank=True, fallback_any=True,
|
||||
help_text=_('to explain the report form or rejection'))
|
||||
fallback_value="", help_text=_('to explain the report form or rejection'))
|
||||
|
||||
color = models.CharField(null=True, blank=True, max_length=32, verbose_name=_('background color'))
|
||||
hub_import_type = models.CharField(max_length=100, verbose_name=_('hub import type'), null=True, blank=True,
|
||||
|
|
|
@ -242,7 +242,7 @@ def get_route(request, parameters: RouteParametersSchema):
|
|||
request=parameters,
|
||||
options=_new_serialize_route_options(options),
|
||||
options_form=options.serialize(),
|
||||
report_issue_url=reverse('site.report_create', kwargs={
|
||||
report_issue_url=reverse('site.report_start', kwargs={
|
||||
'origin': parameters.origin,
|
||||
'destination': parameters.destination,
|
||||
'options': options.serialize_string(),
|
||||
|
|
|
@ -11,7 +11,7 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
from c3nav.api.models import Secret
|
||||
from c3nav.mapdata.forms import I18nModelFormMixin
|
||||
from c3nav.mapdata.models.locations import Position
|
||||
from c3nav.mapdata.models.locations import Position, LocationGroup
|
||||
from c3nav.mapdata.models.report import Report, ReportUpdate
|
||||
|
||||
|
||||
|
@ -26,8 +26,22 @@ class DeleteAccountForm(Form):
|
|||
|
||||
|
||||
class ReportMissingLocationForm(I18nModelFormMixin, ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
def __init__(self, *args, group=None, request=None, **kwargs):
|
||||
super().__init__(*args, initial={"created_groups": [group] if group else []}, **kwargs)
|
||||
if group:
|
||||
self.fields['created_groups'].disabled = True
|
||||
self.fields['created_groups'].queryset = LocationGroup.objects.filter(pk=group.pk)
|
||||
else:
|
||||
exists = LocationGroup.qs_for_request(request).filter(
|
||||
can_report_missing=LocationGroup.CanReportMissing.MULTIPLE
|
||||
).exists()
|
||||
if exists:
|
||||
self.fields['created_groups'].queryset = LocationGroup.qs_for_request(request).filter(
|
||||
can_report_missing=LocationGroup.CanReportMissing.MULTIPLE
|
||||
)
|
||||
else:
|
||||
self.fields['created_groups'].queryset = LocationGroup.objects.none()
|
||||
self.fields['created_groups'].widget = self.fields['created_groups'].hidden_widget()
|
||||
self.fields['created_groups'].label_from_instance = lambda obj: obj.title
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -152,7 +152,7 @@ main.map {
|
|||
main.account form {
|
||||
max-width: 400px;
|
||||
}
|
||||
#modal-content form button[type=submit] {
|
||||
#modal-content form button[type=submit], #modal-content .answers .button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -551,6 +551,14 @@ main.show-options #resultswrapper #route-options {
|
|||
.location.location-form-value {
|
||||
margin: -10px -10px 5px -10px;
|
||||
}
|
||||
.location-answers .location.location-form-value, .location-answers a {
|
||||
margin-bottom: 5px;
|
||||
color: $color-secondary;
|
||||
display: block;
|
||||
}
|
||||
.location-answers {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.location .icon {
|
||||
font-size: 36px;
|
||||
position: absolute;
|
||||
|
|
|
@ -496,8 +496,6 @@ c3nav = {
|
|||
var custom_location = typeof data.id !== 'number',
|
||||
report_url = '/report/l/'+String(data.id)+'/';
|
||||
$location_details.find('.report').attr('href', report_url);
|
||||
$location_details.find('.report-issue').toggle(!custom_location);
|
||||
$location_details.find('.report-missing').toggle(custom_location);
|
||||
} else {
|
||||
$location_details.find('.report').hide();
|
||||
}
|
||||
|
@ -1538,7 +1536,6 @@ c3nav = {
|
|||
maxWidth: 500
|
||||
}, 'autoPanPaddingTopLeft', 'autoPanPaddingBottomRight'));
|
||||
var buttons = $('#location-popup-buttons').clone();
|
||||
buttons.find('.report-issue').remove();
|
||||
buttons.find('.report').attr('href', '/report/l/' + String(data.id) + '/');
|
||||
newpopup.setLatLng(latlng).setContent(c3nav._build_location_html(data) + buttons.html());
|
||||
c3nav._click_anywhere_popup = newpopup;
|
||||
|
@ -1698,11 +1695,6 @@ c3nav = {
|
|||
let buttons_html = '';
|
||||
if (!c3nav.embed) {
|
||||
let buttons = $('#location-popup-buttons').clone();
|
||||
if (typeof location.id == 'number') {
|
||||
buttons.find('.report-missing').remove();
|
||||
} else {
|
||||
buttons.find('.report-issue').remove();
|
||||
}
|
||||
buttons.find('.report').attr('href', '/report/l/'+String(location.id)+'/');
|
||||
buttons_html = buttons.html();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="location{% if form_value %} location-form-value{% endif %}">
|
||||
<i class="icon material-symbols">{% 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>
|
||||
<small>{% if replace_subtitle %}{{ replace_subtitle }}{% else %}{% if add_subtitle %}{{ add_subtitle }}, {% endif %}{{ location.subtitle }}{% endif %}</small>
|
||||
</div>
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
<div class="buttons">
|
||||
<a class="button button-clear report report-missing">
|
||||
<i class="material-symbols">feedback</i>
|
||||
{% trans 'Report missing location' %}
|
||||
{% trans 'Report issue' %}
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -110,7 +110,7 @@
|
|||
</a>
|
||||
<a class="button button-clear report report-missing">
|
||||
<i class="material-symbols">feedback</i>
|
||||
{% trans 'Report missing location' %}
|
||||
{% trans 'Report issue' %}
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -206,10 +206,6 @@
|
|||
<i class="material-symbols">feedback</i>
|
||||
{% trans 'Report issue' %}
|
||||
</a>
|
||||
<a class="button button-clear report report-missing">
|
||||
<i class="material-symbols">feedback</i>
|
||||
{% trans 'Report missing location' %}
|
||||
</a>
|
||||
<a class="button button-clear editor" target="_blank">
|
||||
<i class="material-symbols">edit</i>
|
||||
{% trans 'Open in Editor' %}
|
||||
|
|
|
@ -5,23 +5,15 @@
|
|||
<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' %}
|
||||
{% if help_text %}
|
||||
<ul class="messages">
|
||||
<li class="alert-info">{{ help_text }}</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{{ form.as_p }}
|
||||
<p>
|
||||
<input type="checkbox" required="required" style="margin-bottom: 0" />
|
||||
<blink>
|
||||
<strong>
|
||||
{% blocktrans trimmed %}
|
||||
I understand that if I report an issue related to an assembly,
|
||||
all that will happen is that I owe each member on the c3nav team one bottle of mate.
|
||||
I can avoid this by contacting the assembly team, which will actually be able to fix my issue.
|
||||
{% endblocktrans %}
|
||||
</strong>
|
||||
</blink>
|
||||
</p>
|
||||
<button type="submit">{% trans 'Submit' %}</button>
|
||||
</form>
|
||||
</main>
|
||||
|
|
29
src/c3nav/site/templates/site/report_question.html
Normal file
29
src/c3nav/site/templates/site/report_question.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
{% extends 'site/base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<main class="account">
|
||||
<h2>{% trans 'Report issue' %}</h2>
|
||||
{% include 'site/fragment_messages.html' %}
|
||||
{% include 'site/fragment_report_meta.html' %}
|
||||
<p>{{ question }}</p>
|
||||
{% if locations %}
|
||||
<div class="location-answers">
|
||||
{% for location in locations %}
|
||||
{% if location.url %}
|
||||
<a href="{{ location.url }}">
|
||||
{% endif %}
|
||||
{% include 'site/fragment_location.html' with form_value=1 location=location.location replace_subtitle=location.replace_subtitle %}
|
||||
{% if location.url %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="answers">
|
||||
{% for answer in answers %}
|
||||
<p><a class="button" href="{{ answer.url }}">{{ answer.text }}</a></p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
|
@ -6,7 +6,9 @@ from c3nav.site.converters import AtPositionConverter, CoordinatesConverter, IsE
|
|||
from c3nav.site.views import (about_view, access_redeem_view, account_manage, account_view, api_secret_create,
|
||||
api_secret_list, change_password_view, choose_language, delete_account_view, login_view,
|
||||
logout_view, map_index, position_create, position_detail, position_list, position_set,
|
||||
qr_code, register_view, report_create, report_detail, report_list)
|
||||
qr_code, register_view, report_create, report_detail, report_list,
|
||||
report_start_coordinates, report_start_location, report_start_route, report_missing_check,
|
||||
report_select_location, report_missing_choose)
|
||||
|
||||
register_converter(CoordinatesConverter, 'coords')
|
||||
register_converter(AtPositionConverter, 'at_pos')
|
||||
|
@ -52,9 +54,16 @@ urlpatterns = [
|
|||
path('reports/all/', report_list, {'filter': 'all'}, name='site.report_list'),
|
||||
path('reports/<int:pk>/', report_detail, name='site.report_detail'),
|
||||
path('reports/<int:pk>/<str:secret>/', report_detail, name='site.report_detail'),
|
||||
path('report/l/<coords:coordinates>/', report_create, name='site.report_create'),
|
||||
path('report/l/<int:location>/', report_create, name='site.report_create'),
|
||||
path('report/r/<str:origin>/<str:destination>/<str:options>/', report_create, name='site.report_create'),
|
||||
path('report/l/<coords:coordinates>/', report_start_coordinates, name='site.report_start'),
|
||||
path('report/l/<coords:coordinates>/missing/', report_missing_check, name='site.report_missing_check'),
|
||||
path('report/l/<coords:coordinates>/existing/', report_select_location, name='site.report_select_location'),
|
||||
path('report/l/<coords:coordinates>/choose/', report_missing_choose, name='site.report_missing_choose'),
|
||||
path('report/l/<int:location>/', report_start_location, name='site.report_start'),
|
||||
path('report/r/<str:origin>/<str:destination>/<str:options>/', report_start_route, name='site.report_start'),
|
||||
path('report/create/l/<coords:coordinates>/', report_create, name='site.report_create'),
|
||||
path('report/create/l/<coords:coordinates>/<str:group>/', report_create, name='site.report_create'),
|
||||
path('report/create/l/<int:location>/', report_create, name='site.report_create'),
|
||||
path('report/create/r/<str:origin>/<str:destination>/<str:options>/', report_create, name='site.report_create'),
|
||||
path('positions/', position_list, name='site.position_list'),
|
||||
path('positions/create/', position_create, name='site.position_create'),
|
||||
path('positions/<int:pk>/', position_detail, name='site.position_detail'),
|
||||
|
|
|
@ -30,7 +30,8 @@ from c3nav.api.models import Secret
|
|||
from c3nav.mapdata.grid import grid
|
||||
from c3nav.mapdata.models import Location, Source
|
||||
from c3nav.mapdata.models.access import AccessPermission, AccessPermissionToken
|
||||
from c3nav.mapdata.models.locations import LocationRedirect, Position, SpecificLocation, get_position_secret
|
||||
from c3nav.mapdata.models.locations import LocationRedirect, Position, SpecificLocation, get_position_secret, \
|
||||
LocationGroup
|
||||
from c3nav.mapdata.models.report import Report, ReportUpdate
|
||||
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request,
|
||||
levels_by_short_label_for_request)
|
||||
|
@ -453,15 +454,134 @@ def get_report_location_for_request(pk, request):
|
|||
return location
|
||||
|
||||
|
||||
@never_cache
|
||||
def report_start_coordinates(request, coordinates):
|
||||
return render(request, 'site/report_question.html', {
|
||||
'question': _('What\'s wrong here?'),
|
||||
'answers': [
|
||||
{
|
||||
'url': reverse('site.report_missing_check', kwargs={'coordinates': coordinates}),
|
||||
'text': _('A location is missing'),
|
||||
},
|
||||
{
|
||||
'url': reverse('site.report_select_location', kwargs={'coordinates': coordinates}),
|
||||
'text': _('A location is there, but wrong'),
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@never_cache
|
||||
def report_missing_check(request, coordinates):
|
||||
nearby = get_location_by_id_for_request(coordinates, request).nearby
|
||||
if not nearby:
|
||||
return redirect(reverse('site.report_missing_choose', kwargs={"coordinates": coordinates}))
|
||||
return render(request, 'site/report_question.html', {
|
||||
'question': _('Are you sure it\'s not one of these?'),
|
||||
'locations': [
|
||||
{
|
||||
'location': get_location_by_id_for_request(location.id, request), # todo: correct subtitle w/o this
|
||||
}
|
||||
for location in nearby
|
||||
],
|
||||
'answers': [
|
||||
{
|
||||
'url': reverse('site.report_missing_choose', kwargs={"coordinates": coordinates}),
|
||||
'text': _('Yeah, it\'s not in there'),
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@never_cache
|
||||
def report_select_location(request, coordinates):
|
||||
location = get_location_by_id_for_request(coordinates, request)
|
||||
nearby = list(location.nearby)
|
||||
if location.space:
|
||||
nearby.append(location.space)
|
||||
if not nearby:
|
||||
messages.error(request, _('There are no locations nearby.'))
|
||||
return render(request, 'site/report_question.html', {})
|
||||
return render(request, 'site/report_question.html', {
|
||||
'question': _('Which one is it?'),
|
||||
'locations': [
|
||||
{
|
||||
'url': reverse('site.report_create', kwargs={"location": location.id}),
|
||||
'location': get_location_by_id_for_request(location.id, request), # todo: correct subtitle w/o this
|
||||
}
|
||||
for location in nearby
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
@never_cache
|
||||
def report_missing_choose(request, coordinates):
|
||||
groups = LocationGroup.qs_for_request(request).filter(can_report_missing__in=(
|
||||
LocationGroup.CanReportMissing.SINGLE,
|
||||
LocationGroup.CanReportMissing.REJECT,
|
||||
))
|
||||
if not groups.exists():
|
||||
return redirect(reverse('site.report_create', kwargs={"coordinates": coordinates}))
|
||||
return render(request, 'site/report_question.html', {
|
||||
'question': _('Does one of these describe your missing location?'),
|
||||
'locations': [
|
||||
{
|
||||
"url": reverse('site.report_create',
|
||||
kwargs={"coordinates": coordinates, "group": group.get_slug()}),
|
||||
"location": group,
|
||||
"replace_subtitle": group.description
|
||||
}
|
||||
for group in groups
|
||||
],
|
||||
'answers': [
|
||||
{
|
||||
'url': reverse('site.report_create', kwargs={"coordinates": coordinates}),
|
||||
'text': _('None of these fit'),
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@never_cache
|
||||
def report_start_location(request, location):
|
||||
return redirect(reverse('site.report_create',
|
||||
kwargs={"location": location}))
|
||||
|
||||
|
||||
@never_cache
|
||||
def report_start_route(request, origin, destination, options):
|
||||
return redirect(reverse('site.report_create',
|
||||
kwargs={"origin": origin, "destination": destination, "options": options}))
|
||||
|
||||
|
||||
@never_cache
|
||||
@login_required(login_url='site.login')
|
||||
def report_create(request, coordinates=None, location=None, origin=None, destination=None, options=None):
|
||||
def report_create(request, coordinates=None, location=None, origin=None, destination=None, options=None, group=None):
|
||||
report = Report()
|
||||
report.request = request
|
||||
|
||||
form_kwargs = {}
|
||||
help_text = None
|
||||
|
||||
if coordinates:
|
||||
report.category = 'missing-location'
|
||||
report.coordinates_id = coordinates
|
||||
form_kwargs["request"] = request
|
||||
if group:
|
||||
group = get_location_by_slug_for_request(group, request)
|
||||
if not isinstance(group, LocationGroup):
|
||||
raise Http404
|
||||
if group.can_report_missing == LocationGroup.CanReportMissing.REJECT:
|
||||
messages.error(request, format_html(
|
||||
'{}<br><br>{}',
|
||||
_('We do not accept reports for this type of location.'),
|
||||
group.report_help_text,
|
||||
))
|
||||
return render(request, 'site/report_question.html', {})
|
||||
if group.can_report_missing != LocationGroup.CanReportMissing.SINGLE:
|
||||
raise Http404
|
||||
help_text = group.report_help_text
|
||||
form_kwargs["group"] = group
|
||||
try:
|
||||
report.coordinates
|
||||
except ObjectDoesNotExist:
|
||||
|
@ -491,7 +611,7 @@ def report_create(request, coordinates=None, location=None, origin=None, destina
|
|||
report.options = options.serialize_string()
|
||||
|
||||
if request.method == 'POST':
|
||||
form = report.form_cls(instance=report, data=request.POST)
|
||||
form = report.form_cls(instance=report, data=request.POST, **form_kwargs)
|
||||
if form.is_valid():
|
||||
report = form.instance
|
||||
if request.user.is_authenticated:
|
||||
|
@ -508,12 +628,13 @@ def report_create(request, coordinates=None, location=None, origin=None, destina
|
|||
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)
|
||||
form = report.form_cls(instance=report, **form_kwargs)
|
||||
|
||||
return render(request, 'site/report_create.html', {
|
||||
'report': report,
|
||||
'options': options,
|
||||
'form': form,
|
||||
"help_text": help_text,
|
||||
})
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue