summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorDavid Beguin <dbe@odoo.com>2020-03-04 08:54:15 +0000
committerAurélien Warnon <awa@odoo.com>2020-03-31 16:25:53 +0000
commit280c6bf1d6d823cde7aae1608aca4e4c36a80f22 (patch)
tree7d3f40d1e21c3974bf104b1aa1063f566fc6e5fd /addons
parent176e5a5066ec0248c80d15af60a6be237cb450d0 (diff)
[IMP] survey: auto submit for questions and matrix with simple choice
Purpose ======= Speed up survey completion. Specifications ============== This commit apply an auto commit when user select a choice on a simple choice question or on a matrix question with simple choice. The auto commit happens following those conditions: - Only on simple choice and matrix with simple choice questions - For matrix, only when last subquestion is answered - Only when Back mode is active - If this is not the last question Link ==== PR #46768 Task 2208574
Diffstat (limited to 'addons')
-rw-r--r--addons/survey/controllers/main.py6
-rw-r--r--addons/survey/controllers/survey_session_manage.py3
-rw-r--r--addons/survey/models/survey_survey.py23
-rw-r--r--addons/survey/static/src/js/survey_form.js18
-rw-r--r--addons/survey/views/survey_templates.xml15
5 files changed, 52 insertions, 13 deletions
diff --git a/addons/survey/controllers/main.py b/addons/survey/controllers/main.py
index 8f931ae5cf8..0d0a32ee9a2 100644
--- a/addons/survey/controllers/main.py
+++ b/addons/survey/controllers/main.py
@@ -286,9 +286,9 @@ class Survey(http.Controller):
answer_sudo.last_displayed_page_id.id if answer_sudo.last_displayed_page_id else 0)
if next_page_or_question:
- pages_or_questions = survey_sudo._get_pages_or_questions(answer_sudo)
- if pages_or_questions.ids.index(next_page_or_question.id) == len(pages_or_questions) - 1:
- data.update({'survey_last': True})
+ data.update({
+ 'survey_last': survey_sudo._is_last_page_or_question(answer_sudo, next_page_or_question)
+ })
if answer_sudo.is_session_answer and next_page_or_question.is_time_limited:
data.update({
diff --git a/addons/survey/controllers/survey_session_manage.py b/addons/survey/controllers/survey_session_manage.py
index cdcbabfdfe2..e81626ce95b 100644
--- a/addons/survey/controllers/survey_session_manage.py
+++ b/addons/survey/controllers/survey_session_manage.py
@@ -188,7 +188,8 @@ class UserInputSession(http.Controller):
def _prepare_manage_session_values(self, survey):
is_last_question = False
if survey.question_ids:
- is_last_question = survey.session_question_id == survey.question_ids[-1]
+ most_voted_answers = survey._get_session_most_voted_answers()
+ is_last_question = survey._is_last_page_or_question(most_voted_answers, survey.session_question_id)
values = {
'survey': survey,
diff --git a/addons/survey/models/survey_survey.py b/addons/survey/models/survey_survey.py
index c5d0c5b1367..60558a94924 100644
--- a/addons/survey/models/survey_survey.py
+++ b/addons/survey/models/survey_survey.py
@@ -549,7 +549,7 @@ class Survey(models.Model):
if page_or_question_id == 0:
return pages_or_questions[0]
- current_page_index = pages_or_questions.ids.index(next(p.id for p in pages_or_questions if p.id == page_or_question_id))
+ current_page_index = pages_or_questions.ids.index(page_or_question_id)
# Get previous and we are on first page OR Get Next and we are on last page
if (go_back and current_page_index == 0) or (not go_back and current_page_index == len(pages_or_questions) - 1):
@@ -582,6 +582,27 @@ class Survey(models.Model):
return Question
+ def _is_last_page_or_question(self, user_input, page_or_question):
+ """ This method checks if the given question or page is the last one.
+ This includes conditional questions configuration. If the given question is normally not the last one but
+ every following questions are inactive due to conditional questions configurations (and user choices),
+ the given question will be the last one.
+ For section, we check in each following section if there is an active question.
+ If yes, the given page is not the last one.
+ """
+ pages_or_questions = self._get_pages_or_questions(user_input)
+ current_page_index = pages_or_questions.ids.index(page_or_question.id)
+ next_page_or_question_candidates = pages_or_questions[current_page_index + 1:]
+ if next_page_or_question_candidates:
+ inactive_questions = user_input._get_inactive_conditional_questions()
+ if self.questions_layout == 'page_per_question':
+ return not any(next_question not in inactive_questions for next_question in next_page_or_question_candidates)
+ elif self.questions_layout == 'page_per_section':
+ for section in next_page_or_question_candidates:
+ return not any(next_question not in inactive_questions for next_question in section.question_ids)
+
+ return True
+
def _get_survey_questions(self, answer=None, page_id=None, question_id=None):
""" Returns a tuple containing: the survey question and the passed question_id / page_id
based on the question_layout and the fact that it's a session or not.
diff --git a/addons/survey/static/src/js/survey_form.js b/addons/survey/static/src/js/survey_form.js
index 9827062e6b4..7d77dcab579 100644
--- a/addons/survey/static/src/js/survey_form.js
+++ b/addons/survey/static/src/js/survey_form.js
@@ -111,6 +111,7 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend({
} else {
$choiceInput.prop("checked", !$choiceInput.prop("checked")).trigger('change');
}
+
// Avoid selection key to be typed into the textbox if 'other' is selected by key
event.preventDefault();
}
@@ -146,9 +147,20 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend({
var $matrixBtn = $target.closest('.o_survey_matrix_btn');
if ($target.attr('type') === 'radio') {
+ var isQuestionComplete = false;
if ($matrixBtn.length > 0) {
$matrixBtn.closest('tr').find('td').removeClass('o_survey_selected');
$matrixBtn.addClass('o_survey_selected');
+ if (this.options.questionsLayout === 'page_per_question') {
+ var subQuestionsIds = $matrixBtn.closest('table').data('subQuestions');
+ var completedQuestions = [];
+ subQuestionsIds.forEach(function (id) {
+ if (self.$('tr#' + id).find('input:checked').length !== 0) {
+ completedQuestions.push(id);
+ }
+ });
+ isQuestionComplete = completedQuestions.length === subQuestionsIds.length;
+ }
} else {
var previouslySelectedAnswer = $choiceItemGroup.find('label.o_survey_selected');
previouslySelectedAnswer.removeClass('o_survey_selected');
@@ -156,6 +168,7 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend({
var newlySelectedAnswer = $target.closest('label');
if (newlySelectedAnswer.find('input').val() !== previouslySelectedAnswer.find('input').val()) {
newlySelectedAnswer.addClass('o_survey_selected');
+ isQuestionComplete = this.options.questionsLayout === 'page_per_question';
}
// Conditional display
@@ -187,6 +200,11 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend({
}
}
}
+ // Submit Form
+ var isLastQuestion = this.$('button[value="finish"]').length !== 0;
+ if (!isLastQuestion && this.options.usersCanGoBack && isQuestionComplete) {
+ this._submitForm({});
+ }
} else { // $target.attr('type') === 'checkbox'
if ($matrixBtn.length > 0) {
$matrixBtn.toggleClass('o_survey_selected', !$matrixBtn.hasClass('o_survey_selected'));
diff --git a/addons/survey/views/survey_templates.xml b/addons/survey/views/survey_templates.xml
index c26189a31ce..7a008e7e162 100644
--- a/addons/survey/views/survey_templates.xml
+++ b/addons/survey/views/survey_templates.xml
@@ -88,6 +88,7 @@
class="d-flex flex-grow-1"
t-att-data-answer-token="answer.access_token"
t-att-data-survey-token="survey.access_token"
+ t-att-data-users-can-go-back="survey.users_can_go_back"
t-att-data-session-in-progress="answer.is_session_answer"
t-att-data-is-start-screen="answer.state == 'new'"
t-att-data-readonly="survey_form_readonly"
@@ -186,7 +187,9 @@
<div class="row">
<div class="offset-3 col-6 text-center mt16">
<button type="submit" t-att-value="'next' if not survey_last else 'finish'" class="btn btn-primary">
- Continue</button><span class="font-weight-bold text-muted ml-2 d-none d-md-inline"> or press Enter</span>
+ <t t-if="not survey_last">Continue</t>
+ <t t-else="">Submit</t>
+ </button><span class="font-weight-bold text-muted ml-2 d-none d-md-inline"> or press Enter</span>
</div>
</div>
</t>
@@ -221,12 +224,8 @@
<div class="row">
<div class="offset-3 col-6 text-center mt16">
<button type="submit" t-att-value="'next' if not survey_last else 'finish'" class="btn btn-primary">
- <t t-if="answer.is_session_answer">
- Submit
- </t>
- <t t-else="">
- Continue
- </t>
+ <t t-if="answer.is_session_answer or survey_last">Submit</t>
+ <t t-else="">Continue</t>
</button>
<span class="font-weight-bold text-muted ml-2 d-none d-md-inline">or press Enter</span>
</div>
@@ -532,7 +531,7 @@
<t t-set="item_idx" t-value="0"/>
<!-- For matrix, we have an extra check because we have rows * columns total options -->
<t t-set="useKeySelection" t-value="useKeySelection and (len(question.suggested_answer_ids) * len(question.matrix_row_ids)) &lt; len(letters)" />
- <tr class="bg-white text-white" t-foreach="question.matrix_row_ids" t-as="row_label">
+ <tr class="bg-white text-white" t-foreach="question.matrix_row_ids" t-as="row_label" t-att-id="row_label.id">
<th class="border-0 font-weight-normal text-left"><span t-field="row_label.value" /></th>
<t t-foreach="question.suggested_answer_ids" t-as="col_label">
<t t-set="answer" t-value="answer_lines.filtered(lambda line: line.suggested_answer_id == col_label and line.matrix_row_id == row_label)"/>