Merge pull request #1232 from emanuelschuetze/pollslide-862

Pollslide for motion and assignment (Fixed #862)
This commit is contained in:
Norman Jäckel 2014-05-02 23:47:54 +02:00
commit deff477018
24 changed files with 282 additions and 179 deletions

Binary file not shown.

View File

@ -12,6 +12,7 @@ from openslides.config.api import config
from openslides.poll.models import (BaseOption, BasePoll, BaseVote,
CollectDefaultVotesMixin,
PublishPollMixin)
from openslides.projector.api import get_active_object, update_projector
from openslides.projector.models import RelatedModelMixin, SlideMixin
from openslides.utils.exceptions import OpenSlidesError
from openslides.utils.models import AbsoluteUrlMixin
@ -190,6 +191,11 @@ class Assignment(SlideMixin, AbsoluteUrlMixin, models.Model):
candidate = self.assignment_candidates.get(person=person)
candidate.elected = value
candidate.save()
# update projector if assignment or assignmentpoll slide is active
active_object = get_active_object()
if (type(active_object) is type(self) and active_object.pk == self.pk) or \
(type(active_object) is AssignmentPoll and active_object.assignment_id == self.pk):
update_projector()
def is_elected(self, person):
return person in self.elected
@ -271,8 +277,12 @@ class AssignmentOption(BaseOption):
return unicode(self.candidate)
class AssignmentPoll(RelatedModelMixin, CollectDefaultVotesMixin,
class AssignmentPoll(SlideMixin, RelatedModelMixin, CollectDefaultVotesMixin,
PublishPollMixin, AbsoluteUrlMixin, BasePoll):
slide_callback_name = 'assignmentpoll'
"""Name of the callback for the slide-system."""
option_class = AssignmentOption
assignment = models.ForeignKey(Assignment, related_name='poll_set')
yesnoabstain = models.NullBooleanField()
@ -284,10 +294,15 @@ class AssignmentPoll(RelatedModelMixin, CollectDefaultVotesMixin,
return _("Ballot %d") % self.get_ballot()
def get_absolute_url(self, link='update'):
"""
Return an URL for the poll.
The keyargument 'link' can be 'update' or 'delete'.
"""
if link == 'update':
url = reverse('assignment_poll_view', args=[str(self.pk)])
url = reverse('assignmentpoll_update', args=[str(self.pk)])
elif link == 'delete':
url = reverse('assignment_poll_delete', args=[str(self.pk)])
url = reverse('assignmentpoll_delete', args=[str(self.pk)])
else:
url = super(AssignmentPoll, self).get_absolute_url(link)
return url
@ -325,3 +340,6 @@ class AssignmentPoll(RelatedModelMixin, CollectDefaultVotesMixin,
def append_pollform_fields(self, fields):
fields.append('description')
super(AssignmentPoll, self).append_pollform_fields(fields)
def get_slide_context(self, **context):
return super(AssignmentPoll, self).get_slide_context(poll=self)

View File

@ -59,8 +59,8 @@ def setup_assignment_config(sender, **kwargs):
default_value=False,
form_field=forms.BooleanField(
required=False,
label=ugettext_lazy('Only publish voting results for selected '
'winners (Projector view only)')))
label=ugettext_lazy('Publish election result for elected candidates only '
'(projector view)')))
group_ballot = ConfigGroup(
title=ugettext_lazy('Ballot and ballot papers'),
variables=(assignment_poll_vote_values,

View File

@ -2,6 +2,7 @@
from openslides.projector.api import register_slide_model
from .models import Assignment
from .models import Assignment, AssignmentPoll
register_slide_model(Assignment, 'assignment/slide.html')
register_slide_model(AssignmentPoll, 'assignment/assignmentpoll_slide.html')

View File

@ -18,6 +18,8 @@
{% block content %}
<h1>
{{ assignment }}
<br>
<small>{% trans "Election" %}</small>
<small class="pull-right">
<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>
@ -141,9 +143,9 @@
{% endif %}
<!-- Results -->
<!-- Election result -->
{% if assignment.status != "sea" or polls.exists %}
<h4>{% trans "Election results" %}</h4>
<h4>{% trans "Election result" %}</h4>
{% if polls.exists %}
<table class="table table-striped table-bordered">
<tr>
@ -154,8 +156,8 @@
{{ poll.get_ballot|ordinal|safe }} {% trans 'ballot' %}
{% if perms.assignment.can_manage_assignment %}
<a class="publish_link btn btn-mini btn-danger {% if poll.published %}btn-primary{% endif %}"
href="{% url 'assignment_poll_publish_status' poll.id %}"
rel="tooltip" data-original-title="{% trans 'Publish results' %}">
href="{% url 'assignmentpoll_publish_status' poll.id %}"
rel="tooltip" data-original-title="{% trans 'Publish result' %}">
{% if poll.published %}
<i class="icon-checked-new_white"></i>
{% else %}
@ -164,11 +166,15 @@
</a>
</p>
<p class="text-center">
<a href="{% url 'assignment_poll_pdf' poll.id %}" class="btn btn-mini" target="_blank"
<a href="{{ poll|absolute_url:'projector' }}"
class="btn btn-mini activate_link {% if poll.is_active_slide %}btn-primary{% endif %}"
rel="tooltip" data-original-title="{% trans 'Show election result' %}">
<i class="icon-facetime-video {% if poll.is_active_slide %}icon-white{% endif %}"></i></a>
<a href="{% url 'assignmentpoll_pdf' poll.id %}" class="btn btn-mini" target="_blank"
rel="tooltip" data-original-title="{% trans 'Ballot paper as PDF' %}"><i class="icon-print"></i></a>
<a href="{% url 'assignment_poll_view' poll.id %}" class="btn btn-mini"
<a href="{% url 'assignmentpoll_update' poll.id %}" 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="{% url 'assignmentpoll_delete' poll.id %}" class="btn btn-mini"
rel="tooltip" data-original-title="{% trans 'Delete' %}"><i class="icon-remove"></i></a>
</p>
{% endif %}
@ -176,7 +182,7 @@
{% endfor %}
{% if assignment.candidates and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
<th class="span1 nobr">
<a href="{% url 'assignment_poll_create' assignment.pk %}" class="btn btn-mini">
<a href="{% url 'assignmentpoll_create' assignment.pk %}" class="btn btn-mini">
<i class="icon-plus"></i> {% trans 'New ballot' %}
</a>
</th>
@ -275,7 +281,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_poll_create' assignment.id %}' class="btn">
<a href='{% url 'assignmentpoll_create' assignment.id %}' class="btn">
<i class="icon-plus"></i> {% trans 'New ballot' %}
</a>
</p>

View File

@ -13,15 +13,22 @@
{{ ballotnumber|ordinal|safe }} {% trans "ballot" %}
</small>
<small class="pull-right">
<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.core.can_manage_projector %}
<a href="{{ assignment|absolute_url:'projector' }}"
class="activate_link btn {% if assignment.is_active_slide %}btn-primary{% endif %} btn-mini"
rel="tooltip" data-original-title="{% trans 'Show election' %}">
<i class="icon-facetime-video {% if assignment.is_active_slide %}icon-white{% endif %}"></i>
</a>
{% endif %}
<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.core.can_manage_projector %}
<a href="{{ assignment|absolute_url:'projector' }}"
class="activate_link btn {% if assignment.is_active_slide %}btn-primary{% endif %} btn-mini"
rel="tooltip" data-original-title="{% trans 'Show election' %}">
<i class="icon-facetime-video {% if assignment.is_active_slide %}icon-white{% endif %}"></i>
</a>
<a class="btn btn-mini activate_link {% if poll.is_active_slide %}btn-primary{% endif %}" href="{{ poll|absolute_url:'projector' }}"
rel="tooltip" data-original-title="{% trans 'Show election result' %}">
<i class="icon-facetime-video {% if poll.is_active_slide %}icon-white{% endif %}"></i> {% trans "Vote result" %}</a>
{% endif %}
{% if perms.motion.can_manage_motion %}
<a class="btn btn-mini" href="{{ poll|absolute_url:'delete' }}"
rel="tooltip" data-original-title="{% trans 'Delete ballot' %}"><i class="icon-remove"></i></a>
{% endif %}
</small>
</h1>
@ -50,7 +57,7 @@
{% endfor %}
</tr>
{% endfor %}
<tr>
<tr class="total warning">
<td>{% trans "Valid votes" %}</td>
{% for value in poll.get_vote_values %}
{% if forloop.first %}
@ -85,7 +92,7 @@
<p><strong>{% trans "Short description (for ballot paper)" %}:</strong></p>
<p class="normal-form">{{ pollform.description }}</p>
<p>
<a href="{% url 'assignment_poll_pdf' poll.id %}" class="btn" target="_blank">
<a href="{% url 'assignmentpoll_pdf' poll.id %}" class="btn" target="_blank">
<i class="icon-print"></i> {% trans 'Ballot paper as PDF' %}
</a>
</p>

View File

@ -0,0 +1,59 @@
{% load i18n %}
{% load humanize %}
{% load staticfiles %}
{% load tags %}
<h1>
{{ poll.assignment }}
<br>
<small>
{% trans "Election" %}
{% if poll.get_ballot > 1 %}| {{ poll.get_ballot|ordinal|safe }} {% trans "ballot" %}{% endif %}
</small>
</h1>
<p>
{% if poll.has_votes and poll.published %}
<table class="result big nobr">
{% for option in poll.get_options %}
<tr {% if option.candidate in poll.assignment.elected %}class="elected"{% endif %}>
<td>{{ option }}</td>
<td class="bold">
{% if not "assignment_publish_winner_results_only"|get_config or option.candidate in poll.assignment.elected %}
{% if poll.yesnoabstain %}
<img src="{% static 'img/voting-yes.png' %}"> {% trans 'Yes' %}:
{{ option.Yes }}<br>
<img src="{% static 'img/voting-no.png' %}"> {% trans 'No' %}:
{{ option.No }}<br>
<img src="{% static 'img/voting-abstention.png' %}"> {% trans 'Abstention' %}:
{{ option.Abstain }}
{% else %}
{{ option.Votes }}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
{% if poll.votesvalid != None %}
<tr class="total">
<td><img src="{% static 'img/voting-yes-grey.png' %}"> {% trans 'Valid votes' %}:</td>
<td class="bold">{{ poll.print_votesvalid }}</td>
</tr>
{% endif %}
{% if poll.votesinvalid != None %}
<tr class="total">
<td><img src="{% static 'img/voting-invalid.png' %}"> {% trans 'Invalid votes' %}:</td>
<td class="bold">{{ poll.print_votesinvalid }}</td>
</tr>
{% endif %}
{% if poll.votescast != None %}
<tr class="total">
<td><img src="{% static 'img/voting-total.png' %}"> {% trans 'Votes cast' %}:</td>
<td class="bold">{{ poll.print_votescast }}</td>
</tr>
{% endif %}
</table>
{% else %}
<i>{% trans "No result available." %}</i>
{% endif %}
</p>

View File

@ -1,6 +1,7 @@
{% load i18n %}
{% load staticfiles %}
{% load tags %}
{% load humanize %}
<div id="sidebar">
<div class="well">
@ -38,83 +39,15 @@
<p><br></p>
{% endif %}
{% if polls.exists %}
<h3>{% trans "Election results" %}</h3>
<table class="table-striped table-bordered">
<tr>
<th>{% trans "Candidates" %}</th>
{% for poll in polls %}
<th>
<nobr>{{ poll.get_ballot }}. {% trans "ballot" %}</nobr>
</th>
{% if assignment.status == "fin" %}
<h3>{% trans "Elected candidates" %}</h3>
<ol>
{% for person in assignment.elected %}
<li>{{ person }}</li>
{% empty %}
<li style="list-style: none outside none;">
<i>{% trans "No candidates elected." %}</i>
</li>
{% endfor %}
</tr>
{% for candidate, poll_list in vote_results.items %}
<tr>
<td class="{% if candidate in assignment.elected %} elected{% endif %}">
{% if candidate in assignment.elected %}
<a class="elected">
<img src="{% static 'img/voting-yes.png' %}" title="{% trans 'Candidate is elected' %}">
</a>
{% endif %}
{{ candidate }}
</td>
{% for vote in poll_list %}
<td style="white-space:nowrap;"{% if candidate in assignment.elected %} class="elected"{% endif %}>
{% if not "assignment_publish_winner_results_only"|get_config or candidate in assignment.elected %}
{% if 'Yes' in vote and 'No' in vote and 'Abstain' in vote %}
<img src="{% static 'img/voting-yes.png' %}" title="{% trans 'Yes' %}"> {{ vote.Yes }}<br>
<img src="{% static 'img/voting-no.png' %}" title="{% trans 'No' %}"> {{ vote.No }}<br>
<img src="{% static 'img/voting-abstention.png' %}" title="{% trans 'Abstention' %}"> {{ vote.Abstain }}<br>
{% elif 'Votes' in vote %}
<img src="{% static 'img/voting-yes.png' %}" title="{% trans 'Yes' %}"> {{ vote.Votes }}
{% elif vote == None %}
{% trans 'was not a <br> candidate'%}
{% else %}
&nbsp;
{% endif %}
{% else %}
&nbsp;
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
<tr class="total">
<td>{% trans 'Valid votes' %}</td>
{% for poll in polls %}
<td style="white-space:nowrap;">
{% if poll.has_votes %}
<img src="{% static 'img/voting-yes-grey.png' %}" title="{% trans 'Valid votes' %}">
{{ poll.print_votesvalid }}
{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>{% trans 'Invalid votes' %}</td>
{% for poll in polls %}
<td style="white-space:nowrap;">
{% if poll.has_votes %}
<img src="{% static 'img/voting-invalid.png' %}" title="{% trans 'Invalid votes' %}">
{{ poll.print_votesinvalid }}
{% endif %}
</td>
{% endfor %}
</tr>
<tr class="total">
<td>
{% trans 'Votes cast' %}
</td>
{% for poll in polls %}
<td style="white-space:nowrap;">
{% if poll.has_votes %}
<img src="{% static 'img/voting-total.png' %}" title="{% trans 'Votes cast' %}">
{{ poll.print_votescast }}
{% endif %}
</td>
{% endfor %}
</tr>
</table>
</ol>
{% endif %}

View File

@ -42,10 +42,6 @@ urlpatterns = patterns(
views.AssignmentRunOtherDeleteView.as_view(),
name='assignment_delother'),
url(r'^poll/(?P<poll_id>\d+)/print/$',
views.AssignmentPollPDF.as_view(),
name='assignment_poll_pdf'),
url(r'^(?P<pk>\d+)/agenda/$',
views.CreateRelatedAgendaItemView.as_view(),
name='assignment_create_agenda'),
@ -60,21 +56,25 @@ urlpatterns = patterns(
url(r'^(?P<pk>\d+)/gen_poll/$',
views.PollCreateView.as_view(),
name='assignment_poll_create'),
name='assignmentpoll_create'),
url(r'^poll/(?P<poll_id>\d+)/$',
url(r'^poll/(?P<poll_id>\d+)/edit/$',
views.PollUpdateView.as_view(),
name='assignment_poll_view'),
name='assignmentpoll_update'),
url(r'^poll/(?P<pk>\d+)/del/$',
views.AssignmentPollDeleteView.as_view(),
name='assignment_poll_delete'),
name='assignmentpoll_delete'),
url(r'^poll/(?P<poll_id>\d+)/print/$',
views.AssignmentPollPDF.as_view(),
name='assignmentpoll_pdf'),
# TODO: use seperate urls to publish and unpublish the poll
# see assignment_user_elected
url(r'^poll/(?P<pk>\d+)/pub/$',
views.SetPublishStatusView.as_view(),
name='assignment_poll_publish_status'),
name='assignmentpoll_publish_status'),
url(r'^(?P<pk>\d+)/elected/(?P<user_id>[^/]+)/$',
views.SetElectedView.as_view(),

View File

@ -204,7 +204,7 @@ class PollCreateView(SingleObjectMixin, RedirectView):
class PollUpdateView(PollFormView):
poll_class = AssignmentPoll
template_name = 'assignment/poll_view.html'
template_name = 'assignment/assignmentpoll_form.html'
def get_context_data(self, **kwargs):
context = super(PollUpdateView, self).get_context_data(**kwargs)
@ -382,7 +382,7 @@ class AssignmentPDF(PDFView):
# Left side
cell3a = []
cell3a.append(Paragraph(
"%s:" % (_("Vote results")), stylesheet['Heading4']))
"%s:" % (_("Vote result")), stylesheet['Heading4']))
if polls.count() == 1:
cell3a.append(Paragraph(

View File

@ -12,7 +12,7 @@
{% if field.name == "q" %}
<label for="id_q">{% trans 'Search' %}:</label>
<div class="input-append">
<input type="text" id="id_q" name="q" class="" value="{{ field.value }}">
<input type="text" id="id_q" name="q" value="{{ field.value }}">
<button type="submit" class="btn">{% trans "Search" %}</button>
</div>
{% elif field.name == "models" %}

View File

@ -693,8 +693,12 @@ class MotionOption(BaseOption):
"""The VoteClass, to witch this Class links."""
class MotionPoll(RelatedModelMixin, CollectDefaultVotesMixin, AbsoluteUrlMixin, BasePoll):
"""The Class to saves the poll results for a motion poll."""
class MotionPoll(SlideMixin, RelatedModelMixin, CollectDefaultVotesMixin,
AbsoluteUrlMixin, BasePoll):
"""The Class to saves the vote result for a motion poll."""
slide_callback_name = 'motionpoll'
"""Name of the callback for the slide-system."""
motion = models.ForeignKey(Motion, related_name='polls')
"""The motion to witch the object belongs."""
@ -726,11 +730,11 @@ class MotionPoll(RelatedModelMixin, CollectDefaultVotesMixin, AbsoluteUrlMixin,
The keyargument 'link' can be 'update' or 'delete'.
"""
if link == 'update':
url = reverse('motion_poll_update', args=[str(self.motion.pk),
str(self.poll_number)])
url = reverse('motionpoll_update', args=[str(self.motion.pk),
str(self.poll_number)])
elif link == 'delete':
url = reverse('motion_poll_delete', args=[str(self.motion.pk),
str(self.poll_number)])
url = reverse('motionpoll_delete', args=[str(self.motion.pk),
str(self.poll_number)])
else:
url = super(MotionPoll, self).get_absolute_url(link)
return url
@ -747,6 +751,9 @@ class MotionPoll(RelatedModelMixin, CollectDefaultVotesMixin, AbsoluteUrlMixin,
def get_percent_base_choice(self):
return config['motion_poll_100_percent_base']
def get_slide_context(self, **context):
return super(MotionPoll, self).get_slide_context(poll=self)
class State(models.Model):
"""

View File

@ -97,7 +97,7 @@ def motion_to_pdf(pdf, motion):
cell5b.append(Paragraph("%s" % version.version_number, stylesheet['Normal']))
motion_data.append([cell5a, cell5b])
# voting results
# voting result
polls = []
for poll in motion.polls.all():
if not poll.has_votes():
@ -108,7 +108,7 @@ def motion_to_pdf(pdf, motion):
cell6a = []
cell6b = []
cell6a.append(Paragraph("<font name='Ubuntu-Bold'>%s:</font>" %
_("Vote results"), stylesheet['Heading4']))
_("Vote result"), stylesheet['Heading4']))
ballotcounter = 0
for poll in polls:
ballotcounter += 1

View File

@ -2,6 +2,7 @@
from openslides.projector.api import register_slide_model
from .models import Motion
from .models import Motion, MotionPoll
register_slide_model(Motion, 'motion/slide.html')
register_slide_model(MotionPoll, 'motion/motionpoll_slide.html')

View File

@ -39,20 +39,15 @@ td.diff_header {
}
/*** motion vote results list ***/
#motion-vote-results {
list-style: none;
}
#motion-vote-results li {
margin-top: 5px;
margin-bottom: 15px;
}
#motion-vote-results img {
/*** motion vote result ***/
.well .result img {
margin-top: -4px;
}
#motion-vote-results .resultline {
.well .result {
margin-bottom: 10px;
}
.well .result hr {
border-top: 1px solid;
padding-top: 5px;
margin: 5px 0;
width: 10em;
}

