add Track model

This commit is contained in:
Élie Bouttier 2016-09-22 00:53:09 +02:00
parent 810228c2ac
commit 40429aa580
8 changed files with 140 additions and 13 deletions

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-09-21 22:36
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0008_auto_20160808_2251'),
]
operations = [
migrations.AlterField(
model_name='participation',
name='video_licence',
field=models.IntegerField(choices=[(1, 'CC-Zero'), (2, 'CC-BY'), (3, 'CC-BY-SA'), (4, 'CC-BY-ND'), (5, 'CC-BY-NC'), (6, 'CC-BY-NC-SA'), (7, 'CC-BY-NC-ND')], default=2, verbose_name='Video licence'),
),
]

View File

@ -1,6 +1,6 @@
from django.contrib import admin
from proposals.models import Conference, Talk, Topic, Event
from proposals.models import Conference, Talk, Topic, Track, Event
class TalkAdmin(admin.ModelAdmin):
@ -14,10 +14,12 @@ class TalkAdmin(admin.ModelAdmin):
# in fact, obj should never be none as 'add' button is disabled
if obj:
form.base_fields['topics'].queryset = Topic.objects.filter(site=obj.site)
form.base_fields['track'].queryset = Track.objects.filter(site=obj.site)
form.base_fields['event'].queryset = Event.objects.filter(site=obj.site)
return form
admin.site.register(Conference)
admin.site.register(Topic)
admin.site.register(Track)
admin.site.register(Talk, TalkAdmin)
admin.site.register(Event)

View File

@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
from django_select2.forms import Select2TagWidget
from proposals.models import Talk, Topic, Event, Conference
from proposals.models import Talk, Topic, Track, Event, Conference
from accounts.models import Transport
@ -27,11 +27,12 @@ class TalkForm(forms.ModelForm):
site = kwargs.pop('site')
super(TalkForm, self).__init__(*args, **kwargs)
self.fields['topics'].queryset = Topic.objects.filter(site=site)
self.fields['track'].queryset = Track.objects.filter(site=site)
self.fields['event'].queryset = Event.objects.filter(site=site)
class Meta:
model = Talk
fields = ['title', 'abstract', 'description', 'topics', 'notes', 'event', 'speakers']
fields = ['title', 'abstract', 'description', 'topics', 'track', 'notes', 'event', 'speakers']
widgets = {'topics': forms.CheckboxSelectMultiple(), 'speakers': Select2TagWidget()}
help_texts = {
'abstract': _('Should be less than 255 characters'),
@ -55,7 +56,12 @@ class TalkFilterForm(forms.Form):
widget=forms.CheckboxSelectMultiple,
choices=[],
)
vote = forms.NullBooleanField(help_text='Filter topics you already / not yet voted for')
track = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple,
choices=[],
)
vote = forms.NullBooleanField(help_text=_('Filter topics you already / not yet voted for'))
def __init__(self, *args, **kwargs):
site = kwargs.pop('site')
@ -64,6 +70,8 @@ class TalkFilterForm(forms.Form):
self.fields['kind'].choices = events.values_list('pk', 'name')
topics = Topic.objects.filter(site=site)
self.fields['topic'].choices = topics.values_list('slug', 'name')
tracks = Track.objects.filter(site=site)
self.fields['track'].choices = [('none', 'Not assigned')] + list(tracks.values_list('slug', 'name'))
class SpeakerFilterForm(forms.Form):

View File

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-09-21 22:36
from __future__ import unicode_literals
import autoslug.fields
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('sites', '0002_alter_domain_unique'),
('proposals', '0010_auto_20160822_1010'),
]
operations = [
migrations.CreateModel(
name='Track',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('name', models.CharField(max_length=128, verbose_name='Name')),
('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name')),
('description', models.TextField(blank=True, verbose_name='Description')),
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
],
),
migrations.AlterModelOptions(
name='event',
options={'ordering': ('pk',)},
),
migrations.AlterField(
model_name='talk',
name='event',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='proposals.Event', verbose_name='Intervention kind'),
),
migrations.AddField(
model_name='talk',
name='track',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='proposals.Track', verbose_name='Track'),
),
migrations.AlterUniqueTogether(
name='track',
unique_together=set([('site', 'name')]),
),
]

View File

@ -45,6 +45,21 @@ class Topic(PonyConfModel):
return reverse('list-talks') + '?topic=%s' % self.slug
class Track(PonyConfModel):
site = models.ForeignKey(Site, on_delete=models.CASCADE)
name = models.CharField(max_length=128, verbose_name=_('Name'))
slug = AutoSlugField(populate_from='name')
description = models.TextField(blank=True, verbose_name=_('Description'))
class Meta:
unique_together = ('site', 'name')
def __str__(self):
return self.name
class Event(models.Model):
site = models.ForeignKey(Site, on_delete=models.CASCADE)
@ -72,6 +87,7 @@ class Talk(PonyConfModel):
abstract = models.CharField(max_length=255, blank=True, verbose_name=_('Abstract'))
description = models.TextField(blank=True, verbose_name=_('Description'))
topics = models.ManyToManyField(Topic, blank=True, verbose_name=_('Topics'))
track = models.ForeignKey(Track, blank=True, null=True, verbose_name=_('Track'))
notes = models.TextField(blank=True, verbose_name=_('Notes'))
event = models.ForeignKey(Event, verbose_name=_('Intervention kind'))
accepted = models.NullBooleanField(default=None)

