MIGRATION! ADD: first things for a event registration mangement page.

This commit is contained in:
2019-05-29 16:50:02 +02:00
parent a189f5dbe6
commit bee1623529
12 changed files with 382 additions and 7 deletions

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-05-29 08:31
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dav_events', '0028_auto_20190401_1310'),
]
operations = [
migrations.AddField(
model_name='event',
name='registration_closed',
field=models.BooleanField(default=False, verbose_name='Anmeldung geschlossen'),
),
]

View File

@@ -228,6 +228,9 @@ class Event(models.Model):
internal_note = models.TextField(blank=True,
verbose_name=_('Bearbeitungshinweis'))
registration_closed = models.BooleanField(default=False,
verbose_name=_('Anmeldung geschlossen'))
@property
def workflow(self):
return DefaultWorkflow(self)

View File

@@ -165,6 +165,10 @@
<a class="btn {% if has_permission_update %}btn-warning{% else %}disabled{% endif %}"
href="{% url 'dav_events:update' event.pk %}">{% trans 'Ändern' %}</a>
</li>
<li class="{% if not event.registration_required %}disabled{% endif %}">
<a class="btn {% if not event.registration_required %}disabled{% elif is_published_any %}btn-warning{% endif %}"
href="{% url 'dav_events:registrations' event.pk %}">{% trans 'Anmeldungen' %}</a>
</li>
</ul>
</div>

View File

@@ -0,0 +1,263 @@
{% extends 'dav_events/base.html' %}
{% load bootstrap3 %}
{% load i18n %}
{% load dav_events %}
{% block head-title %}{% trans 'Anmeldungen' %} - {{ event }} - {{ block.super }}{% endblock head-title %}
{% block modals %}
<div id="modal-close-registration-dialog" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{% trans 'Anmeldung schließen?' %}</h4>
</div>
<div class="modal-body">
<p class="text-center">
<strong>{{ event }}</strong>
</p>
<p>
Die Redaktion wird informiert, dass die Veranstaltung im Internet als ausgebucht gekennzeichnet
bzw. nicht abgedruckt werden soll.<br />
Eine Teilnehmeranmeldung über das Touren- und Kurse-Portal wird nicht mehr möglich sein.
</p>
</div>
<div class="modal-footer">
<form action="" method="post">
{% csrf_token %}
<input type="hidden" name="action" value="close-registration">
<button type="submit" class="btn btn-success">
{% bootstrap_icon 'ok' %}&thinsp;
{% trans 'Ja, mach zu!' %}
</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">
{% bootstrap_icon 'remove' %}&thinsp;
{% trans 'Abbrechen' %}
</button>
</form>
</div>
</div>
</div>
</div>
<div id="modal-open-registration-dialog" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{% trans 'Anmeldung wieder öffnen?' %}</h4>
</div>
<div class="modal-body">
<p class="text-center">
<strong>{{ event }}</strong>
</p>
<p>
Die Anmeldung über das Touren- und Kurse-Portal wird wieder möglich
(solange der Anmeldeschluß noch nicht abgelaufen ist).<br />
Die Redaktion wird darüber aber nicht informiert.
</p>
</div>
<div class="modal-footer">
<form action="" method="post">
{% csrf_token %}
<input type="hidden" name="action" value="open-registration">
<button type="submit" class="btn btn-success">
{% bootstrap_icon 'ok' %}&thinsp;
{% trans 'Ja, super!' %}
</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">
{% bootstrap_icon 'remove' %}&thinsp;
{% trans 'Abbrechen' %}
</button>
</form>
</div>
</div>
</div>
</div>
<div id="modal-kill-deadline-dialog" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{% trans 'Anmeldeschluss aufheben?' %}</h4>
</div>
<div class="modal-body">
<p class="text-center">
<strong>{{ event }}</strong>
</p>
<p>
Der bisher gesetzte Anmeldeschluss wird gelöscht.<br />
Somit wird die Anmeldung über das Touren- und Kurse-Portal wieder möglich.<br />
<strong>Die Redaktion wird darüber nicht automatisch informiert</strong>.
Wenn deine Tour bereits mit Anmeldeschluss im <i>KA Alpin</i> abgedruckt wurde,
können wir da auch nichts mehr machen.<br />
</p>
</div>
<div class="modal-footer">
<form action="" method="post">
{% csrf_token %}
<input type="hidden" name="action" value="kill-deadline">
<button type="submit" class="btn btn-success">
{% bootstrap_icon 'ok' %}&thinsp;
{% trans 'Ja, super!' %}
</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">
{% bootstrap_icon 'remove' %}&thinsp;
{% trans 'Abbrechen' %}
</button>
</form>
</div>
</div>
</div>
</div>
{% endblock modals %}
{% block page-container-fluid %}
<div class="action-tabs top-most">
<ul class="nav nav-tabs" role="tablist">
<li>
<a href="{% url 'dav_events:list' %}">{% trans 'Veranstaltungsliste' %}</a>
</li>
<li>
<a href="{% url 'dav_events:detail' event.pk %}">{% trans 'Details' %}</a>
</li>
<li class="{% if not has_permission_update %}disabled{% endif %}">
<a class="{% if not has_permission_update %}disabled{% endif %}"
href="{% url 'dav_events:update' event.pk %}">{% trans 'Ändern' %}</a>
</li>
<li class="active">
<a href="{% url 'dav_events:registrations' event.pk %}">{% trans 'Anmeldungen' %}</a>
</li>
</ul>
</div>
{% if not event.registration_required %}
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{% trans 'Für diese Veranstaltung wurde keine Anmeldung gefordert.' %}
</div>
{% endif %}
<div class="panel panel-default">
<div class="panel-heading">
<div class="pull-right">
{% render_event_status event show_void=False %}
</div>
<h3 class="panel-title">{{ event }}</h3>
</div>
<div class="panel-body">
<div class="panel-group" id="form-accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div id="headingForm1" class="panel-heading" role="tab">
<h4 class="panel-title">
<a role="button" href="#collapseForm1" data-toggle="collapse" data-parent="#accordion"
aria-expanded="true" aria-controls="collapseForm1">
{% trans 'Allgemeines' %}
</a>
</h4>
</div>
<div id="collapseForm1" class="panel-collapse collapse in"
role="tabpanel" aria-labelledby="headingForm1">
<div class="panel-body">
<div class="row">
<div class="col-sm-3">
<strong>{% trans 'Teilnehmerzahl' %}:</strong>
{{ event.min_participants }} -
{% if event.max_participants > 0 %}
{{ event.max_participants }}
{% else %}
&infin;
{% endif %}
</div>
<div class="col-sm-4">
<strong>{% trans 'Anmeldeschluss' %}:</strong>
{% if event.deadline %}
{{ event.deadline|date:'l, d. F Y' }}
{% else %}
-
{% endif %}
</div>
<div class="col-sm-5">
<strong>{% trans 'Anmeldestatus' %}:</strong>
{% if not event.registration_required %}
<span class="label label-success">{% trans 'Anmeldung nicht erforderlich' %}</span>
{% elif is_done %}
<span class="label label-default">{% trans 'Veranstaltung beendet' %}</span>
{% elif event.registration_closed %}
<span class="label label-danger">{% trans 'Anmeldung geschlossen' %}</span>
{% elif event.is_deadline_expired %}
<span class="label label-warning">{% trans 'Anmeldeschluss abgelaufen' %}</span>
{% elif is_published_any %}
<span class="label label-success">{% trans 'Anmeldung geöffnet' %}</span>
{% else %}
<span class="label label-info">{% trans 'Veranstaltung noch nicht veröffentlicht' %}</span>
{% endif %}
</div>
</div>
</div>
<div class="panel-footer">
{% if event.is_deadline_expired %}
<a id="btn-kill-deadline" class="btn btn-danger"
data-toggle="modal" data-target="#modal-kill-deadline-dialog">
{% bootstrap_icon 'remove-circle' %}&thinsp;
{% trans 'Anmeldeschluss aufheben' %}
</a>
{% elif event.registration_closed %}
<a id="btn-open-registration" class="btn btn-warning"
data-toggle="modal" data-target="#modal-open-registration-dialog">
{% bootstrap_icon 'ok-circle' %}&thinsp;
{% trans 'Anmeldung wieder öffnen' %}
</a>
{% else %}
<a id="btn-close-registration" class="btn btn-warning"
data-toggle="modal" data-target="#modal-close-registration-dialog">
{% bootstrap_icon 'ban-circle' %}&thinsp;
{% trans 'Anmeldung schließen' %}
</a>
{% endif %}
</div>
</div>
</div>
<hr />
<h4>Teilnehmer (Designstudie - Das funktioniert alles noch nicht!)</h4>
<div class="panel panel-default">
<div id="headingAddParticipant" class="panel-heading" role="tab">
<h5 class="panel-title">
<a role="button" href="#collapseAddParticipant" data-toggle="collapse" data-parent="#accordion"
aria-expanded="true" aria-controls="collapseAddParticipant">
Teilnehmer hinzufügen
</a>
</h5>
</div>
<div id="collapseAddParticipant" class="panel-collapse collapse in"
role="tabpanel" aria-labelledby="headingAddParticipant">
<div class="panel-body">
Formular
</div>
<div class="panel-footer">
<button class="btn btn-success">Speichern</button>
</div>
</div>
</div>
{% for participant in participants %}
<div class="panel panel-default">
<div id="headingParticipant_{{ participant.id }}" class="panel-heading" role="tab">
<h5 class="panel-title">
<a role="button" href="#collapseParticipant_{{ participant.id }}" data-toggle="collapse" data-parent="#accordion"
aria-expanded="true" aria-controls="collapseParticipant_{{ participant.id }}">
{{ participant.position }}. {{ participant.get_full_name }}
</a>
</h5>
</div>
<div id="collapseParticipant_{{ participant.id }}" class="panel-collapse collapse"
role="tabpanel" aria-labelledby="headingParticipant_{{ participant.id }}">
<div class="panel-body">
Hier tauchen dann die Teilnehmerdaten auf
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock page-container-fluid %}

