new staff design

This commit is contained in:
Élie Bouttier 2016-11-12 13:56:21 +01:00
parent 5c2ecb932b
commit dc6b1f7cb7
53 changed files with 574 additions and 568 deletions

View File

@ -88,7 +88,7 @@ class Participation(PonyConfModel):
return str(self.user.profile)
def get_absolute_url(self):
return reverse('show-speaker', kwargs={'username': self.user.username})
return reverse('show-participant', kwargs={'username': self.user.username})
def is_orga(self):
return self.orga

View File

@ -1,12 +1,15 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load accounts_tags i18n avatar_tags %}
{% block participantstab %} class="active"{% endblock %}
{% block content %}
<h1>{{ profile }}</h1>
{% if request|staff %}
<a href="{% url 'conversation' profile.user.username %}" class="btn btn-primary ">{% trans "Contact" %}</a>
<a href="{% url 'user-conversation' profile.user.username %}" class="btn btn-primary ">{% trans "Contact" %}</a>
{% endif %}
{% if request|edit_profile:profile %}
<a href="{% url 'edit-participant' profile.user.username %}" class="btn btn-success">{% trans "Edit" %}</a>

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load i18n %}
{% block speakertab %} class="active"{% endblock %}
{% block participantstab %} class="active"{% endblock %}
{% block content %}

View File

@ -1,14 +1,12 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 accounts_tags i18n %}
{% block admintab %} active{% endblock %}
{% block participantstab %} class="active"{% endblock %}
{% block content %}
<div class="page-header">
<h1>Participants</h1>
</div>
<h1>{% trans "Participants" %}</h1>
<table class="table table-striped">
<tr>
@ -26,14 +24,14 @@
<td>{% for topic in participation.topic_set.all %}{{ topic.get_link }}{% if not forloop.last %},
{% endif %}{% endfor %}</td>
<td>
<a href="{% url 'conversation' participation.user.username %}" data-toggle="tooltip" data-placement="bottom"
<a href="{% url 'user-conversation' participation.user.username %}" data-toggle="tooltip" data-placement="bottom"
title="{% trans "View conversation" %}"><span class="glyphicon glyphicon-envelope"></span></a>
{% if request.user in participation.conversation.subscribers.all %}
<a href="{% url 'unsubscribe-conversation' participation.user.username %}?next={% url 'list-participant' %}"
<a href="{% url 'unsubscribe-conversation' participation.user.username %}?next={% url 'list-participants' %}"
data-toggle="tooltip" data-placement="bottom" title="{% trans "Unsubscribe from the conversation" %}">
<span class="glyphicon glyphicon-star"></span></a>
{% else %}
<a href="{% url 'subscribe-conversation' participation.user.username %}?next={% url 'list-participant' %}"
<a href="{% url 'subscribe-conversation' participation.user.username %}?next={% url 'list-participants' %}"
data-toggle="tooltip" data-placement="bottom" title="{% trans "Subscribe to the conversation" %}">
<span class="glyphicon glyphicon-star-empty"></span></a>
{% endif %}

View File

@ -47,7 +47,7 @@ class AccountTests(TestCase):
def test_participant_views(self):
self.assertEqual(self.client.get(reverse('registration_register')).status_code, 200)
self.client.login(username='b', password='b')
self.assertEqual(self.client.get(reverse('list-participant')).status_code, 403)
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 403)
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
{'biography': 'foo'}).status_code, 403)
b = User.objects.get(username='b')
@ -55,12 +55,12 @@ class AccountTests(TestCase):
b.save()
p = Participation.objects.get(user=b)
self.assertFalse(p.orga)
self.assertEqual(self.client.get(reverse('list-participant')).status_code, 403)
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 403)
# login signal should set orga to True due to superuser status
self.client.login(username='b', password='b')
p = Participation.objects.get(user=b)
self.assertTrue(p.orga)
self.assertEqual(self.client.get(reverse('list-participant')).status_code, 200)
self.assertEqual(self.client.get(reverse('list-participants')).status_code, 200)
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
{'biography': 'foo', 'nootes': 'bar'}).status_code, 200)
self.assertEqual(User.objects.get(username='a').profile.biography, '')

View File

