cleanup the assignment app

This commit is contained in:
Oskar Hahn 2012-07-10 11:27:06 +02:00
parent 81fc7ae560
commit 01f0823ed7
5 changed files with 181 additions and 120 deletions

View File

@ -29,7 +29,7 @@ from reportlab.platypus import (SimpleDocTemplate, PageBreak, Paragraph, Spacer,
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import transaction from django.db import transaction

View File

@ -11,35 +11,39 @@
""" """
from django import forms from django import forms
from django.forms import ModelForm, Form, ModelChoiceField, Select from django.utils.translation import ugettext_lazy as _, ugettext_noop
from utils.forms import CssClassMixin from utils.forms import CssClassMixin
from utils.translation_ext import ugettext as _
from participant.models import Profile from participant.models import Profile
from assignment.models import Assignment from assignment.models import Assignment
class AssignmentForm(ModelForm, CssClassMixin): class AssignmentForm(forms.ModelForm, CssClassMixin):
posts = forms.IntegerField(min_value=1, label=_("Number of available posts")) posts = forms.IntegerField(min_value=1,
label=_("Number of available posts"))
class Meta: class Meta:
model = Assignment model = Assignment
exclude = ('status', 'profile', 'elected') exclude = ('status', 'profile', 'elected')
class AssignmentRunForm(Form, CssClassMixin): class AssignmentRunForm(forms.Form, CssClassMixin):
candidate = ModelChoiceField( candidate = forms.ModelChoiceField(
widget=Select(attrs={'class': 'medium-input'}), widget=forms.Select(attrs={'class': 'medium-input'}),
queryset=Profile.objects.all().order_by('user__first_name'), queryset=Profile.objects.all().order_by('user__first_name'),
label=_("Nominate a participant"), label=_("Nominate a participant"),
) )
class ConfigForm(Form, CssClassMixin): class ConfigForm(forms.Form, CssClassMixin):
assignment_publish_winner_results_only = forms.BooleanField( assignment_publish_winner_results_only = forms.BooleanField(
required=False, required=False,
label=_("Only publish voting results for selected winners (Projector view only)") label=_("Only publish voting results for selected winners "
"(Projector view only)")
) )
assignment_pdf_ballot_papers_selection = forms.ChoiceField(widget=forms.Select(), assignment_pdf_ballot_papers_selection = forms.ChoiceField(
widget=forms.Select(),
required=False, required=False,
label=_("Number of ballot papers (selection)"), label=_("Number of ballot papers (selection)"),
choices=( choices=(

View File

@ -10,17 +10,21 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.db import models
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _, ugettext_noop
from config.models import config from openslides.config.models import config
from openslides.config.signals import default_config_value
from participant.models import Profile from openslides.projector.api import register_slidemodel
from openslides.projector.projector import SlideMixin
from projector.projector import SlideMixin from openslides.participant.models import Profile
from projector.api import register_slidemodel
from poll.models import BasePoll, CountInvalid, CountVotesCast, BaseOption, PublishPollMixin from openslides.poll.models import (BasePoll, CountInvalid, CountVotesCast,
from utils.translation_ext import ugettext as _ BaseOption, PublishPollMixin)
from agenda.models import Item from agenda.models import Item
@ -34,11 +38,15 @@ class Assignment(models.Model, SlideMixin):
) )
name = models.CharField(max_length=100, verbose_name=_("Name")) name = models.CharField(max_length=100, verbose_name=_("Name"))
description = models.TextField(null=True, blank=True, verbose_name=_("Description")) description = models.TextField(null=True, blank=True,
posts = models.PositiveSmallIntegerField(verbose_name=_("Number of available posts")) verbose_name=_("Description"))
polldescription = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Short description (for ballot paper)")) posts = models.PositiveSmallIntegerField(
profile = models.ManyToManyField(Profile, null=True, blank=True) # Rename it in candidate verbose_name=_("Number of available posts"))
elected = models.ManyToManyField(Profile, null=True, blank=True, related_name='elected_set') polldescription = models.CharField(max_length=100, null=True, blank=True,
verbose_name=_("Short description (for ballot paper)"))
profile = models.ManyToManyField(Profile, null=True, blank=True)
elected = models.ManyToManyField(Profile, null=True, blank=True,
related_name='elected_set')
status = models.CharField(max_length=3, choices=STATUS, default='sea') status = models.CharField(max_length=3, choices=STATUS, default='sea')
def set_status(self, status): def set_status(self, status):
@ -50,7 +58,8 @@ class Assignment(models.Model, SlideMixin):
if error: if error:
raise NameError(_('%s is not a valid status.') % status) raise NameError(_('%s is not a valid status.') % status)
if self.status == status: if self.status == status:
raise NameError(_('The assignment status is already %s.') % self.status) raise NameError(_('The assignment status is already %s.')
% self.status)
self.status = status self.status = status
self.save() self.save()
@ -159,7 +168,8 @@ class Assignment(models.Model, SlideMixin):
data['title'] = self.name data['title'] = self.name
data['polls'] = self.poll_set.filter(published=True) data['polls'] = self.poll_set.filter(published=True)
data['vote_results'] = self.vote_results(only_published=True) data['vote_results'] = self.vote_results(only_published=True)
data['assignment_publish_winner_results_only'] = config['assignment_publish_winner_results_only'] data['assignment_publish_winner_results_only'] = \
config['assignment_publish_winner_results_only']
data['template'] = 'projector/Assignment.html' data['template'] = 'projector/Assignment.html'
return data return data
@ -176,10 +186,11 @@ class Assignment(models.Model, SlideMixin):
class Meta: class Meta:
permissions = ( permissions = (
('can_see_assignment', _("Can see assignment", fixstr=True)), ('can_see_assignment', ugettext_noop("Can see assignment")),
('can_nominate_other', _("Can nominate another person", fixstr=True)), ('can_nominate_other',
('can_nominate_self', _("Can nominate themselves", fixstr=True)), ugettext_noop("Can nominate another person")),
('can_manage_assignment', _("Can manage assignment", fixstr=True)), ('can_nominate_self', ugettext_noop("Can nominate themselves")),
('can_manage_assignment', ugettext_noop("Can manage assignment")),
) )
register_slidemodel(Assignment) register_slidemodel(Assignment)
@ -209,15 +220,16 @@ class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
self.yesnoabstain = True self.yesnoabstain = True
else: else:
# candidates <= available posts -> yes/no/abstain # candidates <= available posts -> yes/no/abstain
if self.assignment.candidates.count() <= self.assignment.posts - self.assignment.elected.count(): if self.assignment.candidates.count() <= (self.assignment.posts
- self.assignment.elected.count()):
self.yesnoabstain = True self.yesnoabstain = True
else: else:
self.yesnoabstain = False self.yesnoabstain = False
self.save() self.save()
if self.yesnoabstain: if self.yesnoabstain:
return [_('Yes', fixstr=True), _('No', fixstr=True), _('Abstain', fixstr=True)] return [_('Yes'), _('No'), _('Abstain')]
else: else:
return [_('Votes', fixstr=True)] return [_('Votes')]
def append_pollform_fields(self, fields): def append_pollform_fields(self, fields):
CountInvalid.append_pollform_fields(self, fields) CountInvalid.append_pollform_fields(self, fields)
@ -237,8 +249,6 @@ class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
return _("Ballot %d") % self.get_ballot() return _("Ballot %d") % self.get_ballot()
from django.dispatch import receiver
from openslides.config.signals import default_config_value
@receiver(default_config_value, dispatch_uid="assignment_default_config") @receiver(default_config_value, dispatch_uid="assignment_default_config")

View File

@ -10,7 +10,7 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.conf.urls.defaults import * from django.conf.urls.defaults import url, patterns
from assignment.views import (ViewPoll, AssignmentPDF, AssignmentPollPDF, from assignment.views import (ViewPoll, AssignmentPDF, AssignmentPollPDF,
AssignmentPollDelete, CreateAgendaItem) AssignmentPollDelete, CreateAgendaItem)
@ -21,41 +21,41 @@ urlpatterns = patterns('assignment.views',
name='assignment_overview', name='assignment_overview',
), ),
url(r'^(?P<assignment_id>\d+)$', url(r'^(?P<assignment_id>\d+)/$',
'view', 'view',
name='assignment_view'), name='assignment_view'),
url(r'^new$', url(r'^new/$',
'edit', 'edit',
name='assignment_new', name='assignment_new',
), ),
url(r'^(?P<assignment_id>\d+)/edit$', url(r'^(?P<assignment_id>\d+)/edit/$',
'edit', 'edit',
name='assignment_edit', name='assignment_edit',
), ),
url(r'^(?P<assignment_id>\d+)/del$', url(r'^(?P<assignment_id>\d+)/del/$',
'delete', 'delete',
name='assignment_delete', name='assignment_delete',
), ),
url(r'^(?P<assignment_id>\d+)/setstatus/(?P<status>[a-z]{3})$', url(r'^(?P<assignment_id>\d+)/setstatus/(?P<status>[a-z]{3})/$',
'set_status', 'set_status',
name='assignment_set_status', name='assignment_set_status',
), ),
url(r'^(?P<assignment_id>\d+)/run$', url(r'^(?P<assignment_id>\d+)/run/$',
'run', 'run',
name='assignment_run', name='assignment_run',
), ),
url(r'^(?P<assignment_id>\d+)/delrun$', url(r'^(?P<assignment_id>\d+)/delrun/$',
'delrun', 'delrun',
name='assignment_delrun', name='assignment_delrun',
), ),
url(r'^(?P<assignment_id>\d+)/delother/(?P<profile_id>\d+)$', url(r'^(?P<assignment_id>\d+)/delother/(?P<profile_id>\d+)/$',
'delother', 'delother',
name='assignment_delother', name='assignment_delother',
), ),
@ -80,22 +80,22 @@ urlpatterns = patterns('assignment.views',
name='print_assignment', name='print_assignment',
), ),
url(r'^(?P<assignment_id>\d+)/print$', url(r'^(?P<assignment_id>\d+)/print/$',
AssignmentPDF.as_view(), AssignmentPDF.as_view(),
name='print_assignment', name='print_assignment',
), ),
url(r'^(?P<assignment_id>\d+)/gen_poll$', url(r'^(?P<assignment_id>\d+)/gen_poll/$',
'gen_poll', 'gen_poll',
name='assignment_gen_poll', name='assignment_gen_poll',
), ),
url(r'^poll/(?P<poll_id>\d+)$', url(r'^poll/(?P<poll_id>\d+)/$',
ViewPoll.as_view(), ViewPoll.as_view(),
name='assignment_poll_view', name='assignment_poll_view',
), ),
url(r'^poll/(?P<pk>\d+)/del$', url(r'^poll/(?P<pk>\d+)/del/$',
AssignmentPollDelete.as_view(), AssignmentPollDelete.as_view(),
name='assignment_poll_delete', name='assignment_poll_delete',
), ),
@ -105,13 +105,13 @@ urlpatterns = patterns('assignment.views',
name='assignment_poll_publish_status', name='assignment_poll_publish_status',
), ),
url(r'^(?P<assignment_id>\d+)/elected/(?P<profile_id>\d+)$', url(r'^(?P<assignment_id>\d+)/elected/(?P<profile_id>\d+)/$',
'set_elected', 'set_elected',
{'elected': True}, {'elected': True},
name='assignment_user_elected', name='assignment_user_elected',
), ),
url(r'^(?P<assignment_id>\d+)/notelected/(?P<profile_id>\d+)$', url(r'^(?P<assignment_id>\d+)/notelected/(?P<profile_id>\d+)/$',
'set_elected', 'set_elected',
{'elected': False}, {'elected': False},
name='assignment_user_not_elected', name='assignment_user_not_elected',

View File

@ -13,35 +13,37 @@
import os import os
from reportlab.lib import colors from reportlab.lib import colors
from reportlab.platypus import (SimpleDocTemplate, PageBreak, Paragraph,
Spacer, Table, TableStyle)
from reportlab.lib.units import cm from reportlab.lib.units import cm
from reportlab.platypus import SimpleDocTemplate, PageBreak, Paragraph, Spacer, Table, TableStyle
from django.shortcuts import redirect from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.utils.translation import ungettext, ugettext as _ from django.shortcuts import redirect
from django.utils.translation import ungettext, ugettext_lazy as _
from config.models import config
from settings import SITE_ROOT
from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form, ajax_request
from utils.pdf import stylesheet from utils.pdf import stylesheet
from utils.views import FormView, DeleteView, PDFView, RedirectView
from utils.template import Tab from utils.template import Tab
from utils.translation_ext import ugettext from utils.utils import (template, permission_required, gen_confirm_form,
del_confirm_form, ajax_request)
from utils.views import FormView, DeleteView, PDFView, RedirectView
from projector.projector import Widget from openslides.config.models import config
from openslides.participant.models import Profile
from poll.views import PollFormView from openslides.projector.projector import Widget
from agenda.models import Item from openslides.poll.views import PollFormView
from assignment.models import Assignment, AssignmentPoll, AssignmentOption from openslides.agenda.models import Item
from assignment.forms import AssignmentForm, AssignmentRunForm, ConfigForm
from participant.models import Profile from openslides.assignment.models import (Assignment, AssignmentPoll,
AssignmentOption)
from openslides.assignment.forms import (AssignmentForm, AssignmentRunForm,
ConfigForm)
@permission_required('assignment.can_see_assignment') @permission_required('assignment.can_see_assignment')
@ -307,7 +309,8 @@ class AssignmentPDF(PDFView):
try: try:
assignment_id = self.kwargs['assignment_id'] assignment_id = self.kwargs['assignment_id']
assignment = Assignment.objects.get(id=assignment_id) assignment = Assignment.objects.get(id=assignment_id)
filename = u'%s-%s' % (_("Assignment"), assignment.name.replace(' ','_')) filename = u'%s-%s' % (_("Assignment"),
assignment.name.replace(' ','_'))
except: except:
filename = _("Elections") filename = _("Elections")
return filename return filename
@ -322,15 +325,18 @@ class AssignmentPDF(PDFView):
story.append(Paragraph(title, stylesheet['Heading1'])) story.append(Paragraph(title, stylesheet['Heading1']))
preamble = config["assignment_pdf_preamble"] preamble = config["assignment_pdf_preamble"]
if preamble: if preamble:
story.append(Paragraph("%s" % preamble.replace('\r\n','<br/>'), stylesheet['Paragraph'])) story.append(Paragraph("%s" % preamble.replace('\r\n','<br/>'),
stylesheet['Paragraph']))
story.append(Spacer(0,0.75*cm)) story.append(Spacer(0,0.75*cm))
assignments = Assignment.objects.order_by('name') assignments = Assignment.objects.order_by('name')
if not assignments: # No assignments existing if not assignments: # No assignments existing
story.append(Paragraph(_("No assignments available."), stylesheet['Heading3'])) story.append(Paragraph(_("No assignments available."),
stylesheet['Heading3']))
else: # Print all assignments else: # Print all assignments
# List of assignments # List of assignments
for assignment in assignments: for assignment in assignments:
story.append(Paragraph(assignment.name, stylesheet['Heading3'])) story.append(Paragraph(assignment.name,
stylesheet['Heading3']))
# Assignment details (each assignment on single page) # Assignment details (each assignment on single page)
for assignment in assignments: for assignment in assignments:
story.append(PageBreak()) story.append(PageBreak())
@ -343,22 +349,28 @@ class AssignmentPDF(PDFView):
def get_assignment(self, assignment, story): def get_assignment(self, assignment, story):
# title # title
story.append(Paragraph(_("Election")+": %s" % assignment.name, stylesheet['Heading1'])) story.append(Paragraph(_("Election")+": %s" % assignment.name,
stylesheet['Heading1']))
story.append(Spacer(0,0.5*cm)) story.append(Spacer(0,0.5*cm))
# posts # posts
cell1a = [] cell1a = []
cell1a.append(Paragraph("<font name='Ubuntu-Bold'>%s:</font>" % _("Number of available posts"), stylesheet['Bold'])) cell1a.append(Paragraph("<font name='Ubuntu-Bold'>%s:</font>" %
_("Number of available posts"), stylesheet['Bold']))
cell1b = [] cell1b = []
cell1b.append(Paragraph(str(assignment.posts), stylesheet['Paragraph'])) cell1b.append(Paragraph(str(assignment.posts), stylesheet['Paragraph']))
# candidates # candidates
cell2a = [] cell2a = []
cell2a.append(Paragraph("<font name='Ubuntu-Bold'>%s:</font><seqreset id='counter'>" % _("Candidates"), stylesheet['Heading4'])) cell2a.append(Paragraph("<font name='Ubuntu-Bold'>%s:</font><seqreset" \
" id='counter'>" % _("Candidates"), stylesheet['Heading4']))
cell2b = [] cell2b = []
for c in assignment.profile.all(): for candidate in assignment.profile.all():
cell2b.append(Paragraph("<seq id='counter'/>.&nbsp; %s" % unicode(c), stylesheet['Signaturefield'])) cell2b.append(Paragraph("<seq id='counter'/>.&nbsp; %s" % candidate,
stylesheet['Signaturefield']))
if assignment.status == "sea": if assignment.status == "sea":
for x in range(0, 2 * assignment.posts): for x in range(0, 2 * assignment.posts):
cell2b.append(Paragraph("<seq id='counter'/>.&nbsp; __________________________________________",stylesheet['Signaturefield'])) cell2b.append(Paragraph("<seq id='counter'/>.&nbsp; "
"__________________________________________",
stylesheet['Signaturefield']))
cell2b.append(Spacer(0,0.2*cm)) cell2b.append(Spacer(0,0.2*cm))
# Vote results # Vote results
@ -371,12 +383,15 @@ class AssignmentPDF(PDFView):
# Left side # Left side
cell3a = [] cell3a = []
cell3a.append(Paragraph("%s:" % (_("Vote results")), stylesheet['Heading4'])) cell3a.append(Paragraph("%s:" % (_("Vote results")),
stylesheet['Heading4']))
if polls.count() == 1: if polls.count() == 1:
cell3a.append(Paragraph("%s %s" % (polls.count(), _("ballot")), stylesheet['Normal'])) cell3a.append(Paragraph("%s %s" % (polls.count(), _("ballot")),
stylesheet['Normal']))
elif polls.count() > 1: elif polls.count() > 1:
cell3a.append(Paragraph("%s %s" % (polls.count(), _("ballots")), stylesheet['Normal'])) cell3a.append(Paragraph("%s %s" % (polls.count(), _("ballots")),
stylesheet['Normal']))
# Add table head row # Add table head row
headrow = [] headrow = []
@ -443,18 +458,19 @@ class AssignmentPDF(PDFView):
data.append(['', '* = '+_('elected')]) data.append(['', '* = '+_('elected')])
else: else:
data.append([cell2a, cell2b]) data.append([cell2a, cell2b])
data.append([Spacer(0,0.2*cm),'']) data.append([Spacer(0, 0.2 * cm), ''])
t=Table(data) t=Table(data)
t._argW[0]=4.5*cm t._argW[0] = 4.5 * cm
t._argW[1]=11*cm t._argW[1] = 11 * cm
t.setStyle(TableStyle([ ('BOX', (0,0), (-1,-1), 1, colors.black), t.setStyle(TableStyle([ ('BOX', (0,0), (-1, -1), 1, colors.black),
('VALIGN', (0,0), (-1,-1), 'TOP'), ('VALIGN', (0, 0), (-1, -1), 'TOP'),
])) ]))
story.append(t) story.append(t)
story.append(Spacer(0,1*cm)) story.append(Spacer(0, 1 * cm))
# text # 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 CreateAgendaItem(RedirectView): class CreateAgendaItem(RedirectView):
@ -478,25 +494,35 @@ class AssignmentPollPDF(PDFView):
return super(AssignmentPollPDF, self).get(request, *args, **kwargs) return super(AssignmentPollPDF, self).get(request, *args, **kwargs)
def get_filename(self): def get_filename(self):
filename = u'%s-%s-#%s' % (_("Election"), self.poll.assignment.name.replace(' ','_'), 1)#self.poll.get_ballot()) filename = u'%s-%s-#%s' % (_("Election"), self.poll.assignment.name
.replace(' ', '_'), 1)
return filename return filename
def get_template(self, buffer): def get_template(self, buffer):
return SimpleDocTemplate(buffer, topMargin=-6, bottomMargin=-6, leftMargin=0, rightMargin=0, showBoundary=False) return SimpleDocTemplate(buffer, topMargin=-6, bottomMargin=-6,
leftMargin=0, rightMargin=0, showBoundary=False)
def build_document(self, pdf_document, story): def build_document(self, pdf_document, story):
pdf_document.build(story) pdf_document.build(story)
def append_to_pdf(self, story): def append_to_pdf(self, story):
imgpath = os.path.join(SITE_ROOT, 'static/images/circle.png') imgpath = os.path.join(settings.SITE_ROOT, 'static/images/circle.png')
circle = "<img src='%s' width='15' height='15'/>&nbsp;&nbsp;" % imgpath circle = "<img src='%s' width='15' height='15'/>&nbsp;&nbsp;" % imgpath
cell = [] cell = []
cell.append(Spacer(0,0.8*cm)) cell.append(Spacer(0,0.8*cm))
cell.append(Paragraph(_("Election") + ": " + self.poll.assignment.name, stylesheet['Ballot_title'])) cell.append(Paragraph(_("Election") + ": " + self.poll.assignment.name,
cell.append(Paragraph(self.poll.assignment.polldescription, stylesheet['Ballot_subtitle'])) stylesheet['Ballot_title']))
cell.append(Paragraph(self.poll.assignment.polldescription,
stylesheet['Ballot_subtitle']))
options = self.poll.get_options().order_by('candidate') options = self.poll.get_options().order_by('candidate')
cell.append(Paragraph(str(self.poll.get_ballot())+". "+_("ballot")+", "+str(len(options))+" "+ ungettext("candidate", "candidates", len(options))+", "+str(self.poll.assignment.posts)+" "+_("available posts"), stylesheet['Ballot_description']))
cell.append(Spacer(0,0.4*cm)) ballot_string = _("%d. ballot") % self.poll.get_ballot()
candidate_string = ungettext("%d candidate", "%d candidates",
len(options)) % len(options)
available_posts_string = _("%d available posts") % self.poll.assignment.posts
cell.append(Paragraph("%s, %s, %s" % (ballot_string, candidate_string,
available_posts_string), stylesheet['Ballot_description']))
cell.append(Spacer(0, 0.4 * cm))
data= [] data= []
# get ballot papers config values # get ballot papers config values
@ -516,12 +542,17 @@ class AssignmentPollPDF(PDFView):
if self.poll.yesnoabstain: if self.poll.yesnoabstain:
for option in options: for option in options:
candidate = option.candidate candidate = option.candidate
cell.append(Paragraph(candidate.user.get_full_name(), stylesheet['Ballot_option_name'])) cell.append(Paragraph(candidate.user.get_full_name(),
stylesheet['Ballot_option_name']))
if candidate.group: if candidate.group:
cell.append(Paragraph("(%s)" % candidate.group, stylesheet['Ballot_option_group'])) cell.append(Paragraph("(%s)" % candidate.group,
stylesheet['Ballot_option_group']))
else: else:
cell.append(Paragraph("&nbsp;", stylesheet['Ballot_option_group'])) cell.append(Paragraph("&nbsp;",
cell.append(Paragraph(circle+_("Yes")+"&nbsp; &nbsp; &nbsp; "+circle+_("No")+"&nbsp; &nbsp; &nbsp; "+circle+_("Abstention"), stylesheet['Ballot_option_YNA'])) stylesheet['Ballot_option_group']))
cell.append(Paragraph(circle + _("Yes") + "&nbsp; " * 3 + circle
+ _("No") + "&nbsp; " * 3 + circle+ _("Abstention"),
stylesheet['Ballot_option_YNA']))
# print ballot papers # print ballot papers
for user in xrange(number / 2): for user in xrange(number / 2):
data.append([cell, cell]) data.append([cell, cell])
@ -529,19 +560,22 @@ class AssignmentPollPDF(PDFView):
if rest: if rest:
data.append([cell, '']) data.append([cell, ''])
if len(options) <= 2: if len(options) <= 2:
t = Table(data, 10.5*cm, 7.42*cm) t = Table(data, 10.5 * cm, 7.42 * cm)
elif len(options) <= 5: elif len(options) <= 5:
t = Table(data, 10.5*cm, 14.84*cm) t = Table(data, 10.5 * cm, 14.84 * cm)
else: else:
t = Table(data, 10.5*cm, 29.7*cm) t = Table(data, 10.5 * cm, 29.7 * cm)
else: else:
for option in options: for option in options:
candidate = option.candidate candidate = option.candidate
cell.append(Paragraph(circle + candidate.user.get_full_name(), stylesheet['Ballot_option_name'])) cell.append(Paragraph(circle + candidate.user.get_full_name(),
stylesheet['Ballot_option_name']))
if candidate.group: if candidate.group:
cell.append(Paragraph("(%s)" % candidate.group, stylesheet['Ballot_option_group_right'])) cell.append(Paragraph("(%s)" % candidate.group,
stylesheet['Ballot_option_group_right']))
else: else:
cell.append(Paragraph("&nbsp;", stylesheet['Ballot_option_group_right'])) cell.append(Paragraph("&nbsp;",
stylesheet['Ballot_option_group_right']))
# print ballot papers # print ballot papers
for user in xrange(number / 2): for user in xrange(number / 2):
data.append([cell, cell]) data.append([cell, cell])
@ -549,15 +583,15 @@ class AssignmentPollPDF(PDFView):
if rest: if rest:
data.append([cell, '']) data.append([cell, ''])
if len(options) <= 4: if len(options) <= 4:
t = Table(data, 10.5*cm, 7.42*cm) t = Table(data, 10.5 * cm, 7.42 * cm)
elif len(options) <= 8: elif len(options) <= 8:
t = Table(data, 10.5*cm, 14.84*cm) t = Table(data, 10.5 * cm, 14.84 * cm)
else: else:
t = Table(data, 10.5*cm, 29.7*cm) t = Table(data, 10.5 * cm, 29.7 * cm)
t.setStyle(TableStyle([ ('GRID', (0,0), (-1,-1), 0.25, colors.grey), t.setStyle(TableStyle([('GRID', (0, 0), (-1, -1), 0.25, colors.grey),
('VALIGN', (0,0), (-1,-1), 'TOP'), ('VALIGN', (0, 0), (-1, -1), 'TOP'),
])) ]))
story.append(t) story.append(t)
@ -568,12 +602,16 @@ class Config(FormView):
def get_initial(self): def get_initial(self):
return { return {
'assignment_publish_winner_results_only': config['assignment_publish_winner_results_only'], 'assignment_publish_winner_results_only':
'assignment_pdf_ballot_papers_selection': config['assignment_pdf_ballot_papers_selection'], config['assignment_publish_winner_results_only'],
'assignment_pdf_ballot_papers_number': config['assignment_pdf_ballot_papers_number'], 'assignment_pdf_ballot_papers_selection':
config['assignment_pdf_ballot_papers_selection'],
'assignment_pdf_ballot_papers_number':
config['assignment_pdf_ballot_papers_number'],
'assignment_pdf_title': config['assignment_pdf_title'], 'assignment_pdf_title': config['assignment_pdf_title'],
'assignment_pdf_preamble': config['assignment_pdf_preamble'], 'assignment_pdf_preamble': config['assignment_pdf_preamble'],
'assignment_poll_vote_values': config['assignment_poll_vote_values'], 'assignment_poll_vote_values':
config['assignment_poll_vote_values'],
} }
def form_valid(self, form): def form_valid(self, form):
@ -581,21 +619,30 @@ class Config(FormView):
config['assignment_publish_winner_results_only'] = True config['assignment_publish_winner_results_only'] = True
else: else:
config['assignment_publish_winner_results_only'] = False config['assignment_publish_winner_results_only'] = False
config['assignment_pdf_ballot_papers_selection'] = form.cleaned_data['assignment_pdf_ballot_papers_selection'] config['assignment_pdf_ballot_papers_selection'] = \
config['assignment_pdf_ballot_papers_number'] = form.cleaned_data['assignment_pdf_ballot_papers_number'] form.cleaned_data['assignment_pdf_ballot_papers_selection']
config['assignment_pdf_title'] = form.cleaned_data['assignment_pdf_title'] config['assignment_pdf_ballot_papers_number'] = \
config['assignment_pdf_preamble'] = form.cleaned_data['assignment_pdf_preamble'] form.cleaned_data['assignment_pdf_ballot_papers_number']
config['assignment_poll_vote_values'] = form.cleaned_data['assignment_poll_vote_values'] config['assignment_pdf_title'] = \
messages.success(self.request, _('Election settings successfully saved.')) form.cleaned_data['assignment_pdf_title']
config['assignment_pdf_preamble'] = \
form.cleaned_data['assignment_pdf_preamble']
config['assignment_poll_vote_values'] = \
form.cleaned_data['assignment_poll_vote_values']
messages.success(self.request,
_('Election settings successfully saved.'))
return super(Config, self).form_valid(form) return super(Config, self).form_valid(form)
def register_tab(request): def register_tab(request):
selected = True if request.path.startswith('/assignment/') else False selected = request.path.startswith('/assignment/')
return Tab( return Tab(
title=_('Elections'), title=_('Elections'),
url=reverse('assignment_overview'), url=reverse('assignment_overview'),
permission=request.user.has_perm('assignment.can_see_assignment') or request.user.has_perm('assignment.can_nominate_other') or request.user.has_perm('assignment.can_nominate_self') or request.user.has_perm('assignment.can_manage_assignment'), permission=request.user.has_perm('assignment.can_see_assignment')
or request.user.has_perm('assignment.can_nominate_other')
or request.user.has_perm('assignment.can_nominate_self')
or request.user.has_perm('assignment.can_manage_assignment'),
selected=selected, selected=selected,
) )