View File

@ -204,54 +204,60 @@
<span class="label label-info">{% trans motion.state.name %}</span>
<br>
<!-- Vote results -->
<h5>{% trans "Vote results" %}:</h5>
<!-- Vote result -->
<h5>{% trans "Vote result" %}:</h5>
{% with motion.polls.all as polls %}
<ul id="motion-vote-results">
{% for poll in polls %}
{% if perms.motion.can_manage_motion or poll.has_votes %}
<li><b>{{ poll.poll_number|ordinal|safe }} {% trans "vote" %}</b>
<p>{{ poll.poll_number|ordinal|safe }} {% trans "vote" %}:<br>
{% if perms.motion.can_manage_motion %}
<a class="btn btn-mini" href="{{ poll|absolute_url:'update' }}" title="{% trans 'Edit Vote' %}"><i class="icon-pencil"></i></a>
<a class="btn btn-mini" href="{{ poll|absolute_url:'delete' }}" title="{% trans 'Delete Vote' %}"><i class="icon-remove"></i></a>
<a class="btn btn-mini activate_link {% if poll.is_active_slide %}btn-primary{% endif %}" href="{{ poll|absolute_url:'projector' }}"
rel="tooltip" data-original-title="{% trans 'Show vote result' %}">
<i class="icon-facetime-video {% if poll.is_active_slide %}icon-white{% endif %}"></i></a>
<a href="{% url 'motionpoll_pdf' motion.id poll.poll_number %}" class="btn btn-mini" target="_blank"
rel="tooltip" data-original-title="{% trans 'Ballot paper as PDF' %}"><i class="icon-print"></i></a>
<a class="btn btn-mini" href="{{ poll|absolute_url:'update' }}"
rel="tooltip" data-original-title="{% trans 'Edit Vote' %}"><i class="icon-pencil"></i></a>
<a class="btn btn-mini" href="{{ poll|absolute_url:'delete' }}"
rel="tooltip" data-original-title="{% trans 'Delete Vote' %}"><i class="icon-remove"></i></a>
</p>
{% endif %}
<br>
{% if poll.has_votes %}
<div class="result">
{% with poll.get_options.0 as option %}
<img src="{% static 'img/voting-yes.png' %}" title="{% trans 'Yes' %}"> {{ option.Yes }}<br>
<img src="{% static 'img/voting-no.png' %}" title="{% trans 'No' %}"> {{ option.No }}<br>
<img src="{% static 'img/voting-abstention.png' %}" title="{% trans 'Abstention' %}"> {{ option.Abstain }}<br>
{% if poll.votesvalid != None or poll.votesinvalid != None %}
<div class="resultline">
<hr>
{% if poll.votesvalid != None %}
<img src="{% static 'img/voting-yes-grey.png' %}" title="{% trans 'Valid votes' %}"> {{ poll.print_votesvalid }}<br>
{% endif %}
{% if poll.votesinvalid != None %}
<img src="{% static 'img/voting-invalid.png' %}" title="{% trans 'Invalid votes' %}"> {{ poll.print_votesinvalid }}<br>
{% endif %}
</div>
{% endif %}
{% if poll.votescast != None %}
<div class="resultline">
<img src="{% static 'img/voting-total.png' %}" title="{% trans 'Votes cast' %}"> {{ poll.print_votescast }}
</div>
<hr>
<img src="{% static 'img/voting-total.png' %}" title="{% trans 'Votes cast' %}"> {{ poll.print_votescast }}
{% endif %}
{% endwith %}
</div>
{% else %}
{% if perms.motion.can_manage_motion %}
<span class="label label-info">{% trans 'No results' %}</span>
<p><span class="label label-info">{% trans 'No result' %}</span></p>
{% endif %}
{% endif %}
</li>
{% endif %}
{% empty %}
<span style="margin-left:-25px;"></span>
{% endfor %}
</ul>
{% if allowed_actions.create_poll %}
<a href="{% url 'motion_poll_create' motion.id %}" class="btn btn-mini">
<i class="icon-assignment"></i> {% trans 'New vote' %}
</a>
<p>
<a href="{% url 'motionpoll_create' motion.id %}" class="btn btn-mini">
<i class="icon-assignment"></i> {% trans 'New vote' %}
</a>
</p>
{% endif %}
{% endwith %}

View File

@ -86,7 +86,7 @@
{% endif %}</td>
<td>
<span style="width: 1px; white-space: nowrap;">
{% if perms.projector.can_manage_projector %}
{% if perms.core.can_manage_projector %}
<a href="{{ motion|absolute_url:'projector' }}" class="activate_link btn {% if motion.is_active_slide %}btn-primary{% endif %} btn-mini"
rel="tooltip" data-original-title="{% trans 'Show motion' %}">
<i class="icon-facetime-video {% if motion.is_active_slide %}icon-white{% endif %}"></i>

View File

@ -15,15 +15,21 @@
{% trans "Motion" %} {{ motion.identifier }}, {{ poll }}
</small>
<small class="pull-right">
<div class="btn-toolbar">
<a href="{% url 'motion_detail' motion.id %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to motion" %}</a>
<!-- activate projector -->
{% if perms.core.can_manage_projector %}
<a href="{{ motion|absolute_url:'projector' }}" class="activate_link btn {% if motion.is_active_slide %}btn-primary{% endif %} btn-mini" rel="tooltip" data-original-title="{% trans 'Show motion' %}">
<a href="{{ motion|absolute_url:'projector' }}" class="activate_link btn {% if motion.is_active_slide %}btn-primary{% endif %} btn-mini"
rel="tooltip" data-original-title="{% trans 'Show motion' %}">
<i class="icon-facetime-video {% if motion.is_active_slide %}icon-white{% endif %}"></i>
</a>
<a class="btn btn-mini activate_link {% if poll.is_active_slide %}btn-primary{% endif %}" href="{{ poll|absolute_url:'projector' }}"
rel="tooltip" data-original-title="{% trans 'Show vote result' %}">
<i class="icon-facetime-video {% if poll.is_active_slide %}icon-white{% endif %}"></i> {% trans "Vote result" %}</a>
{% endif %}
{% if perms.motion.can_manage_motion %}
<a class="btn btn-mini" href="{{ poll|absolute_url:'delete' }}"
rel="tooltip" data-original-title="{% trans 'Delete Vote' %}"><i class="icon-remove"></i></a>
{% endif %}
</div>
</small>
</h1>
@ -44,15 +50,15 @@
<td>{{ value.errors }}{{ value }}</td>
</tr>
{% endfor %}
<tr class="total">
<tr class="total warning">
<td>{% trans "Valid votes" %}</td>
<td>{{ pollform.votesvalid.errors }}{{ pollform.votesvalid }}</td>
</tr>
<tr class="">
<tr>
<td>{% trans "Invalid votes" %}</td>
<td>{{ pollform.votesinvalid.errors }}{{ pollform.votesinvalid }}</td>
</tr>
<tr class="total">
<tr class="total warning">
<td>{% trans "Votes cast" %}</td>
<td>{{ pollform.votescast.errors }}{{ pollform.votescast }}</td>
</tr>
@ -62,7 +68,7 @@
<!-- ballot paper button -->
<p>
<a href="{% url 'motion_poll_pdf' motion.id poll.poll_number %}" class="btn" target="_blank">
<a href="{% url 'motionpoll_pdf' motion.id poll.poll_number %}" class="btn" target="_blank">
<i class="icon-print"></i> {% trans 'Ballot paper as PDF' %}
</a>
</p>

