canidate in assignment can be marked as elected
This commit is contained in:
parent
2a89ccca5a
commit
dcbeb452fb
@ -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/tabledrag.css" />
|
||||||
<link type="text/css" rel="stylesheet" media="all" href="/static/styles/agenda.css" />
|
<link type="text/css" rel="stylesheet" media="all" href="/static/styles/agenda.css" />
|
||||||
{% if perms.agenda.can_manage_agenda %}
|
{% 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.once.js"></script>
|
||||||
<script type="text/javascript" src="/static/javascript/jquery.cookie.js"></script>
|
<script type="text/javascript" src="/static/javascript/jquery.cookie.js"></script>
|
||||||
<script type="text/javascript" src="/static/javascript/jquery.tmpl.js"></script>
|
<script type="text/javascript" src="/static/javascript/jquery.tmpl.js"></script>
|
||||||
|
@ -28,6 +28,7 @@ class Assignment(models.Model):
|
|||||||
assignment_number = models.PositiveSmallIntegerField(verbose_name = _("Number of available posts"))
|
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)"))
|
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')
|
||||||
status = models.CharField(max_length=1, choices=STATUS, default='sea')
|
status = models.CharField(max_length=1, choices=STATUS, default='sea')
|
||||||
|
|
||||||
def set_status(self, status):
|
def set_status(self, status):
|
||||||
@ -66,28 +67,55 @@ class Assignment(models.Model):
|
|||||||
else:
|
else:
|
||||||
return False
|
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):
|
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
|
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
|
# 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
|
poll.optiondecision = True
|
||||||
else:
|
else:
|
||||||
poll.optiondecision = False
|
poll.optiondecision = False
|
||||||
|
|
||||||
# Option B: candidates == 1 -> yes/no/abstention
|
# Option B: candidates == 1 -> yes/no/abstention
|
||||||
#if self.profile.count() == 1:
|
#if self.profile.count() == 1:
|
||||||
# poll.optiondecision = True
|
# poll.optiondecision = True
|
||||||
#else:
|
#else:
|
||||||
# poll.optiondecision = False
|
# poll.optiondecision = False
|
||||||
|
|
||||||
poll.assignment = self
|
poll.assignment = self
|
||||||
poll.description = self.polldescription
|
poll.description = self.polldescription
|
||||||
poll.save()
|
poll.save()
|
||||||
for profile in self.profile.get_query_set():
|
for candidate in candidates:
|
||||||
poll.add_option(profile)
|
poll.add_option(candidate)
|
||||||
return poll
|
return poll
|
||||||
|
|
||||||
@models.permalink
|
@models.permalink
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load tags %}
|
{% 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 %}
|
{% block submenu %}
|
||||||
{% url election_overview as url_electionoverview %}
|
{% url election_overview as url_electionoverview %}
|
||||||
<h4 class="sectiontitle">{%trans "Elections" %}</h4>
|
<h4 class="sectiontitle">{%trans "Elections" %}</h4>
|
||||||
|
@ -25,12 +25,12 @@
|
|||||||
{% if 'vot' in assignment.status %}checked{% endif %}>{% trans 'Voting' %}<br>
|
{% 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' %}';"
|
<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' %}
|
{% if 'fin' in assignment.status %}checked{% endif %}>{% trans 'Finish' %}
|
||||||
|
|
||||||
<h4></h4>
|
<h4></h4>
|
||||||
<a href="{% url assignment_edit assignment.id %}">
|
<a href="{% url assignment_edit assignment.id %}">
|
||||||
<button><span class="icon edit">{%trans 'Edit' %}</span></button>
|
<button><span class="icon edit">{%trans 'Edit' %}</span></button>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
{% if not assignment.itemassignment_set.all %}
|
{% if not assignment.itemassignment_set.all %}
|
||||||
<h4></h4>
|
<h4></h4>
|
||||||
<a href='{% url item_new_default 'ItemAssignment' assignment.id %}'>
|
<a href='{% url item_new_default 'ItemAssignment' assignment.id %}'>
|
||||||
@ -111,7 +111,7 @@
|
|||||||
<h3>{% trans "Election results" %}</h3>
|
<h3>{% trans "Election results" %}</h3>
|
||||||
|
|
||||||
{% if assignment.poll_set.all.count > 0 %}
|
{% if assignment.poll_set.all.count > 0 %}
|
||||||
<table style="width: auto;">
|
<table id="election_table" style="width: auto;">
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
{% with ballotnumber=assignment.poll_set.all.count %}
|
{% with ballotnumber=assignment.poll_set.all.count %}
|
||||||
@ -145,7 +145,17 @@
|
|||||||
|
|
||||||
{% for vote in votes %}
|
{% for vote in votes %}
|
||||||
<tr class="{% cycle 'odd' '' %}">
|
<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 %}
|
<td style="white-space:nowrap;">{% if v %}
|
||||||
{% if v|length == 3 %}
|
{% if v|length == 3 %}
|
||||||
<img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}"> {% if v.0 %}{{ v.0 }}{% else %}∅{% endif %}<br>
|
<img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}"> {% if v.0 %}{{ v.0 }}{% else %}∅{% endif %}<br>
|
||||||
@ -167,7 +177,7 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
<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 %}
|
{% with ballotnumber=assignment.poll_set.all.count %}
|
||||||
<p><a href='{% url assignment_gen_poll assignment.id ballotnumber|add:'1' %}'>
|
<p><a href='{% url assignment_gen_poll assignment.id ballotnumber|add:'1' %}'>
|
||||||
|
@ -51,4 +51,10 @@ urlpatterns = patterns('assignment.views',
|
|||||||
|
|
||||||
url(r'^assignment/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \
|
url(r'^assignment/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \
|
||||||
name='assignment_poll_delete'),
|
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'),
|
||||||
)
|
)
|
||||||
|
@ -20,7 +20,7 @@ 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 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 utils.pdf import print_assignment_poll
|
||||||
from participant.models import Profile
|
from participant.models import Profile
|
||||||
|
|
||||||
@ -65,24 +65,18 @@ def view(request, assignment_id=None):
|
|||||||
if request.user.has_perm('assignment.can_nominate_other'):
|
if request.user.has_perm('assignment.can_nominate_other'):
|
||||||
form = AssigmentRunForm()
|
form = AssigmentRunForm()
|
||||||
|
|
||||||
# list of candidates
|
|
||||||
candidates = set()
|
|
||||||
for option in Option.objects.filter(poll__assignment=assignment):
|
|
||||||
candidates.add(option.value)
|
|
||||||
|
|
||||||
votes = []
|
votes = []
|
||||||
for candidate in candidates:
|
for candidate in assignment.candidates:
|
||||||
tmplist = []
|
tmplist = [[candidate, assignment.is_elected(candidate)], []]
|
||||||
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.append([option.yes, option.no, option.undesided])
|
tmplist[1].append([option.yes, option.no, option.undesided])
|
||||||
else:
|
else:
|
||||||
tmplist.append(option.yes)
|
tmplist[1].append(option.yes)
|
||||||
else:
|
else:
|
||||||
tmplist.append("-")
|
tmplist[1].append("-")
|
||||||
votes.append(tmplist)
|
votes.append(tmplist)
|
||||||
|
|
||||||
return {'assignment': assignment,
|
return {'assignment': assignment,
|
||||||
@ -142,6 +136,26 @@ 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)
|
||||||
|
@ -24,7 +24,9 @@ function renderSlide(slide) {
|
|||||||
|
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
// Set Active Slide with Ajax
|
|
||||||
|
|
||||||
|
|
||||||
$('.activate_link').click(function(event) {
|
$('.activate_link').click(function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
47
openslides/static/javascript/assignment.js
Normal file
47
openslides/static/javascript/assignment.js
Normal 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
5
openslides/static/styles/assignment.css
Normal file
5
openslides/static/styles/assignment.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
td.iselected {
|
||||||
|
background-color: green !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
|||||||
<title>{% block title %}{% get_config 'event_name' %}{% endblock %}</title>
|
<title>{% block title %}{% get_config 'event_name' %}{% endblock %}</title>
|
||||||
<link type="text/css" rel="stylesheet" media="all" href="/static/styles/base.css" />
|
<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" />
|
<link rel="shortcut icon" href="/static/images/favicon.png" type="image/png" />
|
||||||
{% block header %}
|
|
||||||
<script type="text/javascript" src="/static/javascript/jquery.js"></script>
|
<script type="text/javascript" src="/static/javascript/jquery.js"></script>
|
||||||
|
{% block header %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
Loading…
Reference in New Issue
Block a user