@ -8,8 +8,9 @@ urlpatterns = [
url(r'^profile/$', views.profile, name='profile'),
url(r'^login/$', auth_views.login, {'extra_context': {'buttons': [views.RESET_PASSWORD_BUTTON]}}, name='login'),
url(r'^logout/$', auth_views.logout, {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout'),
url(r'^admin/participants/$', views.participation_list, name='list-participant'),
url(r'^admin/participant/(?P<username>[\w.@+-]+)$', views.edit, name='edit-participant'),
url(r'^participant/$', views.participation_list, name='list-participants'),
url(r'^participant/(?P<username>[\w.@+-]+)$', views.participant_details, name='show-participant'),
url(r'^participant/(?P<username>[\w.@+-]+)/edit/$', views.participant_edit, name='edit-participant'),
url(r'^avatar/', include('avatar.urls')),
url(r'', include('django.contrib.auth.urls')),
url(r'', include('registration.backends.default.urls')),

View File

@ -12,6 +12,9 @@ from .forms import (NewParticipationForm, ParticipationForm,
from .models import Participation, Profile, User
from .utils import can_edit_profile, is_orga
from proposals.models import Talk
from proposals.utils import allowed_talks
RESET_PASSWORD_BUTTON = ('password_reset', 'warning', _('Reset your password'))
CHANGE_PASSWORD_BUTTON = ('password_change', 'warning', _('Change password'))
CHANGE_AVATAR_BUTTON = ('avatar_change', 'default', _('Change avatar'))
@ -30,9 +33,9 @@ def profile(request):
if all(form.is_valid() for form in forms):
for form in forms:
form.save()
messages.success(request, 'Profile updated successfully.')
messages.success(request, _('Profile updated successfully.'))
else:
messages.error(request, 'Please correct those errors.')
messages.error(request, _('Please correct those errors.'))
return render(request, 'accounts/profile.html', {
'user_form': user_form,
@ -42,30 +45,8 @@ def profile(request):
})
@staff_required
def participation_list(request):
participation_list = Participation.objects.filter(site=get_current_site(request)).all()
form = NewParticipationForm(request.POST or None, site=get_current_site(request))
if request.method == 'POST' and form.is_valid():
if not Participation.objects.get(user=request.user, site=get_current_site(request)).is_orga():
raise PermissionDenied()
user = User.objects.get(username=form.cleaned_data['participant'])
participation, created = Participation.objects.get_or_create(user=user, site=get_current_site(request))
if created:
messages.success(request, "%s added to participant" % user.profile)
else:
messages.info(request, "%s is already a participant" % user.profile)
return redirect(reverse('list-participant'))
return render(request, 'accounts/participation_list.html', {
'participation_list': participation_list,
'form': form,
})
@login_required
def edit(request, username):
def participant_edit(request, username):
profile = get_object_or_404(Profile, user__username=username)
if not can_edit_profile(request, profile):
@ -81,8 +62,41 @@ def edit(request, username):
if all(form.is_valid() for form in forms):
for form in forms:
form.save()
messages.success(request, 'Profile updated successfully.')
messages.success(request, _('Profile updated successfully.'))
else:
messages.error(request, 'Please correct those errors.')
messages.error(request, _('Please correct those errors.'))
return render(request, 'accounts/edit_profile.html', {'forms': forms, 'profile': profile})
return render(request, 'accounts/participant_edit.html', {'forms': forms, 'profile': profile})
@staff_required
def participation_list(request):
participation_list = Participation.objects.filter(site=get_current_site(request)).all()
form = NewParticipationForm(request.POST or None, site=get_current_site(request))
if request.method == 'POST' and form.is_valid():
if not Participation.objects.get(user=request.user, site=get_current_site(request)).is_orga():
raise PermissionDenied()
user = User.objects.get(username=form.cleaned_data['participant'])
participation, created = Participation.objects.get_or_create(user=user, site=get_current_site(request))
if created:
messages.success(request, _("%(name)s added to participants") % {'name': user.profile})
else:
messages.info(request, _("%(name)s is already a participant") % {'name': user.profile})
return redirect(reverse('list-participants'))
return render(request, 'accounts/participant_list.html', {
'participation_list': participation_list,
'form': form,
})
@login_required
def participant_details(request, username):
user = get_object_or_404(User, username=username)
participation = get_object_or_404(Participation, user=user, site=get_current_site(request))
return render(request, 'accounts/participant_details.html', {
'profile': user.profile,
'participation': participation,
'talk_list': allowed_talks(Talk.objects.filter(site=get_current_site(request), speakers=user), request),
})

View File

@ -53,7 +53,7 @@ class ConversationWithParticipant(Conversation):
return "Conversation with %s" % self.participation.user
def get_absolute_url(self):
return reverse('conversation', kwargs={'username': self.participation.user.username})
return reverse('user-conversation', kwargs={'username': self.participation.user.username})
def get_site(self):
return self.participation.site
@ -67,7 +67,7 @@ class ConversationWithParticipant(Conversation):
self.subscribers.add(message.author)
data = {
'content': message.content,
'uri': site.domain + reverse('conversation', args=[self.participation.user.username]),
'uri': site.domain + reverse('user-conversation', args=[self.participation.user.username]),
}
first = self.messages.first()
if first != message:
@ -117,7 +117,7 @@ class ConversationAboutTalk(Conversation):
data.update({
'talk': self.talk,
'proposer': message.author,
'proposer_uri': site.domain + reverse('show-speaker', args=[message.author.username])
'proposer_uri': site.domain + reverse('show-participant', args=[message.author.username])
})
else:
subject = 'Re: [%s] Talk: %s' % (site.name, self.talk.title)

View File

@ -1,6 +1,6 @@
<div class="panel panel-{% block panelstyleblock %}default{% endblock %}">
<div class="panel panel-{% if message.author == message.conversation.participation.user %}info{% else %}default{% endif %}">
<div class="panel-heading">
{{ message.created }} | <a href="{% url 'show-speaker' message.author.username %}">{{ message.author.profile }}</a>
{{ message.created }} | <a href="{% url 'show-participant' message.author.username %}">{{ message.author.profile }}</a>
</div>
<div class="panel-body">
{{ message.content|linebreaksbr }}

View File

@ -1,17 +1,12 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load i18n %}
{% block admintab %} active{% endblock %}
{% block correspondentstab %} class="active"{% endblock %}
{% block content %}
<div class="page-header">
<h1>{% trans "Messaging" %}</h1>
{% block heading %}
<a href="{% url 'correspondents' %}" class="btn btn-primary"><span class="glyphicon glyphicon-arrow-left"></span>&nbsp;{% trans "Go back to correspondents list" %}</a>
{% endblock %}
</div>
<h1>{% blocktrans with correspondent=correspondent.profile %}Conversation with {{ correspondent }}{% endblocktrans %}</h1>
{% for message in message_list %}
{% include 'conversations/_message_detail.html' %}

View File

@ -0,0 +1,36 @@
{% extends 'staff.html' %}
{% load bootstrap3 i18n %}
{% block correspondentstab %} class="active"{% endblock %}
{% block content %}
<h1>{% trans "Correspondents" %}</h1>
<p>{% trans "This is the list of participants that you follow." %}</p>
<table class="table table-striped">
<tr>
<th>#</th>
<th>Username</th>
<th>Full name</th>
<th>Administration</th>
</tr>
{% for correspondent in correspondent_list %}
<tr>
<th>{{ forloop.counter }}</th>
<td>{{ correspondent.user.username }}</td>
<td>{{ correspondent.user.get_full_name }}</td>
<td>
<a href="{% url 'user-conversation' correspondent.user.username %}"><span class="glyphicon glyphicon-envelope"></span></a>
{% if request.user in correspondent.conversation.subscribers.all %}
<a href="{% url 'unsubscribe-conversation' correspondent.user.username %}?next={% url 'list-correspondents' %}" data-toggle="tooltip" data-placement="bottom" title="{% trans "Unsubscribe from the conversation" %}"><span class="glyphicon glyphicon-star"></span></a>
{% else %}
<a href="{% url 'subscribe-conversation' correspondent.user.username %}?next={% url 'list-correspondents' %}" data-toggle="tooltip" data-placement="bottom" title="{% trans "Subscribe to the conversation" %}"><span class="glyphicon glyphicon-star-empty"></span></a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,38 +0,0 @@
{% extends 'base.html' %}
{% load bootstrap3 i18n %}
{% block admintab %} active{% endblock %}
{% block content %}
<div class="page-header">
<h1>{% trans "Correspondents" %}</h1>
{% trans "This is the list of participants that you follow." %}
</div>
<table class="table table-striped">
<tr>
<th>#</th>
<th>Username</th>
<th>Full name</th>
<th>Administration</th>
</tr>
{% for correspondent in correspondent_list %}
<tr>
<th>{{ forloop.counter }}</th>
<td>{{ correspondent.user.username }}</td>
<td>{{ correspondent.user.get_full_name }}</td>
<td>
<a href="{% url 'conversation' correspondent.user.username %}"><span class="glyphicon glyphicon-envelope"></span></a>
{% if request.user in correspondent.conversation.subscribers.all %}
<a href="{% url 'unsubscribe-conversation' correspondent.user.username %}?next={% url 'correspondents' %}" data-toggle="tooltip" data-placement="bottom" title="{% trans "Unsubscribe from the conversation" %}"><span class="glyphicon glyphicon-star"></span></a>
{% else %}
<a href="{% url 'subscribe-conversation' correspondent.user.username %}?next={% url 'correspondents' %}" data-toggle="tooltip" data-placement="bottom" title="{% trans "Subscribe to the conversation" %}"><span class="glyphicon glyphicon-star-empty"></span></a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,12 +1,18 @@
{% extends 'conversations/conversation.html' %}
{% extends 'base.html' %}
{% load i18n %}
{% block inboxtab %} class="active"{% endblock %}
{% block admintab %}{% endblock %}
{% block heading %}
{% block content %}
<h1>{% trans "Messaging" %}</h1>
<p>{% trans "You can use this page to communicate with the staff." %}</p>
{% endblock %}
{% block panelstyleblock %}{% if message.author == message.conversation.participation.user %}info{% else %}success{% endif %}{% endblock %}
{% for message in message_list %}
{% include 'conversations/_message_detail.html' %}
{% endfor %}
{% include 'conversations/_message_form.html' %}
{% endblock %}

View File

@ -37,12 +37,14 @@ class ConversationTests(TestCase):
self.assertEqual(self.client.get(url).status_code, 302)
self.client.login(username='c', password='c')
self.assertEqual(self.client.get(url).status_code, 403)
self.assertEqual(self.client.get(reverse('correspondents')).status_code, 200)
self.assertEqual(self.client.get(reverse('list-correspondents')).status_code, 403) # c is not staff
self.assertEqual(self.client.get(reverse('inbox')).status_code, 200)
self.client.post(reverse('inbox'), {'content': 'coucou'})
self.client.login(username='d', password='d')
self.client.post(url, {'content': 'im superuser'})
self.assertEqual(Message.objects.last().content, 'im superuser')
self.client.login(username='d', password='d')
self.assertEqual(self.client.get(reverse('list-correspondents')).status_code, 200)
@override_settings(DEFAULT_FROM_EMAIL='noreply@example.org',

View File

@ -3,10 +3,10 @@ from django.conf.urls import url
from conversations import emails, views
urlpatterns = [
url(r'^recv/$', emails.email_recv),
url(r'^recv/$', emails.email_recv), # API
url(r'^inbox/$', views.user_conversation, name='inbox'),
url(r'^$', views.correspondents, name='correspondents'),
url(r'^with/(?P<username>[\w.@+-]+)/$', views.user_conversation, name='conversation'),
url(r'^$', views.correspondent_list, name='list-correspondents'),
url(r'^with/(?P<username>[\w.@+-]+)/$', views.user_conversation, name='user-conversation'),
url(r'^about/(?P<talk>[\w.@+-]+)/$', views.talk_conversation, name='talk-conversation'),
url(r'^subscribe/(?P<username>[\w.@+-]+)/$', views.subscribe, name='subscribe-conversation'),
url(r'^unsubscribe/(?P<username>[\w.@+-]+)/$', views.unsubscribe, name='unsubscribe-conversation'),

View File

@ -5,6 +5,7 @@ from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.translation import ugettext_lazy as _
from accounts.decorators import staff_required
from accounts.models import Participation
@ -36,13 +37,14 @@ def user_conversation(request, username=None):
form.instance.conversation = conversation
form.instance.author = request.user
form.save()
messages.success(request, 'Message sent!')
messages.success(request, _('Message sent!'))
if username:
return redirect(reverse('conversation', args=[username]))
return redirect(reverse('user-conversation', args=[username]))
else:
return redirect('inbox')
return render(request, template, {
'correspondent': user,
'message_list': message_list,
'form': form,
})
@ -63,13 +65,13 @@ def talk_conversation(request, talk):
return redirect(talk.get_absolute_url())
@login_required
def correspondents(request):
@staff_required
def correspondent_list(request):
correspondent_list = Participation.objects.filter(site=get_current_site(request),
conversation__subscribers=request.user)
return render(request, 'conversations/correspondents.html', {
return render(request, 'conversations/correspondent_list.html', {
'correspondent_list': correspondent_list,
})
@ -81,7 +83,7 @@ def subscribe(request, username):
participation.conversation.subscribers.add(request.user)
messages.success(request, 'Subscribed.')
next_url = request.GET.get('next') or reverse('conversation', args=[username])
next_url = request.GET.get('next') or reverse('user-conversation', args=[username])
return redirect(next_url)
@ -93,6 +95,6 @@ def unsubscribe(request, username):
participation.conversation.subscribers.remove(request.user)
messages.success(request, 'Unsubscribed.')
next_url = request.GET.get('next') or reverse('conversation', args=[username])
next_url = request.GET.get('next') or reverse('user-conversation', args=[username])
return redirect(next_url)

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-11-08 20:31+0000\n"
"POT-Creation-Date: 2016-11-12 01:57+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"
@ -25,7 +25,8 @@ msgstr ""
"Par exemple, vous devez rentrer le samedi soir, vous ne pouvez pas manger de "
"viande, etc."
#: accounts/models.py:18 proposals/templates/proposals/user_details.html:17
#: accounts/models.py:18
#: accounts/templates/accounts/participant_details.html:20
msgid "Biography"
msgstr "Biographie"
@ -65,7 +66,8 @@ msgstr "Si différent de la ville de départ"
msgid "Need accommodation?"
msgstr "Besoin d'un hébergement ?"
#: accounts/models.py:73 proposals/templates/proposals/user_details.html:65
#: accounts/models.py:73
#: accounts/templates/accounts/participant_details.html:68
msgid "Constraints"
msgstr "Contraintes"
@ -85,9 +87,9 @@ msgstr "Jaccepte dêtre enregistré en vidéo"
msgid "Video licence"
msgstr "Licence vidéo"
#: accounts/models.py:80 proposals/models.py:144
#: proposals/templates/proposals/talk_detail.html:90
#: proposals/templates/proposals/user_details.html:68
#: accounts/models.py:80
#: accounts/templates/accounts/participant_details.html:71
#: proposals/models.py:144 proposals/templates/proposals/talk_detail.html:90
msgid "Notes"
msgstr "Notes"
@ -131,30 +133,108 @@ msgstr "Bienvenue !"
msgid "Goodbye!"
msgstr "Au revoir !"
#: accounts/templates/accounts/edit_profile.html:11
#: accounts/templates/accounts/participant_details.html:12
#: proposals/templates/proposals/speaker_list.html:92
#: volunteers/templates/volunteers/volunteer_list.html:48
msgid "Contact"
msgstr "Contacter"
#: accounts/templates/accounts/participant_details.html:15
#: proposals/templates/proposals/talk_detail.html:12
msgid "Edit"
msgstr "Éditer"
#: accounts/templates/accounts/participant_details.html:27
#: ponyconf/templates/staff.html:11
#: proposals/templates/proposals/talk_list.html:9
msgid "Talks"
msgstr "Exposés"
#: accounts/templates/accounts/participant_details.html:32
msgid "Information"
msgstr "Informations"
#: accounts/templates/accounts/participant_details.html:34
msgid "Travels and hosting"
msgstr "Déplacement et hébergement"
#: accounts/templates/accounts/participant_details.html:38
msgid "Need transport:"
msgstr "Défraiement du transport :"
#: accounts/templates/accounts/participant_details.html:46
msgid "Accepted transport means:"
msgstr "Moyens de transport souhaités :"
#: accounts/templates/accounts/participant_details.html:47
msgid "Departure city:"
msgstr "Ville de départ :"
#: accounts/templates/accounts/participant_details.html:49
msgid "Return city:"
msgstr "Ville de retour :"
#: accounts/templates/accounts/participant_details.html:51
msgid "Transport booked:"
msgstr "Transport réservé :"
#: accounts/templates/accounts/participant_details.html:55
msgid "Need accommodation:"
msgstr "Besoin d'hébergement :"
#: accounts/templates/accounts/participant_details.html:56
msgid "Accommodation booked:"
msgstr "Hébergement réservé :"
#: accounts/templates/accounts/participant_details.html:59
msgid "Talk needs"
msgstr "Besoins pour présenter"
#: accounts/templates/accounts/participant_details.html:62
msgid "Video output:"
msgstr "Sortie vidéo :"
#: accounts/templates/accounts/participant_details.html:63
msgid "Need sound:"
msgstr "Besoin de son :"
#: accounts/templates/accounts/participant_details.html:64
msgid "Ok to be recorded on video:"
msgstr "Accepte dêtre enregistré en vidéo :"
#: accounts/templates/accounts/participant_details.html:65
msgid "Video licence:"
msgstr "Licence vidéo :"
#: accounts/templates/accounts/participant_edit.html:11
#, python-format
msgid "%(profile)s's profile"
msgstr "Profil de %(profile)s"
#: accounts/templates/accounts/participation_list.html:30
#: accounts/templates/accounts/participant_list.html:9
#: ponyconf/templates/staff.html:16 volunteers/models.py:15
msgid "Participants"
msgstr "Participants"
#: accounts/templates/accounts/participant_list.html:28
msgid "View conversation"
msgstr "Afficher la discussion"
#: accounts/templates/accounts/participation_list.html:33
#: conversations/templates/conversations/correspondents.html:29
#: accounts/templates/accounts/participant_list.html:31
#: conversations/templates/conversations/correspondent_list.html:27
msgid "Unsubscribe from the conversation"
msgstr "Se désabonner de la discussion"
#: accounts/templates/accounts/participation_list.html:37
#: conversations/templates/conversations/correspondents.html:31
#: accounts/templates/accounts/participant_list.html:35
#: conversations/templates/conversations/correspondent_list.html:29
msgid "Subscribe to the conversation"
msgstr "Sabonner à la discussion"
#: accounts/templates/accounts/profile.html:12
#: accounts/templates/accounts/profile.html:12 ponyconf/templates/base.html:33
msgid "Profile"
msgstr "Profil"
#: accounts/templates/accounts/profile.html:20 accounts/views.py:17
#: accounts/templates/accounts/profile.html:20 accounts/views.py:20
msgid "Change avatar"
msgstr "Changer davatar"
@ -209,7 +289,7 @@ msgid "Delete These"
msgstr "Supprimer ces"
#: accounts/templates/registration/login.html:11
#: ponyconf/templates/base.html:98
#: ponyconf/templates/base.html:37
msgid "Login"
msgstr "Se connecter"
@ -237,14 +317,32 @@ msgid ""
"You already have an account? Please <a href=\"%(login_url)s\">login</a>."
msgstr "Déjà inscrit ? <a href=\"%(login_url)s\">Connectez-vous</a>."
#: accounts/views.py:15
#: accounts/views.py:18
msgid "Reset your password"
msgstr "Réinitialiser son mot de passe"
#: accounts/views.py:16
#: accounts/views.py:19
msgid "Change password"
msgstr "Changer de mot de passe"
#: accounts/views.py:36 accounts/views.py:65
msgid "Profile updated successfully."
msgstr "Profil mis à jour avec succès !"
#: accounts/views.py:38 accounts/views.py:67
msgid "Please correct those errors."
msgstr "Veuillez corriger les erreurs."
#: accounts/views.py:83
#, python-format
msgid "%(name)s added to participants"
msgstr "%(name)s ajouter aux participants"
#: accounts/views.py:85
#, python-format
msgid "%(name)s is already a participant"
msgstr "%(name)s est déjà un participant"
#: conversations/templates/conversations/_message_form.html:4
msgid "Send a message"
msgstr "Envoyer un message"
@ -253,31 +351,36 @@ msgstr "Envoyer un message"
msgid "Send"
msgstr "Envoyer"
#: conversations/templates/conversations/conversation.html:10
msgid "Messaging"
msgstr "Messagerie"
#: conversations/templates/conversations/conversation.html:9
#, python-format
msgid "Conversation with %(correspondent)s"
msgstr "Conversation avec %(correspondent)s"
#: conversations/templates/conversations/conversation.html:12
msgid "Go back to correspondents list"
msgstr "Retourner à la liste des correspondants"
#: conversations/templates/conversations/correspondents.html:10
#: conversations/templates/conversations/correspondent_list.html:9
#: ponyconf/templates/staff.html:17
msgid "Correspondents"
msgstr "Correspondants"
#: conversations/templates/conversations/correspondents.html:11
#: conversations/templates/conversations/correspondent_list.html:10
msgid "This is the list of participants that you follow."
msgstr "Ceci est la liste des participants que vous suivez"
msgstr "Ceci est la liste des participants que vous suivez."
#: conversations/templates/conversations/inbox.html:9
msgid "Messaging"
msgstr "Messagerie"
#: conversations/templates/conversations/inbox.html:10
msgid "You can use this page to communicate with the staff."
msgstr ""
"Vous pouvez utiliser cette page pour communiquer avec léquipe organisatrice."
#: planning/templates/planning/pending-program.html:9
#: planning/templates/planning/public-program.html:6
#: ponyconf/templates/base.html:73
msgid "Program"
#: conversations/views.py:40
msgid "Message sent!"
msgstr "Message envoyé !"
#: planning/templates/planning/public-program.html:8
#: planning/templates/planning/schedule.html:9 ponyconf/templates/staff.html:15
msgid "Schedule"
msgstr "Programme"
#: planning/templates/planning/room_detail.html:13
@ -294,20 +397,22 @@ msgid "Unscheduled talks"
msgstr "Exposés non planifiés"
#: planning/templates/planning/room_form.html:14
msgid "Room"
msgstr "Salle"
#: planning/templates/planning/room_list.html:9 ponyconf/templates/base.html:70
msgid "Rooms"
msgstr "Salles"
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
#: ponyconf/templates/staff.html:14
msgid "Rooms"
msgstr "Salles"
#: planning/templates/planning/room_list.html:21
msgid "place"
msgstr ""
msgstr "place"
#: planning/templates/planning/room_list.html:24
msgid "Some talks are not scheduled yet."
@ -332,93 +437,59 @@ msgstr "Anglais"
msgid "French"
msgstr "Français"
#: ponyconf/templates/base.html:19
#: ponyconf/templates/base.html:20
msgid "Home"
msgstr "Accueil"
#: ponyconf/templates/base.html:22
#: proposals/templates/proposals/participate.html:9
msgid "Participate"
msgstr "Participer"
msgid "Exhibitor"
msgstr "Exposant"
#: ponyconf/templates/base.html:23
msgid "Volunteer"
msgstr "Bénévole"
#: ponyconf/templates/base.html:25
msgid "Propose an intervention"
msgstr "Proposer une intervention"
msgid "Workshop registration"
msgstr "Inscription aux ateliers"
#: ponyconf/templates/base.html:28
#: volunteers/templates/volunteers/participate.html:9
msgid "Enrole as volunteer"
msgstr "Devenir bénévole"
#: ponyconf/templates/base.html:30
msgid "Staff"
msgstr "Staff"
#: ponyconf/templates/base.html:34
#: proposals/templates/proposals/subscriptions_list.html:9
#: proposals/templates/proposals/talk_subscribe.html:14
msgid "Subscribe to a workshop"
msgstr "Sinscrire à un atelier"
#: ponyconf/templates/base.html:36
#: proposals/templates/proposals/talk_registrable_list.html:25
msgid "Register"
msgstr "Sinscrire"
#: ponyconf/templates/base.html:38 ponyconf/templates/base.html:59
#: proposals/models.py:142 proposals/templates/proposals/talk_detail.html:22
#: ponyconf/templates/base.html:54
msgid "Powered by"
msgstr "Propulsé par"
#: ponyconf/templates/staff.html:9 proposals/models.py:142
#: proposals/templates/proposals/talk_detail.html:22
#: proposals/templates/proposals/talk_list.html:48
#: proposals/templates/proposals/topic_list.html:9
msgid "Topics"
msgstr "Thèmes"
#: ponyconf/templates/base.html:47
msgid "Listing"
msgstr "Liste"
#: ponyconf/templates/staff.html:10
#: proposals/templates/proposals/track_list.html:9
msgid "Tracks"
msgstr "Sessions"
#: ponyconf/templates/base.html:50
#: proposals/templates/proposals/talk_list.html:9
#: proposals/templates/proposals/user_details.html:24
msgid "Talks"
msgstr "Exposés"
#: ponyconf/templates/base.html:53 proposals/models.py:137
#: ponyconf/templates/staff.html:12 proposals/models.py:137
#: proposals/templates/proposals/speaker_list.html:9
#: proposals/templates/proposals/talk_detail.html:64
#: proposals/templates/proposals/talk_list.html:47
msgid "Speakers"
msgstr "Orateurs"
#: ponyconf/templates/base.html:56
#: ponyconf/templates/staff.html:13
#: volunteers/templates/volunteers/volunteer_list.html:9
msgid "Volunteers"
msgstr "Bénévoles"
#: ponyconf/templates/base.html:62
#: proposals/templates/proposals/track_list.html:9
msgid "Tracks"
msgstr "Sessions"
#: ponyconf/templates/base.html:67
msgid "Planning"
msgstr "Programme"
#: ponyconf/templates/base.html:78
msgid "Administration"
msgstr "Administration"
#: ponyconf/templates/base.html:85
msgid "Conference"
msgstr "Conférence"
#: ponyconf/templates/base.html:87 volunteers/models.py:15
msgid "Participants"
msgstr "Participants"
#: ponyconf/templates/base.html:88
msgid "Correspondence"
msgstr "Correspondance"
#: ponyconf/templates/base.html:97
#: proposals/templates/proposals/subscriptions_list.html:25
msgid "Register"
msgstr "Sinscrire"
#: ponyconf/templates/base.html:110
msgid "Powered by"
msgstr "Propulsé par"
#: proposals/forms.py:37
msgid "Should be less than 255 characters"
msgstr "Texte court, moins de 255 caractères"
@ -562,7 +633,7 @@ msgstr "atelier"
#: proposals/signals.py:31
msgid "stand"
msgstr ""
msgstr "stand"
#: proposals/signals.py:32
msgid "other"
@ -590,6 +661,10 @@ msgstr "Aucun exposé"
msgid "Home page"
msgstr "Page daccueil"
#: proposals/templates/proposals/participate.html:9
msgid "Participate"
msgstr "Participer"
#: proposals/templates/proposals/participate.html:12
msgid "My talks:"
msgstr "Mes exposés :"
@ -599,7 +674,7 @@ msgid "Proposed talks for others speakers:"
msgstr "Exposés proposés pour un tier :"
#: proposals/templates/proposals/participate.html:23
#: proposals/templates/proposals/talk_edit.html:9
#: proposals/templates/proposals/talk_propose.html:9
msgid "Propose a talk"
msgstr "Proposer un exposé"
@ -657,30 +732,6 @@ msgstr "Hébergement ?"
msgid "Need sound?"
msgstr "Son ?"
#: proposals/templates/proposals/speaker_list.html:92
#: proposals/templates/proposals/user_details.html:9
#: volunteers/templates/volunteers/volunteer_list.html:48
msgid "Contact"
msgstr "Contacter"
#: proposals/templates/proposals/subscriptions_list.html:18
#, python-format
msgid "%(remaining)s remaining seat"
msgid_plural "%(remaining)s remaining seats"
msgstr[0] "%(remaining)s place restante"
msgstr[1] "%(remaining)s places restantes"
#: proposals/templates/proposals/subscriptions_list.html:23
msgid "Unregister"
msgstr "Se désinscrire"
#: proposals/templates/proposals/subscriptions_list.html:33
msgid ""
"There are no workshops requiring registration for now … come back later!"
msgstr ""
"Il ny a pas datelier nécessitante inscription pour le moment … mais"
" revenez plus tard !"
#: proposals/templates/proposals/talk_decide.html:9
msgid "Are you sure to accept this proposals?"
msgstr "Êtes-vous sûr daccepter cette propositon dintervention ?"
@ -722,11 +773,6 @@ msgstr "Accepter la proposition"
msgid "Decline the proposal"
msgstr "Décliner la proposition"
#: proposals/templates/proposals/talk_detail.html:12
#: proposals/templates/proposals/user_details.html:12
msgid "Edit"
msgstr "Éditer"
#: proposals/templates/proposals/talk_detail.html:15
msgid "No abstract provided."
msgstr "Aucun résumé fourni."
@ -807,6 +853,10 @@ msgstr "Messages"
msgid "These messages are for organization team only."
msgstr "Ces messages sont à destination de la team dorganisation seulement."
#: proposals/templates/proposals/talk_edit.html:9
msgid "Edit a talk"
msgstr "Éditer un exposé"
#: proposals/templates/proposals/talk_list.html:76
msgid "Accepted"
msgstr "Accepté"
@ -828,6 +878,36 @@ msgstr "Pour les exposés sélectionnés :"
msgid "Apply"
msgstr "Appliquer"
#: proposals/templates/proposals/talk_register.html:14
msgid "Register for a workshop"
msgstr "Sinscrire à un atelier"
#: proposals/templates/proposals/talk_register.html:21
msgid "Login to register with your account"
msgstr "Connectez-vous pour vous inscrire avec votre compte"
#: proposals/templates/proposals/talk_registrable_list.html:9
msgid "Register to a workshop"
msgstr "Sinscrire à un atelier"
#: proposals/templates/proposals/talk_registrable_list.html:18
#, python-format
msgid "%(remaining)s remaining seat"
msgid_plural "%(remaining)s remaining seats"
msgstr[0] "%(remaining)s place restante"
msgstr[1] "%(remaining)s places restantes"
#: proposals/templates/proposals/talk_registrable_list.html:23
msgid "Unregister"
msgstr "Se désinscrire"
#: proposals/templates/proposals/talk_registrable_list.html:33
msgid ""
"There are no workshops requiring registration for now … come back later!"
msgstr ""
"Il ny a pas datelier nécessitante de sinscrire pour le moment … mais "
"revenez plus tard !"
#: proposals/templates/proposals/topic_form.html:14
msgid "Topic"
msgstr "Thème"
@ -852,95 +932,46 @@ msgstr "responsable"
msgid "No tracks."
msgstr "Aucune session."
#: proposals/templates/proposals/user_details.html:29
msgid "Information"
msgstr "Informations"
#: proposals/views.py:208
#, python-format
msgid "Note: the room %(room)s has %(capacity)s seat."
msgid_plural "Note: the room %(room)s has %(capacity)s seats."
msgstr[0] "Note : la salle %(room)s a %(capacity)s place."
msgstr[1] "Note : la salle %(room)s a %(capacity)s places."
#: proposals/templates/proposals/user_details.html:31
msgid "Travels and hosting"
msgstr "Déplacement et hébergement"
#: proposals/templates/proposals/user_details.html:35
msgid "Need transport:"
msgstr "Défraiement du transport :"
#: proposals/templates/proposals/user_details.html:43
msgid "Accepted transport means:"
msgstr "Moyens de transport souhaités :"
#: proposals/templates/proposals/user_details.html:44
msgid "Departure city:"
msgstr "Ville de départ :"
#: proposals/templates/proposals/user_details.html:46
msgid "Return city:"
msgstr "Ville de retour :"
#: proposals/templates/proposals/user_details.html:48
msgid "Transport booked:"
msgstr "Transport réservé :"
#: proposals/templates/proposals/user_details.html:52
msgid "Need accommodation:"
msgstr "Besoin d'hébergement :"
#: proposals/templates/proposals/user_details.html:53
msgid "Accommodation booked:"
msgstr "Hébergement réservé :"
#: proposals/templates/proposals/user_details.html:56
msgid "Talk needs"
msgstr "Besoins pour présenter"
#: proposals/templates/proposals/user_details.html:59
msgid "Video output:"
msgstr "Sortie vidéo :"
#: proposals/templates/proposals/user_details.html:60
msgid "Need sound:"
msgstr "Besoin de son :"
#: proposals/templates/proposals/user_details.html:61
msgid "Ok to be recorded on video:"
msgstr "Accepte dêtre enregistré en vidéo :"
#: proposals/templates/proposals/user_details.html:62
msgid "Video licence:"
msgstr "Licence vidéo :"
#: proposals/views.py:215
#: proposals/views.py:228
msgid "Talk modified successfully!"
msgstr "Exposé modifié avec succès !"
#: proposals/views.py:221
#: proposals/views.py:234
msgid "Talk proposed successfully!"
msgstr "Exposé proposé avec succès !"
#: proposals/views.py:236
#: proposals/views.py:249
msgid "Talk assigned to track successfully!"
msgstr "Exposé assigné à la session avec succès !"
#: proposals/views.py:305
#: proposals/views.py:318
msgid "Vote successfully created"
msgstr "A voté !"
#: proposals/views.py:305
#: proposals/views.py:318
msgid "Vote successfully updated"
msgstr "Vote mis à jour"
#: proposals/views.py:331
#: proposals/views.py:344
msgid "Decision taken in account"
msgstr "Décision enregistrée"
#: proposals/views.py:438
#: proposals/views.py:440
msgid "Unregistered :-("
msgstr "Vous avez été désinscrit :-("
#: proposals/views.py:440
#: proposals/views.py:442
msgid "Already registered!"
msgstr "Vous êtes déjà inscrit !"
#: proposals/views.py:445
#: proposals/views.py:447
msgid "Registered!"
msgstr "Vous avez été inscrit !"
@ -953,15 +984,19 @@ msgstr "Activité"
msgid "Activities"
msgstr "Activités"
#: volunteers/templates/volunteers/participate.html:19
#: volunteers/templates/volunteers/volunteer_enrole.html:9
msgid "Enrole as volunteer"
msgstr "Devenir bénévole"
#: volunteers/templates/volunteers/volunteer_enrole.html:19
msgid "Sorry, I have a setback"
msgstr "Désolé, jai un contretemps"
#: volunteers/templates/volunteers/participate.html:21
#: volunteers/templates/volunteers/volunteer_enrole.html:21
msgid "I will be happy to help on that!"
msgstr "Je serai heureux daider à cela !"
#: volunteers/templates/volunteers/participate.html:28
#: volunteers/templates/volunteers/volunteer_enrole.html:28
msgid "We are not yet looking for volunteers … come back later!"
msgstr ""
"Nous ne sommes pas encore en recherche de bénévoles … mais revenez plus "

View File

@ -1,13 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block planningtab %} active{% endblock %}
{% block content %}
<h1>{% trans "Program" %}</h1>
{{ program }}
{% endblock %}

View File

@ -1,10 +1,14 @@
{% extends '_base.html' %}
{% load i18n %}
{% block content %}
{% block body %}
<h1>{{ site.name }} {% trans "Program" %}</h1>
<div class="container">
<h1>{{ site.name }} {% trans "Schedule" %}</h1>
{{ program }}
</div>
{% endblock %}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load i18n %}
{% block planningtab %} active{% endblock %}
{% block roomstab %} class="active"{% endblock %}
{% block content %}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load i18n %}
{% block planningtab %} active{% endblock %}
{% block roomstab %} class="active"{% endblock %}
{% block css %}
{{ block.super }}
@ -11,7 +11,7 @@
{% block content %}
<h1>{% trans "Room" %}</h1>
<h1>{% if room %}{% trans "Modify the room" %}{% else %}{% trans "Add a room" %}{% endif %}</h1>
{% include "_form.html" %}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 accounts_tags i18n %}
{% block planningtab %} active{% endblock %}
{% block roomstab %} class="active"{% endblock %}
{% block content %}
@ -21,7 +21,7 @@
{{ room.capacity }} {% trans "place" %}{{ room.capacity|pluralize }}
{% if request|staff %}
|
<span{% if room.unscheduled_talks %} class="text-warning" data-toggle="tooltip" data-placement="bottom" title="{% trans "Some talks are not scheduled yet." %}"{% endif %}>
<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>
{% if request|orga %}

View File

@ -0,0 +1,13 @@
{% extends 'staff.html' %}
{% load i18n %}
{% block scheduletab %} class="active"{% endblock %}
{% block content %}
<h1>{% trans "Schedule" %}</h1>
{{ program }}
{% endblock %}

View File

@ -8,6 +8,7 @@ urlpatterns = [
url(r'^room/add/$', views.RoomCreate.as_view(), name='add-room'),
url(r'^room/(?P<slug>[-\w]+)/$', views.RoomDetail.as_view(), name='show-room'),
url(r'^room/(?P<slug>[-\w]+)/edit/$', views.RoomUpdate.as_view(), name='edit-room'),
url(r'^program/$', views.program_pending, name='pending-program'),
url(r'^program/public/$', views.program_public, name='public-program'),
url(r'^schedule/$', views.program_pending, name='show-schedule'),
url(r'^schedule/public/$', views.program_public, name='public-schedule'),
url(r'^planning/program/public/$', views.program_public),
]

View File

@ -226,7 +226,7 @@ class Program:
if talk.registration_required and self.conference.subscriptions_open:
links += mark_safe("""
<link tag="registration">%(link)s</link>""" % {
'link': reverse('subscribe-to-talk', args=[talk.slug]),
'link': reverse('register-for-a-talk', args=[talk.slug]),
})
registration = """
<attendees_max>%(max)s</attendees_max>

View File

@ -41,7 +41,7 @@ class RoomDetail(StaffRequiredMixin, RoomMixin, DetailView):
@staff_required
def program_pending(request):
output = request.GET.get('format', 'html')
return program(request, pending=True, output=output, html_template='pending-program.html', cache=False)
return program(request, pending=True, output=output, html_template='schedule.html', cache=False)
def program_public(request):
@ -52,7 +52,7 @@ def program_public(request):
def program(request, pending=False, output='html', html_template='public-program.html', cache=True):
program = Program(site=get_current_site(request), pending=pending, cache=cache)
if output == 'html':
return render(request, 'planning/' + html_template, {'program': program})
return render(request, 'planning/' + html_template, {'program': program.render('html')})
elif output == 'xml':
return HttpResponse(program.render('xml'), content_type="application/xml")
else:

View File

@ -1,3 +1,3 @@
tr.clickable-row {
cursor: pointer;
.subnav {
padding-bottom: 20px;
}

View File

@ -5,16 +5,8 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<link rel="shortcut icon" type="image/png" href="{% static 'img/favicon.ico' %}"/>
{% comment %}<link rel="icon" href="{% static 'favicon.ico' %}">{% endcomment %}
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
{% comment %}<link rel="icon" href="{% static 'favicon.ico' %}">{% endcomment %}
<title>{% block title %}{{ site.name }}{% endblock %}</title>
@ -23,31 +15,16 @@
{% block css %}{% endblock %}
{% block js %}{% endblock %}
</head>
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
{% block pageheader %}
{% endblock %}
<div class="container">
<div class="row">
<div class="col-md-12">
{% bootstrap_messages %}
{% block content %}{% endblock %}
</div> <!-- /col -->
</div> <!-- /row -->
{% block pagefooter %}
{% endblock %}
</div> <!-- /container -->
{% block body %}{% endblock %}
<script src="{% bootstrap_jquery_url %}"></script>
{% bootstrap_javascript %}

View File

@ -1,105 +1,62 @@
{% extends '_base.html' %}
{% load accounts_tags i18n %}
{% load accounts_tags i18n bootstrap3 %}
{% block pageheader %}
<!-- Static navbar -->
<div class="navbar navbar-default navbar-static-top" role="navigation">
{% block body %}
{% block navbar %}
<nav class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">{{ site.name }}</a>
<a class="navbar-brand" href="{% url 'home' %}">{{ site.name }}</a>
</div>
<div class="navbar-collapse collapse">
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li{% block hometab %}{% endblock %}><a href="{% url 'home' %}">{% trans "Home" %}</a></li>
<li{% block hometab %}{% endblock %}><a href="{% url 'home' %}"><span class="glyphicon glyphicon-home"></span>&nbsp;{% trans "Home" %}</a></li>
{% if request.user.is_authenticated %}
<li class="dropdown{% block participatetab %}{% endblock %}">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-th"></span>&nbsp;{% trans "Participate" %}&nbsp;<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{% url 'participate-as-speaker' %}"><span class="glyphicon glyphicon-bullhorn"></span>&nbsp;{% trans "Propose an intervention" %}</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{% url 'participate-as-volunteer' %}"><span class="glyphicon glyphicon-thumbs-up"></span>&nbsp;{% trans "Enrole as volunteer" %}</a>
</li>
</ul>
</li>
<li{% block exhibitortab %}{% endblock %}><a href="{% url 'participate-as-speaker' %}"><span class="glyphicon glyphicon-bullhorn"></span>&nbsp;{% trans "Exhibitor" %}</a></li>
<li{% block volunteertab %}{% endblock %}><a href="{% url 'enrole-as-volunteer' %}"><span class="glyphicon glyphicon-thumbs-up"></span>&nbsp;{% trans "Volunteer" %}</a></li>
{% endif %}
{% if conference.subscriptions_open %}
<li{% block subscriptiontab %}{% endblock %}><a href="{% url 'subscriptions-list' %}"><span class="glyphicon glyphicon-check"></span>&nbsp;{% trans "Subscribe to a workshop" %}</a></li>
{% endif %}
{% if request.user.is_authenticated %}
{% if not request|staff %}
<li{% block topictab %}{% endblock %}><a href="{% url 'list-topics' %}">{% trans "Topics" %}</a></li>
{% endif %}
{% endif %}
{% block navbar-left %}{% endblock %}
<li{% block wsregtab %}{% endblock %}><a href="{% url 'list-registrable-talks' %}"><span class="glyphicon glyphicon-edit"></span>&nbsp;{% trans "Workshop registration" %}</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if request.user.is_authenticated %}
{% if request|staff %}
<li class="dropdown{% block listingtab %}{% endblock %}">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-th-list"></span>&nbsp;{% trans "Listing" %}&nbsp;<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{% url 'list-talks' %}"><span class="glyphicon glyphicon-bullhorn"></span>&nbsp;{% trans "Talks" %}</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{% url 'list-speakers' %}"><span class="glyphicon glyphicon-user"></span>&nbsp;{% trans "Speakers" %}</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{% url 'list-volunteers' %}"><span class="glyphicon glyphicon-thumbs-up"></span>&nbsp;{% trans "Volunteers" %}</a>
</li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{% url 'list-topics' %}"><span class="glyphicon glyphicon-tag"></span>&nbsp;{% trans "Topics" %}</a></li>
</li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{% url 'list-tracks' %}"><span class="glyphicon glyphicon-screenshot"></span>&nbsp;{% trans "Tracks" %}</a></li>
</li>
<li role="presentation">
<a role="menuitem" tabindex="-1" href="{% url 'list-rooms' %}"><span class="glyphicon glyphicon-tent"></span>&nbsp;{% trans "Rooms" %}</a>
</li>
</ul>
</li>
<li{% block planningtab %}{% endblock %}><a href="{% url 'pending-program' %}"><span class="glyphicon glyphicon-calendar"></span>&nbsp;{% trans "Program" %}</a></li>
<li class="dropdown{% block admintab %}{% endblock %}">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-cog"></span>&nbsp;{% trans "Administration" %}&nbsp;<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li role="presentation">
{% if request.user.is_staff %}
<a role="menuitem" tabindex="-1" href="{% url 'admin:index' %}"><span class="glyphicon glyphicon-dashboard"></span>&nbsp;Django Admin</a>
{% endif %}
{% if request|orga %}
<a role="menuitem" tabindex="-1" href="{% url 'conference' %}"><span class="glyphicon glyphicon-blackboard"></span>&nbsp;{% trans "Conference" %}</a>
{% endif %}
<a role="menuitem" tabindex="-1" href="{% url 'list-participant' %}"><span class="glyphicon glyphicon-user"></span>&nbsp;{% trans "Participants" %}</a>
<a role="menuitem" tabindex="-1" href="{% url 'correspondents' %}"><span class="glyphicon glyphicon-envelope"></span>&nbsp;{% trans "Correspondence" %}</a>
</li>
</ul>
</li>
<li{% block stafftab %}{% endblock %}><a href="{% url 'staff' %}"><span class="glyphicon glyphicon-cog"></span>&nbsp;{% trans "Staff" %}</a></li>
{% endif %}
<li{% block inboxtab %}{% endblock %}><a href="{% url 'inbox' %}" data-toggle="tooltip" data-placement="bottom" title="Inbox"><span class="glyphicon glyphicon-envelope"></span>&nbsp;Inbox</a></li>
<li{% block profiletab %}{% endblock %}><a href="{% url 'profile' %}" data-toggle="tooltip" data-placement="bottom" title="Profile"><span class="glyphicon glyphicon-user"></span>&nbsp;{{ request.user.username }}</a></li>
<li{% block inboxtab %}{% endblock %}><a href="{% url 'inbox' %}"><span class="glyphicon glyphicon-envelope"></span>&nbsp;Inbox</a></li>
<li{% block profiletab %}{% endblock %}><a href="{% url 'profile' %}"><span class="glyphicon glyphicon-user"></span>&nbsp;{% trans "Profile" %}</a></li>
<li><a href="{% url 'logout' %}" data-toggle="tooltip" data-placement="bottom" title="Logout"><span class="glyphicon glyphicon-log-out"></span></a></li>
{% else %}
<li{% block registrationtab %}{% endblock %}><a href="{% url 'registration_register' %}"><span class="glyphicon glyphicon-edit"></span>&nbsp;{% trans "Register" %}</a></li>
<li{% block logintab %}{% endblock %}><a href="{% url 'login' %}"><span class="glyphicon glyphicon-log-in"></span>&nbsp;{% trans "Login" %}</a></li>
{% endif %}
</ul>
{% block navbar-right %}{% endblock %}
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</div>
</div>
</div>
</nav>
{% endblock %}
{% block container %}
<div class="container">
<div class="row">
<div id="content" class="col-md-12">
{% bootstrap_messages %}
{% block content %}{% endblock %}
{% block pagefooter %}
<hr>
<footer>
<p class="text-muted">{% trans "Powered by" %} <a href="https://github.com/toulibre/ponyconf">PonyConf</a></p>
</footer>
<hr>
<footer>
<p class="text-muted">{% trans "Powered by" %} <a href="https://github.com/toulibre/ponyconf">PonyConf</a></p>
</footer>
{% endblock %}
</div>
</div>
</div>
{% endblock %}
{% endblock %}

View File

@ -0,0 +1,21 @@
{% extends 'base.html' %}
{% load staticfiles i18n %}
{% block stafftab %} class="active"{% endblock %}
{% block navbar %}
{{ block.super }}
<ul class="nav nav-tabs nav-justified subnav">
<li{% block topicstab %}{% endblock %}><a href="{% url 'list-topics' %}"><span class="glyphicon glyphicon-tag"></span>&nbsp;{% trans "Topics" %}</a></li>
<li{% block trackstab %}{% endblock %}><a href="{% url 'list-tracks' %}"><span class="glyphicon glyphicon-screenshot"></span>&nbsp;{% trans "Tracks" %}</a></li>
<li{% block talkstab %}{% endblock %}><a href="{% url 'list-talks' %}"><span class="glyphicon glyphicon-blackboard"></span>&nbsp;{% trans "Talks" %}</a></li>
<li{% block speakerstab %}{% endblock %}><a href="{% url 'list-speakers' %}"><span class="glyphicon glyphicon-bullhorn"></span>&nbsp;{% trans "Speakers" %}</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 participantstab %}{% endblock %}><a href="{% url 'list-participants' %}"><span class="glyphicon glyphicon-user"></span>&nbsp;{% trans "Participants" %}</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>
<li><a href="{% url 'admin:index' %}"><span class="glyphicon glyphicon-dashboard"></span>&nbsp;Django-Admin</a></li>
</ul>
{% endblock %}

View File

@ -22,8 +22,8 @@ urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^accounts/', include('accounts.urls')),
url(r'', include('proposals.urls')),
url(r'^conversations/', include('conversations.urls')),
url(r'^planning/', include('planning.urls')),
url(r'', include('planning.urls')),
url(r'^volunteers/', include('volunteers.urls')),
url(r'^conversations/', include('conversations.urls')),
url(r'^select2/', include('django_select2.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -24,10 +24,16 @@ STATUS_VALUES = [
class TalkForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
site = kwargs.pop('site')
staff = kwargs.pop('staff')
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)
if not staff:
for field in ['track', 'duration', 'start_date', 'room', 'registration_required', 'attendees_limit']:
self.fields.pop(field)
if self.instance.pk is not None:
self.fields['title'].disabled = True
class Meta:
model = Talk

View File

@ -7,7 +7,7 @@
{{ talk.get_link }}
<i>{% trans "by" %}</i>
{% for speaker in talk.speakers.all %}
<a href="{% url 'show-speaker' speaker.username %}">{{ speaker }}</a>
<a href="{% url 'show-participant' speaker.username %}">{{ speaker }}</a>
{% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %}
{% endfor %}
{% if talk.topics.exists %}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 staticfiles i18n %}
{% block admintab %} class=active{% endblock %}
{% block conferencetab %} class=active{% endblock %}
{% block content %}

View File

@ -2,7 +2,7 @@
{% load accounts_tags i18n %}
{% block participatetab %} class="active"{% endblock %}
{% block exhibitortab %} class="active"{% endblock %}
{% block content %}
@ -19,8 +19,8 @@
{% endif %}
<br />
{% if conf.cfp_is_open or request|orga %}
<a class="btn btn-{% if conf.cfp_is_open %}success{% else %}danger{% endif %}" href="{% url 'add-talk' %}">{% trans "Propose a talk" %}</a>
{% if conference.cfp_is_open or request|orga %}
<a class="btn btn-{% if conference.cfp_is_open %}success{% else %}danger{% endif %}" href="{% url 'add-talk' %}">{% trans "Propose a talk" %}</a>
{% else %}
{% trans "Sorry, the Call for Participation is closed." %}
{% endif %}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 i18n %}
{% block listingtab %} active{% endblock %}
{% block speakerstab %} class="active"{% endblock %}
{% block content %}
@ -58,8 +58,8 @@
{% if forloop.first %}
<tbody>
{% endif %}
<tr class="clickable-row" data-href="{% url 'show-speaker' username=speaker.user.username %}">
<td>{{ speaker.user.username }}</td>
<tr>
<td><a href="{% url 'show-participant' username=speaker.user.username %}">{{ speaker.user.username }}</a></td>
<td>{{ speaker.user.get_full_name }}</td>
<td class="text-right">{{ speaker.not_refused_talk_set.count }}{% if speaker.pending_talk_set.count %} ({{ speaker.pending_talk_set.count }} pending){% endif %}</td>
{% if speaker.need_transport %}
@ -89,10 +89,9 @@
<td>No</td>
{% endif %}
<td>
<a class="btn btn-{% if speaker.conversation.messages.last.author == speaker.user %}primary{% else %}default{% endif %}" href="{% url 'conversation' speaker.user.username %}">{% trans "Contact" %}</a>
<a class="btn btn-{% if speaker.conversation.messages.last.author == speaker.user %}primary{% else %}default{% endif %}" href="{% url 'user-conversation' speaker.user.username %}">{% trans "Contact" %}</a>
</td>
</tr>
</li>
{% if forloop.last %}
</tbody>
{% endif %}
@ -104,10 +103,6 @@
{% block js_end %}
<script type="text/javascript">
jQuery(document).ready(function($) {
$(".clickable-row").click(function() {
window.location = $(this).data("href");
});
var anchor = window.location.hash.replace("#", "");
if (anchor == "filter") {
$("#filter").collapse('show');

View File

@ -1,9 +1,13 @@
{% extends 'base.html' %}
{% extends base_template %}
{% if staff %}
{% block talkstab %} class="active"{% endblock %}
{% else %}
{% block exhibitortab %} class="active"{% endblock %}
{% endif %}
{% load i18n %}
{% block listingtab %} active{% endblock %}
{% block content %}
<h1>{{ talk.title }}</h1>
@ -65,7 +69,7 @@
{% for speaker in talk.speakers.all %}
{% if forloop.first %}<ul>{% endif %}
<li><a href="{% url 'show-speaker' speaker.username %}">{{ speaker.profile }}</a></li>
<li><a href="{% url 'show-participant' speaker.username %}">{{ speaker.profile }}</a></li>
{% if forloop.last %}</ul>{% endif %}
{% empty %}
<i>{% trans "No speakers." %}</i>

View File

@ -1,12 +1,13 @@
{% extends 'base.html' %}
{% extends base_template %}
{% load bootstrap3 staticfiles i18n %}
{% load i18n %}
{% block listingtab %} active{% endblock %}
{% block talkstab %}{% if base_template == 'staff.html' %} class="active"{% endif %}{% endblock %}
{% block exhibitortab %}{% if base_template == 'base.html' %} class="active"{% endif %}{% endblock %}
{% block content %}
<h1>{% trans "Propose a talk" %}</h1>
<h1>{% if talk %}{% trans "Edit a talk" %}{% else %}{% trans "Propose a talk" %}{% endif %}</h1>
{% include "_form.html" %}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 i18n accounts_tags %}
{% block listingtab %} active{% endblock %}
{% block talkstab %} class="active"{% endblock %}
{% block content %}
@ -60,7 +60,7 @@
<td>{{ talk.event }}</td>
<td>
{% for speaker in talk.speakers.all %}
<a href="{% url 'show-speaker' speaker.username %}">{{ speaker.profile }}</a>
<a href="{% url 'show-participant' speaker.username %}">{{ speaker.profile }}</a>
{% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %}
{% empty %}
{% endfor %}

View File

@ -2,7 +2,7 @@
{% load bootstrap3 i18n %}
{% block subscriptiontab %} class="active"{% endblock %}
{% block wsregtab %} class="active"{% endblock %}
{% block css %}
{{ block.super }}
@ -11,12 +11,14 @@
{% block content %}
<h1>{% trans "Subscribe to a workshop" %}<br /><small>{{ talk.title }}</small></h1>
<h1>{% trans "Register for a workshop" %}<br /><small>{{ talk.title }}</small></h1>
<hr>
{% include "_form.html" %}
<p class="text-center">
<a href="{% url "login" %}?next={% url "subscribe-to-talk" talk.slug %}">{% trans "Login to register with you're account" %}</a>
<a href="{% url "login" %}?next={% url "register-for-a-talk" talk.slug %}">{% trans "Login to register with your account" %}</a>
</p>
{% endblock %}

View File

@ -2,11 +2,11 @@
{% load accounts_tags i18n %}
{% block subscriptiontab %} class="active"{% endblock %}
{% block wsregtab %} class="active"{% endblock %}
{% block content %}
<h1>{% trans "Subscribe to a workshop" %}</h1>
<h1>{% trans "Register to a workshop" %}</h1>
{% for talk in talks %}
{% if forloop.first %}<div class="list-group">{% endif %}
@ -20,9 +20,9 @@
{% if talk.remaining_attendees != 0 or attendee in talk.attendees.all %}
<p>
{% if attendee in talk.attendees.all %}
<a class="btn btn-danger" href="{% url 'subscribe-to-talk' talk=talk.slug %}">{% trans "Unregister" %}</a>
<a class="btn btn-danger" href="{% url 'register-for-a-talk' talk=talk.slug %}">{% trans "Unregister" %}</a>
{% else %}
<a class="btn btn-primary" href="{% url 'subscribe-to-talk' talk=talk.slug %}">{% trans "Register" %}</a>
<a class="btn btn-primary" href="{% url 'register-for-a-talk' talk=talk.slug %}">{% trans "Register" %}</a>
{% endif %}
</p>
{% endif %}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 i18n %}
{% block topictab %} class="active"{% endblock %}
{% block topicstab %} class="active"{% endblock %}
{% block css %}
{{ block.super }}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 accounts_tags i18n %}
{% block topictab %} class="active"{% endblock %}
{% block topicstab %} class="active"{% endblock %}
{% block content %}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 i18n %}
{% block tracktab %} class="active"{% endblock %}
{% block trackstab %} class="active"{% endblock %}
{% block css %}
{{ block.super }}

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 accounts_tags proposals_tags i18n %}
{% block tracktab %} class="active"{% endblock %}
{% block trackstab %} class="active"{% endblock %}
{% block content %}

View File

@ -47,7 +47,7 @@ class ProposalsTests(TestCase):
self.assertEqual(self.client.get(reverse('list-speakers')).status_code, 403)
self.assertEqual(self.client.get(reverse('edit-talk', kwargs={'talk': talk.slug})).status_code, 200)
self.assertEqual(self.client.get(reverse('show-talk', kwargs={'slug': talk.slug})).status_code, 200)
self.assertEqual(self.client.get(reverse('show-speaker', kwargs={'username': 'a'})).status_code, 200)
self.assertEqual(self.client.get(reverse('show-participant', kwargs={'username': 'a'})).status_code, 200)
self.client.login(username='b', password='b')
self.assertEqual(self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),

View File

@ -5,7 +5,8 @@ from proposals import views
urlpatterns = [
url(r'^markdown/$', views.markdown_preview, name='markdown'),
url(r'^$', views.home, name='home'),
url(r'^conference/$', views.conference, name='conference'),
url(r'^staff/$', views.staff, name='staff'),
url(r'^conference/$', views.conference, name='edit-conference'),
url(r'^talk/propose/$', views.participate, name='participate-as-speaker'),
url(r'^talk/$', views.talk_list, name='list-talks'),
url(r'^talk/add/$', views.talk_edit, name='add-talk'),
@ -22,7 +23,6 @@ urlpatterns = [
url(r'^track/add/$', views.TrackCreate.as_view(), name='add-track'),
url(r'^track/(?P<slug>[-\w]+)/edit/$', views.TrackUpdate.as_view(), name='edit-track'),
url(r'^speakers/$', views.speaker_list, name='list-speakers'),
url(r'^speaker/(?P<username>[\w.@+-]+)$', views.user_details, name='show-speaker'),
url(r'^subscribe/$', views.talk_subscriptions, name='subscriptions-list'),
url(r'^subscribe/(?P<talk>[-\w]+)$', views.talk_subscribe, name='subscribe-to-talk'),
url(r'^register/$', views.talk_registrable_list, name='list-registrable-talks'),
url(r'^register/(?P<talk>[-\w]+)$', views.talk_register, name='register-for-a-talk'),
]

View File

@ -29,7 +29,7 @@ from planning.models import Room
from .forms import TalkForm, TopicForm, TrackForm, ConferenceForm, TalkFilterForm, STATUS_VALUES, SpeakerFilterForm, TalkActionForm, SubscribeForm
from .models import Talk, Track, Topic, Vote, Conference, Attendee
from .signals import talk_added, talk_edited
from .utils import allowed_talks, markdown_to_html
from .utils import markdown_to_html
@login_required
@ -43,6 +43,11 @@ def home(request):
return render(request, 'proposals/home.html')
@staff_required
def staff(request):
return render(request, 'staff.html')
@orga_required
def conference(request):
conference = Conference.objects.get(site=get_current_site(request))
@ -50,7 +55,7 @@ def conference(request):
if request.method == 'POST' and form.is_valid():
form.save()
messages.success(request, 'Conference updated!')
return redirect(reverse('conference'))
return redirect(reverse('edit-conference'))
return render(request, 'proposals/conference.html', {
'form': form,
})
@ -185,34 +190,19 @@ def talk_edit(request, talk=None):
conf = Conference.objects.get(site=site)
if not is_orga(request, request.user) and not conf.cfp_is_open():
raise PermissionDenied
form = TalkForm(request.POST or None, instance=talk, site=site)
staff = talk.is_moderable_by(request.user) if talk else is_orga(request, request.user)
form = TalkForm(request.POST or None, instance=talk, site=site, staff=staff)
if talk:
form.fields['topics'].disabled = True
if talk.event.duration:
if 'duration' in form.fields and talk.event.duration:
form.fields['duration'].help_text = 'Default value if zero: %d min' % talk.duration
if not talk.is_editable_by(request.user):
form.fields.pop('track')
form.fields.pop('duration')
form.fields.pop('start_date')
form.fields.pop('room')
form.fields.pop('registration_required')
form.fields.pop('attendees_limit')
elif talk.room and talk.room.capacity:
if 'attendees_limit' in form.fields and talk.is_editable_by(request.user) and talk.room and talk.room.capacity:
form.fields['attendees_limit'].help_text=ungettext_lazy(
"Note: the room %(room)s has %(capacity)s seat.",
"Note: the room %(room)s has %(capacity)s seats.",
talk.room.capacity) % {'room': talk.room.name, 'capacity': talk.room.capacity}
if not talk.is_moderable_by(request.user):
form.fields['title'].disabled = True
else:
form.fields['speakers'].initial = [request.user]
if not is_orga(request, request.user):
form.fields.pop('track')
form.fields.pop('duration')
form.fields.pop('start_date')
form.fields.pop('room')
form.fields.pop('registration_required')
form.fields.pop('attendees_limit')
if request.method == 'POST' and form.is_valid():
if hasattr(talk, 'id'):
talk = form.save()
@ -227,6 +217,8 @@ def talk_edit(request, talk=None):
messages.success(request, _('Talk proposed successfully!'))
return redirect(talk.get_absolute_url())
return render(request, 'proposals/talk_edit.html', {
'base_template': 'staff.html' if staff else 'base.html',
'talk': talk,
'form': form,
})
@ -255,6 +247,10 @@ class TalkDetail(LoginRequiredMixin, DetailView):
form_url=reverse('talk-conversation', kwargs={'talk': self.object.slug}))
else:
ctx['edit_perm'] = self.object.is_editable_by(self.request.user)
if is_staff(self.request, self.request.user):
ctx.update(base_template='staff.html')
else:
ctx.update(base_template='base.html')
return super().get_context_data(**ctx)
@ -402,18 +398,7 @@ def speaker_list(request):
})
@login_required
def user_details(request, username):
user = get_object_or_404(User, username=username)
participation = get_object_or_404(Participation, user=user, site=get_current_site(request))
return render(request, 'proposals/user_details.html', {
'profile': user.profile,
'participation': participation,
'talk_list': allowed_talks(Talk.objects.filter(site=get_current_site(request), speakers=user), request),
})
def talk_subscriptions(request):
def talk_registrable_list(request):
site = get_current_site(request)
if not Conference.objects.get(site=site).subscriptions_open:
raise Http404
@ -422,13 +407,13 @@ def talk_subscriptions(request):
attendee = Attendee.objects.filter(user=request.user).first() # None if it does not exists
else:
attendee = None
return render(request, 'proposals/subscriptions_list.html', {
return render(request, 'proposals/talk_registrable_list.html', {
'talks': talks,
'attendee': attendee,
})
def talk_subscribe(request, talk):
def talk_register(request, talk):
talk = get_object_or_404(Talk, site=get_current_site(request), registration_required=True, slug=talk)
form = SubscribeForm(request.POST or None)
@ -450,9 +435,9 @@ def talk_subscribe(request, talk):
talk.attendees.add(attendee)
messages.success(request, _("Registered!"))
talk.save()
return redirect('subscriptions-list')
return redirect('list-registrable-talks')
return render(request, 'proposals/talk_subscribe.html', {
return render(request, 'proposals/talk_register.html', {
'talk': talk,
'form': form,
})

View File

@ -2,7 +2,7 @@
{% load accounts_tags i18n %}
{% block participatetab %} class="active"{% endblock %}
{% block volunteertab %} class="active"{% endblock %}
{% block content %}
@ -16,9 +16,9 @@
<p>{{ activity.description }}</p>
<p>
{% if request.user in activity.participants.all %}
<a class="btn btn-danger" href="{% url 'enrole-in-activity' slug=activity.slug %}">{% trans "Sorry, I have a setback" %}</a>
<a class="btn btn-danger" href="{% url 'enrole-as-volunteer' slug=activity.slug %}">{% trans "Sorry, I have a setback" %}</a>
{% else %}
<a class="btn btn-primary" href="{% url 'enrole-in-activity' slug=activity.slug %}">{% trans "I will be happy to help on that!" %}</a>
<a class="btn btn-primary" href="{% url 'enrole-as-volunteer' slug=activity.slug %}">{% trans "I will be happy to help on that!" %}</a>
{% endif %}
</p>
</p>

View File

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'staff.html' %}
{% load bootstrap3 i18n %}
{% block listingtab %} active{% endblock %}
{% block volunteerstab %} class="active"{% endblock %}
{% block content %}
@ -36,8 +36,8 @@
{% if forloop.first %}
<tbody>
{% endif %}
<tr class="clickable-row" data-href="{% url 'show-speaker' username=volunteer.user.username %}">
<td>{{ volunteer.user.username }}</td>
<tr>
<td><a href="{% url 'show-participant' username=volunteer.user.username %}">{{ volunteer.user.username }}</a></td>
<td>{{ volunteer.user.get_full_name }}</td>
<td>
{% for activity in volunteer.user.activities.all %}
@ -45,10 +45,9 @@
{% endfor %}
</td>
<td>
<a class="btn btn-{% if volunteer.conversation.messages.last.author == volunteer.user %}primary{% else %}default{% endif %}" href="{% url 'conversation' volunteer.user.username %}">{% trans "Contact" %}</a>
<a class="btn btn-{% if volunteer.conversation.messages.last.author == volunteer.user %}primary{% else %}default{% endif %}" href="{% url 'user-conversation' volunteer.user.username %}">{% trans "Contact" %}</a>
</td>
</tr>
</li>
{% if forloop.last %}
</tbody>
{% endif %}

View File

@ -4,10 +4,10 @@ from . import views
urlpatterns = [
url(r'^enrole/$', views.participate, name='participate-as-volunteer'),
url(r'^enrole/$', views.enrole, name='enrole-as-volunteer'),
url(r'^enrole/(?P<slug>[-\w]+)/$', views.enrole, name='enrole-as-volunteer'),
url(r'^list/$', views.volunteer_list, name='list-volunteers'),
url(r'^activities/$', views.ActivityList.as_view(), name='list-activities'),
url(r'^activities/add/$', views.ActivityCreate.as_view(), name='add-activity'),
url(r'^activities/(?P<slug>[-\w]+)/edit/$', views.ActivityUpdate.as_view(), name='edit-activity'),
url(r'^activities/(?P<slug>[-\w]+)/enrole/$', views.participate, name='enrole-in-activity'),
]

View File

@ -15,7 +15,7 @@ from .forms import ActivityForm, VolunteerFilterForm
@login_required
def participate(request, slug=None):
def enrole(request, slug=None):
if slug:
# TODO: enrole action should be done on post (with bootstrap modal confirmation box?)
activity = get_object_or_404(Activity, site=get_current_site(request), slug=slug)
@ -24,13 +24,32 @@ def participate(request, slug=None):
else:
activity.participants.add(request.user)
activity.save()
return redirect('participate-as-volunteer')
return redirect('enrole-as-volunteer')
activities = Activity.objects.filter(site=get_current_site(request))
return render(request, 'volunteers/participate.html', {
return render(request, 'volunteers/volunteer_enrole.html', {
'activities': activities,
})
@staff_required
def volunteer_list(request):
show_filters = False
site = get_current_site(request)
filter_form = VolunteerFilterForm(request.GET or None, site=site)
# Filtering
volunteers = Participation.objects.filter(site=site,user__activities__isnull=False).order_by('pk').distinct()
if filter_form.is_valid():
data = filter_form.cleaned_data
if len(data['activity']):
show_filters = True
volunteers = volunteers.filter(user__activities__slug__in=data['activity'])
return render(request, 'volunteers/volunteer_list.html', {
'volunteer_list': volunteers,
'filter_form': filter_form,
'show_filters': show_filters,
})
class ActivityMixin(object):
def get_queryset(self):
return Activity.objects.filter(site=get_current_site(self.request)).all()
@ -54,22 +73,3 @@ class ActivityUpdate(OrgaRequiredMixin, ActivityMixin, ActivityFormMixin, Update
class ActivityDetail(StaffRequiredMixin, ActivityMixin, DetailView):
pass
@staff_required
def volunteer_list(request):
show_filters = False
site = get_current_site(request)
filter_form = VolunteerFilterForm(request.GET or None, site=site)
# Filtering
volunteers = Participation.objects.filter(site=site,user__activities__isnull=False).order_by('pk').distinct()
if filter_form.is_valid():
data = filter_form.cleaned_data
if len(data['activity']):
show_filters = True
volunteers = volunteers.filter(user__activities__slug__in=data['activity'])
return render(request, 'volunteers/volunteer_list.html', {
'volunteer_list': volunteers,
'filter_form': filter_form,
'show_filters': show_filters,
})