Merge branch 'dev'
This commit is contained in:
commit
8582f68c77
|
@ -9,7 +9,7 @@ from .models import Participation, Profile
|
||||||
|
|
||||||
UserForm = modelform_factory(User, fields=['first_name', 'last_name', 'email', 'username'])
|
UserForm = modelform_factory(User, fields=['first_name', 'last_name', 'email', 'username'])
|
||||||
|
|
||||||
ProfileForm = modelform_factory(Profile, fields=['biography'])
|
ProfileForm = modelform_factory(Profile, fields=['phone_number', 'biography'])
|
||||||
|
|
||||||
ParticipationForm = modelform_factory(Participation,
|
ParticipationForm = modelform_factory(Participation,
|
||||||
fields=['need_transport', 'transport', 'transport_city_outward', 'transport_city_return',
|
fields=['need_transport', 'transport', 'transport_city_outward', 'transport_city_return',
|
||||||
|
|
20
accounts/migrations/0016_profile_phone_number.py
Normal file
20
accounts/migrations/0016_profile_phone_number.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10 on 2016-11-13 19:08
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('accounts', '0015_auto_20161013_1922'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='profile',
|
||||||
|
name='phone_number',
|
||||||
|
field=models.CharField(blank=True, default='', max_length=16, verbose_name='Phone number'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -15,6 +15,7 @@ from .utils import generate_user_uid
|
||||||
class Profile(PonyConfModel):
|
class Profile(PonyConfModel):
|
||||||
|
|
||||||
user = models.OneToOneField(User)
|
user = models.OneToOneField(User)
|
||||||
|
phone_number = models.CharField(max_length=16, blank=True, default='', verbose_name=_('Phone number'))
|
||||||
biography = models.TextField(blank=True, verbose_name=_('Biography'))
|
biography = models.TextField(blank=True, verbose_name=_('Biography'))
|
||||||
email_token = models.CharField(max_length=12, default=generate_user_uid, unique=True)
|
email_token = models.CharField(max_length=12, default=generate_user_uid, unique=True)
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ class Participation(PonyConfModel):
|
||||||
return str(self.user.profile)
|
return str(self.user.profile)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
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):
|
def is_orga(self):
|
||||||
return self.orga
|
return self.orga
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load accounts_tags i18n avatar_tags %}
|
{% load accounts_tags i18n avatar_tags %}
|
||||||
|
|
||||||
|
{% block participantstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h1>{{ profile }}</h1>
|
<h1>{{ profile }}</h1>
|
||||||
|
|
||||||
{% if request|staff %}
|
{% 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 %}
|
{% endif %}
|
||||||
{% if request|edit_profile:profile %}
|
{% if request|edit_profile:profile %}
|
||||||
<a href="{% url 'edit-participant' profile.user.username %}" class="btn btn-success">{% trans "Edit" %}</a>
|
<a href="{% url 'edit-participant' profile.user.username %}" class="btn btn-success">{% trans "Edit" %}</a>
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block speakertab %} class="active"{% endblock %}
|
{% block participantstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 accounts_tags i18n %}
|
{% load bootstrap3 accounts_tags i18n %}
|
||||||
|
|
||||||
{% block admintab %} active{% endblock %}
|
{% block participantstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="page-header">
|
<h1>{% trans "Participants" %}</h1>
|
||||||
<h1>Participants</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -26,14 +24,14 @@
|
||||||
<td>{% for topic in participation.topic_set.all %}{{ topic.get_link }}{% if not forloop.last %},
|
<td>{% for topic in participation.topic_set.all %}{{ topic.get_link }}{% if not forloop.last %},
|
||||||
{% endif %}{% endfor %}</td>
|
{% endif %}{% endfor %}</td>
|
||||||
<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>
|
title="{% trans "View conversation" %}"><span class="glyphicon glyphicon-envelope"></span></a>
|
||||||
{% if request.user in participation.conversation.subscribers.all %}
|
{% 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" %}">
|
data-toggle="tooltip" data-placement="bottom" title="{% trans "Unsubscribe from the conversation" %}">
|
||||||
<span class="glyphicon glyphicon-star"></span></a>
|
<span class="glyphicon glyphicon-star"></span></a>
|
||||||
{% else %}
|
{% 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" %}">
|
data-toggle="tooltip" data-placement="bottom" title="{% trans "Subscribe to the conversation" %}">
|
||||||
<span class="glyphicon glyphicon-star-empty"></span></a>
|
<span class="glyphicon glyphicon-star-empty"></span></a>
|
||||||
{% endif %}
|
{% endif %}
|
|
@ -47,7 +47,7 @@ class AccountTests(TestCase):
|
||||||
def test_participant_views(self):
|
def test_participant_views(self):
|
||||||
self.assertEqual(self.client.get(reverse('registration_register')).status_code, 200)
|
self.assertEqual(self.client.get(reverse('registration_register')).status_code, 200)
|
||||||
self.client.login(username='b', password='b')
|
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'}),
|
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
|
||||||
{'biography': 'foo'}).status_code, 403)
|
{'biography': 'foo'}).status_code, 403)
|
||||||
b = User.objects.get(username='b')
|
b = User.objects.get(username='b')
|
||||||
|
@ -55,12 +55,12 @@ class AccountTests(TestCase):
|
||||||
b.save()
|
b.save()
|
||||||
p = Participation.objects.get(user=b)
|
p = Participation.objects.get(user=b)
|
||||||
self.assertFalse(p.orga)
|
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
|
# login signal should set orga to True due to superuser status
|
||||||
self.client.login(username='b', password='b')
|
self.client.login(username='b', password='b')
|
||||||
p = Participation.objects.get(user=b)
|
p = Participation.objects.get(user=b)
|
||||||
self.assertTrue(p.orga)
|
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'}),
|
self.assertEqual(self.client.post(reverse('edit-participant', kwargs={'username': 'a'}),
|
||||||
{'biography': 'foo', 'nootes': 'bar'}).status_code, 200)
|
{'biography': 'foo', 'nootes': 'bar'}).status_code, 200)
|
||||||
self.assertEqual(User.objects.get(username='a').profile.biography, '')
|
self.assertEqual(User.objects.get(username='a').profile.biography, '')
|
||||||
|
|
|
@ -8,8 +8,9 @@ urlpatterns = [
|
||||||
url(r'^profile/$', views.profile, name='profile'),
|
url(r'^profile/$', views.profile, name='profile'),
|
||||||
url(r'^login/$', auth_views.login, {'extra_context': {'buttons': [views.RESET_PASSWORD_BUTTON]}}, name='login'),
|
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'^logout/$', auth_views.logout, {'next_page': settings.LOGOUT_REDIRECT_URL}, name='logout'),
|
||||||
url(r'^admin/participants/$', views.participation_list, name='list-participant'),
|
url(r'^participant/$', views.participation_list, name='list-participants'),
|
||||||
url(r'^admin/participant/(?P<username>[\w.@+-]+)$', views.edit, name='edit-participant'),
|
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'^avatar/', include('avatar.urls')),
|
||||||
url(r'', include('django.contrib.auth.urls')),
|
url(r'', include('django.contrib.auth.urls')),
|
||||||
url(r'', include('registration.backends.default.urls')),
|
url(r'', include('registration.backends.default.urls')),
|
||||||
|
|
|
@ -12,6 +12,9 @@ from .forms import (NewParticipationForm, ParticipationForm,
|
||||||
from .models import Participation, Profile, User
|
from .models import Participation, Profile, User
|
||||||
from .utils import can_edit_profile, is_orga
|
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'))
|
RESET_PASSWORD_BUTTON = ('password_reset', 'warning', _('Reset your password'))
|
||||||
CHANGE_PASSWORD_BUTTON = ('password_change', 'warning', _('Change password'))
|
CHANGE_PASSWORD_BUTTON = ('password_change', 'warning', _('Change password'))
|
||||||
CHANGE_AVATAR_BUTTON = ('avatar_change', 'default', _('Change avatar'))
|
CHANGE_AVATAR_BUTTON = ('avatar_change', 'default', _('Change avatar'))
|
||||||
|
@ -30,9 +33,9 @@ def profile(request):
|
||||||
if all(form.is_valid() for form in forms):
|
if all(form.is_valid() for form in forms):
|
||||||
for form in forms:
|
for form in forms:
|
||||||
form.save()
|
form.save()
|
||||||
messages.success(request, 'Profile updated successfully.')
|
messages.success(request, _('Profile updated successfully.'))
|
||||||
else:
|
else:
|
||||||
messages.error(request, 'Please correct those errors.')
|
messages.error(request, _('Please correct those errors.'))
|
||||||
|
|
||||||
return render(request, 'accounts/profile.html', {
|
return render(request, 'accounts/profile.html', {
|
||||||
'user_form': user_form,
|
'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
|
@login_required
|
||||||
def edit(request, username):
|
def participant_edit(request, username):
|
||||||
|
|
||||||
profile = get_object_or_404(Profile, user__username=username)
|
profile = get_object_or_404(Profile, user__username=username)
|
||||||
if not can_edit_profile(request, profile):
|
if not can_edit_profile(request, profile):
|
||||||
|
@ -81,8 +62,41 @@ def edit(request, username):
|
||||||
if all(form.is_valid() for form in forms):
|
if all(form.is_valid() for form in forms):
|
||||||
for form in forms:
|
for form in forms:
|
||||||
form.save()
|
form.save()
|
||||||
messages.success(request, 'Profile updated successfully.')
|
messages.success(request, _('Profile updated successfully.'))
|
||||||
else:
|
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),
|
||||||
|
})
|
||||||
|
|
|
@ -53,7 +53,7 @@ class ConversationWithParticipant(Conversation):
|
||||||
return "Conversation with %s" % self.participation.user
|
return "Conversation with %s" % self.participation.user
|
||||||
|
|
||||||
def get_absolute_url(self):
|
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):
|
def get_site(self):
|
||||||
return self.participation.site
|
return self.participation.site
|
||||||
|
@ -67,7 +67,7 @@ class ConversationWithParticipant(Conversation):
|
||||||
self.subscribers.add(message.author)
|
self.subscribers.add(message.author)
|
||||||
data = {
|
data = {
|
||||||
'content': message.content,
|
'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()
|
first = self.messages.first()
|
||||||
if first != message:
|
if first != message:
|
||||||
|
@ -117,7 +117,7 @@ class ConversationAboutTalk(Conversation):
|
||||||
data.update({
|
data.update({
|
||||||
'talk': self.talk,
|
'talk': self.talk,
|
||||||
'proposer': message.author,
|
'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:
|
else:
|
||||||
subject = 'Re: [%s] Talk: %s' % (site.name, self.talk.title)
|
subject = 'Re: [%s] Talk: %s' % (site.name, self.talk.title)
|
||||||
|
|
|
@ -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">
|
<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>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{{ message.content|linebreaksbr }}
|
{{ message.content|linebreaksbr }}
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block admintab %} active{% endblock %}
|
{% block correspondentstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="page-header">
|
<h1>{% blocktrans with correspondent=correspondent.profile %}Conversation with {{ correspondent }}{% endblocktrans %}</h1>
|
||||||
<h1>{% trans "Messaging" %}</h1>
|
|
||||||
{% block heading %}
|
|
||||||
<a href="{% url 'correspondents' %}" class="btn btn-primary"><span class="glyphicon glyphicon-arrow-left"></span> {% trans "Go back to correspondents list" %}</a>
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% for message in message_list %}
|
{% for message in message_list %}
|
||||||
{% include 'conversations/_message_detail.html' %}
|
{% include 'conversations/_message_detail.html' %}
|
||||||
|
|
|
@ -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 %}
|
|
@ -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 %}
|
|
|
@ -1,12 +1,18 @@
|
||||||
{% extends 'conversations/conversation.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block inboxtab %} class="active"{% endblock %}
|
{% 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>
|
<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 %}
|
||||||
|
|
|
@ -37,12 +37,14 @@ class ConversationTests(TestCase):
|
||||||
self.assertEqual(self.client.get(url).status_code, 302)
|
self.assertEqual(self.client.get(url).status_code, 302)
|
||||||
self.client.login(username='c', password='c')
|
self.client.login(username='c', password='c')
|
||||||
self.assertEqual(self.client.get(url).status_code, 403)
|
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.assertEqual(self.client.get(reverse('inbox')).status_code, 200)
|
||||||
self.client.post(reverse('inbox'), {'content': 'coucou'})
|
self.client.post(reverse('inbox'), {'content': 'coucou'})
|
||||||
self.client.login(username='d', password='d')
|
self.client.login(username='d', password='d')
|
||||||
self.client.post(url, {'content': 'im superuser'})
|
self.client.post(url, {'content': 'im superuser'})
|
||||||
self.assertEqual(Message.objects.last().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',
|
@override_settings(DEFAULT_FROM_EMAIL='noreply@example.org',
|
||||||
|
|
|
@ -3,10 +3,10 @@ from django.conf.urls import url
|
||||||
from conversations import emails, views
|
from conversations import emails, views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^recv/$', emails.email_recv),
|
url(r'^recv/$', emails.email_recv), # API
|
||||||
url(r'^inbox/$', views.user_conversation, name='inbox'),
|
url(r'^inbox/$', views.user_conversation, name='inbox'),
|
||||||
url(r'^$', views.correspondents, name='correspondents'),
|
url(r'^$', views.correspondent_list, name='list-correspondents'),
|
||||||
url(r'^with/(?P<username>[\w.@+-]+)/$', views.user_conversation, name='conversation'),
|
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'^about/(?P<talk>[\w.@+-]+)/$', views.talk_conversation, name='talk-conversation'),
|
||||||
url(r'^subscribe/(?P<username>[\w.@+-]+)/$', views.subscribe, name='subscribe-conversation'),
|
url(r'^subscribe/(?P<username>[\w.@+-]+)/$', views.subscribe, name='subscribe-conversation'),
|
||||||
url(r'^unsubscribe/(?P<username>[\w.@+-]+)/$', views.unsubscribe, name='unsubscribe-conversation'),
|
url(r'^unsubscribe/(?P<username>[\w.@+-]+)/$', views.unsubscribe, name='unsubscribe-conversation'),
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.contrib.sites.shortcuts import get_current_site
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
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.decorators import staff_required
|
||||||
from accounts.models import Participation
|
from accounts.models import Participation
|
||||||
|
@ -36,13 +37,14 @@ def user_conversation(request, username=None):
|
||||||
form.instance.conversation = conversation
|
form.instance.conversation = conversation
|
||||||
form.instance.author = request.user
|
form.instance.author = request.user
|
||||||
form.save()
|
form.save()
|
||||||
messages.success(request, 'Message sent!')
|
messages.success(request, _('Message sent!'))
|
||||||
if username:
|
if username:
|
||||||
return redirect(reverse('conversation', args=[username]))
|
return redirect(reverse('user-conversation', args=[username]))
|
||||||
else:
|
else:
|
||||||
return redirect('inbox')
|
return redirect('inbox')
|
||||||
|
|
||||||
return render(request, template, {
|
return render(request, template, {
|
||||||
|
'correspondent': user,
|
||||||
'message_list': message_list,
|
'message_list': message_list,
|
||||||
'form': form,
|
'form': form,
|
||||||
})
|
})
|
||||||
|
@ -63,13 +65,13 @@ def talk_conversation(request, talk):
|
||||||
return redirect(talk.get_absolute_url())
|
return redirect(talk.get_absolute_url())
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@staff_required
|
||||||
def correspondents(request):
|
def correspondent_list(request):
|
||||||
|
|
||||||
correspondent_list = Participation.objects.filter(site=get_current_site(request),
|
correspondent_list = Participation.objects.filter(site=get_current_site(request),
|
||||||
conversation__subscribers=request.user)
|
conversation__subscribers=request.user)
|
||||||
|
|
||||||
return render(request, 'conversations/correspondents.html', {
|
return render(request, 'conversations/correspondent_list.html', {
|
||||||
'correspondent_list': correspondent_list,
|
'correspondent_list': correspondent_list,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -81,7 +83,7 @@ def subscribe(request, username):
|
||||||
participation.conversation.subscribers.add(request.user)
|
participation.conversation.subscribers.add(request.user)
|
||||||
messages.success(request, 'Subscribed.')
|
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)
|
return redirect(next_url)
|
||||||
|
|
||||||
|
@ -93,6 +95,6 @@ def unsubscribe(request, username):
|
||||||
participation.conversation.subscribers.remove(request.user)
|
participation.conversation.subscribers.remove(request.user)
|
||||||
messages.success(request, 'Unsubscribed.')
|
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)
|
return redirect(next_url)
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -1,13 +0,0 @@
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block planningtab %} active{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<h1>{% trans "Program" %}</h1>
|
|
||||||
|
|
||||||
{{ program }}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
|
@ -1,10 +1,14 @@
|
||||||
{% extends '_base.html' %}
|
{% extends '_base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block body %}
|
||||||
|
|
||||||
<h1>{{ site.name }} – {% trans "Program" %}</h1>
|
<div class="container">
|
||||||
|
|
||||||
|
<h1>{{ site.name }} – {% trans "Schedule" %}</h1>
|
||||||
|
|
||||||
{{ program }}
|
{{ program }}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block planningtab %} active{% endblock %}
|
{% block roomstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block planningtab %} active{% endblock %}
|
{% block roomstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h1>{% trans "Room" %}</h1>
|
<h1>{% if room %}{% trans "Modify the room" %}{% else %}{% trans "Add a room" %}{% endif %}</h1>
|
||||||
|
|
||||||
{% include "_form.html" %}
|
{% include "_form.html" %}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 accounts_tags i18n %}
|
{% load bootstrap3 accounts_tags i18n %}
|
||||||
|
|
||||||
{% block planningtab %} active{% endblock %}
|
{% block roomstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
{{ room.capacity }} {% trans "place" %}{{ room.capacity|pluralize }}
|
{{ room.capacity }} {% trans "place" %}{{ room.capacity|pluralize }}
|
||||||
{% if request|staff %}
|
{% 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 }}
|
{{ room.talks.count }} {% trans "talk" %}{{ room.talks.count|pluralize }}
|
||||||
</span>
|
</span>
|
||||||
{% if request|orga %}
|
{% if request|orga %}
|
||||||
|
|
13
planning/templates/planning/schedule.html
Normal file
13
planning/templates/planning/schedule.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block scheduletab %} class="active"{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1>{% trans "Schedule" %}</h1>
|
||||||
|
|
||||||
|
{{ program }}
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -8,6 +8,7 @@ urlpatterns = [
|
||||||
url(r'^room/add/$', views.RoomCreate.as_view(), name='add-room'),
|
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]+)/$', views.RoomDetail.as_view(), name='show-room'),
|
||||||
url(r'^room/(?P<slug>[-\w]+)/edit/$', views.RoomUpdate.as_view(), name='edit-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'^schedule/$', views.program_pending, name='show-schedule'),
|
||||||
url(r'^program/public/$', views.program_public, name='public-program'),
|
url(r'^schedule/public/$', views.program_public, name='public-schedule'),
|
||||||
|
url(r'^planning/program/public/$', views.program_public),
|
||||||
]
|
]
|
||||||
|
|
|
@ -226,7 +226,7 @@ class Program:
|
||||||
if talk.registration_required and self.conference.subscriptions_open:
|
if talk.registration_required and self.conference.subscriptions_open:
|
||||||
links += mark_safe("""
|
links += mark_safe("""
|
||||||
<link tag="registration">%(link)s</link>""" % {
|
<link tag="registration">%(link)s</link>""" % {
|
||||||
'link': reverse('subscribe-to-talk', args=[talk.slug]),
|
'link': reverse('register-for-a-talk', args=[talk.slug]),
|
||||||
})
|
})
|
||||||
registration = """
|
registration = """
|
||||||
<attendees_max>%(max)s</attendees_max>
|
<attendees_max>%(max)s</attendees_max>
|
||||||
|
|
|
@ -41,7 +41,7 @@ class RoomDetail(StaffRequiredMixin, RoomMixin, DetailView):
|
||||||
@staff_required
|
@staff_required
|
||||||
def program_pending(request):
|
def program_pending(request):
|
||||||
output = request.GET.get('format', 'html')
|
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):
|
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):
|
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)
|
program = Program(site=get_current_site(request), pending=pending, cache=cache)
|
||||||
if output == 'html':
|
if output == 'html':
|
||||||
return render(request, 'planning/' + html_template, {'program': program})
|
return render(request, 'planning/' + html_template, {'program': program.render('html')})
|
||||||
elif output == 'xml':
|
elif output == 'xml':
|
||||||
return HttpResponse(program.render('xml'), content_type="application/xml")
|
return HttpResponse(program.render('xml'), content_type="application/xml")
|
||||||
elif output == 'ics':
|
elif output == 'ics':
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
tr.clickable-row {
|
.subnav {
|
||||||
cursor: pointer;
|
padding-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,8 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<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 -->
|
{% comment %}<link rel="icon" href="{% static 'favicon.ico' %}">{% endcomment %}
|
||||||
<!--[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]-->
|
|
||||||
|
|
||||||
<title>{% block title %}{{ site.name }}{% endblock %}</title>
|
<title>{% block title %}{{ site.name }}{% endblock %}</title>
|
||||||
|
|
||||||
|
@ -23,31 +15,16 @@
|
||||||
{% block css %}{% endblock %}
|
{% block css %}{% endblock %}
|
||||||
|
|
||||||
{% block js %}{% 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>
|
<body>
|
||||||
|
|
||||||
{% block pageheader %}
|
{% block body %}{% endblock %}
|
||||||
{% 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 -->
|
|
||||||
|
|
||||||
<script src="{% bootstrap_jquery_url %}"></script>
|
<script src="{% bootstrap_jquery_url %}"></script>
|
||||||
{% bootstrap_javascript %}
|
{% bootstrap_javascript %}
|
||||||
|
|
|
@ -1,105 +1,62 @@
|
||||||
{% extends '_base.html' %}
|
{% extends '_base.html' %}
|
||||||
{% load accounts_tags i18n %}
|
{% load accounts_tags i18n bootstrap3 %}
|
||||||
|
|
||||||
{% block pageheader %}
|
{% block body %}
|
||||||
<!-- Static navbar -->
|
|
||||||
<div class="navbar navbar-default navbar-static-top" role="navigation">
|
{% block navbar %}
|
||||||
|
<nav class="navbar navbar-inverse" role="navigation">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="navbar-header">
|
<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="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="#">{{ site.name }}</a>
|
<a class="navbar-brand" href="{% url 'home' %}">{{ site.name }}</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-collapse collapse">
|
<div id="navbar" class="navbar-collapse collapse">
|
||||||
<ul class="nav navbar-nav">
|
<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> {% trans "Home" %}</a></li>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<li class="dropdown{% block participatetab %}{% endblock %}">
|
<li{% block exhibitortab %}{% endblock %}><a href="{% url 'participate-as-speaker' %}"><span class="glyphicon glyphicon-bullhorn"></span> {% trans "Exhibitor" %}</a></li>
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-th"></span> {% trans "Participate" %} <span class="caret"></span></a>
|
<li{% block volunteertab %}{% endblock %}><a href="{% url 'enrole-as-volunteer' %}"><span class="glyphicon glyphicon-thumbs-up"></span> {% trans "Volunteer" %}</a></li>
|
||||||
<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> {% 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> {% trans "Enrole as volunteer" %}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if conference.subscriptions_open %}
|
<li{% block wsregtab %}{% endblock %}><a href="{% url 'list-registrable-talks' %}"><span class="glyphicon glyphicon-edit"></span> {% trans "Workshop registration" %}</a></li>
|
||||||
<li{% block subscriptiontab %}{% endblock %}><a href="{% url 'subscriptions-list' %}"><span class="glyphicon glyphicon-check"></span> {% 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 %}
|
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
{% if request|staff %}
|
{% if request|staff %}
|
||||||
<li class="dropdown{% block listingtab %}{% endblock %}">
|
<li{% block stafftab %}{% endblock %}><a href="{% url 'staff' %}"><span class="glyphicon glyphicon-cog"></span> {% trans "Staff" %}</a></li>
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-th-list"></span> {% trans "Listing" %} <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> {% trans "Talks" %}</a>
|
|
||||||
</li>
|
|
||||||
<li role="presentation">
|
|
||||||
<a role="menuitem" tabindex="-1" href="{% url 'list-speakers' %}"><span class="glyphicon glyphicon-user"></span> {% trans "Speakers" %}</a>
|
|
||||||
</li>
|
|
||||||
<li role="presentation">
|
|
||||||
<a role="menuitem" tabindex="-1" href="{% url 'list-volunteers' %}"><span class="glyphicon glyphicon-thumbs-up"></span> {% trans "Volunteers" %}</a>
|
|
||||||
</li>
|
|
||||||
<li role="presentation">
|
|
||||||
<a role="menuitem" tabindex="-1" href="{% url 'list-topics' %}"><span class="glyphicon glyphicon-tag"></span> {% trans "Topics" %}</a></li>
|
|
||||||
</li>
|
|
||||||
<li role="presentation">
|
|
||||||
<a role="menuitem" tabindex="-1" href="{% url 'list-tracks' %}"><span class="glyphicon glyphicon-screenshot"></span> {% trans "Tracks" %}</a></li>
|
|
||||||
</li>
|
|
||||||
<li role="presentation">
|
|
||||||
<a role="menuitem" tabindex="-1" href="{% url 'list-rooms' %}"><span class="glyphicon glyphicon-tent"></span> {% trans "Rooms" %}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li{% block planningtab %}{% endblock %}><a href="{% url 'pending-program' %}"><span class="glyphicon glyphicon-calendar"></span> {% trans "Program" %}</a></li>
|
|
||||||
<li class="dropdown{% block admintab %}{% endblock %}">
|
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-cog"></span> {% trans "Administration" %} <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> Django Admin</a>
|
|
||||||
{% endif %}
|
|
||||||
{% if request|orga %}
|
|
||||||
<a role="menuitem" tabindex="-1" href="{% url 'conference' %}"><span class="glyphicon glyphicon-blackboard"></span> {% trans "Conference" %}</a>
|
|
||||||
{% endif %}
|
|
||||||
<a role="menuitem" tabindex="-1" href="{% url 'list-participant' %}"><span class="glyphicon glyphicon-user"></span> {% trans "Participants" %}</a>
|
|
||||||
<a role="menuitem" tabindex="-1" href="{% url 'correspondents' %}"><span class="glyphicon glyphicon-envelope"></span> {% trans "Correspondence" %}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li{% block inboxtab %}{% endblock %}><a href="{% url 'inbox' %}" data-toggle="tooltip" data-placement="bottom" title="Inbox"><span class="glyphicon glyphicon-envelope"></span> Inbox</a></li>
|
<li{% block inboxtab %}{% endblock %}><a href="{% url 'inbox' %}"><span class="glyphicon glyphicon-envelope"></span> 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> {{ request.user.username }}</a></li>
|
<li{% block profiletab %}{% endblock %}><a href="{% url 'profile' %}"><span class="glyphicon glyphicon-user"></span> {% 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>
|
<li><a href="{% url 'logout' %}" data-toggle="tooltip" data-placement="bottom" title="Logout"><span class="glyphicon glyphicon-log-out"></span></a></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li{% block registrationtab %}{% endblock %}><a href="{% url 'registration_register' %}"><span class="glyphicon glyphicon-edit"></span> {% trans "Register" %}</a></li>
|
<li{% block registrationtab %}{% endblock %}><a href="{% url 'registration_register' %}"><span class="glyphicon glyphicon-edit"></span> {% trans "Register" %}</a></li>
|
||||||
<li{% block logintab %}{% endblock %}><a href="{% url 'login' %}"><span class="glyphicon glyphicon-log-in"></span> {% trans "Login" %}</a></li>
|
<li{% block logintab %}{% endblock %}><a href="{% url 'login' %}"><span class="glyphicon glyphicon-log-in"></span> {% trans "Login" %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
{% block navbar-right %}{% endblock %}
|
</div>
|
||||||
</div><!--/.nav-collapse -->
|
</div>
|
||||||
</div><!--/.container-fluid -->
|
</nav>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block container %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div id="content" class="col-md-12">
|
||||||
|
{% bootstrap_messages %}
|
||||||
|
{% block content %}{% endblock %}
|
||||||
{% block pagefooter %}
|
{% block pagefooter %}
|
||||||
<hr>
|
<hr>
|
||||||
<footer>
|
<footer>
|
||||||
<p class="text-muted">{% trans "Powered by" %} <a href="https://github.com/toulibre/ponyconf">PonyConf</a></p>
|
<p class="text-muted">{% trans "Powered by" %} <a href="https://github.com/toulibre/ponyconf">PonyConf</a></p>
|
||||||
</footer>
|
</footer>
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
21
ponyconf/templates/staff.html
Normal file
21
ponyconf/templates/staff.html
Normal 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> {% trans "Topics" %}</a></li>
|
||||||
|
<li{% block trackstab %}{% endblock %}><a href="{% url 'list-tracks' %}"><span class="glyphicon glyphicon-screenshot"></span> {% trans "Tracks" %}</a></li>
|
||||||
|
<li{% block talkstab %}{% endblock %}><a href="{% url 'list-talks' %}"><span class="glyphicon glyphicon-blackboard"></span> {% trans "Talks" %}</a></li>
|
||||||
|
<li{% block speakerstab %}{% endblock %}><a href="{% url 'list-speakers' %}"><span class="glyphicon glyphicon-bullhorn"></span> {% trans "Speakers" %}</a></li>
|
||||||
|
<li{% block volunteerstab %}{% endblock %}><a href="{% url 'list-volunteers' %}"><span class="glyphicon glyphicon-thumbs-up"></span> {% trans "Volunteers" %}</a></li>
|
||||||
|
<li{% block roomstab %}{% endblock %}><a href="{% url 'list-rooms' %}"><span class="glyphicon glyphicon-tent"></span> {% trans "Rooms" %}</a></li>
|
||||||
|
<li{% block scheduletab %}{% endblock %}><a href="{% url 'show-schedule' %}"><span class="glyphicon glyphicon-calendar"></span> {% trans "Schedule" %}</a></li>
|
||||||
|
<li{% block participantstab %}{% endblock %}><a href="{% url 'list-participants' %}"><span class="glyphicon glyphicon-user"></span> {% trans "Participants" %}</a></li>
|
||||||
|
<li{% block correspondentstab %}{% endblock %}><a href="{% url 'list-correspondents' %}"><span class="glyphicon glyphicon-envelope"></span> {% trans "Correspondents" %}</a></li>
|
||||||
|
<li{% block conferencetab %}{% endblock %}><a href="{% url 'edit-conference' %}"><span class="glyphicon glyphicon-cog"></span> {% trans "Conference" %}</a></li>
|
||||||
|
<li><a href="{% url 'admin:index' %}"><span class="glyphicon glyphicon-dashboard"></span> Django-Admin</a></li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
|
@ -22,8 +22,8 @@ urlpatterns = [
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
url(r'^accounts/', include('accounts.urls')),
|
url(r'^accounts/', include('accounts.urls')),
|
||||||
url(r'', include('proposals.urls')),
|
url(r'', include('proposals.urls')),
|
||||||
url(r'^conversations/', include('conversations.urls')),
|
url(r'', include('planning.urls')),
|
||||||
url(r'^planning/', include('planning.urls')),
|
|
||||||
url(r'^volunteers/', include('volunteers.urls')),
|
url(r'^volunteers/', include('volunteers.urls')),
|
||||||
|
url(r'^conversations/', include('conversations.urls')),
|
||||||
url(r'^select2/', include('django_select2.urls')),
|
url(r'^select2/', include('django_select2.urls')),
|
||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
|
@ -24,10 +24,18 @@ STATUS_VALUES = [
|
||||||
class TalkForm(forms.ModelForm):
|
class TalkForm(forms.ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
site = kwargs.pop('site')
|
site = kwargs.pop('site')
|
||||||
|
staff = kwargs.pop('staff')
|
||||||
super(TalkForm, self).__init__(*args, **kwargs)
|
super(TalkForm, self).__init__(*args, **kwargs)
|
||||||
self.fields['topics'].queryset = Topic.objects.filter(site=site)
|
self.fields['topics'].queryset = Topic.objects.filter(site=site)
|
||||||
self.fields['track'].queryset = Track.objects.filter(site=site)
|
self.fields['track'].queryset = Track.objects.filter(site=site)
|
||||||
self.fields['event'].queryset = Event.objects.filter(site=site)
|
if staff:
|
||||||
|
self.fields['event'].queryset = Event.objects.filter(site=site)
|
||||||
|
else:
|
||||||
|
self.fields['event'].queryset = Conference.objects.get(site=site).opened_events
|
||||||
|
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:
|
class Meta:
|
||||||
model = Talk
|
model = Talk
|
||||||
|
@ -192,9 +200,7 @@ class SubscribeForm(forms.Form):
|
||||||
|
|
||||||
|
|
||||||
ConferenceForm = modelform_factory(Conference,
|
ConferenceForm = modelform_factory(Conference,
|
||||||
fields=['cfp_opening_date', 'cfp_closing_date', 'subscriptions_open', 'venue', 'city', 'home'],
|
fields=['subscriptions_open', 'venue', 'city', 'home'],
|
||||||
widgets={
|
widgets={
|
||||||
'cfp_opening_date': forms.TextInput(),
|
|
||||||
'cfp_closing_date': forms.TextInput(),
|
|
||||||
'venue': forms.Textarea(attrs={'rows': 4}),
|
'venue': forms.Textarea(attrs={'rows': 4}),
|
||||||
})
|
})
|
||||||
|
|
45
proposals/migrations/0028_auto_20161113_2204.py
Normal file
45
proposals/migrations/0028_auto_20161113_2204.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10 on 2016-11-13 22:04
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_opening_closing_dates(apps, schema_editor):
|
||||||
|
db_alias = schema_editor.connection.alias
|
||||||
|
Conference = apps.get_model('proposals', 'Conference')
|
||||||
|
Event = apps.get_model('proposals', 'Event')
|
||||||
|
for conf in Conference.objects.all():
|
||||||
|
for event in Event.objects.filter(site=conf.site).all():
|
||||||
|
event.opening_date = conf.cfp_opening_date
|
||||||
|
event.closing_date = conf.cfp_closing_date
|
||||||
|
event.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('proposals', '0027_conference_subscriptions_open'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='event',
|
||||||
|
name='closing_date',
|
||||||
|
field=models.DateTimeField(blank=True, default=None, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='event',
|
||||||
|
name='opening_date',
|
||||||
|
field=models.DateTimeField(blank=True, default=None, null=True),
|
||||||
|
),
|
||||||
|
migrations.RunPython(migrate_opening_closing_dates),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='conference',
|
||||||
|
name='cfp_closing_date',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='conference',
|
||||||
|
name='cfp_opening_date',
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,6 +6,7 @@ from django.contrib.sites.models import Site
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Q
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.translation import ugettext
|
from django.utils.translation import ugettext
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
@ -26,17 +27,18 @@ class Conference(models.Model):
|
||||||
home = models.TextField(blank=True, default="")
|
home = models.TextField(blank=True, default="")
|
||||||
venue = models.TextField(blank=True, default="")
|
venue = models.TextField(blank=True, default="")
|
||||||
city = models.CharField(max_length=64, blank=True, default="")
|
city = models.CharField(max_length=64, blank=True, default="")
|
||||||
cfp_opening_date = models.DateTimeField(null=True, blank=True, default=None)
|
subscriptions_open = models.BooleanField(default=False) # workshop subscription
|
||||||
cfp_closing_date = models.DateTimeField(null=True, blank=True, default=None)
|
|
||||||
subscriptions_open = models.BooleanField(default=False)
|
|
||||||
|
|
||||||
def cfp_is_open(self):
|
def cfp_is_open(self):
|
||||||
|
events = Event.objects.filter(site=self.site)
|
||||||
|
return any(map(lambda x: x.is_open(), events))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def opened_events(self):
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
if self.cfp_opening_date and now < self.cfp_opening_date:
|
return Event.objects.filter(site=self.site)\
|
||||||
return False
|
.filter(Q(opening_date__isnull=True) | Q(opening_date__lte=now))\
|
||||||
if self.cfp_closing_date and now > self.cfp_closing_date:
|
.filter(Q(closing_date__isnull=True) | Q(closing_date__gte=now))
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.site)
|
return str(self.site)
|
||||||
|
@ -93,6 +95,16 @@ class Event(models.Model):
|
||||||
duration = models.PositiveIntegerField(default=0, verbose_name=_('Default duration (min)'))
|
duration = models.PositiveIntegerField(default=0, verbose_name=_('Default duration (min)'))
|
||||||
color = RGBColorField(default='#ffffff', verbose_name=_("Color on program"))
|
color = RGBColorField(default='#ffffff', verbose_name=_("Color on program"))
|
||||||
label = models.CharField(max_length=64, verbose_name=_("Label on program"), blank=True, default="")
|
label = models.CharField(max_length=64, verbose_name=_("Label on program"), blank=True, default="")
|
||||||
|
opening_date = models.DateTimeField(null=True, blank=True, default=None)
|
||||||
|
closing_date = models.DateTimeField(null=True, blank=True, default=None)
|
||||||
|
|
||||||
|
def is_open(self):
|
||||||
|
now = timezone.now()
|
||||||
|
if self.opening_date and now < self.opening_date:
|
||||||
|
return False
|
||||||
|
if self.closing_date and now > self.closing_date:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('site', 'name')
|
unique_together = ('site', 'name')
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
{{ talk.get_link }}
|
{{ talk.get_link }}
|
||||||
<i>{% trans "by" %}</i>
|
<i>{% trans "by" %}</i>
|
||||||
{% for speaker in talk.speakers.all %}
|
{% 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 %}
|
{% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if talk.topics.exists %}
|
{% if talk.topics.exists %}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 staticfiles i18n %}
|
{% load bootstrap3 staticfiles i18n %}
|
||||||
|
|
||||||
{% block admintab %} class=active{% endblock %}
|
{% block conferencetab %} class=active{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
@ -13,9 +13,7 @@
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<form method="post" role="form">
|
<form method="post" role="form">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% bootstrap_field form.cfp_opening_date addon_after='<span class="glyphicon glyphicon-calendar"></span>' %}
|
{% bootstrap_form form exclude='home' %}
|
||||||
{% bootstrap_field form.cfp_closing_date addon_after='<span class="glyphicon glyphicon-calendar"></span>' %}
|
|
||||||
{% bootstrap_form form exclude='cfp_opening_date,cfp_closing_date,home' %}
|
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li class="active"><a href="#editor" role="tab" data-toggle="tab">Editor</a></li>
|
<li class="active"><a href="#editor" role="tab" data-toggle="tab">Editor</a></li>
|
||||||
<li><a href="#preview" role="tab" data-toggle="tab">Preview</a></li>
|
<li><a href="#preview" role="tab" data-toggle="tab">Preview</a></li>
|
||||||
|
@ -43,7 +41,6 @@
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
{{ form.media.css }}
|
{{ form.media.css }}
|
||||||
<link rel="stylesheet" href="{% static 'eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css' %}" />
|
|
||||||
{% endblock css %}
|
{% endblock css %}
|
||||||
|
|
||||||
{% block js_end %}
|
{% block js_end %}
|
||||||
|
@ -52,28 +49,5 @@
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var markdown_preview_url = "{% url 'markdown' %}";
|
var markdown_preview_url = "{% url 'markdown' %}";
|
||||||
</script>
|
</script>
|
||||||
<script src="{% static 'moment/min/moment.min.js' %}"></script>
|
|
||||||
<script src="{% static 'eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js' %}"></script>
|
|
||||||
<script src="{% static 'jquery.cookie/jquery.cookie.js' %}"></script>
|
|
||||||
<script src="{% static 'js/markdown-preview.js' %}"></script>
|
<script src="{% static 'js/markdown-preview.js' %}"></script>
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
$("#id_cfp_opening_date").datetimepicker({
|
|
||||||
"format": "YYYY-MM-DD HH:mm",
|
|
||||||
"widgetPositioning": {
|
|
||||||
"horizontal": "right",
|
|
||||||
"vertical": "auto"
|
|
||||||
},
|
|
||||||
"showClear": true
|
|
||||||
});
|
|
||||||
$("#id_cfp_closing_date").datetimepicker({
|
|
||||||
"format": "YYYY-MM-DD HH:mm",
|
|
||||||
"widgetPositioning": {
|
|
||||||
"horizontal": "right",
|
|
||||||
"vertical": "auto"
|
|
||||||
},
|
|
||||||
"showClear": true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock js_end %}
|
{% endblock js_end %}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
{% load accounts_tags i18n %}
|
{% load accounts_tags i18n %}
|
||||||
|
|
||||||
{% block participatetab %} class="active"{% endblock %}
|
{% block exhibitortab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
@ -19,8 +19,15 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
{% if conf.cfp_is_open or request|orga %}
|
{% if conference.cfp_is_open %}
|
||||||
<a class="btn btn-{% if conf.cfp_is_open %}success{% else %}danger{% endif %}" href="{% url 'add-talk' %}">{% trans "Propose a talk" %}</a>
|
{% trans "The Call for Participation is currently open for following categories:" %}
|
||||||
|
{% for event in conference.opened_events.all %}
|
||||||
|
{% if forloop.first %}<ul>{% endif %}
|
||||||
|
<li>{{ event }}{% if event.closing_date %} ({% blocktrans with closing_date=event.closing_date|date:"DATETIME_FORMAT" %}until {{ closing_date }}{% endblocktrans %}){% endif %}</li>
|
||||||
|
{% if forloop.last %}</ul>{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<br />
|
||||||
|
<a class="btn btn-{% if conference.cfp_is_open %}success{% else %}danger{% endif %}" href="{% url 'add-talk' %}">{% trans "Propose a talk" %}</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% trans "Sorry, the Call for Participation is closed." %}
|
{% trans "Sorry, the Call for Participation is closed." %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 i18n %}
|
{% load bootstrap3 i18n %}
|
||||||
|
|
||||||
{% block listingtab %} active{% endblock %}
|
{% block speakerstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
@ -56,15 +56,15 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="7">{% trans "Contact:" %}<a href="{{ contact_link }}">lien</a></td>
|
<td colspan="7">{% trans "Contact:" %} <a href="{{ contact_link }}">{% trans "link" %}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
{% for speaker in speaker_list %}
|
{% for speaker in speaker_list %}
|
||||||
{% if forloop.first %}
|
{% if forloop.first %}
|
||||||
<tbody>
|
<tbody>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<tr class="clickable-row" data-href="{% url 'show-speaker' username=speaker.user.username %}">
|
<tr>
|
||||||
<td>{{ speaker.user.username }}</td>
|
<td><a href="{% url 'show-participant' username=speaker.user.username %}">{{ speaker.user.username }}</a></td>
|
||||||
<td>{{ speaker.user.get_full_name }}</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>
|
<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 %}
|
{% if speaker.need_transport %}
|
||||||
|
@ -94,10 +94,9 @@
|
||||||
<td>No</td>
|
<td>No</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td>
|
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</li>
|
|
||||||
{% if forloop.last %}
|
{% if forloop.last %}
|
||||||
</tbody>
|
</tbody>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -109,10 +108,6 @@
|
||||||
{% block js_end %}
|
{% block js_end %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
jQuery(document).ready(function($) {
|
jQuery(document).ready(function($) {
|
||||||
$(".clickable-row").click(function() {
|
|
||||||
window.location = $(this).data("href");
|
|
||||||
});
|
|
||||||
|
|
||||||
var anchor = window.location.hash.replace("#", "");
|
var anchor = window.location.hash.replace("#", "");
|
||||||
if (anchor == "filter") {
|
if (anchor == "filter") {
|
||||||
$("#filter").collapse('show');
|
$("#filter").collapse('show');
|
||||||
|
|
|
@ -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 %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block listingtab %} active{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h1>{{ talk.title }}</h1>
|
<h1>{{ talk.title }}</h1>
|
||||||
|
@ -65,7 +69,7 @@
|
||||||
|
|
||||||
{% for speaker in talk.speakers.all %}
|
{% for speaker in talk.speakers.all %}
|
||||||
{% if forloop.first %}<ul>{% endif %}
|
{% 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 %}
|
{% if forloop.last %}</ul>{% endif %}
|
||||||
{% empty %}
|
{% empty %}
|
||||||
<i>{% trans "No speakers." %}</i>
|
<i>{% trans "No speakers." %}</i>
|
||||||
|
|
|
@ -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 %}
|
{% 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" %}
|
{% include "_form.html" %}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 i18n accounts_tags %}
|
{% load bootstrap3 i18n accounts_tags %}
|
||||||
|
|
||||||
{% block listingtab %} active{% endblock %}
|
{% block talkstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
<td>{{ talk.event }}</td>
|
<td>{{ talk.event }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% for speaker in talk.speakers.all %}
|
{% 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 %}
|
{% if forloop.revcounter == 2 %} {% trans "and" %} {% elif not forloop.last %}, {% endif %}
|
||||||
{% empty %}–
|
{% empty %}–
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
{% load bootstrap3 i18n %}
|
{% load bootstrap3 i18n %}
|
||||||
|
|
||||||
{% block subscriptiontab %} class="active"{% endblock %}
|
{% block wsregtab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
@ -11,12 +11,14 @@
|
||||||
|
|
||||||
{% block content %}
|
{% 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" %}
|
{% include "_form.html" %}
|
||||||
|
|
||||||
<p class="text-center">
|
<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>
|
</p>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
{% load accounts_tags i18n %}
|
{% load accounts_tags i18n %}
|
||||||
|
|
||||||
{% block subscriptiontab %} class="active"{% endblock %}
|
{% block wsregtab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h1>{% trans "Subscribe to a workshop" %}</h1>
|
<h1>{% trans "Register to a workshop" %}</h1>
|
||||||
|
|
||||||
{% for talk in talks %}
|
{% for talk in talks %}
|
||||||
{% if forloop.first %}<div class="list-group">{% endif %}
|
{% if forloop.first %}<div class="list-group">{% endif %}
|
||||||
|
@ -20,9 +20,9 @@
|
||||||
{% if talk.remaining_attendees != 0 or attendee in talk.attendees.all %}
|
{% if talk.remaining_attendees != 0 or attendee in talk.attendees.all %}
|
||||||
<p>
|
<p>
|
||||||
{% if attendee in talk.attendees.all %}
|
{% 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 %}
|
{% 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 %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 i18n %}
|
{% load bootstrap3 i18n %}
|
||||||
|
|
||||||
{% block topictab %} class="active"{% endblock %}
|
{% block topicstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 accounts_tags i18n %}
|
{% load bootstrap3 accounts_tags i18n %}
|
||||||
|
|
||||||
{% block topictab %} class="active"{% endblock %}
|
{% block topicstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 i18n %}
|
{% load bootstrap3 i18n %}
|
||||||
|
|
||||||
{% block tracktab %} class="active"{% endblock %}
|
{% block trackstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 accounts_tags proposals_tags i18n %}
|
{% load bootstrap3 accounts_tags proposals_tags i18n %}
|
||||||
|
|
||||||
{% block tracktab %} class="active"{% endblock %}
|
{% block trackstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ class ProposalsTests(TestCase):
|
||||||
self.assertEqual(self.client.get(reverse('list-speakers')).status_code, 403)
|
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('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-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.client.login(username='b', password='b')
|
||||||
self.assertEqual(self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),
|
self.assertEqual(self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),
|
||||||
|
|
|
@ -5,7 +5,8 @@ from proposals import views
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^markdown/$', views.markdown_preview, name='markdown'),
|
url(r'^markdown/$', views.markdown_preview, name='markdown'),
|
||||||
url(r'^$', views.home, name='home'),
|
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/propose/$', views.participate, name='participate-as-speaker'),
|
||||||
url(r'^talk/$', views.talk_list, name='list-talks'),
|
url(r'^talk/$', views.talk_list, name='list-talks'),
|
||||||
url(r'^talk/add/$', views.talk_edit, name='add-talk'),
|
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/add/$', views.TrackCreate.as_view(), name='add-track'),
|
||||||
url(r'^track/(?P<slug>[-\w]+)/edit/$', views.TrackUpdate.as_view(), name='edit-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'^speakers/$', views.speaker_list, name='list-speakers'),
|
||||||
url(r'^speaker/(?P<username>[\w.@+-]+)$', views.user_details, name='show-speaker'),
|
url(r'^register/$', views.talk_registrable_list, name='list-registrable-talks'),
|
||||||
url(r'^subscribe/$', views.talk_subscriptions, name='subscriptions-list'),
|
url(r'^register/(?P<talk>[-\w]+)$', views.talk_register, name='register-for-a-talk'),
|
||||||
url(r'^subscribe/(?P<talk>[-\w]+)$', views.talk_subscribe, name='subscribe-to-talk'),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -29,7 +29,7 @@ from planning.models import Room
|
||||||
from .forms import TalkForm, TopicForm, TrackForm, ConferenceForm, TalkFilterForm, STATUS_VALUES, SpeakerFilterForm, TalkActionForm, SubscribeForm
|
from .forms import TalkForm, TopicForm, TrackForm, ConferenceForm, TalkFilterForm, STATUS_VALUES, SpeakerFilterForm, TalkActionForm, SubscribeForm
|
||||||
from .models import Talk, Track, Topic, Vote, Conference, Attendee
|
from .models import Talk, Track, Topic, Vote, Conference, Attendee
|
||||||
from .signals import talk_added, talk_edited
|
from .signals import talk_added, talk_edited
|
||||||
from .utils import allowed_talks, markdown_to_html
|
from .utils import markdown_to_html
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -43,6 +43,11 @@ def home(request):
|
||||||
return render(request, 'proposals/home.html')
|
return render(request, 'proposals/home.html')
|
||||||
|
|
||||||
|
|
||||||
|
@staff_required
|
||||||
|
def staff(request):
|
||||||
|
return render(request, 'staff.html')
|
||||||
|
|
||||||
|
|
||||||
@orga_required
|
@orga_required
|
||||||
def conference(request):
|
def conference(request):
|
||||||
conference = Conference.objects.get(site=get_current_site(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():
|
if request.method == 'POST' and form.is_valid():
|
||||||
form.save()
|
form.save()
|
||||||
messages.success(request, 'Conference updated!')
|
messages.success(request, 'Conference updated!')
|
||||||
return redirect(reverse('conference'))
|
return redirect(reverse('edit-conference'))
|
||||||
return render(request, 'proposals/conference.html', {
|
return render(request, 'proposals/conference.html', {
|
||||||
'form': form,
|
'form': form,
|
||||||
})
|
})
|
||||||
|
@ -185,34 +190,19 @@ def talk_edit(request, talk=None):
|
||||||
conf = Conference.objects.get(site=site)
|
conf = Conference.objects.get(site=site)
|
||||||
if not is_orga(request, request.user) and not conf.cfp_is_open():
|
if not is_orga(request, request.user) and not conf.cfp_is_open():
|
||||||
raise PermissionDenied
|
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:
|
if talk:
|
||||||
form.fields['topics'].disabled = True
|
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
|
form.fields['duration'].help_text = 'Default value if zero: %d min' % talk.duration
|
||||||
if not talk.is_editable_by(request.user):
|
if 'attendees_limit' in form.fields and talk.is_editable_by(request.user) and talk.room and talk.room.capacity:
|
||||||
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:
|
|
||||||
form.fields['attendees_limit'].help_text=ungettext_lazy(
|
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 seat.",
|
||||||
"Note: the room %(room)s has %(capacity)s seats.",
|
"Note: the room %(room)s has %(capacity)s seats.",
|
||||||
talk.room.capacity) % {'room': talk.room.name, 'capacity': talk.room.capacity}
|
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:
|
else:
|
||||||
form.fields['speakers'].initial = [request.user]
|
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 request.method == 'POST' and form.is_valid():
|
||||||
if hasattr(talk, 'id'):
|
if hasattr(talk, 'id'):
|
||||||
talk = form.save()
|
talk = form.save()
|
||||||
|
@ -227,6 +217,8 @@ def talk_edit(request, talk=None):
|
||||||
messages.success(request, _('Talk proposed successfully!'))
|
messages.success(request, _('Talk proposed successfully!'))
|
||||||
return redirect(talk.get_absolute_url())
|
return redirect(talk.get_absolute_url())
|
||||||
return render(request, 'proposals/talk_edit.html', {
|
return render(request, 'proposals/talk_edit.html', {
|
||||||
|
'base_template': 'staff.html' if staff else 'base.html',
|
||||||
|
'talk': talk,
|
||||||
'form': form,
|
'form': form,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -255,6 +247,10 @@ class TalkDetail(LoginRequiredMixin, DetailView):
|
||||||
form_url=reverse('talk-conversation', kwargs={'talk': self.object.slug}))
|
form_url=reverse('talk-conversation', kwargs={'talk': self.object.slug}))
|
||||||
else:
|
else:
|
||||||
ctx['edit_perm'] = self.object.is_editable_by(self.request.user)
|
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)
|
return super().get_context_data(**ctx)
|
||||||
|
|
||||||
|
|
||||||
|
@ -404,18 +400,7 @@ def speaker_list(request):
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
def talk_registrable_list(request):
|
||||||
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):
|
|
||||||
site = get_current_site(request)
|
site = get_current_site(request)
|
||||||
if not Conference.objects.get(site=site).subscriptions_open:
|
if not Conference.objects.get(site=site).subscriptions_open:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
@ -424,13 +409,13 @@ def talk_subscriptions(request):
|
||||||
attendee = Attendee.objects.filter(user=request.user).first() # None if it does not exists
|
attendee = Attendee.objects.filter(user=request.user).first() # None if it does not exists
|
||||||
else:
|
else:
|
||||||
attendee = None
|
attendee = None
|
||||||
return render(request, 'proposals/subscriptions_list.html', {
|
return render(request, 'proposals/talk_registrable_list.html', {
|
||||||
'talks': talks,
|
'talks': talks,
|
||||||
'attendee': attendee,
|
'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)
|
talk = get_object_or_404(Talk, site=get_current_site(request), registration_required=True, slug=talk)
|
||||||
|
|
||||||
form = SubscribeForm(request.POST or None)
|
form = SubscribeForm(request.POST or None)
|
||||||
|
@ -452,9 +437,9 @@ def talk_subscribe(request, talk):
|
||||||
talk.attendees.add(attendee)
|
talk.attendees.add(attendee)
|
||||||
messages.success(request, _("Registered!"))
|
messages.success(request, _("Registered!"))
|
||||||
talk.save()
|
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,
|
'talk': talk,
|
||||||
'form': form,
|
'form': form,
|
||||||
})
|
})
|
||||||
|
|
19
volunteers/migrations/0004_auto_20161113_1908.py
Normal file
19
volunteers/migrations/0004_auto_20161113_1908.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10 on 2016-11-13 19:08
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('volunteers', '0003_auto_20161024_1313'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='activity',
|
||||||
|
options={'verbose_name': 'Activity', 'verbose_name_plural': 'Activities'},
|
||||||
|
),
|
||||||
|
]
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
{% load accounts_tags i18n %}
|
{% load accounts_tags i18n %}
|
||||||
|
|
||||||
{% block participatetab %} class="active"{% endblock %}
|
{% block volunteertab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@
|
||||||
<p>{{ activity.description }}</p>
|
<p>{{ activity.description }}</p>
|
||||||
<p>
|
<p>
|
||||||
{% if request.user in activity.participants.all %}
|
{% 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 %}
|
{% 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 %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
</p>
|
</p>
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'staff.html' %}
|
||||||
|
|
||||||
{% load bootstrap3 i18n %}
|
{% load bootstrap3 i18n %}
|
||||||
|
|
||||||
{% block listingtab %} active{% endblock %}
|
{% block volunteerstab %} class="active"{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@
|
||||||
{% if forloop.first %}
|
{% if forloop.first %}
|
||||||
<tbody>
|
<tbody>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<tr class="clickable-row" data-href="{% url 'show-speaker' username=volunteer.user.username %}">
|
<tr>
|
||||||
<td>{{ volunteer.user.username }}</td>
|
<td><a href="{% url 'show-participant' username=volunteer.user.username %}">{{ volunteer.user.username }}</a></td>
|
||||||
<td>{{ volunteer.user.get_full_name }}</td>
|
<td>{{ volunteer.user.get_full_name }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% for activity in volunteer.user.activities.all %}
|
{% for activity in volunteer.user.activities.all %}
|
||||||
|
@ -45,10 +45,9 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</li>
|
|
||||||
{% if forloop.last %}
|
{% if forloop.last %}
|
||||||
</tbody>
|
</tbody>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -4,10 +4,10 @@ from . import views
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
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'^list/$', views.volunteer_list, name='list-volunteers'),
|
||||||
url(r'^activities/$', views.ActivityList.as_view(), name='list-activities'),
|
url(r'^activities/$', views.ActivityList.as_view(), name='list-activities'),
|
||||||
url(r'^activities/add/$', views.ActivityCreate.as_view(), name='add-activity'),
|
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]+)/edit/$', views.ActivityUpdate.as_view(), name='edit-activity'),
|
||||||
url(r'^activities/(?P<slug>[-\w]+)/enrole/$', views.participate, name='enrole-in-activity'),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -15,7 +15,7 @@ from .forms import ActivityForm, VolunteerFilterForm
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def participate(request, slug=None):
|
def enrole(request, slug=None):
|
||||||
if slug:
|
if slug:
|
||||||
# TODO: enrole action should be done on post (with bootstrap modal confirmation box?)
|
# 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)
|
activity = get_object_or_404(Activity, site=get_current_site(request), slug=slug)
|
||||||
|
@ -24,13 +24,32 @@ def participate(request, slug=None):
|
||||||
else:
|
else:
|
||||||
activity.participants.add(request.user)
|
activity.participants.add(request.user)
|
||||||
activity.save()
|
activity.save()
|
||||||
return redirect('participate-as-volunteer')
|
return redirect('enrole-as-volunteer')
|
||||||
activities = Activity.objects.filter(site=get_current_site(request))
|
activities = Activity.objects.filter(site=get_current_site(request))
|
||||||
return render(request, 'volunteers/participate.html', {
|
return render(request, 'volunteers/volunteer_enrole.html', {
|
||||||
'activities': activities,
|
'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):
|
class ActivityMixin(object):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Activity.objects.filter(site=get_current_site(self.request)).all()
|
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):
|
class ActivityDetail(StaffRequiredMixin, ActivityMixin, DetailView):
|
||||||
pass
|
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,
|
|
||||||
})
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user