[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
This commit is contained in:
committed by
Aurélien Warnon
parent
176e5a5066
commit
280c6bf1d6
@@ -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({
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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'));
|
||||
|
||||
@@ -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)"/>
|
||||
|
||||
Reference in New Issue
Block a user