speaker list filtering
This commit is contained in:
parent
7fe3582730
commit
802e1a36a3
|
@ -2,6 +2,7 @@ from django.contrib import admin
|
|||
|
||||
from accounts.models import Participation, Profile, Transport, Connector
|
||||
|
||||
|
||||
admin.site.register(Profile) # FIXME extend user admin
|
||||
admin.site.register(Participation)
|
||||
admin.site.register(Transport)
|
||||
|
|
|
@ -8,7 +8,7 @@ class TalkAdmin(admin.ModelAdmin):
|
|||
# (it is easy to obtain incoherent data due to site framework)
|
||||
def has_add_permission(self, request):
|
||||
return False
|
||||
# Filter for 'on site' tocpis and event
|
||||
# Filter for 'on site' topics and event
|
||||
def get_form(self, request, obj=None, **kwargs):
|
||||
form = super(TalkAdmin, self).get_form(request, obj, **kwargs)
|
||||
# in fact, obj should never be none as 'add' button is disabled
|
||||
|
|
|
@ -7,6 +7,8 @@ from django_select2.forms import Select2TagWidget
|
|||
|
||||
from proposals.models import Talk, Topic, Event, Conference
|
||||
|
||||
from accounts.models import Transport
|
||||
|
||||
|
||||
STATUS_CHOICES = [
|
||||
('pending', 'Pending decision'),
|
||||
|
@ -37,7 +39,7 @@ class TalkForm(forms.ModelForm):
|
|||
}
|
||||
|
||||
|
||||
class FilterForm(forms.Form):
|
||||
class TalkFilterForm(forms.Form):
|
||||
kind = forms.MultipleChoiceField(
|
||||
required=False,
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
|
@ -62,6 +64,25 @@ class FilterForm(forms.Form):
|
|||
self.fields['topic'].choices = topics.values_list('slug', 'name')
|
||||
|
||||
|
||||
class SpeakerFilterForm(forms.Form):
|
||||
transport = forms.MultipleChoiceField(
|
||||
required=False,
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
choices=Transport.objects.values_list('pk', 'name'),
|
||||
)
|
||||
hosting = forms.MultipleChoiceField(
|
||||
required=False,
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
choices=[
|
||||
('hotel', 'Hotel'),
|
||||
('homestay', 'Homestay'),
|
||||
],
|
||||
)
|
||||
sound = forms.NullBooleanField()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class TopicCreateForm(forms.ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.site_id = kwargs.pop('site_id')
|
||||
|
|
|
@ -1,22 +1,111 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 i18n %}
|
||||
|
||||
{% block speakertab %} class="active"{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{% trans "Speakers" %} ({{ user_list|length }})</h1>
|
||||
<h1>{% trans "Speakers" %}</h1>
|
||||
|
||||
<ul>
|
||||
{% for speaker in user_list %}
|
||||
<li>
|
||||
<a href="{% url 'show-speaker' username=speaker.username %}">{{ speaker.profile }}</a>
|
||||
({{ speaker.talk_set.count }} {% trans "talk" %}{{ speaker.talk_set.count|pluralize }})
|
||||
<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 />
|
||||
|
||||
<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-4 col-xs-6">
|
||||
{% bootstrap_field filter_form.transport layout="horizontal" %}
|
||||
</div>
|
||||
<div class="col-md-4 col-xs-6">
|
||||
{% bootstrap_field filter_form.hosting layout="horizontal" %}
|
||||
</div>
|
||||
<div class="col-md-4 col-xs-6">
|
||||
{% bootstrap_field filter_form.sound layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success" value="{% trans "Filter" %}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">{% trans "Username" %}</th>
|
||||
<th class="text-center">{% trans "Fullname" %}</th>
|
||||
<th class="text-center">{% trans "Talk count" %}</th>
|
||||
<th class="text-center">{% blocktrans context "table column title" %}Need transport?{% endblocktrans %}</th>
|
||||
<th class="text-center">{% blocktrans context "table column title" %}Need hosting?{% endblocktrans %}</th>
|
||||
<th class="text-center">{% trans "Need sound?" %}</th>
|
||||
<th class="text-center"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for speaker in speaker_list %}
|
||||
{% if forloop.first %}
|
||||
<tbody>
|
||||
{% endif %}
|
||||
<tr class="clickable-row" data-href="{% url 'show-speaker' username=speaker.user.username %}">
|
||||
<td>{{ speaker.user.username }}</td>
|
||||
<td>{{ speaker.user.get_full_name }}</td>
|
||||
<td class="text-right">{{ speaker.talk_set.count }}</td>
|
||||
{% if speaker.need_transport %}
|
||||
<td class="warning">
|
||||
{% for transport in speaker.transport.all %}
|
||||
{% if not forloop.first %}, {% endif %}
|
||||
{{ transport }}
|
||||
{% endfor %}
|
||||
</td>
|
||||
{% else %}
|
||||
<td>—</td>
|
||||
{% endif %}
|
||||
{% if speaker.need_hosting %}
|
||||
<td class="warning">
|
||||
{% if speaker.homestay %}
|
||||
Logement chez habitant
|
||||
{% else %}
|
||||
Hotel
|
||||
{% endif %}
|
||||
</td>
|
||||
{% else %}
|
||||
<td>—</td>
|
||||
{% endif %}
|
||||
{% if speaker.sound %}
|
||||
<td class="warning">Yes</td>
|
||||
{% else %}
|
||||
<td>No</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
<a class="btn btn-primary" href="{% url 'conversation' speaker.user.username %}">{% trans "Contact" %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li><i>{% trans "No speakers." %}</i></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if forloop.last %}
|
||||
</tbody>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan="5">{% trans "Total:" %} {{ speaker_list|length }} {% trans "speaker" %}{{ speaker_list|length|pluralize }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js_end %}
|
||||
<script type="text/javascript">
|
||||
jQuery(document).ready(function($) {
|
||||
$(".clickable-row").click(function() {
|
||||
window.location = $(this).data("href");
|
||||
});
|
||||
|
||||
var anchor = window.location.hash.replace("#", "");
|
||||
if (anchor == "filter") {
|
||||
$("#filter").collapse('show');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -8,7 +8,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">Show filtering options…</a>
|
||||
<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 />
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
|||
{% bootstrap_field filter_form.topic layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-success" value="Filter">
|
||||
<input type="submit" class="btn btn-success" value="{% trans "Filter" %}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,12 +12,11 @@ urlpatterns = [
|
|||
url(r'^talk/edit/(?P<talk>[-\w]+)$', views.talk_edit, name='edit-talk'),
|
||||
url(r'^talk/vote/(?P<talk>[-\w]+)/(?P<score>[-0-2]+)$', views.vote, name='vote'),
|
||||
url(r'^talk/details/(?P<slug>[-\w]+)$', views.TalkDetail.as_view(), name='show-talk'),
|
||||
#url(r'^talk/by-topic/(?P<topic>[-\w]+)$', views.talk_list_by_topic, name='list-talks-by-topic'),
|
||||
url(r'^talk/accept/(?P<talk>[-\w]+)/$', views.talk_decide, {'accepted': True}, name='accept-talk'),
|
||||
url(r'^talk/decline/(?P<talk>[-\w]+)/$', views.talk_decide, {'accepted': False}, name='decline-talk'),
|
||||
url(r'^topic/$', views.TopicList.as_view(), name='list-topics'),
|
||||
url(r'^topic/add/$', views.TopicCreate.as_view(), name='add-topic'),
|
||||
url(r'^topic/(?P<slug>[-\w]+)/edit/$', views.TopicUpdate.as_view(), name='edit-topic'),
|
||||
url(r'^speakers/$', views.SpeakerList.as_view(), name='list-speakers'),
|
||||
url(r'^speakers/$', views.speaker_list, name='list-speakers'),
|
||||
url(r'^speaker/(?P<username>[\w.@+-]+)$', views.user_details, name='show-speaker'),
|
||||
]
|
||||
|
|
|
@ -20,7 +20,7 @@ from accounts.decorators import orga_required, staff_required
|
|||
|
||||
from conversations.models import ConversationWithParticipant, ConversationAboutTalk, Message
|
||||
|
||||
from .forms import TalkForm, TopicCreateForm, TopicUpdateForm, ConferenceForm, FilterForm, STATUS_VALUES
|
||||
from .forms import TalkForm, TopicCreateForm, TopicUpdateForm, ConferenceForm, TalkFilterForm, STATUS_VALUES, SpeakerFilterForm
|
||||
from .models import Talk, Topic, Vote, Conference
|
||||
from .signals import talk_added, talk_edited
|
||||
from .utils import allowed_talks, markdown_to_html
|
||||
|
@ -64,7 +64,7 @@ def participate(request):
|
|||
def talk_list(request):
|
||||
show_filters = False
|
||||
talks = Talk.objects.filter(site=get_current_site(request))
|
||||
filter_form = FilterForm(request.GET or None, site=get_current_site(request))
|
||||
filter_form = TalkFilterForm(request.GET or None, site=get_current_site(request))
|
||||
# Filtering
|
||||
if filter_form.is_valid():
|
||||
data = filter_form.cleaned_data
|
||||
|
@ -192,14 +192,6 @@ class TopicUpdate(OrgaRequiredMixin, TopicMixin, TopicFormMixin, UpdateView):
|
|||
return TopicCreateForm if self.request.user.is_superuser else TopicUpdateForm
|
||||
|
||||
|
||||
class SpeakerList(StaffRequiredMixin, ListView):
|
||||
template_name = 'proposals/speaker_list.html'
|
||||
|
||||
def get_queryset(self):
|
||||
site = get_current_site(self.request)
|
||||
return User.objects.filter(talk__in=Talk.objects.filter(site=site)).all().distinct()
|
||||
|
||||
|
||||
@login_required
|
||||
def vote(request, talk, score):
|
||||
talk = get_object_or_404(Talk, site=get_current_site(request), slug=talk)
|
||||
|
@ -242,6 +234,36 @@ def talk_decide(request, talk, accepted):
|
|||
})
|
||||
|
||||
|
||||
@staff_required
|
||||
def speaker_list(request):
|
||||
show_filters = False
|
||||
site = get_current_site(request)
|
||||
speakers = Participation.objects.filter(user__talk__in=Talk.objects.filter(site=site)).all().distinct()
|
||||
filter_form = SpeakerFilterForm(request.GET or None)
|
||||
# Filtering
|
||||
if filter_form.is_valid():
|
||||
data = filter_form.cleaned_data
|
||||
if len(data['transport']):
|
||||
show_filters = True
|
||||
speakers = speakers.filter(reduce(lambda x, y: x | y, [Q(transport__pk=pk) for pk in data['transport']]))
|
||||
if len(data['hosting']):
|
||||
show_filters = True
|
||||
queries = []
|
||||
if 'hotel' in data['hosting']:
|
||||
queries += [ Q(need_hosting=True, homestay=False) ]
|
||||
if 'homestay' in data['hosting']:
|
||||
queries += [ Q(need_hosting=True, homestay=True) ]
|
||||
speakers = speakers.filter(reduce(lambda x, y: x | y, queries))
|
||||
if data['sound'] != None:
|
||||
show_filters = True
|
||||
speakers = speakers.filter(sound=data['sound'])
|
||||
return render(request, 'proposals/speaker_list.html', {
|
||||
'speaker_list': speakers,
|
||||
'filter_form': filter_form,
|
||||
'show_filters': show_filters,
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
def user_details(request, username):
|
||||
user = get_object_or_404(User, username=username)
|
||||
|
|
Loading…
Reference in New Issue