View File

@ -0,0 +1,54 @@
{% load i18n %}
{% load humanize %}
{% load staticfiles %}
<h1>
{{ poll.motion.active_version.title }}
<br>
<small>
{% trans "Motion" %} {{ poll.motion.identifier|default:'' }}
{% if poll.motion.get_active_version.version_number > 1 %} | {% trans 'Version' %} {{ poll.motion.active_version.version_number }}{% endif %}
{% if poll.poll_number > 1 %}| {{ poll.poll_number|ordinal|safe }} {% trans "vote" %}{% endif %}
</small>
</h1>
<p>
{% if poll.has_votes %}
{% with poll.get_options.0 as option %}
<table class="well result big">
<tr>
<td><img src="{% static 'img/voting-yes.png' %}"> {% trans 'Yes' %}:</td>
<td class="bold">{{ option.Yes }}</td>
</tr>
<tr>
<td><img src="{% static 'img/voting-no.png' %}"> {% trans 'No' %}:</td>
<td class="bold">{{ option.No }}</td>
</tr>
<tr>
<td><img src="{% static 'img/voting-abstention.png' %}"> {% trans 'Abstention' %}:</td>
<td class="bold">{{ option.No }}</td>
</tr>
{% if poll.votesvalid != None %}
<tr class="total">
<td><img src="{% static 'img/voting-yes-grey.png' %}"> {% trans 'Valid votes' %}:</td>
<td class="bold">{{ poll.print_votesvalid }}</td>
</tr>
{% endif %}
{% if poll.votesinvalid != None %}
<tr class="total">
<td><img src="{% static 'img/voting-invalid.png' %}"> {% trans 'Invalid votes' %}:</td>
<td class="bold">{{ poll.print_votesinvalid }}</td>
</tr>
{% endif %}
{% if poll.votescast != None %}
<tr class="total">
<td><img src="{% static 'img/voting-total.png' %}"> {% trans 'Votes cast' %}:</td>
<td class="bold">{{ poll.print_votescast }}</td>
</tr>
{% endif %}
</table>
{% endwith %}
{% else %}
<i>{% trans "No result available." %}</i>
{% endif %}
</p>

