From b2cd5f494044f4e7e5ba399de68f739589840799 Mon Sep 17 00:00:00 2001 From: James Graham Date: Wed, 16 Dec 2020 14:54:46 +0000 Subject: [PATCH] feature: add map of all people --- breccia_mapper/templates/base.html | 4 ++ people/static/js/map.js | 40 +++++++++++++++++-- people/templates/people/person/detail.html | 18 +-------- .../people/person/includes/answer_set.html | 7 ---- people/templates/people/person/map.html | 28 +++++++++++++ people/urls.py | 4 ++ people/views/person.py | 37 +++++++++++++++++ 7 files changed, 111 insertions(+), 27 deletions(-) create mode 100644 people/templates/people/person/map.html diff --git a/breccia_mapper/templates/base.html b/breccia_mapper/templates/base.html index 1b93a01..4aac740 100644 --- a/breccia_mapper/templates/base.html +++ b/breccia_mapper/templates/base.html @@ -74,6 +74,10 @@ Activities + + diff --git a/people/static/js/map.js b/people/static/js/map.js index 36550e9..154a16d 100644 --- a/people/static/js/map.js +++ b/people/static/js/map.js @@ -10,17 +10,26 @@ const marker_label_offset = 0.27 * marker_scale; const marker_edge_alpha = 1.0; const marker_edge_width = 1.0; +let map = null + // The function called when Google Maps starts up function initMap() { - const centre_latlng = new google.maps.LatLng(settings.centre_lat, settings.centre_lng); + // const centre_latlng = new google.maps.LatLng(settings.centre_lat, settings.centre_lng); // The map, centered at Soton - const map = new google.maps.Map( - document.getElementById('map'), { zoom: settings.zoom, center: centre_latlng }); + map = new google.maps.Map( + // document.getElementById('map'), { zoom: settings.zoom, center: centre_latlng }); + document.getElementById('map')); + + const bounds = new google.maps.LatLngBounds() + const markers_data = JSON.parse( + document.getElementById('map-markers').textContent + ).filter(data => data.lat !== null && data.lng !== null); // For each data entry in the json... - for (const pin_data of data) { + for (const pin_data of markers_data) { // Get the lat-long position from the data const lat_lng = new google.maps.LatLng(pin_data.lat, pin_data.lng); + console.log(lat_lng) // Generate a new marker const marker = new google.maps.Marker({ @@ -38,6 +47,10 @@ function initMap() { }, }); + console.log(marker) + + bounds.extend(marker.position) + // Build the info window content to tell the user the last time it was visited. marker.info = new google.maps.InfoWindow({ content: "
" + @@ -56,6 +69,25 @@ function initMap() { }) } + map.fitBounds(bounds) + const max_zoom = 10 + if (map.getZoom() > max_zoom) { + map.setZoom(max_zoom) + } + + // Set the last info window to null var last_info = null; + + setTimeout(setMaxZoom, 100) +} + +/** + * Zoom to set level if map is zoomed in more than this. + */ +function setMaxZoom() { + const max_zoom = 10 + if (map.getZoom() > max_zoom) { + map.setZoom(max_zoom) + } } diff --git a/people/templates/people/person/detail.html b/people/templates/people/person/detail.html index 520043a..b071b83 100644 --- a/people/templates/people/person/detail.html +++ b/people/templates/people/person/detail.html @@ -1,23 +1,9 @@ {% extends 'base.html' %} {% block extra_head %} + {{ map_markers|json_script:'map-markers' }} + {% load staticfiles %} - - + + +{% endblock %} + +{% block content %} + + +

Map

+ +
+ +{% endblock %} diff --git a/people/urls.py b/people/urls.py index eb73fe1..9fa4f32 100644 --- a/people/urls.py +++ b/people/urls.py @@ -38,6 +38,10 @@ urlpatterns = [ views.relationship.RelationshipUpdateView.as_view(), name='relationship.update'), + path('map', + views.person.PersonMapView.as_view(), + name='person.map'), + path('network', views.network.NetworkView.as_view(), name='network'), diff --git a/people/views/person.py b/people/views/person.py index ba4d4ed..d0023dd 100644 --- a/people/views/person.py +++ b/people/views/person.py @@ -5,6 +5,7 @@ Views for displaying or manipulating instances of :class:`Person`. import typing from django.contrib.auth.mixins import LoginRequiredMixin +from django.urls import reverse from django.utils import timezone from django.views.generic import CreateView, DetailView, ListView, UpdateView @@ -61,6 +62,7 @@ class ProfileView(permissions.UserIsLinkedPersonMixin, DetailView): context = super().get_context_data(**kwargs) context['answer_set'] = self.object.current_answers + context['map_markers'] = [get_map_data(self.object)] return context @@ -103,3 +105,38 @@ class PersonUpdateView(permissions.UserIsLinkedPersonMixin, UpdateView): answer_set.save() return response + + +def get_map_data(person: models.Person) -> typing.Dict[str, typing.Any]: + answer_set = person.current_answers + try: + latitude = answer_set.latitude or None + longitude = answer_set.longitude or None + + except AttributeError: + latitude = None + longitude = None + + return { + 'name': person.name, + 'lat': latitude, + 'lng': longitude, + 'url': reverse('people:person.detail', kwargs={'pk': person.pk}) + } + + +class PersonMapView(LoginRequiredMixin, ListView): + """ + View displaying a map of :class:`Person` locations. + """ + model = models.Person + template_name = 'people/person/map.html' + + def get_context_data(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + context = super().get_context_data(**kwargs) + + context['map_markers'] = [ + get_map_data(person) for person in self.object_list + ] + + return context