Automated merge with ssh://oshahn.de/openslides

This commit is contained in:
Oskar Hahn 2011-09-03 11:46:22 +02:00
commit f5d2a503d0
25 changed files with 103 additions and 529 deletions

View File

@ -70,8 +70,7 @@
{% if perms.agenda.can_manage_agenda %} {% if perms.agenda.can_manage_agenda %}
<td></td> <td></td>
{% endif %} {% endif %}
<td style="width: 1px;white-space: nowrap"><a href="{% url print_agenda %}" title="{%trans 'Print reduced agenda (only first parent items)' %}"><img src="/static/images/icons/application-pdf.png"></a> <td style="width: 1px;white-space: nowrap"><a href="{% url print_agenda %}" title="{%trans 'Print agenda' %}"><img src="/static/images/icons/application-pdf.png"></a></td>
<a href="{% url print_agenda_full printAllItems=1 %}" title="{%trans 'Print full agenda (all items)' %}"><img src="/static/images/icons/pdf-annotations.png"></a></td>
</tr> </tr>
{% for item in items %} {% for item in items %}
{% if not item.hidden or perms.agenda.can_manage_agenda %} {% if not item.hidden or perms.agenda.can_manage_agenda %}

View File

@ -10,7 +10,7 @@
<h4>{% trans "Status" %}:</h4> <h4>{% trans "Status" %}:</h4>
{% trans item.assignment.get_status_display %} {% trans item.assignment.get_status_display %}
<h4>{% trans "Number of available posts" %}:</h4> <h4>{% trans "Number of available posts" %}:</h4>
{{ item.assignment.assignment_number }} {{ item.assignment.posts }}
</div> </div>
</div> </div>
{% endif %} {% endif %}

View File

@ -54,9 +54,6 @@ urlpatterns = patterns('agenda.views',
url(r'^item/(?P<item_id>\d+)/del/$', 'delete', url(r'^item/(?P<item_id>\d+)/del/$', 'delete',
name='item_delete'), name='item_delete'),
url(r'^item/print/(?P<printAllItems>\d+)/$', 'print_agenda',
name='print_agenda_full'),
url(r'^item/print/$', 'print_agenda', url(r'^item/print/$', 'print_agenda',
name='print_agenda'), name='print_agenda'),
) )

View File

@ -351,14 +351,8 @@ class Application(models.Model):
Generates a poll object for the application Generates a poll object for the application
""" """
from poll.models import Poll from poll.models import Poll
if pollcount > 1: poll = Poll(optiondecision=True, \
description = _("%s. poll") % pollcount application=self)
else:
description = _("Poll")
poll = Poll(title=_("Application #%s") % self.number, \
optiondecision=True, \
application=self,
description=description)
poll.save() poll.save()
poll.add_option(self) poll.add_option(self)
self.writelog(_("Poll created"), user) self.writelog(_("Poll created"), user)

View File

@ -1,25 +1,25 @@
{% extends 'application/base_application.html' %} {% extends 'application/base_application.html' %}
{% block title %}{{ block.super }} - {{ poll.title }}{% endblock %} {% block title %}{{ block.super }} - {{ poll }}{% endblock %}
{% if perms.poll.can_manage_poll %} {% if perms.application.can_manage_application %}
{% block submenu %} {% block submenu %}
{{ block.super }} {{ block.super }}
<br> <br>
<h3>{%trans "Application" %} #{{ poll.application.number }}</h3> <h3>{%trans "Application" %} #{{ poll.application.number }}</h3>
<ul> <ul>
<li><a href="{% url print_application_poll poll.id %}"><img src="/static/images/icons/application-pdf.png"> {%trans 'Print Poll' %}</a></li> <li><a href="{% url print_application_poll poll.id %}"><img src="/static/images/icons/application-pdf.png"> {%trans 'Print vote' %}</a></li>
</ul> </ul>
{% endblock %} {% endblock %}
{% endif %} {% endif %}
{% block content %} {% block content %}
<h1>{{ poll.title }}</h1> <h1>{%trans "Application" %} #{{ poll.application.number }} - {%trans "Vote" %}</h1>
<h4>Title: "{{ poll.application.title }}"</h4> <h4>{{ poll.application.title }}</h4>
{% if perms.poll.can_manage_poll %} {% if perms.poll.can_manage_poll %}
<form action="" method="post">{% csrf_token %} <form action="" method="post">{% csrf_token %}
<fieldset> <fieldset>
<legend>{{ poll.description }}</legend> <legend>{%trans "Results" %}: {{ ballot }}. {%trans "Vote" %}</legend>
<p><nobr><label>{%trans "Votes in favour" %}:</label></nobr> <p><nobr><label>{%trans "Votes in favour" %}:</label></nobr>
{{ options.0.form.yes.errors }}{{ options.0.form.yes }} {{ options.0.form.yes.errors }}{{ options.0.form.yes }}
</p> </p>

View File

@ -149,7 +149,7 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% else %} {% else %}
<a href="{% url application_poll_view poll.id %}">{% trans "Enter vote result!" %}</a> <a href="{% url application_poll_view poll.id %}">{% trans "Enter vote results!" %}</a>
{% endif %} {% endif %}
{% if not forloop.last %}<br>{% endif %} {% if not forloop.last %}<br>{% endif %}
{% empty %} {% empty %}
@ -206,13 +206,13 @@
<div> <div>
<p>{% trans "Application" %} <h1>{% trans "Application" %}
{% if application.number != None %} {% if application.number != None %}
#{{ application.number }} #{{ application.number }}
{% else %} {% else %}
<i>[no number]</i> <i>[no number]</i>
{% endif %}</p> {% endif %}</h1>
<h1>{{ application.title }}</h1> <h2>{{ application.title }}</h2>
{{ application.text|linebreaks }} {{ application.text|linebreaks }}

View File

