commit
a4b671f0ac
@ -11,6 +11,7 @@
|
||||
"""
|
||||
|
||||
import random
|
||||
import os
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from reportlab.lib import colors
|
||||
@ -18,15 +19,21 @@ from reportlab.lib.units import cm
|
||||
from reportlab.platypus import (
|
||||
SimpleDocTemplate, PageBreak, Paragraph, Spacer, Table, TableStyle)
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.conf import settings
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.utils.pdf import stylesheet
|
||||
from .models import Motion
|
||||
|
||||
# Needed to count the delegates
|
||||
# TODO: find another way to do this.
|
||||
from openslides.participant.models import User
|
||||
|
||||
|
||||
def motions_to_pdf(pdf):
|
||||
"""Create a PDF with all motions."""
|
||||
|
||||
"""
|
||||
Create a PDF with all motions.
|
||||
"""
|
||||
motions = Motion.objects.all()
|
||||
all_motion_cover(pdf, motions)
|
||||
for motion in motions:
|
||||
@ -35,8 +42,9 @@ def motions_to_pdf(pdf):
|
||||
|
||||
|
||||
def motion_to_pdf(pdf, motion):
|
||||
"""Create a PDF for one motion."""
|
||||
|
||||
"""
|
||||
Create a PDF for one motion.
|
||||
"""
|
||||
pdf.append(Paragraph(_("Motion: %s") % motion.title, stylesheet['Heading1']))
|
||||
|
||||
motion_data = []
|
||||
@ -231,7 +239,9 @@ def convert_html_to_reportlab(pdf, text):
|
||||
|
||||
|
||||
def all_motion_cover(pdf, motions):
|
||||
"""Create a coverpage for all motions."""
|
||||
"""
|
||||
Create a coverpage for all motions.
|
||||
"""
|
||||
pdf.append(Paragraph(config["motion_pdf_title"], stylesheet['Heading1']))
|
||||
|
||||
preamble = config["motion_pdf_preamble"]
|
||||
@ -245,3 +255,46 @@ def all_motion_cover(pdf, motions):
|
||||
else:
|
||||
for motion in motions:
|
||||
pdf.append(Paragraph(motion.title, stylesheet['Heading3']))
|
||||
|
||||
|
||||
def motion_poll_to_pdf(pdf, poll):
|
||||
imgpath = os.path.join(settings.SITE_ROOT, 'static/img/circle.png')
|
||||
circle = "<img src='%s' width='15' height='15'/> " % imgpath
|
||||
cell = []
|
||||
cell.append(Spacer(0, 0.8 * cm))
|
||||
cell.append(Paragraph(_("Motion No. %s") % poll.motion.identifier, stylesheet['Ballot_title']))
|
||||
cell.append(Paragraph(poll.motion.title, stylesheet['Ballot_subtitle']))
|
||||
cell.append(Paragraph(_("%d. Vote") % poll.poll_number, stylesheet['Ballot_description']))
|
||||
cell.append(Spacer(0, 0.5 * cm))
|
||||
cell.append(Paragraph(circle + unicode(_("Yes")), stylesheet['Ballot_option']))
|
||||
cell.append(Paragraph(circle + unicode(_("No")), stylesheet['Ballot_option']))
|
||||
cell.append(Paragraph(circle + unicode(_("Abstention")), stylesheet['Ballot_option']))
|
||||
data = []
|
||||
# get ballot papers config values
|
||||
ballot_papers_selection = config["motion_pdf_ballot_papers_selection"]
|
||||
ballot_papers_number = config["motion_pdf_ballot_papers_number"]
|
||||
|
||||
# set number of ballot papers
|
||||
if ballot_papers_selection == "NUMBER_OF_DELEGATES":
|
||||
# TODO: get this number from persons
|
||||
number = User.objects.filter(type__iexact="delegate").count()
|
||||
elif ballot_papers_selection == "NUMBER_OF_ALL_PARTICIPANTS":
|
||||
# TODO: get the number from the persons
|
||||
number = int(User.objects.count())
|
||||
else: # ballot_papers_selection == "CUSTOM_NUMBER"
|
||||
number = int(ballot_papers_number)
|
||||
number = max(1, number)
|
||||
|
||||
# print ballot papers
|
||||
if number > 0:
|
||||
# TODO: try [cell, cell] * (number / 2)
|
||||
for user in xrange(number / 2):
|
||||
data.append([cell, cell])
|
||||
rest = number % 2
|
||||
if rest:
|
||||
data.append([cell, ''])
|
||||
t = Table(data, 10.5 * cm, 7.42 * cm)
|
||||
t.setStyle(TableStyle(
|
||||
[('GRID', (0, 0), (-1, -1), 0.25, colors.grey),
|
||||
('VALIGN', (0, 0), (-1, -1), 'TOP')]))
|
||||
pdf.append(t)
|
||||
|
@ -3,7 +3,7 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}
|
||||
{{ block.super }} - {% trans "Motion" %} {{ motion.identifier }}, {{ ballot }}. {% trans "Vote" %}
|
||||
{{ block.super }} - {% trans "Motion" %} {{ motion.identifier }}, {{ poll }}. {% trans "Vote" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -11,7 +11,7 @@
|
||||
{{ motion }}
|
||||
<br>
|
||||
<small>
|
||||
{% trans "Motion" %} {{ motion.identifier }}, {{ ballot }}. {% trans "Vote" %}
|
||||
{% trans "Motion" %} {{ motion.identifier }}, {{ poll }}. {% trans "Vote" %}
|
||||
</small>
|
||||
<small class="pull-right">
|
||||
<div class="btn-toolbar">
|
||||
@ -57,8 +57,7 @@
|
||||
|
||||
<!-- ballot paper button -->
|
||||
<p>
|
||||
{# TODO: create ballot paper instead of motion_detail_pdf ! #}
|
||||
<a href="{% url 'motion_detail_pdf' motion.id %}" class="btn">
|
||||
<a href="{% url 'motion_poll_pdf' motion.id poll.poll_number %}" class="btn">
|
||||
<i class="icon-print"></i> {% trans 'Ballot paper as PDF' %}
|
||||
</a>
|
||||
</p>
|
||||
|
@ -90,6 +90,11 @@ urlpatterns = patterns('openslides.motion.views',
|
||||
name='motion_poll_delete',
|
||||
),
|
||||
|
||||
url(r'^(?P<pk>\d+)/poll/(?P<poll_number>\d+)/pdf/$',
|
||||
'poll_pdf',
|
||||
name='motion_poll_pdf',
|
||||
),
|
||||
|
||||
url(r'^(?P<pk>\d+)/set_state/(?P<state>\d+)/$',
|
||||
'set_state',
|
||||
name='motion_set_state',
|
||||
|
@ -37,7 +37,7 @@ from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll,
|
||||
from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin,
|
||||
MotionDisableVersioningMixin, MotionCategoryMixin,
|
||||
MotionIdentifierMixin)
|
||||
from .pdf import motions_to_pdf, motion_to_pdf
|
||||
from .pdf import motions_to_pdf, motion_to_pdf, motion_poll_to_pdf
|
||||
|
||||
|
||||
class MotionListView(ListView):
|
||||
@ -422,12 +422,16 @@ poll_create = PollCreateView.as_view()
|
||||
|
||||
|
||||
class PollMixin(object):
|
||||
"""Mixin for the PollUpdateView and the PollDeleteView."""
|
||||
"""
|
||||
Mixin for the PollUpdateView and the PollDeleteView.
|
||||
"""
|
||||
|
||||
permission_required = 'motion.can_manage_motion'
|
||||
success_url_name = 'motion_detail'
|
||||
|
||||
def get_object(self):
|
||||
"""Return a MotionPoll object.
|
||||
"""
|
||||
Return a MotionPoll object.
|
||||
|
||||
Use the motion id and the poll_number from the url kwargs to get the
|
||||
object.
|
||||
@ -437,30 +441,40 @@ class PollMixin(object):
|
||||
poll_number=self.kwargs['poll_number']).get()
|
||||
|
||||
def get_url_name_args(self):
|
||||
"""Return the arguments to create the url to the success_url"""
|
||||
"""
|
||||
Return the arguments to create the url to the success_url.
|
||||
"""
|
||||
return [self.object.motion.pk]
|
||||
|
||||
|
||||
class PollUpdateView(PollMixin, PollFormView):
|
||||
"""View to update a MotionPoll."""
|
||||
"""
|
||||
View to update a MotionPoll.
|
||||
"""
|
||||
|
||||
poll_class = MotionPoll
|
||||
"""Poll Class to use for this view."""
|
||||
"""
|
||||
Poll Class to use for this view.
|
||||
"""
|
||||
|
||||
template_name = 'motion/poll_form.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Return the template context.
|
||||
"""
|
||||
Return the template context.
|
||||
|
||||
Append the motion object to the context.
|
||||
"""
|
||||
context = super(PollUpdateView, self).get_context_data(**kwargs)
|
||||
context.update({
|
||||
'motion': self.poll.motion})
|
||||
'motion': self.poll.motion,
|
||||
'poll': self.poll})
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Write a log message, if the form is valid."""
|
||||
"""
|
||||
Write a log message, if the form is valid.
|
||||
"""
|
||||
value = super(PollUpdateView, self).form_valid(form)
|
||||
self.object.write_log(ugettext_noop('Poll updated'), self.request.user)
|
||||
return value
|
||||
@ -469,21 +483,54 @@ poll_edit = PollUpdateView.as_view()
|
||||
|
||||
|
||||
class PollDeleteView(PollMixin, DeleteView):
|
||||
"""View to delete a MotionPoll."""
|
||||
"""
|
||||
View to delete a MotionPoll.
|
||||
"""
|
||||
|
||||
model = MotionPoll
|
||||
|
||||
def case_yes(self):
|
||||
"""Write a log message, if the form is valid."""
|
||||
"""
|
||||
Write a log message, if the form is valid.
|
||||
"""
|
||||
super(PollDeleteView, self).case_yes()
|
||||
self.object.write_log(ugettext_noop('Poll deleted'), self.request.user)
|
||||
|
||||
def get_redirect_url(self, **kwargs):
|
||||
"""Return the URL to the DetailView of the motion."""
|
||||
"""
|
||||
Return the URL to the DetailView of the motion.
|
||||
"""
|
||||
return reverse('motion_detail', args=[self.object.motion.pk])
|
||||
|
||||
poll_delete = PollDeleteView.as_view()
|
||||
|
||||
|
||||
class PollPDFView(PollMixin, PDFView):
|
||||
"""
|
||||
Generates a ballotpaper.
|
||||
"""
|
||||
|
||||
permission_required = 'motion.can_manage_motion'
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
return super(PollPDFView, self).get(*args, **kwargs)
|
||||
|
||||
def get_filename(self):
|
||||
"""
|
||||
Return the filename for the PDF.
|
||||
"""
|
||||
return u'%s%s_%s' % (_("Motion"), str(self.object.poll_number), _("Poll"))
|
||||
|
||||
def append_to_pdf(self, pdf):
|
||||
"""
|
||||
Append PDF objects.
|
||||
"""
|
||||
motion_poll_to_pdf(pdf, self.object)
|
||||
|
||||
poll_pdf = PollPDFView.as_view()
|
||||
|
||||
|
||||
class MotionSetStateView(SingleObjectMixin, RedirectView):
|
||||
"""View to set the state of a motion.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user