From 9788839fb9912c15c4cd64dec050d8ec23ed03be Mon Sep 17 00:00:00 2001 From: Miguel Barão Date: Sun, 1 Dec 2019 20:12:20 +0000 Subject: [PATCH] - 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 | 7 +++---- aprendizations/__init__.py | 2 +- aprendizations/questions.py | 10 +++++----- aprendizations/serve.py | 2 +- aprendizations/static/js/topic.js | 51 +++++++++++++++++++++++++++++++++++---------------- aprendizations/templates/topic.html | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 8 files changed, 50 insertions(+), 32 deletions(-) diff --git a/BUGS.md b/BUGS.md index 81b6095..2a44e32 100644 --- a/BUGS.md +++ b/BUGS.md @@ -1,16 +1,13 @@ # BUGS -- apos clicar no botao responder, inactivar o input (importante quando o tempo de correcção é grande) - nao esta a seguir o max_tries definido no ficheiro de dependencias. -- initdb da integrity error se no mesmo comando existirem alunos repetidos (p.ex em ficheiros csv diferentes ou entre csv e opcao -a) -- double click submits twice. -- 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 - devia mostrar timeout para o aluno saber a razao. - permitir configuracao para escolher entre static files locais ou remotos - templates question-*.html tem input hidden question_ref que não é usado. remover? - shift-enter não está a funcionar - default prefix should be obtained from each course (yaml conf)? +- initdb da integrity error se no mesmo comando existirem alunos repetidos (p.ex em ficheiros csv diferentes ou entre csv e opcao -a) # TODO @@ -34,6 +31,8 @@ # FIXED +- apos clicar no botao responder, inactivar o input (importante quando o tempo de correcção é grande) +- double click submits twice. - 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. - marking all options right in a radio question breaks! - implementar servidor http com redirect para https. diff --git a/aprendizations/__init__.py b/aprendizations/__init__.py index 15eb36a..9a04fde 100644 --- a/aprendizations/__init__.py +++ b/aprendizations/__init__.py @@ -30,7 +30,7 @@ are progressively uncovered as the students progress. ''' APP_NAME = 'aprendizations' -APP_VERSION = '2019.11.dev4' +APP_VERSION = '2019.12.dev1' APP_DESCRIPTION = __doc__ __author__ = 'Miguel Barão' diff --git a/aprendizations/questions.py b/aprendizations/questions.py index 62fc9d3..93d639f 100644 --- a/aprendizations/questions.py +++ b/aprendizations/questions.py @@ -220,11 +220,11 @@ class QuestionCheckbox(Question): if self['discount'] and not all(0.0 <= x <= 1.0 for x in self['correct']): - msg0 = ('+-------------- BEHAVIOR CHANGE NOTICE --------------+') - msg1 = ('| Correct values must be in the interval [0.0, 1.0]. |') - msg2 = ('| I will convert to the new behavior, but you should |') - msg3 = ('| fix it in the question. |') - msg4 = ('+----------------------------------------------------+') + msg0 = ('+--------------- BEHAVIOR CHANGE NOTICE ---------------+') + msg1 = ('| Correct values in checkbox questions must be in the |') + msg2 = ('| interval [0.0, 1.0]. I will convert to the new |') + msg3 = ('| behavior, for now, but you should fix it. |') + msg4 = ('+------------------------------------------------------+') logger.warning(msg0) logger.warning(msg1) logger.warning(msg2) diff --git a/aprendizations/serve.py b/aprendizations/serve.py index 160d9ff..6767c3d 100644 --- a/aprendizations/serve.py +++ b/aprendizations/serve.py @@ -345,7 +345,7 @@ class QuestionHandler(BaseHandler): return # --- brain hacking ;) - await asyncio.sleep(2) + await asyncio.sleep(1.5) # --- answers are in a list. fix depending on question type qtype = self.learn.get_student_question_type(user) diff --git a/aprendizations/static/js/topic.js b/aprendizations/static/js/topic.js index 532af82..637a022 100644 --- a/aprendizations/static/js/topic.js +++ b/aprendizations/static/js/topic.js @@ -1,9 +1,11 @@ $.fn.extend({ - animateCSS: function (animation) { + animateCSS: function (animation, run_on_end) { var animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend'; this.addClass('animated ' + animation).one(animationEnd, function() { $(this).removeClass('animated ' + animation); - $("#submit").removeClass("disabled"); + if (run_on_end !== undefined) { + run_on_end(); + } }); } }); @@ -21,7 +23,9 @@ function showTriesLeft(tries) { // Get current question function getQuestion() { + $("#comments").html("").hide(); $("#submit").addClass("disabled"); + $.ajax({ type: "GET", url: "/question", @@ -37,6 +41,7 @@ function updateQuestion(response) { var params = response["params"]; $("#right, #wrong").hide(); + switch (method) { case "new_question": new_question(params["type"], params["question"], params["tries"], params["progress"]); @@ -52,13 +57,18 @@ function updateQuestion(response) { function new_question(type, question, tries, progress) { window.scrollTo(0, 0); - $("#question_div").html(question).animateCSS('bounceInDown'); - showTriesLeft(tries); - $("#comments").html("").hide(); + $("#submit").hide(); + $("#question_div").animateCSS('bounceOutUp', function() { + $("#question_div").html(question); + MathJax.typeset(); + $("#question_div").animateCSS('bounceInDown', function() { + showTriesLeft(tries); + $("#submit").removeClass("disabled").show(); + }); + }); var btntext = (type == "information") ? "Continuar" : "Responder"; $("#submit").html(btntext).off().click(postAnswer); $('#topic_progress').css('width', (100*progress)+'%').attr('aria-valuenow', 100*progress); - MathJax.typeset(); if (type == "radio") { $(".list-group-item").click(function (e) { @@ -93,6 +103,8 @@ function postAnswer() { success: getFeedback, error: function() {alert("O servidor não responde.");} }); + $("#submit").addClass("disabled").html(''); + $("fieldset").prop("disabled", true); } function getFeedback(response) { @@ -106,32 +118,39 @@ function getFeedback(response) { switch (method) { case "right": + $('#wrong').hide(); $('#comments').html(params['comments']).show(); $('#solution_right').html(params['solution']); MathJax.typeset(); - $('#wrong').hide(); - $('#right').show().animateCSS('flipInX'); - $("#submit").html("Continuar").off().click(getQuestion); + $('#right').show().animateCSS('zoomIn', function(){ + $("#submit").html("Continuar").removeClass("disabled").off().click(getQuestion); + }); break; case "try_again": $('#comments').html(params['comments']).show(); MathJax.typeset(); - $('#question_div').animateCSS('shake'); $('#topic_progress').css('width', (100*params["progress"])+'%').attr('aria-valuenow', 100*params["progress"]); - showTriesLeft(params["tries"]); + $('#question_div').animateCSS('shake', function() { + showTriesLeft(params["tries"]); + $("fieldset").prop("disabled", false); + $("#submit").html("Responder").removeClass("disabled"); + }); break; case "wrong": + $("fieldset").prop("disabled", true); + $('#right').hide(); $('#comments').html(params['comments']).show(); $('#solution_wrong').html(params['solution']); MathJax.typeset(); - $('#right').hide(); - $('#wrong').show().animateCSS('flipInX'); + $('#question_div').animateCSS('shake', function() { + showTriesLeft(params["tries"]); + $('#wrong').show().animateCSS('zoomIn', function() { + $("#submit").html("Continuar").removeClass("disabled").off().click(getQuestion); + }); + }); $('#topic_progress').css('width', (100*params["progress"])+'%').attr('aria-valuenow', 100*params["progress"]); - showTriesLeft(params["tries"]); - $("fieldset").attr("disabled", "disabled"); - $("#submit").html("Continuar").off().click(getQuestion); break; case "invalid": diff --git a/aprendizations/templates/topic.html b/aprendizations/templates/topic.html index 0431e84..a54b23b 100644 --- a/aprendizations/templates/topic.html +++ b/aprendizations/templates/topic.html @@ -21,7 +21,7 @@ } }; - + diff --git a/package-lock.json b/package-lock.json index 406ffc9..a62318f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,9 +40,9 @@ } }, "mdbootstrap": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/mdbootstrap/-/mdbootstrap-4.9.0.tgz", - "integrity": "sha512-6R3j5D9Qmp+Aa90FblOVAwVDSqpAICYW2dpNxh6uaVB9E9MCaBLdaTKLrXCB7xznReHEaA57pNABXgFoi2z7Rg==" + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/mdbootstrap/-/mdbootstrap-4.10.0.tgz", + "integrity": "sha512-jpDSrAv9BbqHGFCHf9iQts7dWAuJYT3VFmElLkKpD6cGJ5Pcjv5oiTvfKvFGjVsxWsjLtj7Y0Rh135EYejkaeg==" }, "mj-context-menu": { "version": "0.2.0", diff --git a/package.json b/package.json index 1414bbe..fc1e45f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "@fortawesome/fontawesome-free": "^5.11.2", "codemirror": "^5.49.2", "mathjax": "^3", - "mdbootstrap": "^4.9.0" + "mdbootstrap": "^4.10.0" }, "private": true } -- libgit2 0.21.2