canidate in assignment can be marked as elected

This commit is contained in:
Oskar Hahn 2011-09-03 11:42:44 +02:00
parent 2a89ccca5a
commit dcbeb452fb
10 changed files with 142 additions and 26 deletions

View File

@ -6,7 +6,6 @@
<link type="text/css" rel="stylesheet" media="all" href="/static/styles/tabledrag.css" />
<link type="text/css" rel="stylesheet" media="all" href="/static/styles/agenda.css" />
{% if perms.agenda.can_manage_agenda %}
<script type="text/javascript" src="/static/javascript/jquery.js"></script>
<script type="text/javascript" src="/static/javascript/jquery.once.js"></script>
<script type="text/javascript" src="/static/javascript/jquery.cookie.js"></script>
<script type="text/javascript" src="/static/javascript/jquery.tmpl.js"></script>

View File

@ -28,6 +28,7 @@ class Assignment(models.Model):
assignment_number = 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)"))
profile = models.ManyToManyField(Profile, null=True, blank=True)
elected = models.ManyToManyField(Profile, null=True, blank=True, related_name='elected_set')
status = models.CharField(max_length=1, choices=STATUS, default='sea')
def set_status(self, status):
@ -66,28 +67,55 @@ class Assignment(models.Model):
else:
return False
@property
def candidates(self):
# list of candidates
from poll.models import Option
candidates = set()
for option in Option.objects.filter(poll__assignment=self):
candidates.add(option.value)
return candidates
def set_elected(self, profile, value=True):
if profile in self.candidates:
if value and not self.is_elected(profile):
self.elected.add(profile)
elif not value:
self.elected.remove(profile)
def is_elected(self, profile):
if profile in self.elected.all():
return True
return False
def gen_poll(self):
from poll.models import Poll
poll = Poll()
poll.title = _("Election for %s") % self.name
candidates = list(self.profile.all())
for elected in self.elected.all():
try:
candidates.remove(elected)
except ValueError:
pass
# Option A: candidates <= available posts -> yes/no/abstention
if self.profile.count() <= self.assignment_number:
if len(candidates) <= self.assignment_number - self.elected.count():
poll.optiondecision = True
else:
poll.optiondecision = False
# Option B: candidates == 1 -> yes/no/abstention
#if self.profile.count() == 1:
# poll.optiondecision = True
#else:
# poll.optiondecision = False
poll.assignment = self
poll.description = self.polldescription
poll.save()
for profile in self.profile.get_query_set():
poll.add_option(profile)
for candidate in candidates:
poll.add_option(candidate)
return poll
@models.permalink

View File

@ -1,6 +1,11 @@
{% extends "base.html" %}
{% load tags %}
{% block header %}
<link type="text/css" rel="stylesheet" media="all" href="/static/styles/assignment.css" />
<script type="text/javascript" src="/static/javascript/assignment.js"></script>
{% endblock %}
{% block submenu %}
{% url election_overview as url_electionoverview %}
<h4 class="sectiontitle">{%trans "Elections" %}</h4>

View File

@ -25,12 +25,12 @@
{% if 'vot' in assignment.status %}checked{% endif %}>{% trans 'Voting' %}<br>
<input type="radio" name="status" onclick="window.location.href='{% url assignment_set_status assignment.id 'fin' %}';"
{% if 'fin' in assignment.status %}checked{% endif %}>{% trans 'Finish' %}
<h4></h4>
<a href="{% url assignment_edit assignment.id %}">
<button><span class="icon edit">{%trans 'Edit' %}</span></button>
</a>
{% if not assignment.itemassignment_set.all %}
<h4></h4>
<a href='{% url item_new_default 'ItemAssignment' assignment.id %}'>
@ -111,7 +111,7 @@
<h3>{% trans "Election results" %}</h3>
{% if assignment.poll_set.all.count > 0 %}
<table style="width: auto;">
<table id="election_table" style="width: auto;">
<tr>
<th></th>
{% with ballotnumber=assignment.poll_set.all.count %}
@ -145,7 +145,17 @@
{% for vote in votes %}
<tr class="{% cycle 'odd' '' %}">
{% for v in vote %}
<td class="candidate">
{% with vote|first as candidate %}
{{ candidate.0 }}
{% if candidate.1 %}
<a class="election_link iselected" href='{% url assignment_user_not_elected assignment.id candidate.0.id %}'>{% trans 'not elected' %}</a>
{% else %}
<a class="election_link" href='{% url assignment_user_elected assignment.id candidate.0.id %}'>{% trans 'elected' %}</a>
{% endif %}
{% endwith %}
</td>
{% for v in vote|last %}
<td style="white-space:nowrap;">{% if v %}
{% if v|length == 3 %}
<img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}"> {% if v.0 %}{{ v.0 }}{% else %}&empty;{% endif %}<br>
@ -167,7 +177,7 @@
{% else %}
<i>{% trans "No ballots available." %}</i>
{% 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 ballotnumber|add:'1' %}'>

