Commit 9788839fb9912c15c4cd64dec050d8ec23ed03be

Authored by Miguel Barão
1 parent 24e493a4
Exists in master and in 1 other branch dev

- fixed inactivate input on submit (also double clicks)

- changed animations and shows a spinner while correcting
- improved submit button dynamics
- link to latest mathjax from cdn
BUGS.md
1 1  
2 2 # BUGS
3 3  
4   -- apos clicar no botao responder, inactivar o input (importante quando o tempo de correcção é grande)
5 4 - nao esta a seguir o max_tries definido no ficheiro de dependencias.
6   -- initdb da integrity error se no mesmo comando existirem alunos repetidos (p.ex em ficheiros csv diferentes ou entre csv e opcao -a)
7   -- double click submits twice.
8   -- duplo clicks no botao "responder" dessincroniza as questões, ver debounce em https://stackoverflow.com/questions/20281546/how-to-prevent-calling-of-en-event-handler-twice-on-fast-clicks
9 5 - devia mostrar timeout para o aluno saber a razao.
10 6 - permitir configuracao para escolher entre static files locais ou remotos
11 7 - templates question-*.html tem input hidden question_ref que não é usado. remover?
12 8 - shift-enter não está a funcionar
13 9 - default prefix should be obtained from each course (yaml conf)?
  10 +- initdb da integrity error se no mesmo comando existirem alunos repetidos (p.ex em ficheiros csv diferentes ou entre csv e opcao -a)
14 11  
15 12 # TODO
16 13  
... ... @@ -34,6 +31,8 @@
34 31  
35 32 # FIXED
36 33  
  34 +- apos clicar no botao responder, inactivar o input (importante quando o tempo de correcção é grande)
  35 +- double click submits twice.
