mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 11:27:09 +00:00
feat: add views for Organisation model
Location picker on update view
This commit is contained in:
@@ -66,6 +66,10 @@
|
|||||||
<a href="{% url 'people:person.list' %}" class="nav-link">People</a>
|
<a href="{% url 'people:person.list' %}" class="nav-link">People</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{% url 'people:organisation.list' %}" class="nav-link">Organisations</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="{% url 'activities:activity-series.list' %}" class="nav-link">Activity Series</a>
|
<a href="{% url 'activities:activity-series.list' %}" class="nav-link">Activity Series</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -24,6 +24,17 @@ def get_date_year_range() -> typing.Iterable[int]:
|
|||||||
return range(this_year, this_year - num_years_display, -1)
|
return range(this_year, this_year - num_years_display, -1)
|
||||||
|
|
||||||
|
|
||||||
|
class OrganisationForm(forms.ModelForm):
|
||||||
|
"""Form for creating / updating an instance of :class:`Organisation`."""
|
||||||
|
class Meta:
|
||||||
|
model = models.Organisation
|
||||||
|
fields = [
|
||||||
|
'name',
|
||||||
|
'latitude',
|
||||||
|
'longitude'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class PersonForm(forms.ModelForm):
|
class PersonForm(forms.ModelForm):
|
||||||
"""Form for creating / updating an instance of :class:`Person`."""
|
"""Form for creating / updating an instance of :class:`Person`."""
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|||||||
@@ -64,9 +64,7 @@ class User(AbstractUser):
|
|||||||
|
|
||||||
|
|
||||||
class Organisation(models.Model):
|
class Organisation(models.Model):
|
||||||
"""
|
"""Organisation to which a :class:`Person` belongs."""
|
||||||
Organisation to which a :class:`Person` belongs.
|
|
||||||
"""
|
|
||||||
name = models.CharField(max_length=255, blank=False, null=False)
|
name = models.CharField(max_length=255, blank=False, null=False)
|
||||||
|
|
||||||
#: Latitude for displaying location on a map
|
#: Latitude for displaying location on a map
|
||||||
@@ -78,6 +76,9 @@ class Organisation(models.Model):
|
|||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse('people:organisation.detail', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
|
|
||||||
class Theme(models.Model):
|
class Theme(models.Model):
|
||||||
"""
|
"""
|
||||||
|
|||||||
29
people/templates/people/organisation/create.html
Normal file
29
people/templates/people/organisation/create.html
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="{% url 'people:organisation.list' %}">Organisations</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">Create</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<h1>New Organisation</h1>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<form class="form"
|
||||||
|
method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
|
||||||
|
{% buttons %}
|
||||||
|
<button class="btn btn-success" type="submit">Submit</button>
|
||||||
|
{% endbuttons %}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
36
people/templates/people/organisation/detail.html
Normal file
36
people/templates/people/organisation/detail.html
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
{% 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:organisation.list' %}">Organisations</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">{{ object }}</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<h1>{{ organisation.name }}</h1>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<a class="btn btn-success"
|
||||||
|
href="{% url 'people:organisation.update' pk=organisation.pk %}">Update</a>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div id="map" style="height: 800px; width: 100%"></div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
42
people/templates/people/organisation/list.html
Normal file
42
people/templates/people/organisation/list.html
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">Organisation</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<h1>People</h1>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<a class="btn btn-success"
|
||||||
|
href="{% url 'people:organisation.create' %}">New Organisation</a>
|
||||||
|
|
||||||
|
<table class="table table-borderless">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for organisation in organisation_list.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ organisation }}</td>
|
||||||
|
<td>
|
||||||
|
<a class="btn btn-sm btn-info"
|
||||||
|
href="{% url 'people:organisation.detail' pk=organisation.pk %}">Details</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td>No records</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
68
people/templates/people/organisation/update.html
Normal file
68
people/templates/people/organisation/update.html
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block extra_head %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
<script type="application/javascript">
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
name: '{{ organisation.name }}',
|
||||||
|
lat: '{{ organisation.latitude }}',
|
||||||
|
lng: '{{ organisation.longitude }}'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const settings = {
|
||||||
|
zoom: 2,
|
||||||
|
centre_lat: '{{ organisation.latitude }}',
|
||||||
|
centre_lng: '{{ organisation.longitude }}',
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- {{ map_markers|json_script:'map-markers' }} -->
|
||||||
|
|
||||||
|
<script src="{% static 'js/location_picker.js' %}"></script>
|
||||||
|
|
||||||
|
<script async defer src="https://maps.googleapis.com/maps/api/js?key={{ settings.GOOGLE_MAPS_API_KEY }}&callback=initMap&libraries=places"
|
||||||
|
type="text/javascript"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="{% url 'people:organisation.list' %}">Organisations</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="{% url 'people:organisation.detail' pk=organisation.pk %}">{{ organisation }}</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">Update</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<h1>{{ organisation.name }}</h1>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<form class="form"
|
||||||
|
method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form exclude='latitude,longitude' %}
|
||||||
|
|
||||||
|
{% bootstrap_field form.latitude %}
|
||||||
|
{% bootstrap_field form.longitude %}
|
||||||
|
|
||||||
|
{% buttons %}
|
||||||
|
<button class="btn btn-success" type="submit">Submit</button>
|
||||||
|
{% endbuttons %}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<input id="location-search" class="controls" type="text" placeholder="Location Search"/>
|
||||||
|
<div id="map" style="height: 800px; width: 100%"></div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -6,6 +6,22 @@ from . import views
|
|||||||
app_name = 'people'
|
app_name = 'people'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
path('organisations/create',
|
||||||
|
views.organisation.OrganisationCreateView.as_view(),
|
||||||
|
name='organisation.create'),
|
||||||
|
|
||||||
|
path('organisations',
|
||||||
|
views.organisation.OrganisationListView.as_view(),
|
||||||
|
name='organisation.list'),
|
||||||
|
|
||||||
|
path('organisations/<int:pk>',
|
||||||
|
views.organisation.OrganisationDetailView.as_view(),
|
||||||
|
name='organisation.detail'),
|
||||||
|
|
||||||
|
path('organisations/<int:pk>/update',
|
||||||
|
views.organisation.OrganisationUpdateView.as_view(),
|
||||||
|
name='organisation.update'),
|
||||||
|
|
||||||
path('profile/',
|
path('profile/',
|
||||||
views.person.ProfileView.as_view(),
|
views.person.ProfileView.as_view(),
|
||||||
name='person.profile'),
|
name='person.profile'),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ Views for displaying or manipulating models within the `people` app.
|
|||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
network,
|
network,
|
||||||
|
organisation,
|
||||||
person,
|
person,
|
||||||
relationship
|
relationship
|
||||||
)
|
)
|
||||||
@@ -11,6 +12,7 @@ from . import (
|
|||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'network',
|
'network',
|
||||||
|
'organisation',
|
||||||
'person',
|
'person',
|
||||||
'relationship',
|
'relationship',
|
||||||
]
|
]
|
||||||
|
|||||||
47
people/views/organisation.py
Normal file
47
people/views/organisation.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import typing
|
||||||
|
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.views.generic import CreateView, DetailView, ListView, UpdateView
|
||||||
|
|
||||||
|
from people import forms, models
|
||||||
|
|
||||||
|
|
||||||
|
class OrganisationCreateView(LoginRequiredMixin, CreateView):
|
||||||
|
"""View to create a new instance of :class:`Organisation`."""
|
||||||
|
model = models.Organisation
|
||||||
|
template_name = 'people/organisation/create.html'
|
||||||
|
form_class = forms.OrganisationForm
|
||||||
|
|
||||||
|
|
||||||
|
class OrganisationListView(LoginRequiredMixin, ListView):
|
||||||
|
"""View displaying a list of :class:`organisation` objects."""
|
||||||
|
model = models.Organisation
|
||||||
|
template_name = 'people/organisation/list.html'
|
||||||
|
|
||||||
|
|
||||||
|
class OrganisationDetailView(LoginRequiredMixin, DetailView):
|
||||||
|
"""View displaying details of a :class:`Organisation`."""
|
||||||
|
model = models.Organisation
|
||||||
|
context_object_name = 'organisation'
|
||||||
|
template_name = 'people/organisation/detail.html'
|
||||||
|
|
||||||
|
def get_context_data(self,
|
||||||
|
**kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
|
||||||
|
"""Add map marker to context."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
context['map_markers'] = [{
|
||||||
|
'name': self.object.name,
|
||||||
|
'lat': self.object.latitude,
|
||||||
|
'lng': self.object.longitude,
|
||||||
|
}]
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class OrganisationUpdateView(LoginRequiredMixin, UpdateView):
|
||||||
|
"""View for updating a :class:`Organisation` record."""
|
||||||
|
model = models.Organisation
|
||||||
|
context_object_name = 'organisation'
|
||||||
|
template_name = 'people/organisation/update.html'
|
||||||
|
form_class = forms.OrganisationForm
|
||||||
Reference in New Issue
Block a user