[FIX] website_slides: auto set done successfull quizz
For now, in no fullscreen mode, if the quiz is succeed, the user progress is not updated because the quiz is not set to done. This commit implements this call to mark slide as done and green the check bullet. We decided to unify the submit RPC call with the done one, so a quiz (or a slide with questions) can only be done when submitting answers. As consequence, we need to prevent some slide type to use the /set_completed route (quiz and certif). Task-1941250
This commit is contained in:
@@ -61,6 +61,9 @@ class WebsiteSlides(WebsiteProfile):
|
||||
return True
|
||||
|
||||
def _set_completed_slide(self, slide, quiz_attempts_inc=False):
|
||||
# quiz use their specific mechanism to be marked as done
|
||||
if slide.slide_type == 'quiz' or slide.question_ids:
|
||||
raise werkzeug.exceptions.Forbidden(_("Slide with questions must be marked as done when submitting all good answers "))
|
||||
if slide.website_published and slide.channel_id.is_member:
|
||||
slide.action_set_completed(quiz_attempts_inc=quiz_attempts_inc)
|
||||
return True
|
||||
@@ -662,6 +665,7 @@ class WebsiteSlides(WebsiteProfile):
|
||||
rank_progress = {}
|
||||
if not user_bad_answers:
|
||||
slide._action_set_quiz_done()
|
||||
slide.action_set_completed(quiz_attempts_inc=True)
|
||||
lower_bound = request.env.user.rank_id.karma_min
|
||||
upper_bound = request.env.user.next_rank_id.karma_min
|
||||
rank_progress = {
|
||||
@@ -674,11 +678,12 @@ class WebsiteSlides(WebsiteProfile):
|
||||
return {
|
||||
'goodAnswers': user_good_answers.ids,
|
||||
'badAnswers': user_bad_answers.ids,
|
||||
'completed': not user_bad_answers,
|
||||
'completed': slide.user_membership_id.sudo().completed,
|
||||
'channel_completion': slide.channel_id.completion,
|
||||
'quizKarmaWon': quiz_info['quiz_karma_won'],
|
||||
'quizKarmaGain': quiz_info['quiz_karma_gain'],
|
||||
'quizAttemptsCount': quiz_info['quiz_attempts_count'],
|
||||
'rankProgress': rank_progress
|
||||
'rankProgress': rank_progress,
|
||||
}
|
||||
|
||||
# --------------------------------------------------
|
||||
|
||||
@@ -102,7 +102,7 @@ odoo.define('website_slides.fullscreen', function (require) {
|
||||
if (totalTime && currentTime > totalTime - 30){
|
||||
clearInterval(self.tid);
|
||||
if (!self.slide.hasQuestion && !self.slide.completed){
|
||||
self.trigger_up('slide_completed', self.slide);
|
||||
self.trigger_up('slide_to_complete', self.slide);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,8 +289,8 @@ odoo.define('website_slides.fullscreen', function (require) {
|
||||
},
|
||||
custom_events: {
|
||||
'change_slide': '_onChangeSlideRequest',
|
||||
'slide_to_complete': '_onSlideToComplete',
|
||||
'slide_completed': '_onSlideCompleted',
|
||||
'quiz_completed': '_onSlideCompleted',
|
||||
'slide_go_next': '_onSlideGoToNext',
|
||||
},
|
||||
/**
|
||||
@@ -367,11 +367,17 @@ odoo.define('website_slides.fullscreen', function (require) {
|
||||
*/
|
||||
_fetchSlideContent: function (){
|
||||
var slide = this.get('slide');
|
||||
if (slide.type === 'webpage') {
|
||||
if (slide.type === 'webpage' && !slide.isQuiz) {
|
||||
return this._fetchHtmlContent();
|
||||
}
|
||||
return $.when();
|
||||
},
|
||||
_markAsCompleted: function (slideId, completion) {
|
||||
var slide = findSlide(this.slides, {id: slideId});
|
||||
slide.completed = true;
|
||||
this.sidebar.setSlideCompleted(slide.id);
|
||||
this.sidebar.updateProgressbar(completion);
|
||||
},
|
||||
/**
|
||||
* Extend the slide data list to add informations about rendering method, and other
|
||||
* specific values according to their slide_type.
|
||||
@@ -459,9 +465,7 @@ odoo.define('website_slides.fullscreen', function (require) {
|
||||
slide_id: slide.id,
|
||||
}
|
||||
}).then(function (data){
|
||||
slide.completed = true;
|
||||
self.sidebar.setSlideCompleted(slide.id);
|
||||
self.sidebar.updateProgressbar(data.channel_completion);
|
||||
self._markAsCompleted(slideId, data.channel_completion);
|
||||
});
|
||||
}
|
||||
return $.when();
|
||||
@@ -504,13 +508,23 @@ odoo.define('website_slides.fullscreen', function (require) {
|
||||
});
|
||||
this.set('slide', newSlide);
|
||||
},
|
||||
/**
|
||||
* Triggered when subwidget has mark the slide as done, and the UI need to be adapted.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onSlideCompleted: function (ev) {
|
||||
var slide = ev.data.slide;
|
||||
var completion = ev.data.completion;
|
||||
this._markAsCompleted(slide.id, completion);
|
||||
},
|
||||
/**
|
||||
* Triggered when sub widget business is done and that slide
|
||||
* can now be marked as done.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onSlideCompleted: function (ev) {
|
||||
_onSlideToComplete: function (ev) {
|
||||
if (!session.is_website_user) { // no useless RPC call
|
||||
var slideId = ev.data.id;
|
||||
this._setCompleted(slideId);
|
||||
|
||||
@@ -177,15 +177,6 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
QWeb.render('slide.slide.quiz.validation', {'widget': this})
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the slide as completed and done. Trigger up the completion.
|
||||
*
|
||||
* @param {Integer} completion
|
||||
*/
|
||||
_setCompleted: function () {
|
||||
this.trigger_up('quiz_completed', this.slide);
|
||||
},
|
||||
/*
|
||||
* Submit the given answer, and display the result
|
||||
*
|
||||
@@ -203,13 +194,12 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
if (data.error) {
|
||||
self._alertShow(data.error);
|
||||
} else {
|
||||
self.slide.completed = data.completed;
|
||||
self.quiz = _.extend(self.quiz, data);
|
||||
self._renderAnswersHighlighting();
|
||||
self._renderValidationInfo();
|
||||
if (self.slide.completed) {
|
||||
if (data.completed) {
|
||||
self._renderSuccessModal(data);
|
||||
self._setCompleted();
|
||||
self.trigger_up('slide_completed', {slide: self.slide, completion: data.channel_completion});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -266,10 +256,10 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
});
|
||||
|
||||
sAnimations.registry.websiteSlidesQuizNoFullscreen = sAnimations.Class.extend({
|
||||
selector: '.o_wslides_js_lesson_quiz',
|
||||
selector: '.o_wslides_lesson_main', // selector of complete page, as we need slide content and aside content table
|
||||
custom_events: {
|
||||
slide_go_next: '_onQuizNextSlide',
|
||||
quiz_completed: '_onQuizCompleted',
|
||||
slide_completed: '_onQuizCompleted',
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -282,8 +272,9 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
*/
|
||||
start: function () {
|
||||
var self = this;
|
||||
this.quizWidgets = [];
|
||||
var defs = [this._super.apply(this, arguments)];
|
||||
$('.o_wslides_js_lesson_quiz').each(function () {
|
||||
this.$('.o_wslides_js_lesson_quiz').each(function () {
|
||||
var slideData = $(this).data();
|
||||
slideData.quizData = {
|
||||
questions: self._extractQuestionsAndAnswers(),
|
||||
@@ -300,13 +291,17 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
//----------------------------------------------------------------------
|
||||
// Handlers
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
_onQuizCompleted: function (slideId) {
|
||||
console.log('set completed', slideId);
|
||||
_onQuizCompleted: function (ev) {
|
||||
var self = this;
|
||||
var slide = ev.data.slide;
|
||||
var completion = ev.data.completion;
|
||||
this.$('#o_wslides_lesson_aside_slide_check_' + slide.id).addClass('text-success fa-check-circle').removeClass('text-600 fa-circle-o');
|
||||
// need to use global selector as progress bar is ouside this animation widget scope
|
||||
$('.o_wslides_lesson_header .progress-bar').css('width', completion + "%");
|
||||
$('.o_wslides_lesson_header .progress span').text(_.str.sprintf("%s %%", completion));
|
||||
},
|
||||
|
||||
_onQuizNextSlide: function () {
|
||||
var url = this.$el.data('next-slide-url');
|
||||
var url = this.$('.o_wslides_js_lesson_quiz').data('next-slide-url');
|
||||
window.location.replace(url);
|
||||
},
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.website_slides.controllers.main import WebsiteSlides
|
||||
import werkzeug
|
||||
|
||||
from odoo.addons.website_slides.controllers.main import WebsiteSlides
|
||||
from odoo import _
|
||||
from odoo.http import request
|
||||
|
||||
|
||||
@@ -49,6 +51,13 @@ class WebsiteSlides(WebsiteSlides):
|
||||
|
||||
return result
|
||||
|
||||
# Utils
|
||||
# ---------------------------------------------------
|
||||
def _set_completed_slide(self, slide, quiz_attempts_inc=False):
|
||||
if slide.slide_type == 'certification':
|
||||
raise werkzeug.exceptions.Forbidden(_("Certification slides are completed when the survey is succeeded."))
|
||||
return super(WebsiteSlides, self)._set_completed_slide(slide, quiz_attempts_inc=quiz_attempts_inc)
|
||||
|
||||
# Profile
|
||||
# ---------------------------------------------------
|
||||
def _prepare_user_slides_profile(self, user):
|
||||
|
||||
Reference in New Issue
Block a user