240 lines
6.9 KiB
HTML
240 lines
6.9 KiB
HTML
{% extends 'base.html' %}
|
|
|
|
{#
|
|
Eos - Verifiable elections
|
|
Copyright © 2017 RunasSudo (Yingtong Li)
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#}
|
|
|
|
{% block title %}{{ election.name }} – Voting booth{% endblock %}
|
|
|
|
{% block head %}
|
|
{{ super() }}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='bower_components/dragula.js/dist/dragula.min.css') }}" type="text/css">
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="ui container" id="booth-content">
|
|
<div class="ui active text loader">Loading voting booth. Please wait.</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block basecontent %}
|
|
{{ super() }}
|
|
|
|
<script src="{{ url_for('static', filename='bower_components/nunjucks/browser/nunjucks.min.js') }}"></script>
|
|
<script src="{{ url_for('static', filename='js/eosjs.js') }}"></script>
|
|
|
|
<script src="{{ url_for('static', filename='bower_components/dragula.js/dist/dragula.min.js') }}"></script>
|
|
|
|
<script>
|
|
var templates = {};
|
|
var election = null;
|
|
var booth = null;
|
|
var boothWorker = null;
|
|
var boothTasks = [];
|
|
var currentBoothTask = 0;
|
|
var selection_model_view_map = {{ selection_model_view_map|safe }}; {# :rooWut: #}
|
|
|
|
var username = {% if session.user %}"{{ session.user.name }}"{% else %}null{% endif %};
|
|
var auth_methods = {{ auth_methods|safe }};
|
|
|
|
function resetBooth() {
|
|
booth = {
|
|
"questionNum": 0,
|
|
"answers": [],
|
|
};
|
|
}
|
|
resetBooth();
|
|
|
|
function loadElection() {
|
|
$.ajax({ url: "{{ url_for('election_api_json', election_id=election._id) }}", dataType: "text" })
|
|
.done(function(data) {
|
|
try {
|
|
election = eosjs.eos.core.objects.__all__.EosObject.deserialise_and_unwrap(eosjs.eos.core.objects.__all__.EosObject.from_json(data), null);
|
|
|
|
boothWorker = new Worker("{{ url_for('static', filename='js/booth_worker.js') }}");
|
|
|
|
electionLoaded();
|
|
} catch (err) {
|
|
loadError(err);
|
|
throw err;
|
|
}
|
|
})
|
|
.fail(function(xhr, status, err) {
|
|
loadError(err);
|
|
throw err;
|
|
});
|
|
}
|
|
|
|
function electionLoaded() {
|
|
// Load templates for the question types
|
|
for (var i = 0; i < election.questions.__len__(); i++) {
|
|
var question = election.questions.__getitem__(i);
|
|
templates[selection_model_view_map[question._name]['selections_make']] = null;
|
|
templates[selection_model_view_map[question._name]['selections_review']] = null;
|
|
}
|
|
|
|
loadTemplates();
|
|
}
|
|
|
|
function loadTemplates() {
|
|
// Load all the templates
|
|
var templateUrls = Object.keys(templates);
|
|
var numTemplatesLoaded = 0;
|
|
for (var templateUrl of templateUrls) {
|
|
(function(templateUrl) {
|
|
$.ajax({
|
|
url: "{{ url_for('static', filename='nunjucks') }}/" + templateUrl,
|
|
dataType: "text"
|
|
})
|
|
.done(function(data) {
|
|
try {
|
|
templates[templateUrl] = nunjucks.compile(data);
|
|
numTemplatesLoaded += 1;
|
|
if (numTemplatesLoaded == templateUrls.length) {
|
|
// All templates loaded. Show voting booth
|
|
boothTasks[0].activate(true);
|
|
}
|
|
} catch (err) {
|
|
loadError(err);
|
|
throw err;
|
|
}
|
|
})
|
|
.fail(function(xhr, status, err) {
|
|
loadError(err);
|
|
throw err;
|
|
});
|
|
})(templateUrl);
|
|
}
|
|
}
|
|
|
|
function loadError(err) {
|
|
var techDetails = '';
|
|
if (err) {
|
|
techDetails = '<p>Technical details: ' + err + '</p>';
|
|
}
|
|
$("#booth-content").html('<div class="ui error message"><p>We were unable to load the voting booth for this election. Please try again. If this problem persists, contact the election administrator.</p>' + techDetails + '</div>');
|
|
}
|
|
|
|
function boothError(err) {
|
|
resetBooth();
|
|
var techDetails = '';
|
|
if (err) {
|
|
techDetails = '<p>Technical details: ' + err + '</p>';
|
|
}
|
|
$("#booth-content").html('<div class="ui error message"><p>We were unable to display the next page of the voting booth. For your security, your ballot selections have been cleared. Please try again. If this problem persists, contact the election administrator.</p>' + techDetails + '</div>');
|
|
}
|
|
|
|
function showTemplate(template, opts, destination) {
|
|
try {
|
|
if (!destination) {
|
|
destination = "#booth-content";
|
|
}
|
|
if (!opts) {
|
|
opts = {};
|
|
}
|
|
opts = $.extend({
|
|
"templates": templates,
|
|
"template": template,
|
|
"election_base_url": "{{ url_for('election_api_json', election_id=election._id) }}",
|
|
"static_base_url": "{{ url_for('static', filename='') }}",
|
|
"election": election,
|
|
"booth": booth,
|
|
"eosjs": eosjs,
|
|
"selection_model_view_map": selection_model_view_map,
|
|
"username": username,
|
|
"auth_methods": auth_methods
|
|
}, opts);
|
|
$(destination).html(templates[template].render(opts));
|
|
} catch (err) {
|
|
boothError(err);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
function nextTemplate(num) {
|
|
if (!num) {
|
|
num = 1;
|
|
}
|
|
currentBoothTask += num;
|
|
boothTasks[currentBoothTask].activate(true);
|
|
}
|
|
|
|
function prevTemplate(num) {
|
|
if (!num) {
|
|
num = 1;
|
|
}
|
|
currentBoothTask -= num;
|
|
boothTasks[currentBoothTask].activate(false);
|
|
}
|
|
|
|
// === BOOTH TASKS ===
|
|
// TODO: Make modular
|
|
|
|
boothTasks.append({
|
|
activate: function(fromLeft) {
|
|
showTemplate('booth/welcome.html');
|
|
}
|
|
});
|
|
templates['booth/base.html'] = null;
|
|
templates['booth/welcome.html'] = null;
|
|
boothTasks.append({
|
|
activate: function(fromLeft) {
|
|
showTemplate('booth/selections.html');
|
|
}
|
|
});
|
|
templates['booth/selections.html'] = null;
|
|
boothTasks.append({
|
|
activate: function(fromLeft) {
|
|
if (fromLeft) {
|
|
showTemplate('booth/encrypt.html');
|
|
} else {
|
|
prevTemplate();
|
|
}
|
|
}
|
|
});
|
|
templates['booth/encrypt.html'] = null;
|
|
boothTasks.append({
|
|
activate: function(fromLeft) {
|
|
showTemplate('booth/review.html', {ballot: booth.ballot});
|
|
}
|
|
});
|
|
templates['booth/review.html'] = null;
|
|
boothTasks.append({
|
|
activate: function(fromLeft) {
|
|
showTemplate('booth/audit.html', {ballot: booth.ballot});
|
|
}
|
|
});
|
|
templates['booth/audit.html'] = null;
|
|
boothTasks.append({
|
|
activate: function(fromLeft) {
|
|
showTemplate('booth/cast.html', {ballot: booth.ballot});
|
|
}
|
|
});
|
|
templates['booth/cast.html'] = null;
|
|
boothTasks.append({
|
|
activate: function(fromLeft) {
|
|
showTemplate('booth/complete.html', {voter: booth.voter, vote: booth.vote});
|
|
}
|
|
});
|
|
templates['booth/complete.html'] = null;
|
|
|
|
// === END BOOTH TASKS ===
|
|
|
|
loadElection();
|
|
</script>
|
|
{% endblock %}
|