forked from AFPy/PonyConf
filter talks
This commit is contained in:
parent
2aecfe3abe
commit
c8dd061481
49
cfp/forms.py
49
cfp/forms.py
|
@ -3,12 +3,24 @@ from django.forms.models import modelform_factory
|
|||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.forms import UsernameField
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.template.defaultfilters import slugify
|
||||
|
||||
from django_select2.forms import ModelSelect2MultipleWidget
|
||||
|
||||
from .models import Participant, Talk, Conference
|
||||
from .models import Participant, Talk, TalkCategory, Track, Conference
|
||||
|
||||
|
||||
STATUS_CHOICES = [
|
||||
('pending', _('Pending decision')),
|
||||
('accepted', _('Accepted')),
|
||||
('declined', _('Declined')),
|
||||
]
|
||||
STATUS_VALUES = [
|
||||
('pending', None),
|
||||
('accepted', True),
|
||||
('declined', False),
|
||||
]
|
||||
|
||||
|
||||
class TalkForm(forms.ModelForm):
|
||||
|
@ -25,6 +37,39 @@ class TalkForm(forms.ModelForm):
|
|||
fields = ('category', 'title', 'description','notes')
|
||||
|
||||
|
||||
class TalkFilterForm(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=[],
|
||||
)
|
||||
vote = forms.NullBooleanField(
|
||||
label=_('Vote'),
|
||||
help_text=_('Filter talks you already / not yet voted for'),
|
||||
)
|
||||
|
||||
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'))
|
||||
|
||||
|
||||
ParticipantForm = modelform_factory(Participant, fields=('name','email', 'biography'))
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,28 @@
|
|||
|
||||
<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 />
|
||||
|
||||
<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 col-xs-6">
|
||||
{% bootstrap_field filter_form.status layout="horizontal" %}
|
||||
{% bootstrap_field filter_form.category layout="horizontal" %}
|
||||
{% bootstrap_field filter_form.vote layout="horizontal" %}
|
||||
</div>
|
||||
<div class="col-md-6 col-xs-6">
|
||||
{% bootstrap_field filter_form.track layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success" value="{% trans "Filter" %}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered table-hover">
|
||||
<caption>{% trans "Total:" %} {{ talk_list|length }} {% trans "talk" %}{{ talk_list|length|pluralize }}</caption>
|
||||
<thead>
|
||||
|
|
33
cfp/views.py
33
cfp/views.py
|
@ -5,14 +5,17 @@ from django.urls import reverse
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import FormView, TemplateView
|
||||
from django.contrib import messages
|
||||
from django.db.models import Q
|
||||
|
||||
from django_select2.views import AutoResponseView
|
||||
|
||||
from functools import reduce
|
||||
|
||||
from cfp.decorators import staff_required
|
||||
from .mixins import StaffRequiredMixin
|
||||
from .utils import is_staff
|
||||
from .models import Participant, Talk, TalkCategory, Vote
|
||||
from .forms import TalkForm, ParticipantForm, ConferenceForm, CreateUserForm
|
||||
from .forms import TalkForm, TalkFilterForm, ParticipantForm, ConferenceForm, CreateUserForm, STATUS_VALUES
|
||||
|
||||
|
||||
def home(request, conference):
|
||||
|
@ -131,7 +134,33 @@ def staff(request, conference):
|
|||
|
||||
@staff_required
|
||||
def talk_list(request, conference):
|
||||
show_filters = False
|
||||
talks = Talk.objects.filter(site=conference.site)
|
||||
filter_form = TalkFilterForm(request.GET or None, site=conference.site)
|
||||
# Filtering
|
||||
if filter_form.is_valid():
|
||||
data = filter_form.cleaned_data
|
||||
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)
|
||||
if data['vote'] != None:
|
||||
show_filters = True
|
||||
if data['vote']:
|
||||
talks = talks.filter(vote__user=request.user)
|
||||
else:
|
||||
talks = talks.exclude(vote__user=request.user)
|
||||
# Sorting
|
||||
if request.GET.get('order') == 'desc':
|
||||
reverse = True
|
||||
|
@ -166,7 +195,9 @@ def talk_list(request, conference):
|
|||
sort_urls[c] = url.urlencode()
|
||||
sort_glyphicons[c] = glyphicon
|
||||
return render(request, 'cfp/staff/talk_list.html', {
|
||||
'show_filters': show_filters,
|
||||
'talk_list': talks,
|
||||
'filter_form': filter_form,
|
||||
'sort_urls': sort_urls,
|
||||
'sort_glyphicons': sort_glyphicons,
|
||||
})
|
||||
|
|
Binary file not shown.
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-08-01 11:13+0000\n"
|
||||
"POT-Creation-Date: 2017-08-01 12:23+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -288,17 +288,67 @@ msgstr "%(name)s a été ajouté aux participants"
|
|||
msgid "%(name)s is already a participant"
|
||||
msgstr "%(name)s est déjà participant"
|
||||
|
||||
#: cfp/forms.py:44
|
||||
#: cfp/forms.py:15
|
||||
msgid "Pending decision"
|
||||
msgstr "Décision en attente"
|
||||
|
||||
#: cfp/forms.py:16 cfp/templates/cfp/staff/talk_list.html:64
|
||||
#: proposals/templates/proposals/talk_list.html:78
|
||||
msgid "Accepted"
|
||||
msgstr "Accepté"
|
||||
|
||||
#: cfp/forms.py:17 cfp/templates/cfp/staff/talk_list.html:66
|
||||
#: proposals/templates/proposals/talk_list.html:80
|
||||
msgid "Declined"
|
||||
msgstr "Décliné"
|
||||
|
||||
#: cfp/forms.py:42 cfp/templates/cfp/staff/talk_details.html:71
|
||||
msgid "Category"
|
||||
msgstr "Catégorie"
|
||||
|
||||
#: cfp/forms.py:48 cfp/templates/cfp/staff/talk_details.html:102
|
||||
#: cfp/templates/cfp/staff/talk_list.html:42
|
||||
#: proposals/templates/proposals/talk_detail.html:110
|
||||
#: proposals/templates/proposals/talk_list.html:52
|
||||
msgid "Status"
|
||||
msgstr "Statut"
|
||||
|
||||
#: cfp/forms.py:54 cfp/models.py:234
|
||||
#: cfp/templates/cfp/staff/talk_details.html:89
|
||||
#: cfp/templates/cfp/staff/talk_list.html:41 proposals/models.py:160
|
||||
#: proposals/templates/proposals/talk_detail.html:33
|
||||
#: proposals/templates/proposals/talk_detail.html:89
|
||||
#: proposals/templates/proposals/talk_list.html:51
|
||||
#: proposals/templates/proposals/track_form.html:14
|
||||
msgid "Track"
|
||||
msgstr "Session"
|
||||
|
||||
#: cfp/forms.py:60 cfp/templates/cfp/staff/talk_details.html:107
|
||||
#: proposals/templates/proposals/talk_detail.html:115
|
||||
msgid "Vote"
|
||||
msgstr "Vote"
|
||||
|
||||
#: cfp/forms.py:61 proposals/forms.py:72
|
||||
msgid "Filter talks you already / not yet voted for"
|
||||
msgstr ""
|
||||
"Filtrer les propositions pour lesquelles vous avez déjà voté / pas encore "
|
||||
"voté"
|
||||
|
||||
#: cfp/forms.py:70
|
||||
msgid "Not assigned"
|
||||
msgstr "Pas encore assignée."
|
||||
|
||||
#: cfp/forms.py:89
|
||||
msgid "New staff members will be informed of their new position by e-mail."
|
||||
msgstr ""
|
||||
"Les nouveaux membres du staff seront informés de leur nouveau rôle par "
|
||||
"courrier électronique."
|
||||
|
||||
#: cfp/forms.py:64
|
||||
#: cfp/forms.py:109
|
||||
msgid "An user with that firstname and that lastname already exists."
|
||||
msgstr "Un utilisateur avec ce prénom et ce nom existe déjà."
|
||||
|
||||
#: cfp/forms.py:69
|
||||
#: cfp/forms.py:114
|
||||
msgid "A user with that email already exists."
|
||||
msgstr "Un utilisateur avec cet email existe déjà."
|
||||
|
||||
|
@ -361,7 +411,7 @@ msgstr "Label dans le xml du programme"
|
|||
#: cfp/models.py:229 cfp/templates/cfp/staff/base.html:20
|
||||
#: cfp/templates/cfp/staff/participant_list.html:8
|
||||
#: cfp/templates/cfp/staff/talk_details.html:79
|
||||
#: cfp/templates/cfp/staff/talk_list.html:18 proposals/models.py:154
|
||||
#: cfp/templates/cfp/staff/talk_list.html:40 proposals/models.py:154
|
||||
#: proposals/templates/proposals/speaker_list.html:9
|
||||
#: proposals/templates/proposals/talk_detail.html:76
|
||||
#: proposals/templates/proposals/talk_list.html:49
|
||||
|
@ -376,15 +426,6 @@ msgstr "Titre de votre proposition:"
|
|||
msgid "Description of your talk"
|
||||
msgstr "Description de votre proposition"
|
||||
|
||||
#: cfp/models.py:234 cfp/templates/cfp/staff/talk_details.html:89
|
||||
#: cfp/templates/cfp/staff/talk_list.html:19 proposals/models.py:160
|
||||
#: proposals/templates/proposals/talk_detail.html:33
|
||||
#: proposals/templates/proposals/talk_detail.html:89
|
||||
#: proposals/templates/proposals/talk_list.html:51
|
||||
#: proposals/templates/proposals/track_form.html:14
|
||||
msgid "Track"
|
||||
msgstr "Session"
|
||||
|
||||
#: cfp/models.py:235
|
||||
msgid "Message to organizers"
|
||||
msgstr "Message aux organisateurs"
|
||||
|
@ -523,7 +564,7 @@ msgid "by"
|
|||
msgstr "par"
|
||||
|
||||
#: cfp/templates/cfp/staff/participant_details.html:41
|
||||
#: cfp/templates/cfp/staff/talk_list.html:35
|
||||
#: cfp/templates/cfp/staff/talk_list.html:57
|
||||
#: proposals/templates/proposals/_talk_list.html:11
|
||||
#: proposals/templates/proposals/_talk_list.html:17
|
||||
#: proposals/templates/proposals/talk_list.html:66
|
||||
|
@ -541,7 +582,7 @@ msgid "No talks"
|
|||
msgstr "Aucun exposé"
|
||||
|
||||
#: cfp/templates/cfp/staff/participant_list.html:45
|
||||
#: cfp/templates/cfp/staff/talk_list.html:11
|
||||
#: cfp/templates/cfp/staff/talk_list.html:33
|
||||
#: proposals/templates/proposals/speaker_list.html:44
|
||||
#: proposals/templates/proposals/talk_list.html:43
|
||||
#: volunteers/templates/volunteers/volunteer_list.html:25
|
||||
|
@ -619,10 +660,6 @@ msgstr "Décliner la proposition"
|
|||
msgid "No abstract provided."
|
||||
msgstr "Aucun résumé fourni."
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_details.html:71
|
||||
msgid "Category"
|
||||
msgstr "Catégorie"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_details.html:77
|
||||
#: proposals/templates/proposals/talk_detail.html:74
|
||||
msgid "No description provided."
|
||||
|
@ -648,18 +685,6 @@ msgstr "Aucune note."
|
|||
msgid "Moderation"
|
||||
msgstr "Modération"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_details.html:102
|
||||
#: cfp/templates/cfp/staff/talk_list.html:20
|
||||
#: proposals/templates/proposals/talk_detail.html:110
|
||||
#: proposals/templates/proposals/talk_list.html:52
|
||||
msgid "Status"
|
||||
msgstr "Statut"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_details.html:107
|
||||
#: proposals/templates/proposals/talk_detail.html:115
|
||||
msgid "Vote"
|
||||
msgstr "Vote"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_details.html:116
|
||||
#: proposals/templates/proposals/talk_detail.html:124
|
||||
msgid "vote"
|
||||
|
@ -670,7 +695,21 @@ msgstr "vote"
|
|||
msgid "average:"
|
||||
msgstr "moyenne :"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_list.html:11
|
||||
#: cfp/templates/cfp/staff/talk_list.html:10
|
||||
#: proposals/templates/proposals/speaker_list.html:11
|
||||
#: proposals/templates/proposals/talk_list.html:11
|
||||
#: volunteers/templates/volunteers/volunteer_list.html:11
|
||||
msgid "Show filtering options…"
|
||||
msgstr "Afficher les options de filtrage…"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_list.html:27
|
||||
#: proposals/templates/proposals/speaker_list.html:38
|
||||
#: proposals/templates/proposals/talk_list.html:35
|
||||
#: volunteers/templates/volunteers/volunteer_list.html:19
|
||||
msgid "Filter"
|
||||
msgstr "Filtrer"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_list.html:33
|
||||
#: planning/templates/planning/room_list.html:28
|
||||
#: proposals/templates/proposals/talk_list.html:43
|
||||
#: proposals/templates/proposals/topic_list.html:23
|
||||
|
@ -678,37 +717,27 @@ msgstr "moyenne :"
|
|||
msgid "talk"
|
||||
msgstr "exposé"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_list.html:16 proposals/models.py:155
|
||||
#: cfp/templates/cfp/staff/talk_list.html:38 proposals/models.py:155
|
||||
#: proposals/templates/proposals/talk_list.html:47
|
||||
msgid "Title"
|
||||
msgstr "Titre"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_list.html:17 proposals/models.py:162
|
||||
#: cfp/templates/cfp/staff/talk_list.html:39 proposals/models.py:162
|
||||
#: proposals/templates/proposals/talk_list.html:48
|
||||
msgid "Intervention kind"
|
||||
msgstr "Type d’intervention"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_list.html:42
|
||||
#: proposals/templates/proposals/talk_list.html:78
|
||||
msgid "Accepted"
|
||||
msgstr "Accepté"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_list.html:44
|
||||
#: proposals/templates/proposals/talk_list.html:80
|
||||
msgid "Declined"
|
||||
msgstr "Décliné"
|
||||
|
||||
#: cfp/templates/cfp/staff/talk_list.html:46
|
||||
#: cfp/templates/cfp/staff/talk_list.html:68
|
||||
#: proposals/templates/proposals/talk_list.html:82
|
||||
#, python-format
|
||||
msgid "Pending, score: %(score)s"
|
||||
msgstr "En cours, score : %(score)s"
|
||||
|
||||
#: cfp/views.py:62
|
||||
#: cfp/views.py:65
|
||||
msgid "Your talk \"{}\" has been submitted for {}"
|
||||
msgstr "Votre proposition \"{}\" a été transmise à {}"
|
||||
|
||||
#: cfp/views.py:63
|
||||
#: cfp/views.py:66
|
||||
msgid ""
|
||||
"Hi {},\n"
|
||||
"\n"
|
||||
|
@ -748,23 +777,23 @@ msgstr ""
|
|||
"{}\n"
|
||||
"\n"
|
||||
|
||||
#: cfp/views.py:154 proposals/views.py:321
|
||||
#: cfp/views.py:220 proposals/views.py:321
|
||||
msgid "Vote successfully created"
|
||||
msgstr "A voté !"
|
||||
|
||||
#: cfp/views.py:154 proposals/views.py:321
|
||||
#: cfp/views.py:220 proposals/views.py:321
|
||||
msgid "Vote successfully updated"
|
||||
msgstr "Vote mis à jour"
|
||||
|
||||
#: cfp/views.py:177 proposals/views.py:347
|
||||
#: cfp/views.py:243 proposals/views.py:347
|
||||
msgid "Decision taken in account"
|
||||
msgstr "Décision enregistrée"
|
||||
|
||||
#: cfp/views.py:214
|
||||
#: cfp/views.py:280
|
||||
msgid "[{}] You have been added to the staff team"
|
||||
msgstr "[{}] Vous avez été ajouté aux membres du staff"
|
||||
|
||||
#: cfp/views.py:215
|
||||
#: cfp/views.py:281
|
||||
msgid ""
|
||||
"Hi {},\n"
|
||||
"\n"
|
||||
|
@ -788,11 +817,11 @@ msgstr ""
|
|||
"{}\n"
|
||||
"\n"
|
||||
|
||||
#: cfp/views.py:235
|
||||
#: cfp/views.py:301
|
||||
msgid "Modifications successfully saved."
|
||||
msgstr "Modification enregistrée avec succès."
|
||||
|
||||
#: cfp/views.py:249
|
||||
#: cfp/views.py:315
|
||||
msgid "User created successfully."
|
||||
msgstr "Utilisateur créé avec succès."
|
||||
|
||||
|
@ -933,12 +962,6 @@ msgstr "Texte court, moins de 255 caractères"
|
|||
msgid "If you want to add some precisions for the organizers."
|
||||
msgstr "Si vous souhaitez apporter des précisions à l'équipe d'organisation."
|
||||
|
||||
#: proposals/forms.py:72
|
||||
msgid "Filter talks you already / not yet voted for"
|
||||
msgstr ""
|
||||
"Filtrer les propositions pour lesquelles vous avez déjà voté / pas encore "
|
||||
"voté"
|
||||
|
||||
#: proposals/forms.py:73
|
||||
msgid "Filter talks already / not yet affected to a room"
|
||||
msgstr "Filtrer les exposés déjà / pas encore affectées à une salle"
|
||||
|
@ -1090,18 +1113,6 @@ msgstr "Proposer un exposé"
|
|||
msgid "Sorry, the Call for Participation is closed."
|
||||
msgstr "Désolé, l’appel à participation est fermé."
|
||||
|
||||
#: proposals/templates/proposals/speaker_list.html:11
|
||||
#: proposals/templates/proposals/talk_list.html:11
|
||||
#: volunteers/templates/volunteers/volunteer_list.html:11
|
||||
msgid "Show filtering options…"
|
||||
msgstr "Afficher les options de filtrage…"
|
||||
|
||||
#: proposals/templates/proposals/speaker_list.html:38
|
||||
#: proposals/templates/proposals/talk_list.html:35
|
||||
#: volunteers/templates/volunteers/volunteer_list.html:19
|
||||
msgid "Filter"
|
||||
msgstr "Filtrer"
|
||||
|
||||
#: proposals/templates/proposals/speaker_list.html:48
|
||||
#: volunteers/templates/volunteers/volunteer_list.html:29
|
||||
msgid "Username"
|
||||
|
|
Loading…
Reference in New Issue
Block a user