participant list filtering
This commit is contained in:
parent
fca9a1eb1a
commit
6fc3457ddc
29
cfp/forms.py
29
cfp/forms.py
|
@ -125,6 +125,35 @@ class ParticipantStaffForm(ParticipantForm):
|
|||
}
|
||||
|
||||
|
||||
class ParticipantFilterForm(forms.Form):
|
||||
category = forms.MultipleChoiceField(
|
||||
label=_('Category'),
|
||||
required=False,
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
choices=[],
|
||||
)
|
||||
status = forms.MultipleChoiceField(
|
||||
label=_('Status'),
|
||||
required=False,
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
choices=STATUS_CHOICES,
|
||||
)
|
||||
track = forms.MultipleChoiceField(
|
||||
label=_('Track'),
|
||||
required=False,
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
choices=[],
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
site = kwargs.pop('site')
|
||||
super().__init__(*args, **kwargs)
|
||||
categories = TalkCategory.objects.filter(site=site)
|
||||
self.fields['category'].choices = categories.values_list('pk', 'name')
|
||||
tracks = Track.objects.filter(site=site)
|
||||
self.fields['track'].choices = [('none', _('Not assigned'))] + list(tracks.values_list('slug', 'name'))
|
||||
|
||||
|
||||
class UsersWidget(ModelSelect2MultipleWidget):
|
||||
model = User
|
||||
search_fields = [ '%s__icontains' % field for field in UserAdmin.search_fields ]
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.core.urlresolvers import reverse
|
|||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.db.models import Q, Sum, Avg, Case, When
|
||||
from django.db.models import Q, Count, Avg, Case, When
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||
|
@ -69,9 +69,9 @@ class ParticipantManager(models.Manager):
|
|||
def get_queryset(self):
|
||||
qs = super().get_queryset()
|
||||
qs = qs.annotate(
|
||||
accepted_talk_count=Sum(Case(When(talk__accepted=True, then=1), default=0, output_field=models.IntegerField())),
|
||||
pending_talk_count=Sum(Case(When(talk__accepted=None, then=1), default=0, output_field=models.IntegerField())),
|
||||
refused_talk_count=Sum(Case(When(talk__accepted=False, then=1), default=0, output_field=models.IntegerField())),
|
||||
accepted_talk_count=Count(Case(When(talk__accepted=True, then='talk__pk'), output_field=models.IntegerField()), distinct=True),
|
||||
pending_talk_count=Count(Case(When(talk__accepted=None, then='talk__pk'), output_field=models.IntegerField()), distinct=True),
|
||||
refused_talk_count=Count(Case(When(talk__accepted=False, then='talk__pk'), output_field=models.IntegerField()), distinct=True),
|
||||
)
|
||||
return qs
|
||||
|
||||
|
|
|
@ -7,30 +7,16 @@
|
|||
|
||||
<h1>{% trans "Speakers" %}</h1>
|
||||
|
||||
{% comment %}
|
||||
<a class="btn btn-primary" role="button" data-toggle="collapse" href="#filter" aria-expanded="{{ show_filters|yesno:"true,false" }}" aria-controles="filter">{% trans "Show filtering options…" %}</a>
|
||||
|
||||
<br /><br />
|
||||
<p><a class="btn btn-primary" role="button" data-toggle="collapse" href="#filter" aria-expanded="{{ show_filters|yesno:"true,false" }}" aria-controles="filter">{% trans "Show filtering options…" %}</a></p>
|
||||
|
||||
<div class="collapse{{ show_filters|yesno:" in," }}" id="filter">
|
||||
<div class="well">
|
||||
<form class="form-horizontal" method="get">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{% bootstrap_field filter_form.transport layout="horizontal" %}
|
||||
{% bootstrap_field filter_form.transport_booked layout="horizontal" %}
|
||||
{% bootstrap_field filter_form.sound layout="horizontal" %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{% bootstrap_field filter_form.accommodation layout="horizontal" %}
|
||||
{% bootstrap_field filter_form.accommodation_booked layout="horizontal" %}
|
||||
{% bootstrap_field filter_form.category layout="horizontal" %}
|
||||
{% bootstrap_field filter_form.status layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{% bootstrap_field filter_form.topic layout="horizontal" %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{% bootstrap_field filter_form.track layout="horizontal" %}
|
||||
</div>
|
||||
|
@ -39,7 +25,6 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endcomment %}
|
||||
|
||||
<table class="table table-bordered table-hover">
|
||||
<caption>{% trans "Total:" %} {{ participant_list|length }} {% trans "speaker" %}{{ participant_list|length|pluralize }}
|
||||
|
@ -51,13 +36,11 @@
|
|||
{% comment %}<th class="text-center"></th>{% endcomment %}
|
||||
</tr>
|
||||
</thead>
|
||||
{% comment %}
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="7">{% trans "Contact:" %} <a href="{{ contact_link }}">{% trans "link" %}</a></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
{% endcomment %}
|
||||
{% for participant in participant_list %}
|
||||
{% if forloop.first %}
|
||||
<tbody>
|
||||
|
@ -84,16 +67,3 @@
|
|||
</table>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% comment %}
|
||||
{% block js_end %}
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function($) {
|
||||
var anchor = window.location.hash.replace("#", "");
|
||||
if (anchor == "filter") {
|
||||
$("#filter").collapse('show');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endcomment %}
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
|
||||
<h1>{% trans "Talks" %}</h1>
|
||||
|
||||
<a class="btn btn-primary" role="button" data-toggle="collapse" href="#filter" aria-expanded="{{ show_filters|yesno:"true,false" }}" aria-controls="filter">{% trans "Show filtering options…" %}</a>
|
||||
|
||||
<br /><br />
|
||||
<p><a class="btn btn-primary" role="button" data-toggle="collapse" href="#filter" aria-expanded="{{ show_filters|yesno:"true,false" }}" aria-controles="filter">{% trans "Show filtering options…" %}</a></p>
|
||||
|
||||
<div class="collapse{{ show_filters|yesno:" in," }}" id="filter">
|
||||
<div class="well">
|
||||
|
|
35
cfp/views.py
35
cfp/views.py
|
@ -18,8 +18,9 @@ from .decorators import staff_required
|
|||
from .mixins import StaffRequiredMixin, OnSiteMixin
|
||||
from .utils import is_staff
|
||||
from .models import Participant, Talk, TalkCategory, Vote, Track, Room
|
||||
from .forms import TalkForm, TalkStaffForm, TalkFilterForm, TalkActionForm, ParticipantForm, \
|
||||
ParticipantStaffForm, ConferenceForm, CreateUserForm, STATUS_VALUES, TrackForm, RoomForm
|
||||
from .forms import TalkForm, TalkStaffForm, TalkFilterForm, TalkActionForm, \
|
||||
ParticipantForm, ParticipantStaffForm, ParticipantFilterForm, \
|
||||
ConferenceForm, CreateUserForm, STATUS_VALUES, TrackForm, RoomForm
|
||||
|
||||
|
||||
def home(request):
|
||||
|
@ -137,10 +138,10 @@ def staff(request):
|
|||
|
||||
@staff_required
|
||||
def talk_list(request):
|
||||
show_filters = False
|
||||
talks = Talk.objects.filter(site=request.conference.site)
|
||||
filter_form = TalkFilterForm(request.GET or None, site=request.conference.site)
|
||||
# Filtering
|
||||
show_filters = False
|
||||
filter_form = TalkFilterForm(request.GET or None, site=request.conference.site)
|
||||
if filter_form.is_valid():
|
||||
data = filter_form.cleaned_data
|
||||
if len(data['category']):
|
||||
|
@ -290,8 +291,34 @@ def participant_list(request):
|
|||
participants = Participant.objects.filter(site=request.conference.site) \
|
||||
.extra(select={'lower_name': 'lower(name)'}) \
|
||||
.order_by('lower_name')
|
||||
# Filtering
|
||||
show_filters = False
|
||||
filter_form = ParticipantFilterForm(request.GET or None, site=request.conference.site)
|
||||
if filter_form.is_valid():
|
||||
data = filter_form.cleaned_data
|
||||
talks = Talk.objects.filter(site=request.conference.site)
|
||||
if len(data['category']):
|
||||
show_filters = True
|
||||
talks = talks.filter(reduce(lambda x, y: x | y, [Q(category__pk=pk) for pk in data['category']]))
|
||||
if len(data['status']):
|
||||
show_filters = True
|
||||
talks = talks.filter(reduce(lambda x, y: x | y, [Q(accepted=dict(STATUS_VALUES)[status]) for status in data['status']]))
|
||||
if len(data['track']):
|
||||
show_filters = True
|
||||
q = Q()
|
||||
if 'none' in data['track']:
|
||||
data['track'].remove('none')
|
||||
q |= Q(track__isnull=True)
|
||||
if len(data['track']):
|
||||
q |= Q(track__slug__in=data['track'])
|
||||
talks = talks.filter(q)
|
||||
participants = participants.filter(talk__in=talks)
|
||||
contact_link = 'mailto:' + ','.join([participant.email for participant in participants.all()])
|
||||
return render(request, 'cfp/staff/participant_list.html', {
|
||||
'filter_form': filter_form,
|
||||
'participant_list': participants,
|
||||
'show_filters': show_filters,
|
||||
'contact_link': contact_link,
|
||||
})
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue