talk: batch actions

This commit is contained in:
Élie Bouttier 2017-08-12 16:57:12 +02:00
parent bb436f80a4
commit b332b72065
4 changed files with 59 additions and 27 deletions

View File

@ -98,6 +98,23 @@ class TalkFilterForm(forms.Form):
self.fields['track'].choices = [('none', _('Not assigned'))] + list(tracks.values_list('slug', 'name'))
class TalkActionForm(forms.Form):
talks = forms.MultipleChoiceField(choices=[])
decision = forms.NullBooleanField(label=_('Accept talk?'))
track = forms.ChoiceField(required=False, choices=[], label=_('Assign to a track'))
room = forms.ChoiceField(required=False, choices=[], label=_('Put in a room'))
def __init__(self, *args, **kwargs):
site = kwargs.pop('site')
talks = kwargs.pop('talks')
super().__init__(*args, **kwargs)
self.fields['talks'].choices = [(talk.token, None) for talk in talks.all()]
tracks = Track.objects.filter(site=site)
self.fields['track'].choices = [(None, "---------")] + list(tracks.values_list('slug', 'name'))
rooms = Room.objects.filter(site=site)
self.fields['room'].choices = [(None, "---------")] + list(rooms.values_list('slug', 'name'))
ParticipantForm = modelform_factory(Participant, fields=('name', 'email', 'biography'))

View File

@ -31,11 +31,13 @@
</div>
</div>
<form method="post">
<table class="table table-bordered table-hover">
<caption>{% trans "Total:" %} {{ talk_list|length }} {% trans "talk" %}{{ talk_list|length|pluralize }}</caption>
<thead>
<tr>
{% comment %}<th></th>{% endcomment %}
<th></th>
<th class="text-center">{% trans "Title" %} <a href="?{{ sort_urls.title }}"><span class="glyphicon glyphicon-{{ sort_glyphicons.title }} pull-right"></span></a></th>
<th class="text-center">{% trans "Intervention kind" %} <a href="?{{ sort_urls.category }}"><span class="glyphicon glyphicon-{{ sort_glyphicons.category }} pull-right"></span></a></th>
<th class="text-center">{% trans "Speakers" %}</th>
@ -48,7 +50,7 @@
<tbody>
{% endif %}
<tr class="{{ talk.accepted|yesno:"success,danger,warning" }}">
{% comment %}<td><input type="checkbox" name="talks" value="{{ talk.slug }}"></td>{% endcomment %}
<td><input type="checkbox" name="talks" value="{{ talk.token }}"></td>
<td><a href="{% url 'talk-details' talk.token %}">{{ talk.title }}</a></td>
<td>{{ talk.category }}</td>
<td>
@ -75,4 +77,18 @@
{% endfor %}
</table>
<div id="filter">
<div class="well">
<h4>{% trans "For selected talks:" %}</h4>
{% csrf_token %}
{% bootstrap_form_errors action_form %}
{% bootstrap_form action_form exclude="talks" %}
{% buttons %}
<button type="submit" class="btn btn-primary">{% trans "Apply" %}</button>
{% endbuttons %}
</div>
</div>
</form>
{% endblock %}

View File

@ -28,27 +28,5 @@ urlpatterns = [
url(r'^staff/rooms/(?P<slug>[-\w]+)/edit/$', views.RoomUpdate.as_view(), name='room-edit'),
url(r'^staff/add-user/$', views.create_user, name='create-user'),
url(r'^staff/select2/$', views.Select2View.as_view(), name='django_select2-json'),
#url(r'^markdown/$', views.markdown_preview, name='markdown'),
#url(r'^$', views.home, name='home'),
#url(r'^staff/$', views.staff, name='staff'),
#url(r'^conference/$', views.conference, name='edit-conference'),
#url(r'^talk/propose/$', views.participate, name='participate-as-speaker'),
#url(r'^talk/$', views.talk_list, name='list-talks'),
#url(r'^talk/add/$', views.talk_edit, name='add-talk'),
#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/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'^talk/assign-to-track/(?P<talk>[-\w]+)/(?P<track>[-\w]+)/$', views.talk_assign_to_track, name='assign-talk-to-track'),
#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'^track/$', views.TrackList.as_view(), name='list-tracks'),
#url(r'^track/add/$', views.TrackCreate.as_view(), name='add-track'),
#url(r'^track/(?P<slug>[-\w]+)/edit/$', views.TrackUpdate.as_view(), name='edit-track'),
#url(r'^speakers/$', views.speaker_list, name='list-speakers'),
#url(r'^register/$', views.talk_registrable_list, name='list-registrable-talks'),
#url(r'^register/(?P<talk>[-\w]+)$', views.talk_register, name='register-for-a-talk'),
]

View File

@ -18,7 +18,8 @@ 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, ParticipantForm, ParticipantStaffForm, ConferenceForm, CreateUserForm, STATUS_VALUES, TrackForm, RoomForm
from .forms import TalkForm, TalkStaffForm, TalkFilterForm, TalkActionForm, ParticipantForm, \
ParticipantStaffForm, ConferenceForm, CreateUserForm, STATUS_VALUES, TrackForm, RoomForm
def home(request):
@ -169,6 +170,25 @@ def talk_list(request):
talks = talks.filter(vote__user=request.user)
else:
talks = talks.exclude(vote__user=request.user)
# Action
action_form = TalkActionForm(request.POST or None, talks=talks, site=request.conference.site)
if request.method == 'POST' and action_form.is_valid():
data = action_form.cleaned_data
for talk in data['talks']:
talk = Talk.objects.get(site=request.conference.site, token=talk)
if data['decision'] != None and data['decision'] != talk.accepted:
if data['decision']:
note = _("The talk has been accepted.")
else:
note = _("The talk has been declined.")
Message.objects.create(thread=talk.conversation, author=request.user, content=note)
talk.accepted = data['decision']
if data['track']:
talk.track = Track.objects.get(site=request.conference.site, slug=data['track'])
if data['room']:
talk.room = Room.objects.get(site=request.conference.site, slug=data['room'])
talk.save()
return redirect(request.get_full_path())
# Sorting
if request.GET.get('order') == 'desc':
sort_reverse = True
@ -207,6 +227,7 @@ def talk_list(request):
'show_filters': show_filters,
'talk_list': talks,
'filter_form': filter_form,
'action_form': action_form,
'sort_urls': sort_urls,
'sort_glyphicons': sort_glyphicons,
})
@ -243,6 +264,8 @@ def talk_vote(request, talk_id, score):
def talk_decide(request, talk_id, accept):
talk = get_object_or_404(Talk, token=talk_id, site=request.conference.site)
if request.method == 'POST':
talk.accepted = accept
talk.save()
# Does we need to send a notification to the proposer?
m = request.POST.get('message', '').strip()
if m:
@ -254,8 +277,6 @@ def talk_decide(request, talk_id, accept):
else:
note = _("The talk has been declined.")
Message.objects.create(thread=talk.conversation, author=request.user, content=note)
talk.accepted = accept
talk.save()
messages.success(request, _('Decision taken in account'))
return redirect(talk.get_absolute_url())
return render(request, 'cfp/staff/talk_decide.html', {