[MOV/REF] website_slides: move quiz finish modal to its own dialog widget
This commit moves the finished quiz modal into a dedicated dialog widget. It will lessen the "slide_course_quiz.js" code length and simplify the dialog template. Task ID : 2126621 PR : #40801 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -8,6 +8,7 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
|
||||
var CourseJoinWidget = require('website_slides.course.join.widget').courseJoinWidget;
|
||||
var QuestionFormWidget = require('website_slides.quiz.question.form');
|
||||
var SlideQuizFinishModal = require('website_slides.quiz.finish');
|
||||
|
||||
var QWeb = core.qweb;
|
||||
var _t = core._t;
|
||||
@@ -243,118 +244,6 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* When the quiz is done and succeed, a congratulation modal appears.
|
||||
*/
|
||||
_renderSuccessModal: function () {
|
||||
var $modal = this.$('#slides_quiz_modal');
|
||||
if (!$modal.length) {
|
||||
this.$el.append(QWeb.render('slide.slide.quiz.finish', {'widget': this}));
|
||||
$modal = this.$('#slides_quiz_modal');
|
||||
}
|
||||
var self = this;
|
||||
$modal.on('shown.bs.modal', function () {
|
||||
var rankProgress = self.quiz.rankProgress;
|
||||
self._animateText($modal, rankProgress);
|
||||
self._animateProgressBar($modal, rankProgress);
|
||||
});
|
||||
$modal.modal({
|
||||
'show': true,
|
||||
});
|
||||
$modal.on('hidden.bs.modal', function () {
|
||||
$modal.remove();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the animation of the karma gain in the following steps:
|
||||
* 1. Initiate the tooltip which will display the actual Karma
|
||||
* over the progress bar.
|
||||
* 2. Animate the tooltip text to increment smoothly from the old
|
||||
* karma value to the new karma value and updates it to make it
|
||||
* move as the progress bar moves.
|
||||
* 3a. The user doesn't level up
|
||||
* I. When the user doesn't level up the progress bar simply goes
|
||||
* from the old karma value to the new karma value.
|
||||
* 3b. The user levels up
|
||||
* I. The first step makes the progress bar go from the old karma
|
||||
* value to 100%.
|
||||
* II. The second step makes the progress bar go from 100% to 0%.
|
||||
* III. The third and final step makes the progress bar go from 0%
|
||||
* to the new karma value. It also changes the lower and upper
|
||||
* bound to match the new rank.
|
||||
* @param $modal
|
||||
* @param rankProgress
|
||||
* @private
|
||||
*/
|
||||
_animateProgressBar: function ($modal, rankProgress) {
|
||||
var self = this;
|
||||
|
||||
this.$('[data-toggle="tooltip"]').tooltip({
|
||||
trigger: 'manual',
|
||||
container: '.progress-bar-tooltip',
|
||||
}).tooltip('show');
|
||||
|
||||
$modal.find('.tooltip-inner')
|
||||
.prop('karma', rankProgress.previous_rank.karma)
|
||||
.animate({
|
||||
karma: rankProgress.new_rank.karma
|
||||
}, {
|
||||
duration: rankProgress.level_up ? 1700 : 800,
|
||||
step: function (newKarma) {
|
||||
$modal.find('.tooltip-inner').text(Math.ceil(newKarma));
|
||||
self.$('[data-toggle="tooltip"]').tooltip('update');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var $progressBar = $modal.find('.progress-bar');
|
||||
if (rankProgress.level_up) {
|
||||
$modal.find('.o_wslides_quiz_modal_title').text(_('Level up!'));
|
||||
$progressBar.css('width', '100%');
|
||||
_.delay(function () {
|
||||
$modal.find('.o_wslides_quiz_modal_rank_lower_bound')
|
||||
.text(rankProgress.new_rank.lower_bound);
|
||||
$modal.find('.o_wslides_quiz_modal_rank_upper_bound')
|
||||
.text(rankProgress.new_rank.upper_bound || "");
|
||||
|
||||
// we need to use _.delay to force DOM re-rendering between 0 and new percentage
|
||||
_.delay(function () {
|
||||
$progressBar.addClass('no-transition').width('0%');
|
||||
}, 1);
|
||||
_.delay(function () {
|
||||
$progressBar
|
||||
.removeClass('no-transition')
|
||||
.width(rankProgress.new_rank.progress + '%');
|
||||
}, 100);
|
||||
}, 800);
|
||||
} else {
|
||||
$progressBar.css('width', rankProgress.new_rank.progress + '%');
|
||||
}
|
||||
},
|
||||
|
||||
_animateText: function ($modal, rankProgress) {
|
||||
_.delay(function () {
|
||||
$modal.find('h4.o_wslides_quiz_modal_xp_gained').addClass('show in');
|
||||
$modal.find('.o_wslides_quiz_modal_dismiss').removeClass('d-none');
|
||||
}, 800);
|
||||
|
||||
if (rankProgress.level_up) {
|
||||
_.delay(function () {
|
||||
$modal.find('.o_wslides_quiz_modal_rank_motivational').addClass('fade');
|
||||
_.delay(function () {
|
||||
$modal.find('.o_wslides_quiz_modal_rank_motivational').html(
|
||||
rankProgress.last_rank ?
|
||||
rankProgress.description :
|
||||
rankProgress.new_rank.motivational
|
||||
);
|
||||
$modal.find('.o_wslides_quiz_modal_rank_motivational').addClass('show in');
|
||||
}, 800);
|
||||
}, 800);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* @private
|
||||
* Update validation box (karma, buttons) according to widget state
|
||||
@@ -384,7 +273,11 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
} else {
|
||||
self.quiz = _.extend(self.quiz, data);
|
||||
if (data.completed) {
|
||||
self._renderSuccessModal(data);
|
||||
new SlideQuizFinishModal(self, {
|
||||
quiz: self.quiz,
|
||||
hasNext: self.slide.hasNext,
|
||||
userId: self.userId
|
||||
}).open();
|
||||
self.slide.completed = true;
|
||||
self.trigger_up('slide_completed', {slide: self.slide, completion: data.channel_completion});
|
||||
}
|
||||
@@ -454,9 +347,6 @@ odoo.define('website_slides.quiz', function (require) {
|
||||
*/
|
||||
_onClickNext: function (ev) {
|
||||
if (this.slide.hasNext) {
|
||||
if (this.$('#slides_quiz_modal').length !== 0) {
|
||||
this.$('#slides_quiz_modal').modal('hide');
|
||||
}
|
||||
this.trigger_up('slide_go_next');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
odoo.define('website_slides.quiz.finish', function (require) {
|
||||
'use strict';
|
||||
|
||||
var Dialog = require('web.Dialog');
|
||||
var core = require('web.core');
|
||||
var _t = core._t;
|
||||
|
||||
/**
|
||||
* This modal is used when the user finishes the quiz.
|
||||
* It handles the animation of karma gain and leveling up by animating
|
||||
* the progress bar and the text.
|
||||
*/
|
||||
var SlideQuizFinishModal = Dialog.extend({
|
||||
template: 'slide.slide.quiz.finish',
|
||||
events: {
|
||||
"click .o_wslides_quiz_modal_btn": '_onClickNext',
|
||||
},
|
||||
|
||||
init: function(parent, options) {
|
||||
var self = this;
|
||||
this.quiz = options.quiz;
|
||||
this.hasNext = options.hasNext;
|
||||
this.userId = options.userId;
|
||||
options = _.defaults(options || {}, {
|
||||
size: 'medium',
|
||||
dialogClass: 'd-flex p-0',
|
||||
$parentNode: parent.$el,
|
||||
technical: false,
|
||||
renderHeader: false,
|
||||
renderFooter: false
|
||||
});
|
||||
this._super.apply(this, arguments);
|
||||
this.opened(function () {
|
||||
self._animateProgressBar();
|
||||
self._animateText();
|
||||
})
|
||||
},
|
||||
|
||||
start: function() {
|
||||
var self = this;
|
||||
this._super.apply(this, arguments).then(function () {
|
||||
self.$modal.addClass('o_wslides_quiz_modal pt-5');
|
||||
self.$modal.find('.modal-dialog').addClass('mt-5');
|
||||
self.$modal.find('.modal-content').addClass('shadow-lg');
|
||||
});
|
||||
},
|
||||
|
||||
//--------------------------------
|
||||
// Handlers
|
||||
//--------------------------------
|
||||
|
||||
_onClickNext: function() {
|
||||
this.trigger_up('slide_go_next');
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
//--------------------------------
|
||||
// Private
|
||||
//--------------------------------
|
||||
|
||||
/**
|
||||
* Handles the animation of the karma gain in the following steps:
|
||||
* 1. Initiate the tooltip which will display the actual Karma
|
||||
* over the progress bar.
|
||||
* 2. Animate the tooltip text to increment smoothly from the old
|
||||
* karma value to the new karma value and updates it to make it
|
||||
* move as the progress bar moves.
|
||||
* 3a. The user doesn't level up
|
||||
* I. When the user doesn't level up the progress bar simply goes
|
||||
* from the old karma value to the new karma value.
|
||||
* 3b. The user levels up
|
||||
* I. The first step makes the progress bar go from the old karma
|
||||
* value to 100%.
|
||||
* II. The second step makes the progress bar go from 100% to 0%.
|
||||
* III. The third and final step makes the progress bar go from 0%
|
||||
* to the new karma value. It also changes the lower and upper
|
||||
* bound to match the new rank.
|
||||
* @param $modal
|
||||
* @param rankProgress
|
||||
* @private
|
||||
*/
|
||||
_animateProgressBar: function () {
|
||||
var self = this;
|
||||
this.$('[data-toggle="tooltip"]').tooltip({
|
||||
trigger: 'manual',
|
||||
container: '.progress-bar-tooltip',
|
||||
}).tooltip('show');
|
||||
|
||||
this.$('.tooltip-inner')
|
||||
.prop('karma', this.quiz.rankProgress.previous_rank.karma)
|
||||
.animate({
|
||||
karma: this.quiz.rankProgress.new_rank.karma
|
||||
}, {
|
||||
duration: this.quiz.rankProgress.level_up ? 1700 : 800,
|
||||
step: function (newKarma) {
|
||||
self.$('.tooltip-inner').text(Math.ceil(newKarma));
|
||||
self.$('[data-toggle="tooltip"]').tooltip('update');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
var $progressBar = this.$('.progress-bar');
|
||||
if (this.quiz.rankProgress.level_up) {
|
||||
this.$('.o_wslides_quiz_modal_title').text(_t('Level up!'));
|
||||
$progressBar.css('width', '100%');
|
||||
_.delay(function () {
|
||||
self.$('.o_wslides_quiz_modal_rank_lower_bound')
|
||||
.text(self.quiz.rankProgress.new_rank.lower_bound);
|
||||
self.$('.o_wslides_quiz_modal_rank_upper_bound')
|
||||
.text(self.quiz.rankProgress.new_rank.upper_bound || "");
|
||||
|
||||
// we need to use _.delay to force DOM re-rendering between 0 and new percentage
|
||||
_.delay(function () {
|
||||
$progressBar.addClass('no-transition').width('0%');
|
||||
}, 1);
|
||||
_.delay(function () {
|
||||
$progressBar
|
||||
.removeClass('no-transition')
|
||||
.width(self.quiz.rankProgress.new_rank.progress + '%');
|
||||
}, 100);
|
||||
}, 800);
|
||||
} else {
|
||||
$progressBar.css('width', this.quiz.rankProgress.new_rank.progress + '%');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the animation of the different text such as the karma gain
|
||||
* and the motivational message when the user levels up.
|
||||
* @private
|
||||
*/
|
||||
_animateText: function () {
|
||||
var self = this;
|
||||
_.delay(function () {
|
||||
self.$('h4.o_wslides_quiz_modal_xp_gained').addClass('show in');
|
||||
self.$('.o_wslides_quiz_modal_dismiss').removeClass('d-none');
|
||||
}, 800);
|
||||
|
||||
if (this.quiz.rankProgress.level_up) {
|
||||
_.delay(function () {
|
||||
self.$('.o_wslides_quiz_modal_rank_motivational').addClass('fade');
|
||||
_.delay(function () {
|
||||
self.$('.o_wslides_quiz_modal_rank_motivational').html(
|
||||
self.quiz.rankProgress.last_rank ?
|
||||
self.quiz.rankProgress.description :
|
||||
self.quiz.rankProgress.new_rank.motivational
|
||||
);
|
||||
self.$('.o_wslides_quiz_modal_rank_motivational').addClass('show in');
|
||||
}, 800);
|
||||
}, 800);
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
return SlideQuizFinishModal;
|
||||
|
||||
});
|
||||
@@ -449,6 +449,14 @@ $o-wslides-fs-side-width: 300px;
|
||||
@include media-breakpoint-up (sm) {
|
||||
.modal-body {
|
||||
overflow: visible!important;
|
||||
|
||||
.o_wslides_quiz_modal_close_btn {
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.o_wslides_gradient {
|
||||
width: 42%;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
|
||||
@@ -84,52 +84,45 @@
|
||||
</t>
|
||||
|
||||
<t t-name="slide.slide.quiz.finish">
|
||||
<div class="modal o_wslides_quiz_modal pt-5" tabindex="-1" role="dialog" id="slides_quiz_modal">
|
||||
<div class="modal-backdrop show bg-white" style="z-index:0"/>
|
||||
<div class="modal-dialog mt-5" role="document">
|
||||
<div class="modal-content shadow-lg">
|
||||
<div class="modal-body d-flex p-0">
|
||||
<button type="button" class="close position-absolute" data-dismiss="modal" aria-label="Close" style="right: 5px">×</button>
|
||||
<div class="o_wslides_gradient rounded-left d-none d-md-flex flex-shrink-0" style="width: 42%">
|
||||
<img class="o_wslides_quiz_modal_hero" src="/website_slides/static/src/img/quiz_modal_success.svg" alt=""/>
|
||||
</div>
|
||||
<div class="d-flex flex-column flex-grow-1 justify-content-between pl-md-5 p-3 overflow-auto">
|
||||
<div>
|
||||
<h1 class="o_wslides_quiz_modal_title mt-3 display-4 font-weight-bold">Amazing!</h1>
|
||||
<div class="pb-3">
|
||||
<h4 class="o_wslides_quiz_modal_xp_gained pb-2 d-flex fade">You gained <span class="badge badge-pill badge-success text-white font-weight-bold ml-2 mr-1"><t t-esc="widget.quiz.quizKarmaWon"/> XP</span> !</h4>
|
||||
<div class="mt-5 mb-4">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" t-att-aria-valuenow="widget.quiz.rankProgress.previous_rank.progress" aria-valuemin="0" aria-valuemax="100"
|
||||
t-attf-style="width: #{widget.quiz.rankProgress.previous_rank.progress}%"/>
|
||||
<div class="progress-bar-tooltip" data-toggle="tooltip" data-placement="top" t-att-title="widget.quiz.rankProgress.new_rank.karma" />
|
||||
</div>
|
||||
<small class="float-left text-primary font-weight-bold o_wslides_quiz_modal_rank_lower_bound">
|
||||
<t t-esc="widget.quiz.rankProgress.previous_rank.lower_bound"/>
|
||||
</small>
|
||||
<small t-if="widget.quiz.rankProgress.previous_rank.upper_bound" class="float-right font-weight-bold o_wslides_quiz_modal_rank_upper_bound">
|
||||
<t t-esc="widget.quiz.rankProgress.previous_rank.upper_bound"/>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pb-3 o_wslides_quiz_modal_rank_motivational">
|
||||
<t t-set="showLastRankDescription" t-value="widget.quiz.rankProgress.last_rank && !widget.quiz.rankProgress.level_up" />
|
||||
<t t-raw="showLastRankDescription ? widget.quiz.rankProgress.description : widget.quiz.rankProgress.previous_rank.motivational" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_wslides_quiz_modal_dismiss align-self-end d-none">
|
||||
<t t-if="widget.quiz.rankProgress.level_up">
|
||||
<a type="button" target="_blank" t-attf-href="/profile/user/#{widget.userId}" class="btn btn-light border">Check Profile</a>
|
||||
</t>
|
||||
<t t-if="widget.slide.hasNext">
|
||||
<button type="button" class="btn btn-light border o_wslides_quiz_modal_btn">Next <i class="fa fa-chevron-right"/></button>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<a type="button" href="/slides" class="btn btn-light border">End course</a>
|
||||
</t>
|
||||
<div>
|
||||
<button type="button" class="o_wslides_quiz_modal_close_btn close position-absolute" data-dismiss="modal" aria-label="Close">×</button>
|
||||
<div class="o_wslides_gradient d-none d-md-flex flex-shrink-0">
|
||||
<img class="o_wslides_quiz_modal_hero" src="/website_slides/static/src/img/quiz_modal_success.svg" alt=""/>
|
||||
</div>
|
||||
<div class="d-flex flex-column flex-grow-1 justify-content-between pl-md-5 p-3 overflow-auto">
|
||||
<div>
|
||||
<h1 class="o_wslides_quiz_modal_title mt-3 display-4 font-weight-bold">Amazing!</h1>
|
||||
<div class="pb-3">
|
||||
<h4 class="o_wslides_quiz_modal_xp_gained pb-2 d-flex fade">You gained <span class="badge badge-pill badge-success text-white font-weight-bold ml-2 mr-1"><t t-esc="widget.quiz.quizKarmaWon"/> XP</span> !</h4>
|
||||
<div class="mt-5 mb-4">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" t-att-aria-valuenow="widget.quiz.rankProgress.previous_rank.progress" aria-valuemin="0" aria-valuemax="100"
|
||||
t-attf-style="width: #{widget.quiz.rankProgress.previous_rank.progress}%"/>
|
||||
<div class="progress-bar-tooltip" data-toggle="tooltip" data-placement="top" t-att-title="widget.quiz.rankProgress.new_rank.karma" />
|
||||
</div>
|
||||
<small class="float-left text-primary font-weight-bold o_wslides_quiz_modal_rank_lower_bound">
|
||||
<t t-esc="widget.quiz.rankProgress.previous_rank.lower_bound"/>
|
||||
</small>
|
||||
<small t-if="widget.quiz.rankProgress.previous_rank.upper_bound" class="float-right font-weight-bold o_wslides_quiz_modal_rank_upper_bound">
|
||||
<t t-esc="widget.quiz.rankProgress.previous_rank.upper_bound"/>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pb-3 o_wslides_quiz_modal_rank_motivational">
|
||||
<t t-set="showLastRankDescription" t-value="widget.quiz.rankProgress.last_rank && !widget.quiz.rankProgress.level_up" />
|
||||
<t t-raw="showLastRankDescription ? widget.quiz.rankProgress.description : widget.quiz.rankProgress.previous_rank.motivational" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="o_wslides_quiz_modal_dismiss align-self-end d-none">
|
||||
<t t-if="widget.quiz.rankProgress.level_up">
|
||||
<a type="button" target="_blank" t-attf-href="/profile/user/#{widget.userId}" class="btn btn-light border">Check Profile</a>
|
||||
</t>
|
||||
<t t-if="widget.hasNext">
|
||||
<button type="button" class="btn btn-light border o_wslides_quiz_modal_btn">Next <i class="fa fa-chevron-right"/></button>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<a type="button" href="/slides" class="btn btn-light border">End course</a>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_course_join.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_course_quiz.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_course_quiz_question_form.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_course_quiz_finish.js"/>
|
||||
<script type="text/javascript" src="/website_slides/static/src/js/slides_course_unsubscribe.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user