From da07faf3cb5052bd1a1e8694a2df874bf02038eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Fri, 27 Dec 2019 16:51:06 +0100 Subject: [PATCH] set coordinates for position --- .../migrations/0083_auto_20191227_1642.py | 31 +++++++++++++++++ src/c3nav/mapdata/models/locations.py | 4 +-- src/c3nav/site/forms.py | 13 ++++++- src/c3nav/site/static/site/css/c3nav.scss | 2 +- src/c3nav/site/static/site/js/c3nav.js | 14 +++++--- src/c3nav/site/templates/site/map.html | 6 ++++ .../site/templates/site/position_detail.html | 10 +++++- .../site/templates/site/position_set.html | 16 +++++++++ src/c3nav/site/urls.py | 3 +- src/c3nav/site/views.py | 34 ++++++++++++++++--- 10 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 src/c3nav/mapdata/migrations/0083_auto_20191227_1642.py create mode 100644 src/c3nav/site/templates/site/position_set.html diff --git a/src/c3nav/mapdata/migrations/0083_auto_20191227_1642.py b/src/c3nav/mapdata/migrations/0083_auto_20191227_1642.py new file mode 100644 index 00000000..25e1514c --- /dev/null +++ b/src/c3nav/mapdata/migrations/0083_auto_20191227_1642.py @@ -0,0 +1,31 @@ +# Generated by Django 2.2.8 on 2019-12-27 15:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0082_dynamiclocation_position'), + ] + + operations = [ + migrations.RemoveField( + model_name='position', + name='last_location_update', + ), + migrations.RemoveField( + model_name='position', + name='location_id', + ), + migrations.AddField( + model_name='position', + name='coordinates_id', + field=models.CharField(max_length=48, null=True, verbose_name='coordinates'), + ), + migrations.AddField( + model_name='position', + name='last_coordinates_update', + field=models.DateTimeField(null=True, verbose_name='last coordinates update'), + ), + ] diff --git a/src/c3nav/mapdata/models/locations.py b/src/c3nav/mapdata/models/locations.py index c966442c..18ff500d 100644 --- a/src/c3nav/mapdata/models/locations.py +++ b/src/c3nav/mapdata/models/locations.py @@ -496,8 +496,8 @@ 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) + last_coordinates_update = models.DateTimeField(_('last coordinates update'), null=True) + coordinates_id = models.CharField(_('coordinates'), null=True, max_length=48) api_secret = models.CharField(_('api secret'), max_length=64, default=get_position_api_secret) coordinates = LocationById() diff --git a/src/c3nav/site/forms.py b/src/c3nav/site/forms.py index 45489819..6ce023b6 100644 --- a/src/c3nav/site/forms.py +++ b/src/c3nav/site/forms.py @@ -1,5 +1,7 @@ +from operator import attrgetter + from django.db import transaction -from django.forms import ModelForm +from django.forms import Form, ModelChoiceField, ModelForm from django.utils.translation import ugettext_lazy as _ from c3nav.mapdata.forms import I18nModelFormMixin @@ -53,3 +55,12 @@ class PositionForm(ModelForm): class Meta: model = Position fields = ['name'] + + +class PositionSetForm(Form): + position = ModelChoiceField(Position.objects.none()) + + def __init__(self, request, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['position'].queryset = Position.objects.filter(owner=request.user) + self.fields['position'].label_from_instance = attrgetter('name') diff --git a/src/c3nav/site/static/site/css/c3nav.scss b/src/c3nav/site/static/site/css/c3nav.scss index 5a0b048e..3e9f58eb 100644 --- a/src/c3nav/site/static/site/css/c3nav.scss +++ b/src/c3nav/site/static/site/css/c3nav.scss @@ -1290,7 +1290,7 @@ main form > p, #modal form > p { resize: none; height: 100px; } - select { + select[multiple] { height: 100px; } } diff --git a/src/c3nav/site/static/site/js/c3nav.js b/src/c3nav/site/static/site/js/c3nav.js index adef336d..3333a08a 100644 --- a/src/c3nav/site/static/site/js/c3nav.js +++ b/src/c3nav/site/static/site/js/c3nav.js @@ -1361,21 +1361,24 @@ c3nav = { _click_anywhere: function(e) { if (e.originalEvent.target.id !== 'map') return; var popup = L.popup(c3nav._add_map_padding({className: 'location-popup', maxWidth: 500}, 'autoPanPaddingTopLeft', 'autoPanPaddingBottomRight')), - level = c3nav._levelControl.currentLevel, - name = 'c:'+String(c3nav.level_labels_by_id[level])+':'+Math.round(e.latlng.lng*100)/100+':'+Math.round(e.latlng.lat*100)/100; + name = c3nav._latlng_to_name(e.latlng); var buttons = $('#anywhere-popup-buttons').clone(); - buttons.find('.report').attr('href', '/report/l/' + name + '/'); + buttons.find('.report').attr('href', '/report/l/' + name + '/'); + buttons.find('.set-position').attr('href', '/positions/set/' + name + '/'); popup.setLatLng(e.latlng).setContent(buttons.html()); c3nav._click_anywhere_popup = popup; popup.on('remove', function() { c3nav._click_anywhere_popup = null }).openOn(c3nav.map); }, + _latlng_to_name: function(latlng) { + var level = c3nav._levelControl.currentLevel; + return 'c:'+String(c3nav.level_labels_by_id[level])+':'+Math.round(latlng.lng*100)/100+':'+Math.round(latlng.lat*100)/100; + }, _click_anywhere_load: function(nearby) { if (!c3nav._click_anywhere_popup) return; var latlng = c3nav._click_anywhere_popup.getLatLng(); c3nav._click_anywhere_popup.remove(); var popup = L.popup().setLatLng(latlng).setContent('
'), - level = c3nav._levelControl.currentLevel, - name = 'c:'+String(c3nav.level_labels_by_id[level])+':'+Math.round(latlng.lng*100)/100+':'+Math.round(latlng.lat*100)/100; + name = c3nav._latlng_to_name(latlng); c3nav._click_anywhere_popup = popup; popup.on('remove', function() { c3nav._click_anywhere_popup = null }).openOn(c3nav.map); $.getJSON('/api/locations/'+name+'/', function(data) { @@ -1621,6 +1624,7 @@ c3nav = { var $user = $('header #user'); $user.find('span').text(data.title); $user.find('small').text(data.subtitle || ''); + $('.position-buttons').toggle(data.has_positions); if (window.mobileclient) mobileclient.setUserData(JSON.stringify(data)); }, diff --git a/src/c3nav/site/templates/site/map.html b/src/c3nav/site/templates/site/map.html index c6b41c8e..beee9ddd 100644 --- a/src/c3nav/site/templates/site/map.html +++ b/src/c3nav/site/templates/site/map.html @@ -42,6 +42,12 @@ {% trans 'Show nearby locations' %} +
+ + my_location + {% trans 'Set my position' %} + +
feedback diff --git a/src/c3nav/site/templates/site/position_detail.html b/src/c3nav/site/templates/site/position_detail.html index 9ca3d8d9..1fba4a41 100644 --- a/src/c3nav/site/templates/site/position_detail.html +++ b/src/c3nav/site/templates/site/position_detail.html @@ -7,6 +7,13 @@