View File

@ -46,10 +46,18 @@
{% if moderate_perm %}
<h3>{% trans "Track:" %}</h3>
<p>{% if talk.track %}{{ talk.track }}{% else %}<em>{% trans "No assigned yet." %}</em>{% endif %}</p>
{% endif %}
<h3>{% trans "Notes:" %}</h3>
<p>{% if talk.notes %}{{ talk.notes }}{% else %}<i>{% trans "No notes." %}</i>{% endif %}</p>
{% if moderate_perm %}
<h2>{% trans "Moderation" %}</h2>
<h3>{% trans "Vote:" %}</h3>

View File

@ -17,14 +17,15 @@
<form class="form-horizontal" method="get">
<div class="row">
<div class="col-md-4 col-xs-6">
{% bootstrap_field filter_form.status layout="horizontal" %}
{% bootstrap_field filter_form.vote layout="horizontal" %}
{% bootstrap_field filter_form.kind layout="horizontal" %}
</div>
<div class="col-md-4 col-xs-6">
{% bootstrap_field filter_form.status layout="horizontal" %}
{% bootstrap_field filter_form.vote layout="horizontal" %}
{% bootstrap_field filter_form.topic layout="horizontal" %}
</div>
<div class="col-md-4 col-xs-6">
{% bootstrap_field filter_form.topic layout="horizontal" %}
{% bootstrap_field filter_form.track layout="horizontal" %}
</div>
</div>
<input type="submit" class="btn btn-success" value="{% trans "Filter" %}">
@ -39,6 +40,7 @@
<th class="text-center">{% trans "Intervention kind" %} <a href="?{{ sort_urls.kind }}"><span class="glyphicon glyphicon-{{ sort_glyphicons.kind }} pull-right"></span></a></th>
<th class="text-center">{% trans "Speakers" %}</th>
<th class="text-center">{% trans "Topics" %}</th>
<th class="text-center">{% trans "Track" %}</th>
<th class="text-center">{% trans "Status" %} <a href="?{{ sort_urls.status }}"><span class="glyphicon glyphicon-{{ sort_glyphicons.status }} pull-right"></span></a></th>
</tr>
</thead>
@ -46,24 +48,25 @@
{% if forloop.first %}
<tbody>
{% endif %}
<tr class="clickable-row" data-href="{% url 'show-talk' talk.slug %}">
<td class="{{ talk.accepted|yesno:"success,danger,warning" }}">{{ talk.title }}</td>
<td class="{{ talk.accepted|yesno:"success,danger,warning" }}">{{ talk.event }}</td>
<td class="{{ talk.accepted|yesno:"success,danger,warning" }}">
<tr class="clickable-row {{ talk.accepted|yesno:"success,danger,warning" }}" data-href="{% url 'show-talk' talk.slug %}">
<td>{{ talk.title }}</td>
<td>{{ talk.event }}</td>
<td>
{% for speaker in talk.speakers.all %}
{{ speaker }}
{% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %}
{% empty %}
{% endfor %}
</td>
<td class="{{ talk.accepted|yesno:"success,danger,warning" }}">
<td>
{% for topic in talk.topics.all %}
{{ topic }}
{% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %}
{% empty %}
{% endfor %}
</td>
<td class="{{ talk.accepted|yesno:"success,danger,warning" }}">
<td>{{ talk.track|default:"" }}</td>
<td>
{% if talk.accepted == True %}
{% trans "Accepted" %}
{% elif talk.accepted == False %}

View File

@ -17,6 +17,7 @@ from django.http import HttpResponse
from accounts.models import Participation
from accounts.mixins import OrgaRequiredMixin, StaffRequiredMixin
from accounts.decorators import orga_required, staff_required
from accounts.utils import is_staff
from conversations.models import ConversationWithParticipant, ConversationAboutTalk, Message
@ -77,6 +78,25 @@ def talk_list(request):
if len(data['topic']):
show_filters = True
talks = talks.filter(reduce(lambda x, y: x | y, [Q(topics__slug=topic) for topic in data['topic']]))
if len(data['track']):
show_filters = True
q1 = None
q2 = None
if 'none' in data['track']:
data['track'].remove('none')
q1 = Q(track__isnull=True)
if len(data['track']):
q2 = Q(track__slug__in=data['track'])
if q1 and q2:
q = q1 | q2
elif q1:
q = q1
elif q2:
q = q2
else:
q = None
if q:
talks = talks.filter(q)
if data['vote'] != None:
if data['vote']:
talks = talks.filter(vote__user=request.user)
@ -130,6 +150,8 @@ def talk_edit(request, talk=None):
if not talk.is_editable_by(request.user):
raise PermissionDenied()
form = TalkForm(request.POST or None, instance=talk, site=get_current_site(request))
if not is_staff(request, request.user):
form.fields.pop('track')
if talk:
form.fields['title'].disabled = True
form.fields['topics'].disabled = True