mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 03:17:07 +00:00
feature: add map of all people
This commit is contained in:
@@ -74,6 +74,10 @@
|
|||||||
<a href="{% url 'activities:activity.list' %}" class="nav-link">Activities</a>
|
<a href="{% url 'activities:activity.list' %}" class="nav-link">Activities</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{% url 'people:person.map' %}" class="nav-link">Map</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="{% url 'people:network' %}" class="nav-link">Network</a>
|
<a href="{% url 'people:network' %}" class="nav-link">Network</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -10,17 +10,26 @@ const marker_label_offset = 0.27 * marker_scale;
|
|||||||
const marker_edge_alpha = 1.0;
|
const marker_edge_alpha = 1.0;
|
||||||
const marker_edge_width = 1.0;
|
const marker_edge_width = 1.0;
|
||||||
|
|
||||||
|
let map = null
|
||||||
|
|
||||||
// The function called when Google Maps starts up
|
// The function called when Google Maps starts up
|
||||||
function initMap() {
|
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
|
// The map, centered at Soton
|
||||||
const map = new google.maps.Map(
|
map = new google.maps.Map(
|
||||||
document.getElementById('map'), { zoom: settings.zoom, center: centre_latlng });
|
// 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 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
|
// Get the lat-long position from the data
|
||||||
const lat_lng = new google.maps.LatLng(pin_data.lat, pin_data.lng);
|
const lat_lng = new google.maps.LatLng(pin_data.lat, pin_data.lng);
|
||||||
|
console.log(lat_lng)
|
||||||
|
|
||||||
// Generate a new marker
|
// Generate a new marker
|
||||||
const marker = new google.maps.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.
|
// Build the info window content to tell the user the last time it was visited.
|
||||||
marker.info = new google.maps.InfoWindow({
|
marker.info = new google.maps.InfoWindow({
|
||||||
content: "<div id='content'>" +
|
content: "<div id='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
|
// Set the last info window to null
|
||||||
var last_info = 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,9 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block extra_head %}
|
{% block extra_head %}
|
||||||
|
{{ map_markers|json_script:'map-markers' }}
|
||||||
|
|
||||||
{% load staticfiles %}
|
{% load staticfiles %}
|
||||||
<script type="application/javascript">
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
name: '{{ person.name }}',
|
|
||||||
lat: '{{ answer_set.latitude }}',
|
|
||||||
lng: '{{ answer_set.longitude }}'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const settings = {
|
|
||||||
zoom: 8,
|
|
||||||
centre_lat: '{{ answer_set.latitude }}',
|
|
||||||
centre_lng: '{{ answer_set.longitude }}',
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script src="{% static 'js/map.js' %}"></script>
|
<script src="{% static 'js/map.js' %}"></script>
|
||||||
|
|
||||||
<script async defer src="https://maps.googleapis.com/maps/api/js?key={{ settings.GOOGLE_MAPS_API_KEY }}&callback=initMap"
|
<script async defer src="https://maps.googleapis.com/maps/api/js?key={{ settings.GOOGLE_MAPS_API_KEY }}&callback=initMap"
|
||||||
|
|||||||
@@ -42,13 +42,6 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if answer_set.latitude and answer_set.longitude %}
|
|
||||||
<tr>
|
|
||||||
<td>Location</td>
|
|
||||||
<td>{{ answer_set.latitude }}, {{ answer_set.longitude }}</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for answer in answer_set.question_answers.all %}
|
{% for answer in answer_set.question_answers.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ answer.question }}</td>
|
<td>{{ answer.question }}</td>
|
||||||
|
|||||||
28
people/templates/people/person/map.html
Normal file
28
people/templates/people/person/map.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
{{ map_markers|json_script:'map-markers' }}
|
||||||
|
|
||||||
|
{% load staticfiles %}
|
||||||
|
<script src="{% static 'js/map.js' %}"></script>
|
||||||
|
|
||||||
|
<script async defer
|
||||||
|
src="https://maps.googleapis.com/maps/api/js?key={{ settings.GOOGLE_MAPS_API_KEY }}&callback=initMap"
|
||||||
|
type="text/javascript"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="{% url 'people:person.list' %}">People</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">Map</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<h1>Map</h1>
|
||||||
|
|
||||||
|
<div id="map" style="height: 800px; width: 100%"></div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -38,6 +38,10 @@ urlpatterns = [
|
|||||||
views.relationship.RelationshipUpdateView.as_view(),
|
views.relationship.RelationshipUpdateView.as_view(),
|
||||||
name='relationship.update'),
|
name='relationship.update'),
|
||||||
|
|
||||||
|
path('map',
|
||||||
|
views.person.PersonMapView.as_view(),
|
||||||
|
name='person.map'),
|
||||||
|
|
||||||
path('network',
|
path('network',
|
||||||
views.network.NetworkView.as_view(),
|
views.network.NetworkView.as_view(),
|
||||||
name='network'),
|
name='network'),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Views for displaying or manipulating instances of :class:`Person`.
|
|||||||
import typing
|
import typing
|
||||||
|
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.views.generic import CreateView, DetailView, ListView, UpdateView
|
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 = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
context['answer_set'] = self.object.current_answers
|
context['answer_set'] = self.object.current_answers
|
||||||
|
context['map_markers'] = [get_map_data(self.object)]
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
@@ -103,3 +105,38 @@ class PersonUpdateView(permissions.UserIsLinkedPersonMixin, UpdateView):
|
|||||||
answer_set.save()
|
answer_set.save()
|
||||||
|
|
||||||
return response
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user