settings talks timeslot and room

This commit is contained in:
Élie Bouttier 2017-08-12 02:05:53 +02:00
parent d10d30b0cc
commit 39b765bb51
17 changed files with 436 additions and 246 deletions

View File

@ -9,7 +9,7 @@ from django.utils.crypto import get_random_string
from django_select2.forms import ModelSelect2MultipleWidget
from .models import Participant, Talk, TalkCategory, Track, Conference
from .models import Participant, Talk, TalkCategory, Track, Conference, Room
STATUS_CHOICES = [
@ -45,7 +45,7 @@ class TalkStaffForm(TalkForm):
self.fields['track'].queryset = tracks
class Meta(TalkForm.Meta):
fields = ('category', 'track', 'title', 'description','notes')
fields = ('category', 'track', 'title', 'description', 'notes', 'start_date', 'duration', 'room',)
labels = {
'category': _('Category'),
'title': _('Title'),
@ -80,6 +80,14 @@ class TalkFilterForm(forms.Form):
label=_('Vote'),
help_text=_('Filter talks you already / not yet voted for'),
)
room = forms.NullBooleanField(
label=_('Room'),
help_text=_('Filter talks already / not yet affected to a room'),
)
scheduled = forms.NullBooleanField(
label=_('Scheduled'),
help_text=_('Filter talks already / not yet scheduled'),
)
def __init__(self, *args, **kwargs):
site = kwargs.pop('site')
@ -150,11 +158,7 @@ class CreateUserForm(forms.ModelForm):
return user
class TrackForm(forms.ModelForm):
class Meta:
model = Track
fields = ['name', 'description']
class OnSiteNamedModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.conference = kwargs.pop('conference')
super().__init__(*args, **kwargs)
@ -168,8 +172,20 @@ class TrackForm(forms.ModelForm):
return name
def save(self, commit=True):
track = super().save(commit=False)
track.site = self.conference.site
obj = super().save(commit=False)
obj.site = self.conference.site
if commit:
track.save()
return track
obj.save()
return obj
class TrackForm(OnSiteNamedModelForm):
class Meta:
model = Track
fields = ['name', 'description']
class RoomForm(OnSiteNamedModelForm):
class Meta:
model = Room
fields = ['name', 'label', 'capacity']

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.3 on 2017-01-13 10:49
# Generated by Django 1.11.3 on 2017-08-11 23:42
from __future__ import unicode_literals
import autoslug.fields
@ -9,10 +9,9 @@ import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('sites', '0002_alter_domain_unique'),
('cfp', '0007_conference_secure_domain'),
]
operations = [
@ -30,6 +29,21 @@ class Migration(migrations.Migration):
'ordering': ['name'],
},
),
migrations.AddField(
model_name='talk',
name='start_date',
field=models.DateTimeField(blank=True, default=None, null=True, verbose_name='Beginning date and time'),
),
migrations.AlterField(
model_name='conference',
name='secure_domain',
field=models.BooleanField(default=True, verbose_name='Secure domain (HTTPS)'),
),
migrations.AddField(
model_name='talk',
name='room',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='cfp.Room'),
),
migrations.AlterUniqueTogether(
name='room',
unique_together=set([('site', 'name')]),

View File

@ -115,27 +115,6 @@ class Participant(PonyConfModel):
def __str__(self):
return str(self.name)
#def get_absolute_url(self):
# return reverse('show-participant', kwargs={'username': self.user.username})
#def is_orga(self):
# return self.orga
#def is_staff(self):
# return self.is_orga() or self.topic_set.exists() or self.track_set.exists()
#@property
#def topic_set(self):
# return self.user.topic_set.filter(site=self.site)
#@property
#def track_set(self):
# return self.user.track_set.filter(site=self.site)
#@property
#def talk_set(self):
# return self.user.talk_set.filter(site=self.site)
@property
def accepted_talk_set(self):
return self.talk_set.filter(accepted=True)
@ -145,9 +124,6 @@ class Participant(PonyConfModel):
@property
def refused_talk_set(self):
return self.talk_set.filter(accepted=False)
#@property
#def not_refused_talk_set(self): # accepted + pending
# return self.talk_set.exclude(accepted=False)
class Track(PonyConfModel):
@ -173,6 +149,37 @@ class Track(PonyConfModel):
return reverse('talk-list') + '?track=%s' % self.slug
class Room(models.Model):
site = models.ForeignKey(Site, on_delete=models.CASCADE)
slug = AutoSlugField(populate_from='name')
name = models.CharField(max_length=256, blank=True, default="")
label = models.CharField(max_length=256, blank=True, default="")
capacity = models.IntegerField(default=0)
class Meta:
unique_together = ['site', 'name']
ordering = ['name']
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('room-details', kwargs={'slug': self.slug})
@property
def talks(self):
return self.talk_set.exclude(accepted=False)
@property
def talks_by_date(self):
return self.talks.filter(start_date__isnull=False).exclude(duration=0, category__duration=0).order_by('start_date').all()
@property
def unscheduled_talks(self):
return self.talks.filter(Q(start_date__isnull=True) | Q(duration=0, category__duration=0)).all()
class TalkCategory(models.Model): # type of talk (conf 30min, 1h, stand, …)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
@ -200,8 +207,8 @@ class TalkCategory(models.Model): # type of talk (conf 30min, 1h, stand, …)
def __str__(self):
return ugettext(self.name)
#def get_absolute_url(self):
# return reverse('list-talks') + '?kind=%d' % self.pk
def get_absolute_url(self):
return reverse('talk-list') + '?category=%d' % self.pk
#class Attendee(PonyConfModel):
@ -252,7 +259,6 @@ class Talk(PonyConfModel):
site = models.ForeignKey(Site, on_delete=models.CASCADE)
#proposer = models.ForeignKey(User, related_name='+')
speakers = models.ManyToManyField(Participant, verbose_name=_('Speakers'))
title = models.CharField(max_length=128, verbose_name=_('Talk Title'))
slug = AutoSlugField(populate_from='title', unique=True)
@ -265,9 +271,9 @@ class Talk(PonyConfModel):
video_licence = models.CharField(choices=LICENCES, default='CC-BY-SA', max_length=10, verbose_name=_("Video licence"))
sound = models.BooleanField(_("I need sound"), default=False)
accepted = models.NullBooleanField(default=None)
#start_date = models.DateTimeField(null=True, blank=True, default=None)
start_date = models.DateTimeField(null=True, blank=True, default=None, verbose_name=_('Beginning date and time'))
duration = models.PositiveIntegerField(default=0, verbose_name=_('Duration (min)'))
#room = models.ForeignKey(Room, blank=True, null=True, default=None)
room = models.ForeignKey(Room, blank=True, null=True, default=None)
plenary = models.BooleanField(default=False)
#materials = models.FileField(null=True, upload_to=talk_materials_destination, verbose_name=_('Materials'),
# help_text=_('You can use this field to share some materials related to your intervention.'))
@ -287,7 +293,7 @@ class Talk(PonyConfModel):
return self.title
def get_speakers_str(self):
speakers = [str(Participant.objects.get(site=self.site, user=speaker)) for speaker in self.speakers.all()]
speakers = list(map(str, self.speakers.all()))
if len(speakers) == 0:
return 'superman'
elif len(speakers) == 1:
@ -309,13 +315,13 @@ class Talk(PonyConfModel):
else:
return None
#@property
#def dtstart(self):
# return self.start_date.strftime('%Y%m%dT%H%M%SZ')
@property
def dtstart(self):
return self.start_date.strftime('%Y%m%dT%H%M%SZ')
#@property
#def dtend(self):
# return self.end_date.strftime('%Y%m%dT%H%M%SZ')
@property
def dtend(self):
return self.end_date.strftime('%Y%m%dT%H%M%SZ')
#@property
#def materials_name(self):
@ -337,5 +343,5 @@ class Vote(PonyConfModel):
def __str__(self):
return "%+i by %s for %s" % (self.vote, self.user, self.talk)
#def get_absolute_url(self):
# return self.talk.get_absolute_url()
def get_absolute_url(self):
return self.talk.get_absolute_url()

View File

@ -9,7 +9,6 @@
{% comment %}
<li{% block topicstab %}{% endblock %}><a href="{% url 'list-topics' %}"><span class="glyphicon glyphicon-tag"></span>&nbsp;{% trans "Topics" %}</a></li>
<li{% block volunteerstab %}{% endblock %}><a href="{% url 'list-volunteers' %}"><span class="glyphicon glyphicon-thumbs-up"></span>&nbsp;{% trans "Volunteers" %}</a></li>
<li{% block roomstab %}{% endblock %}><a href="{% url 'list-rooms' %}"><span class="glyphicon glyphicon-tent"></span>&nbsp;{% trans "Rooms" %}</a></li>
<li{% block scheduletab %}{% endblock %}><a href="{% url 'show-schedule' %}"><span class="glyphicon glyphicon-calendar"></span>&nbsp;{% trans "Schedule" %}</a></li>
<li{% block correspondentstab %}{% endblock %}><a href="{% url 'list-correspondents' %}"><span class="glyphicon glyphicon-envelope"></span>&nbsp;{% trans "Correspondents" %}</a></li>
<li{% block conferencetab %}{% endblock %}><a href="{% url 'edit-conference' %}"><span class="glyphicon glyphicon-cog"></span>&nbsp;{% trans "Conference" %}</a></li>
@ -17,6 +16,7 @@
<li{% block talkstab %}{% endblock %}><a href="{% url 'talk-list' %}"><span class="glyphicon glyphicon-blackboard"></span>&nbsp;{% trans "Talks" %}</a></li>
<li{% block speakerstab %}{% endblock %}><a href="{% url 'participant-list' %}"><span class="glyphicon glyphicon-bullhorn"></span>&nbsp;{% trans "Speakers" %}</a></li>
<li{% block trackstab %}{% endblock %}><a href="{% url 'track-list' %}"><span class="glyphicon glyphicon-screenshot"></span>&nbsp;{% trans "Tracks" %}</a></li>
<li{% block roomstab %}{% endblock %}><a href="{% url 'room-list' %}"><span class="glyphicon glyphicon-tent"></span>&nbsp;{% trans "Rooms" %}</a></li>
<li{% block conferencetab %}{% endblock %}><a href="{% url 'conference' %}"><span class="glyphicon glyphicon-asterisk"></span>&nbsp;{% trans "Conference" %}</a></li>
{% if request.user.is_staff %}
<li><a href="{% url 'admin:index' %}"><span class="glyphicon glyphicon-dashboard"></span>&nbsp;Django-Admin</a></li>

View File

@ -0,0 +1,48 @@
{% extends 'cfp/staff/base.html' %}
{% load bootstrap3 cfp_tags i18n %}
{% block roomstab %} class="active"{% endblock %}
{% block content %}
<h1>{{ room.name }}
<small>{{ room.label }}</small>
</h1>
<h2>{% trans "Scheduled talks" %}</h2>
{% for talk in room.talks_by_date %}
{% if forloop.first %}<ul>{% endif %}
<li>
<a href="{{ talk.get_absolute_url }}"><strong>{{ talk }}</strong></a>
{% for participant in talk.speakers.all %}
{% if forloop.first %} &ndash; <em>{% endif %}
<a href="{% url 'participant-details' participant.token %}">{{ participant }}</a>
{% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %}
{% if forloop.last %}</em>{% endif %}
{% endfor %}
&ndash; <span>{{ talk.start_date }} &ndash; {% if talk.end_date %}{{ talk.end_date|date:"H:i" }}{% else %}?{% endif %}</span>
</li>
{% if forloop.last %}</ul>{% endif %}
{% empty %}
<em>{% trans "No talks." %}</em>
{% endfor %}
<h3>{% trans "Unscheduled talks" %}</h3>
{% for talk in room.unscheduled_talks %}
{% if forloop.first %}<ul>{% endif %}
<li>
<a href="{{ talk.get_absolute_url }}"><strong>{{ talk }}</strong></a>
{% for participant in talk.speakers.all %}
{% if forloop.first %} &ndash; <em>{% endif %}
<a href="{% url 'participant-details' participant.token %}">{{ participant }}</a>
{% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %}
{% if forloop.last %}</em>{% endif %}
{% endfor %}
</li>
{% if forloop.last %}</ul>{% endif %}
{% empty %}
<em>{% trans "No talks." %}</em>
{% endfor %}
{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends 'cfp/staff/base.html' %}
{% load bootstrap3 i18n %}
{% block roomstab %} class="active"{% endblock %}
{% block css %}
{{ block.super }}
{{ form.media.css }}
{% endblock %}
{% block content %}
<h1>{% trans "Room" %}</h1>
{% include "_form.html" %}
{% endblock %}
{% block js_end %}
{{ block.super }}
{{ form.media.js }}
{% endblock %}

View File

@ -0,0 +1,46 @@
{% extends 'cfp/staff/base.html' %}
{% load bootstrap3 cfp_tags i18n %}
{% block roomstab %} class="active"{% endblock %}
{% block content %}
<h1>{% trans "Rooms" %}</h1>
<p><a href="{% url 'room-add' %}" class="btn btn-success">{% trans "Add a room" %}</a><p>
<div class="row">
{% for room in room_list %}
<div class="col-xs-6 col-sm-4">
<h2>
<a href="{{ room.get_absolute_url }}">{{ room }}</a>
</h2>
{% if room.label %}<p>{{ room.label }}</p>{% endif %}
<p>
{{ room.capacity }} {% trans "place" %}{{ room.capacity|pluralize }}
|
<span{% if room.unscheduled_talks %} class="text-danger" data-toggle="tooltip" data-placement="bottom" title="{% trans "Some talks are not scheduled yet." %}"{% endif %}>
{{ room.talks.count }} {% trans "talk" %}{{ room.talks.count|pluralize }}
</span>
|
<a href="{% url 'room-edit' room.slug %}">{% bootstrap_icon "pencil" %}</a>
</p>
</div>
{% cycle '' '<div class="clearfix visible-xs"></div>' %}
{% cycle '' '' '<div class="clearfix hidden-xs"></div>' %}
{% empty %}
<div class="col-xs-12"><em>{% trans "No rooms." %}</em></div>
{% endfor %}
</div>
{% endblock %}
{% block js_end %}
{{ block.super }}
<script type="text/javascript">
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
</script>
{% endblock %}

View File

@ -9,36 +9,30 @@
<p><a class="btn btn-success" href="{% url 'talk-edit' talk.token %}">{% trans "Edit" %}</a></p>
<p>{% if talk.abstract %}{{ talk.abstract }}{% else %}<i>{% trans "No abstract provided." %}</i>{% endif %}</p>
{% comment %}
{% if moderate_perm %}
<h3>{% trans "Information" %}</h3>
<dl class="dl-horizontal">
<dt>{% trans "Format" %}</dt>
<dd><a href="{{ talk.event.get_absolute_url }}">{{ talk.event }}</a></dd>
<dt>{% trans "Topics" %}</dt>
<dd>{% for topic in talk.topics.all %}
<a href="{{ topic.get_absolute_url }}">{{ topic }}</a>{% if not forloop.last %}, {% endif %}
{% empty %}
<i>{% trans "No topics." %}</i>
{% endfor %}</dd>
<dt>{% trans "Category" %}</dt>
<dd><a href="{{ talk.category.get_absolute_url }}">{{ talk.category }}</a></dd>
<dt>{% trans "Status" %}</dt>
<dd><span class="label label-{{ talk.accepted|yesno:"success,danger,warning" }}">{{ talk.accepted|yesno:"Accepted,Declined,Pending decision" }}</span></dd>
<dt>{% trans "Track" %}</dt>
<dd>{% if talk.track %}
<a href="{{ talk.track.get_absolute_url }}">{{ talk.track }}</a>
{% else %}
<em>{% trans "No assigned yet." %}</em>
<em>{% trans "No assigned yet." context "session" %}</em>
{% endif %}</dd>
<dt>Horaire</dt>
<dt>{% trans "Timeslot" %}</dt>
<dd>{% if talk.start_date %}
<span class="date">{{ talk.start_date|date:"l d b" }}</span>,
<span class="time">{{ talk.start_date|date:"H:i" }} &ndash; {% if talk.end_date %}{{ talk.end_date|date:"H:i" }}{% else %}?{% endif %}</span>
{% else %}<em>{% trans "not defined" %}</em>
{% endif %}
</dd>
<dt>Salle</dt>
<dt>{% trans "Room" %}</dt>
<dd>{% if talk.room %}
<a href="{{ talk.room.get_absolute_url }}">
<span class="label label-info">{{ talk.room }}</span>
@ -46,6 +40,7 @@
{% else %}<em>{% trans "not defined" %}</em>
{% endif %}
</dd>
{% comment %}
{% if talk.registration_required %}
<dt>{% trans "Registrations" %}</dt>
<dd>{% if talk.attendees_limit %}{{ talk.attendees.count }} / {{ talk.attendees_limit }}{% else %}{% trans "required but unlimited" %}{% endif %}</dd>
@ -58,16 +53,10 @@
<dt>{% trans "Video" %}</dt>
<dd><a href="{{ talk.video }}">{% trans "download" %}</a></dd>
{% endif %}
{% endcomment %}
</dl>
{% endif %}
{% endcomment %}
<h3>{% trans "Category" %}</h3>
<p>{{ talk.category }}</p>
<h3>{% trans "Description" %}</h3>
<p>{% if talk.description %}{{ talk.description|linebreaksbr }}{% else %}<i>{% trans "No description provided." %}</i>{% endif %}</p>
@ -82,13 +71,6 @@
<i>{% trans "No speakers." %}</i>
{% endfor %}
<h3>{% trans "Track" %}</h3>
{% if talk.track %}
<p>{{ talk.track }}</p>
{% else %}
<p><em>{% trans "No assigned yet." context "session" %}</em></p>
{% endif %}
<h3>{% trans "Notes" %}</h3>
<p>{% if talk.notes %}{{ talk.notes|linebreaksbr }}{% else %}<i>{% trans "No notes." %}</i>{% endif %}</p>
@ -97,8 +79,6 @@
<h3>{% trans "Status" %}</h3>
<span class="label label-{{ talk.accepted|yesno:"success,danger,warning" }}">{{ talk.accepted|yesno:"Accepted,Declined,Pending decision" }}</span><br />
{% if talk.accepted == None %}
<h3>{% trans "Vote" %}</h3>
<div class="btn-group" role="group" aria-label="vote">

View File

@ -19,6 +19,8 @@
{% bootstrap_field filter_form.status layout="horizontal" %}
{% bootstrap_field filter_form.category layout="horizontal" %}
{% bootstrap_field filter_form.vote layout="horizontal" %}
{% bootstrap_field filter_form.scheduled layout="horizontal" %}
{% bootstrap_field filter_form.room layout="horizontal" %}
</div>
<div class="col-md-6 col-xs-6">
{% bootstrap_field filter_form.track layout="horizontal" %}

View File

@ -22,6 +22,10 @@ urlpatterns = [
url(r'^staff/tracks/$', views.TrackList.as_view(), name='track-list'),
url(r'^staff/tracks/add/$', views.TrackCreate.as_view(), name='track-add'),
url(r'^staff/tracks/(?P<slug>[-\w]+)/edit/$', views.TrackUpdate.as_view(), name='track-edit'),
url(r'^staff/rooms/$', views.RoomList.as_view(), name='room-list'),
url(r'^staff/rooms/add/$', views.RoomCreate.as_view(), name='room-add'),
url(r'^staff/rooms/(?P<slug>[-\w]+)/$', views.RoomDetail.as_view(), name='room-details'),
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'),

View File

@ -17,8 +17,8 @@ from mailing.forms import MessageForm
from .decorators import staff_required
from .mixins import StaffRequiredMixin, OnSiteMixin
from .utils import is_staff
from .models import Participant, Talk, TalkCategory, Vote, Track
from .forms import TalkForm, TalkStaffForm, TalkFilterForm, ParticipantForm, ParticipantStaffForm, ConferenceForm, CreateUserForm, STATUS_VALUES, TrackForm
from .models import Participant, Talk, TalkCategory, Vote, Track, Room
from .forms import TalkForm, TalkStaffForm, TalkFilterForm, ParticipantForm, ParticipantStaffForm, ConferenceForm, CreateUserForm, STATUS_VALUES, TrackForm, RoomForm
def home(request, conference):
@ -147,6 +147,12 @@ def talk_list(request, conference):
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 data['room'] != None:
show_filters = True
talks = talks.filter(room__isnull=not data['room'])
if data['scheduled'] != None:
show_filters = True
talks = talks.filter(start_date__isnull=not data['scheduled'])
if len(data['track']):
show_filters = True
q = Q()
@ -380,6 +386,39 @@ class TrackUpdate(StaffRequiredMixin, TrackFormMixin, UpdateView):
pass
class RoomMixin(OnSiteMixin):
model = Room
class RoomList(StaffRequiredMixin, RoomMixin, ListView):
template_name = 'cfp/staff/room_list.html'
class RoomDetail(StaffRequiredMixin, RoomMixin, DetailView):
template_name = 'cfp/staff/room_details.html'
class RoomFormMixin(RoomMixin):
template_name = 'cfp/staff/room_form.html'
form_class = RoomForm
success_url = reverse_lazy('room-list')
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update({
'conference': self.kwargs['conference'],
})
return kwargs
class RoomCreate(StaffRequiredMixin, RoomFormMixin, CreateView):
pass
class RoomUpdate(StaffRequiredMixin, RoomFormMixin, UpdateView):
pass
@staff_required
def create_user(request, conference):
form = CreateUserForm(request.POST or None)

Binary file not shown.

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-08-11 22:51+0000\n"
"POT-Creation-Date: 2017-08-12 00:02+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"
@ -107,7 +107,7 @@ msgid "Biography"
msgstr "Biographie"
#: accounts/templates/accounts/participant_details.html:27
#: cfp/templates/cfp/staff/base.html:18
#: cfp/templates/cfp/staff/base.html:17
#: cfp/templates/cfp/staff/participant_details.html:33
#: cfp/templates/cfp/staff/talk_list.html:8
#: proposals/templates/proposals/talk_list.html:9
@ -115,6 +115,7 @@ msgid "Talks"
msgstr "Exposés"
#: accounts/templates/accounts/participant_details.html:32
#: cfp/templates/cfp/staff/talk_details.html:12
msgid "Information"
msgstr "Informations"
@ -176,7 +177,7 @@ msgstr "Contraintes"
#: accounts/templates/accounts/participant_details.html:71 cfp/forms.py:53
#: cfp/models.py:100 cfp/templates/cfp/staff/participant_details.html:16
#: cfp/templates/cfp/staff/talk_details.html:92 proposals/models.py:161
#: cfp/templates/cfp/staff/talk_details.html:75 proposals/models.py:161
#: proposals/templates/proposals/talk_detail.html:102
msgid "Notes"
msgstr "Notes"
@ -292,27 +293,27 @@ msgstr "%(name)s est déjà participant"
msgid "Pending decision"
msgstr "Décision en attente"
#: cfp/forms.py:17 cfp/templates/cfp/staff/talk_list.html:64
#: cfp/forms.py:17 cfp/templates/cfp/staff/talk_list.html:66
#: proposals/templates/proposals/talk_list.html:78
msgid "Accepted"
msgstr "Accepté"
#: cfp/forms.py:18 cfp/templates/cfp/staff/talk_list.html:66
#: cfp/forms.py:18 cfp/templates/cfp/staff/talk_list.html:68
#: proposals/templates/proposals/talk_list.html:80
msgid "Declined"
msgstr "Décliné"
#: cfp/forms.py:50 cfp/forms.py:62 cfp/templates/cfp/staff/talk_details.html:67
#: cfp/forms.py:50 cfp/forms.py:62 cfp/templates/cfp/staff/talk_details.html:15
msgid "Category"
msgstr "Catégorie"
#: cfp/forms.py:51 cfp/templates/cfp/staff/talk_list.html:38
#: cfp/forms.py:51 cfp/templates/cfp/staff/talk_list.html:40
#: proposals/models.py:155 proposals/templates/proposals/talk_list.html:47
msgid "Title"
msgstr "Titre"
#: cfp/forms.py:52 cfp/models.py:159
#: cfp/templates/cfp/staff/talk_details.html:71 proposals/models.py:54
#: cfp/forms.py:52 cfp/models.py:135
#: cfp/templates/cfp/staff/talk_details.html:61 proposals/models.py:54
#: proposals/models.py:77 proposals/models.py:158
#: proposals/templates/proposals/talk_detail.html:72 volunteers/models.py:14
msgid "Description"
@ -322,16 +323,17 @@ msgstr "Description"
msgid "Visible by speakers"
msgstr "Visible par les orateurs"
#: cfp/forms.py:68 cfp/templates/cfp/staff/talk_details.html:98
#: cfp/templates/cfp/staff/talk_list.html:42
#: cfp/forms.py:68 cfp/templates/cfp/staff/talk_details.html:18
#: cfp/templates/cfp/staff/talk_details.html:81
#: cfp/templates/cfp/staff/talk_list.html:44
#: proposals/templates/proposals/talk_detail.html:110
#: proposals/templates/proposals/talk_list.html:52
msgid "Status"
msgstr "Statut"
#: cfp/forms.py:74 cfp/models.py:261
#: cfp/templates/cfp/staff/talk_details.html:85
#: cfp/templates/cfp/staff/talk_list.html:41
#: cfp/forms.py:74 cfp/models.py:267
#: cfp/templates/cfp/staff/talk_details.html:21
#: cfp/templates/cfp/staff/talk_list.html:43
#: cfp/templates/cfp/staff/track_form.html:14 proposals/models.py:160
#: proposals/templates/proposals/talk_detail.html:33
#: proposals/templates/proposals/talk_detail.html:89
@ -340,7 +342,7 @@ msgstr "Statut"
msgid "Track"
msgstr "Session"
#: cfp/forms.py:80 cfp/templates/cfp/staff/talk_details.html:103
#: cfp/forms.py:80 cfp/templates/cfp/staff/talk_details.html:84
#: proposals/templates/proposals/talk_detail.html:115
msgid "Vote"
msgstr "Vote"
@ -351,27 +353,44 @@ msgstr ""
"Filtrer les propositions pour lesquelles vous avez déjà voté / pas encore "
"voté"
#: cfp/forms.py:90
#: cfp/forms.py:84 cfp/templates/cfp/staff/room_form.html:14
#: cfp/templates/cfp/staff/talk_details.html:35
msgid "Room"
msgstr "Salle"
#: cfp/forms.py:85 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"
#: cfp/forms.py:88
msgid "Scheduled"
msgstr "Programmé"
#: cfp/forms.py:89 proposals/forms.py:74
msgid "Filter talks already / not yet scheduled"
msgstr "Filtrer les exposés déjà / pas encore planifiées"
#: cfp/forms.py:98
msgid "Not assigned"
msgstr "Pas encore assignée."
#: cfp/forms.py:99 cfp/models.py:157
#: cfp/forms.py:107 cfp/models.py:133
#: cfp/templates/cfp/staff/participant_list.html:49 proposals/models.py:52
#: proposals/models.py:75 proposals/models.py:132 volunteers/models.py:12
msgid "Name"
msgstr "Nom"
#: cfp/forms.py:116
#: cfp/forms.py:124
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:136
#: cfp/forms.py:144
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:141
#: cfp/forms.py:149
msgid "A user with that email already exists."
msgstr "Un utilisateur avec cet email existe déjà."
@ -424,41 +443,41 @@ msgstr "Votre Nom"
msgid "This field is only visible by organizers."
msgstr "Ce champs est uniquement visible par les organisateurs."
#: cfp/models.py:180 proposals/models.py:96
#: cfp/models.py:187 proposals/models.py:96
msgid "Default duration (min)"
msgstr "Durée par défaut (min)"
#: cfp/models.py:181 proposals/models.py:97
#: cfp/models.py:188 proposals/models.py:97
msgid "Color on program"
msgstr "Couleur sur le programme"
#: cfp/models.py:182 proposals/models.py:98
#: cfp/models.py:189 proposals/models.py:98
msgid "Label on program"
msgstr "Label dans le xml du programme"
#: cfp/models.py:256 cfp/templates/cfp/staff/base.html:19
#: cfp/models.py:262 cfp/templates/cfp/staff/base.html:18
#: cfp/templates/cfp/staff/participant_list.html:8
#: cfp/templates/cfp/staff/talk_details.html:75
#: cfp/templates/cfp/staff/talk_list.html:40 proposals/models.py:154
#: cfp/templates/cfp/staff/talk_details.html:65
#: cfp/templates/cfp/staff/talk_list.html:42 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
msgid "Speakers"
msgstr "Orateurs"
#: cfp/models.py:257
#: cfp/models.py:263
msgid "Talk Title"
msgstr "Titre de votre proposition:"
#: cfp/models.py:260
#: cfp/models.py:266
msgid "Description of your talk"
msgstr "Description de votre proposition"
#: cfp/models.py:262
#: cfp/models.py:268
msgid "Message to organizers"
msgstr "Message aux organisateurs"
#: cfp/models.py:262
#: cfp/models.py:268
msgid ""
"If you have any constraint or if you have anything that may help you to "
"select your talk, like a video or slides of your talk, please write it down "
@ -468,23 +487,27 @@ msgstr ""
"votre proposition, comme une vidéo, des slides, n'hésitez pas à les ajouter "
"ici."
#: cfp/models.py:263
#: cfp/models.py:269
msgid "Talk Category"
msgstr "Catégorie de proposition"
#: cfp/models.py:264
#: cfp/models.py:270
msgid "I'm ok to be recorded on video"
msgstr "Jaccepte dêtre enregistré en vidéo"
#: cfp/models.py:265
#: cfp/models.py:271
msgid "Video licence"
msgstr "Licence vidéo"
#: cfp/models.py:266
#: cfp/models.py:272
msgid "I need sound"
msgstr "Jai besoin de son"
#: cfp/models.py:269 proposals/models.py:165
#: cfp/models.py:274
msgid "Beginning date and time"
msgstr "Date et heure de début"
#: cfp/models.py:275 proposals/models.py:165
msgid "Duration (min)"
msgstr "Durée (min)"
@ -547,12 +570,18 @@ msgstr "Un mail vous a été envoyé avec toutes les URLs"
msgid "Save"
msgstr "Envoyer"
#: cfp/templates/cfp/staff/base.html:20
#: cfp/templates/cfp/staff/base.html:19
#: cfp/templates/cfp/staff/track_list.html:9
#: proposals/templates/proposals/track_list.html:9
msgid "Tracks"
msgstr "Sessions"
#: cfp/templates/cfp/staff/base.html:20
#: cfp/templates/cfp/staff/room_list.html:9
#: planning/templates/planning/room_list.html:9
msgid "Rooms"
msgstr "Salles"
#: cfp/templates/cfp/staff/base.html:21
#: cfp/templates/cfp/staff/conference.html:8
msgid "Conference"
@ -613,7 +642,9 @@ msgid "by"
msgstr "par"
#: cfp/templates/cfp/staff/participant_details.html:43
#: cfp/templates/cfp/staff/talk_list.html:57
#: cfp/templates/cfp/staff/room_details.html:21
#: cfp/templates/cfp/staff/room_details.html:39
#: cfp/templates/cfp/staff/talk_list.html:59
#: proposals/templates/proposals/_talk_list.html:11
#: proposals/templates/proposals/_talk_list.html:17
#: proposals/templates/proposals/talk_list.html:66
@ -631,7 +662,7 @@ msgid "No talks"
msgstr "Aucun exposé"
#: cfp/templates/cfp/staff/participant_details.html:55
#: cfp/templates/cfp/staff/talk_details.html:133
#: cfp/templates/cfp/staff/talk_details.html:114
msgid "Messaging"
msgstr "Messagerie"
@ -648,7 +679,7 @@ msgid "Edit a speaker"
msgstr "Éditer un orateur"
#: cfp/templates/cfp/staff/participant_list.html:45
#: cfp/templates/cfp/staff/talk_list.html:33
#: cfp/templates/cfp/staff/talk_list.html:35
#: proposals/templates/proposals/speaker_list.html:44
#: proposals/templates/proposals/talk_list.html:43
#: volunteers/templates/volunteers/volunteer_list.html:25
@ -686,6 +717,54 @@ msgid_plural "refused: %(refused)s"
msgstr[0] "refusé : %(refused)s"
msgstr[1] "refusés : %(refused)s"
#: cfp/templates/cfp/staff/room_details.html:13
#: planning/templates/planning/room_detail.html:14
msgid "Scheduled talks"
msgstr "Exposés planifiés"
#: cfp/templates/cfp/staff/room_details.html:28
#: cfp/templates/cfp/staff/room_details.html:45
#: planning/templates/planning/room_detail.html:23
#: planning/templates/planning/room_detail.html:34
msgid "No talks."
msgstr "Aucun exposé."
#: cfp/templates/cfp/staff/room_details.html:31
#: planning/templates/planning/room_detail.html:26
msgid "Unscheduled talks"
msgstr "Exposés non planifiés"
#: cfp/templates/cfp/staff/room_list.html:11
#: planning/templates/planning/room_form.html:14
#: planning/templates/planning/room_list.html:12
msgid "Add a room"
msgstr "Ajouter une salle"
#: cfp/templates/cfp/staff/room_list.html:21
#: planning/templates/planning/room_list.html:24
msgid "place"
msgstr "place"
#: cfp/templates/cfp/staff/room_list.html:23
#: planning/templates/planning/room_list.html:27
msgid "Some talks are not scheduled yet."
msgstr "Certains exposés ne sont pas encore planifiés."
#: cfp/templates/cfp/staff/room_list.html:24
#: cfp/templates/cfp/staff/talk_list.html:35
#: cfp/templates/cfp/staff/track_list.html:21
#: planning/templates/planning/room_list.html:28
#: proposals/templates/proposals/talk_list.html:43
#: proposals/templates/proposals/topic_list.html:23
#: proposals/templates/proposals/track_list.html:23
msgid "talk"
msgstr "exposé"
#: cfp/templates/cfp/staff/room_list.html:33
#: planning/templates/planning/room_list.html:40
msgid "No rooms."
msgstr "Aucune salle."
#: cfp/templates/cfp/staff/talk_decide.html:8
#: proposals/templates/proposals/talk_decide.html:9
msgid "Are you sure to accept this proposals?"
@ -736,47 +815,53 @@ msgstr "Accepter la proposition"
msgid "Decline the proposal"
msgstr "Décliner la proposition"
#: cfp/templates/cfp/staff/talk_details.html:12
#: proposals/templates/proposals/talk_detail.html:19
msgid "No abstract provided."
msgstr "Aucun résumé fourni."
#: cfp/templates/cfp/staff/talk_details.html:73
#: proposals/templates/proposals/talk_detail.html:74
msgid "No description provided."
msgstr "Aucune description fournie."
#: cfp/templates/cfp/staff/talk_details.html:82
#: proposals/templates/proposals/talk_detail.html:83
msgid "No speakers."
msgstr "Aucun orateur."
#: cfp/templates/cfp/staff/talk_details.html:89
#: cfp/templates/cfp/staff/talk_details.html:25
msgctxt "session"
msgid "No assigned yet."
msgstr "Pas encore assignée."
#: cfp/templates/cfp/staff/talk_details.html:94
#: cfp/templates/cfp/staff/talk_details.html:28
msgid "Timeslot"
msgstr "Créneau"
#: cfp/templates/cfp/staff/talk_details.html:32
#: cfp/templates/cfp/staff/talk_details.html:40
#: proposals/templates/proposals/talk_detail.html:44
#: proposals/templates/proposals/talk_detail.html:52
msgid "not defined"
msgstr "non défini"
#: cfp/templates/cfp/staff/talk_details.html:63
#: proposals/templates/proposals/talk_detail.html:74
msgid "No description provided."
msgstr "Aucune description fournie."
#: cfp/templates/cfp/staff/talk_details.html:72
#: proposals/templates/proposals/talk_detail.html:83
msgid "No speakers."
msgstr "Aucun orateur."
#: cfp/templates/cfp/staff/talk_details.html:77
#: proposals/templates/proposals/talk_detail.html:104
msgid "No notes."
msgstr "Aucune note."
#: cfp/templates/cfp/staff/talk_details.html:96
#: cfp/templates/cfp/staff/talk_details.html:79
#: proposals/templates/proposals/talk_detail.html:108
msgid "Moderation"
msgstr "Modération"
#: cfp/templates/cfp/staff/talk_details.html:112
#: cfp/templates/cfp/staff/talk_details.html:93
#: proposals/templates/proposals/talk_detail.html:124
msgid "vote"
msgstr "vote"
#: cfp/templates/cfp/staff/talk_details.html:112
#: cfp/templates/cfp/staff/talk_details.html:93
#: proposals/templates/proposals/talk_detail.html:124
msgid "average:"
msgstr "moyenne :"
#: cfp/templates/cfp/staff/talk_details.html:137
#: cfp/templates/cfp/staff/talk_details.html:118
msgid ""
"Comment this talk <em>this message will be received by the staff team "
"only</em>"
@ -796,28 +881,19 @@ msgstr "Éditer un exposé"
msgid "Show filtering options…"
msgstr "Afficher les options de filtrage…"
#: cfp/templates/cfp/staff/talk_list.html:27
#: cfp/templates/cfp/staff/talk_list.html:29
#: 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
#: cfp/templates/cfp/staff/track_list.html:21
#: planning/templates/planning/room_list.html:28
#: proposals/templates/proposals/talk_list.html:43
#: proposals/templates/proposals/topic_list.html:23
#: proposals/templates/proposals/track_list.html:23
msgid "talk"
msgstr "exposé"
#: cfp/templates/cfp/staff/talk_list.html:39 proposals/models.py:162
#: cfp/templates/cfp/staff/talk_list.html:41 proposals/models.py:162
#: proposals/templates/proposals/talk_list.html:48
msgid "Intervention kind"
msgstr "Type dintervention"
#: cfp/templates/cfp/staff/talk_list.html:68
#: cfp/templates/cfp/staff/talk_list.html:70
#: proposals/templates/proposals/talk_list.html:82
#, python-format
msgid "Pending, score: %(score)s"
@ -878,35 +954,35 @@ msgstr ""
"{}\n"
"\n"
#: cfp/views.py:218 cfp/views.py:278
#: cfp/views.py:224 cfp/views.py:286
msgid "Message sent!"
msgstr "Message envoyé !"
#: cfp/views.py:231 proposals/views.py:321
#: cfp/views.py:237 proposals/views.py:321
msgid "Vote successfully created"
msgstr "A voté !"
#: cfp/views.py:231 proposals/views.py:321
#: cfp/views.py:237 proposals/views.py:321
msgid "Vote successfully updated"
msgstr "Vote mis à jour"
#: cfp/views.py:246
#: cfp/views.py:252
msgid "The talk has been accepted."
msgstr "Lexposé a été accepté."
#: cfp/views.py:248
#: cfp/views.py:254
msgid "The talk has been declined."
msgstr "Lexposé a été décliné."
#: cfp/views.py:252 proposals/views.py:347
#: cfp/views.py:258 proposals/views.py:347
msgid "Decision taken in account"
msgstr "Décision enregistrée"
#: cfp/views.py:306
#: cfp/views.py:314
msgid "[{}] You have been added to the staff team"
msgstr "[{}] Vous avez été ajouté aux membres du staff"
#: cfp/views.py:307
#: cfp/views.py:315
msgid ""
"Hi {},\n"
"\n"
@ -930,11 +1006,11 @@ msgstr ""
"{}\n"
"\n"
#: cfp/views.py:328
#: cfp/views.py:336
msgid "Modifications successfully saved."
msgstr "Modification enregistrée avec succès."
#: cfp/views.py:387
#: cfp/views.py:428
msgid "User created successfully."
msgstr "Utilisateur créé avec succès."
@ -956,49 +1032,15 @@ msgstr "Aucun message."
msgid "Schedule"
msgstr "Programme"
#: planning/templates/planning/room_detail.html:14
msgid "Scheduled talks"
msgstr "Exposés planifiés"
#: planning/templates/planning/room_detail.html:23
#: planning/templates/planning/room_detail.html:34
msgid "No talks."
msgstr "Aucun exposé."
#: planning/templates/planning/room_detail.html:26
msgid "Unscheduled talks"
msgstr "Exposés non planifiés"
#: planning/templates/planning/room_form.html:14
msgid "Modify the room"
msgstr "Modifier la salle"
#: planning/templates/planning/room_form.html:14
#: planning/templates/planning/room_list.html:12
msgid "Add a room"
msgstr "Ajouter une salle"
#: planning/templates/planning/room_list.html:9
msgid "Rooms"
msgstr "Salles"
#: planning/templates/planning/room_list.html:24
msgid "place"
msgstr "place"
#: planning/templates/planning/room_list.html:27
msgid "Some talks are not scheduled yet."
msgstr "Certains exposés ne sont pas encore planifiés."
#: planning/templates/planning/room_list.html:40
msgid "No rooms."
msgstr "Aucune salle."
#: ponyconf/settings.py:146
#: ponyconf/settings.py:145
msgid "English"
msgstr "Anglais"
#: ponyconf/settings.py:147
#: ponyconf/settings.py:146
msgid "French"
msgstr "Français"
@ -1016,7 +1058,7 @@ msgstr "Staff"
#: ponyconf/templates/base.html:48
msgid "Logout"
msgstr ""
msgstr "Déconnection"
#: ponyconf/templates/base.html:67
msgid "Powered by"
@ -1044,7 +1086,7 @@ msgstr "Changement de mot de passe"
#: ponyconf/urls.py:27
msgid "Email address"
msgstr ""
msgstr "Adresse e-mail"
#: proposals/forms.py:46
msgid "Should be less than 255 characters"
@ -1054,14 +1096,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:73
msgid "Filter talks already / not yet affected to a room"
msgstr "Filtrer les exposés déjà / pas encore affectées à une salle"
#: proposals/forms.py:74
msgid "Filter talks already / not yet scheduled"
msgstr "Filtrer les exposés déjà / pas encore planifiées"
#: proposals/forms.py:75
msgid "Filter talks with / without materials"
msgstr "Filtrer les exposés avec / sans supports"
@ -1237,6 +1271,10 @@ msgstr "Contacter :"
msgid "link"
msgstr "lien"
#: proposals/templates/proposals/talk_detail.html:19
msgid "No abstract provided."
msgstr "Aucun résumé fourni."
#: proposals/templates/proposals/talk_detail.html:24
msgid "Format"
msgstr "Format"
@ -1251,11 +1289,6 @@ msgstr "Aucun thème."
msgid "No assigned yet."
msgstr "Pas encore assigné."
#: proposals/templates/proposals/talk_detail.html:44
#: proposals/templates/proposals/talk_detail.html:52
msgid "not defined"
msgstr "non défini"
#: proposals/templates/proposals/talk_detail.html:56
msgid "Registrations"
msgstr "Inscriptions"

View File

@ -4,16 +4,17 @@ from .models import Room
class RoomForm(forms.ModelForm):
class Meta:
model = Room
fields = ['name', 'label', 'capacity']
def __init__(self, *args, **kwargs):
self.site = kwargs.pop('site')
super().__init__(*args, **kwargs)
class Meta:
model = Room
fields = ['name', 'label', 'capacity', 'sound']
def clean_name(self):
name = self.cleaned_data['name']
if self.instance and name != self.instance.name and Room.objects.filter(site=self.site, name=name).exists():
if (not self.instance or self.instance.name != name) \
and Room.objects.filter(site=self.site, name=name).exists():
raise self.instance.unique_error_message(self._meta.model, ['name'])
return name

View File

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-05-26 11:18
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('planning', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='room',
name='sound',
field=models.BooleanField(default=False),
),
]

View File

@ -14,7 +14,6 @@ class Room(models.Model):
name = models.CharField(max_length=256, blank=True, default="")
label = models.CharField(max_length=256, blank=True, default="")
capacity = models.IntegerField(default=0)
sound = models.BooleanField(default=False)
class Meta:
unique_together = ['site', 'name']

View File

@ -42,7 +42,6 @@ INSTALLED_APPS = [
'cfp',
'mailing',
#'proposals',
#'conversations',
#'planning',
#'volunteers',