forked from AFPy/PonyConf
add Track model
This commit is contained in:
parent
810228c2ac
commit
40429aa580
20
accounts/migrations/0009_auto_20160921_2236.py
Normal file
20
accounts/migrations/0009_auto_20160921_2236.py
Normal 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'),
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
48
proposals/migrations/0011_auto_20160921_2236.py
Normal file
48
proposals/migrations/0011_auto_20160921_2236.py
Normal 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')]),
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user