{% trans 'Position:' %} {{ position.name }}

« {% trans 'back to overview' %}

+ {% if position.coordinates %} + {% include 'site/fragment_location.html' with location=position.coordinates %} + {% else %} +

{% trans 'currently no coordinates' %}

+ {% endif %} +

{% trans 'last coordinates update:' %} {{ position.last_coordinates_update }}

+

{% trans 'Secret' %}: {{ position.secret }} @@ -21,9 +28,10 @@

{% csrf_token %} {{ form.as_p }} + - +
diff --git a/src/c3nav/site/templates/site/position_set.html b/src/c3nav/site/templates/site/position_set.html new file mode 100644 index 00000000..2b30af8d --- /dev/null +++ b/src/c3nav/site/templates/site/position_set.html @@ -0,0 +1,16 @@ +{% extends 'site/base.html' %} +{% load i18n %} + +{% block content %} +
+ {% include 'site/fragment_messages.html' %} +

{% trans 'Set position coordinates' %}

+

{% trans 'Please select the position to set to these coordinates:' %}

+ {% include 'site/fragment_location.html' with location=coordinates %} +
+ {% csrf_token %} + {{ form.as_p }} + +
+
+{% endblock %} diff --git a/src/c3nav/site/urls.py b/src/c3nav/site/urls.py index 1e957aa4..8f8fc918 100644 --- a/src/c3nav/site/urls.py +++ b/src/c3nav/site/urls.py @@ -2,7 +2,7 @@ from django.conf.urls import url from c3nav.site.views import (about_view, access_redeem_view, account_view, change_password_view, choose_language, login_view, logout_view, map_index, position_create, position_detail, position_list, - qr_code, register_view, report_create, report_detail, report_list) + position_set, 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+)?)' @@ -38,4 +38,5 @@ urlpatterns = [ 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'), + url(r'^positions/set/%s/$' % coordinates, position_set, name='site.position_set'), ] diff --git a/src/c3nav/site/views.py b/src/c3nav/site/views.py index 0c1d1d75..6d73edde 100644 --- a/src/c3nav/site/views.py +++ b/src/c3nav/site/views.py @@ -36,7 +36,7 @@ from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_l 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 PositionForm, ReportUpdateForm +from c3nav.site.forms import PositionForm, PositionSetForm, ReportUpdateForm from c3nav.site.models import Announcement, SiteUpdate @@ -514,12 +514,11 @@ def position_create(request): '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) + position.request = request if request.method == 'POST': with transaction.atomic(): @@ -528,6 +527,10 @@ def position_detail(request, pk): messages.success(request, _('Position deleted.')) return redirect(reverse('site.position_list')) + if request.POST.get('set_null', None): + position.last_coordinates_update = timezone.now() + position.coordinates = None + if request.POST.get('reset_secret', None): position.secret = get_position_secret() @@ -546,4 +549,27 @@ def position_detail(request, pk): 'position': position, 'form': form, }) - pass + + +@login_required(login_url='site.login') +def position_set(request, coordinates): + coordinates = get_location_by_id_for_request(coordinates, request) + if coordinates is None: + raise Http404 + + if request.method == 'POST': + form = PositionSetForm(request, data=request.POST) + if form.is_valid(): + position = form.cleaned_data['position'] + position.last_coordinates_update = timezone.now() + position.coordinates = coordinates + position.save() + messages.success(request, _('Position set.')) + return redirect(reverse('site.position_detail', kwargs={'pk': position.pk})) + else: + form = PositionSetForm(request) + + return render(request, 'site/position_set.html', { + 'coordinates': coordinates, + 'form': form, + })