37 36 - checkbox devia ter correct no intervalo [0,1] tal como radio. em caso de desconto a correccção faz 2*x-1. isto permite a mesma semantica nos dois tipos de perguntas.
38 37 - marking all options right in a radio question breaks!
39 38 - implementar servidor http com redirect para https.
... ...
aprendizations/__init__.py
... ... @@ -30,7 +30,7 @@ are progressively uncovered as the students progress.
30 30 '''
31 31  
32 32 APP_NAME = 'aprendizations'
33   -APP_VERSION = '2019.11.dev4'
  33 +APP_VERSION = '2019.12.dev1'
34 34 APP_DESCRIPTION = __doc__
35 35  
36 36 __author__ = 'Miguel Barão'
... ...
aprendizations/questions.py
... ... @@ -220,11 +220,11 @@ class QuestionCheckbox(Question):
220 220 if self['discount'] and not all(0.0 <= x <= 1.0
221 221 for x in self['correct']):
222 222  
223   - msg0 = ('+-------------- BEHAVIOR CHANGE NOTICE --------------+')
224   - msg1 = ('| Correct values must be in the interval [0.0, 1.0]. |')
225   - msg2 = ('| I will convert to the new behavior, but you should |')
226   - msg3 = ('| fix it in the question. |')
227   - msg4 = ('+----------------------------------------------------+')
  223 + msg0 = ('+--------------- BEHAVIOR CHANGE NOTICE ---------------+')
  224 + msg1 = ('| Correct values in checkbox questions must be in the |')
  225 + msg2 = ('| interval [0.0, 1.0]. I will convert to the new |')
  226 + msg3 = ('| behavior, for now, but you should fix it. |')
  227 + msg4 = ('+------------------------------------------------------+')
228 228 logger.warning(msg0)
229 229 logger.warning(msg1)
230 230 logger.warning(msg2)
... ...
aprendizations/serve.py
... ... @@ -345,7 +345,7 @@ class QuestionHandler(BaseHandler):
345 345 return
346 346  
347 347 # --- brain hacking ;)
348   - await asyncio.sleep(2)
  348 + await asyncio.sleep(1.5)
349 349  
350 350 # --- answers are in a list. fix depending on question type
351 351 qtype = self.learn.get_student_question_type(user)
... ...
aprendizations/static/js/topic.js
1 1 $.fn.extend({
2   - animateCSS: function (animation) {
  2 + animateCSS: function (animation, run_on_end) {
3 3 var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
4 4 this.addClass('animated ' + animation).one(animationEnd, function() {
5 5 $(this).removeClass('animated ' + animation);
6   - $("#submit").removeClass("disabled");
  6 + if (run_on_end !== undefined) {
  7 + run_on_end();
  8 + }
7 9 });
8 10 }
9 11 });
... ... @@ -21,7 +23,9 @@ function showTriesLeft(tries) {
21 23  
22 24 // Get current question
23 25 function getQuestion() {
  26 + $("#comments").html("").hide();
24 27 $("#submit").addClass("disabled");
  28 +
25 29 $.ajax({
26 30 type: "GET",
27 31 url: "/question",
... ... @@ -37,6 +41,7 @@ function updateQuestion(response) {
37 41 var params = response["params"];
38 42  
39 43 $("#right, #wrong").hide();
  44 +
40 45 switch (method) {
41 46 case "new_question":
42 47 new_question(params["type"], params["question"], params["tries"], params["progress"]);
... ... @@ -52,13 +57,18 @@ function updateQuestion(response) {
52 57  
53 58 function new_question(type, question, tries, progress) {
54 59 window.scrollTo(0, 0);
55   - $("#question_div").html(question).animateCSS('bounceInDown');
56   - showTriesLeft(tries);
57   - $("#comments").html("").hide();
  60 + $("#submit").hide();
  61 + $("#question_div").animateCSS('bounceOutUp', function() {
  62 + $("#question_div").html(question);
  63 + MathJax.typeset();
  64 + $("#question_div").animateCSS('bounceInDown', function() {
  65 + showTriesLeft(tries);
  66 + $("#submit").removeClass("disabled").show();
  67 + });
  68 + });
58 69 var btntext = (type == "information") ? "Continuar" : "Responder";
59 70 $("#submit").html(btntext).off().click(postAnswer);
60 71 $('#topic_progress').css('width', (100*progress)+'%').attr('aria-valuenow', 100*progress);
61   - MathJax.typeset();
62 72  
63 73 if (type == "radio") {
64 74 $(".list-group-item").click(function (e) {
... ... @@ -93,6 +103,8 @@ function postAnswer() {
93 103 success: getFeedback,
94 104 error: function() {alert("O servidor não responde.");}
95 105 });
  106 + $("#submit").addClass("disabled").html('<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>');
  107 + $("fieldset").prop("disabled", true);
96 108 }
97 109  
98 110 function getFeedback(response) {
... ... @@ -106,32 +118,39 @@ function getFeedback(response) {
106 118  
107 119 switch (method) {
108 120 case "right":
  121 + $('#wrong').hide();
109 122 $('#comments').html(params['comments']).show();
110 123 $('#solution_right').html(params['solution']);
111 124 MathJax.typeset();
112   - $('#wrong').hide();
113   - $('#right').show().animateCSS('flipInX');
114   - $("#submit").html("Continuar").off().click(getQuestion);
  125 + $('#right').show().animateCSS('zoomIn', function(){
  126 + $("#submit").html("Continuar").removeClass("disabled").off().click(getQuestion);
  127 + });
115 128 break;
116 129  
117 130 case "try_again":
118 131 $('#comments').html(params['comments']).show();
119 132 MathJax.typeset();
120   - $('#question_div').animateCSS('shake');
121 133 $('#topic_progress').css('width', (100*params["progress"])+'%').attr('aria-valuenow', 100*params["progress"]);
122   - showTriesLeft(params["tries"]);
  134 + $('#question_div').animateCSS('shake', function() {
  135 + showTriesLeft(params["tries"]);
  136 + $("fieldset").prop("disabled", false);
  137 + $("#submit").html("Responder").removeClass("disabled");
  138 + });
123 139 break;
124 140  
125 141 case "wrong":
  142 + $("fieldset").prop("disabled", true);
  143 + $('#right').hide();
126 144 $('#comments').html(params['comments']).show();
127 145 $('#solution_wrong').html(params['solution']);
128 146 MathJax.typeset();
129   - $('#right').hide();
130   - $('#wrong').show().animateCSS('flipInX');
  147 + $('#question_div').animateCSS('shake', function() {
  148 + showTriesLeft(params["tries"]);
  149 + $('#wrong').show().animateCSS('zoomIn', function() {
  150 + $("#submit").html("Continuar").removeClass("disabled").off().click(getQuestion);
  151 + });
  152 + });
131 153 $('#topic_progress').css('width', (100*params["progress"])+'%').attr('aria-valuenow', 100*params["progress"]);
132   - showTriesLeft(params["tries"]);
133   - $("fieldset").attr("disabled", "disabled");
134   - $("#submit").html("Continuar").off().click(getQuestion);
135 154 break;
136 155  
137 156 case "invalid":
... ...
aprendizations/templates/topic.html
... ... @@ -21,7 +21,7 @@
21 21 }
22 22 };
23 23 </script>
24   - <script async type="text/javascript" id="MathJax-script" src="/static/mathjax/es5/tex-svg.js"></script>
  24 + <script async type="text/javascript" id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
25 25 <!-- Styles -->
26 26 <link rel="stylesheet" href="/static/mdbootstrap/css/bootstrap.min.css">
27 27 <link rel="stylesheet" href="/static/mdbootstrap/css/mdb.min.css">
... ...
package-lock.json
... ... @@ -40,9 +40,9 @@
40 40 }
41 41 },
42 42 "mdbootstrap": {
43   - "version": "4.9.0",
44   - "resolved": "https://registry.npmjs.org/mdbootstrap/-/mdbootstrap-4.9.0.tgz",
45   - "integrity": "sha512-6R3j5D9Qmp+Aa90FblOVAwVDSqpAICYW2dpNxh6uaVB9E9MCaBLdaTKLrXCB7xznReHEaA57pNABXgFoi2z7Rg=="
  43 + "version": "4.10.0",
  44 + "resolved": "https://registry.npmjs.org/mdbootstrap/-/mdbootstrap-4.10.0.tgz",
  45 + "integrity": "sha512-jpDSrAv9BbqHGFCHf9iQts7dWAuJYT3VFmElLkKpD6cGJ5Pcjv5oiTvfKvFGjVsxWsjLtj7Y0Rh135EYejkaeg=="
46 46 },
47 47 "mj-context-menu": {
48 48 "version": "0.2.0",
... ...
package.json
... ... @@ -5,7 +5,7 @@
5 5 "@fortawesome/fontawesome-free": "^5.11.2",
6 6 "codemirror": "^5.49.2",
7 7 "mathjax": "^3",
8   - "mdbootstrap": "^4.9.0"
  8 + "mdbootstrap": "^4.10.0"
9 9 },
10 10 "private": true
11 11 }
... ...