feat: add views for Organisation model

Location picker on update view
This commit is contained in:
James Graham
2021-01-15 14:58:05 +00:00
parent 2d85ab4370
commit 9db870bcb0
10 changed files with 259 additions and 3 deletions

View File

@@ -66,6 +66,10 @@
<a href="{% url 'people:person.list' %}" class="nav-link">People</a>
</li>
<li class="nav-item">
<a href="{% url 'people:organisation.list' %}" class="nav-link">Organisations</a>
</li>
<li class="nav-item">
<a href="{% url 'activities:activity-series.list' %}" class="nav-link">Activity Series</a>
</li>

View File

@@ -24,6 +24,17 @@ def get_date_year_range() -> typing.Iterable[int]:
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):
"""Form for creating / updating an instance of :class:`Person`."""
class Meta:

View File

@@ -64,9 +64,7 @@ class User(AbstractUser):
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)
#: Latitude for displaying location on a map
@@ -78,6 +76,9 @@ class Organisation(models.Model):
def __str__(self) -> str:
return self.name
def get_absolute_url(self):
return reverse('people:organisation.detail', kwargs={'pk': self.pk})
class Theme(models.Model):
"""

View 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 %}

View 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 %}

View 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 %}

View 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 %}

View File

@@ -6,6 +6,22 @@ from . import views
app_name = 'people'
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/',
views.person.ProfileView.as_view(),
name='person.profile'),

View File

@@ -4,6 +4,7 @@ Views for displaying or manipulating models within the `people` app.
from . import (
network,
organisation,
person,
relationship
)
@@ -11,6 +12,7 @@ from . import (
__all__ = [
'network',
'organisation',
'person',
'relationship',
]

View 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