Merge pull request #1232 from emanuelschuetze/pollslide-862
Pollslide for motion and assignment (Fixed #862)
This commit is contained in:
commit
deff477018
Binary file not shown.
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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')
|
||||
|
@ -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>
|
||||
|
@ -21,6 +21,13 @@
|
||||
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>
|
@ -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>
|
@ -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 %}
|
||||
|
||||
{% endif %}
|
||||
{% else %}
|
||||
|
||||
{% 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 %}
|
||||
|
@ -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(),
|
||||
|
@ -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(
|
||||
|
@ -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" %}
|
||||
|
@ -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,10 +730,10 @@ 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),
|
||||
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),
|
||||
url = reverse('motionpoll_delete', args=[str(self.motion.pk),
|
||||
str(self.poll_number)])
|
||||
else:
|
||||
url = super(MotionPoll, self).get_absolute_url(link)
|
||||
@ -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):
|
||||
"""
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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">
|
||||
<hr>
|
||||
<img src="{% static 'img/voting-total.png' %}" title="{% trans 'Votes cast' %}"> {{ poll.print_votescast }}
|
||||
</div>
|
||||
{% 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">
|
||||
<p>
|
||||
<a href="{% url 'motionpoll_create' motion.id %}" class="btn btn-mini">
|
||||
<i class="icon-assignment"></i> {% trans 'New vote' %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
54
openslides/motion/templates/motion/motionpoll_slide.html
Normal file
54
openslides/motion/templates/motion/motionpoll_slide.html
Normal 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>
|
@ -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 %}
|
||||
|
@ -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',
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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):
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user