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

View file

@ -283,7 +283,7 @@ def create_editor_form(editor_model):
'outside', 'can_search', 'can_describe', 'geometry', 'single', 'altitude', 'short_label', 'outside', 'can_search', 'can_describe', 'geometry', 'single', 'altitude', 'short_label',
'origin_space', 'target_space', 'data', 'comment', 'slow_down_factor', 'origin_space', 'target_space', 'data', 'comment', 'slow_down_factor',
'extra_seconds', 'speed', 'description', 'speed_up', 'description_up', 'enter_description', 'extra_seconds', 'speed', 'description', 'speed_up', 'description_up', 'enter_description',
'level_change_description', 'base_mapdata_accessible', 'level_change_description', 'base_mapdata_accessible', 'can_report_missing',
'label_settings', 'label_override', 'min_zoom', 'max_zoom', 'font_size', 'label_settings', 'label_override', 'min_zoom', 'max_zoom', 'font_size',
'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', 'left', 'top', 'right', 'bottom'] 'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', 'left', 'top', 'right', 'bottom']
field_names = [field.name for field in editor_model._meta.get_fields() if not field.one_to_many] field_names = [field.name for field in editor_model._meta.get_fields() if not field.one_to_many]

View file

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-12-24 03:50+0100\n" "POT-Creation-Date: 2019-12-24 17:22+0100\n"
"PO-Revision-Date: 2019-12-22 00:44+0100\n" "PO-Revision-Date: 2019-12-22 00:44+0100\n"
"Last-Translator: Jenny Danzmayr <mail@evilscientress.at>\n" "Last-Translator: Jenny Danzmayr <mail@evilscientress.at>\n"
"Language-Team: \n" "Language-Team: \n"
@ -42,7 +42,7 @@ msgstr "Nich angemeldet."
msgid "Logout successful." msgid "Logout successful."
msgstr "Login erfolgreich." msgstr "Login erfolgreich."
#: c3nav/api/models.py:14 #: c3nav/api/models.py:14 c3nav/mapdata/models/report.py:79
msgid "secret" msgid "secret"
msgstr "secret" msgstr "secret"
@ -514,6 +514,7 @@ msgstr "zurück"
#: c3nav/control/templates/control/user.html:73 #: c3nav/control/templates/control/user.html:73
#: c3nav/mapdata/models/access.py:77 c3nav/mapdata/models/geometry/space.py:385 #: c3nav/mapdata/models/access.py:77 c3nav/mapdata/models/geometry/space.py:385
#: c3nav/mapdata/models/report.py:58 c3nav/mapdata/models/report.py:109
#: c3nav/site/models.py:17 #: c3nav/site/models.py:17
msgid "author" msgid "author"
msgstr "Autor" msgstr "Autor"
@ -788,8 +789,8 @@ msgid "Change Set"
msgstr "Änderungsset" msgstr "Änderungsset"
#: c3nav/editor/models/changedobject.py:35 c3nav/editor/models/changeset.py:39 #: c3nav/editor/models/changedobject.py:35 c3nav/editor/models/changeset.py:39
#: c3nav/editor/views/changes.py:266 c3nav/site/models.py:14 #: c3nav/editor/views/changes.py:266 c3nav/mapdata/models/report.py:56
#: c3nav/site/models.py:54 #: c3nav/site/models.py:14 c3nav/site/models.py:54
msgid "created" msgid "created"
msgstr "erstellt" msgstr "erstellt"
@ -863,7 +864,7 @@ msgstr "letzte Statusänderung"
#: c3nav/editor/models/changeset.py:48 c3nav/mapdata/models/base.py:64 #: c3nav/editor/models/changeset.py:48 c3nav/mapdata/models/base.py:64
#: c3nav/mapdata/models/graph.py:38 c3nav/mapdata/models/locations.py:256 #: c3nav/mapdata/models/graph.py:38 c3nav/mapdata/models/locations.py:256
#: c3nav/mapdata/models/locations.py:421 c3nav/mapdata/utils/locations.py:344 #: c3nav/mapdata/models/locations.py:423 c3nav/mapdata/utils/locations.py:344
msgid "Title" msgid "Title"
msgstr "Titel" msgstr "Titel"
@ -871,7 +872,8 @@ msgstr "Titel"
msgid "Description" msgid "Description"
msgstr "Beschreibung" msgstr "Beschreibung"
#: c3nav/editor/models/changeset.py:51 #: c3nav/editor/models/changeset.py:51 c3nav/mapdata/models/report.py:66
#: c3nav/mapdata/models/report.py:113
msgid "assigned to" msgid "assigned to"
msgstr "zugewiesen" msgstr "zugewiesen"
@ -898,7 +900,7 @@ msgid_plural "%(num)d objects changed"
msgstr[0] "%(num)d Objekt geändert" msgstr[0] "%(num)d Objekt geändert"
msgstr[1] "%(num)d Objekte geändert" msgstr[1] "%(num)d Objekte geändert"
#: c3nav/editor/models/changesetupdate.py:12 #: c3nav/editor/models/changesetupdate.py:12 c3nav/mapdata/models/report.py:108
msgid "datetime" msgid "datetime"
msgstr "Zeitpunkt" msgstr "Zeitpunkt"
@ -1150,7 +1152,7 @@ msgid "Log out"
msgstr "Abmelden" msgstr "Abmelden"
#: c3nav/editor/templates/editor/fragment_nav.html:23 #: c3nav/editor/templates/editor/fragment_nav.html:23
#: c3nav/editor/views/account.py:27 c3nav/site/views.py:227 #: c3nav/editor/views/account.py:27 c3nav/site/views.py:232
msgid "Log in" msgid "Log in"
msgstr "Anmelden" msgstr "Anmelden"
@ -1277,7 +1279,7 @@ msgid "Activate direct editing"
msgstr "Direktes Bearbeiten aktivieren" msgstr "Direktes Bearbeiten aktivieren"
#: c3nav/editor/templates/editor/user.html:54 c3nav/editor/views/account.py:85 #: c3nav/editor/templates/editor/user.html:54 c3nav/editor/views/account.py:85
#: c3nav/site/templates/site/account.html:29 c3nav/site/views.py:292 #: c3nav/site/templates/site/account.html:29 c3nav/site/views.py:297
msgid "Change password" msgid "Change password"
msgstr "Passwort ändern" msgstr "Passwort ändern"
@ -1298,11 +1300,11 @@ msgid "All recent change sets"
msgstr "Alle kürzlichen Änderungssets" msgstr "Alle kürzlichen Änderungssets"
#: c3nav/editor/views/account.py:30 c3nav/editor/views/account.py:61 #: c3nav/editor/views/account.py:30 c3nav/editor/views/account.py:61
#: c3nav/site/views.py:234 c3nav/site/views.py:269 #: c3nav/site/views.py:239 c3nav/site/views.py:274
msgid "Create new account" msgid "Create new account"
msgstr "Neues Konto erstellen" msgstr "Neues Konto erstellen"
#: c3nav/editor/views/account.py:75 c3nav/site/views.py:283 #: c3nav/editor/views/account.py:75 c3nav/site/views.py:288
msgid "Password successfully changed." msgid "Password successfully changed."
msgstr "Passwort erfolgreich geändert." msgstr "Passwort erfolgreich geändert."
@ -1509,7 +1511,7 @@ msgstr "Invalides GeoJSON."
msgid "Could not clean geometry." msgid "Could not clean geometry."
msgstr "Konnte Geometrie nicht bereinigen." msgstr "Konnte Geometrie nicht bereinigen."
#: c3nav/mapdata/forms.py:54 #: c3nav/mapdata/forms.py:55
#, python-brace-format #, python-brace-format
msgid "You have to choose a value for {field} in at least one language." msgid "You have to choose a value for {field} in at least one language."
msgstr "Du must das Feld {field} in mindestens einer Sprache ausfüllen." msgstr "Du must das Feld {field} in mindestens einer Sprache ausfüllen."
@ -1679,9 +1681,11 @@ msgstr "Werte zurücksetzen"
msgid "save result to the stats directory" msgid "save result to the stats directory"
msgstr "Ergebnis im stats-Ordner speichern" msgstr "Ergebnis im stats-Ordner speichern"
#: c3nav/mapdata/models/access.py:23 #: c3nav/mapdata/models/access.py:23 c3nav/mapdata/models/report.py:59
#: c3nav/mapdata/models/report.py:110
#: c3nav/site/templates/site/report_detail.html:9
msgid "open" msgid "open"
msgstr "öffnen" msgstr "offen"
#: c3nav/mapdata/models/access.py:24 #: c3nav/mapdata/models/access.py:24
msgid "Groups" msgid "Groups"
@ -1723,8 +1727,8 @@ msgstr "Zugangserlaubnis-Token"
msgid "Access Permission Tokens" msgid "Access Permission Tokens"
msgstr "Zugangserlaubnis-Token" msgstr "Zugangserlaubnis-Token"
#: c3nav/mapdata/models/access.py:133 c3nav/site/views.py:79 #: c3nav/mapdata/models/access.py:133 c3nav/site/views.py:84
#: c3nav/site/views.py:326 #: c3nav/site/views.py:331
msgid "Area successfully unlocked." msgid "Area successfully unlocked."
msgid_plural "Areas successfully unlocked." msgid_plural "Areas successfully unlocked."
msgstr[0] "Bereich erfolgreich freigeschaltet." msgstr[0] "Bereich erfolgreich freigeschaltet."
@ -1976,6 +1980,7 @@ msgstr "Zielraum"
#: c3nav/mapdata/models/geometry/space.py:308 #: c3nav/mapdata/models/geometry/space.py:308
#: c3nav/mapdata/models/geometry/space.py:347 c3nav/mapdata/models/graph.py:48 #: c3nav/mapdata/models/geometry/space.py:347 c3nav/mapdata/models/graph.py:48
#: c3nav/mapdata/models/report.py:63
msgid "description" msgid "description"
msgstr "Beschreibung" msgstr "Beschreibung"
@ -2000,6 +2005,7 @@ msgid "Cross descriptions"
msgstr "Durchschreitungsbeschreibungen" msgstr "Durchschreitungsbeschreibungen"
#: c3nav/mapdata/models/geometry/space.py:386 #: c3nav/mapdata/models/geometry/space.py:386
#: c3nav/mapdata/models/report.py:111
msgid "comment" msgid "comment"
msgstr "Kommentar" msgstr "Kommentar"
@ -2159,7 +2165,7 @@ msgstr "name eines material icons"
msgid "searchable" msgid "searchable"
msgstr "suchbar" msgstr "suchbar"
#: c3nav/mapdata/models/locations.py:162 c3nav/mapdata/models/locations.py:321 #: c3nav/mapdata/models/locations.py:162 c3nav/mapdata/models/locations.py:323
msgid "Location Groups" msgid "Location Groups"
msgstr "Ortgruppen" msgstr "Ortgruppen"
@ -2215,7 +2221,7 @@ msgstr "Ortgruppenkategorie"
msgid "Location Group Categories" msgid "Location Group Categories"
msgstr "Ortgruppenkategorien" msgstr "Ortgruppenkategorien"
#: c3nav/mapdata/models/locations.py:309 c3nav/mapdata/models/locations.py:342 #: c3nav/mapdata/models/locations.py:309 c3nav/mapdata/models/locations.py:344
msgid "Category" msgid "Category"
msgstr "Kategorie" msgstr "Kategorie"
@ -2228,65 +2234,162 @@ msgid "unless location specifies otherwise"
msgstr "kann von Orten überschrieben werden" msgstr "kann von Orten überschrieben werden"
#: c3nav/mapdata/models/locations.py:315 #: c3nav/mapdata/models/locations.py:315
msgid "for missing locations"
msgstr "for fehlende Orte"
#: c3nav/mapdata/models/locations.py:316
msgid "can be used when reporting a missing location"
msgstr "kann beim melden eines fehlenden Ortges genutzt werden"
#: c3nav/mapdata/models/locations.py:317
msgid "background color" msgid "background color"
msgstr "Hintergrundfarbe" msgstr "Hintergrundfarbe"
#: c3nav/mapdata/models/locations.py:320 #: c3nav/mapdata/models/locations.py:322
msgid "Location Group" msgid "Location Group"
msgstr "Ortgruppe" msgstr "Ortgruppe"
#: c3nav/mapdata/models/locations.py:344 c3nav/mapdata/models/locations.py:359 #: c3nav/mapdata/models/locations.py:346 c3nav/mapdata/models/locations.py:361
msgid "color" msgid "color"
msgstr "Farbe" msgstr "Farbe"
#: c3nav/mapdata/models/locations.py:345 #: c3nav/mapdata/models/locations.py:347
msgid "priority" msgid "priority"
msgstr "Priorität" msgstr "Priorität"
#: c3nav/mapdata/models/locations.py:355 #: c3nav/mapdata/models/locations.py:357
msgid "search" msgid "search"
msgstr "suchen" msgstr "suchen"
#: c3nav/mapdata/models/locations.py:357 #: c3nav/mapdata/models/locations.py:359
msgid "describe" msgid "describe"
msgstr "beschreiben" msgstr "beschreiben"
#: c3nav/mapdata/models/locations.py:361 #: c3nav/mapdata/models/locations.py:363
msgid "internal" msgid "internal"
msgstr "intern" msgstr "intern"
#: c3nav/mapdata/models/locations.py:378 #: c3nav/mapdata/models/locations.py:380
#, python-brace-format #, python-brace-format
msgid "{category_title}, {num_locations}" msgid "{category_title}, {num_locations}"
msgstr "{category_title}, {num_locations}" msgstr "{category_title}, {num_locations}"
#: c3nav/mapdata/models/locations.py:380 #: c3nav/mapdata/models/locations.py:382
#, python-format #, python-format
msgid "%(num)d location" msgid "%(num)d location"
msgid_plural "%(num)d locations" msgid_plural "%(num)d locations"
msgstr[0] "%(num)d Ort" msgstr[0] "%(num)d Ort"
msgstr[1] "%(num)d Orte" msgstr[1] "%(num)d Orte"
#: c3nav/mapdata/models/locations.py:403 #: c3nav/mapdata/models/locations.py:405
msgid "target" msgid "target"
msgstr "Ziel" msgstr "Ziel"
#: c3nav/mapdata/models/locations.py:422 #: c3nav/mapdata/models/locations.py:424
msgid "min zoom" msgid "min zoom"
msgstr "Mindestzoom" msgstr "Mindestzoom"
#: c3nav/mapdata/models/locations.py:425 #: c3nav/mapdata/models/locations.py:427
msgid "max zoom" msgid "max zoom"
msgstr "Maximalzoom" msgstr "Maximalzoom"
#: c3nav/mapdata/models/locations.py:428 #: c3nav/mapdata/models/locations.py:430
msgid "font size" msgid "font size"
msgstr "Schriftgröße" msgstr "Schriftgröße"
#: c3nav/mapdata/models/locations.py:444 c3nav/mapdata/models/locations.py:445 #: c3nav/mapdata/models/locations.py:446 c3nav/mapdata/models/locations.py:447
msgid "Label Settings" msgid "Label Settings"
msgstr "Labeleinstellungen" msgstr "Labeleinstellungen"
#: c3nav/mapdata/models/report.py:52
msgid "location issue"
msgstr "Ortfehler"
#: c3nav/mapdata/models/report.py:53
msgid "missing location"
msgstr "fehlender Ort"
#: c3nav/mapdata/models/report.py:54
msgid "route issue"
msgstr "Routenfehler"
#: c3nav/mapdata/models/report.py:57
msgid "category"
msgstr "Kategorie"
#: c3nav/mapdata/models/report.py:60
msgid "last_update"
msgstr "letzte Anderung"
#: c3nav/mapdata/models/report.py:61
msgid "title"
msgstr "Titel"
#: c3nav/mapdata/models/report.py:62
msgid "a short title for your report"
msgstr "ein kurzer Titel für deine Meldung"
#: c3nav/mapdata/models/report.py:64
msgid "tell us precisely what's wrong"
msgstr "Sag uns im Detail was falsch ist"
#: c3nav/mapdata/models/report.py:68
msgid "location"
msgstr "Ort"
#: c3nav/mapdata/models/report.py:69
msgid "coordinates"
msgstr "Koordinaten"
#: c3nav/mapdata/models/report.py:70
msgid "origin"
msgstr "Start"
#: c3nav/mapdata/models/report.py:71
msgid "destination"
msgstr "Ziel"
#: c3nav/mapdata/models/report.py:72
msgid "route options"
msgstr "Routenoptionen"
#: c3nav/mapdata/models/report.py:74
msgid "new location title"
msgstr "Neuer Ortstitel"
#: c3nav/mapdata/models/report.py:75
msgid "you have to supply a title in at least one language"
msgstr "Du must das Feld {field} in mindestens einer Sprache ausfüllen."
#: c3nav/mapdata/models/report.py:76
msgid "location groups"
msgstr "Ortgruppen"
#: c3nav/mapdata/models/report.py:78
msgid "select all groups that apply, if any"
msgstr ""
#: c3nav/mapdata/models/report.py:86
#: c3nav/site/templates/site/report_detail.html:6
msgid "Report"
msgstr "Meldung"
#: c3nav/mapdata/models/report.py:87
msgid "Reports"
msgstr "Meldungen"
#: c3nav/mapdata/models/report.py:114
msgid "public"
msgstr "öffentlich"
#: c3nav/mapdata/models/report.py:117
msgid "Report update"
msgstr "Meldungsupdate"
#: c3nav/mapdata/models/report.py:118
msgid "Report updates"
msgstr "Meldungsupdates"
#: c3nav/mapdata/models/source.py:18 #: c3nav/mapdata/models/source.py:18
msgid "Source" msgid "Source"
msgstr "Vorlage" msgstr "Vorlage"
@ -2408,7 +2511,7 @@ msgstr "Unerreichbarer Ort."
msgid "No route found." msgid "No route found."
msgstr "Keine Route gefunden." msgstr "Keine Route gefunden."
#: c3nav/routing/api.py:110 #: c3nav/routing/api.py:109
msgid "Invalid scan data." msgid "Invalid scan data."
msgstr "Invalide Scandaten." msgstr "Invalide Scandaten."
@ -2456,65 +2559,66 @@ msgstr "Invalider Scan. Unerlaubte Frequenz."
msgid "Invalid Scan. Invalid last timestamp." msgid "Invalid Scan. Invalid last timestamp."
msgstr "Invalider Scan. Letzter Zeitstempel ungültig." msgstr "Invalider Scan. Letzter Zeitstempel ungültig."
#: c3nav/routing/models.py:21 c3nav/routing/models.py:22 #: c3nav/routing/models.py:20 c3nav/routing/models.py:21
#: c3nav/site/templates/site/fragment_report_meta.html:17
#: c3nav/site/templates/site/map.html:177 #: c3nav/site/templates/site/map.html:177
msgid "Route options" msgid "Route options"
msgstr "Routenoptionen" msgstr "Routenoptionen"
#: c3nav/routing/models.py:33 #: c3nav/routing/models.py:32
msgid "Routing mode" msgid "Routing mode"
msgstr "Routemodus" msgstr "Routemodus"
#: c3nav/routing/models.py:34 #: c3nav/routing/models.py:33
msgid "fastest" msgid "fastest"
msgstr "schnellste" msgstr "schnellste"
#: c3nav/routing/models.py:34 #: c3nav/routing/models.py:33
msgid "shortest" msgid "shortest"
msgstr "kürzeste" msgstr "kürzeste"
#: c3nav/routing/models.py:38 #: c3nav/routing/models.py:37
msgid "Walk speed" msgid "Walk speed"
msgstr "Gehgeschwindigkeit" msgstr "Gehgeschwindigkeit"
#: c3nav/routing/models.py:39 #: c3nav/routing/models.py:38
msgid "slow" msgid "slow"
msgstr "langsam" msgstr "langsam"
#: c3nav/routing/models.py:39 #: c3nav/routing/models.py:38
msgid "default" msgid "default"
msgstr "standard" msgstr "standard"
#: c3nav/routing/models.py:39 #: c3nav/routing/models.py:38
msgid "fast" msgid "fast"
msgstr "schnell" msgstr "schnell"
#: c3nav/routing/models.py:45 #: c3nav/routing/models.py:44
msgid "allow" msgid "allow"
msgstr "erlaubt" msgstr "erlaubt"
#: c3nav/routing/models.py:47 #: c3nav/routing/models.py:46
msgid "avoid upwards" msgid "avoid upwards"
msgstr "aufwärts vermeiden" msgstr "aufwärts vermeiden"
#: c3nav/routing/models.py:48 #: c3nav/routing/models.py:47
msgid "avoid downwards" msgid "avoid downwards"
msgstr "abwärts vermeiden" msgstr "abwärts vermeiden"
#: c3nav/routing/models.py:49 #: c3nav/routing/models.py:48
msgid "avoid completely" msgid "avoid completely"
msgstr "komplett vermeiden" msgstr "komplett vermeiden"
#: c3nav/routing/models.py:51 #: c3nav/routing/models.py:50
msgid "avoid" msgid "avoid"
msgstr "vermeiden" msgstr "vermeiden"
#: c3nav/routing/models.py:144 #: c3nav/routing/models.py:143
#, python-format #, python-format
msgid "Unknown route option: %s" msgid "Unknown route option: %s"
msgstr "Unbekannte Routenoption: %s" msgstr "Unbekannte Routenoption: %s"
#: c3nav/routing/models.py:148 #: c3nav/routing/models.py:147
#, python-format #, python-format
msgid "Invalid value for route option %s." msgid "Invalid value for route option %s."
msgstr "Invalider Wert für Routenoption %s." msgstr "Invalider Wert für Routenoption %s."
@ -2658,6 +2762,26 @@ msgstr "Du bist angemeldet als <strong>%(username)s</strong>."
msgid "You can access the control panel." msgid "You can access the control panel."
msgstr "Du kannst das Control Panel betreten." msgstr "Du kannst das Control Panel betreten."
#: c3nav/site/templates/site/fragment_report_meta.html:3
msgid "You are reporting an issue with the following location:"
msgstr "Du meldest einen Fehler beim folgenden Ort:"
#: c3nav/site/templates/site/fragment_report_meta.html:6
msgid "You are reporting an missing location at the following position:"
msgstr "Du meldest einen fehlenden Ort an der folgenden Stelle."
#: c3nav/site/templates/site/fragment_report_meta.html:9
msgid "You are reporting an issue with the following route:"
msgstr "Du meldest einen Fehler bei der folgenden Route:"
#: c3nav/site/templates/site/fragment_report_meta.html:11
msgid "Origin"
msgstr "Start"
#: c3nav/site/templates/site/fragment_report_meta.html:14
msgid "Destination"
msgstr "Ziel"
#: c3nav/site/templates/site/language.html:7 #: c3nav/site/templates/site/language.html:7
msgid "Pick your language" msgid "Pick your language"
msgstr "Sprache wählen" msgstr "Sprache wählen"
@ -2697,11 +2821,11 @@ msgstr "Route von hier aus"
#: c3nav/site/templates/site/map.html:52 c3nav/site/templates/site/map.html:149 #: c3nav/site/templates/site/map.html:52 c3nav/site/templates/site/map.html:149
#: c3nav/site/templates/site/map.html:170 #: c3nav/site/templates/site/map.html:170
#: c3nav/site/templates/site/report_create.html:6
msgid "Report issue" msgid "Report issue"
msgstr "Fehler melden" msgstr "Fehler melden"
#: c3nav/site/templates/site/map.html:56 c3nav/site/templates/site/map.html:153 #: c3nav/site/templates/site/map.html:56 c3nav/site/templates/site/map.html:153
#| msgid "Select this location"
msgid "Report missing location" msgid "Report missing location"
msgstr "Fehlenden Ort melden" msgstr "Fehlenden Ort melden"
@ -2770,39 +2894,70 @@ msgstr ""
msgid "open in c3nav" msgid "open in c3nav"
msgstr "in c3nav öffnen" msgstr "in c3nav öffnen"
#: c3nav/site/templates/site/report.html:6 #: c3nav/site/templates/site/report_create.html:13
msgid "Coming soon" msgid "Submit"
msgstr "Coming soon" msgstr "Absenden"
#: c3nav/site/views.py:71 c3nav/site/views.py:318 #: c3nav/site/templates/site/report_detail.html:11
msgid "closed"
msgstr "geschlossen"
#: c3nav/site/templates/site/report_detail.html:15
msgid "anonymous submission"
msgstr "anonyme Meldung"
#: c3nav/site/templates/site/report_detail.html:17
msgid "by"
msgstr "von"
#: c3nav/site/templates/site/report_detail.html:35
msgid "(none)"
msgstr "(keine)"
#: c3nav/site/views.py:76 c3nav/site/views.py:323
msgid "You need to log in to unlock areas." msgid "You need to log in to unlock areas."
msgstr "Du musst dich anmelden um Bereiche freizuschalten." msgstr "Du musst dich anmelden um Bereiche freizuschalten."
#: c3nav/site/views.py:206 #: c3nav/site/views.py:211
msgid "Areas could not be unlocked because the token has expired." msgid "Areas could not be unlocked because the token has expired."
msgstr "" msgstr ""
"Zugangserlaubnis konnte nicht gewährt werden weil der Code abgelaufen ist." "Zugangserlaubnis konnte nicht gewährt werden weil der Code abgelaufen ist."
#: c3nav/site/views.py:249 #: c3nav/site/views.py:254
msgid "account creation is currently disabled." msgid "account creation is currently disabled."
msgstr "Benutzerregistrierung ist momentan deaktiviert." msgstr "Benutzerregistrierung ist momentan deaktiviert."
#: c3nav/site/views.py:311 #: c3nav/site/views.py:316
msgid "This token does not exist or was already redeemed." msgid "This token does not exist or was already redeemed."
msgstr "Dieser Code existiert nicht oder wurde bereits eingelöst." msgstr "Dieser Code existiert nicht oder wurde bereits eingelöst."
#: c3nav/site/views.py:331 #: c3nav/site/views.py:336
msgid "Unlock area" msgid "Unlock area"
msgid_plural "Unlock areas" msgid_plural "Unlock areas"
msgstr[0] "Bereich freischalten" msgstr[0] "Bereich freischalten"
msgstr[1] "Bereiche freischalten" msgstr[1] "Bereiche freischalten"
#: c3nav/site/views.py:332 #: c3nav/site/views.py:337
msgid "You have been invited to unlock the following area:" msgid "You have been invited to unlock the following area:"
msgid_plural "You have been invited to unlock the following areas:" msgid_plural "You have been invited to unlock the following areas:"
msgstr[0] "Du wurdest eingeladen, den folgenden Bereich freizuschalten:" msgstr[0] "Du wurdest eingeladen, den folgenden Bereich freizuschalten:"
msgstr[1] "Du wurdest eingeladen, die folgenden Bereiche freizuschalten:" msgstr[1] "Du wurdest eingeladen, die folgenden Bereiche freizuschalten:"
#: c3nav/site/views.py:408
msgid "Your report was submitted."
msgstr "Deine Meldiung wurde abgesendet."
#: c3nav/site/views.py:411
msgid "You can keep track of it from your user dashboard."
msgstr "Du kannst sie in deinerm Benutzerdashboard verfolgen."
#: c3nav/site/views.py:413
msgid "You can keep track of it by revisiting the public URL mentioned below."
msgstr "Du kannst sie mit dem unten angegebenen öffentlichen link verfolgen."
#~ msgid "Coming soon"
#~ msgstr "Coming soon"
#~ msgid "You can not edit this object." #~ msgid "You can not edit this object."
#~ msgstr "Du kannst dieses Objekt nicht bearbeiten." #~ msgstr "Du kannst dieses Objekt nicht bearbeiten."