@ -318,12 +318,13 @@ def view_poll(request, poll_id):
view a poll for this application. view a poll for this application.
""" """
poll = Poll.objects.get(pk=poll_id) poll = Poll.objects.get(pk=poll_id)
ballot = poll.ballot
options = poll.options options = poll.options
if request.user.has_perm('application.can_manage_applications'): if request.user.has_perm('application.can_manage_applications'):
if request.method == 'POST': if request.method == 'POST':
form = PollInvalidForm(request.POST, prefix="poll") form = PollInvalidForm(request.POST, prefix="poll")
if form.is_valid(): if form.is_valid():
poll.voteinvalid = form.cleaned_data['invalid'] or 0 poll.votesinvalid = form.cleaned_data['invalid'] or 0
poll.save() poll.save()
for option in options: for option in options:
@ -336,7 +337,7 @@ def view_poll(request, poll_id):
cleaned_data['undesided'] or 0 cleaned_data['undesided'] or 0
option.save() option.save()
else: else:
form = PollInvalidForm(initial={'invalid': poll.voteinvalid}, prefix="poll") form = PollInvalidForm(initial={'invalid': poll.votesinvalid}, prefix="poll")
for option in options: for option in options:
option.form = OptionResultForm(initial={ option.form = OptionResultForm(initial={
'yes': option.voteyes, 'yes': option.voteyes,
@ -347,4 +348,5 @@ def view_poll(request, poll_id):
'poll': poll, 'poll': poll,
'form': form, 'form': form,
'options': options, 'options': options,
'ballot': ballot,
} }

View File

@ -17,7 +17,7 @@ from participant.models import Profile
from assignment.models import Assignment from assignment.models import Assignment
class AssigmentForm(ModelForm): class AssignmentForm(ModelForm):
error_css_class = 'error' error_css_class = 'error'
required_css_class = 'required' required_css_class = 'required'
@ -26,7 +26,7 @@ class AssigmentForm(ModelForm):
exclude = ('status', 'profile') exclude = ('status', 'profile')
class AssigmentRunForm(Form): class AssignmentRunForm(Form):
error_css_class = 'error' error_css_class = 'error'
candidate = ModelChoiceField( candidate = ModelChoiceField(

View File

@ -25,7 +25,7 @@ class Assignment(models.Model):
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, verbose_name = _("Description"))
assignment_number = models.PositiveSmallIntegerField(verbose_name = _("Number of available posts")) posts = models.PositiveSmallIntegerField(verbose_name = _("Number of available posts"))
polldescription = models.CharField(max_length=50, null=True, blank=True, verbose_name = _("Short description (for ballot paper)")) polldescription = models.CharField(max_length=50, null=True, blank=True, verbose_name = _("Short description (for ballot paper)"))
profile = models.ManyToManyField(Profile, null=True, blank=True) profile = models.ManyToManyField(Profile, null=True, blank=True)
elected = models.ManyToManyField(Profile, null=True, blank=True, related_name='elected_set') elected = models.ManyToManyField(Profile, null=True, blank=True, related_name='elected_set')
@ -91,7 +91,7 @@ class Assignment(models.Model):
def gen_poll(self): def gen_poll(self):
from poll.models import Poll from poll.models import Poll
poll = Poll() poll = Poll()
poll.title = _("Election for %s") % self.name
candidates = list(self.profile.all()) candidates = list(self.profile.all())
for elected in self.elected.all(): for elected in self.elected.all():
try: try:
@ -100,7 +100,7 @@ class Assignment(models.Model):
pass pass
# Option A: candidates <= available posts -> yes/no/abstention # Option A: candidates <= available posts -> yes/no/abstention
if len(candidates) <= self.assignment_number - self.elected.count(): if len(candidates) <= self.posts - self.elected.count():
poll.optiondecision = True poll.optiondecision = True
else: else:
poll.optiondecision = False poll.optiondecision = False

View File

@ -27,7 +27,7 @@
{% for assignment in assignments %} {% for assignment in assignments %}
<tr class="{% cycle '' 'odd' %}"> <tr class="{% cycle '' 'odd' %}">
<td><a href="{% url assignment_view assignment.id %}">{{ assignment }}</a></td> <td><a href="{% url assignment_view assignment.id %}">{{ assignment }}</a></td>
<td>{{ assignment.profile.count }} / {{ assignment.assignment_number }}</td> <td>{{ assignment.profile.count }} / {{ assignment.posts }}</td>
<td>{{ assignment.get_status_display }}</td> <td>{{ assignment.get_status_display }}</td>
{% if perms.assignment.can_manage_assignment %} {% if perms.assignment.can_manage_assignment %}
<td><a href="{% url assignment_edit assignment.id %}"><img src="/static/images/icons/document-edit.png" title="{%trans 'Edit assignment' %}"></a> <td><a href="{% url assignment_edit assignment.id %}"><img src="/static/images/icons/document-edit.png" title="{%trans 'Edit assignment' %}"></a>

View File

@ -1,8 +1,8 @@
{% extends 'assignment/base_assignment.html' %} {% extends 'assignment/base_assignment.html' %}
{% block title %}{{ block.super }} - {%trans "Poll" %} "{{ poll.title }}"{% endblock %} {% block title %}{{ block.super }} - {%trans "Poll" %} "{{ poll }}"{% endblock %}
{% block content %} {% block content %}
<h1>{{ poll.title }}</h1> <h1>{{ poll }}</h1>
<p>{{ ballotnumber }}. {%trans "ballot" %}: {{options.count}} <p>{{ ballotnumber }}. {%trans "ballot" %}: {{options.count}}
{% blocktrans count counter=options|length %}candidate{% plural %}candidates{% endblocktrans %} {% blocktrans count counter=options|length %}candidate{% plural %}candidates{% endblocktrans %}
</p> </p>
@ -33,7 +33,7 @@
{% endfor %} {% endfor %}
</table> </table>
<label for="id_voteinvalid">{% trans "Invalid" %}:</label> <label for="id_votesinvalid">{% trans "Invalid" %}:</label>
{{ form.invalid.errors }}{{ form.invalid }} {{ form.invalid.errors }}{{ form.invalid }}
{% if perms.poll.can_manage_poll %} {% if perms.poll.can_manage_poll %}
@ -46,7 +46,7 @@
<span class="icon previous">{%trans 'Back to election' %}</span> <span class="icon previous">{%trans 'Back to election' %}</span>
</button> </button>
</a> </a>
<a href='{% url print_assignment_poll poll.id ballotnumber poll.assignment.assignment_number %}'> <a href='{% url print_assignment_poll poll.id %}'>
<button type="button"> <button type="button">
<span class="icon pdf">{%trans 'Print ballot' %}</span> <span class="icon pdf">{%trans 'Print ballot' %}</span>
</button> </button>

View File

@ -9,7 +9,7 @@
{% trans assignment.get_status_display %} {% trans assignment.get_status_display %}
<h4>{% trans "Number of available posts" %}:</h4> <h4>{% trans "Number of available posts" %}:</h4>
{{ assignment.assignment_number }} {{ assignment.posts }}
</div> </div>
<br><br> <br><br>
@ -122,7 +122,7 @@
<tr> <tr>
<th>{% trans "Candidates" %}</th> <th>{% trans "Candidates" %}</th>
{% for poll in assignment.poll_set.all %} {% for poll in assignment.poll_set.all %}
<th style="vertical-align: top; white-space:nowrap;">{% if perms.assignment.can_manage_assignment %}<a href="{% url assignment_poll_view poll.id forloop.counter %}">{% endif %} <th style="vertical-align: top; white-space:nowrap;">{% if perms.assignment.can_manage_assignment %}<a href="{% url assignment_poll_view poll.id %}">{% endif %}
{{forloop.counter}}. {{forloop.counter}}.
{% if perms.assignment.can_manage_assignment %} {% if perms.assignment.can_manage_assignment %}
</a> </a>
@ -132,13 +132,11 @@
{% endfor %} {% endfor %}
{% if assignment.profile.count > 0 and perms.assignment.can_manage_assignment and assignment.status == "vot" %} {% if assignment.profile.count > 0 and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
<th> <th>
{% with ballotnumber=assignment.poll_set.all.count %} <a href='{% url assignment_gen_poll assignment.id %}'>
<a href='{% url assignment_gen_poll assignment.id ballotnumber|add:'1' %}'>
<button type="button"> <button type="button">
<span class="icon poll">{%trans 'New ballot' %}</span> <span class="icon poll">{%trans 'New ballot' %}</span>
</button> </button>
</a> </a>
{% endwith %}
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -179,13 +177,11 @@
<i>{% trans "No ballots available." %}</i> <i>{% trans "No ballots available." %}</i>
{% if assignment.profile.count > 0 and perms.assignment.can_manage_assignment and assignment.status == "vot" %} {% if assignment.profile.count > 0 and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
{% with ballotnumber=assignment.poll_set.all.count %} <p><a href='{% url assignment_gen_poll assignment.id %}'>
<p><a href='{% url assignment_gen_poll assignment.id ballotnumber|add:'1' %}'>
<button type="button"> <button type="button">
<span class="icon poll">{%trans 'New ballot' %}</span> <span class="icon poll">{%trans 'New ballot' %}</span>
</button> </button>
</a></p> </a></p>
{% endwith %}
{% endif %} {% endif %}
{% endif %} {% endif %}

View File

@ -40,13 +40,13 @@ urlpatterns = patterns('assignment.views',
url(r'^assignment/(?P<assignment_id>\d+)/delother/(?P<profile_id>\d+)$', 'delother', \ url(r'^assignment/(?P<assignment_id>\d+)/delother/(?P<profile_id>\d+)$', 'delother', \
name='assignment_delother'), name='assignment_delother'),
url(r'^assignment/poll/(?P<poll_id>\d+)/print/(?P<ballotnumber>\d+)/(?P<posts>\d+)$', 'print_assignment_poll', \ url(r'^assignment/poll/(?P<poll_id>\d+)/print$', 'print_assignment_poll', \
name='print_assignment_poll'), name='print_assignment_poll'),
url(r'^assignment/(?P<assignment_id>\d+)/gen_poll/(?P<ballotnumber>\d+)$', 'gen_poll', \ url(r'^assignment/(?P<assignment_id>\d+)/gen_poll$', 'gen_poll', \
name='assignment_gen_poll'), name='assignment_gen_poll'),
url(r'^assignment/poll/(?P<poll_id>\d+)/(?P<ballotnumber>\d+)$', 'poll_view', \ url(r'^assignment/poll/(?P<poll_id>\d+)$', 'poll_view', \
name='assignment_poll_view'), name='assignment_poll_view'),
url(r'^assignment/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \ url(r'^assignment/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \

View File

@ -19,7 +19,7 @@ from django.utils.translation import ugettext as _
from poll.models import Poll, Option from poll.models import Poll, Option
from poll.forms import OptionResultForm, PollInvalidForm from poll.forms import OptionResultForm, PollInvalidForm
from assignment.models import Assignment from assignment.models import Assignment
from assignment.forms import AssigmentForm, AssigmentRunForm from assignment.forms import AssignmentForm, AssignmentRunForm
from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form, ajax_request from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form, ajax_request
from utils.pdf import print_assignment_poll from utils.pdf import print_assignment_poll
from participant.models import Profile from participant.models import Profile
@ -53,7 +53,7 @@ def view(request, assignment_id=None):
assignment = Assignment.objects.get(pk=assignment_id) assignment = Assignment.objects.get(pk=assignment_id)
if request.method == 'POST': if request.method == 'POST':
if request.user.has_perm('assignment.can_nominate_other'): if request.user.has_perm('assignment.can_nominate_other'):
form = AssigmentRunForm(request.POST) form = AssignmentRunForm(request.POST)
if form.is_valid(): if form.is_valid():
user = form.cleaned_data['candidate'] user = form.cleaned_data['candidate']
try: try:
@ -63,20 +63,26 @@ def view(request, assignment_id=None):
messages.error(request, e) messages.error(request, e)
else: else:
if request.user.has_perm('assignment.can_nominate_other'): if request.user.has_perm('assignment.can_nominate_other'):
form = AssigmentRunForm() form = AssignmentRunForm()
# list of candidates
candidates = set()
for option in Option.objects.filter(poll__assignment=assignment):
candidates.add(option.value)
votes = [] votes = []
for candidate in assignment.candidates: for candidate in candidates:
tmplist = [[candidate, assignment.is_elected(candidate)], []] tmplist = []
tmplist.append(candidate)
for poll in assignment.poll_set.all(): for poll in assignment.poll_set.all():
if candidate in poll.options_values: if candidate in poll.options_values:
option = Option.objects.filter(poll=poll).filter(user=candidate)[0] option = Option.objects.filter(poll=poll).filter(user=candidate)[0]
if poll.optiondecision: if poll.optiondecision:
tmplist[1].append([option.yes, option.no, option.undesided]) tmplist.append([option.yes, option.no, option.undesided])
else: else:
tmplist[1].append(option.yes) tmplist.append(option.yes)
else: else:
tmplist[1].append("-") tmplist.append("-")
votes.append(tmplist) votes.append(tmplist)
return {'assignment': assignment, return {'assignment': assignment,
@ -96,7 +102,7 @@ def edit(request, assignment_id=None):
assignment = None assignment = None
if request.method == 'POST': if request.method == 'POST':
form = AssigmentForm(request.POST, instance=assignment) form = AssignmentForm(request.POST, instance=assignment)
if form.is_valid(): if form.is_valid():
form.save() form.save()
if assignment_id is None: if assignment_id is None:
@ -105,7 +111,7 @@ def edit(request, assignment_id=None):
messages.success(request, _('Election was successfully modified.')) messages.success(request, _('Election was successfully modified.'))
return redirect(reverse("assignment_overview")) return redirect(reverse("assignment_overview"))
else: else:
form = AssigmentForm(instance=assignment) form = AssignmentForm(instance=assignment)
return { return {
'form': form, 'form': form,
'assignment': assignment, 'assignment': assignment,
@ -136,26 +142,6 @@ def set_status(request, assignment_id=None, status=None):
return redirect(reverse('assignment_view', args=[assignment_id])) return redirect(reverse('assignment_view', args=[assignment_id]))
@permission_required('assignment.can_manage_assignment')
def set_elected(request, assignment_id, profile_id, elected=True):
assignment = Assignment.objects.get(pk=assignment_id)
profile = Profile.objects.get(pk=profile_id)
assignment.set_elected(profile, elected)
if request.is_ajax():
if elected:
link = reverse('assignment_user_not_elected', args=[assignment.id, profile.id])
text = _('not elected')
else:
link = reverse('assignment_user_elected', args=[assignment.id, profile.id])
text = _('elected')
return ajax_request({'elected': elected,
'link': link,
'text': text})
return redirect(reverse('assignment_view', args=[assignment_id]))
@permission_required('assignment.can_nominate_self') @permission_required('assignment.can_nominate_self')
def run(request, assignment_id): def run(request, assignment_id):
assignment = Assignment.objects.get(pk=assignment_id) assignment = Assignment.objects.get(pk=assignment_id)
@ -194,26 +180,27 @@ def delother(request, assignment_id, profile_id):
@permission_required('assignment.can_manage_assignment') @permission_required('assignment.can_manage_assignment')
def gen_poll(request, assignment_id, ballotnumber): def gen_poll(request, assignment_id):
try: try:
poll = Assignment.objects.get(pk=assignment_id).gen_poll() poll = Assignment.objects.get(pk=assignment_id).gen_poll()
messages.success(request, _("New ballot was successfully created.") ) messages.success(request, _("New ballot was successfully created.") )
except Assignment.DoesNotExist: except Assignment.DoesNotExist:
pass pass
return redirect(reverse('assignment_poll_view', args=[poll.id, ballotnumber])) return redirect(reverse('assignment_poll_view', args=[poll.id]))
@permission_required('assignment.can_view_assignment') @permission_required('assignment.can_view_assignment')
@template('assignment/poll_view.html') @template('assignment/poll_view.html')
def poll_view(request, poll_id, ballotnumber=1): def poll_view(request, poll_id):
poll = Poll.objects.get(pk=poll_id) poll = Poll.objects.get(pk=poll_id)
ballotnumber = poll.ballot
options = poll.options.order_by('user__user__first_name') options = poll.options.order_by('user__user__first_name')
assignment = poll.assignment assignment = poll.assignment
if request.user.has_perm('assignment.can_manage_assignment'): if request.user.has_perm('assignment.can_manage_assignment'):
if request.method == 'POST': if request.method == 'POST':
form = PollInvalidForm(request.POST, prefix="poll") form = PollInvalidForm(request.POST, prefix="poll")
if form.is_valid(): if form.is_valid():
poll.voteinvalid = form.cleaned_data['invalid'] or 0 poll.votesinvalid = form.cleaned_data['invalid'] or 0
poll.save() poll.save()
success = 0 success = 0
@ -228,7 +215,7 @@ def poll_view(request, poll_id, ballotnumber=1):
if success == options.count(): if success == options.count():
messages.success(request, _("Votes are successfully saved.") ) messages.success(request, _("Votes are successfully saved.") )
else: else:
form = PollInvalidForm(initial={'invalid': poll.voteinvalid}, prefix="poll") form = PollInvalidForm(initial={'invalid': poll.votesinvalid}, prefix="poll")
for option in options: for option in options:
option.form = OptionResultForm(initial={ option.form = OptionResultForm(initial={
'yes': option.voteyes, 'yes': option.voteyes,

View File

@ -19,14 +19,12 @@ from participant.models import Profile
class Poll(models.Model): class Poll(models.Model):
#TODO: Mehrheit in den Zahlen festmachen
title = models.CharField(max_length=100, verbose_name = _("Title"))
optiondecision = models.BooleanField(default=True, verbose_name = _("Poll of decision (yes, no, abstention)")) optiondecision = models.BooleanField(default=True, verbose_name = _("Poll of decision (yes, no, abstention)"))
application = models.ForeignKey(Application, null=True, blank=True, verbose_name = _("Application")) application = models.ForeignKey(Application, null=True, blank=True, verbose_name = _("Application"))
assignment = models.ForeignKey(Assignment, null=True, blank=True, verbose_name = _("Election")) assignment = models.ForeignKey(Assignment, null=True, blank=True, verbose_name = _("Election"))
description = models.TextField(null=True, blank=True, verbose_name = _("Description")) description = models.TextField(null=True, blank=True, verbose_name = _("Description"))
votescast = models.IntegerField(null=True, blank=True, verbose_name = _("Votes cast")) votescast = models.IntegerField(null=True, blank=True, verbose_name = _("Votes cast"))
voteinvalid = models.IntegerField(null=True, blank=True, verbose_name = _("Votes invalid")) votesinvalid = models.IntegerField(null=True, blank=True, verbose_name = _("Votes invalid"))
def add_option(self, option): def add_option(self, option):
self.save() self.save()
@ -58,6 +56,30 @@ class Poll(models.Model):
def options_values(self): def options_values(self):
return [option.value for option in self.options] return [option.value for option in self.options]
@property
def count_ballots(self):
if self.application:
return Poll.objects.filter(application=self.application).count()
if self.assignment:
return Poll.objects.filter(assignment=self.assignment).count()
return None
@property
def ballot(self):
if self.application:
counter = 0
for poll in Poll.objects.filter(application=self.application):
counter = counter + 1
if self == poll:
return counter
if self.assignment:
counter = 0
for poll in Poll.objects.filter(assignment=self.assignment):
counter = counter + 1
if self == poll:
return counter
return None
@models.permalink @models.permalink
def get_absolute_url(self, link='view'): def get_absolute_url(self, link='view'):
if self.application: if self.application:
@ -76,13 +98,10 @@ class Poll(models.Model):
return ('poll_delete', [str(self.id)]) return ('poll_delete', [str(self.id)])
def __unicode__(self): def __unicode__(self):
return self.title if self.application:
return self.application.title
class Meta: if self.assignment:
permissions = ( return self.assignment.name
('can_view_poll', "Can view polls"),
('can_manage_poll', "Can manage polls"),
)
class Option(models.Model): class Option(models.Model):

View File

@ -1,13 +0,0 @@
{% extends "base.html" %}
{% load tags %}
{% block submenu %}
{% url poll_overview as url_polloverview %}
<h4 class="sectiontitle">{%trans "Polls" %}</h4>
<ul>
<li class="{% if request.path == url_polloverview %}selected{% endif %}"><a href="{% url poll_overview %}">{%trans "All polls" %}</a></li>
{% if perms.poll.can_manage_poll %}
<li class="{% active request '/poll/new' %}"><a href="{% url poll_new %}">{%trans "New poll" %}</a></li>
{% endif %}
</ul>
{% endblock %}

View File

@ -1,48 +0,0 @@
{% extends "poll/base_poll.html" %}
{% block title %}{{ block.super }} - {%trans "Poll" %}{% endblock %}
{% block content %}
{% if poll %}
<h1>{%trans "Edit poll" %}</h1>
{% else %}
<h1>{%trans "New poll" %}</h1>
{% endif %}
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<button type="submit">
<span class="icon ok">{%trans 'Save' %}</span>
</button>
<a href='{% url poll_overview %}'>
<button type="button">
<span class="icon cancel">{%trans 'Cancel' %}</span>
</button>
</a>
{% if poll %}
<h3>{%trans "Options" %}</h3>
<table class="table">
<tr>
<th>{%trans "Option" %}</th>
<th>{%trans "Actions" %}</th>
</tr>
{% for option in options %}
<tr>
<td>{{ option }}</td>
<td><a href="{% url option_edit option.id %}"><img src="/static/images/icons/document-edit.png" title="{%trans 'Edit option' %}"></a>
<a href="{% url option_delete option.id %}"><img src="/static/images/icons/edit-delete.png" title="{%trans 'Delete option' %}"></a>
</td>
</tr>
{% endfor %}
</table>
<br>
<a href='{% url option_new_fixpoll poll.id %}'>
<button type="button">
<span class="icon add">{%trans 'Add new Option' %}</span>
</button>
</a>
{% endif %}
</form>
{% endblock %}

View File

@ -1,23 +0,0 @@
{% extends "poll/base_poll.html" %}
{% block title %}{{ block.super }} - {%trans "Poll" %}{% endblock %}
{% block content %}
{% if option %}
<h1>{%trans "Edit Poll Option" %}</h1>
{% else %}
<h1>{%trans "New Poll Option" %}</h1>
{% endif %}
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<button type="submit">
<span class="icon ok">{%trans 'Save' %}</span>
</button>
<a href='{% url poll_overview %}'>
<button type="button">
<span class="icon cancel">{%trans 'Cancel' %}</span>
</button>
</a>
</form>
{% endblock %}

View File

@ -1,30 +0,0 @@
{% extends "poll/base_poll.html" %}
{% block title %}{{ block.super }} - {%trans "Polls" %}{% endblock %}
{% block content %}
<h1>{%trans "Polls" %}</h1>
<table>
<tr>
<th><a href="?sort=title{% if 'title' in request.GET.sort and 'reverse' not in request.GET %}&reverse{%endif%}">{%trans "Polls" %}</a></th>
<th>{%trans "Options" %}</th>
{% if perms.poll.can_manage_poll %}
<th>{%trans "Actions" %}</th>
{% endif %}
</tr>
{% for poll in polls %}
<tr class="{% cycle '' 'odd' %}">
<td><a href="{% url poll_view poll.id %}">{{ poll }}</a></td>
<td>{{ poll.get_options|length }}</td>
{% if perms.poll.can_manage_poll %}
<td><a href="{% url poll_edit poll.id %}"><img src="/static/images/icons/document-edit.png" title="{%trans 'Edit poll' %}"></a>
<a href="{% url poll_delete poll.id %}"><img src="/static/images/icons/edit-delete.png" title="{%trans 'Delete poll' %}"></a>
</td>
{% endif %}
</tr>
{% empty %}
<tr>
<td colspan="4"><i>{%trans "No polls available." %}</i></td>
</tr>
{% endfor %}
</table>
{% endblock %}

View File

@ -1,63 +0,0 @@
{% extends app %}
{% block title %}{{ block.super }} - {%trans "Poll" %} "{{ poll.title }}"{% endblock %}
{% block content %}
<h1>{{ poll.title }}</h1>
<p>{{ poll.description }}</p>
<form action="" method="post">{% csrf_token %}
<table class="table">
<tr>
<th>{%trans "Option" %}</th>
{% if poll.optiondecision %}
<th>{%trans "Yes" %}</th>
<th>{%trans "No" %}</th>
<th>{%trans "Abstention" %}</th>
{% else %}
<th>{%trans "Votes" %}</th>
{% endif %}
{% if perms.poll.can_manage_poll %}
<th>{% trans "Actions" %}</th>
{% endif %}
</tr>
{% for option in options %}
<tr>
<td>{{ option }}</td>
{% if poll.optiondecision %}
<td>{{ option.form.yes.errors }}{{ option.form.yes }}</td>
<td>{{ option.form.no.errors }}{{ option.form.no }}</td>
<td>{{ option.form.undesided.errors }}{{ option.form.undesided }}</td>
{% else %}
<td>{{ option.form.yes.errors }}{{ option.form.yes }}</td>
{% endif %}
{% if perms.poll.can_manage_poll %}
<td><a href="{% url option_delete option.id %}"><img src="/static/images/icons/edit-delete.png" title="{%trans 'Delete option' %}"></a></td>
{% endif %}
</tr>
{% endfor %}
</table>
{% if perms.poll.can_manage_poll %}
<p>
<button type="submit">
<span class="icon ok">{%trans 'Apply' %}</span>
</button>
{% if not poll.application and not poll.assignment %}
<a href='{% url option_new_fixpoll poll.id %}'>
<button type="button">
<span class="icon add">{%trans 'Add new Option' %}</span>
</button>
</a>
{% endif %}
<!--print pdf
<a href=' url poll_print poll.id '>
<button type="button">
<span class="icon pdf">{%trans 'Print Poll' %}</span>
</button>
</a>-->
</p>
{% endif %}
</form>
{% endblock %}

View File

@ -1,26 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.poll.urls
~~~~~~~~~~~~~~~~~~~~
URL list for the poll app.
:copyright: 2011 by the OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.conf.urls.defaults import *
urlpatterns = patterns('poll.views',
url(r'^poll/$', 'get_overview', name='poll_overview'),
url(r'^poll/(?P<poll_id>\d+)$', 'view', name='poll_view'),
url(r'^poll/new$', 'edit', name='poll_new'),
url(r'^poll/(?P<poll_id>\d+)/edit$', 'edit', name='poll_edit'),
url(r'^poll/(?P<poll_id>\d+)/del$', 'delete', name='poll_delete'),
url(r'^poll/option/new$', 'option_edit', name='option_new'),
url(r'^poll/(?P<poll_id>\d+)/option/new$', 'option_edit', name='option_new_fixpoll'),
url(r'^poll/option/(?P<option_id>\d+)/edit$', 'option_edit', name='option_edit'),
url(r'^poll/option/(?P<option_id>\d+)/del$', 'option_delete', name='option_delete'),
# url(r'^poll/pdf/(?P<poll_id>\d+)$', 'print_poll', name='poll_print'),
)

View File

@ -1,191 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.poll.views
~~~~~~~~~~~~~~~~~~~~~
Views for the poll app.
:copyright: 2011 by the OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.utils.translation import ugettext as _
from poll.models import Poll, Option
from poll.forms import PollForm, OptionForm, OptionResultForm
from utils.utils import template, permission_required, gen_confirm_form
#from utils.pdf import print_poll
@permission_required('poll.can_view_poll')
@template('poll/overview.html')
def get_overview(request):
query = Poll.objects.filter(assignment=None).filter(application=None)
try:
sort = request.GET['sort']
if sort in ['title']:
query = query.order_by(sort)
except KeyError:
pass
if 'reverse' in request.GET:
query = query.reverse()
polls = query.all()
return {
'polls': polls,
}
@template('poll/view.html')
@permission_required('poll.can_view_poll')
def view(request, poll_id):
poll = Poll.objects.get(pk=poll_id)
if poll.application and not request.path.startswith('/application'):
return redirect(reverse('application_poll_view', args=[poll_id]))
if poll.assignment and not request.path.startswith('/assignment'):
return redirect(reverse('assignment_poll_view', args=[poll_id, 0]))
if not (poll.application or poll.assignment) and not request.path.startswith('/poll'):
return redirect(reverse('poll_view', args=[poll_id]))
options = poll.option_set.all()
if request.user.has_perm('poll.can_manage_poll'):
success = 0
for option in options:
if request.method == 'POST':
option.form = OptionResultForm(request.POST, prefix="o%d" % option.id)
if option.form.is_valid():
option.voteyes = option.form.cleaned_data['yes']
option.voteno = option.form.cleaned_data['no'] or 0
option.voteundesided = option.form.cleaned_data['undesided'] or 0
option.save()
success = success + 1
else:
messages.error(request, _('Please check the form for errors.'))
else:
option.form = OptionResultForm(initial={
'yes': option.voteyes,
'no': option.voteno,
'undesided': option.voteundesided,
}, prefix="o%d" % option.id)
if request.method == 'POST' and success == options.count():
messages.success(request, _("Votes are successfully saved.") )
if poll.application:
app = 'application/base_application.html'
elif poll.assignment:
app = 'assignment/base_assignment.html'
else:
app = 'poll/base_poll.html'
return {
'poll': poll,
'options': options,
'app': app,
}
@permission_required('poll.can_manage_poll')
@template('poll/edit.html')
def edit(request, poll_id=None):
"""
View zum editieren und neuanlegen von Wahlen
"""
if poll_id is not None:
poll = Poll.objects.get(id=poll_id)
else:
poll = None
if request.method == 'POST':
if poll_id is None:
form = PollForm(request.POST)
else:
form = PollForm(request.POST, instance=poll)
if form.is_valid():
poll = form.save()
if poll_id is None:
messages.success(request, _('New poll was successfully created.'))
else:
messages.success(request, _('Poll was successfully modified.'))
return redirect(reverse("poll_overview"))
messages.error(request, _('Please check the form for errors.'))
else:
if poll_id is None:
form = PollForm()
else:
form = PollForm(instance=poll)
try:
options = poll.option_set.all()
except AttributeError:
options = []
return {
'form': form,
'poll': poll,
'options': options,
}
@permission_required('poll.can_manage_poll')
def delete(request, poll_id):
poll = Poll.objects.get(id=poll_id)
if request.method == 'POST':
poll.delete()
messages.success(request, _('Poll <b>%s</b> was successfully deleted.') % poll)
else:
gen_confirm_form(request, _('Do you really want to delete <b>%s</b>?') % poll, reverse('poll_delete', args=[poll_id]))
return redirect(reverse('poll_overview'))
@permission_required('poll.can_manage_poll')
@template('poll/option_edit.html')
def option_edit(request, poll_id=None, option_id=None):
"""
View zum editieren und neuanlegen von Optionen für eine Wahl
"""
if option_id is not None:
option = Option.objects.get(id=option_id)
else:
option = None
if request.method == 'POST':
if option_id is None:
form = OptionForm(request.POST)
else:
form = OptionForm(request.POST, instance=option)
if form.is_valid():
option = form.save()
if option_id is None:
messages.success(request, _('New option was successfully created.'))
else:
messages.success(request, _('Option was successfully modified.'))
return redirect(reverse("poll_overview"))
messages.error(request, _('Please check the form for errors.'))
else:
if option_id is None:
if poll_id is None:
form = OptionForm()
else:
poll = poll = Poll.objects.get(id=poll_id)
form = OptionForm(initial={'poll': poll})
else:
form = OptionForm(instance=option)
return {
'form': form,
'option': option,
}
@permission_required('poll.can_manage_poll')
def option_delete(request, option_id):
option = Option.objects.get(id=option_id)
if request.method == 'POST':
option.delete()
messages.success(request, _('Option <b>%s</b> was successfully deleted.') % option)
else:
gen_confirm_form(request, _('Do you really want to delete the option <b>%s</b>?') % option_id, reverse('option_delete', args=[option_id]))
return redirect(reverse('poll_overview'))

View File

@ -55,10 +55,6 @@
<li class="{% active request '/assignment' %}"> <li class="{% active request '/assignment' %}">
<a href="{% url assignment_overview %}" title="">{%trans "Elections" %}</a></li> <a href="{% url assignment_overview %}" title="">{%trans "Elections" %}</a></li>
{% endif %} {% endif %}
{% if perms.poll.can_view_poll or perms.poll.can_manage_poll %}
<li class="{% active request '/poll' %}">
<a href="{% url poll_overview %}" title="">{%trans "Polls" %}</a></li>
{% endif %}
{% if perms.participant.can_view_participants or perms.participant.can_manage_participants %} {% if perms.participant.can_view_participants or perms.participant.can_manage_participants %}
<li class="{% active request '/participant' %}"> <li class="{% active request '/participant' %}">
<a href="{% url user_overview %}" title="">{%trans "Participants" %}</a></li> <a href="{% url user_overview %}" title="">{%trans "Participants" %}</a></li>

View File

@ -21,7 +21,6 @@ urlpatterns = patterns('',
(r'', include('openslides.agenda.urls')), (r'', include('openslides.agenda.urls')),
(r'', include('openslides.application.urls')), (r'', include('openslides.application.urls')),
(r'', include('openslides.participant.urls')), (r'', include('openslides.participant.urls')),
(r'', include('openslides.poll.urls')),
(r'', include('openslides.assignment.urls')), (r'', include('openslides.assignment.urls')),
(r'', include('openslides.system.urls')), (r'', include('openslides.system.urls')),
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_DOC_ROOT}), (r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_DOC_ROOT}),

View File

@ -182,11 +182,6 @@ def firstPage(canvas, doc):
canvas.setFillGray(0) canvas.setFillGray(0)
#canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, doc.title) #canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-108, doc.title)
canvas.drawString(2.75*cm, PAGE_HEIGHT-108, doc.title) canvas.drawString(2.75*cm, PAGE_HEIGHT-108, doc.title)
if doc.subtitle:
canvas.setFont('Ubuntu',10)
canvas.setFillGray(0.4)
#canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT-125, doc.subtitle)
canvas.drawString(2.75*cm, PAGE_HEIGHT-125, doc.subtitle)
# footer (with page number) # footer (with page number)
canvas.setFont('Ubuntu',8) canvas.setFont('Ubuntu',8)
canvas.setFillGray(0.4) canvas.setFillGray(0.4)
@ -201,7 +196,7 @@ def laterPages(canvas, doc):
canvas.drawString(10*cm, 1*cm, _("Page")+" %s" % doc.page) canvas.drawString(10*cm, 1*cm, _("Page")+" %s" % doc.page)
canvas.restoreState() canvas.restoreState()
def print_agenda(request, printAllItems=None): def print_agenda(request):
response = HttpResponse(mimetype='application/pdf') response = HttpResponse(mimetype='application/pdf')
filename = u'filename=%s.pdf;' % _("Agenda") filename = u'filename=%s.pdf;' % _("Agenda")
response['Content-Disposition'] = filename.encode('utf-8') response['Content-Disposition'] = filename.encode('utf-8')
@ -209,25 +204,16 @@ def print_agenda(request, printAllItems=None):
story = [Spacer(1,3*cm)] story = [Spacer(1,3*cm)]
doc.title = _("Agenda") doc.title = _("Agenda")
if printAllItems:
doc.subtitle = "("+_("full")+")"
else:
doc.subtitle = "("+_("abridged")+")"
# print item list # print item list
items = children_list(Item.objects.filter(parent=None).order_by('weight')) items = children_list(Item.objects.filter(parent=None).order_by('weight'))
for item in items: for item in items:
if item.hidden is False: if item.hidden is False:
# print all items # print all items
if printAllItems:
if item.parents: if item.parents:
story.append(Paragraph(item.title, stylesheet['Subitem'])) story.append(Paragraph(item.title, stylesheet['Subitem']))
else: else:
story.append(Paragraph(item.title, stylesheet['Item'])) story.append(Paragraph(item.title, stylesheet['Item']))
# print items without parents only
else:
if item.parent is None:
story.append(Paragraph(item.title, stylesheet['Subitem']))
doc.build(story, onFirstPage=firstPage, onLaterPages=laterPages) doc.build(story, onFirstPage=firstPage, onLaterPages=laterPages)
return response return response
@ -240,7 +226,6 @@ def print_userlist(request):
story = [Spacer(1,2*cm)] story = [Spacer(1,2*cm)]
doc.title = _("List of Participants") doc.title = _("List of Participants")
doc.subtitle = ""
# Table # Table
data= [['#', _('Last Name'), _('First Name'), _('Group'), _('Type'), _('Committee')]] data= [['#', _('Last Name'), _('First Name'), _('Group'), _('Type'), _('Committee')]]
sort = 'last_name' sort = 'last_name'
@ -303,7 +288,6 @@ def print_application(request, application_id=None):
response['Content-Disposition'] = filename.encode('utf-8') response['Content-Disposition'] = filename.encode('utf-8')
doc = SimpleDocTemplate(response) doc = SimpleDocTemplate(response)
doc.title = None doc.title = None
doc.subtitle = None
story = [Spacer(1,2*cm)] story = [Spacer(1,2*cm)]
if application_id is None: #print all applications if application_id is None: #print all applications
@ -336,10 +320,10 @@ def print_application_poll(request, poll_id=None):
circle = "<img src='openslides/static/images/circle.png' width='15' height='15'/>&nbsp;&nbsp;" circle = "<img src='openslides/static/images/circle.png' width='15' height='15'/>&nbsp;&nbsp;"
cell = [] cell = []
cell.append(Spacer(0,0.8*cm)) cell.append(Spacer(0,0.8*cm))
cell.append(Paragraph(poll.title, stylesheet['Ballot_title'])) cell.append(Paragraph(_("Application")+" #"+str(poll.application.number), stylesheet['Ballot_title']))
cell.append(Paragraph(_("Title")+": "+poll.application.title, stylesheet['Ballot_subtitle'])) cell.append(Paragraph(poll.application.title, stylesheet['Ballot_subtitle']))
if poll.description: #if poll.description:
cell.append(Paragraph(poll.description, stylesheet['Ballot_description'])) cell.append(Paragraph(str(poll.ballot)+". "+_("Vote"), stylesheet['Ballot_description']))
cell.append(Spacer(0,0.5*cm)) cell.append(Spacer(0,0.5*cm))
cell.append(Paragraph(circle+_("Yes"), stylesheet['Ballot_option'])) cell.append(Paragraph(circle+_("Yes"), stylesheet['Ballot_option']))
cell.append(Paragraph(circle+_("No"), stylesheet['Ballot_option'])) cell.append(Paragraph(circle+_("No"), stylesheet['Ballot_option']))
@ -356,10 +340,10 @@ def print_application_poll(request, poll_id=None):
doc.build(story) doc.build(story)
return response return response
def print_assignment_poll(request, poll_id=None, ballotnumber=1, posts=None): def print_assignment_poll(request, poll_id=None):
poll = Poll.objects.get(id=poll_id) poll = Poll.objects.get(id=poll_id)
response = HttpResponse(mimetype='application/pdf') response = HttpResponse(mimetype='application/pdf')
filename = u'filename=%s-%s-#%s.pdf;' % (_("Election"), poll.title.replace(' ','_'), ballotnumber) filename = u'filename=%s-%s-#%s.pdf;' % (_("Election"), poll.assignment.name.replace(' ','_'), poll.ballot)
response['Content-Disposition'] = filename.encode('utf-8') response['Content-Disposition'] = filename.encode('utf-8')
doc = SimpleDocTemplate(response, pagesize=A4, topMargin=-6, bottomMargin=-6, leftMargin=0, rightMargin=0, showBoundary=False) doc = SimpleDocTemplate(response, pagesize=A4, topMargin=-6, bottomMargin=-6, leftMargin=0, rightMargin=0, showBoundary=False)
story = [Spacer(0,0*cm)] story = [Spacer(0,0*cm)]
@ -367,18 +351,13 @@ def print_assignment_poll(request, poll_id=None, ballotnumber=1, posts=None):
circle = "<img src='openslides/static/images/circle.png' width='15' height='15'/>&nbsp;" circle = "<img src='openslides/static/images/circle.png' width='15' height='15'/>&nbsp;"
cell = [] cell = []
cell.append(Spacer(0,0.8*cm)) cell.append(Spacer(0,0.8*cm))
cell.append(Paragraph(poll.title, stylesheet['Ballot_title'])) cell.append(Paragraph(_("Election") + ": " + poll.assignment.name, stylesheet['Ballot_title']))
cell.append(Paragraph(poll.description, stylesheet['Ballot_subtitle'])) cell.append(Paragraph(poll.description, stylesheet['Ballot_subtitle']))
options = poll.get_options().order_by('user__user__first_name') options = poll.get_options().order_by('user__user__first_name')
cell.append(Paragraph(ballotnumber+". "+_("ballot")+", "+str(len(options))+" "+ ungettext("candidate", "candidates", len(options))+", "+posts+" "+_("available posts"), stylesheet['Ballot_description'])) cell.append(Paragraph(str(poll.ballot)+". "+_("ballot")+", "+str(len(options))+" "+ ungettext("candidate", "candidates", len(options))+", "+str(poll.assignment.posts)+" "+_("available posts"), stylesheet['Ballot_description']))
cell.append(Spacer(0,0.4*cm)) cell.append(Spacer(0,0.4*cm))
if len(options) <= int(posts): if poll.optiondecision:
optiondecision = True
else:
optiondecision = False
if optiondecision:
for option in options: for option in options:
o = str(option).rsplit("(",1) o = str(option).rsplit("(",1)
cell.append(Paragraph(o[0], stylesheet['Ballot_option_name'])) cell.append(Paragraph(o[0], stylesheet['Ballot_option_name']))