Basic ticket dragging #7
This commit is contained in:
parent
c0752f71ed
commit
6bb2dfddcb
@ -110,14 +110,16 @@ class Result(EmbeddedObject):
|
||||
pass
|
||||
|
||||
class ListChoiceQuestion(Question):
|
||||
choices = ListField(StringField())
|
||||
_ver = StringField(default='0.4')
|
||||
|
||||
choices = EmbeddedObjectListField()
|
||||
min_choices = IntField()
|
||||
max_choices = IntField()
|
||||
|
||||
def pretty_answer(self, answer):
|
||||
if len(answer.choices) == 0:
|
||||
return '(blank votes)'
|
||||
return ', '.join([self.choices[choice] for choice in answer.choices])
|
||||
return ', '.join([self.choices[choice].name for choice in answer.choices])
|
||||
|
||||
def max_bits(self):
|
||||
answer = self.answer_type(choices=list(range(len(self.choices))))
|
||||
@ -135,6 +137,14 @@ class PreferentialAnswer(Answer):
|
||||
class PreferentialQuestion(ListChoiceQuestion):
|
||||
answer_type = PreferentialAnswer
|
||||
|
||||
class Choice(EmbeddedObject):
|
||||
name = StringField()
|
||||
party = StringField(default=None)
|
||||
|
||||
class Ticket(EmbeddedObject):
|
||||
name = StringField()
|
||||
choices = EmbeddedObjectListField()
|
||||
|
||||
class RawResult(Result):
|
||||
plaintexts = ListField(EmbeddedObjectListField())
|
||||
answers = EmbeddedObjectListField()
|
||||
|
@ -56,10 +56,10 @@ class ElectionTestCase(EosTestCase):
|
||||
# Check _instance
|
||||
self.assertEqual(voter._instance, (election.voters, i))
|
||||
|
||||
question = ApprovalQuestion(prompt='President', choices=['John Smith', 'Joe Bloggs', 'John Q. Public'])
|
||||
question = ApprovalQuestion(prompt='President', choices=[Choice(name='John Smith'), Choice(name='Joe Bloggs'), Choice(name='John Q. Public')])
|
||||
election.questions.append(question)
|
||||
|
||||
question = ApprovalQuestion(prompt='Chairman', choices=['John Doe', 'Andrew Citizen'])
|
||||
question = ApprovalQuestion(prompt='Chairman', choices=[Choice(name='John Doe'), Choice(name='Andrew Citizen')])
|
||||
election.questions.append(question)
|
||||
|
||||
election.save()
|
||||
|
@ -252,10 +252,10 @@ class ElectionTestCase(EosTestCase):
|
||||
election.sk = EGPrivateKey.generate()
|
||||
election.public_key = election.sk.public_key
|
||||
|
||||
question = ApprovalQuestion(prompt='President', choices=['John Smith', 'Joe Bloggs', 'John Q. Public'])
|
||||
question = ApprovalQuestion(prompt='President', choices=[Choice(name='John Smith'), Choice(name='Joe Bloggs'), Choice(name='John Q. Public')])
|
||||
election.questions.append(question)
|
||||
|
||||
question = ApprovalQuestion(prompt='Chairman', choices=['John Doe', 'Andrew Citizen'])
|
||||
question = ApprovalQuestion(prompt='Chairman', choices=[Choice(name='John Doe'), Choice(name='Andrew Citizen')])
|
||||
election.questions.append(question)
|
||||
|
||||
election.save()
|
||||
|
@ -123,10 +123,16 @@ def setup_test_election():
|
||||
election.sk = EGPrivateKey.generate()
|
||||
election.public_key = election.sk.public_key
|
||||
|
||||
question = PreferentialQuestion(prompt='President', choices=['John Smith', 'Joe Bloggs', 'John Q. Public'], min_choices=0, max_choices=3)
|
||||
question = PreferentialQuestion(prompt='President', choices=[
|
||||
Ticket(name='ACME Party', choices=[
|
||||
Choice(name='John Smith'),
|
||||
Choice(name='Joe Bloggs', party='Independent ACME')
|
||||
]),
|
||||
Choice(name='John Q. Public')
|
||||
], min_choices=0, max_choices=3)
|
||||
election.questions.append(question)
|
||||
|
||||
question = ApprovalQuestion(prompt='Chairman', choices=['John Doe', 'Andrew Citizen'], min_choices=0, max_choices=1)
|
||||
question = ApprovalQuestion(prompt='Chairman', choices=[Choice(name='John Doe'), Choice(name='Andrew Citizen')], min_choices=0, max_choices=1)
|
||||
election.questions.append(question)
|
||||
|
||||
election.save()
|
||||
|
@ -51,13 +51,13 @@
|
||||
}
|
||||
|
||||
.preferential-choices .dragarea {
|
||||
min-height: 3em;
|
||||
min-height: 2em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.preferential-choices .dragarea-hint:first-child:last-child {
|
||||
width: calc(100% - 1em);
|
||||
height: 3em;
|
||||
height: 2em;
|
||||
box-sizing: border-box;
|
||||
z-index: -100;
|
||||
border: 1px dashed #555;
|
||||
@ -71,11 +71,13 @@
|
||||
|
||||
.preferential-choice {
|
||||
background-color: #eee;
|
||||
font-size: 1.1rem;
|
||||
margin-top: 0.5em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 3em;
|
||||
min-height: 2em;
|
||||
}
|
||||
|
||||
.ticket-choices .preferential-choice {
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
.preferential-choice:first-child {
|
||||
@ -94,11 +96,23 @@
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.preferential-choice .number, .preferential-choice .name {
|
||||
.preferential-choice .number, .preferential-choice .content {
|
||||
padding: 0.5em 0 0.5em 0.5em;
|
||||
}
|
||||
|
||||
.ticket-choices .number, .ticket-choices .content {
|
||||
padding: 0 0 0 0.5em;
|
||||
}
|
||||
|
||||
.preferential-choice .number {
|
||||
width: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.preferential-choice .party-name {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.ticket > .content > .party-name {
|
||||
min-height: 2em;
|
||||
}
|
||||
|
@ -30,16 +30,41 @@
|
||||
<div class="ui hidden message" id="message-max-choices">
|
||||
<p>You have now selected the maximum allowed number of choices. If you wish to add different choices, you must deselect some choices by dragging them from the blue box back to the grey box.</p>
|
||||
</div>
|
||||
<div class="ui hidden error message" id="message-too-many-choices">
|
||||
<p>You have selected more than the maximum allowed number of choices. To proceed, you must deselect some choices by dragging them from the blue box back to the grey box.</p>
|
||||
</div>
|
||||
|
||||
{% macro printchoice(choice, ticket=None) %}
|
||||
<div class="preferential-choice" data-choiceno="{{ loop.index0 }}">
|
||||
<div class="number"></div>
|
||||
<div class="content">
|
||||
<div class="candidate-name">{{ choice.name }}</div>
|
||||
{% if (ticket and choice.party and choice.party != ticket.name) or (not ticket and choice.party) %}<div class="party-name">{{ choice.party }}</div>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
<div id="question-choices-remaining" class="preferential-choices">
|
||||
<div>Options not yet voted for:</div>
|
||||
<div class="dragarea">
|
||||
<div class="dragarea-hint"></div>
|
||||
{% for choice in election.questions.__getitem__(questionNum).choices.impl %}
|
||||
<div class="preferential-choice" data-choiceno="{{ loop.index0 }}">
|
||||
{% if choice.choices %}
|
||||
{# Ticket #}
|
||||
<div class="preferential-choice ticket" data-choiceno="{{ loop.index0 }}">
|
||||
<div class="number"></div>
|
||||
<div class="name">{{ choice }}</div>
|
||||
<div class="content">
|
||||
<div class="party-name">{{ choice.name }}</div>
|
||||
<div class="ticket-choices">
|
||||
{% for choice2 in choice.choices.impl %}
|
||||
{{ printchoice(choice2, choice) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ printchoice(choice) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
@ -52,17 +77,28 @@
|
||||
$(".preferential-choices .preferential-choice .number").each(function(i, el) {
|
||||
$(el).text("");
|
||||
});
|
||||
var selectedChoices = $("#question-choices-selected .preferential-choice .number");
|
||||
var selectedChoices = $("#question-choices-selected .dragarea > .preferential-choice > .number");
|
||||
selectedChoices.each(function(i, el) {
|
||||
$(el).text(i + 1);
|
||||
});
|
||||
if (selectedChoices.length >= election.questions.__getitem__(booth.questionNum).max_choices) {
|
||||
var selectedCandidates = $("#question-choices-selected .preferential-choice:not(.ticket) .number");
|
||||
if (selectedCandidates.length >= election.questions.__getitem__(booth.questionNum).max_choices) {
|
||||
// Prevent making any more selections
|
||||
allowAdding = false;
|
||||
|
||||
if (selectedCandidates.length > election.questions.__getitem__(booth.questionNum).max_choices) {
|
||||
// Prevent progression
|
||||
$(".primary.button").addClass("disabled");
|
||||
$("#message-too-many-choices").removeClass("hidden");
|
||||
} else {
|
||||
$(".primary.button").removeClass("disabled");
|
||||
$("#message-max-choices").removeClass("hidden");
|
||||
}
|
||||
} else {
|
||||
allowAdding = true;
|
||||
$("#message-max-choices").addClass("hidden");
|
||||
$("#message-too-many-choices").addClass("hidden");
|
||||
$(".primary.button").removeClass("disabled");
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,17 +111,21 @@
|
||||
}
|
||||
|
||||
var dragulaChoices = dragula(
|
||||
[document.querySelector("#question-choices-selected .dragarea"), document.querySelector("#question-choices-remaining .dragarea")],
|
||||
[document.querySelector("#question-choices-selected .dragarea"), document.querySelector("#question-choices-remaining .dragarea")].concat([].slice.apply(document.querySelectorAll(".ticket-choices"))),
|
||||
{
|
||||
moves: function(el, source, handle, sibling) {
|
||||
if ("dragarea-hint" in el.classList) {
|
||||
return false;
|
||||
}
|
||||
//if ("ticket" in el.classList && !("party-name" in handle.classList)) {
|
||||
// return false;
|
||||
//}
|
||||
if ($.contains(document.querySelector("#question-choices-remaining"), el)) {
|
||||
return allowAdding;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
mirrorContainer: document.querySelector("#question-choices-remaining")
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -20,6 +20,6 @@
|
||||
|
||||
<ul class="ui list">
|
||||
{% for choice in question.choices %}
|
||||
<li>{{ choice }}</li>
|
||||
<li>{{ choice.name }}{% if choice.party %} – {{ choice.party }}{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
@ -20,6 +20,18 @@
|
||||
|
||||
<ul class="ui list">
|
||||
{% for choice in question.choices %}
|
||||
<li>{{ choice }}</li>
|
||||
{% if choice.choices %}
|
||||
{# Ticket #}
|
||||
<li>
|
||||
{{ choice.name }}
|
||||
<ul>
|
||||
{% for choice2 in choice.choices %}
|
||||
<li>{{ choice2.name }}{% if choice2.party and choice2.party != choice.name %} – {{ choice2.party }}{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>{{ choice.name }}{% if choice.party %} – {{ choice.party }}{% endif %}</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
Loading…
Reference in New Issue
Block a user