From 407e3ba06bc3680f5a36feda6a5378da006b6297 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laura=20Kl=C3=BCnder?=
Date: Fri, 27 Dec 2019 14:13:40 +0100
Subject: [PATCH] first stuff for custom positions
---
src/c3nav/locale/de/LC_MESSAGES/django.po | 586 +++++++++++-------
.../0082_dynamiclocation_position.py | 56 ++
src/c3nav/mapdata/models/locations.py | 53 ++
src/c3nav/mapdata/models/report.py | 36 +-
src/c3nav/mapdata/utils/fields.py | 35 ++
src/c3nav/site/forms.py | 7 +
src/c3nav/site/templates/site/account.html | 9 +
.../site/templates/site/position_create.html | 16 +
.../site/templates/site/position_detail.html | 30 +
.../site/templates/site/position_list.html | 18 +
src/c3nav/site/urls.py | 7 +-
src/c3nav/site/views.py | 69 ++-
12 files changed, 655 insertions(+), 267 deletions(-)
create mode 100644 src/c3nav/mapdata/migrations/0082_dynamiclocation_position.py
create mode 100644 src/c3nav/mapdata/utils/fields.py
create mode 100644 src/c3nav/site/templates/site/position_create.html
create mode 100644 src/c3nav/site/templates/site/position_detail.html
create mode 100644 src/c3nav/site/templates/site/position_list.html
diff --git a/src/c3nav/locale/de/LC_MESSAGES/django.po b/src/c3nav/locale/de/LC_MESSAGES/django.po
index f32f2163..3049f9fe 100644
--- a/src/c3nav/locale/de/LC_MESSAGES/django.po
+++ b/src/c3nav/locale/de/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-12-25 00:40+0100\n"
-"PO-Revision-Date: 2019-12-25 00:41+0100\n"
+"POT-Creation-Date: 2019-12-27 14:08+0100\n"
+"PO-Revision-Date: 2019-12-27 14:11+0100\n"
"Last-Translator: Jenny Danzmayr \n"
"Language-Team: \n"
"Language: de\n"
@@ -42,7 +42,8 @@ msgstr "Nich angemeldet."
msgid "Logout successful."
msgstr "Login erfolgreich."
-#: c3nav/api/models.py:14 c3nav/mapdata/models/report.py:85
+#: c3nav/api/models.py:14 c3nav/mapdata/models/locations.py:497
+#: c3nav/mapdata/models/report.py:55
msgid "secret"
msgstr "secret"
@@ -206,6 +207,7 @@ msgid "can review reports belonging to"
msgstr "can Meldungen überprüfen die zu diesen Gruppen gehören"
#: c3nav/control/models.py:38 c3nav/control/templates/control/user.html:34
+#: c3nav/site/templates/site/position_detail.html:15
msgid "API secret"
msgstr "API secret"
@@ -266,7 +268,7 @@ msgstr "Benutzer"
#: c3nav/control/templates/control/announcements.html:9
#: c3nav/control/templates/control/map_updates.html:59
#: c3nav/control/templates/control/users.html:15
-#: c3nav/mapdata/models/base.py:43 c3nav/mapdata/utils/locations.py:309
+#: c3nav/mapdata/models/base.py:43 c3nav/mapdata/utils/locations.py:315
#: c3nav/site/templates/site/report_list.html:18
msgid "ID"
msgstr "ID"
@@ -450,7 +452,7 @@ msgstr ""
#: c3nav/control/templates/control/user.html:144
#: c3nav/control/templates/control/user.html:177
#: c3nav/mapdata/models/geometry/level.py:142
-#: c3nav/mapdata/models/locations.py:122 c3nav/mapdata/models/locations.py:123
+#: c3nav/mapdata/models/locations.py:131 c3nav/mapdata/models/locations.py:132
msgid "Yes"
msgstr "Ja"
@@ -460,7 +462,7 @@ msgstr "Ja"
#: c3nav/control/templates/control/user.html:146
#: c3nav/control/templates/control/user.html:179
#: c3nav/mapdata/models/geometry/level.py:142
-#: c3nav/mapdata/models/locations.py:122 c3nav/mapdata/models/locations.py:123
+#: c3nav/mapdata/models/locations.py:131 c3nav/mapdata/models/locations.py:132
msgid "No"
msgstr "Nein"
@@ -528,7 +530,7 @@ msgstr "zurück"
#: c3nav/control/templates/control/user.html:77
#: c3nav/mapdata/models/access.py:77 c3nav/mapdata/models/geometry/space.py:385
-#: c3nav/mapdata/models/report.py:64 c3nav/mapdata/models/report.py:163
+#: c3nav/mapdata/models/report.py:34 c3nav/mapdata/models/report.py:170
#: c3nav/site/models.py:17
msgid "author"
msgstr "Autor"
@@ -571,10 +573,10 @@ msgstr "Zugangsbeschränkung"
#: c3nav/control/templates/control/user.html:149
#: c3nav/editor/templates/editor/fragment_changesets.html:10
#: c3nav/editor/templates/editor/list.html:26
-#: c3nav/site/templates/site/map.html:112
-#: c3nav/site/templates/site/map.html:146
-#: c3nav/site/templates/site/map.html:155
-#: c3nav/site/templates/site/map.html:176
+#: c3nav/site/templates/site/map.html:119
+#: c3nav/site/templates/site/map.html:153
+#: c3nav/site/templates/site/map.html:162
+#: c3nav/site/templates/site/map.html:183
msgid "Details"
msgstr "Details"
@@ -586,7 +588,7 @@ msgstr "Raumzugriffserlaubnis"
#: c3nav/editor/templates/editor/space.html:9
#: c3nav/mapdata/models/geometry/level.py:124
#: c3nav/mapdata/models/geometry/space.py:81
-#: c3nav/mapdata/utils/locations.py:317
+#: c3nav/mapdata/utils/locations.py:323
msgid "Space"
msgstr "Raum"
@@ -688,37 +690,37 @@ msgstr ""
"Kartenänderungsverarbeitung konnte nicht veranlasst werden da Celery nicht "
"konfiguriert ist."
-#: c3nav/editor/api.py:411
+#: c3nav/editor/api.py:414
msgid "No matching editor view endpoint found."
msgstr "Es wurde keine passende Editor-Endpunkt gefunden."
-#: c3nav/editor/api.py:414
+#: c3nav/editor/api.py:417
msgid "Matching editor view point does not provide an API."
msgstr "Der entsprechende Editor-Endpunkt bietet diese API nicht an."
-#: c3nav/editor/api.py:497
+#: c3nav/editor/api.py:500
msgid "You don't have the permission to activate direct editing."
msgstr "Du darfst direktes Bearbeiten nicht aktivieren."
-#: c3nav/editor/api.py:501
+#: c3nav/editor/api.py:504
msgid "You cannot activate direct editing if you have an active changeset."
msgstr ""
"Du kannst direktes Bearbeiten nicht aktivieren, wenn du ein aktives "
"Änderungsset hast."
-#: c3nav/editor/api.py:532 c3nav/editor/views/changes.py:66
+#: c3nav/editor/api.py:535 c3nav/editor/views/changes.py:66
msgid "You can not activate this change set."
msgstr "Du kannst dieses Änderungsset nicht aktivieren."
-#: c3nav/editor/api.py:542 c3nav/editor/views/changes.py:400
+#: c3nav/editor/api.py:545 c3nav/editor/views/changes.py:400
msgid "You cannot edit this change set."
msgstr "Du kannst dieses Änderungsset nicht bearbeiten."
-#: c3nav/editor/api.py:571 c3nav/editor/views/changes.py:56
+#: c3nav/editor/api.py:574 c3nav/editor/views/changes.py:56
msgid "You can not edit changes on this change set."
msgstr "Du kannst keine Änderungen dieses Änderungssets bearbeiten."
-#: c3nav/editor/api.py:581 c3nav/editor/views/changes.py:52
+#: c3nav/editor/api.py:584 c3nav/editor/views/changes.py:52
msgid ""
"You cannot restore this object, because it depends on a deleted object or it "
"would violate a unique contraint."
@@ -726,41 +728,41 @@ msgstr ""
"Du kannst dieses Objekt nicht wiederherstellen weil es ein anderes Objekt "
"benötigt oder weil es einer Eindeutigen Beschränkung wiedersprechen würde."
-#: c3nav/editor/api.py:589 c3nav/editor/views/changes.py:72
+#: c3nav/editor/api.py:592 c3nav/editor/views/changes.py:72
msgid "You need to log in to propose changes."
msgstr "Du musst dich anmelden um Änderungen vorzuschlagen."
-#: c3nav/editor/api.py:594 c3nav/editor/views/changes.py:77
+#: c3nav/editor/api.py:597 c3nav/editor/views/changes.py:77
msgid "You need to add a title an a description to propose this change set."
msgstr ""
"Du musst einen Titel und eine Beschreibung hinzufügen, um dieses "
"Änderungsset vorzuschlagen."
-#: c3nav/editor/api.py:597 c3nav/editor/views/changes.py:84
+#: c3nav/editor/api.py:600 c3nav/editor/views/changes.py:84
msgid "You cannot propose this change set."
msgstr "Du kannst dieses Änderungsset nicht vorschlagen."
-#: c3nav/editor/api.py:607 c3nav/editor/views/changes.py:94
+#: c3nav/editor/api.py:610 c3nav/editor/views/changes.py:94
msgid "You cannot unpropose this change set."
msgstr "Du kannst diesen Änderungsvorschlag nicht zurücknehmen."
-#: c3nav/editor/api.py:617 c3nav/editor/views/changes.py:104
+#: c3nav/editor/api.py:620 c3nav/editor/views/changes.py:104
msgid "You cannot review these changes."
msgstr "Du kannst diese Änderungen nicht überprüfen."
-#: c3nav/editor/api.py:627 c3nav/editor/views/changes.py:111
+#: c3nav/editor/api.py:630 c3nav/editor/views/changes.py:111
msgid "You cannot reject these changes."
msgstr "Du kannst diese Änderungen nicht ablehnen."
-#: c3nav/editor/api.py:641 c3nav/editor/views/changes.py:131
+#: c3nav/editor/api.py:644 c3nav/editor/views/changes.py:131
msgid "You cannot unreject these changes."
msgstr "Du kannst diese Änderungsablehnung nicht zurücknehmen."
-#: c3nav/editor/api.py:651 c3nav/editor/views/changes.py:142
+#: c3nav/editor/api.py:654 c3nav/editor/views/changes.py:142
msgid "You cannot accept and apply these changes."
msgstr "Du kannst diese Änderungen nicht akzeptieren und anwenden."
-#: c3nav/editor/api.py:661 c3nav/editor/views/changes.py:155
+#: c3nav/editor/api.py:664 c3nav/editor/views/changes.py:155
msgid "You cannot delete this change set."
msgstr "Du kannst dieses Änderungsset nicht löschen."
@@ -803,7 +805,7 @@ msgid "Change Set"
msgstr "Änderungsset"
#: c3nav/editor/models/changedobject.py:35 c3nav/editor/models/changeset.py:39
-#: c3nav/editor/views/changes.py:266 c3nav/mapdata/models/report.py:62
+#: c3nav/editor/views/changes.py:266 c3nav/mapdata/models/report.py:32
#: c3nav/site/models.py:14 c3nav/site/models.py:54
msgid "created"
msgstr "erstellt"
@@ -877,8 +879,8 @@ msgid "last state update"
msgstr "letzte Statusänderung"
#: 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/locations.py:423 c3nav/mapdata/utils/locations.py:345
+#: c3nav/mapdata/models/graph.py:38 c3nav/mapdata/models/locations.py:265
+#: c3nav/mapdata/models/locations.py:432 c3nav/mapdata/utils/locations.py:351
#: c3nav/site/templates/site/report_list.html:19
msgid "Title"
msgstr "Titel"
@@ -887,8 +889,8 @@ msgstr "Titel"
msgid "Description"
msgstr "Beschreibung"
-#: c3nav/editor/models/changeset.py:51 c3nav/mapdata/models/report.py:72
-#: c3nav/mapdata/models/report.py:167
+#: c3nav/editor/models/changeset.py:51 c3nav/mapdata/models/report.py:42
+#: c3nav/mapdata/models/report.py:174
msgid "assigned to"
msgstr "zugewiesen"
@@ -900,22 +902,22 @@ msgstr "Kartenänderung"
msgid "Change Sets"
msgstr "Änderungssets"
-#: c3nav/editor/models/changeset.py:801
+#: c3nav/editor/models/changeset.py:805
msgid "Direct editing active"
msgstr "Direktes Bearbeiten aktiv"
-#: c3nav/editor/models/changeset.py:802
+#: c3nav/editor/models/changeset.py:806
msgid "No objects changed"
msgstr "Keine Objekte geändert"
-#: c3nav/editor/models/changeset.py:803
+#: c3nav/editor/models/changeset.py:807
#, python-format
msgid "%(num)d object changed"
msgid_plural "%(num)d objects changed"
msgstr[0] "%(num)d Objekt geändert"
msgstr[1] "%(num)d Objekte geändert"
-#: c3nav/editor/models/changesetupdate.py:12 c3nav/mapdata/models/report.py:162
+#: c3nav/editor/models/changesetupdate.py:12 c3nav/mapdata/models/report.py:169
msgid "datetime"
msgstr "Zeitpunkt"
@@ -1162,12 +1164,12 @@ msgid "close dialog"
msgstr "Dialog schließen"
#: c3nav/editor/templates/editor/fragment_nav.html:21
-#: c3nav/site/templates/site/account.html:46
+#: c3nav/site/templates/site/account.html:55
msgid "Log out"
msgstr "Abmelden"
#: c3nav/editor/templates/editor/fragment_nav.html:23
-#: c3nav/editor/views/account.py:27 c3nav/site/views.py:233
+#: c3nav/editor/views/account.py:27 c3nav/site/views.py:238
msgid "Log in"
msgstr "Anmelden"
@@ -1210,12 +1212,14 @@ msgstr "Einstellungen für neue Kanten"
#: c3nav/editor/templates/editor/index.html:10
#: c3nav/editor/templates/editor/level.html:16
#: c3nav/mapdata/models/geometry/level.py:58 c3nav/mapdata/models/level.py:29
-#: c3nav/mapdata/utils/locations.py:311
+#: c3nav/mapdata/utils/locations.py:317
msgid "Level"
msgstr "Etage"
#: c3nav/editor/templates/editor/level.html:22
#: c3nav/editor/templates/editor/space.html:14 c3nav/editor/views/edit.py:495
+#: c3nav/site/templates/site/position_create.html:8
+#: c3nav/site/templates/site/position_detail.html:8
msgid "back to overview"
msgstr "zurück zur Übersicht"
@@ -1294,7 +1298,7 @@ msgid "Activate direct editing"
msgstr "Direktes Bearbeiten aktivieren"
#: c3nav/editor/templates/editor/user.html:54 c3nav/editor/views/account.py:85
-#: c3nav/site/templates/site/account.html:47 c3nav/site/views.py:298
+#: c3nav/site/templates/site/account.html:56 c3nav/site/views.py:303
msgid "Change password"
msgstr "Passwort ändern"
@@ -1315,11 +1319,11 @@ msgid "All recent change sets"
msgstr "Alle kürzlichen Änderungssets"
#: c3nav/editor/views/account.py:30 c3nav/editor/views/account.py:61
-#: c3nav/site/views.py:240 c3nav/site/views.py:275
+#: c3nav/site/views.py:245 c3nav/site/views.py:280
msgid "Create new account"
msgstr "Neues Konto erstellen"
-#: c3nav/editor/views/account.py:75 c3nav/site/views.py:289
+#: c3nav/editor/views/account.py:75 c3nav/site/views.py:294
msgid "Password successfully changed."
msgstr "Passwort erfolgreich geändert."
@@ -1508,12 +1512,12 @@ msgstr "Du hast direktes Bearbeiten aktiviert."
msgid "You deactivated direct editing."
msgstr "Du hast direktes Bearbeiten deaktiviert."
-#: c3nav/mapdata/api.py:202
+#: c3nav/mapdata/api.py:201
#, python-format
msgid "%(field)s is not an integer."
msgstr "%(field)s ist keine ganze Zahl."
-#: c3nav/mapdata/api.py:210
+#: c3nav/mapdata/api.py:209
#, python-format
msgid "%(model)s not found."
msgstr "%(model)s nicht gefunden."
@@ -1696,9 +1700,9 @@ msgstr "Werte zurücksetzen"
msgid "save result to the stats directory"
msgstr "Ergebnis im stats-Ordner speichern"
-#: c3nav/mapdata/models/access.py:23 c3nav/mapdata/models/report.py:65
-#: c3nav/mapdata/models/report.py:164
-#: c3nav/site/templates/site/report_detail.html:11
+#: c3nav/mapdata/models/access.py:23 c3nav/mapdata/models/report.py:35
+#: c3nav/mapdata/models/report.py:171 c3nav/site/forms.py:33
+#: c3nav/site/templates/site/report_detail.html:15
#: c3nav/site/templates/site/report_list.html:28
msgid "open"
msgstr "offen"
@@ -1743,8 +1747,8 @@ msgstr "Zugangserlaubnis-Token"
msgid "Access Permission Tokens"
msgstr "Zugangserlaubnis-Token"
-#: c3nav/mapdata/models/access.py:133 c3nav/site/views.py:84
-#: c3nav/site/views.py:334
+#: c3nav/mapdata/models/access.py:133 c3nav/site/views.py:86
+#: c3nav/site/views.py:339
msgid "Area successfully unlocked."
msgid_plural "Areas successfully unlocked."
msgstr[0] "Bereich erfolgreich freigeschaltet."
@@ -1758,28 +1762,28 @@ msgstr "Zugangserlaubnis-Token"
msgid "Access Permission"
msgstr "Zugangserlaubnis"
-#: c3nav/mapdata/models/base.py:42 c3nav/mapdata/utils/locations.py:308
+#: c3nav/mapdata/models/base.py:42 c3nav/mapdata/utils/locations.py:314
msgid "Type"
msgstr "Typ"
-#: c3nav/mapdata/models/base.py:83
+#: c3nav/mapdata/models/base.py:87
#, python-brace-format
msgid "Title ({lang})"
msgstr "Titel ({lang})"
-#: c3nav/mapdata/models/base.py:89
+#: c3nav/mapdata/models/base.py:93
msgid "bottom coordinate"
msgstr "untere koordinate"
-#: c3nav/mapdata/models/base.py:90
+#: c3nav/mapdata/models/base.py:94
msgid "left coordinate"
msgstr "linke koordinate"
-#: c3nav/mapdata/models/base.py:91
+#: c3nav/mapdata/models/base.py:95
msgid "top coordinate"
msgstr "obere koordinate"
-#: c3nav/mapdata/models/base.py:92
+#: c3nav/mapdata/models/base.py:96
msgid "right coordinate"
msgstr "rechte koordinate"
@@ -1915,7 +1919,7 @@ msgid "Area"
msgstr "Bereich"
#: c3nav/mapdata/models/geometry/space.py:124
-#: c3nav/mapdata/utils/locations.py:323
+#: c3nav/mapdata/utils/locations.py:329
msgid "Areas"
msgstr "Bereiche"
@@ -1996,7 +2000,7 @@ msgstr "Zielraum"
#: c3nav/mapdata/models/geometry/space.py:308
#: c3nav/mapdata/models/geometry/space.py:347 c3nav/mapdata/models/graph.py:48
-#: c3nav/mapdata/models/report.py:69
+#: c3nav/mapdata/models/report.py:39
msgid "description"
msgstr "Beschreibung"
@@ -2021,7 +2025,7 @@ msgid "Cross descriptions"
msgstr "Durchschreitungsbeschreibungen"
#: c3nav/mapdata/models/geometry/space.py:386
-#: c3nav/mapdata/models/report.py:165
+#: c3nav/mapdata/models/report.py:172
msgid "comment"
msgstr "Kommentar"
@@ -2045,7 +2049,7 @@ msgstr "Graphknoten"
msgid "Graph Nodes"
msgstr "Graphknoten"
-#: c3nav/mapdata/models/graph.py:39 c3nav/mapdata/models/locations.py:257
+#: c3nav/mapdata/models/graph.py:39 c3nav/mapdata/models/locations.py:266
msgid "Title (Plural)"
msgstr "Titel (Plural)"
@@ -2142,7 +2146,7 @@ msgid "default height"
msgstr "Standarddeckenhöhe"
#. Translators: "letters" means latin letters: a-z and A-Z.
-#: c3nav/mapdata/models/locations.py:47
+#: c3nav/mapdata/models/locations.py:51
msgid ""
"Enter a valid location slug consisting of lowercase letters, numbers or "
"hyphens, not starting or ending with hyphens or containing consecutive "
@@ -2152,257 +2156,285 @@ msgstr ""
"Bindestrichen besteht und nicht mit einem Bindestrich beginnt oder endet "
"oder aufeinanderfolgende Bindestriche enthält."
-#: c3nav/mapdata/models/locations.py:62 c3nav/mapdata/models/locations.py:82
-#: c3nav/mapdata/utils/locations.py:310
+#: c3nav/mapdata/models/locations.py:66 c3nav/mapdata/models/locations.py:86
+#: c3nav/mapdata/utils/locations.py:316
msgid "Slug"
msgstr "Slug"
-#: c3nav/mapdata/models/locations.py:90 c3nav/mapdata/models/locations.py:91
+#: c3nav/mapdata/models/locations.py:94 c3nav/mapdata/models/locations.py:95
msgid "Location with Slug"
msgstr "Ort mit Slug"
-#: c3nav/mapdata/models/locations.py:96
+#: c3nav/mapdata/models/locations.py:100
msgid "can be searched"
msgstr "zur Suche zugelassen"
-#: c3nav/mapdata/models/locations.py:97 c3nav/mapdata/models/locations.py:123
+#: c3nav/mapdata/models/locations.py:101 c3nav/mapdata/models/locations.py:132
msgid "can describe"
msgstr "beschreibend"
-#: c3nav/mapdata/models/locations.py:98 c3nav/mapdata/models/locations.py:124
+#: c3nav/mapdata/models/locations.py:102 c3nav/mapdata/models/locations.py:133
msgid "icon"
msgstr "Icon"
-#: c3nav/mapdata/models/locations.py:98
+#: c3nav/mapdata/models/locations.py:102
msgid "any material icons name"
msgstr "name eines material icons"
-#: c3nav/mapdata/models/locations.py:122
+#: c3nav/mapdata/models/locations.py:131
msgid "searchable"
msgstr "suchbar"
-#: c3nav/mapdata/models/locations.py:162 c3nav/mapdata/models/locations.py:323
+#: c3nav/mapdata/models/locations.py:171 c3nav/mapdata/models/locations.py:332
msgid "Location Groups"
msgstr "Ortgruppen"
-#: c3nav/mapdata/models/locations.py:164 c3nav/mapdata/models/locations.py:313
+#: c3nav/mapdata/models/locations.py:173 c3nav/mapdata/models/locations.py:322
msgid "label settings"
msgstr "Labeleinstellungen"
-#: c3nav/mapdata/models/locations.py:165
+#: c3nav/mapdata/models/locations.py:174
msgid "Label override"
msgstr "Label überschreiben"
-#: c3nav/mapdata/models/locations.py:211
+#: c3nav/mapdata/models/locations.py:220
msgid "Grid Squares"
msgstr "Planquadrate"
-#: c3nav/mapdata/models/locations.py:211 c3nav/mapdata/utils/locations.py:329
+#: c3nav/mapdata/models/locations.py:220 c3nav/mapdata/utils/locations.py:335
msgid "Grid Square"
msgstr "Planquadrat"
-#: c3nav/mapdata/models/locations.py:254 c3nav/mapdata/models/source.py:15
+#: c3nav/mapdata/models/locations.py:263 c3nav/mapdata/models/source.py:15
msgid "Name"
msgstr "Name"
-#: c3nav/mapdata/models/locations.py:255
+#: c3nav/mapdata/models/locations.py:264
msgid "single selection"
msgstr "nur eine Auswahl möglich"
-#: c3nav/mapdata/models/locations.py:258
+#: c3nav/mapdata/models/locations.py:267
msgid "Help text"
msgstr "Hilfehinweis"
-#: c3nav/mapdata/models/locations.py:259
+#: c3nav/mapdata/models/locations.py:268
msgid "allow levels"
msgstr "bei Etagen erlauben"
-#: c3nav/mapdata/models/locations.py:260
+#: c3nav/mapdata/models/locations.py:269
msgid "allow spaces"
msgstr "bei Räumen erlauben"
-#: c3nav/mapdata/models/locations.py:261
+#: c3nav/mapdata/models/locations.py:270
msgid "allow areas"
msgstr "bei Bereichen erlauben"
-#: c3nav/mapdata/models/locations.py:262
+#: c3nav/mapdata/models/locations.py:271
msgid "allow pois"
msgstr "bei POI erlauben"
-#: c3nav/mapdata/models/locations.py:270
+#: c3nav/mapdata/models/locations.py:279
msgid "Location Group Category"
msgstr "Ortgruppenkategorie"
-#: c3nav/mapdata/models/locations.py:271
+#: c3nav/mapdata/models/locations.py:280
msgid "Location Group Categories"
msgstr "Ortgruppenkategorien"
-#: c3nav/mapdata/models/locations.py:309 c3nav/mapdata/models/locations.py:344
+#: c3nav/mapdata/models/locations.py:318 c3nav/mapdata/models/locations.py:353
msgid "Category"
msgstr "Kategorie"
-#: c3nav/mapdata/models/locations.py:311
+#: c3nav/mapdata/models/locations.py:320
msgid "hierarchy"
msgstr "Hierarchie"
-#: c3nav/mapdata/models/locations.py:314
+#: c3nav/mapdata/models/locations.py:323
msgid "unless location specifies otherwise"
msgstr "kann von Orten überschrieben werden"
-#: c3nav/mapdata/models/locations.py:315
+#: c3nav/mapdata/models/locations.py:324
msgid "for missing locations"
msgstr "für fehlende Orte"
-#: c3nav/mapdata/models/locations.py:316
+#: c3nav/mapdata/models/locations.py:325
msgid "can be used when reporting a missing location"
msgstr "kann beim melden eines fehlenden Ortges genutzt werden"
-#: c3nav/mapdata/models/locations.py:317
+#: c3nav/mapdata/models/locations.py:326
msgid "background color"
msgstr "Hintergrundfarbe"
-#: c3nav/mapdata/models/locations.py:322
+#: c3nav/mapdata/models/locations.py:331
msgid "Location Group"
msgstr "Ortgruppe"
-#: c3nav/mapdata/models/locations.py:346 c3nav/mapdata/models/locations.py:361
+#: c3nav/mapdata/models/locations.py:355 c3nav/mapdata/models/locations.py:370
msgid "color"
msgstr "Farbe"
-#: c3nav/mapdata/models/locations.py:347
+#: c3nav/mapdata/models/locations.py:356
msgid "priority"
msgstr "Priorität"
-#: c3nav/mapdata/models/locations.py:357
+#: c3nav/mapdata/models/locations.py:366
msgid "search"
msgstr "suchen"
-#: c3nav/mapdata/models/locations.py:359
+#: c3nav/mapdata/models/locations.py:368
msgid "describe"
msgstr "beschreiben"
-#: c3nav/mapdata/models/locations.py:363
+#: c3nav/mapdata/models/locations.py:372
msgid "internal"
msgstr "intern"
-#: c3nav/mapdata/models/locations.py:380
+#: c3nav/mapdata/models/locations.py:389
#, python-brace-format
msgid "{category_title}, {num_locations}"
msgstr "{category_title}, {num_locations}"
-#: c3nav/mapdata/models/locations.py:382
+#: c3nav/mapdata/models/locations.py:391
#, python-format
msgid "%(num)d location"
msgid_plural "%(num)d locations"
msgstr[0] "%(num)d Ort"
msgstr[1] "%(num)d Orte"
-#: c3nav/mapdata/models/locations.py:405
+#: c3nav/mapdata/models/locations.py:414
msgid "target"
msgstr "Ziel"
-#: c3nav/mapdata/models/locations.py:424
+#: c3nav/mapdata/models/locations.py:433
msgid "min zoom"
msgstr "Mindestzoom"
-#: c3nav/mapdata/models/locations.py:427
+#: c3nav/mapdata/models/locations.py:436
msgid "max zoom"
msgstr "Maximalzoom"
-#: c3nav/mapdata/models/locations.py:430
+#: c3nav/mapdata/models/locations.py:439
msgid "font size"
msgstr "Schriftgröße"
-#: c3nav/mapdata/models/locations.py:446 c3nav/mapdata/models/locations.py:447
+#: c3nav/mapdata/models/locations.py:455 c3nav/mapdata/models/locations.py:456
msgid "Label Settings"
msgstr "Labeleinstellungen"
-#: c3nav/mapdata/models/report.py:58
-msgid "location issue"
-msgstr "Ortfehler"
+#: c3nav/mapdata/models/locations.py:462
+msgid "position secret"
+msgstr "position secret"
-#: c3nav/mapdata/models/report.py:59
-msgid "missing location"
-msgstr "fehlender Ort"
+#: c3nav/mapdata/models/locations.py:465
+msgid "Dynamic location"
+msgstr "Dynamischer Ort."
-#: c3nav/mapdata/models/report.py:60
-msgid "route issue"
-msgstr "Routenfehler"
+#: c3nav/mapdata/models/locations.py:466
+msgid "Dynamic locations"
+msgstr "Dynamische Orte."
-#: c3nav/mapdata/models/report.py:63
-msgid "category"
-msgstr "Kategorie"
+#: c3nav/mapdata/models/locations.py:496
+msgid "name"
+msgstr "Name"
-#: c3nav/mapdata/models/report.py:66
-msgid "last_update"
-msgstr "letzte Anderung"
+#: c3nav/mapdata/models/locations.py:498
+msgid "last location update"
+msgstr "Letzte Ortänderung"
-#: c3nav/mapdata/models/report.py:67
-msgid "title"
-msgstr "Titel"
-
-#: c3nav/mapdata/models/report.py:68
-msgid "a short title for your report"
-msgstr "ein kurzer Titel für deine Meldung"
-
-#: c3nav/mapdata/models/report.py:70
-msgid "tell us precisely what's wrong"
-msgstr "Sag uns im Detail was falsch ist"
-
-#: c3nav/mapdata/models/report.py:74
+#: c3nav/mapdata/models/locations.py:499 c3nav/mapdata/models/report.py:44
msgid "location"
msgstr "Ort"
-#: c3nav/mapdata/models/report.py:75
+#: c3nav/mapdata/models/locations.py:500
+msgid "api secret"
+msgstr "API secret"
+
+#: c3nav/mapdata/models/locations.py:505 c3nav/mapdata/models/locations.py:506
+msgid "Dynamic position"
+msgstr "Dynamische Position"
+
+#: c3nav/mapdata/models/report.py:28
+msgid "location issue"
+msgstr "Ortfehler"
+
+#: c3nav/mapdata/models/report.py:29
+msgid "missing location"
+msgstr "fehlender Ort"
+
+#: c3nav/mapdata/models/report.py:30
+msgid "route issue"
+msgstr "Routenfehler"
+
+#: c3nav/mapdata/models/report.py:33
+msgid "category"
+msgstr "Kategorie"
+
+#: c3nav/mapdata/models/report.py:36
+msgid "last_update"
+msgstr "letzte Anderung"
+
+#: c3nav/mapdata/models/report.py:37
+msgid "title"
+msgstr "Titel"
+
+#: c3nav/mapdata/models/report.py:38
+msgid "a short title for your report"
+msgstr "ein kurzer Titel für deine Meldung"
+
+#: c3nav/mapdata/models/report.py:40
+msgid "tell us precisely what's wrong"
+msgstr "Sag uns im Detail was falsch ist"
+
+#: c3nav/mapdata/models/report.py:45
msgid "coordinates"
msgstr "Koordinaten"
-#: c3nav/mapdata/models/report.py:76
+#: c3nav/mapdata/models/report.py:46
msgid "origin"
msgstr "Start"
-#: c3nav/mapdata/models/report.py:77
+#: c3nav/mapdata/models/report.py:47
msgid "destination"
msgstr "Ziel"
-#: c3nav/mapdata/models/report.py:78
+#: c3nav/mapdata/models/report.py:48
msgid "route options"
msgstr "Routenoptionen"
-#: c3nav/mapdata/models/report.py:80
+#: c3nav/mapdata/models/report.py:50
msgid "new location title"
msgstr "Neuer Ortstitel"
-#: c3nav/mapdata/models/report.py:81
+#: c3nav/mapdata/models/report.py:51
msgid "you have to supply a title in at least one language"
msgstr "Du musst einen Titel in mindestens einer Sprache angeben"
-#: c3nav/mapdata/models/report.py:82
+#: c3nav/mapdata/models/report.py:52
msgid "location groups"
msgstr "Ortgruppen"
-#: c3nav/mapdata/models/report.py:84
+#: c3nav/mapdata/models/report.py:54
msgid "select all groups that apply, if any"
msgstr "wähle zutreffende Gruppen aus"
-#: c3nav/mapdata/models/report.py:92
+#: c3nav/mapdata/models/report.py:62
#: c3nav/site/templates/site/report_detail.html:7
msgid "Report"
msgstr "Meldung"
-#: c3nav/mapdata/models/report.py:93
+#: c3nav/mapdata/models/report.py:63
msgid "Reports"
msgstr "Meldungen"
-#: c3nav/mapdata/models/report.py:168
-msgid "public"
-msgstr "öffentlich"
+#: c3nav/mapdata/models/report.py:175
+msgid "comment is public"
+msgstr "Kommentar ist öffentlich"
-#: c3nav/mapdata/models/report.py:171
+#: c3nav/mapdata/models/report.py:178
msgid "Report update"
msgstr "Meldungsupdate"
-#: c3nav/mapdata/models/report.py:172
+#: c3nav/mapdata/models/report.py:179
msgid "Report updates"
msgstr "Meldungsupdates"
@@ -2442,60 +2474,60 @@ msgstr[1] "%d Kartenänderungen verarbeitet."
msgid "Last processed update: %(date)s (#%(id)d)"
msgstr "Letztes verarbeitetes Update: %(date)s (#%(id)d)"
-#: c3nav/mapdata/utils/locations.py:308
+#: c3nav/mapdata/utils/locations.py:314
msgid "Coordinates"
msgstr "Koordinaten"
-#: c3nav/mapdata/utils/locations.py:330
+#: c3nav/mapdata/utils/locations.py:336
msgid "Near Area"
msgstr "Naher Bereich"
-#: c3nav/mapdata/utils/locations.py:336
+#: c3nav/mapdata/utils/locations.py:342
msgid "Near POI"
msgstr "Naher POI"
-#: c3nav/mapdata/utils/locations.py:342
+#: c3nav/mapdata/utils/locations.py:348
msgid "X Coordinate"
msgstr "X-Koordinate"
-#: c3nav/mapdata/utils/locations.py:343
+#: c3nav/mapdata/utils/locations.py:349
msgid "Y Coordinate"
msgstr "Y-Koordinate"
-#: c3nav/mapdata/utils/locations.py:344
+#: c3nav/mapdata/utils/locations.py:350
msgid "Altitude"
msgstr "Höhe"
-#: c3nav/mapdata/utils/locations.py:346
+#: c3nav/mapdata/utils/locations.py:352
msgid "Subtitle"
msgstr "Untertitel"
-#: c3nav/mapdata/utils/locations.py:395
+#: c3nav/mapdata/utils/locations.py:401
#, python-format
msgid "In %(level)s"
msgstr "In %(level)s"
-#: c3nav/mapdata/utils/locations.py:401
+#: c3nav/mapdata/utils/locations.py:407
#, python-format
msgid "Near %(poi)s"
msgstr "Nahe %(poi)s"
-#: c3nav/mapdata/utils/locations.py:405
+#: c3nav/mapdata/utils/locations.py:411
#, python-format
msgid "near %(area)s"
msgstr "nahe %(area)s"
-#: c3nav/mapdata/utils/locations.py:407
+#: c3nav/mapdata/utils/locations.py:413
#, python-format
msgid "In %(area)s"
msgstr "In %(area)s"
-#: c3nav/mapdata/utils/locations.py:411
+#: c3nav/mapdata/utils/locations.py:417
#, python-format
msgid "Near %(area)s"
msgstr "Nahe %(area)s"
-#: c3nav/mapdata/utils/locations.py:413
+#: c3nav/mapdata/utils/locations.py:419
#, python-format
msgid "In %(space)s"
msgstr "In %(space)s"
@@ -2539,45 +2571,45 @@ msgstr "Unbekannter Startort."
msgid "Unknown destination."
msgstr "Unbekannter Zielort."
-#: c3nav/routing/locator.py:208
+#: c3nav/routing/locator.py:213
msgid "Invalid Scan. Scans list list not a list."
msgstr "Invalider Scan. Scan List Liste ist keine Liste."
-#: c3nav/routing/locator.py:214
+#: c3nav/routing/locator.py:219
msgid "Invalid Scan. Scan not a list."
msgstr "Invalider Scan. Scan is keine Liste."
-#: c3nav/routing/locator.py:227
+#: c3nav/routing/locator.py:232
msgid "Invalid Scan. Scan value not a dictionary."
msgstr "Invalider Scan. Scan wert ist kein Dictonary."
-#: c3nav/routing/locator.py:230
+#: c3nav/routing/locator.py:235
msgid "Invalid Scan. Missing or forbidden keys."
msgstr "Invalider Scan. Fehlender oder Falscher Key."
-#: c3nav/routing/locator.py:232
+#: c3nav/routing/locator.py:237
msgid "Invalid Scan. BSSID not a String."
msgstr "Invalider Scan. BSSID ist kein String."
-#: c3nav/routing/locator.py:235
+#: c3nav/routing/locator.py:240
msgid "Invalid Scan. Invalid BSSID."
msgstr "Invalider Scan. Ungültige BSSID."
-#: c3nav/routing/locator.py:237
+#: c3nav/routing/locator.py:242
msgid "Invalid Scan. Invalid RSSI/Level."
msgstr "Invalider Scan. Ungültiger RSSI."
-#: c3nav/routing/locator.py:239
+#: c3nav/routing/locator.py:244
msgid "Invalid Scan. Not an allowed frequency."
msgstr "Invalider Scan. Unerlaubte Frequenz."
-#: c3nav/routing/locator.py:241
+#: c3nav/routing/locator.py:246
msgid "Invalid Scan. Invalid last timestamp."
msgstr "Invalider Scan. Letzter Zeitstempel ungültig."
#: 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:189
+#: c3nav/site/templates/site/fragment_report_meta.html:29
+#: c3nav/site/templates/site/map.html:196
msgid "Route options"
msgstr "Routenoptionen"
@@ -2669,14 +2701,27 @@ msgstr "einige Wegtypen vermieden"
msgid "default options"
msgstr "Standardoptionen"
-#: c3nav/settings.py:304
+#: c3nav/settings.py:308
msgid "English"
msgstr "Englisch"
-#: c3nav/settings.py:305
+#: c3nav/settings.py:309
msgid "German"
msgstr "Deutsch"
+#: c3nav/site/forms.py:30
+msgid "change status"
+msgstr "Status ändern"
+
+#: c3nav/site/forms.py:32
+msgid "don't change"
+msgstr "nicht ändern"
+
+#: c3nav/site/forms.py:34 c3nav/site/templates/site/report_detail.html:17
+#: c3nav/site/templates/site/report_list.html:30
+msgid "closed"
+msgstr "geschlossen"
+
#: c3nav/site/models.py:15
msgid "active until"
msgstr "aktiv bis"
@@ -2794,23 +2839,42 @@ msgstr "Du hast Meldungen eingereicht."
msgid "Show your reports"
msgstr "Deine Meldungen anzeigen"
+#: c3nav/site/templates/site/account.html:47
+msgid "You can create custom positions."
+msgstr "Du kannst benutzerdefinierte Positionen erstellen."
+
+#: c3nav/site/templates/site/account.html:50
+msgid "Manage your positions"
+msgstr "Positionen verwalten"
+
#: 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
+#: c3nav/site/templates/site/fragment_report_meta.html:15
+#: c3nav/site/templates/site/map.html:216
+msgid "open in c3nav"
+msgstr "in c3nav öffnen"
+
+#: c3nav/site/templates/site/fragment_report_meta.html:8
+#: c3nav/site/templates/site/fragment_report_meta.html:17
+msgid "open in editor"
+msgstr "Im Editor öffnen"
+
+#: c3nav/site/templates/site/fragment_report_meta.html:12
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
+#: c3nav/site/templates/site/fragment_report_meta.html:21
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
+#: c3nav/site/templates/site/fragment_report_meta.html:23
msgid "Origin"
msgstr "Start"
-#: c3nav/site/templates/site/fragment_report_meta.html:14
+#: c3nav/site/templates/site/fragment_report_meta.html:26
msgid "Destination"
msgstr "Ziel"
@@ -2842,84 +2906,86 @@ msgstr "Diesen Punkt zeigen"
msgid "Show nearby locations"
msgstr "Nahegelegene Orte zeigen"
-#: c3nav/site/templates/site/map.html:50
+#: c3nav/site/templates/site/map.html:48 c3nav/site/templates/site/map.html:74
+#: c3nav/site/templates/site/map.html:172
+msgid "Report missing location"
+msgstr "Fehlenden Ort melden"
+
+#: c3nav/site/templates/site/map.html:56
msgid "Select"
msgstr "Auswählen"
-#: c3nav/site/templates/site/map.html:54 c3nav/site/templates/site/map.html:73
-#: c3nav/site/templates/site/map.html:116
+#: c3nav/site/templates/site/map.html:60 c3nav/site/templates/site/map.html:79
+#: c3nav/site/templates/site/map.html:123
msgid "Share"
msgstr "Teilen"
-#: c3nav/site/templates/site/map.html:58
+#: c3nav/site/templates/site/map.html:64
msgid "from here"
msgstr "von hier"
-#: c3nav/site/templates/site/map.html:59
+#: c3nav/site/templates/site/map.html:65
msgid "to here"
msgstr "hierhin"
-#: c3nav/site/templates/site/map.html:64 c3nav/site/templates/site/map.html:161
-#: c3nav/site/templates/site/map.html:182
+#: c3nav/site/templates/site/map.html:70 c3nav/site/templates/site/map.html:168
+#: c3nav/site/templates/site/map.html:189
#: c3nav/site/templates/site/report_create.html:6
msgid "Report issue"
msgstr "Fehler melden"
-#: c3nav/site/templates/site/map.html:68 c3nav/site/templates/site/map.html:165
-msgid "Report missing location"
-msgstr "Fehlenden Ort melden"
-
-#: c3nav/site/templates/site/map.html:77
+#: c3nav/site/templates/site/map.html:83
msgid "share"
msgstr "Teilen"
-#: c3nav/site/templates/site/map.html:78
+#: c3nav/site/templates/site/map.html:84
msgid "create shortcut"
msgstr "Verknüpfung anlegen"
-#: c3nav/site/templates/site/map.html:82
+#: c3nav/site/templates/site/map.html:88
msgid "Wifi-based location"
msgstr "WLAN-basierte Ortung"
-#: c3nav/site/templates/site/map.html:83
+#: c3nav/site/templates/site/map.html:89
msgid "Get the c3nav app for Android to see your location on the map."
msgstr ""
"Hole dir die c3nav-App für Android um deine Position auf der Karte zu sehen."
-#: c3nav/site/templates/site/map.html:86
+#: c3nav/site/templates/site/map.html:92
msgid "Download APK"
msgstr "APK herunterladen"
-#: c3nav/site/templates/site/map.html:96 c3nav/site/templates/site/map.html:103
+#: c3nav/site/templates/site/map.html:102
+#: c3nav/site/templates/site/map.html:109
msgid "Search any location…"
msgstr "Suche einen beliebigen Ort…"
-#: c3nav/site/templates/site/map.html:120
+#: c3nav/site/templates/site/map.html:127
msgid "Route"
msgstr "Route"
-#: c3nav/site/templates/site/map.html:132
-#: c3nav/site/templates/site/map.html:142
+#: c3nav/site/templates/site/map.html:139
+#: c3nav/site/templates/site/map.html:149
msgid "Swap"
msgstr "Vertauschen"
-#: c3nav/site/templates/site/map.html:136
+#: c3nav/site/templates/site/map.html:143
msgid "Close"
msgstr "Schließen"
-#: c3nav/site/templates/site/map.html:169
+#: c3nav/site/templates/site/map.html:176
msgid "Open in Editor"
msgstr "Im Editor öffnen"
-#: c3nav/site/templates/site/map.html:194
+#: c3nav/site/templates/site/map.html:201
msgid "Save and reroute"
msgstr "Speichern und neu routen"
-#: c3nav/site/templates/site/map.html:195
+#: c3nav/site/templates/site/map.html:202
msgid "Just reroute"
msgstr "Nur neu routen"
-#: c3nav/site/templates/site/map.html:204
+#: c3nav/site/templates/site/map.html:211
#, python-format
msgid ""
"Get the c3nav Android app on Google Play oder downloade "
"die APK!"
-#: c3nav/site/templates/site/map.html:209
-msgid "open in c3nav"
-msgstr "in c3nav öffnen"
+#: c3nav/site/templates/site/position_create.html:6
+#: c3nav/site/templates/site/position_list.html:16
+msgid "Create position"
+msgstr "Position erstellen"
+#: c3nav/site/templates/site/position_create.html:13
#: c3nav/site/templates/site/report_create.html:13
+#: c3nav/site/templates/site/report_detail.html:79
msgid "Submit"
msgstr "Absenden"
-#: c3nav/site/templates/site/report_detail.html:13
-#: c3nav/site/templates/site/report_list.html:30
-msgid "closed"
-msgstr "geschlossen"
+#: c3nav/site/templates/site/position_detail.html:7
+msgid "Position:"
+msgstr "Position:"
-#: c3nav/site/templates/site/report_detail.html:17
+#: c3nav/site/templates/site/position_detail.html:11
+msgid "Secret"
+msgstr "Secret"
+
+#: c3nav/site/templates/site/position_detail.html:24
+msgid "reset secret"
+msgstr "Secret zurücksetzen"
+
+#: c3nav/site/templates/site/position_detail.html:25
+msgid "reset API secret"
+msgstr "API Secret zurücksetzen"
+
+#: c3nav/site/templates/site/position_detail.html:26
+msgid "delete this position"
+msgstr "diese Position löschen"
+
+#: c3nav/site/templates/site/position_detail.html:27
+msgid "Update position"
+msgstr "Position speichern"
+
+#: c3nav/site/templates/site/position_list.html:7
+msgid "Your positions"
+msgstr "Deine Positionsn"
+
+#: c3nav/site/templates/site/report_detail.html:9
+#: c3nav/site/templates/site/report_list.html:9
+msgid "show all reports"
+msgstr "alle Meldungen anzeigen"
+
+#: c3nav/site/templates/site/report_detail.html:10
+#: c3nav/site/templates/site/report_list.html:12
+msgid "show open reports"
+msgstr "offene Meldungen anzeigen"
+
+#: c3nav/site/templates/site/report_detail.html:21
msgid "by"
msgstr "von"
-#: c3nav/site/templates/site/report_detail.html:19
+#: c3nav/site/templates/site/report_detail.html:23
msgid "anonymous submission"
msgstr "anonyme Meldung"
-#: c3nav/site/templates/site/report_detail.html:25
+#: c3nav/site/templates/site/report_detail.html:29
msgid "public URL to this report"
msgstr "öffentliche URL zu dieser Meldung"
-#: c3nav/site/templates/site/report_detail.html:39
+#: c3nav/site/templates/site/report_detail.html:43
msgid "(none)"
msgstr "(keine)"
+#: c3nav/site/templates/site/report_detail.html:57
+msgid "Issue was opened."
+msgstr "Meldung wurde geöffnet."
+
+#: c3nav/site/templates/site/report_detail.html:59
+msgid "Issue was closed."
+msgstr "Meldung wurde geschlossen."
+
+#: c3nav/site/templates/site/report_detail.html:66
+msgid "(public)"
+msgstr "(öffentlich)"
+
+#: c3nav/site/templates/site/report_detail.html:77
+msgid "Update issue"
+msgstr "Meldung updaten"
+
#: c3nav/site/templates/site/report_list.html:8
msgid "Open reports"
msgstr "Offene Meldungen"
-#: c3nav/site/templates/site/report_list.html:9
-msgid "show all reports"
-msgstr "alle Meldungen anzeigen"
-
#: c3nav/site/templates/site/report_list.html:11
msgid "All reports"
msgstr "Alle Meldungen"
-#: c3nav/site/templates/site/report_list.html:12
-msgid "show open reports"
-msgstr "offene Meldungen anzeigen"
-
#: c3nav/site/templates/site/report_list.html:20
msgid "State"
msgstr "Status"
-#: c3nav/site/views.py:76 c3nav/site/views.py:326
+#: c3nav/site/views.py:78 c3nav/site/views.py:331
msgid "You need to log in to unlock areas."
msgstr "Du musst dich anmelden um Bereiche freizuschalten."
-#: c3nav/site/views.py:212
+#: c3nav/site/views.py:217
msgid "Areas could not be unlocked because the token has expired."
msgstr ""
"Zugangserlaubnis konnte nicht gewährt werden weil der Code abgelaufen ist."
-#: c3nav/site/views.py:255
+#: c3nav/site/views.py:260
msgid "account creation is currently disabled."
msgstr "Benutzerregistrierung ist momentan deaktiviert."
-#: c3nav/site/views.py:319
+#: c3nav/site/views.py:324
msgid "This token does not exist or was already redeemed."
msgstr "Dieser Code existiert nicht oder wurde bereits eingelöst."
-#: c3nav/site/views.py:339
+#: c3nav/site/views.py:344
msgid "Unlock area"
msgid_plural "Unlock areas"
msgstr[0] "Bereich freischalten"
msgstr[1] "Bereiche freischalten"
-#: c3nav/site/views.py:340
+#: c3nav/site/views.py:345
msgid "You have been invited to unlock the following area:"
msgid_plural "You have been invited to unlock the following areas:"
msgstr[0] "Du wurdest eingeladen, den folgenden Bereich freizuschalten:"
msgstr[1] "Du wurdest eingeladen, die folgenden Bereiche freizuschalten:"
-#: c3nav/site/views.py:412
+#: c3nav/site/views.py:418
msgid "Your report was submitted."
msgstr "Deine Meldung wurde abgesendet."
-#: c3nav/site/views.py:415
+#: c3nav/site/views.py:421
msgid "You can keep track of it from your user dashboard."
msgstr "Du kannst sie in deinerm Benutzerdashboard verfolgen."
-#: c3nav/site/views.py:417
+#: c3nav/site/views.py:423
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."
+#: c3nav/site/views.py:474
+msgid "Report updated."
+msgstr "Meldung aktualisiert."
+
+#: c3nav/site/views.py:498
+msgid "You can't create more than 20 positions."
+msgstr "Du kannst nicht mehr als 20 Positionen erstellen."
+
+#: c3nav/site/views.py:507
+msgid "Position created."
+msgstr "Position erstellt."
+
+#: c3nav/site/views.py:527
+msgid "Position deleted."
+msgstr "Position gelöscht."
+
+#: c3nav/site/views.py:539
+msgid "Position updated."
+msgstr "Position geändert."
+
#~ msgid "Coming soon"
#~ msgstr "Coming soon"
diff --git a/src/c3nav/mapdata/migrations/0082_dynamiclocation_position.py b/src/c3nav/mapdata/migrations/0082_dynamiclocation_position.py
new file mode 100644
index 00000000..2ef2ee48
--- /dev/null
+++ b/src/c3nav/mapdata/migrations/0082_dynamiclocation_position.py
@@ -0,0 +1,56 @@
+# Generated by Django 2.2.8 on 2019-12-27 12:51
+
+import c3nav.mapdata.fields
+import c3nav.mapdata.models.locations
+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', '0081_auto_20191225_1015'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Position',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=32, verbose_name='name')),
+ ('secret', models.CharField(default=c3nav.mapdata.models.locations.get_position_secret, max_length=32, unique=True, verbose_name='secret')),
+ ('last_location_update', models.DateTimeField(null=True, verbose_name='last location update')),
+ ('location_id', models.CharField(max_length=48, null=True, verbose_name='location')),
+ ('api_secret', models.CharField(default=c3nav.mapdata.models.locations.get_position_api_secret, max_length=64, verbose_name='api secret')),
+ ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dynamic_positions', to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': 'Dynamic position',
+ 'verbose_name_plural': 'Dynamic position',
+ 'default_related_name': 'dynamic_positions',
+ },
+ ),
+ migrations.CreateModel(
+ name='DynamicLocation',
+ fields=[
+ ('locationslug_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='dynamic_locations', serialize=False, to='mapdata.LocationSlug')),
+ ('title', c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, fallback_value='{model} {pk}', plural_name='titles', verbose_name='Title')),
+ ('can_search', models.BooleanField(default=True, verbose_name='can be searched')),
+ ('can_describe', models.BooleanField(default=True, verbose_name='can describe')),
+ ('icon', models.CharField(blank=True, help_text='any material icons name', max_length=32, null=True, verbose_name='icon')),
+ ('label_override', c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, plural_name='label_overrides', verbose_name='Label override')),
+ ('position_secret', models.CharField(blank=True, max_length=32, null=True, verbose_name='position secret')),
+ ('access_restriction', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='dynamic_locations', to='mapdata.AccessRestriction', verbose_name='Access Restriction')),
+ ('groups', models.ManyToManyField(blank=True, related_name='dynamic_locations', to='mapdata.LocationGroup', verbose_name='Location Groups')),
+ ('label_settings', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='dynamic_locations', to='mapdata.LabelSettings', verbose_name='label settings')),
+ ],
+ options={
+ 'verbose_name': 'Dynamic location',
+ 'verbose_name_plural': 'Dynamic locations',
+ 'default_related_name': 'dynamic_locations',
+ },
+ bases=('mapdata.locationslug', models.Model),
+ ),
+ ]
diff --git a/src/c3nav/mapdata/models/locations.py b/src/c3nav/mapdata/models/locations.py
index 5174c949..b0b492e7 100644
--- a/src/c3nav/mapdata/models/locations.py
+++ b/src/c3nav/mapdata/models/locations.py
@@ -1,11 +1,14 @@
+import string
from contextlib import suppress
from decimal import Decimal
from operator import attrgetter
+from django.conf import settings
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
from django.db import models
from django.db.models import FieldDoesNotExist, Prefetch
from django.urls import reverse
+from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
@@ -15,6 +18,7 @@ from c3nav.mapdata.fields import I18nField
from c3nav.mapdata.grid import grid
from c3nav.mapdata.models.access import AccessRestrictionMixin
from c3nav.mapdata.models.base import SerializableMixin, TitledMixin
+from c3nav.mapdata.utils.fields import LocationById
from c3nav.mapdata.utils.models import get_submodels
@@ -452,3 +456,52 @@ class LabelSettings(SerializableMixin, models.Model):
verbose_name_plural = _('Label Settings')
default_related_name = 'labelsettings'
ordering = ('min_zoom', '-font_size')
+
+
+class DynamicLocation(SpecificLocation, models.Model):
+ position_secret = models.CharField(_('position secret'), max_length=32, null=True, blank=True)
+
+ class Meta:
+ verbose_name = _('Dynamic location')
+ verbose_name_plural = _('Dynamic locations')
+ default_related_name = 'dynamic_locations'
+
+ """
+ def _serialize(self, **kwargs):
+ result = super()._serialize(**kwargs)
+ return result
+
+ @property
+ def grid_square(self):
+ return grid.get_squares_for_bounds(self.geometry.bounds) or ''
+
+ def details_display(self, editor_url=True, **kwargs):
+ result = super().details_display(**kwargs)
+ if editor_url:
+ result['editor_url'] = reverse('editor.areas.edit', kwargs={'space': self.space_id, 'pk': self.pk})
+ return result
+ """
+
+
+def get_position_secret():
+ return get_random_string(32, string.ascii_letters+string.digits)
+
+
+def get_position_api_secret():
+ return get_random_string(64, string.ascii_letters+string.digits)
+
+
+class Position(models.Model):
+ owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
+ name = models.CharField(_('name'), max_length=32)
+ secret = models.CharField(_('secret'), unique=True, max_length=32, default=get_position_secret)
+ last_location_update = models.DateTimeField(_('last location update'), null=True)
+ location_id = models.CharField(_('location'), null=True, max_length=48)
+ api_secret = models.CharField(_('api secret'), max_length=64, default=get_position_api_secret)
+
+ coordinates = LocationById()
+
+ class Meta:
+ verbose_name = _('Dynamic position')
+ verbose_name_plural = _('Dynamic position')
+ default_related_name = 'dynamic_positions'
diff --git a/src/c3nav/mapdata/models/report.py b/src/c3nav/mapdata/models/report.py
index ce63a9c7..0aa73ca2 100644
--- a/src/c3nav/mapdata/models/report.py
+++ b/src/c3nav/mapdata/models/report.py
@@ -3,7 +3,6 @@ import string
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.cache import cache
-from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models import Q
from django.urls import reverse
@@ -15,7 +14,7 @@ from c3nav.mapdata.fields import I18nField
from c3nav.mapdata.models.geometry.level import LevelGeometryMixin
from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
from c3nav.mapdata.models.locations import SpecificLocation
-from c3nav.mapdata.utils.locations import get_location_by_id_for_request
+from c3nav.mapdata.utils.fields import LocationById
from c3nav.mapdata.utils.models import get_submodels
from c3nav.site.tasks import send_report_notification
@@ -24,39 +23,6 @@ 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')),
diff --git a/src/c3nav/mapdata/utils/fields.py b/src/c3nav/mapdata/utils/fields.py
new file mode 100644
index 00000000..9cb19d14
--- /dev/null
+++ b/src/c3nav/mapdata/utils/fields.py
@@ -0,0 +1,35 @@
+from django.core.exceptions import ObjectDoesNotExist
+
+
+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
+
+ from c3nav.mapdata.utils.locations import get_location_by_id_for_request
+ 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)
diff --git a/src/c3nav/site/forms.py b/src/c3nav/site/forms.py
index 9481c9fc..45489819 100644
--- a/src/c3nav/site/forms.py
+++ b/src/c3nav/site/forms.py
@@ -3,6 +3,7 @@ from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _
from c3nav.mapdata.forms import I18nModelFormMixin
+from c3nav.mapdata.models.locations import Position
from c3nav.mapdata.models.report import Report, ReportUpdate
@@ -46,3 +47,9 @@ class ReportUpdateForm(ModelForm):
class Meta:
model = ReportUpdate
fields = ['open', 'comment', 'public']
+
+
+class PositionForm(ModelForm):
+ class Meta:
+ model = Position
+ fields = ['name']
diff --git a/src/c3nav/site/templates/site/account.html b/src/c3nav/site/templates/site/account.html
index 574ced43..24737cb4 100644
--- a/src/c3nav/site/templates/site/account.html
+++ b/src/c3nav/site/templates/site/account.html
@@ -41,6 +41,15 @@
{% endif %}
+
+
+
+ {% trans 'You can create custom positions.' %}
+
+
+ {% trans 'Manage your positions' %}
+
+
{% trans 'Log out' %}
diff --git a/src/c3nav/site/templates/site/position_create.html b/src/c3nav/site/templates/site/position_create.html
new file mode 100644
index 00000000..0da7b8f2
--- /dev/null
+++ b/src/c3nav/site/templates/site/position_create.html
@@ -0,0 +1,16 @@
+{% extends 'site/base.html' %}
+{% load i18n %}
+
+{% block content %}
+
+ {% trans 'Create position' %}
+ {% include 'site/fragment_messages.html' %}
+ « {% trans 'back to overview' %}
+
+
+
+{% endblock %}
diff --git a/src/c3nav/site/templates/site/position_detail.html b/src/c3nav/site/templates/site/position_detail.html
new file mode 100644
index 00000000..9ca3d8d9
--- /dev/null
+++ b/src/c3nav/site/templates/site/position_detail.html
@@ -0,0 +1,30 @@
+{% extends 'site/base.html' %}
+{% load i18n %}
+
+{% block content %}
+
+ {% include 'site/fragment_messages.html' %}
+ {% trans 'Position:' %} {{ position.name }}
+ « {% trans 'back to overview' %}
+
+
+ {% trans 'Secret' %}:
+ {{ position.secret }}
+
+
+ {% trans 'API secret' %}:
+ {{ position.api_secret }}
+
+
+
+
+
+
+{% endblock %}
diff --git a/src/c3nav/site/templates/site/position_list.html b/src/c3nav/site/templates/site/position_list.html
new file mode 100644
index 00000000..ac8d4609
--- /dev/null
+++ b/src/c3nav/site/templates/site/position_list.html
@@ -0,0 +1,18 @@
+{% extends 'site/base.html' %}
+{% load i18n %}
+
+{% block content %}
+
+ {% include 'site/fragment_messages.html' %}
+ {% trans 'Your positions' %}
+ (still work in progress, stay tuned for more information)
+
+
+
+ {% trans 'Create position' %}
+
+{% endblock %}
diff --git a/src/c3nav/site/urls.py b/src/c3nav/site/urls.py
index 5f102c9a..1e957aa4 100644
--- a/src/c3nav/site/urls.py
+++ b/src/c3nav/site/urls.py
@@ -1,8 +1,8 @@
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_create, report_detail,
- report_list)
+ login_view, logout_view, map_index, position_create, position_detail, position_list,
+ qr_code, register_view, report_create, report_detail, report_list)
slug = r'(?P[a-z0-9-_.:]+)'
coordinates = r'(?P[a-z0-9-_:]+:-?\d+(\.\d+)?:-?\d+(\.\d+)?)'
@@ -35,4 +35,7 @@ urlpatterns = [
url(r'^report/l/(?P\d+)/$', report_create, name='site.report_create'),
url(r'^report/r/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/$',
report_create, name='site.report_create'),
+ url(r'^positions/$', position_list, name='site.position_list'),
+ url(r'^positions/create/$', position_create, name='site.position_create'),
+ url(r'^positions/(?P\d+)/$', position_detail, name='site.position_detail'),
]
diff --git a/src/c3nav/site/views.py b/src/c3nav/site/views.py
index a3f9a159..6326ac00 100644
--- a/src/c3nav/site/views.py
+++ b/src/c3nav/site/views.py
@@ -28,14 +28,15 @@ from c3nav.control.forms import AccessPermissionForm, SignedPermissionDataError
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.models.locations import (LocationRedirect, Position, SpecificLocation, get_position_api_secret,
+ get_position_secret)
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)
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.forms import ReportUpdateForm
+from c3nav.site.forms import PositionForm, ReportUpdateForm
from c3nav.site.models import Announcement, SiteUpdate
@@ -433,6 +434,7 @@ def report_create(request, coordinates=None, location=None, origin=None, destina
})
+@login_required(login_url='site.login')
def report_list(request, filter):
page = request.GET.get('page', 1)
@@ -481,3 +483,66 @@ def report_detail(request, pk, secret=None):
'form': form,
'update_form': update_form,
})
+
+
+@login_required(login_url='site.login')
+def position_list(request):
+ return render(request, 'site/position_list.html', {
+ 'positions': Position.objects.filter(owner=request.user),
+ })
+
+
+@login_required(login_url='site.login')
+def position_create(request):
+ if Position.objects.filter(owner=request.user).count() >= 20:
+ messages.error(request, _('You can\'t create more than 20 positions.'))
+
+ position = Position()
+ position.owner = request.user
+
+ if request.method == 'POST':
+ form = PositionForm(instance=position, data=request.POST)
+ if form.is_valid():
+ form.save()
+ messages.success(request, _('Position created.'))
+ return redirect(reverse('site.position_detail', kwargs={'pk': position.pk}))
+ else:
+ form = PositionForm(instance=position)
+
+ return render(request, 'site/position_create.html', {
+ 'form': form,
+ })
+
+ pass
+
+
+@login_required(login_url='site.login')
+def position_detail(request, pk):
+ position = get_object_or_404(Position.objects.filter(owner=request.user), pk=pk)
+
+ if request.method == 'POST':
+ with transaction.atomic():
+ if request.POST.get('delete', None):
+ position.delete()
+ messages.success(request, _('Position deleted.'))
+ return redirect(reverse('site.position_list'))
+
+ if request.POST.get('reset_secret', None):
+ position.secret = get_position_secret()
+
+ if request.POST.get('reset_api_secret', None):
+ position.api_secret = get_position_api_secret()
+
+ form = PositionForm(instance=position, data=request.POST)
+ if form.is_valid():
+ form.save()
+ messages.success(request, _('Position updated.'))
+ return redirect(reverse('site.position_detail', kwargs={'pk': position.pk}))
+ else:
+ form = PositionForm(instance=position)
+
+ return render(request, 'site/position_detail.html', {
+ 'position': position,
+ 'form': form,
+ })
+ pass