View File

@ -8,7 +8,7 @@
<h4 class="first">{% trans "Status" %}:</h4>
{% trans motion.state.name %}
<!-- poll results -->
<!-- vote result -->
{% with motion.polls.all as polls %}
{% if polls.exists and polls.0.has_votes %}
{% for poll in polls reversed %}
@ -19,12 +19,12 @@
<h4>{% trans "Poll result" %}:</h4>
{% endif %}
{% with poll.get_options.0 as option %}
<div class="results">
<div class="result">
<img src="{% static 'img/voting-yes.png' %}" title="{% trans 'Yes' %}"> {{ option.Yes }} <br>
<img src="{% static 'img/voting-no.png' %}" title="{% trans 'No' %}"> {{ option.No }} <br>
<img src="{% static 'img/voting-abstention.png' %}" title="{% trans 'Abstention' %}"> {{ option.Abstain }}<br>
{% if poll.votesvalid != None or poll.votesinvalid != None %}
<div class="resultline"></div>
<hr>
{% if poll.votesvalid != None %}
<img src="{% static 'img/voting-yes-grey.png' %}" title="{% trans 'Valid votes' %}"> {{ poll.print_votesvalid }}<br>
{% endif %}
@ -33,14 +33,14 @@
{% endif %}
{% endif %}
{% if poll.votescast != None %}
<div class="resultline"></div>
<hr>
<img src="{% static 'img/voting-total.png' %}" title="{% trans 'Votes cast' %}"> {{ poll.print_votescast }}
{% endif %}
</div>
{% endwith %}
{% else %}
{% if poll|length == 1 %}
<i>{% trans "No poll results available." %}</i>
<i>{% trans "No result available." %}</i>
{% endif %}
{% endif %}
{% endfor %}

