diff --git a/addons/survey/models/survey_user.py b/addons/survey/models/survey_user.py index e7592caa721..bab1fd5165a 100644 --- a/addons/survey/models/survey_user.py +++ b/addons/survey/models/survey_user.py @@ -91,7 +91,7 @@ class SurveyUserInput(models.Model): start_time = user_input.start_datetime time_limit = user_input.survey_id.time_limit user_input.survey_time_limit_reached = user_input.survey_id.is_time_limited and \ - fields.Datetime.now() > start_time + relativedelta(minutes=time_limit) + fields.Datetime.now() >= start_time + relativedelta(minutes=time_limit) else: user_input.survey_time_limit_reached = False @@ -107,7 +107,7 @@ class SurveyUserInput(models.Model): start_time = user_input.survey_id.session_question_start_time time_limit = user_input.survey_id.session_question_id.time_limit user_input.question_time_limit_reached = user_input.survey_id.session_question_id.is_time_limited and \ - fields.Datetime.now() > start_time + relativedelta(seconds=time_limit) + fields.Datetime.now() >= start_time + relativedelta(seconds=time_limit) else: user_input.question_time_limit_reached = False diff --git a/addons/survey/static/src/js/survey_session_manage.js b/addons/survey/static/src/js/survey_session_manage.js index 897aab6d7b3..79d53a2db91 100644 --- a/addons/survey/static/src/js/survey_session_manage.js +++ b/addons/survey/static/src/js/survey_session_manage.js @@ -26,6 +26,7 @@ publicWidget.registry.SurveySessionManage = publicWidget.Widget.extend({ */ start: function () { var self = this; + this.fadeInOutTime = 500; return this._super.apply(this, arguments).then(function () { // general survey props self.surveyId = self.$el.data('surveyId'); @@ -304,7 +305,7 @@ publicWidget.registry.SurveySessionManage = publicWidget.Widget.extend({ var resolveFadeOut; var fadeOutPromise = new Promise(function (resolve, reject) { resolveFadeOut = resolve; }); - this.$el.fadeOut(500, function () { + this.$el.fadeOut(this.fadeInOutTime, function () { resolveFadeOut(); }); @@ -323,7 +324,7 @@ publicWidget.registry.SurveySessionManage = publicWidget.Widget.extend({ var $renderedTemplate = $(results[1]); self.$el.replaceWith($renderedTemplate); self.attachTo($renderedTemplate); - self.$el.fadeIn(500, function () { + self.$el.fadeIn(self.fadeInOutTime, function () { self._startTimer(); }); } else { diff --git a/addons/survey/static/src/js/survey_timer.js b/addons/survey/static/src/js/survey_timer.js index d0a38c88324..2bfd78fedf8 100644 --- a/addons/survey/static/src/js/survey_timer.js +++ b/addons/survey/static/src/js/survey_timer.js @@ -25,17 +25,16 @@ publicWidget.registry.SurveyTimerWidget = publicWidget.Widget.extend({ * @override */ start: function () { - var superDef = this._super.apply(this, arguments); - - this.countDownDate = moment.utc(this.timer).add(this.timeLimitMinutes, 'minutes'); - if (this.timeLimitMinutes <= 0 || this.countDownDate.diff(moment.utc(), 'seconds') < 0) { - this.trigger_up('time_up'); - } else { - this._updateTimer(this); - this.surveyTimerInterval = setInterval(this._updateTimer.bind(this), 1000); - } - - return superDef; + var self = this; + return this._super.apply(this, arguments).then(function () { + self.countDownDate = moment.utc(self.timer).add(self.timeLimitMinutes, 'minutes'); + if (self.timeLimitMinutes <= 0 || self.countDownDate.diff(moment.utc(), 'seconds') < 0) { + self.trigger_up('time_up'); + } else { + self._updateTimer(); + self.surveyTimerInterval = setInterval(self._updateTimer.bind(self), 1000); + } + }); }, // ------------------------------------------------------------------------- @@ -49,9 +48,13 @@ publicWidget.registry.SurveyTimerWidget = publicWidget.Widget.extend({ /** * This function is responsible for the visual update of the timer DOM every second. * When the time runs out, it triggers a 'time_up' event to notify the parent widget. + * + * We use a diff in millis and not a second, that we round to the nearest second. + * Indeed, a difference of 999 millis is interpreted as 0 second by moment, which is problematic + * for our use case. */ _updateTimer: function () { - var timeLeft = this.countDownDate.diff(moment.utc(), 'seconds'); + var timeLeft = Math.round(this.countDownDate.diff(moment.utc(), 'milliseconds') / 1000); if (timeLeft >= 0) { var timeLeftMinutes = parseInt(timeLeft / 60); diff --git a/addons/survey/static/src/scss/survey_form.scss b/addons/survey/static/src/scss/survey_form.scss index 97b1343b2fe..e7613950ccc 100644 --- a/addons/survey/static/src/scss/survey_form.scss +++ b/addons/survey/static/src/scss/survey_form.scss @@ -31,6 +31,10 @@ nav#oe_main_menu_navbar { cursor: pointer; } +.o_survey_timer { + min-height: 1.2rem; +} + .o_survey_brand_message { background-color: rgba(255,255,255,0.7); } diff --git a/addons/survey/static/tests/tours/survey_session_manage_test.js b/addons/survey/static/tests/tours/survey_session_manage_test.js index acf3d99c945..dfd7f53841e 100644 --- a/addons/survey/static/tests/tours/survey_session_manage_test.js +++ b/addons/survey/static/tests/tours/survey_session_manage_test.js @@ -4,13 +4,31 @@ odoo.define('survey.session_manage_test', function (require) { var SessionManager = require('survey.session_manage'); /** * Small override for test/tour purposes. - * We trigger the fetch of answer results immediately at the start. - * (Instead of wasting 2 seconds waiting after the start). */ SessionManager.include({ + /** + * - Trigger the fetch of answer results immediately at the start. + * (Instead of wasting 2 seconds waiting after the start). + * - Set the fade in/out time to 1 ms to avoid unnecessary delays. + * - Avoid refreshing the results every 2 seconds + */ start: function () { + var self = this; return this._super.apply(this, arguments) - .then(this._refreshResults.bind(this)); + .then(this._refreshResults.bind(this)) + .then(function () { + self.fadeInOutTime = 1; + clearInterval(self.resultsRefreshInterval); + }); + }, + + /** + * Force the timer to "now" to avoid introducing potential test breaking + * timely variables (rpc/small server delay/...) if the start_question_time flickers. + */ + _startTimer: function () { + this.$el.data('timer', moment.utc()); + return this._super.apply(this, arguments); } }); diff --git a/addons/survey/static/tests/tours/survey_tour_session_manage.js b/addons/survey/static/tests/tours/survey_tour_session_manage.js index 36b5d8dfeca..06c0916850e 100644 --- a/addons/survey/static/tests/tours/survey_tour_session_manage.js +++ b/addons/survey/static/tests/tours/survey_tour_session_manage.js @@ -282,8 +282,9 @@ tour.register('test_survey_session_manage_tour', { } } - // after 1 second, results are displayed automatically because question timer - // runs out + // after 1 second, results are displayed automatically because question timer runs out + // we add 1 extra second because of the way the timer works: + // it only triggers the time_up event 1 second AFTER the delay is passed setTimeout(function () { chartData = getChartData(); var firstAnswerData = chartData[0]; @@ -338,7 +339,7 @@ tour.register('test_survey_session_manage_tour', { } nextScreen(); - }, 1500); + }, 2100); } }, { trigger: 'h1:contains("Final Leaderboard")', diff --git a/addons/survey/views/survey_templates_user_input_session.xml b/addons/survey/views/survey_templates_user_input_session.xml index 005dd879bb2..2bd533f1367 100644 --- a/addons/survey/views/survey_templates_user_input_session.xml +++ b/addons/survey/views/survey_templates_user_input_session.xml @@ -91,7 +91,7 @@

- +