From 276a7ccc801d985ef76bd0eb259e8dd7ea961590 Mon Sep 17 00:00:00 2001 From: Struan Donald Date: Wed, 20 Nov 2024 17:57:09 +0000 Subject: [PATCH] add some filters to the volunteers list --- ceuk-marking/settings.py | 1 + crowdsourcer/filters.py | 28 ++++++++++++++++ crowdsourcer/models.py | 5 +++ crowdsourcer/static/css/_forms.scss | 6 ++++ .../crowdsourcer/volunteers/list.html | 32 +++++++++++++++++++ crowdsourcer/views/volunteers.py | 10 ++++-- 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 crowdsourcer/filters.py diff --git a/ceuk-marking/settings.py b/ceuk-marking/settings.py index 8599ef5e..9a3bad43 100644 --- a/ceuk-marking/settings.py +++ b/ceuk-marking/settings.py @@ -87,6 +87,7 @@ "django.contrib.staticfiles", "compressor", "django_bootstrap5", + "django_filters", "django_json_widget", "crowdsourcer", ] diff --git a/crowdsourcer/filters.py b/crowdsourcer/filters.py new file mode 100644 index 00000000..eb56c073 --- /dev/null +++ b/crowdsourcer/filters.py @@ -0,0 +1,28 @@ +from django.contrib.auth.models import User + +import django_filters + +from crowdsourcer.models import ResponseType + + +def filter_not_empty(queryset, name, value): + lookup = "__".join([name, "isnull"]) + return queryset.filter(**{lookup: not value}) + + +class VolunteerFilter(django_filters.FilterSet): + has_assignments = django_filters.BooleanFilter( + field_name="num_assignments", method=filter_not_empty, label="Has assignments" + ) + marker__response_type = django_filters.ChoiceFilter( + label="Stage", choices=ResponseType.choices() + ) + # have to specify it like this otherwise bootstrap doesn't recognise it as a bound field + username = django_filters.CharFilter(field_name="username", lookup_expr="icontains") + + class Meta: + model = User + fields = { + "marker__response_type": ["exact"], + "is_active": ["exact"], + } diff --git a/crowdsourcer/models.py b/crowdsourcer/models.py index 26600f5b..e3e711c8 100644 --- a/crowdsourcer/models.py +++ b/crowdsourcer/models.py @@ -321,6 +321,11 @@ class ResponseType(models.Model): priority = models.IntegerField() active = models.BooleanField(default=False) + @classmethod + def choices(cls): + choices = cls.objects.values_list("pk", "type") + return choices + def __str__(self): return self.type diff --git a/crowdsourcer/static/css/_forms.scss b/crowdsourcer/static/css/_forms.scss index 692bc483..ccbec71e 100644 --- a/crowdsourcer/static/css/_forms.scss +++ b/crowdsourcer/static/css/_forms.scss @@ -8,3 +8,9 @@ margin-bottom: 0; } } + +#volunteer_filter { + .form-group { + margin-bottom: 1rem; + } +} diff --git a/crowdsourcer/templates/crowdsourcer/volunteers/list.html b/crowdsourcer/templates/crowdsourcer/volunteers/list.html index 0a002f05..0393b19b 100644 --- a/crowdsourcer/templates/crowdsourcer/volunteers/list.html +++ b/crowdsourcer/templates/crowdsourcer/volunteers/list.html @@ -1,6 +1,7 @@ {% extends 'crowdsourcer/base.html' %} {% load crowdsourcer_tags %} +{% load django_bootstrap5 %} {% block content %} {% if show_login %} @@ -12,7 +13,38 @@

Sign in

Bulk assignment Stage deactivate +

Volunteers

+
+
+
+
+ {% bootstrap_field filter.form.marker__response_type %} +
+
+
+
+ {% bootstrap_field filter.form.is_active %} +
+
+
+
+ {% bootstrap_field filter.form.has_assignments %} +
+
+
+
+ {% bootstrap_field filter.form.username %} +
+
+
+
+ +
+
+
+
+ diff --git a/crowdsourcer/views/volunteers.py b/crowdsourcer/views/volunteers.py index 2bd62795..6faa3ef0 100644 --- a/crowdsourcer/views/volunteers.py +++ b/crowdsourcer/views/volunteers.py @@ -8,6 +8,9 @@ from django.urls import reverse from django.views.generic import FormView, ListView +from django_filters.views import FilterView + +from crowdsourcer.filters import VolunteerFilter from crowdsourcer.forms import ( CreateMarkerForm, MarkerFormset, @@ -35,12 +38,13 @@ def test_func(self): return self.request.user.has_perm("crowdsourcer.can_manage_users") -class VolunteersView(VolunteerAccessMixin, ListView): +class VolunteersView(VolunteerAccessMixin, FilterView): template_name = "crowdsourcer/volunteers/list.html" context_object_name = "volunteers" + filterset_class = VolunteerFilter def get_queryset(self): - return ( + qs = ( User.objects.filter(marker__marking_session=self.request.current_session) .select_related("marker") .annotate( @@ -57,6 +61,8 @@ def get_queryset(self): .order_by("username") ) + return qs + class VolunteerAddView(VolunteerAccessMixin, FormView): template_name = "crowdsourcer/volunteers/create.html"