View file

@ -41,7 +41,8 @@ class I18nModelFormMixin(ModelForm):
new_fields[sub_field_name] = CharField(label=field_title, new_fields[sub_field_name] = CharField(label=field_title,
required=False, required=False,
initial=values[language].strip(), initial=values[language].strip(),
max_length=model_field.i18n_max_length) max_length=model_field.i18n_max_length,
help_text=form_field.help_text)
if has_values: if has_values:
self.i18n_fields.append((model_field, values)) self.i18n_fields.append((model_field, values))

View file

@ -0,0 +1,84 @@
# Generated by Django 2.2.8 on 2019-12-24 15:52
import c3nav.mapdata.fields
import c3nav.mapdata.models.report
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('mapdata', '0077_obstacle_altitude'),
]
operations = [
migrations.CreateModel(
name='Report',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='created')),
('category', models.CharField(choices=[('location-issue', 'location issue'), ('missing-location', 'missing location'), ('route-issue', 'route issue')], db_index=True, max_length=20, verbose_name='category')),
('open', models.BooleanField(default=True, verbose_name='open')),
('last_update', models.DateTimeField(auto_now=True, verbose_name='last_update')),
('title', models.CharField(default='', help_text='a short title for your report', max_length=100, verbose_name='title')),
('description', models.TextField(default='', help_text="tell us precisely what's wrong", max_length=1000, verbose_name='description')),
('coordinates_id', models.CharField(max_length=48, null=True, verbose_name='coordinates')),
('origin_id', models.CharField(max_length=48, null=True, verbose_name='origin')),
('destination_id', models.CharField(max_length=48, null=True, verbose_name='destination')),
('route_options', models.CharField(max_length=128, null=True, verbose_name='route options')),
('created_title', c3nav.mapdata.fields.I18nField(fallback_any=True, help_text='you have to supply a title in at least one language', plural_name='titles', verbose_name='new location title')),
('secret', models.CharField(default=c3nav.mapdata.models.report.get_report_secret, max_length=32, verbose_name='secret')),
('assigned_to', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='assigned_reports', to=settings.AUTH_USER_MODEL, verbose_name='assigned to')),
('author', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='report', to=settings.AUTH_USER_MODEL, verbose_name='author')),
],
options={
'verbose_name': 'Report',
'verbose_name_plural': 'Reports',
'default_related_name': 'report',
},
),
migrations.AlterModelOptions(
name='lineobstacle',
options={'default_related_name': 'lineobstacles', 'ordering': ('altitude', 'height'), 'verbose_name': 'Line Obstacle', 'verbose_name_plural': 'Line Obstacles'},
),
migrations.AlterModelOptions(
name='obstacle',
options={'default_related_name': 'obstacles', 'ordering': ('altitude', 'height'), 'verbose_name': 'Obstacle', 'verbose_name_plural': 'Obstacles'},
),
migrations.AddField(
model_name='locationgroup',
name='can_report_missing',
field=models.BooleanField(default=False, help_text='can be used when reporting a missing location', verbose_name='for missing locations'),
),
migrations.CreateModel(
name='ReportUpdate',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('datetime', models.DateTimeField(auto_now_add=True, verbose_name='datetime')),
('open', models.NullBooleanField(verbose_name='open')),
('comment', models.TextField(verbose_name='comment')),
('public', models.BooleanField(verbose_name='public')),
('assigned_to', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='report_update_assigns', to=settings.AUTH_USER_MODEL, verbose_name='assigned to')),
('author', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='reportupdate', to=settings.AUTH_USER_MODEL, verbose_name='author')),
('report', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reportupdate', to='mapdata.Report')),
],
options={
'verbose_name': 'Report update',
'verbose_name_plural': 'Report updates',
'default_related_name': 'reportupdate',
},
),
migrations.AddField(
model_name='report',
name='created_groups',
field=models.ManyToManyField(blank=True, help_text='select all groups that apply, if any', limit_choices_to={'can_report_missing': True}, related_name='report', to='mapdata.LocationGroup', verbose_name='location groups'),
),
migrations.AddField(
model_name='report',
name='location',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='reports', to='mapdata.LocationSlug', verbose_name='location'),
),
]

