workshop attendee: subscription
This commit is contained in:
parent
71103d5f6b
commit
483a794d23
|
@ -29,9 +29,13 @@
|
|||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if conference.subscriptions_open %}
|
||||
<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>
|
||||
{% if request|staff %}
|
||||
<li{% block tracktab %}{% endblock %}><a href="{% url 'list-tracks' %}">{% trans "Tracks" %}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% block navbar-left %}{% endblock %}
|
||||
|
@ -51,6 +55,12 @@
|
|||
<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>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown{% block planningtab %}{% endblock %}">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.contrib import admin
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
|
||||
from proposals.models import Conference, Talk, Topic, Track, Event
|
||||
from proposals.models import Conference, Talk, Topic, Track, Event, Attendee
|
||||
from planning.models import Room
|
||||
|
||||
from ponyconf.admin import SiteAdminMixin
|
||||
|
@ -35,8 +35,13 @@ class EventAdmin(SiteAdminMixin, admin.ModelAdmin):
|
|||
pass
|
||||
|
||||
|
||||
class AttendeeAdmin(admin.ModelAdmin):
|
||||
list_display = ('get_name', 'get_email')
|
||||
|
||||
|
||||
admin.site.register(Conference)
|
||||
admin.site.register(Topic, TopicAdmin)
|
||||
admin.site.register(Track, TrackAdmin)
|
||||
admin.site.register(Talk, TalkAdmin)
|
||||
admin.site.register(Event, EventAdmin)
|
||||
admin.site.register(Attendee, AttendeeAdmin)
|
||||
|
|
|
@ -179,6 +179,18 @@ class TrackForm(forms.ModelForm):
|
|||
return name
|
||||
|
||||
|
||||
class SubscribeForm(forms.Form):
|
||||
email = forms.EmailField()
|
||||
name = forms.CharField(max_length=128, label=_('Name or nickname'))
|
||||
captcha = forms.IntegerField(label=_('How much is 3+4?'), help_text=_('Anti-bot'))
|
||||
|
||||
def clean_captcha(self):
|
||||
value = self.cleaned_data['captcha']
|
||||
if value != 7:
|
||||
raise forms.ValidationError(_("Please re-do the maths."))
|
||||
return value
|
||||
|
||||
|
||||
ConferenceForm = modelform_factory(Conference,
|
||||
fields=['cfp_opening_date', 'cfp_closing_date', 'subscriptions_open', 'venue', 'city', 'home'],
|
||||
widgets={
|
||||
|
|
|
@ -112,16 +112,21 @@ class Attendee(PonyConfModel):
|
|||
email = models.EmailField(blank=True, default="")
|
||||
|
||||
def get_name(self):
|
||||
if user:
|
||||
return str(user.profile)
|
||||
if self.user:
|
||||
return str(self.user.profile)
|
||||
else:
|
||||
return name
|
||||
return self.name
|
||||
get_name.short_description = _('Name')
|
||||
|
||||
def get_email(self):
|
||||
if user:
|
||||
return user.email
|
||||
if self.user:
|
||||
return self.user.email
|
||||
else:
|
||||
return self.email
|
||||
get_email.short_description = _('Email')
|
||||
|
||||
def __str__(self):
|
||||
return self.get_name()
|
||||
|
||||
|
||||
class Talk(PonyConfModel):
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load accounts_tags i18n %}
|
||||
|
||||
{% block subscriptiontab %} class="active"{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{% trans "Subscribe to a workshop" %}</h1>
|
||||
|
||||
{% for talk in talks %}
|
||||
{% if forloop.first %}<div class="list-group">{% endif %}
|
||||
<div class="list-group-item{% if attendee in talk.attendees.all %} list-group-item-info{% endif %}">
|
||||
<h4 clas="list-group-item-heading">{{ talk.title }}</h4>
|
||||
<p class="list-group-item-text">
|
||||
<p>{{ talk.description }}</p>
|
||||
{% if talk.attendees_limit %}
|
||||
<p><em>{% blocktrans count remaining=talk.remaining_attendees %}{{ remaining }} remaining seat{% plural %}{{ remaining }} remaining seats{% endblocktrans %}</em></p>
|
||||
{% endif %}
|
||||
{% if talk.remaining_attendees != 0 or attendee in talk.attendees.all %}
|
||||
<p>
|
||||
{% if attendee in talk.attendees.all %}
|
||||
<a class="btn btn-danger" href="{% url 'subscribe-to-talk' talk=talk.slug %}">{% trans "Unregister" %}</a>
|
||||
{% else %}
|
||||
<a class="btn btn-primary" href="{% url 'subscribe-to-talk' talk=talk.slug %}">{% trans "Register" %}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
{% if forloop.last %}</div>{% endif %}
|
||||
{% empty %}
|
||||
<em>{% trans "There are no workshops requiring registration for now … come back later!" %}</em>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
|
@ -48,6 +48,10 @@
|
|||
{% else %}<em>{% trans "not defined" %}</em>
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% if talk.registration_required %}
|
||||
<dt>{% trans "Registrations" %}</dt>
|
||||
<dd>{% if talk.attendees_limit %}{{ talk.attendees.count }} / {{ talk.attendees_limit }}{% else %}{% trans "required but unlimited" %}{% endif %}</dd>
|
||||
{% endif %}
|
||||
|
||||
</dl>
|
||||
|
||||
|
@ -111,6 +115,19 @@
|
|||
<a href="{% url 'decline-talk' talk.slug %}" class="btn btn-danger">Decline</a>
|
||||
{% endif %}
|
||||
|
||||
{% if talk.registration_required %}
|
||||
<h3>{% trans "Attendees" %}</h3>
|
||||
|
||||
{% for attendee in talk.attendees.all %}
|
||||
{% if forloop.first %}<ol>{% endif %}
|
||||
<li><a href="mailto:{{ attendee.get_email }}">{{ attendee.get_name }}</a></li>
|
||||
{% if forloop.last %}</ol>{% endif %}
|
||||
{% empty %}
|
||||
<em>{% trans "No attendees yet." %}</em>
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
<h3>{% trans "Messages" %}</h3>
|
||||
{% trans "These messages are for organization team only." %}<br /><br />
|
||||
{% for message in talk.conversation.messages.all %}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load bootstrap3 i18n %}
|
||||
|
||||
{% block subscriptiontab %} class="active"{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ block.super }}
|
||||
{{ form.media.css }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{% trans "Subscribe to a workshop" %}</h1>
|
||||
|
||||
{% include "_form.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js_end %}
|
||||
{{ block.super }}
|
||||
{{ form.media.js }}
|
||||
{% endblock %}
|
|
@ -23,4 +23,6 @@ urlpatterns = [
|
|||
url(r'^track/(?P<slug>[-\w]+)/edit/$', views.TrackUpdate.as_view(), name='edit-track'),
|
||||
url(r'^speakers/$', views.speaker_list, name='list-speakers'),
|
||||
url(r'^speaker/(?P<username>[\w.@+-]+)$', views.user_details, name='show-speaker'),
|
||||
url(r'^subscribe/$', views.talk_subscriptions, name='subscriptions-list'),
|
||||
url(r'^subscribe/(?P<talk>[-\w]+)$', views.talk_subscribe, name='subscribe-to-talk'),
|
||||
]
|
||||
|
|
|
@ -12,7 +12,7 @@ from django.shortcuts import get_object_or_404, redirect, render
|
|||
from django.views.generic import CreateView, DetailView, ListView, UpdateView
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.http import HttpResponse
|
||||
from django.http import HttpResponse, Http404
|
||||
|
||||
from ponyconf.mixins import OnSiteFormMixin
|
||||
|
||||
|
@ -25,8 +25,8 @@ from conversations.models import ConversationWithParticipant, ConversationAboutT
|
|||
|
||||
from planning.models import Room
|
||||
|
||||
from .forms import TalkForm, TopicForm, TrackForm, ConferenceForm, TalkFilterForm, STATUS_VALUES, SpeakerFilterForm, TalkActionForm
|
||||
from .models import Talk, Track, Topic, Vote, Conference
|
||||
from .forms import TalkForm, TopicForm, TrackForm, ConferenceForm, TalkFilterForm, STATUS_VALUES, SpeakerFilterForm, TalkActionForm, SubscribeForm
|
||||
from .models import Talk, Track, Topic, Vote, Conference, Attendee
|
||||
from .signals import talk_added, talk_edited
|
||||
from .utils import allowed_talks, markdown_to_html
|
||||
|
||||
|
@ -179,11 +179,11 @@ def talk_edit(request, talk=None):
|
|||
if talk: # edit existing talk
|
||||
talk = get_object_or_404(Talk, slug=talk, site=site)
|
||||
if not talk.is_editable_by(request.user):
|
||||
raise PermissionDenied()
|
||||
raise PermissionDenied
|
||||
else: # add new talk
|
||||
conf = Conference.objects.get(site=site)
|
||||
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)
|
||||
if talk:
|
||||
form.fields['topics'].disabled = True
|
||||
|
@ -225,7 +225,7 @@ def talk_edit(request, talk=None):
|
|||
def talk_assign_to_track(request, talk, track):
|
||||
talk = get_object_or_404(Talk, slug=talk, site=get_current_site(request))
|
||||
if not talk.is_moderable_by(request.user):
|
||||
raise PermissionDenied()
|
||||
raise PermissionDenied
|
||||
track = get_object_or_404(Track, slug=track, site=get_current_site(request))
|
||||
talk.track = track
|
||||
talk.save()
|
||||
|
@ -294,7 +294,7 @@ class TrackUpdate(OrgaRequiredMixin, TrackMixin, TrackFormMixin, UpdateView):
|
|||
def vote(request, talk, score):
|
||||
talk = get_object_or_404(Talk, site=get_current_site(request), slug=talk)
|
||||
if not talk.is_moderable_by(request.user):
|
||||
raise PermissionDenied()
|
||||
raise PermissionDenied
|
||||
vote, created = Vote.objects.get_or_create(talk=talk, user=request.user)
|
||||
vote.vote = int(score)
|
||||
vote.save()
|
||||
|
@ -307,7 +307,7 @@ def talk_decide(request, talk, accepted):
|
|||
site = get_current_site(request)
|
||||
talk = get_object_or_404(Talk, site=site, slug=talk)
|
||||
if not talk.is_moderable_by(request.user):
|
||||
raise PermissionDenied()
|
||||
raise PermissionDenied
|
||||
if request.method == 'POST':
|
||||
# Does we need to send a notification to the proposer?
|
||||
m = request.POST.get('message', '').strip()
|
||||
|
@ -401,3 +401,48 @@ def user_details(request, username):
|
|||
'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)
|
||||
if not Conference.objects.get(site=site).subscriptions_open:
|
||||
raise Http404
|
||||
talks = Talk.objects.filter(site=site, registration_required=True)
|
||||
if request.user.is_authenticated():
|
||||
attendee = Attendee.objects.filter(user=request.user).first() # None if it does not exists
|
||||
else:
|
||||
attendee = None
|
||||
return render(request, 'proposals/subscriptions_list.html', {
|
||||
'talks': talks,
|
||||
'attendee': attendee,
|
||||
})
|
||||
|
||||
|
||||
def talk_subscribe(request, talk):
|
||||
talk = get_object_or_404(Talk, site=get_current_site(request), registration_required=True, slug=talk)
|
||||
|
||||
form = SubscribeForm(request.POST or None)
|
||||
|
||||
if request.user.is_authenticated() or (request.method == 'POST' and form.is_valid()):
|
||||
if request.user.is_authenticated():
|
||||
attendee, created = Attendee.objects.get_or_create(user=request.user)
|
||||
else:
|
||||
attendee, created = Attendee.objects.get_or_create(email=form.cleaned_data['email'], name=form.cleaned_data['name'])
|
||||
if attendee in talk.attendees.all():
|
||||
if request.user.is_authenticated():
|
||||
talk.attendees.remove(attendee)
|
||||
messages.success(request, _("Unregistered :-("))
|
||||
else:
|
||||
messages.error(request, _("Already registered!"))
|
||||
elif talk.remaining_attendees == 0:
|
||||
raise PermissionDenied
|
||||
else:
|
||||
talk.attendees.add(attendee)
|
||||
messages.success(request, _("Registered!"))
|
||||
talk.save()
|
||||
return redirect('subscriptions-list')
|
||||
|
||||
return render(request, 'proposals/talk_subscribe.html', {
|
||||
'talk': talk,
|
||||
'form': form,
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue