Merge pull request #1170 from ostcar/poll_description

Added a poll description field for each assignment poll
This commit is contained in:
Norman Jäckel 2014-01-12 02:03:57 -08:00
commit e10d9e5e86
9 changed files with 56 additions and 40 deletions

View File

@ -22,6 +22,7 @@ Other:
- Changed api for main menu entries.
- Enhanced http error pages.
- Moved dashboard and select widgets view from projector to core app.
- Created a poll description field for each assignment-poll.
Version 1.5.1 (unreleased)

View File

@ -9,7 +9,7 @@ from openslides.utils.person import PersonFormField
from .models import Assignment
class AssignmentForm(forms.ModelForm, CssClassMixin):
class AssignmentForm(CssClassMixin, forms.ModelForm):
posts = forms.IntegerField(
min_value=1, initial=1, label=ugettext_lazy("Number of available posts"))
@ -18,8 +18,7 @@ class AssignmentForm(forms.ModelForm, CssClassMixin):
exclude = ('status', 'elected')
class AssignmentRunForm(forms.Form, CssClassMixin):
class AssignmentRunForm(CssClassMixin, forms.Form):
candidate = PersonFormField(
widget=forms.Select(attrs={'class': 'medium-input'}),
label=ugettext_lazy("Nominate a participant"),
)
label=ugettext_lazy("Nominate a participant"))

View File

@ -50,9 +50,9 @@ class Assignment(SlideMixin, AbsoluteUrlMixin, models.Model):
name = models.CharField(max_length=100, verbose_name=ugettext_lazy("Name"))
description = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Description"))
posts = models.PositiveSmallIntegerField(verbose_name=ugettext_lazy("Number of available posts"))
polldescription = models.CharField(
max_length=100, null=True, blank=True,
verbose_name=ugettext_lazy("Comment on the ballot paper"))
poll_description_default = models.CharField(
max_length=79, null=True, blank=True,
verbose_name=ugettext_lazy("Default comment on the ballot paper"))
status = models.CharField(max_length=3, choices=STATUS, default='sea')
class Meta:
@ -192,8 +192,8 @@ class Assignment(SlideMixin, AbsoluteUrlMixin, models.Model):
return person in self.elected
def gen_poll(self):
poll = AssignmentPoll(assignment=self)
poll.save()
poll = AssignmentPoll.objects.create(
assignment=self, description=self.poll_description_default)
poll.set_options([{'candidate': person} for person in self.candidates])
return poll
@ -255,9 +255,11 @@ class AssignmentOption(BaseOption):
class AssignmentPoll(RelatedModelMixin, CollectInvalid, CollectVotesCast,
PublishPollMixin, AbsoluteUrlMixin, BasePoll):
option_class = AssignmentOption
assignment = models.ForeignKey(Assignment, related_name='poll_set')
yesnoabstain = models.NullBooleanField()
description = models.CharField(
max_length=79, null=True, blank=True,
verbose_name=ugettext_lazy("Comment on the ballot paper"))
def __unicode__(self):
return _("Ballot %d") % self.get_ballot()
@ -297,3 +299,6 @@ class AssignmentPoll(RelatedModelMixin, CollectInvalid, CollectVotesCast,
def get_ballot(self):
return self.assignment.poll_set.filter(id__lte=self.id).count()
def append_pollform_fields(self, fields):
fields.append('description')

View File

@ -25,14 +25,13 @@
</small>
</h1>
{% if assignment.polldescription %}
<p><b>{% trans "Short description (for ballot paper)" %}:</b> {{ assignment.polldescription }}</p>
{% endif %}
<p>
{% trans "Special values" %}: <span class="badge badge-success">-1</span> = {% trans 'majority' %} | <span class="badge">-2</span> = {% trans 'undocumented' %}
</p>
<form action="" method="post" class="small-form">{% csrf_token %}
<p>
{% trans "Special values" %}:
<span class="badge badge-success">-1</span> = {% trans 'majority' %}|
<span class="badge">-2</span> = {% trans 'undocumented' %}
</p>
<table class="table table-striped table-bordered" style="width: auto;">
<tr>
<th>{% trans "Candidates" %}</th>
@ -73,10 +72,12 @@
</tr>
</table>
<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">
<i class="icon-print"></i> {% trans 'Ballot paper as PDF' %}
</a>
<a href="{% url 'assignment_poll_pdf' poll.id %}" class="btn" target="_blank">
<i class="icon-print"></i> {% trans 'Ballot paper as PDF' %}
</a>
</p>
<!-- Control buttons -->
<div class="control-group">

View File

@ -197,10 +197,11 @@ class AssignmentRunOtherDeleteView(SingleObjectMixin, QuestionView):
class PollCreateView(SingleObjectMixin, RedirectView):
model = Assignment
permission_required = 'assignment.can_manage_assignment'
url_name = 'assignment_poll_view'
url_name = 'assignment_detail'
def pre_redirect(self, *args, **kwargs):
self.object = self.get_object().gen_poll()
self.object = self.get_object()
self.object.gen_poll()
messages.success(self.request, _("New ballot was successfully created."))
@ -213,7 +214,7 @@ class PollUpdateView(PollFormView):
self.assignment = self.poll.get_assignment()
context['assignment'] = self.assignment
context['poll'] = self.poll
context['polls'] = self.assignment.poll_set.filter(assignment=self.assignment)
context['polls'] = self.assignment.poll_set.all()
context['ballotnumber'] = self.poll.get_ballot()
return context
@ -513,7 +514,7 @@ class AssignmentPollPDF(PDFView):
_("Election") + ": " + self.poll.assignment.name,
stylesheet['Ballot_title']))
cell.append(Paragraph(
self.poll.assignment.polldescription,
self.poll.description or '',
stylesheet['Ballot_subtitle']))
options = self.poll.get_options()

