[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:
@@ -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 {
|
||||
|
||||
@@ -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...">
|
||||
|
||||
Reference in New Issue
Block a user