View File

@@ -45,6 +45,10 @@
<li class="active">
<a href="{% url 'dav_events:update' event.pk %}">{% trans 'Ändern' %}</a>
</li>
<li class="{% if not event.registration_required %}disabled{% endif %}">
<a class="{% if not event.registration_required %}disabled{% endif %}"
href="{% url 'dav_events:registrations' event.pk %}">{% trans 'Anmeldungen' %}</a>
</li>
</ul>
</div>
<form action="" method="post">

View File

@@ -7,6 +7,7 @@ urlpatterns = [
url(r'^$', views.events.EventListView.as_view(), name='list'),
url(r'^export$', views.events.EventListExportView.as_view(), name='list_export'),
url(r'^create$', views.events.EventCreateView.as_view(), name='create'),
url(r'^(?P<pk>\d+)/registrations', views.events.EventRegistrationsView.as_view(), name='registrations'),
url(r'^(?P<pk>\d+)/status/(?P<status>[a-z0-9._-][a-z0-9._-]*)',
views.events.EventUpdateStatusView.as_view(), name='updatestatus'),
url(r'^(?P<pk>\d+)/edit', views.events.EventUpdateView.as_view(), name='update'),

View File

@@ -150,6 +150,7 @@ class EventDetailView(EventPermissionMixin, generic.DetailView):
context['is_publishing'] = obj.workflow.has_reached_status('publishing')
context['is_publishing_any'] = obj.workflow.has_reached_status('publishing*')
context['is_published'] = obj.workflow.has_reached_status('published')
context['is_published_any'] = obj.workflow.has_reached_status('published*')
return context
@method_decorator(login_required)
@@ -157,6 +158,63 @@ class EventDetailView(EventPermissionMixin, generic.DetailView):
return super(EventDetailView, self).dispatch(request, *args, **kwargs)
class EventRegistrationsView(EventPermissionMixin, generic.DetailView):
permission = 'update-registration'
model = models.Event
template_name = 'dav_events/event_registrations.html'
def get_object(self, queryset=None):
obj = super(EventRegistrationsView, self).get_object(queryset=queryset)
self.enforce_permission(obj)
return obj
def get_context_data(self, **kwargs):
context = super(EventRegistrationsView, self).get_context_data(**kwargs)
obj = context.get('event')
context['has_permission_update'] = self.has_permission('update', obj)
context['is_published_any'] = obj.workflow.has_reached_status('published*')
context['is_done'] = obj.workflow.has_reached_status('expired')
class MockParticipant(object):
def __init__(self, id, name):
self.id = id
self.name = name
@property
def position(self):
return self.id
def get_full_name(self):
return self.name
participants = [MockParticipant(1, 'Erika Musterfrau'), MockParticipant(2, 'Max Mustermann')]
context['participants'] = participants
return context
def post(self, request, *args, **kwargs):
event = self.get_object()
action = request.POST.get('action')
if action == 'close-registration':
event.registration_closed = True
event.save()
messages.success(request, _(u'Die Anmeldung wurde geschlossen'))
elif action == 'open-registration':
event.registration_closed = False
event.save()
messages.success(request, _(u'Die Anmeldung wurde geöffnet'))
elif action == 'kill-deadline':
event.deadline = None
event.registration_closed = False
event.save()
messages.success(request, _(u'Der Anmeldeschluss wurde gelöscht'))
return HttpResponseRedirect(reverse('dav_events:registrations', kwargs={'pk': event.pk}))
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(EventRegistrationsView, self).dispatch(request, *args, **kwargs)
class EventUpdateStatusView(EventPermissionMixin, generic.DetailView):
model = models.Event

View File

@@ -436,6 +436,15 @@ class BasicWorkflow(object):
return True
elif has_role(user, 'publisher'):
return True
elif permission == 'update-registration':
if user == event.owner:
return True
if has_role(user, 'manager_super'):
return True
if has_role(user, 'manager_{}'.format(event.sport.lower())):
return True
if has_role(user, 'publisher'):
return True
return False
# TODO: is a class method a good idea?