View file

@ -312,6 +312,8 @@ class LocationGroup(Location, models.Model):
label_settings = models.ForeignKey('mapdata.LabelSettings', null=True, blank=True, on_delete=models.PROTECT, label_settings = models.ForeignKey('mapdata.LabelSettings', null=True, blank=True, on_delete=models.PROTECT,
verbose_name=_('label settings'), verbose_name=_('label settings'),
help_text=_('unless location specifies otherwise')) help_text=_('unless location specifies otherwise'))
can_report_missing = models.BooleanField(default=False, verbose_name=_('for missing locations'),
help_text=_('can be used when reporting a missing location'))
color = models.CharField(null=True, blank=True, max_length=32, verbose_name=_('background color')) color = models.CharField(null=True, blank=True, max_length=32, verbose_name=_('background color'))
objects = LocationGroupManager() objects = LocationGroupManager()

View file

@ -0,0 +1,119 @@
import string
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils.crypto import get_random_string
from django.utils.translation import ugettext_lazy as _
from c3nav.mapdata.fields import I18nField
from c3nav.mapdata.utils.locations import get_location_by_id_for_request
def get_report_secret():
return get_random_string(32, string.ascii_letters)
class LocationById():
def __init__(self):
super().__init__()
self.name = None
self.cached_id = None
self.cached_value = None
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner=None):
value_id = getattr(instance, self.name+'_id')
if value_id is None:
self.cached_pk = None
self.cached_value = None
return None
if value_id == self.cached_id:
return self.cached_value
value = get_location_by_id_for_request(value_id, getattr(instance, 'request', None))
if value is None:
raise ObjectDoesNotExist
self.cached_id = value_id
self.cached_value = value
return value
def __set__(self, instance, value):
self.cached_id = value.pk
self.cached_value = value
setattr(instance, self.name+'_id', value.pk)
class Report(models.Model):
CATEGORIES = (
('location-issue', _('location issue')),
('missing-location', _('missing location')),
('route-issue', _('route issue')),
)
created = models.DateTimeField(auto_now_add=True, verbose_name=_('created'))
category = models.CharField(max_length=20, db_index=True, choices=CATEGORIES, verbose_name=_('category'))
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, verbose_name=_('author'))
open = models.BooleanField(default=True, verbose_name=_('open'))
last_update = models.DateTimeField(auto_now=True, verbose_name=_('last_update'))
title = models.CharField(max_length=100, default='', verbose_name=_('title'),
help_text=_('a short title for your report'))
description = models.TextField(max_length=1000, default='', verbose_name=_('description'),
help_text=_('tell us precisely what\'s wrong'))
assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT,
related_name='assigned_reports', verbose_name=_('assigned to'))
location = models.ForeignKey('mapdata.LocationSlug', null=True, on_delete=models.SET_NULL,
related_name='reports', verbose_name=_('location'))
coordinates_id = models.CharField(_('coordinates'), null=True, max_length=48)
origin_id = models.CharField(_('origin'), null=True, max_length=48)
destination_id = models.CharField(_('destination'), null=True, max_length=48)
route_options = models.CharField(_('route options'), null=True, max_length=128)
created_title = I18nField(_('new location title'), plural_name='titles', blank=False, fallback_any=True,
help_text=_('you have to supply a title in at least one language'))
created_groups = models.ManyToManyField('mapdata.LocationGroup', verbose_name=_('location groups'), blank=True,
limit_choices_to={'can_report_missing': True},
help_text=_('select all groups that apply, if any'))
secret = models.CharField(_('secret'), max_length=32, default=get_report_secret)
coordinates = LocationById()
origin = LocationById()
destination = LocationById()
class Meta:
verbose_name = _('Report')
verbose_name_plural = _('Reports')
default_related_name = 'report'
@property
def form_cls(self):
from c3nav.site.forms import ReportMissingLocationForm, ReportIssueForm
return ReportMissingLocationForm if self.category == 'missing-location' else ReportIssueForm
@classmethod
def qs_for_request(cls, request):
if request.user.is_superuser:
# todo: permissions!
return cls.objects.all()
elif request.user.is_authenticated:
return cls.objects.filter(author=request.user)
else:
return cls.objects.none()
class ReportUpdate(models.Model):
report = models.ForeignKey(Report, on_delete=models.CASCADE)
datetime = models.DateTimeField(auto_now_add=True, verbose_name=_('datetime'))
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, verbose_name=_('author'))
open = models.NullBooleanField(verbose_name=_('open'))
comment = models.TextField(verbose_name=_('comment'))
assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT,
related_name='report_update_assigns', verbose_name=_('assigned to'))
public = models.BooleanField(verbose_name=_('public'))
class Meta:
verbose_name = _('Report update')
verbose_name_plural = _('Report updates')
default_related_name = 'reportupdate'

