diff options
| author | David Beguin <dbe@odoo.com> | 2020-03-04 08:54:15 +0000 |
|---|---|---|
| committer | Aurélien Warnon <awa@odoo.com> | 2020-03-31 16:25:53 +0000 |
| commit | 280c6bf1d6d823cde7aae1608aca4e4c36a80f22 (patch) | |
| tree | 7d3f40d1e21c3974bf104b1aa1063f566fc6e5fd /addons | |
| parent | 176e5a5066ec0248c80d15af60a6be237cb450d0 (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.py | 6 | ||||
| -rw-r--r-- | addons/survey/controllers/survey_session_manage.py | 3 | ||||
| -rw-r--r-- | addons/survey/models/survey_survey.py | 23 | ||||
| -rw-r--r-- | addons/survey/static/src/js/survey_form.js | 18 | ||||
| -rw-r--r-- | addons/survey/views/survey_templates.xml | 15 |
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)) < 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)"/> |
