Merge pull request #879 from DebVortex/feature/refactor-assignments
Refactored assignments app.
This commit is contained in:
commit
7ea8a6195c
1
AUTHORS
1
AUTHORS
@ -11,3 +11,4 @@ Authors of OpenSlides in chronological order of first contribution:
|
||||
Roland Geider <roland@geider.net>
|
||||
Tobias Hößl <tobias@hoessl.eu>
|
||||
Pavel Fric <pavelfric@seznam.cz> (Czech translation)
|
||||
Max Brauer <max@max-brauer.de>
|
||||
|
@ -16,12 +16,12 @@ from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
|
||||
from django.utils.datastructures import SortedDict
|
||||
|
||||
from openslides.utils.person import PersonField
|
||||
from openslides.utils.utils import html_strong
|
||||
from openslides.config.api import config
|
||||
from openslides.projector.api import register_slidemodel
|
||||
from openslides.projector.projector import SlideMixin
|
||||
from openslides.poll.models import (
|
||||
BasePoll, CountInvalid, CountVotesCast, BaseOption, PublishPollMixin, BaseVote)
|
||||
from openslides.agenda.models import Item
|
||||
|
||||
|
||||
class AssignmentCandidate(models.Model):
|
||||
@ -54,16 +54,12 @@ class Assignment(models.Model, SlideMixin):
|
||||
status = models.CharField(max_length=3, choices=STATUS, default='sea')
|
||||
|
||||
def set_status(self, status):
|
||||
error = True
|
||||
for a, b in Assignment.STATUS:
|
||||
if status == a:
|
||||
error = False
|
||||
break
|
||||
if error:
|
||||
raise NameError(_('%s is not a valid status.') % status)
|
||||
status_dict = dict(self.STATUS)
|
||||
if status not in status_dict:
|
||||
raise ValueError(_('%s is not a valid status.') % html_strong(status))
|
||||
if self.status == status:
|
||||
raise NameError(
|
||||
_('The assignment status is already %s.') % self.status)
|
||||
raise ValueError(
|
||||
_('The assignment status is already %s.') % html_strong(status_dict[status]))
|
||||
self.status = status
|
||||
self.save()
|
||||
|
||||
@ -228,9 +224,9 @@ class Assignment(models.Model, SlideMixin):
|
||||
|
||||
def get_absolute_url(self, link='detail'):
|
||||
if link == 'detail' or link == 'view':
|
||||
return reverse('assignment_view', args=[str(self.id)])
|
||||
return reverse('assignment_detail', args=[str(self.id)])
|
||||
if link == 'update' or link == 'edit':
|
||||
return reverse('assignment_edit', args=[str(self.id)])
|
||||
return reverse('assignment_update', args=[str(self.id)])
|
||||
if link == 'delete':
|
||||
return reverse('assignment_delete', args=[str(self.id)])
|
||||
|
||||
@ -299,7 +295,7 @@ class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
|
||||
|
||||
@models.permalink
|
||||
def get_absolute_url(self, link='view'):
|
||||
if link == 'view':
|
||||
if link == 'view' or link == 'detail' or link == 'update':
|
||||
return ('assignment_poll_view', [str(self.id)])
|
||||
if link == 'delete':
|
||||
return ('assignment_poll_delete', [str(self.id)])
|
||||
|
@ -19,8 +19,8 @@
|
||||
<h1>
|
||||
{{ assignment }}
|
||||
<small class="pull-right">
|
||||
<a href="{% url 'assignment_overview' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a>
|
||||
<a href="{% url 'print_assignment' assignment.id %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Print election as PDF' %}" target="_blank"><i class="icon-print"></i> PDF</a>
|
||||
<a href="{% url 'assignment_list' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a>
|
||||
<a href="{% url 'assignment_pdf' assignment.id %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Print election as PDF' %}" target="_blank"><i class="icon-print"></i> PDF</a>
|
||||
<!-- activate projector -->
|
||||
{% if perms.projector.can_manage_projector %}
|
||||
<a href="{% url 'projector_activate_slide' assignment.sid %}" class="activate_link btn {% if assignment.active %}btn-primary{% endif %} btn-mini" rel="tooltip" data-original-title="{% trans 'Show election' %}">
|
||||
@ -35,9 +35,9 @@
|
||||
<ul class="dropdown-menu pull-right">
|
||||
{% if perms.assignment.can_manage_assignment %}
|
||||
<!-- edit -->
|
||||
<li><a href="{% url 'assignment_edit' assignment.id %}"><i class="icon-pencil"></i> {% trans 'Edit election' %}</a></li>
|
||||
<li><a href="{{ assignment|absolute_url:'update' }}"><i class="icon-pencil"></i> {% trans 'Edit election' %}</a></li>
|
||||
<!-- delete -->
|
||||
<li><a href="{% url 'assignment_delete' assignment.id %}"><i class="icon-remove"></i> {% trans 'Delete election' %}</a></li>
|
||||
<li><a href="{{ assignment|absolute_url:'delete' }}"><i class="icon-remove"></i> {% trans 'Delete election' %}</a></li>
|
||||
{% endif %}
|
||||
<!-- create agenda item -->
|
||||
{% if perms.agenda.can_manage_agenda %}
|
||||
@ -65,7 +65,7 @@
|
||||
<ol>
|
||||
{% for person in assignment.get_participants %}
|
||||
<li>
|
||||
<a href="{% model_url person 'view' %}">{{ person }}</a>
|
||||
<a href="{{ person|absolute_url:'detail' }}">{{ person }}</a>
|
||||
{% if perms.assignment.can_manage_assignment %}
|
||||
{% if assignment.status == "sea" or assignment.status == "vot" %}
|
||||
<a href="{% url 'assignment_delother' assignment.id person.person_id %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Remove candidate' %}"><i class="icon-remove"></i></a>
|
||||
@ -126,7 +126,7 @@
|
||||
<ul>
|
||||
{% for person in blocked_candidates %}
|
||||
<li>
|
||||
<a href="{% model_url person 'view' %}">{{ person }}</a>
|
||||
<a href="{{ person|absolute_url:'detail' }}">{{ person }}</a>
|
||||
<a class="btn btn-mini" href="{% url 'assignment_delother' assignment.id person.person_id %}"
|
||||
rel="tooltip" data-original-title="{% trans 'Remove candidate' %}">
|
||||
<i class="icon-ban-circle"></i>
|
||||
@ -168,16 +168,16 @@
|
||||
<i class="icon-unchecked-new"></i>
|
||||
{% endif %}
|
||||
</a>
|
||||
<a href="{% url 'assignment_poll_view' poll.id %}" class="btn btn-mini"
|
||||
<a href="{{ poll|absolute_url:'update' }}" class="btn btn-mini"
|
||||
rel="tooltip" data-original-title="{% trans 'Edit' %}"><i class="icon-pencil"></i></a>
|
||||
<a href="{% url 'assignment_poll_delete' poll.id %}" class="btn btn-mini"
|
||||
<a href="{{ poll|absolute_url:'delete' }}" class="btn btn-mini"
|
||||
rel="tooltip" data-original-title="{% trans 'Delete' %}"><i class="icon-remove"></i></a>
|
||||
{% endif %}
|
||||
</th>
|
||||
{% endfor %}
|
||||
{% if assignment.candidates and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
|
||||
<th class="span1 nobr">
|
||||
<a href="{% url 'assignment_gen_poll' assignment.id %}" class="btn btn-mini">
|
||||
<a href="{% url 'assignment_poll_create' assignment.id %}" class="btn btn-mini">
|
||||
<i class="icon-plus"></i> {% trans 'New ballot' %}
|
||||
</a>
|
||||
</th>
|
||||
@ -200,7 +200,7 @@
|
||||
<a class="election_link" href="{% url 'assignment_user_elected' assignment.id candidate.person_id %}"></a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<a href="{% model_url candidate 'view' %}">{{ candidate }}</a>
|
||||
<a href="{{ candidate|absolute_url:'detail' }}">{{ candidate }}</a>
|
||||
</td>
|
||||
{% for vote in poll_list %}
|
||||
<td style="white-space:nowrap;">
|
||||
@ -259,7 +259,7 @@
|
||||
<i>{% trans "No ballots available." %}</i>
|
||||
{% if assignment.candidates and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
|
||||
<p>
|
||||
<a href='{% url 'assignment_gen_poll' assignment.id %}' class="btn">
|
||||
<a href='{% url 'assignment_poll_create' assignment.id %}' class="btn">
|
||||
<i class="icon-plus"></i> {% trans 'New ballot' %}
|
||||
</a>
|
||||
</p>
|
@ -19,7 +19,7 @@
|
||||
{% trans "New election" %}
|
||||
{% endif %}
|
||||
<small class="pull-right">
|
||||
<a href="{% url 'assignment_overview' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a>
|
||||
<a href="{% url 'assignment_list' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a>
|
||||
</small>
|
||||
</h1>
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
{% include "form.html" %}
|
||||
<p>
|
||||
{% include "formbuttons_saveapply.html" %}
|
||||
<a href='{% url 'assignment_overview' %}' class="btn">
|
||||
<a href='{% url 'assignment_list' %}' class="btn">
|
||||
{% trans 'Cancel' %}
|
||||
</a>
|
||||
</p>
|
@ -2,6 +2,7 @@
|
||||
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load tags %}
|
||||
|
||||
{% block title %}{% trans "Elections" %} – {{ block.super }}{% endblock %}
|
||||
|
||||
@ -18,10 +19,10 @@
|
||||
<h1>{% trans "Elections" %}
|
||||
<small class="pull-right">
|
||||
{% if perms.assignment.can_manage_assignment %}
|
||||
<a href="{% url 'assignment_new' %}" class="btn btn-mini btn-primary" rel="tooltip" data-original-title="{% trans 'New election' %}"><i class="icon-plus icon-white"></i> {% trans "New" %}</a>
|
||||
<a href="{% url 'assignment_create' %}" class="btn btn-mini btn-primary" rel="tooltip" data-original-title="{% trans 'New election' %}"><i class="icon-plus icon-white"></i> {% trans "New" %}</a>
|
||||
{% endif %}
|
||||
{% if perms.assignment.can_see_assignment %}
|
||||
<a href="{% url 'print_assignment' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Print all elections as PDF' %}" target="_blank"><i class="icon-print"></i> PDF</a>
|
||||
<a href="{% url 'assignment_list_pdf' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Print all elections as PDF' %}" target="_blank"><i class="icon-print"></i> PDF</a>
|
||||
{% endif %}
|
||||
</small>
|
||||
</h1>
|
||||
@ -35,41 +36,41 @@
|
||||
<th class="mini_width">{% trans "Actions" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% for assignment in assignments %}
|
||||
<tr class="{% if assignment.active %}activeline{% endif %}">
|
||||
<td><a href="{% url 'assignment_view' assignment.id %}">{{ assignment }}</a></td>
|
||||
{% for object in object_list %}
|
||||
<tr class="{% if object.active %}activeline{% endif %}">
|
||||
<td><a href="{{ object|absolute_url:'detail' }}">{{ object }}</a></td>
|
||||
<td class="optional">
|
||||
<!-- posts -->
|
||||
{% trans "Posts" context "Number of searched candidates for an election" %}:
|
||||
<span class="badge badge-info">{{ assignment.posts }}</span>
|
||||
<span class="badge badge-info">{{ object.posts }}</span>
|
||||
<!-- candidates -->
|
||||
{% if assignment.status != 'fin' %}
|
||||
| {% trans "Candidates" %}: <span class="badge badge-warning">{{ assignment.get_participants|length }}</span>
|
||||
{% if object.status != 'fin' %}
|
||||
| {% trans "Candidates" %}: <span class="badge badge-warning">{{ object.get_participants|length }}</span>
|
||||
{% endif %}
|
||||
<!-- elected candidates -->
|
||||
| {% trans "Elected" %}: <span class="badge badge-success">{{ assignment.elected|length }}</span>
|
||||
| {% trans "Elected" %}: <span class="badge badge-success">{{ object.elected|length }}</span>
|
||||
</td>
|
||||
<td><span class="label label-info">{{ assignment.get_status_display }}</status></td>
|
||||
<td><span class="label label-info">{{ object.get_status_display }}</status></td>
|
||||
<td>
|
||||
<span style="width: 1px; white-space: nowrap;">
|
||||
{% if perms.projector.can_manage_projector %}
|
||||
<a href="{% url 'projector_activate_slide' assignment.sid %}"
|
||||
class="activate_link btn {% if assignment.active %}btn-primary{% endif %} btn-mini"
|
||||
<a href="{% url 'projector_activate_slide' object.sid %}"
|
||||
class="activate_link btn {% if object.active %}btn-primary{% endif %} btn-mini"
|
||||
rel="tooltip" data-original-title="{% trans 'Show election' %}">
|
||||
<i class="icon-facetime-video {% if assignment.active %}icon-white{% endif %}"></i>
|
||||
<i class="icon-facetime-video {% if object.active %}icon-white{% endif %}"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.assignment.can_manage_assignment %}
|
||||
<a href="{% url 'assignment_edit' assignment.id %}"
|
||||
<a href="{{ object|absolute_url:'update' }}"
|
||||
rel="tooltip" data-original-title="{% trans 'Edit' %}"
|
||||
class="btn btn-mini"><i class="icon-pencil"></i>
|
||||
</a>
|
||||
<a href="{% url 'assignment_delete' assignment.id %}"
|
||||
<a href="{% url 'assignment_delete' object.id %}"
|
||||
rel="tooltip" data-original-title="{% trans 'Delete' %}"
|
||||
class="btn btn-mini"><i class="icon-remove"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'print_assignment' assignment.id %}"
|
||||
<a href="{% url 'assignment_pdf' object.id %}"
|
||||
data-original-title="{% trans 'Print election as PDF' %}" target="_blank"
|
||||
class="btn btn-mini tooltip-left"><i class="icon-print"></i> PDF
|
||||
</a>
|
@ -2,6 +2,7 @@
|
||||
|
||||
{% load i18n %}
|
||||
{% load humanize %}
|
||||
{% load tags %}
|
||||
|
||||
{% block title %}{% trans "Election" %} "{{ assignment }}", {{ ballotnumber }}. {% trans "ballot" %} – {{ block.super }}{% endblock %}
|
||||
|
||||
@ -12,7 +13,7 @@
|
||||
{{ ballotnumber|ordinal|safe }} {% trans "ballot" %}
|
||||
</small>
|
||||
<small class="pull-right">
|
||||
<a href="{% url 'assignment_view' assignment.id %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to election" %}</a>
|
||||
<a href="{{ assignment|absolute_url:'detail' }}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to election" %}</a>
|
||||
<!-- activate projector -->
|
||||
{% if perms.projector.can_manage_projector %}
|
||||
<a href="{% url 'projector_activate_slide' assignment.sid %}" class="activate_link btn {% if assignment.active %}btn-primary{% endif %} btn-mini" rel="tooltip" data-original-title="{% trans 'Show election' %}">
|
||||
@ -71,7 +72,7 @@
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<a href="{% url 'print_assignment_poll' poll.id %}" class="btn" target="_blank">
|
||||
<a href="{% url 'assignment_poll_pdf' poll.id %}" class="btn" target="_blank">
|
||||
<i class="icon-print"></i> {% trans 'Ballot paper as PDF' %}
|
||||
</a>
|
||||
</p>
|
||||
@ -83,7 +84,7 @@
|
||||
<button type="submit" name="apply" class="btn">
|
||||
{% trans 'Apply' %}
|
||||
</button>
|
||||
<a href="{% url 'assignment_view' poll.assignment.id %}" class="btn">
|
||||
<a href="{{ poll.assignment|absolute_url:'detail' }}" class="btn">
|
||||
{% trans 'Cancel' %}
|
||||
</a>
|
||||
</div>
|
||||
|
@ -7,13 +7,13 @@
|
||||
<a href="{% url 'projector_activate_slide' assignment.sid %}" class="activate_link btn {% if assignment.active %}btn-primary{% endif %} btn-mini" title="{% trans 'Show' %}">
|
||||
<i class="icon-facetime-video {% if assignment.active %}icon-white{% endif %}"></i>
|
||||
</a>
|
||||
<a href="{% model_url assignment 'edit' %}" title="{% trans 'Edit' %}" class="btn btn-mini right">
|
||||
<a href="{{ assignment|absolute_url:'update' }}" title="{% trans 'Edit' %}" class="btn btn-mini right">
|
||||
<i class="icon-pencil"></i>
|
||||
</a>
|
||||
<a href="{% url 'projctor_preview_slide' assignment.sid %}" title="{% trans 'Preview' %}" class="btn btn-mini right">
|
||||
<i class="icon-search"></i>
|
||||
</a>
|
||||
<a href="{% model_url assignment 'view' %}">{{ assignment }}</a>
|
||||
<a href="{{ assignment|absolute_url:'detail' }}">{{ assignment }}</a>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>{% trans 'No assignments available.' %}</li>
|
||||
|
@ -12,62 +12,61 @@
|
||||
|
||||
from django.conf.urls import url, patterns
|
||||
|
||||
from openslides.assignment.views import (ViewPoll, AssignmentPDF,
|
||||
AssignmentPollPDF, AssignmentPollDelete, CreateRelatedAgendaItemView)
|
||||
from openslides.assignment.views import (AssignmentListView, AssignmentDetail,
|
||||
AssignmentCreateView, AssignmentUpdateView, AssignmentDeleteView,
|
||||
AssignmentSetStatusView, AssignmentRunView, AssignmentRunDeleteView,
|
||||
AssignmentRunOtherDeleteView, PollCreateView, PollUpdateView, AssignmentPDF,
|
||||
AssignmentPollPDF, AssignmentPollDeleteView, SetPublishStatusView,
|
||||
SetElectedView, CreateRelatedAgendaItemView)
|
||||
|
||||
urlpatterns = patterns('openslides.assignment.views',
|
||||
url(r'^$',
|
||||
'get_overview',
|
||||
name='assignment_overview',
|
||||
AssignmentListView.as_view(),
|
||||
name='assignment_list',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/$',
|
||||
'view',
|
||||
name='assignment_view'),
|
||||
url(r'^(?P<pk>\d+)/$',
|
||||
AssignmentDetail.as_view(),
|
||||
name='assignment_detail'),
|
||||
|
||||
url(r'^new/$',
|
||||
'edit',
|
||||
name='assignment_new',
|
||||
AssignmentCreateView.as_view(),
|
||||
name='assignment_create',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/edit/$',
|
||||
'edit',
|
||||
name='assignment_edit',
|
||||
url(r'^(?P<pk>\d+)/edit/$',
|
||||
AssignmentUpdateView.as_view(),
|
||||
name='assignment_update',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/del/$',
|
||||
'delete',
|
||||
url(r'^(?P<pk>\d+)/del/$',
|
||||
AssignmentDeleteView.as_view(),
|
||||
name='assignment_delete',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/setstatus/(?P<status>[a-z]{3})/$',
|
||||
'set_status',
|
||||
url(r'^(?P<pk>\d+)/setstatus/(?P<status>[a-z]{3})/$',
|
||||
AssignmentSetStatusView.as_view(),
|
||||
name='assignment_set_status',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/run/$',
|
||||
'run',
|
||||
url(r'^(?P<pk>\d+)/run/$',
|
||||
AssignmentRunView.as_view(),
|
||||
name='assignment_run',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/delrun/$',
|
||||
'delrun',
|
||||
url(r'^(?P<pk>\d+)/delrun/$',
|
||||
AssignmentRunDeleteView.as_view(),
|
||||
name='assignment_delrun',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/delother/(?P<user_id>[^/]+)/$',
|
||||
'delother',
|
||||
url(r'^(?P<pk>\d+)/delother/(?P<user_id>[^/]+)/$',
|
||||
AssignmentRunOtherDeleteView.as_view(),
|
||||
name='assignment_delother',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/set_active/$',
|
||||
'set_active',
|
||||
name='assignment_activate_item',
|
||||
),
|
||||
|
||||
url(r'^poll/(?P<poll_id>\d+)/print/$',
|
||||
AssignmentPollPDF.as_view(),
|
||||
name='print_assignment_poll',
|
||||
name='assignment_poll_pdf',
|
||||
),
|
||||
|
||||
url(r'^(?P<pk>\d+)/agenda/$',
|
||||
@ -77,42 +76,42 @@ urlpatterns = patterns('openslides.assignment.views',
|
||||
|
||||
url(r'^print/$',
|
||||
AssignmentPDF.as_view(),
|
||||
name='print_assignment',
|
||||
name='assignment_list_pdf',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/print/$',
|
||||
url(r'^(?P<pk>\d+)/print/$',
|
||||
AssignmentPDF.as_view(),
|
||||
name='print_assignment',
|
||||
name='assignment_pdf',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/gen_poll/$',
|
||||
'gen_poll',
|
||||
name='assignment_gen_poll',
|
||||
url(r'^(?P<pk>\d+)/gen_poll/$',
|
||||
PollCreateView.as_view(),
|
||||
name='assignment_poll_create',
|
||||
),
|
||||
|
||||
url(r'^poll/(?P<poll_id>\d+)/$',
|
||||
ViewPoll.as_view(),
|
||||
PollUpdateView.as_view(),
|
||||
name='assignment_poll_view',
|
||||
),
|
||||
|
||||
url(r'^poll/(?P<pk>\d+)/del/$',
|
||||
AssignmentPollDelete.as_view(),
|
||||
AssignmentPollDeleteView.as_view(),
|
||||
name='assignment_poll_delete',
|
||||
),
|
||||
|
||||
url(r'^poll/(?P<poll_id>\d+)/pub/$',
|
||||
'set_publish_status',
|
||||
url(r'^poll/(?P<pk>\d+)/pub/$',
|
||||
SetPublishStatusView.as_view(),
|
||||
name='assignment_poll_publish_status',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/elected/(?P<user_id>[^/]+)/$',
|
||||
'set_elected',
|
||||
url(r'^(?P<pk>\d+)/elected/(?P<user_id>[^/]+)/$',
|
||||
SetElectedView.as_view(),
|
||||
{'elected': True},
|
||||
name='assignment_user_elected',
|
||||
),
|
||||
|
||||
url(r'^(?P<assignment_id>\d+)/notelected/(?P<user_id>[^/]+)/$',
|
||||
'set_elected',
|
||||
url(r'^(?P<pk>\d+)/notelected/(?P<user_id>[^/]+)/$',
|
||||
SetElectedView.as_view(),
|
||||
{'elected': False},
|
||||
name='assignment_user_not_elected',
|
||||
),
|
||||
|
@ -20,16 +20,18 @@ from reportlab.lib.units import cm
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import ungettext, ugettext as _
|
||||
|
||||
from openslides.utils.pdf import stylesheet
|
||||
from openslides.utils.template import Tab
|
||||
from openslides.utils.utils import (
|
||||
template, permission_required, gen_confirm_form, del_confirm_form, ajax_request)
|
||||
from openslides.utils.views import FormView, DeleteView, PDFView, RedirectView
|
||||
from openslides.utils.utils import gen_confirm_form
|
||||
|
||||
from openslides.utils.views import (
|
||||
CreateView, DeleteView, RedirectView, UpdateView, ListView, PDFView,
|
||||
DetailView, View, PermissionMixin, SingleObjectMixin, QuestionMixin)
|
||||
from openslides.utils.person import get_person
|
||||
from openslides.utils.utils import html_strong
|
||||
from openslides.config.api import config
|
||||
from openslides.participant.models import User, Group
|
||||
from openslides.projector.projector import Widget
|
||||
@ -39,199 +41,194 @@ from openslides.assignment.models import Assignment, AssignmentPoll
|
||||
from openslides.assignment.forms import AssignmentForm, AssignmentRunForm
|
||||
|
||||
|
||||
@permission_required('assignment.can_see_assignment')
|
||||
@template('assignment/overview.html')
|
||||
def get_overview(request):
|
||||
assignments = Assignment.objects.all()
|
||||
return {
|
||||
'assignments': assignments,
|
||||
}
|
||||
class AssignmentListView(ListView):
|
||||
"""ListView for all Assignments"""
|
||||
permission_required = 'assignment.can_see_assignment'
|
||||
model = Assignment
|
||||
|
||||
|
||||
@permission_required('assignment.can_see_assignment')
|
||||
@template('assignment/view.html')
|
||||
def view(request, assignment_id=None):
|
||||
form = None
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
if request.method == 'POST':
|
||||
if request.user.has_perm('assignment.can_nominate_other'):
|
||||
form = AssignmentRunForm(request.POST)
|
||||
if form.is_valid():
|
||||
user = form.cleaned_data['candidate']
|
||||
try:
|
||||
assignment.run(user, request.user)
|
||||
except NameError, e:
|
||||
messages.error(request, e)
|
||||
else:
|
||||
messages.success(request, _(
|
||||
"Candidate <b>%s</b> was nominated successfully.")
|
||||
% user)
|
||||
else:
|
||||
if request.user.has_perm('assignment.can_nominate_other'):
|
||||
form = AssignmentRunForm()
|
||||
class AssignmentDetail(DetailView):
|
||||
permission_required = 'assignment.can_see_assignment'
|
||||
model = Assignment
|
||||
form_class = AssignmentRunForm
|
||||
|
||||
polls = assignment.poll_set.all()
|
||||
if not request.user.has_perm('assignment.can_manage_assignment'):
|
||||
polls = assignment.poll_set.filter(published=True)
|
||||
vote_results = assignment.vote_results(only_published=True)
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
context = super(AssignmentDetail, self).get_context_data(*args, **kwargs)
|
||||
if self.request.method == 'POST':
|
||||
context['form'] = self.form_class(self.request.POST)
|
||||
else:
|
||||
polls = assignment.poll_set.all()
|
||||
vote_results = assignment.vote_results(only_published=False)
|
||||
context['form'] = self.form_class()
|
||||
polls = self.object.poll_set.all()
|
||||
if not self.request.user.has_perm('assignment.can_manage_assignment'):
|
||||
polls = self.object.poll_set.filter(published=True)
|
||||
vote_results = self.object.vote_results(only_published=True)
|
||||
else:
|
||||
polls = self.object.poll_set.all()
|
||||
vote_results = self.object.vote_results(only_published=False)
|
||||
|
||||
blocked_candidates = [
|
||||
candidate.person for candidate in
|
||||
assignment.assignment_candidates.filter(blocked=True)]
|
||||
return {
|
||||
'assignment': assignment,
|
||||
'blocked_candidates': blocked_candidates,
|
||||
'form': form,
|
||||
'vote_results': vote_results,
|
||||
'polls': polls,
|
||||
'user_is_candidate': assignment.is_candidate(request.user)}
|
||||
self.object.assignment_candidates.filter(blocked=True)]
|
||||
context['polls'] = polls
|
||||
context['vote_results'] = vote_results
|
||||
context['blocked_candidates'] = blocked_candidates
|
||||
context['user_is_candidate'] = self.object.is_candidate(self.request.user)
|
||||
return context
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
@template('assignment/edit.html')
|
||||
def edit(request, assignment_id=None):
|
||||
"""
|
||||
View zum editieren und neuanlegen von Wahlen
|
||||
"""
|
||||
if assignment_id is not None:
|
||||
assignment = Assignment.objects.get(id=assignment_id)
|
||||
else:
|
||||
assignment = None
|
||||
|
||||
if request.method == 'POST':
|
||||
form = AssignmentForm(request.POST, instance=assignment)
|
||||
def post(self, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
if self.request.user.has_perm('assignment.can_nominate_other'):
|
||||
form = self.form_class(self.request.POST)
|
||||
if form.is_valid():
|
||||
assignment = form.save()
|
||||
if assignment_id is None:
|
||||
messages.success(request, _('New election was successfully created.'))
|
||||
else:
|
||||
messages.success(request, _('Election was successfully modified.'))
|
||||
if not 'apply' in request.POST:
|
||||
return redirect(reverse("assignment_overview"))
|
||||
if assignment_id is None:
|
||||
return redirect(reverse('assignment_edit', args=[assignment.id]))
|
||||
else:
|
||||
messages.error(request, _('Please check the form for errors.'))
|
||||
else:
|
||||
form = AssignmentForm(instance=assignment)
|
||||
if assignment:
|
||||
polls = assignment.poll_set.filter(assignment=assignment)
|
||||
else:
|
||||
polls = None
|
||||
return {
|
||||
'form': form,
|
||||
'assignment': assignment,
|
||||
'polls': polls,
|
||||
}
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
def delete(request, assignment_id):
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
if request.method == 'POST':
|
||||
if 'submit' in request.POST:
|
||||
assignment.delete()
|
||||
messages.success(request, _('Election <b>%s</b> was successfully deleted.') % assignment)
|
||||
else:
|
||||
del_confirm_form(request, assignment)
|
||||
return redirect(reverse('assignment_overview'))
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
@template('assignment/view.html')
|
||||
def set_status(request, assignment_id=None, status=None):
|
||||
user = form.cleaned_data['candidate']
|
||||
try:
|
||||
self.object.run(user, self.request.user)
|
||||
except NameError, e:
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
messages.success(self.request, _(
|
||||
"Candidate %s was nominated successfully.")
|
||||
% html_strong(user))
|
||||
return super(AssignmentDetail, self).get(*args, **kwargs)
|
||||
|
||||
|
||||
class AssignmentCreateView(CreateView):
|
||||
model = Assignment
|
||||
form_class = AssignmentForm
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
|
||||
|
||||
class AssignmentUpdateView(UpdateView):
|
||||
model = Assignment
|
||||
form_class = AssignmentForm
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
|
||||
|
||||
class AssignmentDeleteView(DeleteView):
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
model = Assignment
|
||||
success_url_name = 'assignment_list'
|
||||
|
||||
|
||||
class AssignmentSetStatusView(SingleObjectMixin, RedirectView):
|
||||
model = Assignment
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
url_name = 'assignment_detail'
|
||||
|
||||
def pre_redirect(self, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
status = kwargs.get('status')
|
||||
if status is not None:
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
assignment.set_status(status)
|
||||
messages.success(request, _('Election status was set to: <b>%s</b>.') % assignment.get_status_display())
|
||||
except Assignment.DoesNotExist:
|
||||
pass
|
||||
except NameError, e:
|
||||
messages.error(request, e)
|
||||
return redirect(reverse('assignment_view', args=[assignment_id]))
|
||||
|
||||
|
||||
@permission_required('assignment.can_nominate_self')
|
||||
def run(request, assignment_id):
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
try:
|
||||
assignment.run(request.user, request.user)
|
||||
messages.success(request, _('You have set your candidature successfully.'))
|
||||
except NameError, e:
|
||||
messages.error(request, e)
|
||||
return redirect(reverse('assignment_view', args=[assignment_id]))
|
||||
|
||||
|
||||
@login_required
|
||||
def delrun(request, assignment_id):
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
if assignment.status == 'sea' or request.user.has_perm("assignment.can_manage_assignment"):
|
||||
try:
|
||||
assignment.delrun(request.user, blocked=True)
|
||||
except Exception, e:
|
||||
messages.error(request, e)
|
||||
self.object.set_status(status)
|
||||
except ValueError, e:
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
messages.success(
|
||||
request,
|
||||
_("You have withdrawn your candidature successfully. "
|
||||
"You can not be nominated by other participants anymore."))
|
||||
else:
|
||||
messages.error(request, _('The candidate list is already closed.'))
|
||||
|
||||
return redirect(reverse('assignment_view', args=[assignment_id]))
|
||||
self.request,
|
||||
_('Election status was set to: %s.') %
|
||||
html_strong(self.object.get_status_display())
|
||||
)
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
def delother(request, assignment_id, user_id):
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
person = get_person(user_id)
|
||||
is_blocked = assignment.is_blocked(person)
|
||||
class AssignmentRunView(SingleObjectMixin, PermissionMixin, View):
|
||||
model = Assignment
|
||||
permission_required = 'assignment.can_nominate_self'
|
||||
|
||||
if request.method == 'POST':
|
||||
if 'submit' in request.POST:
|
||||
def get(self, *args, **kwargs):
|
||||
assignment = self.get_object()
|
||||
try:
|
||||
assignment.delrun(person, blocked=False)
|
||||
assignment.run(self.request.user, self.request.user)
|
||||
except NameError, e:
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
messages.success(
|
||||
self.request, _('You have set your candidature successfully.'))
|
||||
return redirect(reverse('assignment_detail', args=[assignment.pk]))
|
||||
|
||||
|
||||
class AssignmentRunDeleteView(SingleObjectMixin, RedirectView):
|
||||
model = Assignment
|
||||
url_name = 'assignment_detail'
|
||||
success_message = _("You have withdrawn your candidature successfully. "
|
||||
"You can not be nominated by other participants anymore.")
|
||||
|
||||
def pre_redirect(self, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
if self.object.status == 'sea' or self.request.user.has_perm(
|
||||
"assignment.can_manage_assignment"):
|
||||
try:
|
||||
self.object.delrun(self.request.user, blocked=True)
|
||||
except Exception, e:
|
||||
messages.error(request, e)
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
if not is_blocked:
|
||||
message = _("Candidate <b>%s</b> was withdrawn successfully.") % person
|
||||
messages.success(self.request, self.success_message)
|
||||
else:
|
||||
message = _("<b>%s</b> was unblocked successfully.") % person
|
||||
messages.success(request, message)
|
||||
messages.error(self.request, _('The candidate list is already closed.'))
|
||||
|
||||
|
||||
class AssignmentRunOtherDeleteView(SingleObjectMixin, QuestionMixin,
|
||||
RedirectView):
|
||||
model = Assignment
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
question_url_name = 'assignment_detail'
|
||||
success_url_name = 'assignment_detail'
|
||||
success_message = ''
|
||||
|
||||
def pre_redirect(self, *args, **kwargs):
|
||||
self._get_person_information(*args, **kwargs)
|
||||
if not self.is_blocked:
|
||||
message = _("Do you really want to withdraw %s from the election?") % html_strong(self.person)
|
||||
else:
|
||||
if not is_blocked:
|
||||
message = _("Do you really want to withdraw <b>%s</b> from the election?") % person
|
||||
message = _("Do you really want to unblock %s for the election?") % html_strong(self.person)
|
||||
gen_confirm_form(self.request, message, reverse('assignment_delother',
|
||||
args=[self.object.pk, kwargs['user_id']]))
|
||||
|
||||
def pre_post_redirect(self, *args, **kwargs):
|
||||
self._get_person_information(*args, **kwargs)
|
||||
if self.get_answer() == 'yes':
|
||||
self.case_yes()
|
||||
|
||||
def get_answer(self):
|
||||
if 'submit' in self.request.POST:
|
||||
return 'yes'
|
||||
|
||||
def case_yes(self):
|
||||
try:
|
||||
self.object.delrun(self.person, blocked=False)
|
||||
except Exception, e:
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
message = _("Do you really want to unblock <b>%s</b> for the election?") % person
|
||||
gen_confirm_form(request, message, reverse('assignment_delother', args=[assignment_id, user_id]))
|
||||
return redirect(reverse('assignment_view', args=[assignment_id]))
|
||||
messages.success(self.request, self.get_success_message())
|
||||
|
||||
def get_success_message(self):
|
||||
success_message = _("Candidate %s was withdrawn successfully.") % html_strong(self.person)
|
||||
if self.is_blocked:
|
||||
success_message = _("%s was unblocked successfully.") % html_strong(self.person)
|
||||
return success_message
|
||||
|
||||
def _get_person_information(self, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.person = get_person(kwargs.get('user_id'))
|
||||
self.is_blocked = self.object.is_blocked(self.person)
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
def set_active(request, assignment_id):
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
assignment.set_active()
|
||||
return redirect(reverse('assignment_view', args=[assignment_id]))
|
||||
class PollCreateView(SingleObjectMixin, RedirectView):
|
||||
model = Assignment
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
url_name = 'assignment_poll_view'
|
||||
|
||||
def pre_redirect(self, *args, **kwargs):
|
||||
self.object = self.get_object().gen_poll()
|
||||
messages.success(self.request, _("New ballot was successfully created."))
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
def gen_poll(request, assignment_id):
|
||||
poll = Assignment.objects.get(pk=assignment_id).gen_poll()
|
||||
messages.success(request, _("New ballot was successfully created."))
|
||||
return redirect(reverse('assignment_poll_view', args=[poll.id]))
|
||||
|
||||
|
||||
class ViewPoll(PollFormView):
|
||||
class PollUpdateView(PollFormView):
|
||||
poll_class = AssignmentPoll
|
||||
template_name = 'assignment/poll_view.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ViewPoll, self).get_context_data(**kwargs)
|
||||
context = super(PollUpdateView, self).get_context_data(**kwargs)
|
||||
self.assignment = self.poll.get_assignment()
|
||||
context['assignment'] = self.assignment
|
||||
context['poll'] = self.poll
|
||||
@ -240,52 +237,63 @@ class ViewPoll(PollFormView):
|
||||
return context
|
||||
|
||||
def get_success_url(self):
|
||||
return_url = ''
|
||||
if not 'apply' in self.request.POST:
|
||||
return reverse('assignment_view', args=[self.poll.assignment.id])
|
||||
return ''
|
||||
return_url = reverse('assignment_detail', args=[self.poll.assignment.id])
|
||||
return return_url
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
def set_publish_status(request, poll_id):
|
||||
class SetPublishStatusView(SingleObjectMixin, RedirectView):
|
||||
model = AssignmentPoll
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
url_name = 'assignment_list'
|
||||
allow_ajax = True
|
||||
|
||||
def get_ajax_context(self):
|
||||
return {'published': self.object.published}
|
||||
|
||||
def pre_redirect(self, *args, **kwargs):
|
||||
try:
|
||||
poll = AssignmentPoll.objects.get(pk=poll_id)
|
||||
if poll.published:
|
||||
poll.set_published(False)
|
||||
self.object = self.get_object()
|
||||
except self.model.DoesNotExist:
|
||||
messages.error(self.request, _('Ballot ID %d does not exist.') %
|
||||
int(kwargs['poll_id']))
|
||||
return
|
||||
if self.object.published:
|
||||
self.object.set_published(False)
|
||||
else:
|
||||
poll.set_published(True)
|
||||
except AssignmentPoll.DoesNotExist:
|
||||
messages.error(request, _('Ballot ID %d does not exist.') % int(poll_id))
|
||||
return redirect(reverse('assignment_overview'))
|
||||
|
||||
if request.is_ajax():
|
||||
return ajax_request({'published': poll.published})
|
||||
|
||||
if poll.published:
|
||||
messages.success(request, _("Ballot successfully published."))
|
||||
self.object.set_published(True)
|
||||
if self.object.published:
|
||||
messages.success(self.request, _("Ballot successfully published."))
|
||||
else:
|
||||
messages.success(request, _("Ballot successfully unpublished."))
|
||||
return redirect(reverse('assignment_view', args=[poll.assignment.id]))
|
||||
messages.success(self.request, _("Ballot successfully unpublished."))
|
||||
|
||||
|
||||
@permission_required('assignment.can_manage_assignment')
|
||||
def set_elected(request, assignment_id, user_id, elected=True):
|
||||
assignment = Assignment.objects.get(pk=assignment_id)
|
||||
person = get_person(user_id)
|
||||
assignment.set_elected(person, elected)
|
||||
class SetElectedView(SingleObjectMixin, RedirectView):
|
||||
model = Assignment
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
url_name = 'assignment_detail'
|
||||
allow_ajax = True
|
||||
|
||||
if request.is_ajax():
|
||||
if elected:
|
||||
link = reverse('assignment_user_not_elected', args=[assignment.id, person.person_id])
|
||||
def pre_redirect(self, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.person = get_person(kwargs['user_id'])
|
||||
self.elected = kwargs['elected']
|
||||
self.object.set_elected(self.person, self.elected)
|
||||
|
||||
def get_ajax_context(self):
|
||||
if self.elected:
|
||||
link = reverse('assignment_user_not_elected',
|
||||
args=[self.object.id, self.person.person_id])
|
||||
text = _('not elected')
|
||||
else:
|
||||
link = reverse('assignment_user_elected', args=[assignment.id, person.person_id])
|
||||
link = reverse('assignment_user_elected',
|
||||
args=[self.self.object.id, self.person.person_id])
|
||||
text = _('elected')
|
||||
return ajax_request({'elected': elected, 'link': link, 'text': text})
|
||||
|
||||
return redirect(reverse('assignment_view', args=[assignment_id]))
|
||||
return {'elected': self.elected, 'link': link, 'text': text}
|
||||
|
||||
|
||||
class AssignmentPollDelete(DeleteView):
|
||||
class AssignmentPollDeleteView(DeleteView):
|
||||
"""
|
||||
Delete an assignment poll object.
|
||||
"""
|
||||
@ -294,17 +302,17 @@ class AssignmentPollDelete(DeleteView):
|
||||
|
||||
def pre_redirect(self, request, *args, **kwargs):
|
||||
self.set_assignment()
|
||||
super(AssignmentPollDelete, self).pre_redirect(request, *args, **kwargs)
|
||||
super(AssignmentPollDeleteView, self).pre_redirect(request, *args, **kwargs)
|
||||
|
||||
def pre_post_redirect(self, request, *args, **kwargs):
|
||||
self.set_assignment()
|
||||
super(AssignmentPollDelete, self).pre_post_redirect(request, *args, **kwargs)
|
||||
super(AssignmentPollDeleteView, self).pre_post_redirect(request, *args, **kwargs)
|
||||
|
||||
def set_assignment(self):
|
||||
self.assignment = self.object.assignment
|
||||
|
||||
def get_redirect_url(self, **kwargs):
|
||||
return reverse('assignment_view', args=[self.assignment.id])
|
||||
return reverse('assignment_detail', args=[self.assignment.id])
|
||||
|
||||
def get_success_message(self):
|
||||
return _('Ballot was successfully deleted.')
|
||||
@ -316,7 +324,7 @@ class AssignmentPDF(PDFView):
|
||||
|
||||
def get_filename(self):
|
||||
try:
|
||||
assignment_id = self.kwargs['assignment_id']
|
||||
assignment_id = self.kwargs['pk']
|
||||
assignment = Assignment.objects.get(id=assignment_id)
|
||||
filename = u'%s-%s' % (
|
||||
_("Assignment"),
|
||||
@ -327,7 +335,7 @@ class AssignmentPDF(PDFView):
|
||||
|
||||
def append_to_pdf(self, story):
|
||||
try:
|
||||
assignment_id = self.kwargs['assignment_id']
|
||||
assignment_id = self.kwargs['pk']
|
||||
except KeyError:
|
||||
assignment_id = None
|
||||
if assignment_id is None: # print all assignments
|
||||
@ -455,13 +463,16 @@ class AssignmentPDF(PDFView):
|
||||
data_votes.append(footrow_two)
|
||||
|
||||
table_votes = Table(data_votes)
|
||||
table_votes.setStyle(TableStyle([
|
||||
table_votes.setStyle(
|
||||
TableStyle([
|
||||
('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
|
||||
('VALIGN', (0, 0), (-1, -1), 'TOP'),
|
||||
('LINEABOVE', (0, 0), (-1, 0), 2, colors.black),
|
||||
('LINEABOVE', (0, 1), (-1, 1), 1, colors.black),
|
||||
('LINEBELOW', (0, -1), (-1, -1), 2, colors.black),
|
||||
('ROWBACKGROUNDS', (0, 1), (-1, -1), (colors.white, (.9, .9, .9)))]))
|
||||
('ROWBACKGROUNDS', (0, 1), (-1, -1), (colors.white, (.9, .9, .9)))
|
||||
])
|
||||
)
|
||||
|
||||
# table
|
||||
data = []
|
||||
@ -482,9 +493,9 @@ class AssignmentPDF(PDFView):
|
||||
story.append(Spacer(0, 1 * cm))
|
||||
|
||||
# text
|
||||
story.append(Paragraph(
|
||||
"%s" % assignment.description.replace('\r\n',
|
||||
'<br/>'), stylesheet['Paragraph']))
|
||||
story.append(
|
||||
Paragraph("%s" % assignment.description.replace('\r\n', '<br/>'),
|
||||
stylesheet['Paragraph']))
|
||||
|
||||
|
||||
class CreateRelatedAgendaItemView(_CreateRelatedAgendaItemView):
|
||||
@ -536,8 +547,8 @@ class AssignmentPollPDF(PDFView):
|
||||
"%d available post", "%d available posts",
|
||||
self.poll.assignment.posts) % self.poll.assignment.posts
|
||||
cell.append(Paragraph(
|
||||
"%s, %s, %s" % (ballot_string, candidate_string,
|
||||
available_posts_string), stylesheet['Ballot_description']))
|
||||
"%s, %s, %s" % (ballot_string, candidate_string, available_posts_string),
|
||||
stylesheet['Ballot_description']))
|
||||
cell.append(Spacer(0, 0.4 * cm))
|
||||
|
||||
data = []
|
||||
@ -624,7 +635,7 @@ def register_tab(request):
|
||||
return Tab(
|
||||
title=_('Elections'),
|
||||
app='assignment',
|
||||
url=reverse('assignment_overview'),
|
||||
url=reverse('assignment_list'),
|
||||
permission=(
|
||||
request.user.has_perm('assignment.can_see_assignment') or
|
||||
request.user.has_perm('assignment.can_nominate_other') or
|
||||
|
Loading…
Reference in New Issue
Block a user