View File

@ -51,4 +51,10 @@ urlpatterns = patterns('assignment.views',
url(r'^assignment/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \
name='assignment_poll_delete'),
url(r'^assignment/(?P<assignment_id>\d+)/elected/(?P<profile_id>\d+)$', 'set_elected', {'elected': True}, \
name='assignment_user_elected'),
url(r'^assignment/(?P<assignment_id>\d+)/notelected/(?P<profile_id>\d+)$', 'set_elected', {'elected': False}, \
name='assignment_user_not_elected'),
)

View File

@ -20,7 +20,7 @@ from poll.models import Poll, Option
from poll.forms import OptionResultForm, PollInvalidForm
from assignment.models import Assignment
from assignment.forms import AssigmentForm, AssigmentRunForm
from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form
from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form, ajax_request
from utils.pdf import print_assignment_poll
from participant.models import Profile
@ -65,24 +65,18 @@ def view(request, assignment_id=None):
if request.user.has_perm('assignment.can_nominate_other'):
form = AssigmentRunForm()
# list of candidates
candidates = set()
for option in Option.objects.filter(poll__assignment=assignment):
candidates.add(option.value)
votes = []
for candidate in candidates:
tmplist = []
tmplist.append(candidate)
for candidate in assignment.candidates:
tmplist = [[candidate, assignment.is_elected(candidate)], []]
for poll in assignment.poll_set.all():
if candidate in poll.options_values:
option = Option.objects.filter(poll=poll).filter(user=candidate)[0]
if poll.optiondecision:
tmplist.append([option.yes, option.no, option.undesided])
tmplist[1].append([option.yes, option.no, option.undesided])
else:
tmplist.append(option.yes)
tmplist[1].append(option.yes)
else:
tmplist.append("-")
tmplist[1].append("-")
votes.append(tmplist)
return {'assignment': assignment,
@ -142,6 +136,26 @@ def set_status(request, assignment_id=None, status=None):
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')
def run(request, assignment_id):
assignment = Assignment.objects.get(pk=assignment_id)

View File

@ -24,7 +24,9 @@ function renderSlide(slide) {
$(function() {
// Set Active Slide with Ajax
$('.activate_link').click(function(event) {
event.preventDefault();
$.ajax({

View File

@ -0,0 +1,47 @@
$(function() {
$('a.iselected').parent().parent().children('td').addClass('iselected');
$('.election_link').click(function(event) {
event.preventDefault();
line = $(this);
$.ajax({
type: 'GET',
url: line.attr('href'),
dataType: 'json',
success: function(data) {
if (line.hasClass('iselected') && !data.elected) {
line.removeClass('iselected')
line.parent().parent().children('td').removeClass('iselected')
} else if (!line.hasClass('iselected') && data.elected) {
line.addClass('iselected')
line.parent().parent().children('td').addClass('iselected')
}
line.attr('href', data.link);
line.text(data.text);
},
error: function () {
alert("Ajax Error");
}
});
});
$('.close_link').click(function(event) {
event.preventDefault();
slide = $(this);
$.ajax({
type: 'GET',
url: slide.attr('href'),
dataType: 'json',
success: function(data) {
if (data.closed) {
newclass = 'closed';
} else {
newclass = 'open';
}
slide.removeClass('closed open').addClass(newclass);
slide.attr('href', data.link);
}
});
});
});

View File

@ -0,0 +1,5 @@
td.iselected {
background-color: green !important;
}

View File

@ -7,8 +7,8 @@
<title>{% block title %}{% get_config 'event_name' %}{% endblock %}</title>
<link type="text/css" rel="stylesheet" media="all" href="/static/styles/base.css" />
<link rel="shortcut icon" href="/static/images/favicon.png" type="image/png" />
{% block header %}
<script type="text/javascript" src="/static/javascript/jquery.js"></script>
{% block header %}
{% endblock %}
</head>
<body>