mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 03:17:07 +00:00
19
activities/migrations/0004_activity_attendance_list.py
Normal file
19
activities/migrations/0004_activity_attendance_list.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 2.2.10 on 2020-02-19 15:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('people', '0005_user_one_person'),
|
||||
('activities', '0003_rename_activity_series_fk'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='activity',
|
||||
name='attendance_list',
|
||||
field=models.ManyToManyField(related_name='activities', to='people.Person'),
|
||||
),
|
||||
]
|
||||
@@ -1,6 +1,9 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
from people import models as people_models
|
||||
|
||||
|
||||
class ActivityType(models.Model):
|
||||
"""
|
||||
Representation of the type of activity being conducted.
|
||||
@@ -33,7 +36,7 @@ class ActivityMedium(models.Model):
|
||||
|
||||
class ActivitySeries(models.Model):
|
||||
"""
|
||||
A series of related :class:`Activity`s
|
||||
A series of related :class:`Activity`s.
|
||||
"""
|
||||
class Meta:
|
||||
verbose_name_plural = 'activity series'
|
||||
@@ -58,7 +61,7 @@ class ActivitySeries(models.Model):
|
||||
|
||||
class Activity(models.Model):
|
||||
"""
|
||||
An instance of an activity - e.g. a workshop
|
||||
An instance of an activity - e.g. a workshop.
|
||||
"""
|
||||
class Meta:
|
||||
verbose_name_plural = 'activities'
|
||||
@@ -73,15 +76,19 @@ class Activity(models.Model):
|
||||
on_delete=models.PROTECT,
|
||||
blank=True, null=True)
|
||||
|
||||
#: What type of activity does this series represent?
|
||||
#: What type of activity is this?
|
||||
type = models.ForeignKey(ActivityType,
|
||||
on_delete=models.PROTECT,
|
||||
blank=False, null=False)
|
||||
|
||||
#: How are activities in this series typically conducted?
|
||||
#: How was this activity conducted?
|
||||
medium = models.ForeignKey(ActivityMedium,
|
||||
on_delete=models.PROTECT,
|
||||
blank=False, null=False)
|
||||
|
||||
#: Who attended this activity?
|
||||
attendance_list = models.ManyToManyField(people_models.Person,
|
||||
related_name='activities')
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
@@ -10,6 +10,20 @@
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
{% if user_is_attending %}
|
||||
<button class="btn btn-danger"
|
||||
onclick="clickCancelAttend();">
|
||||
Cancel Attendance
|
||||
</button>
|
||||
|
||||
{% else %}
|
||||
<button class="btn btn-success"
|
||||
onclick="clickAttend();">
|
||||
Attend
|
||||
</button>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<hr>
|
||||
|
||||
<dl>
|
||||
@@ -23,4 +37,91 @@
|
||||
<dd>{{ activity.medium }}</dd>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for person in activity.attendance_list.all %}
|
||||
<tr>
|
||||
<td>{{ person }}</td>
|
||||
<td>
|
||||
<a class="btn btn-sm btn-info"
|
||||
href="{% url 'people:person.detail' pk=person.pk %}">Profile</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td>No records</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block extra_script %}
|
||||
<script type="application/javascript">
|
||||
/**
|
||||
* Get the value of a named cookie.
|
||||
*/
|
||||
function getCookie(name) {
|
||||
for (const cookie of document.cookie.split(';')) {
|
||||
const tokens = cookie.split('=');
|
||||
if (tokens[0].trim() === name) {
|
||||
return tokens[1].trim();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit that user is attending this activity.
|
||||
*/
|
||||
function clickAttend() {
|
||||
$.ajax({
|
||||
url: '{% url "activities:activity.attendance" pk=activity.pk %}',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
},
|
||||
data: JSON.stringify({
|
||||
pk: {{ request.user.person.pk }}
|
||||
}),
|
||||
success: function() {
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit that user is not attending this activity.
|
||||
*/
|
||||
function clickCancelAttend() {
|
||||
$.ajax({
|
||||
url: '{% url "activities:activity.attendance" pk=activity.pk %}',
|
||||
type: 'DELETE',
|
||||
contentType: 'application/json',
|
||||
headers: {
|
||||
'X-CSRFToken': getCookie('csrftoken')
|
||||
},
|
||||
data: JSON.stringify({
|
||||
pk: {{ request.user.person.pk }}
|
||||
}),
|
||||
success: function() {
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -21,4 +21,8 @@ urlpatterns = [
|
||||
path('activities/<int:pk>',
|
||||
views.ActivityDetailView.as_view(),
|
||||
name='activity.detail'),
|
||||
|
||||
path('activities/<int:pk>/attendance',
|
||||
views.ActivityAttendanceView.as_view(),
|
||||
name='activity.attendance'),
|
||||
]
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
"""
|
||||
Views for displaying / manipulating models within the Activities app.
|
||||
"""
|
||||
from django.views.generic import DetailView, ListView
|
||||
import json
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.views.generic import DetailView, ListView, View
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
|
||||
from . import models
|
||||
from people import models as people_models
|
||||
|
||||
|
||||
class ActivitySeriesListView(ListView):
|
||||
@@ -38,3 +43,44 @@ class ActivityDetailView(DetailView):
|
||||
"""
|
||||
model = models.Activity
|
||||
template_name = 'activities/activity/detail.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['user_is_attending'] = self.object.attendance_list.filter(pk=self.request.user.person.pk).exists()
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class ActivityAttendanceView(SingleObjectMixin, View):
|
||||
"""
|
||||
View to add or delete attendance of an activity.
|
||||
"""
|
||||
model = models.Activity
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
|
||||
if request.is_ajax():
|
||||
data = json.loads(request.body)
|
||||
|
||||
person = people_models.Person.objects.get(pk=data['pk'])
|
||||
self.object.attendance_list.add(person)
|
||||
|
||||
return HttpResponse(status=204)
|
||||
|
||||
pass
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
|
||||
if request.is_ajax():
|
||||
data = json.loads(request.body)
|
||||
|
||||
person = people_models.Person.objects.get(pk=data['pk'])
|
||||
self.object.attendance_list.remove(person)
|
||||
|
||||
return HttpResponse(status=204)
|
||||
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user