[FIX] survey: correctly handle "free text sections" in surveys and sessions

We now have a way to display "free text sections" during the survey flow.
(Since 5b74f54396 )

However, the behavior during survey sessions was not optimal:
- Attendees could click on "submit" and it would raise an error
- The section description was not displayed on the host screen
- The section description was never the "current question" of the session of it
  was the first item of the question_and_page_ids

This commit fixes all those points to have a nice session flow.

While the host is explaining the section description to the attendees, they get
a waiting message on their screen.

In addition, we fixed the display to avoid showing pages that lack a
description, and we reworked the '_get_pages_or_questions' method to have more
meaningful and readable cases for every layouts.

LINKS

PR #48442
Task 2208574
This commit is contained in:
Aurélien Warnon
2020-03-27 15:03:32 +00:00
parent 090f9ad333
commit 8d09178b42
6 changed files with 37 additions and 15 deletions
+2 -1
View File
@@ -13,7 +13,7 @@ from odoo.addons.base.models.ir_ui_view import keep_query
from odoo.exceptions import UserError
from odoo.http import request, content_disposition
from odoo.osv import expression
from odoo.tools import format_datetime, format_date
from odoo.tools import format_datetime, format_date, is_html_empty
from odoo.addons.web.controllers.main import Binary
@@ -266,6 +266,7 @@ class Survey(http.Controller):
- previous_page_id : come from the breadcrumb or the back button and force the next questions to load
to be the previous ones. """
data = {
'is_html_empty': is_html_empty,
'survey': survey_sudo,
'answer': answer_sudo,
'breadcrumb_pages': [{
@@ -10,6 +10,7 @@ from werkzeug.urls import url_join
from odoo import fields, http
from odoo.http import request
from odoo.tools import is_html_empty
class UserInputSession(http.Controller):
@@ -165,6 +166,7 @@ class UserInputSession(http.Controller):
} for line in full_statistics.get('table_data', request.env['survey.user_input.line'])[:100]]
return {
'is_html_empty': is_html_empty,
'question_statistics_graph': full_statistics.get('graph_data'),
'input_line_values': input_line_values,
'answers_validity': json.dumps(answers_validity),
+20 -13
View File
@@ -9,6 +9,7 @@ import werkzeug
from odoo import api, exceptions, fields, models, _
from odoo.exceptions import AccessError
from odoo.osv import expression
from odoo.tools import is_html_empty
class Survey(models.Model):
@@ -437,12 +438,21 @@ class Survey(models.Model):
@api.model
def _get_pages_or_questions(self, user_input):
if self.questions_layout == 'one_page':
return self.env['survey.question']
elif self.questions_layout == 'page_per_question' and self.questions_selection == 'random':
return user_input.predefined_question_ids
else:
return self.question_and_page_ids if self.questions_layout == 'page_per_question' else self.page_ids
""" Returns the pages or questions (depending on the layout) that will be shown
to the user taking the survey.
In 'page_per_question' layout, we also want to show pages that have a description. """
result = self.env['survey.question']
if self.questions_layout == 'page_per_section':
result = self.page_ids
elif self.questions_layout == 'page_per_question':
if self.questions_selection == 'random':
result = user_input.predefined_question_ids
else:
result = self.question_and_page_ids.filtered(
lambda question: not question.is_page or not is_html_empty(question.description))
return result
def _get_next_page_or_question(self, user_input, page_or_question_id, go_back=False):
"""
@@ -580,13 +590,10 @@ class Survey(models.Model):
if not self.question_ids or not self.env.user.has_group('survey.group_survey_user'):
return
if not self.session_question_id:
next_question = self.question_ids[0]
else:
most_voted_answers = self._get_session_most_voted_answers()
next_question = self._get_next_page_or_question(most_voted_answers, self.session_question_id.id)
return next_question
most_voted_answers = self._get_session_most_voted_answers()
return self._get_next_page_or_question(
most_voted_answers,
self.session_question_id.id if self.session_question_id else 0)
def _get_session_most_voted_answers(self):
""" In sessions of survey that has conditional questions, as the survey is passed at the same time by
+7 -1
View File
@@ -51,7 +51,7 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend({
$(document).on('keypress', self._onKeyPress.bind(self));
}
if (self.options.sessionInProgress &&
(self.options.isStartScreen || self.options.hasAnswered)) {
(self.options.isStartScreen || self.options.hasAnswered || self.options.isPageDescription)) {
self.preventEnterSubmit = true;
}
self._initSessionManagement();
@@ -428,6 +428,12 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend({
}
self._initChoiceItems();
self._initTextArea();
if (this.options.sessionInProgress && this.$('.o_survey_form_content_data').data('isPageDescription')) {
// prevent enter submit if we're on a page description (there is nothing to submit)
this.preventEnterSubmit = true;
}
this.$('.o_survey_form_content').fadeIn(this.fadeInOutDelay);
$("html, body").animate({ scrollTop: 0 }, this.fadeInOutDelay);
self._focusOnFirstInput();
+5
View File
@@ -74,6 +74,7 @@
t-att-data-is-start-screen="answer.state == 'new'"
t-att-data-readonly="survey_form_readonly"
t-att-data-has-answered="bool(has_answered)"
t-att-data-is-page-description="bool(question and question.is_page and not is_html_empty(question.description))"
t-att-data-questions-layout="survey.questions_layout"
t-att-data-triggered-questions-by-answer="json.dumps(triggered_questions_by_answer)"
t-att-data-selected-answers="json.dumps(selected_answers)">
@@ -139,6 +140,7 @@
<div class="o_survey_form_content_data d-none"
t-att-data-question-time-limit-reached="answer.question_time_limit_reached"
t-att-data-has-answered="bool(has_answered)"
t-att-data-is-page-description="bool(question and question.is_page and not is_html_empty(question.description))"
t-att-data-timer="timer_start"
t-att-data-time-limit-minutes="time_limit_minutes"/>
<t t-if="survey.questions_layout == 'one_page'">
@@ -192,6 +194,9 @@
<div t-if="answer.question_time_limit_reached and not has_answered" class="font-weight-bold mb128">Sorry, you have not been fast enough.</div>
<div t-else="" class="font-weight-bold mb128">We have registered your answer! Please wait for the host to go to the next question.</div>
</t>
<t t-elif="answer.is_session_answer and question.is_page and not is_html_empty(question.description)">
<div class="font-weight-bold mt-5">Pay attention to the host screen until the next question.</div>
</t>
<t t-else="">
<t t-call="survey.question_container"/>
@@ -112,6 +112,7 @@
</div>
<div t-elif="show_text_answers" class="p-2 pt-4 o_survey_session_text_answers_container">
</div>
<div t-elif="question.is_page and not is_html_empty(question.description)" class="mb-6 o_survey_manage_fontsize_14" t-field="question.description" />
<div t-else="" class="mb-6">
<h2 class="font-weight-normal mb-3">
<span>Waiting for attendees...</span>