Commit 123f04c3 authored by Julien Palard's avatar Julien Palard
Browse files

Move js out of HTML to ease work for xgettext.

parent 343dfda7
......@@ -30,7 +30,7 @@ Templates are translated using django `makemessages` and `compilemessages` comma
```
$ ./manage.py makemessages --locale fr
$ ./manage.py makemessages --locale fr --domain djangojs --extension html
$ ./manage.py makemessages --locale fr --domain djangojs
# Edit the .po files
$ ./manage.py compilemessages
```
......
......@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-11-13 00:02+0100\n"
"PO-Revision-Date: 2020-11-13 00:03+0100\n"
"POT-Creation-Date: 2020-11-24 16:45+0100\n"
"PO-Revision-Date: 2020-11-24 16:47+0100\n"
"Last-Translator: Julien Palard <julien@palard.fr>\n"
"Language-Team: fr <julien@palard.fr>\n"
"Language: fr\n"
......@@ -17,14 +17,24 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: website/templates/hkis/exercise.html:84
#: website/static/js/exercise.js:32
msgid ""
"This will send this answer to a human for manual review, so it can be "
"enhanced, are you sure?"
msgstr "Cette réponse sera envoyée à un human pour relecture, dans l'espoir de l'améliorer. L'envoyer maintenant ?"
#: website/static/js/exercise.js:58
msgid "Your new <a href=\"%(url)s\">rank</a> is: %(new_rank)s"
msgstr "Votre nouveau <a href=\"%(url)s\">classement</a> est: %(new_rank)s"
#: website/static/js/exercise.js:65
#, javascript-format
msgid "<a href=\"%s\">Login</a> to backup your code and progression."
msgstr ""
"<a href=\"%s\">Connectez-vous</a> pour sauvegarder votre code et votre "
"progression."
#: website/templates/hkis/exercise.html:92
#: website/static/js/exercise.js:73
msgid ""
"Flag this answer as particularly unhelpfull,\n"
"It'll be reviewed by a human."
......@@ -32,46 +42,46 @@ msgstr ""
"Marquer cette correction comme particulièrement innutile,\n"
"un humain passera la relire."
#: website/templates/hkis/exercise.html:95
#: website/static/js/exercise.js:76
msgid "Report"
msgstr "Signaler"
#: website/templates/hkis/exercise.html:102
#: website/static/js/exercise.js:83
msgid "Reported"
msgstr "Signalé"
#: website/templates/hkis/exercise.html:103
#: website/static/js/exercise.js:84
msgid "Thanks for the feedback!"
msgstr "Merci, je regarde ça bientôt !"
#: website/templates/hkis/exercise.html:110
#: website/static/js/exercise.js:91
msgid "Waiting for correction..."
msgstr "Correction en cours…"
#: website/templates/hkis/exercise.html:133
#: website/static/js/exercise.js:114
msgid "Waiting for test run"
msgstr "Exécution en cours…"
#: website/templates/hkis/exercise.html:156
#: website/static/js/exercise.js:137
msgid "Connecting to correction server…"
msgstr "Connexion au serveur de correction en cours…"
#: website/templates/hkis/exercise.html:173
#: website/static/js/exercise.js:154
msgid "Connected to correction server."
msgstr "Connecté au serveur de correction!"
#: website/templates/hkis/exercise.html:184
#: website/static/js/exercise.js:165
msgid "Connection to correction server lost, will retry in 5s…"
msgstr ""
"La connexion au serveur de correction a échouée. Nouvelle tentative dans 5s…"
#: website/templates/hkis/exercise.html:187
#: website/static/js/exercise.js:168
msgid "Cannot connect to correction server, will retry in 5s…"
msgstr ""
"Impossible de se connecter au serveur de correction. Nouvelle tentative dans "
"5s…"
#: website/templates/hkis/exercise.html:188
#: website/static/js/exercise.js:169
#, javascript-format
msgid "(See the <a href='%s'#FAQ'>FAQ</a> if it persists.)"
msgstr "(Consultez la <a href='%s#FAQ'>FAQ</a> si le problème persiste.)"
if (typeof Element.prototype.swapChild === 'undefined') {
Object.defineProperty(Element.prototype, 'swapChild', {
configurable: true,
enumerable: false,
value: function(newChild) {
while (this.firstChild) this.removeChild(this.lastChild);
this.appendChild(newChild);
}
});
}
var hkis = {
createElement: function(tagName, attrs, dataset) {
el = document.createElement(tagName)
for (const property in attrs)
el[property] = attrs[property]
if (typeof dataset != "undefined")
for (const property in dataset)
el.dataset[property] = dataset[property]
return el
}
}
function append_to_answer_table(html) {
if (document.querySelectorAll("#answer-table tr").length)
document.querySelectorAll("#answer-table tr")[0].insertAdjacentHTML("beforebegin", html);
else
document.querySelectorAll("#answer-table")[0].insertAdjacentHTML("afterbegin", html);
}
function report_as_unhelpfull(answer_id) {
if (confirm(gettext("This will send this answer to a human for manual review, so it can be enhanced, are you sure?")))
window.ws.send(JSON.stringify({type: "is_unhelpfull", answer_id: answer_id}));
return false;
}
function fill_answer(answer) {
var result = document.getElementById("answers-result");
if (!result)
return;
var answerbox = document.getElementById("td-".concat(answer.id));
if (!answerbox) {
var answer_table = document.getElementById("answer-table");
append_to_answer_table('<tr><td id="td-'.concat(answer.id).concat('">…</td> </tr>'));
answerbox = document.getElementById("td-".concat(answer.id));
}
if (answer.is_corrected) {
var answer_table = document.getElementById("answer-table");
var div = hkis.createElement("div", {innerHTML: answer.correction_message_html});
if (answer.is_valid) {
console.log("Answer is valid: old_rank=", HKIS_SETTINGS.CURRENT_RANK, "new_rank=", answer.user_rank)
document.getElementById("btn_next").className = "btn btn-primary"
document.getElementById("submit_answer").className = "btn btn-secondary"
answer_table.rows[0].className = "table-success";
if (answer.user && answer.user_rank < HKIS_SETTINGS.CURRENT_RANK ) {
div.appendChild(hkis.createElement("div", {
className: "alert alert-success",
innerHTML: interpolate(gettext('Your new <a href="%(url)s">rank</a> is: %(new_rank)s'),
{url: HKIS_SETTINGS.PROFILE_URL, new_rank: answer.user_rank},
true)}));
}
if (!answer.user) {
div.appendChild(hkis.createElement("div", {
className: "alert alert-warning",
innerHTML: interpolate(gettext('<a href="%s">Login</a> to backup your code and progression.'), [HKIS_SETTINGS.AUTH_LOGIN_URL])
}));
}
document.getElementById("solution_link").classList.remove("disabled");
}
else {
answer_table.rows[0].className = "table-danger";
var button_unhelpfull = hkis.createElement("button", {
title: gettext("Flag this answer as particularly unhelpfull,\nIt'll be reviewed by a human."),
className: "btn, btn-outline-danger btn-sm",
onclick: function() {return report_as_unhelpfull(answer.id);},
innerHTML: gettext("Report")
}, {
toggle: "tooltip"
});
if (answer.is_unhelpfull) {
button_unhelpfull.disabled = true;
button_unhelpfull.innerHTML = gettext("Reported")
button_unhelpfull.title = gettext("Thanks for the feedback!")
}
div.appendChild(button_unhelpfull);
}
answerbox.swapChild(div)
unlock_button("submit_answer")
} else {
answerbox.innerHTML = gettext("Waiting for correction...")
}
}
function fill_snippet(id, executed_at, output) {
var result = document.getElementById("answers-result");
if (!result)
return;
var elem = document.getElementById("td-snippet-".concat(id));
if (!elem) {
var answer_table = document.getElementById("answer-table");
append_to_answer_table('<tr class="table-info"><td id="td-snippet-'.concat(id).concat('">…</td> </tr>'));
elem = document.getElementById("td-snippet-".concat(id));
}
if (executed_at) {
var pre = document.createElement("pre");
var div = document.createElement("div");
div.appendChild(pre);
var content = document.createTextNode(output);
pre.appendChild(content);
elem.swapChild(div);
unlock_button("submit_answer");
} else {
elem.innerHTML = gettext("Waiting for test run");
}
}
function fill_message(message, type) {
/* type in {"success", "danger", "warning", "info" } */
console.log("[" + type + "]" + message);
var answer_table = document.getElementById("answer-table");
if (!answer_table)
return;
var first_row = answer_table.getElementsByTagName("tr")[0];
var first_cell = null;
if (first_row)
first_cell = first_row.getElementsByTagName("td")[0];
var html = '<div class="alert alert-' + type + '">' + message + "</td> </tr>";
if (first_cell && !first_cell.id)
first_cell.innerHTML = html
else
append_to_answer_table("<tr><td>" + html + "</td></tr>");
}
function websocket_connect(ws_location) {
var connected = false;
fill_message(gettext("Connecting to correction server…"), "info");
window.ws = new WebSocket(ws_location);
window.ws.onmessage = function(e) {
var data = JSON.parse(e.data);
console.log("WebSocket recv:", data);
if (data.type == "snippet.update")
fill_snippet(data.id, data.executed_at, data.output)
if (data.type == "answer.update")
fill_answer(data);
};
window.ws.onerror = function(event) {
console.error("WebSocket error observed:", event);
};
window.ws.onopen = function() {
unlock_button("submit_answer");
unlock_button("submit_snippet");
connected = true;
fill_message(gettext("Connected to correction server."), "success");
window.ws.send(JSON.stringify({type: "settings", value: HKIS_SETTINGS}));
document.querySelectorAll("td.answer-cell").forEach(function(answer) {
if (answer.dataset.isCorrected == "True") return ;
console.log("Need to correct answer number", answer.dataset.answerId);
window.ws.send(JSON.stringify({"type": "recorrect", "id": Number(answer.dataset.answerId)}));
});
};
window.ws.onclose = function(event) {
console.log("onclose", event);
if (connected)
fill_message(gettext("Connection to correction server lost, will retry in 5s…"), "warning");
else
fill_message(gettext("Cannot connect to correction server, will retry in 5s…") + "<br/>" +
interpolate(gettext("(See the <a href='%s'#FAQ'>FAQ</a> if it persists.)"), [HKIS_SETTINGS.HELP_URL]), "warning");
setTimeout(function(){websocket_connect(ws_location)}, 5000);
lock_button("submit_answer", 0);
lock_button("submit_snippet", 0);
};
}
function ws_submit_answer(form) {
var message = {"type": "answer", "source_code": form["source_code"].value};
lock_button("submit_answer", 1);
console.log("WebSocket send answer", message);
window.ws.send(JSON.stringify(message));
}
function unlock_button(button_id) {
document.getElementById(button_id).removeAttribute("disabled");
}
function lock_button(button_id, unlock_after_seconds) {
document.getElementById(button_id).setAttribute("disabled", true);
if (unlock_after_seconds)
setTimeout(function(){unlock_button(button_id);}, unlock_after_seconds * 1000);
}
function ws_submit_snippet(form) {
var message = {"type": "snippet", "source_code": form["source_code"].value};
lock_button("submit_snippet", 1);
console.log("WebSocket send snippet", message);
window.ws.send(JSON.stringify(message));
}
function ctrl_enter_handler(event) {
if (!event.ctrlKey) return;
if (event.code !== "Enter") return;
console.log("Sending via Ctrl-enter");
ws_submit_answer(document.getElementById("answer_form"));
}
var ws_protocol = window.location.protocol == "http:" ? "ws:" : "wss:";
if (!HKIS_SETTINGS.IS_IMPERSONATING) {
window.addEventListener("DOMContentLoaded", function (event) {
websocket_connect(ws_protocol + "//" + window.location.host + "/ws/exercises/" + HKIS_SETTINGS.ID + "/");
document.addEventListener("keydown", ctrl_enter_handler);
});
}
......@@ -13,6 +13,12 @@
var HKIS_SETTINGS = {
{% get_current_language as LANGUAGE_CODE %}
LANGUAGE_CODE: "{{ LANGUAGE_CODE }}",
PROFILE_URL: "{% if user.is_anonymous %}{% url "auth_login" %}{% else %}{% url "profile" user.id %}{% endif %}",
HELP_URL: "{% url "help" %}",
CURRENT_RANK: {{ current_rank|default:999999 }},
ID: {{object.id|default:0}},
AUTH_LOGIN_URL: "{% url "auth_login" %}",
IS_IMPERSONATING: {% if is_impersonating %}true{% else %}false{% endif %},
};
</script>
{% block stylesheets %}{% endblock %}
......
......@@ -9,232 +9,9 @@
{% endif %}
{% endblock %}
{% block stylesheets %}
<link href="{% static "css/codehilite.css" %}" rel="stylesheet" type="text/css" />
<link href="{% static 'css/codehilite.css' %}" rel="stylesheet" type="text/css" >
{% endblock %}
{% block extrahead %}
{% autoescape off %}
{% url "profile" user.id as profile_url %}
<script>
if (typeof Element.prototype.swapChild === 'undefined') {
Object.defineProperty(Element.prototype, 'swapChild', {
configurable: true,
enumerable: false,
value: function(newChild) {
while (this.firstChild) this.removeChild(this.lastChild);
this.appendChild(newChild);
}
});
}
var hkis = {
createElement: function(tagName, attrs, dataset) {
el = document.createElement(tagName)
for (const property in attrs)
el[property] = attrs[property]
if (typeof dataset != "undefined")
for (const property in dataset)
el.dataset[property] = dataset[property]
return el
}
}
function append_to_answer_table(html) {
if (document.querySelectorAll("#answer-table tr").length)
document.querySelectorAll("#answer-table tr")[0].insertAdjacentHTML("beforebegin", html);
else
document.querySelectorAll("#answer-table")[0].insertAdjacentHTML("afterbegin", html);
}
function report_as_unhelpfull(answer_id) {
window.ws.send(JSON.stringify({type: "is_unhelpfull", answer_id: answer_id}));
return false;
}
function fill_answer(answer) {
var result = document.getElementById("answers-result");
if (!result)
return;
var answerbox = document.getElementById("td-".concat(answer.id));
if (!answerbox) {
var answer_table = document.getElementById("answer-table");
append_to_answer_table('<tr><td id="td-'.concat(answer.id).concat('">…</td> </tr>'));
answerbox = document.getElementById("td-".concat(answer.id));
}
if (answer.is_corrected) {
var answer_table = document.getElementById("answer-table");
var div = hkis.createElement("div", {innerHTML: answer.correction_message_html});
if (answer.is_valid) {
console.log("Answer is valid: old_rank={{current_rank}}, new_rank=", answer.user_rank)
document.getElementById("btn_next").className = "btn btn-primary"
document.getElementById("submit_answer").className = "btn btn-secondary"
answer_table.rows[0].className = "table-success";
if (answer.user && answer.user_rank < {{ current_rank }}) {
{% url "profile" user.id as profile_url %}
div.appendChild(hkis.createElement("div", {
className: "alert alert-success",
innerHTML: interpolate(gettext('Your new <a href="%(url)s">rank</a> is: %(new_rank)s'),
{url: "{{ profile_url }}", new_rank: answer.user_rank},
true)}));
}
if (!answer.user) {
div.appendChild(hkis.createElement("div", {
className: "alert alert-warning",
innerHTML: interpolate(gettext('<a href="%s">Login</a> to backup your code and progression.'), ["{% url "auth_login" %}"])
}));
}
document.getElementById("solution_link").classList.remove("disabled");
}
else {
answer_table.rows[0].className = "table-danger";
var button_unhelpfull = hkis.createElement("button", {
title: gettext("Flag this answer as particularly unhelpfull,\nIt'll be reviewed by a human."),
className: "btn, btn-secondary btn-sm",
onclick: function() { report_as_unhelpfull(answer.id); return false},
innerHTML: gettext("Report")
}, {
toggle: "tooltip"
});
if (answer.is_unhelpfull) {
button_unhelpfull.disabled = true;
button_unhelpfull.innerHTML = gettext("Reported")
button_unhelpfull.title = gettext("Thanks for the feedback!")
}
div.appendChild(button_unhelpfull);
}
answerbox.swapChild(div)
unlock_button("submit_answer")
} else {
answerbox.innerHTML = gettext("Waiting for correction...")
}
}
function fill_snippet(id, executed_at, output) {
var result = document.getElementById("answers-result");
if (!result)
return;
var elem = document.getElementById("td-snippet-".concat(id));
if (!elem) {
var answer_table = document.getElementById("answer-table");
append_to_answer_table('<tr class="table-info"><td id="td-snippet-'.concat(id).concat('">…</td> </tr>'));
elem = document.getElementById("td-snippet-".concat(id));
}
if (executed_at) {
var pre = document.createElement("pre");
var div = document.createElement("div");
div.appendChild(pre);
var content = document.createTextNode(output);
pre.appendChild(content);
elem.swapChild(div);
unlock_button("submit_answer");
} else {
elem.innerHTML = gettext("Waiting for test run");
}
}
function fill_message(message, type) {
/* type in {"success", "danger", "warning", "info" } */
console.log("[" + type + "]" + message);
var answer_table = document.getElementById("answer-table");
if (!answer_table)
return;
var first_row = answer_table.getElementsByTagName("tr")[0];
var first_cell = null;
if (first_row)
first_cell = first_row.getElementsByTagName("td")[0];
var html = '<div class="alert alert-' + type + '">' + message + "</td> </tr>";
if (first_cell && !first_cell.id)
first_cell.innerHTML = html
else
append_to_answer_table("<tr><td>" + html + "</td></tr>");
}
function websocket_connect(ws_location) {
var connected = false;
fill_message(gettext("Connecting to correction server…"), "info");
window.ws = new WebSocket(ws_location);
window.ws.onmessage = function(e) {
var data = JSON.parse(e.data);
console.log("WebSocket recv:", data);
if (data.type == "snippet.update")
fill_snippet(data.id, data.executed_at, data.output)
if (data.type == "answer.update")
fill_answer(data);
};
window.ws.onerror = function(event) {
console.error("WebSocket error observed:", event);
};
window.ws.onopen = function() {
unlock_button("submit_answer");
unlock_button("submit_snippet");
connected = true;
fill_message(gettext("Connected to correction server."), "success");
window.ws.send(JSON.stringify({type: "settings", value: HKIS_SETTINGS}));
document.querySelectorAll("td.answer-cell").forEach(function(answer) {
if (answer.dataset.isCorrected == "True") return ;
console.log("Need to correct answer number", answer.dataset.answerId);
window.ws.send(JSON.stringify({"type": "recorrect", "id": Number(answer.dataset.answerId)}));
});
};
window.ws.onclose = function(event) {
console.log("onclose", event);
if (connected)
fill_message(gettext("Connection to correction server lost, will retry in 5s…"), "warning");
else
fill_message(gettext("Cannot connect to correction server, will retry in 5s…") + "<br/>" +
interpolate(gettext("(See the <a href='%s'#FAQ'>FAQ</a> if it persists.)"), ["{% url "help" %}"]), "warning");
setTimeout(function(){websocket_connect(ws_location)}, 5000);
lock_button("submit_answer", 0);
lock_button("submit_snippet", 0);
};
}
function ws_submit_answer(form) {
var message = {"type": "answer", "source_code": form["source_code"].value};
lock_button("submit_answer", 1);
console.log("WebSocket send answer", message);
window.ws.send(JSON.stringify(message));
}
function unlock_button(button_id) {
document.getElementById(button_id).removeAttribute("disabled");
}
function lock_button(button_id, unlock_after_seconds) {
document.getElementById(button_id).setAttribute("disabled", true);
if (unlock_after_seconds)
setTimeout(function(){unlock_button(button_id);}, unlock_after_seconds * 1000);
}
function ws_submit_snippet(form) {
var message = {"type": "snippet", "source_code": form["source_code"].value};
lock_button("submit_snippet", 1);
console.log("WebSocket send snippet", message);
window.ws.send(JSON.stringify(message));
}
function ctrl_enter_handler(event) {
if (!event.ctrlKey) return;
if (event.code !== "Enter") return;
console.log("Sending via Ctrl-enter");
ws_submit_answer(document.getElementById("answer_form"));
}
var ws_protocol = window.location.protocol == "http:" ? "ws:" : "wss:";
{% if not is_impersonating %}
window.addEventListener("DOMContentLoaded", function (event) {
websocket_connect(ws_protocol + "//" + window.location.host + "/ws/exercises/" + {{object.id}} + "/");
document.addEventListener("keydown", ctrl_enter_handler);
});
{% endif %}
</script>
{% endautoescape %}
{% endblock %}
{% block container %}
{% if is_impersonating %}
<div class="alert alert-warning" role="alert">
......@@ -331,4 +108,5 @@
</div>
</div>
</div>
<script src="{% static 'js/exercise.js' %}?v={{ version }}" type="text/javascript"></script>
{% endblock %}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment