[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:
jem-odoo
2019-03-15 20:38:58 +00:00
parent 55f61d95bf
commit 32c5632aa5
4 changed files with 53 additions and 30 deletions
+7 -2
View File
@@ -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):