View file

@ -418,3 +418,6 @@ class CustomLocation:
@cached_property @cached_property
def subtitle(self): def subtitle(self):
return self.title_subtitle[1] return self.title_subtitle[1]
def get_icon(self):
return self.icon

View file

@ -174,6 +174,7 @@ class RouteOptions(models.Model):
for choice_name, choice_title in field.choices for choice_name, choice_title in field.choices
], ],
'value': self[name], 'value': self[name],
'value_display': dict(field.choices)[self[name]],
} }
for name, field in self.get_fields().items() for name, field in self.get_fields().items()
] ]
@ -181,6 +182,12 @@ class RouteOptions(models.Model):
def serialize_string(self): def serialize_string(self):
return ','.join('%s=%s' % (key, val) for key, val in self.data.items()) return ','.join('%s=%s' % (key, val) for key, val in self.data.items())
@classmethod
def unserialize_string(cls, data):
return RouteOptions(
data=dict(item.split('=') for item in data.split(','))
)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self.request is None or self.request.user.is_authenticated: if self.request is None or self.request.user.is_authenticated:
self.user = self.request.user self.user = self.request.user

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; padding: 5px 10px 5px 53px;
height: 55px; height: 55px;
} }
.location.location-form-value {
margin: -10px -10px 5px -10px;
}
.location .icon { .location .icon {
font-size: 36px; font-size: 36px;
position: absolute; position: absolute;
@ -1256,6 +1259,25 @@ main .narrow p, main .narrow form, main .narrow button {
main .narrow form button { main .narrow form button {
width: 100%; 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 { .user-permissions-form label {
font-weight: 400; font-weight: 400;

View file

@ -14,7 +14,7 @@
<form method="post" action="{{ request.path_info }}?{{ request.META.QUERY_STRING }}"> <form method="post" action="{{ request.path_info }}?{{ request.META.QUERY_STRING }}">
{% csrf_token %} {% csrf_token %}
{{ form }} {{ form.as_p }}
<button type="submit">{{ title }}</button> <button type="submit">{{ title }}</button>
{% if bottom_link_url %} {% if bottom_link_url %}
<a href="{{ bottom_link_url }}?{{ request.META.QUERY_STRING }}">{{ bottom_link_text }}</a> <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 django.conf.urls import url
from c3nav.site.views import (about_view, access_redeem_view, account_view, change_password_view, choose_language, 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-_.:]+)' slug = r'(?P<slug>[a-z0-9-_.:]+)'
coordinates = r'(?P<coordinates>[a-z0-9-_:]+:-?\d+(\.\d+)?:-?\d+(\.\d+)?)' 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'^lang/$', choose_language, name='site.language'),
url(r'^about/$', about_view, name='site.about'), url(r'^about/$', about_view, name='site.about'),
url(r'^report/$', 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/(?P<pk>\d+)/$', report_detail, name='site.report_detail'),
url(r'^report/l/(?P<location>\d+)/$', report_view, name='site.report'), url(r'^report/(?P<pk>\d+)/(?P<secret>[^/]+)/$', report_detail, name='site.report_detail'),
url(r'^report/r/(?P<origin>[^/]+)/(?P<destination>[^/]+)/(?P<options>[^/]+)/$', report_view, name='site.report'), 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.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm, UserCreationForm from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm, UserCreationForm
from django.contrib.auth.views import redirect_to_login 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.core.serializers.json import DjangoJSONEncoder
from django.db import transaction 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.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.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ 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 import Location, Source
from c3nav.mapdata.models.access import AccessPermissionToken from c3nav.mapdata.models.access import AccessPermissionToken
from c3nav.mapdata.models.locations import LocationRedirect, SpecificLocation 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.utils.user import can_access_editor, get_user_data
from c3nav.mapdata.views import set_tile_access_cookie from c3nav.mapdata.views import set_tile_access_cookie
from c3nav.routing.models import RouteOptions
from c3nav.site.models import Announcement, SiteUpdate 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 @never_cache
def report_view(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):
return render(request, 'site/report.html', {}) 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,
})