From 9f151c90b66acbd16161f856e4fc5f593afa7be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lie=20Bouttier?= Date: Sun, 30 Jul 2017 16:57:38 +0200 Subject: [PATCH] Staff area --- cfp/context_processors.py | 5 + cfp/decorators.py | 17 + cfp/middleware.py | 10 + cfp/migrations/0002_conference_staff.py | 22 + cfp/models.py | 32 +- cfp/templates/cfp/complete.html | 6 +- .../ponyconf => cfp/templates/cfp}/home.html | 2 +- .../templates/cfp/staff/base.html | 13 +- .../cfp/staff/participant_details.html | 54 +++ cfp/templates/cfp/staff/participant_list.html | 99 +++++ cfp/templates/cfp/staff/talk_decide.html | 28 ++ cfp/templates/cfp/staff/talk_details.html | 143 +++++++ cfp/templates/cfp/staff/talk_list.html | 54 +++ cfp/templatetags/__init__.py | 0 cfp/templatetags/cfp_tags.py | 11 + cfp/urls.py | 18 +- cfp/utils.py | 23 +- cfp/views.py | 106 ++++- locale/fr/LC_MESSAGES/django.mo | Bin 16723 -> 17629 bytes locale/fr/LC_MESSAGES/django.po | 393 +++++++++++------- ponyconf/settings.py | 6 +- ponyconf/templates/_base.html | 6 +- ponyconf/templates/base.html | 12 +- ponyconf/urls.py | 5 +- ponyconf/views.py | 5 - 25 files changed, 854 insertions(+), 216 deletions(-) create mode 100644 cfp/context_processors.py create mode 100644 cfp/decorators.py create mode 100644 cfp/middleware.py create mode 100644 cfp/migrations/0002_conference_staff.py rename {ponyconf/templates/ponyconf => cfp/templates/cfp}/home.html (80%) rename ponyconf/templates/staff.html => cfp/templates/cfp/staff/base.html (78%) create mode 100644 cfp/templates/cfp/staff/participant_details.html create mode 100644 cfp/templates/cfp/staff/participant_list.html create mode 100644 cfp/templates/cfp/staff/talk_decide.html create mode 100644 cfp/templates/cfp/staff/talk_details.html create mode 100644 cfp/templates/cfp/staff/talk_list.html create mode 100644 cfp/templatetags/__init__.py create mode 100644 cfp/templatetags/cfp_tags.py delete mode 100644 ponyconf/views.py diff --git a/cfp/context_processors.py b/cfp/context_processors.py new file mode 100644 index 0000000..cec76e0 --- /dev/null +++ b/cfp/context_processors.py @@ -0,0 +1,5 @@ +from .utils import get_current_conf + + +def conference(request): + return {'conference': get_current_conf(request)} diff --git a/cfp/decorators.py b/cfp/decorators.py new file mode 100644 index 0000000..a5ca0ac --- /dev/null +++ b/cfp/decorators.py @@ -0,0 +1,17 @@ +from functools import wraps + +from django.core.exceptions import PermissionDenied +from django.contrib.auth.decorators import login_required + +from cfp.utils import is_staff + + +def staff_required(view_func): + def _is_staff(request, *args, **kwargs): + if not request.user.is_authenticated(): + return login_required(view_func)(request, *args, **kwargs) + elif is_staff(request, request.user): + return view_func(request, *args, **kwargs) + else: + raise PermissionDenied + return wraps(view_func)(_is_staff) diff --git a/cfp/middleware.py b/cfp/middleware.py new file mode 100644 index 0000000..353bdc8 --- /dev/null +++ b/cfp/middleware.py @@ -0,0 +1,10 @@ +from django.core.exceptions import ImproperlyConfigured + +from .utils import get_current_conf + + +class ConferenceMiddleware: + def process_view(self, request, view, view_args, view_kwargs): + if view.__module__ != 'cfp.views': + return + view_kwargs['conference'] = get_current_conf(request) diff --git a/cfp/migrations/0002_conference_staff.py b/cfp/migrations/0002_conference_staff.py new file mode 100644 index 0000000..ddc6e91 --- /dev/null +++ b/cfp/migrations/0002_conference_staff.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.3 on 2017-07-29 23:30 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('cfp', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='conference', + name='staff', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Staff'), + ), + ] diff --git a/cfp/models.py b/cfp/models.py index 943f653..4d9ce56 100644 --- a/cfp/models.py +++ b/cfp/models.py @@ -8,7 +8,7 @@ from django.contrib.sites.models import Site from django.core.urlresolvers import reverse from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models -from django.db.models import Q +from django.db.models import Q, Avg from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext from django.utils import timezone @@ -18,8 +18,6 @@ from ponyconf.utils import PonyConfModel from autoslug import AutoSlugField from colorful.fields import RGBColorField -from .utils import query_sum - from django.contrib.auth.models import User from django.contrib.sites.models import Site from django.core.urlresolvers import reverse @@ -40,6 +38,7 @@ class Conference(models.Model): venue = models.TextField(blank=True, default="") city = models.CharField(max_length=64, blank=True, default="") contact_email = models.CharField(max_length=100, blank=True) + staff = models.ManyToManyField(User, verbose_name=_('Staff'), blank=True) custom_css = models.TextField(blank=True) external_css_link = models.URLField(blank=True) @@ -117,15 +116,15 @@ class Participant(PonyConfModel): #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) - #@property - #def pending_talk_set(self): - # return self.talk_set.filter(accepted=None) - #@property - #def refused_talk_set(self): - # return self.talk_set.filter(accepted=False) + @property + def accepted_talk_set(self): + return self.talk_set.filter(accepted=True) + @property + def pending_talk_set(self): + return self.talk_set.filter(accepted=None) + @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) @@ -268,14 +267,11 @@ class Talk(PonyConfModel): def estimated_duration(self): return self.duration or self.category.duration - #def get_absolute_url(self): - # return reverse('show-talk', kwargs={'slug': self.slug}) + def get_absolute_url(self): + return reverse('talk-details', kwargs={'talk_id': self.token}) def score(self): - if self.vote_set.exists(): - return query_sum(self.vote_set, 'vote') / len(self.vote_set.all()) - else: - return 0 + return self.vote_set.aggregate(Avg('vote'))['vote__avg'] or 0 @property def end_date(self): diff --git a/cfp/templates/cfp/complete.html b/cfp/templates/cfp/complete.html index 595bf41..22b820f 100644 --- a/cfp/templates/cfp/complete.html +++ b/cfp/templates/cfp/complete.html @@ -16,9 +16,9 @@

{% trans "Thanks for your proposal" %} {{ participant }} !

{% trans "You can at anytime:" %}

{% trans "An email has been sent to you with those URLs" %}

diff --git a/ponyconf/templates/ponyconf/home.html b/cfp/templates/cfp/home.html similarity index 80% rename from ponyconf/templates/ponyconf/home.html rename to cfp/templates/cfp/home.html index cf50b1e..412c415 100644 --- a/ponyconf/templates/ponyconf/home.html +++ b/cfp/templates/cfp/home.html @@ -6,6 +6,6 @@ {% block content %} -{% markdown site.conference.home %} +{% markdown conference.home %} {% endblock %} diff --git a/ponyconf/templates/staff.html b/cfp/templates/cfp/staff/base.html similarity index 78% rename from ponyconf/templates/staff.html rename to cfp/templates/cfp/staff/base.html index 74713a5..e16abdc 100644 --- a/ponyconf/templates/staff.html +++ b/cfp/templates/cfp/staff/base.html @@ -6,16 +6,23 @@ {% block navbar %} {{ block.super }} {% endblock %} + +{% block content %} +{% trans "Please select a category." %} +{% endblock %} diff --git a/cfp/templates/cfp/staff/participant_details.html b/cfp/templates/cfp/staff/participant_details.html new file mode 100644 index 0000000..bc92d0d --- /dev/null +++ b/cfp/templates/cfp/staff/participant_details.html @@ -0,0 +1,54 @@ +{% extends 'cfp/staff/base.html' %} +{% load i18n %} + +{% block speakerstab %} class="active"{% endblock %} + +{% block content %} + +

{{ participant }}

+ +

{% trans "Biography" %}

+

{{ participant.biography }}

+ +

{% trans "Informations" %}

+ + +{% if participant.notes %} +

{% trans "Notes" %}

+{% trans "This field is only visible by organizers." %} +

{{ participant.notes }}

+{% endif %} + +

{% trans "Talks" %}

+{% regroup participant.talk_set.all by category as category_list %} +{% for category in category_list %} +

{{ category.list.0.category }}

+ +{% empty %}{% trans "No talks" %} +{% endfor %} + +{% endblock %} diff --git a/cfp/templates/cfp/staff/participant_list.html b/cfp/templates/cfp/staff/participant_list.html new file mode 100644 index 0000000..e76ec35 --- /dev/null +++ b/cfp/templates/cfp/staff/participant_list.html @@ -0,0 +1,99 @@ +{% extends 'cfp/staff/base.html' %} +{% load bootstrap3 i18n %} + +{% block speakerstab %} class="active"{% endblock %} + +{% block content %} + +

{% trans "Speakers" %}

+ +{% comment %} +{% trans "Show filtering options…" %} + +

+ +
+
+
+
+
+ {% bootstrap_field filter_form.transport layout="horizontal" %} + {% bootstrap_field filter_form.transport_booked layout="horizontal" %} + {% bootstrap_field filter_form.sound layout="horizontal" %} +
+
+ {% bootstrap_field filter_form.accommodation layout="horizontal" %} + {% bootstrap_field filter_form.accommodation_booked layout="horizontal" %} + {% bootstrap_field filter_form.status layout="horizontal" %} +
+
+
+
+ {% bootstrap_field filter_form.topic layout="horizontal" %} +
+
+ {% bootstrap_field filter_form.track layout="horizontal" %} +
+
+ +
+
+
+{% endcomment %} + + + + + + + + {% comment %}{% endcomment %} + + + {% comment %} + + + + + + {% endcomment %} + {% for participant in participant_list %} + {% if forloop.first %} + + {% endif %} + + + + {% comment %} + + {% endcomment %} + + {% if forloop.last %} + + {% endif %} + {% endfor %} +
{% trans "Total:" %} {{ participant_list|length }} {% trans "speaker" %}{{ participant_list|length|pluralize }} +
{% trans "Name" %}{% trans "Talk count" %}
{% trans "Contact:" %} {% trans "link" %}
{{ participant }} + {% blocktrans count accepted=participant.accepted_talk_set.count %}accepted: {{ accepted }}{% plural %}accepted: {{ accepted }}{% endblocktrans %} + — + {% blocktrans count pending=participant.pending_talk_set.count %}pending: {{ pending }}{% plural %}pending: {{ pending }}{% endblocktrans %} + — + {% blocktrans count refused=participant.refused_talk_set.count %}refused: {{ refused }}{% plural %}refused: {{ refused }}{% endblocktrans %} + + {% trans "Contact" %} +
+ +{% endblock %} + +{% comment %} +{% block js_end %} + +{% endblock %} +{% endcomment %} diff --git a/cfp/templates/cfp/staff/talk_decide.html b/cfp/templates/cfp/staff/talk_decide.html new file mode 100644 index 0000000..1fcd04b --- /dev/null +++ b/cfp/templates/cfp/staff/talk_decide.html @@ -0,0 +1,28 @@ +{% extends 'cfp/staff/base.html' %} +{% load i18n %} + +{% block talkstab %} class="active"{% endblock %} + +{% block content %} + +

{% if accept %}{% trans "Are you sure to accept this proposals?" %}{% else %}{% trans "Are you sure to decline this proposals?" %}{% endif %}

+ +

{% trans "Information about the proposals" %}

+{% trans "Title:" %} {{ talk.title }}
+{% trans "Kind:" %} {{ talk.category }}
+ +
+{% comment %}

{% trans "Information for the proposer" %}

{% endcomment %} +
+ {% csrf_token %} + {% comment %} +
+ + +
+ {% endcomment %} + + {% trans "Cancel" %} +
+ +{% endblock %} diff --git a/cfp/templates/cfp/staff/talk_details.html b/cfp/templates/cfp/staff/talk_details.html new file mode 100644 index 0000000..b5f6733 --- /dev/null +++ b/cfp/templates/cfp/staff/talk_details.html @@ -0,0 +1,143 @@ +{% extends 'cfp/staff/base.html' %} +{% load bootstrap3 i18n %} + +{% block talkstab %} class="active"{% endblock %} + +{% block content %} + +

{{ talk.title }}

+ +{% comment %} +{% if edit_perm %} +{% trans "Edit" %}
+{% endif %} +{% endcomment %} + +

{% if talk.abstract %}{{ talk.abstract }}{% else %}{% trans "No abstract provided." %}{% endif %}

+ +{% comment %} +{% if moderate_perm %} + +
+
{% trans "Format" %}
+
{{ talk.event }}
+
{% trans "Topics" %}
+
{% for topic in talk.topics.all %} + {{ topic }}{% if not forloop.last %}, {% endif %} + {% empty %} + {% trans "No topics." %} + {% endfor %}
+ +
{% trans "Track" %}
+
{% if talk.track %} + {{ talk.track }} + {% else %} + {% trans "No assigned yet." %} + {% endif %}
+ +
Horaire
+
{% if talk.start_date %} + {{ talk.start_date|date:"l d b" }}, + {{ talk.start_date|date:"H:i" }} – {% if talk.end_date %}{{ talk.end_date|date:"H:i" }}{% else %}?{% endif %} + {% else %}{% trans "not defined" %} + {% endif %} +
+
Salle
+
{% if talk.room %} + + {{ talk.room }} + + {% else %}{% trans "not defined" %} + {% endif %} +
+ {% if talk.registration_required %} +
{% trans "Registrations" %}
+
{% if talk.attendees_limit %}{{ talk.attendees.count }} / {{ talk.attendees_limit }}{% else %}{% trans "required but unlimited" %}{% endif %}
+ {% endif %} + {% if talk.materials %} +
{% trans "Materials" %}
+
{{ talk.materials_name }}
+ {% endif %} + {% if talk.video %} +
{% trans "Video" %}
+
{% trans "download" %}
+ {% endif %} + +
+ +{% endif %} +{% endcomment %} + +

{% trans "Description" %}

+ +

{% if talk.description %}{{ talk.description|linebreaksbr }}{% else %}{% trans "No description provided." %}{% endif %}

+ +

{% trans "Speakers" %}

+ +{% for participant in talk.speakers.all %} +{% if forloop.first %}{% endif %} +{% empty %} +{% trans "No speakers." %} +{% endfor %} + +

{% trans "Track" %}

+{% if talk.track %} +

{{ talk.track }}

+{% else %} +

{% trans "No assigned yet." context "session" %}

+{% endif %} + +

{% trans "Notes" %}

+ +

{% if talk.notes %}{{ talk.notes|linebreaksbr }}{% else %}{% trans "No notes." %}{% endif %}

+ +

{% trans "Moderation" %}

+ +

{% trans "Status" %}

+ +{{ talk.accepted|yesno:"Accepted,Declined,Pending decision" }}
+ +{% if talk.accepted == None %} +

{% trans "Vote" %}

+
+ -2 + -1 + 0 + +1 + +2 +
+

+

{{ talk.vote_set.count }} {% trans "vote" %}{{ talk.vote_set.count|pluralize }}, {% trans "average:" %} {{ talk.score|floatformat:1 }}

+ +Accept +Decline +{% endif %} + +{% comment %} +{% if talk.registration_required %} +

{% trans "Attendees" %}

+ +{% for attendee in talk.attendees.all %} +{% if forloop.first %}
    {% endif %} +
  1. {{ attendee.get_name }}
  2. +{% if forloop.last %}
{% endif %} +{% empty %} +{% trans "No attendees yet." %} +{% endfor %} + +{% endif %} +{% endcomment %} + +{% comment %} +

{% trans "Messages" %}

+{% trans "These messages are for organization team only." %}

+{% for message in talk.conversation.messages.all %} +{% include 'conversations/_message_detail.html' %} +{% endfor %} + +{% include 'conversations/_message_form.html' %} +{% endcomment %} + +{% endblock %} diff --git a/cfp/templates/cfp/staff/talk_list.html b/cfp/templates/cfp/staff/talk_list.html new file mode 100644 index 0000000..cbb603a --- /dev/null +++ b/cfp/templates/cfp/staff/talk_list.html @@ -0,0 +1,54 @@ +{% extends 'cfp/staff/base.html' %} +{% load bootstrap3 i18n %} + +{% block talkstab %} class="active"{% endblock %} + +{% block content %} + +

{% trans "Talks" %}

+ + + + + + {% comment %}{% endcomment %} + + + + + + + + {% for talk in talk_list %} + {% if forloop.first %} + + {% endif %} + + {% comment %}{% endcomment %} + + + + + + + {% if forloop.last%} + + {% endif %} + {% endfor %} +
{% trans "Total:" %} {{ talk_list|length }} {% trans "talk" %}{{ talk_list|length|pluralize }}
{% trans "Title" %} {% trans "Intervention kind" %} {% trans "Speakers" %}{% trans "Track" %}{% trans "Status" %}
{{ talk.title }}{{ talk.category }} + {% for participant in talk.speakers.all %} + {{ participant }} + {% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %} + {% empty %}– + {% endfor %} + {{ talk.track|default:"–" }} + {% if talk.accepted == True %} + {% trans "Accepted" %} + {% elif talk.accepted == False %} + {% trans "Declined" %} + {% else %} + {% blocktrans with score=talk.score|floatformat:1 %}Pending, score: {{ score }}{% endblocktrans %} + {% endif %} +
+ +{% endblock %} diff --git a/cfp/templatetags/__init__.py b/cfp/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cfp/templatetags/cfp_tags.py b/cfp/templatetags/cfp_tags.py new file mode 100644 index 0000000..5c7c33e --- /dev/null +++ b/cfp/templatetags/cfp_tags.py @@ -0,0 +1,11 @@ +from django import template + +from cfp.utils import is_staff + + +register = template.Library() + + +@register.filter +def staff(request): + return is_staff(request, request.user) diff --git a/cfp/urls.py b/cfp/urls.py index f173afb..418d1dd 100644 --- a/cfp/urls.py +++ b/cfp/urls.py @@ -3,10 +3,20 @@ from django.conf.urls import url from . import views urlpatterns = [ - url(r'^$', views.talk_proposal, name='talk-proposal'), - url(r'^(?P[\w\-]+)/speaker/add/$', views.talk_proposal_speaker_edit, name='talk-proposal-speaker-add'), - url(r'^(?P[\w\-]+)/speaker/(?P[\w\-]+)/$', views.talk_proposal_speaker_edit, name='talk-proposal-speaker-edit'), - url(r'^(?P[\w\-]+)/(?P[\w\-]+)/$', views.talk_proposal, name='talk-proposal-edit'), + url(r'^$', views.home, name='home'), + url(r'^cfp/$', views.talk_proposal, name='talk-proposal'), + url(r'^cfp/(?P[\w\-]+)/speaker/add/$', views.talk_proposal_speaker_edit, name='talk-proposal-speaker-add'), + url(r'^cfp/(?P[\w\-]+)/speaker/(?P[\w\-]+)/$', views.talk_proposal_speaker_edit, name='talk-proposal-speaker-edit'), + url(r'^cfp/(?P[\w\-]+)/(?P[\w\-]+)/$', views.talk_proposal, name='talk-proposal-edit'), + url(r'^staff/$', views.staff, name='staff'), + url(r'^staff/talks/$', views.talk_list, name='talk-list'), + url(r'^staff/talks/(?P[\w\-]+)/$', views.talk_details, name='talk-details'), + url(r'^staff/talks/(?P[\w\-]+)/vote/(?P[-+0-2]+)/$', views.talk_vote, name='talk-vote'), + url(r'^staff/talks/(?P[\w\-]+)/accept/$', views.talk_decide, {'accept': True}, name='talk-accept'), + url(r'^staff/talks/(?P[\w\-]+)/decline/$', views.talk_decide, {'accept': False}, name='talk-decline'), + url(r'^staff/speakers/$', views.participant_list, name='participant-list'), + url(r'^staff/speakers/(?P[\w\-]+)/$', views.participant_details, name='participant-details'), + #url(r'^markdown/$', views.markdown_preview, name='markdown'), #url(r'^$', views.home, name='home'), #url(r'^staff/$', views.staff, name='staff'), diff --git a/cfp/utils.py b/cfp/utils.py index 6db8b88..c98d84c 100644 --- a/cfp/utils.py +++ b/cfp/utils.py @@ -1,31 +1,40 @@ from django.utils.crypto import get_random_string - - -def generate_user_uid(): - return get_random_string(length=12, allowed_chars='abcdefghijklmnopqrstuvwxyz0123456789') - from django.contrib.sites.shortcuts import get_current_site from django.db.models import Q, Sum from django.db.models.functions import Coalesce from django.utils.safestring import mark_safe -#from accounts.models import Participation - from markdown import markdown import bleach +from .models import Conference + + +def get_current_conf(request): + site = get_current_site(request) + return Conference.objects.get(site=site) + def query_sum(queryset, field): return queryset.aggregate(s=Coalesce(Sum(field), 0))['s'] +def generate_user_uid(): + return get_random_string(length=12, allowed_chars='abcdefghijklmnopqrstuvwxyz0123456789') + + def allowed_talks(talks, request): if not Participation.objects.get(site=get_current_site(request), user=request.user).is_orga(): talks = talks.filter(Q(topics__reviewers=request.user) | Q(speakers=request.user) | Q(proposer=request.user)) return talks.distinct() + def markdown_to_html(md): html = markdown(md) allowed_tags = bleach.ALLOWED_TAGS + ['p', 'pre', 'span' ] + ['h%d' % i for i in range(1, 7) ] html = bleach.clean(html, tags=allowed_tags) return mark_safe(html) + + +def is_staff(request, user): + return user.is_authenticated and (user.is_superuser or user in site.conference.staff) diff --git a/cfp/views.py b/cfp/views.py index 13745d8..efc1146 100644 --- a/cfp/views.py +++ b/cfp/views.py @@ -1,5 +1,3 @@ - -from django.contrib.sites.shortcuts import get_current_site from django.core.mail import send_mail from django.core.urlresolvers import reverse_lazy from django.forms.models import modelform_factory @@ -7,13 +5,22 @@ from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from django.views.generic import FormView, TemplateView +from django.contrib import messages -from .models import Participant, Talk +from cfp.decorators import staff_required +from .models import Participant, Talk, Vote -def talk_proposal(request, talk_id=None, participant_id=None): +def home(request, conference): + if conference.home: + return render(request, 'cfp/home.html') + else: + return redirect(reverse('talk-proposal')) - site = get_current_site(request) + +def talk_proposal(request, conference, talk_id=None, participant_id=None): + + site = conference.site talk = None participant = None @@ -44,7 +51,7 @@ def talk_proposal(request, talk_id=None, participant_id=None): url_talk_proposal_edit = base_url + reverse('talk-proposal-edit', args=[talk.token, participant.token]) url_talk_proposal_speaker_add = base_url + reverse('talk-proposal-speaker-add', args=[talk.token]) url_talk_proposal_speaker_edit = base_url + reverse('talk-proposal-speaker-edit', args=[talk.token, participant.token]) - msg_title = _('Your talk "{}" has been submitted for {}').format(talk.title, site.conference.name) + msg_title = _('Your talk "{}" has been submitted for {}').format(talk.title, conference.name) msg_body = _("""Hi {}, Your talk has been submitted for {}. @@ -64,12 +71,12 @@ Thanks! {} -""").format(participant.name, site.conference.name, talk.title, talk.description, url_talk_proposal_edit, url_talk_proposal_speaker_add, url_talk_proposal_speaker_edit, site.conference.name) +""").format(participant.name, conference.name, talk.title, talk.description, url_talk_proposal_edit, url_talk_proposal_speaker_add, url_talk_proposal_speaker_edit, conference.name) send_mail( msg_title, msg_body, - site.conference.from_email(), + conference.from_email(), [participant.email], fail_silently=False, ) @@ -83,21 +90,20 @@ Thanks! }) -def talk_proposal_speaker_edit(request, talk_id, participant_id=None): +def talk_proposal_speaker_edit(request, conference, talk_id, participant_id=None): - site = get_current_site(request) - talk = get_object_or_404(Talk, token=talk_id, site=site) + talk = get_object_or_404(Talk, token=talk_id, site=conference.site) participant = None if participant_id: - participant = get_object_or_404(Participant, token=participant_id, site=site) + participant = get_object_or_404(Participant, token=participant_id, site=conference.site) ParticipantForm = modelform_factory(Participant, fields=('name','email', 'biography')) participant_form = ParticipantForm(request.POST or None, instance=participant) if request.method == 'POST' and participant_form.is_valid(): - participant, created = Participant.objects.get_or_create(email=participant_form.cleaned_data['email'], site=site) + participant, created = Participant.objects.get_or_create(email=participant_form.cleaned_data['email'], site=conference.site) participant_form = ParticipantForm(request.POST, instance=participant) participant = participant_form.save() participant.save() @@ -108,6 +114,78 @@ def talk_proposal_speaker_edit(request, talk_id, participant_id=None): return render(request, 'cfp/speaker.html', { 'participant_form': participant_form, - 'site': site, }) + +@staff_required +def staff(request, conference): + return render(request, 'cfp/staff/base.html') + + +@staff_required +def talk_list(request, conference): + talks = Talk.objects.filter(site=conference.site) + return render(request, 'cfp/staff/talk_list.html', { + 'talk_list': talks, + }) + + +@staff_required +def talk_details(request, conference, talk_id): + talk = get_object_or_404(Talk, token=talk_id, site=conference.site) + return render(request, 'cfp/staff/talk_details.html', { + 'talk': talk, + }) + + +@staff_required +def talk_vote(request, conference, talk_id, score): + talk = get_object_or_404(Talk, token=talk_id, site=conference.site) + vote, created = Vote.objects.get_or_create(talk=talk, user=request.user) + vote.vote = int(score) + vote.save() + messages.success(request, _('Vote successfully created') if created else _('Vote successfully updated')) + return redirect(talk.get_absolute_url()) + + +@staff_required +def talk_decide(request, conference, talk_id, accept): + talk = get_object_or_404(Talk, token=talk_id, site=conference.site) + if request.method == 'POST': + # # Does we need to send a notification to the proposer? + # m = request.POST.get('message', '').strip() + # if m: + # participation = Participation.objects.get(site=site, user=talk.proposer) + # conversation = ConversationWithParticipant.objects.get(participation=participation) + # Message.objects.create(conversation=conversation, author=request.user, content=m) + # # Save the decision in the talk's conversation + # conversation = ConversationAboutTalk.objects.get(talk=talk) + if accept: + note = "The talk has been accepted." + else: + note = "The talk has been declined." + #Message.objects.create(conversation=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', { + 'talk': talk, + 'accept': accept, + }) + + +@staff_required +def participant_list(request, conference): + participants = Participant.objects.filter(site=conference.site) + return render(request, 'cfp/staff/participant_list.html', { + 'participant_list': participants, + }) + + +@staff_required +def participant_details(request, conference, participant_id): + participant = get_object_or_404(Participant, token=participant_id, site=conference.site) + return render(request, 'cfp/staff/participant_details.html', { + 'participant': participant, + }) diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo index d31a42732f6ba16b00a386c45d7a18ecb786ac89..f5350e0b11b689720cc6e4cba097425d2b1c8241 100644 GIT binary patch delta 6153 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 delta 5285 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 Z@l1TV*#CZ3o2nCn9e3%G;Gf*1;6Ef?JE#Bv diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 82c819f..e89780a 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-06 21:13+0000\n" +"POT-Creation-Date: 2017-07-30 14:00+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -24,31 +24,31 @@ msgstr "" "Par exemple, vous devez rentrer le samedi soir, vous ne pouvez pas manger de " "viande, etc." -#: accounts/models.py:18 cfp/models.py:84 +#: accounts/models.py:18 cfp/models.py:83 msgid "Phone number" msgstr "Numéro de téléphone" -#: accounts/models.py:20 cfp/models.py:77 +#: accounts/models.py:20 cfp/models.py:76 msgid "Twitter" msgstr "" -#: accounts/models.py:21 cfp/models.py:78 +#: accounts/models.py:21 cfp/models.py:77 msgid "LinkedIn" msgstr "" -#: accounts/models.py:22 cfp/models.py:79 +#: accounts/models.py:22 cfp/models.py:78 msgid "Github" msgstr "" -#: accounts/models.py:23 cfp/models.py:80 +#: accounts/models.py:23 cfp/models.py:79 msgid "Website" msgstr "" -#: accounts/models.py:24 cfp/models.py:81 +#: accounts/models.py:24 cfp/models.py:80 msgid "Facebook" msgstr "" -#: accounts/models.py:25 cfp/models.py:82 +#: accounts/models.py:25 cfp/models.py:81 msgid "Mastodon" msgstr "" @@ -99,12 +99,15 @@ msgstr "Contacter" msgid "Edit" msgstr "Éditer" -#: accounts/templates/accounts/participant_details.html:20 cfp/models.py:74 +#: accounts/templates/accounts/participant_details.html:20 cfp/models.py:73 +#: cfp/templates/cfp/staff/participant_details.html:10 msgid "Biography" msgstr "Biographie" #: accounts/templates/accounts/participant_details.html:27 -#: ponyconf/templates/staff.html:11 +#: cfp/templates/cfp/staff/base.html:20 +#: cfp/templates/cfp/staff/participant_details.html:32 +#: cfp/templates/cfp/staff/talk_list.html:8 #: proposals/templates/proposals/talk_list.html:9 msgid "Talks" msgstr "Exposés" @@ -169,8 +172,10 @@ msgstr "Licence vidéo :" msgid "Constraints" msgstr "Contraintes" -#: accounts/templates/accounts/participant_details.html:71 cfp/models.py:88 -#: proposals/models.py:161 proposals/templates/proposals/talk_detail.html:102 +#: accounts/templates/accounts/participant_details.html:71 cfp/models.py:87 +#: cfp/templates/cfp/staff/participant_details.html:27 +#: cfp/templates/cfp/staff/talk_details.html:92 proposals/models.py:161 +#: proposals/templates/proposals/talk_detail.html:102 msgid "Notes" msgstr "Notes" @@ -179,8 +184,7 @@ msgstr "Notes" msgid "%(profile)s's profile" msgstr "Profil de %(profile)s" -#: accounts/templates/accounts/participant_list.html:9 -#: ponyconf/templates/staff.html:16 volunteers/models.py:15 +#: accounts/templates/accounts/participant_list.html:9 volunteers/models.py:15 msgid "Participants" msgstr "Participants" @@ -282,53 +286,62 @@ msgstr "%(name)s a été ajouté aux participants" msgid "%(name)s is already a participant" msgstr "%(name)s est déjà participant" -#: cfp/models.py:71 +#: cfp/models.py:41 ponyconf/templates/base.html:36 +msgid "Staff" +msgstr "" + +#: cfp/models.py:70 msgid "Your Name" msgstr "Votre Nom" -#: cfp/models.py:88 +#: cfp/models.py:87 cfp/templates/cfp/staff/participant_details.html:28 msgid "This field is only visible by organizers." msgstr "Ce champs est uniquement visible par les organisateurs." -#: cfp/models.py:138 proposals/models.py:52 proposals/models.py:75 -#: proposals/models.py:132 volunteers/models.py:12 +#: cfp/models.py:137 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/models.py:140 proposals/models.py:54 proposals/models.py:77 -#: proposals/models.py:158 proposals/templates/proposals/talk_detail.html:72 -#: volunteers/models.py:14 +#: cfp/models.py:139 cfp/templates/cfp/staff/talk_details.html:71 +#: 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" msgstr "Description" -#: cfp/models.py:161 proposals/models.py:96 +#: cfp/models.py:160 proposals/models.py:96 msgid "Default duration (min)" msgstr "Durée par défaut (min)" -#: cfp/models.py:162 proposals/models.py:97 +#: cfp/models.py:161 proposals/models.py:97 msgid "Color on program" msgstr "Couleur sur le programme" -#: cfp/models.py:163 proposals/models.py:98 +#: cfp/models.py:162 proposals/models.py:98 msgid "Label on program" msgstr "Label dans le xml du programme" -#: cfp/models.py:230 ponyconf/templates/staff.html:12 proposals/models.py:154 +#: cfp/models.py:229 cfp/templates/cfp/staff/base.html:21 +#: cfp/templates/cfp/staff/participant_list.html:8 +#: cfp/templates/cfp/staff/talk_details.html:75 +#: cfp/templates/cfp/staff/talk_list.html:18 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:231 +#: cfp/models.py:230 msgid "Talk Title" msgstr "Titre de votre proposition:" -#: cfp/models.py:234 +#: cfp/models.py:233 msgid "Description of your talk" msgstr "Description de votre proposition" -#: cfp/models.py:235 proposals/models.py:160 +#: cfp/models.py:234 cfp/templates/cfp/staff/talk_details.html:85 +#: cfp/templates/cfp/staff/talk_list.html:19 proposals/models.py:160 #: proposals/templates/proposals/talk_detail.html:33 #: proposals/templates/proposals/talk_detail.html:89 #: proposals/templates/proposals/talk_list.html:51 @@ -336,11 +349,11 @@ msgstr "Description de votre proposition" msgid "Track" msgstr "Session" -#: cfp/models.py:236 +#: cfp/models.py:235 msgid "Message to organizers" msgstr "Message aux organisateurs" -#: cfp/models.py:236 +#: cfp/models.py:235 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 " @@ -350,23 +363,23 @@ msgstr "" "votre proposition, comme une vidéo, des slides, n'hésitez pas à les ajouter " "ici." -#: cfp/models.py:237 +#: cfp/models.py:236 msgid "Talk Category" msgstr "Catégorie de proposition" -#: cfp/models.py:238 +#: cfp/models.py:237 msgid "I'm ok to be recorded on video" msgstr "J’accepte d’être enregistré en vidéo" -#: cfp/models.py:239 +#: cfp/models.py:238 msgid "Video licence" msgstr "Licence vidéo" -#: cfp/models.py:240 +#: cfp/models.py:239 msgid "I need sound" msgstr "J’ai besoin de son" -#: cfp/models.py:243 proposals/models.py:165 +#: cfp/models.py:242 proposals/models.py:165 msgid "Duration (min)" msgstr "Durée (min)" @@ -407,11 +420,182 @@ msgstr "Participer" msgid "Save" msgstr "Envoyer" -#: cfp/views.py:47 +#: cfp/templates/cfp/staff/base.html:29 +msgid "Please select a category." +msgstr "Veuillez sélectionner une catégorie." + +#: cfp/templates/cfp/staff/participant_details.html:13 +msgid "Informations" +msgstr "Informations" + +#: cfp/templates/cfp/staff/participant_details.html:15 +msgid "E-mail:" +msgstr "E-mail :" + +#: cfp/templates/cfp/staff/participant_details.html:16 +msgid "Twitter:" +msgstr "Twitter :" + +#: cfp/templates/cfp/staff/participant_details.html:17 +msgid "LinkedIn:" +msgstr "LinkedIn :" + +#: cfp/templates/cfp/staff/participant_details.html:18 +msgid "Github:" +msgstr "Github :" + +#: cfp/templates/cfp/staff/participant_details.html:19 +msgid "Website:" +msgstr "Website :" + +#: cfp/templates/cfp/staff/participant_details.html:20 +msgid "Facebook:" +msgstr "Facebook :" + +#: cfp/templates/cfp/staff/participant_details.html:21 +msgid "Mastodon:" +msgstr "Mastodon :" + +#: cfp/templates/cfp/staff/participant_details.html:22 +msgid "Phone number:" +msgstr "Numéro de téléphone :" + +#: cfp/templates/cfp/staff/participant_details.html:23 +msgid "Language:" +msgstr "Langue :" + +#: cfp/templates/cfp/staff/participant_details.html:39 +#: proposals/templates/proposals/_talk_list.html:8 +msgid "by" +msgstr "par" + +#: cfp/templates/cfp/staff/participant_details.html:42 +#: cfp/templates/cfp/staff/talk_list.html:35 +#: proposals/templates/proposals/_talk_list.html:11 +#: proposals/templates/proposals/_talk_list.html:17 +#: proposals/templates/proposals/talk_list.html:66 +msgid "and" +msgstr "et" + +#: cfp/templates/cfp/staff/participant_details.html:45 +#: proposals/templates/proposals/_talk_list.html:14 +msgid "in" +msgstr "dans la session" + +#: cfp/templates/cfp/staff/participant_details.html:51 +#: proposals/templates/proposals/_talk_list.html:23 +msgid "No talks" +msgstr "Aucun exposé" + +#: cfp/templates/cfp/staff/participant_list.html:45 +#: cfp/templates/cfp/staff/talk_list.html:11 +#: proposals/templates/proposals/speaker_list.html:44 +#: proposals/templates/proposals/talk_list.html:43 +#: volunteers/templates/volunteers/volunteer_list.html:25 +msgid "Total:" +msgstr "Total :" + +#: cfp/templates/cfp/staff/participant_list.html:45 +#: proposals/templates/proposals/speaker_list.html:44 +msgid "speaker" +msgstr "orateur" + +#: cfp/templates/cfp/staff/participant_list.html:50 +#: proposals/templates/proposals/speaker_list.html:50 +msgid "Talk count" +msgstr "Nombre d’exposé" + +#: cfp/templates/cfp/staff/participant_list.html:70 +#, python-format +msgid "accepted: %(accepted)s" +msgid_plural "accepted: %(accepted)s" +msgstr[0] "accepté : %(accepted)s" +msgstr[1] "acceptés : %(accepted)s" + +#: cfp/templates/cfp/staff/participant_list.html:72 +#, python-format +msgid "pending: %(pending)s" +msgid_plural "pending: %(pending)s" +msgstr[0] "en attente : %(pending)s" +msgstr[1] "en attente : %(pending)s" + +#: cfp/templates/cfp/staff/participant_list.html:74 +#, python-format +msgid "refused: %(refused)s" +msgid_plural "refused: %(refused)s" +msgstr[0] "refusé : %(refused)s" +msgstr[1] "refusés : %(refused)s" + +#: cfp/templates/cfp/staff/talk_details.html:16 +#: 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 +msgctxt "session" +msgid "No assigned yet." +msgstr "Pas encore assignée." + +#: cfp/templates/cfp/staff/talk_details.html:94 +#: proposals/templates/proposals/talk_detail.html:104 +msgid "No notes." +msgstr "Aucune note." + +#: cfp/templates/cfp/staff/talk_list.html:11 +#: 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:16 proposals/models.py:155 +#: proposals/templates/proposals/talk_list.html:47 +msgid "Title" +msgstr "Titre" + +#: cfp/templates/cfp/staff/talk_list.html:17 proposals/models.py:162 +#: proposals/templates/proposals/talk_list.html:48 +msgid "Intervention kind" +msgstr "Type d’intervention" + +#: cfp/templates/cfp/staff/talk_list.html:20 +#: proposals/templates/proposals/talk_detail.html:110 +#: proposals/templates/proposals/talk_list.html:52 +msgid "Status" +msgstr "Statut" + +#: cfp/templates/cfp/staff/talk_list.html:42 +#: proposals/templates/proposals/talk_list.html:78 +msgid "Accepted" +msgstr "Accepté" + +#: cfp/templates/cfp/staff/talk_list.html:44 +#: proposals/templates/proposals/talk_list.html:80 +msgid "Declined" +msgstr "Décliné" + +#: cfp/templates/cfp/staff/talk_list.html:46 +#: proposals/templates/proposals/talk_list.html:82 +#, python-format +msgid "Pending, score: %(score)s" +msgstr "En cours, score : %(score)s" + +#: cfp/views.py:53 msgid "Your talk \"{}\" has been submitted for {}" msgstr "Votre proposition \"{}\" a été transmise à {}" -#: cfp/views.py:48 +#: cfp/views.py:54 msgid "" "Hi {},\n" "\n" @@ -465,7 +649,6 @@ msgid "Conversation with %(correspondent)s" msgstr "Conversation avec %(correspondent)s" #: conversations/templates/conversations/correspondent_list.html:9 -#: ponyconf/templates/staff.html:17 msgid "Correspondents" msgstr "Correspondants" @@ -487,7 +670,7 @@ msgid "Message sent!" msgstr "Message envoyé !" #: planning/templates/planning/public-program.html:8 -#: planning/templates/planning/schedule.html:9 ponyconf/templates/staff.html:15 +#: planning/templates/planning/schedule.html:9 msgid "Schedule" msgstr "Programme" @@ -514,7 +697,6 @@ msgid "Add a room" msgstr "Ajouter une salle" #: planning/templates/planning/room_list.html:9 -#: ponyconf/templates/staff.html:14 msgid "Rooms" msgstr "Salles" @@ -526,39 +708,32 @@ msgstr "place" msgid "Some talks are not scheduled yet." msgstr "Certains exposés ne sont pas encore planifiés." -#: 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é" - #: planning/templates/planning/room_list.html:40 msgid "No rooms." msgstr "Aucune salle." -#: ponyconf/settings.py:143 +#: ponyconf/settings.py:145 msgid "English" msgstr "Anglais" -#: ponyconf/settings.py:144 +#: ponyconf/settings.py:146 msgid "French" msgstr "Français" -#: ponyconf/templates/base.html:20 +#: ponyconf/templates/base.html:21 msgid "Home" msgstr "Accueil" -#: ponyconf/templates/base.html:21 +#: ponyconf/templates/base.html:23 msgid "Call for participation" msgstr "Appel à participation" -#: ponyconf/templates/base.html:46 +#: ponyconf/templates/base.html:50 #: ponyconf/templates/registration/login.html:10 msgid "Login" msgstr "Se connecter" -#: ponyconf/templates/base.html:63 +#: ponyconf/templates/base.html:67 msgid "Powered by" msgstr "Propulsé par" @@ -566,27 +741,6 @@ msgstr "Propulsé par" msgid "Password Change" msgstr "Changement de mot de passe" -#: ponyconf/templates/staff.html:9 proposals/models.py:159 -#: proposals/templates/proposals/talk_detail.html:26 -#: proposals/templates/proposals/talk_list.html:50 -#: proposals/templates/proposals/topic_list.html:9 -msgid "Topics" -msgstr "Thèmes" - -#: ponyconf/templates/staff.html:10 -#: proposals/templates/proposals/track_list.html:9 -msgid "Tracks" -msgstr "Sessions" - -#: ponyconf/templates/staff.html:13 -#: volunteers/templates/volunteers/volunteer_list.html:9 -msgid "Volunteers" -msgstr "Bénévoles" - -#: ponyconf/templates/staff.html:18 -msgid "Conference" -msgstr "Conférence" - #: proposals/forms.py:46 msgid "Should be less than 255 characters" msgstr "Texte court, moins de 255 caractères" @@ -661,10 +815,6 @@ msgstr "Responsables" msgid "Email" msgstr "E-mail" -#: proposals/models.py:155 proposals/templates/proposals/talk_list.html:47 -msgid "Title" -msgstr "Titre" - #: proposals/models.py:155 msgid "After submission, title can only be changed by the staff." msgstr "" @@ -675,14 +825,16 @@ msgstr "" msgid "Abstract" msgstr "Résumé" +#: proposals/models.py:159 proposals/templates/proposals/talk_detail.html:26 +#: proposals/templates/proposals/talk_list.html:50 +#: proposals/templates/proposals/topic_list.html:9 +msgid "Topics" +msgstr "Thèmes" + #: proposals/models.py:159 msgid "The topics can not be changed after submission." msgstr "Les thèmes ne peuvent pas être modifiés après soumission." -#: proposals/models.py:162 proposals/templates/proposals/talk_list.html:48 -msgid "Intervention kind" -msgstr "Type d’intervention" - #: proposals/models.py:169 proposals/templates/proposals/talk_detail.html:131 msgid "Attendees" msgstr "Inscrits" @@ -722,24 +874,6 @@ msgstr "stand" msgid "other" msgstr "autre" -#: proposals/templates/proposals/_talk_list.html:8 -msgid "by" -msgstr "par" - -#: proposals/templates/proposals/_talk_list.html:11 -#: proposals/templates/proposals/_talk_list.html:17 -#: proposals/templates/proposals/talk_list.html:66 -msgid "and" -msgstr "et" - -#: proposals/templates/proposals/_talk_list.html:14 -msgid "in" -msgstr "portant sur" - -#: proposals/templates/proposals/_talk_list.html:23 -msgid "No talks" -msgstr "Aucun exposé" - #: proposals/templates/proposals/conference.html:11 msgid "Home page" msgstr "Page d’accueil" @@ -784,16 +918,6 @@ msgstr "Afficher les options de filtrage…" msgid "Filter" msgstr "Filtrer" -#: proposals/templates/proposals/speaker_list.html:44 -#: proposals/templates/proposals/talk_list.html:43 -#: volunteers/templates/volunteers/volunteer_list.html:25 -msgid "Total:" -msgstr "Total :" - -#: proposals/templates/proposals/speaker_list.html:44 -msgid "speaker" -msgstr "orateur" - #: proposals/templates/proposals/speaker_list.html:48 #: volunteers/templates/volunteers/volunteer_list.html:29 msgid "Username" @@ -804,10 +928,6 @@ msgstr "Nom d’utilisateur" msgid "Fullname" msgstr "Prénom et nom" -#: proposals/templates/proposals/speaker_list.html:50 -msgid "Talk count" -msgstr "Nombre d’exposé" - #: proposals/templates/proposals/speaker_list.html:51 msgctxt "table column title" msgid "Need transport?" @@ -871,10 +991,6 @@ msgstr "Accepter la proposition" msgid "Decline the proposal" msgstr "Décliner la proposition" -#: 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" @@ -910,31 +1026,14 @@ msgstr "Vidéo" msgid "download" msgstr "Télécharger" -#: proposals/templates/proposals/talk_detail.html:74 -msgid "No description provided." -msgstr "Aucune description fournie." - -#: proposals/templates/proposals/talk_detail.html:83 -msgid "No speakers." -msgstr "Aucun orateur." - #: proposals/templates/proposals/talk_detail.html:94 msgid "Assign to" msgstr "Assigner à" -#: proposals/templates/proposals/talk_detail.html:104 -msgid "No notes." -msgstr "Aucune note." - #: proposals/templates/proposals/talk_detail.html:108 msgid "Moderation" msgstr "Modération" -#: proposals/templates/proposals/talk_detail.html:110 -#: proposals/templates/proposals/talk_list.html:52 -msgid "Status" -msgstr "Statut" - #: proposals/templates/proposals/talk_detail.html:115 msgid "Vote" msgstr "Vote" @@ -963,19 +1062,6 @@ msgstr "Ces messages sont à destination de la team d’organisation seulement." msgid "Edit a talk" msgstr "Éditer un exposé" -#: proposals/templates/proposals/talk_list.html:78 -msgid "Accepted" -msgstr "Accepté" - -#: proposals/templates/proposals/talk_list.html:80 -msgid "Declined" -msgstr "Décliné" - -#: proposals/templates/proposals/talk_list.html:82 -#, python-format -msgid "Pending, score: %(score)s" -msgstr "En cours, score : %(score)s" - #: proposals/templates/proposals/talk_list.html:95 msgid "For selected talks:" msgstr "Pour les exposés sélectionnés :" @@ -1030,6 +1116,10 @@ msgstr "Ajouter un thème" msgid "reviewer" msgstr "Responsable" +#: proposals/templates/proposals/track_list.html:9 +msgid "Tracks" +msgstr "Sessions" + #: proposals/templates/proposals/track_list.html:12 msgid "Add a track" msgstr "Ajouter une session" @@ -1112,6 +1202,13 @@ msgstr "" "Nous ne sommes pas encore en recherche de bénévoles … mais revenez plus " "tard !" +#: volunteers/templates/volunteers/volunteer_list.html:9 +msgid "Volunteers" +msgstr "Bénévoles" + #: volunteers/templates/volunteers/volunteer_list.html:25 msgid "volunteer" msgstr "bénévole" + +#~ msgid "Conference" +#~ msgstr "Conférence" diff --git a/ponyconf/settings.py b/ponyconf/settings.py index b6a7e12..3df5e05 100644 --- a/ponyconf/settings.py +++ b/ponyconf/settings.py @@ -72,6 +72,8 @@ MIDDLEWARE_CLASSES = [ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + + 'cfp.middleware.ConferenceMiddleware', ] ROOT_URLCONF = 'ponyconf.urls' @@ -88,8 +90,8 @@ TEMPLATES = [ 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', - 'ponyconf.context_processors.site', - #'proposals.context_processors.conference', + #'ponyconf.context_processors.site', + 'cfp.context_processors.conference', ], }, }, diff --git a/ponyconf/templates/_base.html b/ponyconf/templates/_base.html index df528dc..091d020 100644 --- a/ponyconf/templates/_base.html +++ b/ponyconf/templates/_base.html @@ -8,7 +8,7 @@ {% comment %}{% endcomment %} - {% block title %}{{ site.name }}{% endblock %} + {% block title %}{{ conference.name }}{% endblock %} {% bootstrap_css %} @@ -16,8 +16,8 @@ {% block js %}{% endblock %} - {% if site.conference.external_css_link %} - + {% if conference.external_css_link %} + {% endif %} diff --git a/ponyconf/templates/base.html b/ponyconf/templates/base.html index 4bcde22..dc15d67 100644 --- a/ponyconf/templates/base.html +++ b/ponyconf/templates/base.html @@ -1,5 +1,5 @@ {% extends '_base.html' %} -{% load i18n bootstrap3 %} +{% load i18n bootstrap3 cfp_tags %} {% block body %} @@ -13,11 +13,13 @@ - {{ site.name }} + {{ conference.name }}