View File

@ -5,7 +5,7 @@ from django import forms
from openslides.utils.forms import CssClassMixin
class OptionForm(forms.Form, CssClassMixin):
class OptionForm(CssClassMixin, forms.Form):
def __init__(self, *args, **kwargs):
extra = kwargs.pop('extra')
formid = kwargs.pop('formid')
@ -20,5 +20,4 @@ class OptionForm(forms.Form, CssClassMixin):
label=value,
initial=weight,
min_value=-2,
required=False,
)
required=False)

View File

@ -30,19 +30,19 @@ class PollFormView(FormMixin, TemplateView):
error = True
if error:
return self.render_to_response(self.get_context_data(
response = self.render_to_response(self.get_context_data(
forms=option_forms,
pollform=pollform,
))
pollform=pollform))
else:
for form in option_forms:
data = {}
for value in self.poll.get_vote_values():
data[value] = form.cleaned_data[value]
self.poll.set_vote_objects_with_values(form.option, data)
for form in option_forms:
data = {}
for value in self.poll.get_vote_values():
data[value] = form.cleaned_data[value]
self.poll.set_vote_objects_with_values(form.option, data)
pollform.save()
return HttpResponseRedirect(self.get_success_url())
pollform.save()
response = HttpResponseRedirect(self.get_success_url())
return response
def get_poll_class(self):
if self.poll_class is not None:
@ -71,4 +71,4 @@ class PollFormView(FormMixin, TemplateView):
def get_modelform_class(self):
fields = []
self.poll.append_pollform_fields(fields)
return modelform_factory(self.poll.__class__, fields=fields)
return modelform_factory(type(self.poll), fields=fields)

View File

@ -142,6 +142,9 @@ input, textarea {
.small-form input {
width: 55px;
}
.normal-form input {
width: 320px;
}
textarea {
height: 100px;
}
@ -379,7 +382,7 @@ legend + .control-group {
margin: 0 5px 0 45px;
width: auto;
}
/* hide optional column */
/* hide optional column */
.optional {
display: none;
}

View File

@ -10,6 +10,13 @@ from openslides.utils.main_menu import MainMenuEntry
class MainMenuEntryObject(TestCase):
request_factory = RequestFactory()
def tearDown(self):
"""
Remove all receivers of the MainMenuEntry-signal, so it is not called in
other tests.
"""
MainMenuEntry.signal.receivers = []
def get_entry(self, cls):
request = self.request_factory.get('/')
request.user = AnonymousUser()