View File

@ -52,19 +52,19 @@ urlpatterns = patterns(
url(r'^(?P<pk>\d+)/create_poll/$',
'poll_create',
name='motion_poll_create'),
name='motionpoll_create'),
url(r'^(?P<pk>\d+)/poll/(?P<poll_number>\d+)/edit/$',
'poll_update',
name='motion_poll_update'),
name='motionpoll_update'),
url(r'^(?P<pk>\d+)/poll/(?P<poll_number>\d+)/del/$',
'poll_delete',
name='motion_poll_delete'),
name='motionpoll_delete'),
url(r'^(?P<pk>\d+)/poll/(?P<poll_number>\d+)/pdf/$',
'poll_pdf',
name='motion_poll_pdf'),
name='motionpoll_pdf'),
url(r'^(?P<pk>\d+)/set_state/(?P<state>\d+)/$',
'set_state',

View File

@ -483,7 +483,7 @@ class PollCreateView(SingleObjectMixin, RedirectView):
"""
permission_required = 'motion.can_manage_motion'
model = Motion
url_name = 'motion_poll_detail'
url_name = 'motionpoll_detail'
def get(self, request, *args, **kwargs):
"""
@ -504,7 +504,7 @@ class PollCreateView(SingleObjectMixin, RedirectView):
"""
Return the URL to the UpdateView of the poll.
"""
return reverse('motion_poll_update', args=[self.object.pk, self.poll.poll_number])
return reverse('motionpoll_update', args=[self.object.pk, self.poll.poll_number])
poll_create = PollCreateView.as_view()
@ -545,7 +545,7 @@ class PollUpdateView(PollMixin, PollFormView):
Poll Class to use for this view.
"""
template_name = 'motion/poll_form.html'
template_name = 'motion/motionpoll_form.html'
def get_context_data(self, **kwargs):
"""

View File

@ -36,7 +36,7 @@ class BaseOption(models.Model):
try:
return self.get_votes().get(value=name)
except self.get_vote_class().DoesNotExist:
return None
raise KeyError
class BaseVote(models.Model):

View File

@ -53,7 +53,7 @@ body{
background: url(../img/glyphicons_054_clock_big.png) no-repeat scroll 0px 0px;
}
/*** CONTENT with base style elements***/
/*** CONTENT with base style elements ***/
#content {
position: absolute;
left: 75px;
@ -104,11 +104,21 @@ li {
.well h4.first {
margin-top: 0;
}
.resultline {
.well .result {
line-height: 30px;
}
.well .result hr {
border-top: 1px solid;
margin: 5px 0;
width: 10em;
}
.result.big {
font-size: 120%;
line-height: 40px;
}
.result .bold {
font-weight: bold;
}
hr {
margin: 10px 0;
}
@ -187,6 +197,6 @@ tr.total td {
border-top: 1px solid #333333;
background-color: #e3e3e3;
}
td.elected {
tr.elected td {
background-color: #BED4DE !important;
}