[FIX] survey: fix survey timer related issues

This commit fixes timer related issues on survey flows, for both regulars
surveys and survey sessions.
The timer was unreliable in its completion by a whole second, which had not a
big impact at the user level but could make some tests fail (randomly).

Side changes from this commit:
- Reduced delays in the survey session tests to speed up testing
- Removed some timer flickering on survey views

LINKS

Task 2230526
Runbot error ID 535

closes odoo/odoo#49178

X-original-commit: 15c72aec71d42624685fb0fc9df25279c7855310
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Aurélien Warnon
2020-04-08 07:33:14 +00:00
parent e3b5b20b39
commit f4803d548b
7 changed files with 50 additions and 23 deletions
+2 -2
View File
@@ -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
@@ -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 {
+15 -12
View File
@@ -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);
@@ -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);
}
@@ -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);
}
});
@@ -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")',
@@ -91,7 +91,7 @@
<div class="col-lg-8"><h1 t-esc="question.title"></h1></div>
<div class="col-lg-4 text-right d-flex flex-column justify-content-center">
<h1 t-if="question.is_time_limited" class="o_survey_timer_container">
<span class="o_survey_timer"/>
<span class="o_survey_timer d-inline-block"/>
</h1>
<div t-if="show_bar_chart or show_text_answers">
<div class="progress" title="Attendees are answering the question...">