[MERGE][FIX] website_slides: clean course and lesson pages layout and fix various small UX issues

Purpose of this merge is to at last perform a cleaning of layout and design for
eLearning pages still not completely updated with magic layout touch.

Impacted pages
 * course (channel) main page: better top and banner, better navigation.
   Improve training content list display, clean documentation content list
   display and navigation;
 * lesson (slide) main not-fullscreen page;
 * lesson (slide) fullscreen page / widget;
 * homepage: clean navigation;

This merge also contains various fixes and UX improvements for fullscreen
lesson display as well as user profile page. Thanks to @stefanorigano and
@qmo-odoo for their input.

This merge closes tasks 1941250 about fixes and layouting of new eLearning
application. Thanks for your attention.

closes odoo/odoo#31977

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Robot Odoo
2019-03-21 14:29:56 +01:00
committed by GitHub
28 changed files with 1237 additions and 1074 deletions
@@ -1,5 +1,5 @@
$owprofile-color-bg: desaturate(map-get($grays, "200"), 80%);
$owprofile-tabs-height: 37px;
$owprofile-tabs-height: 36px;
.o_wprofile_wrap {
background-color: $owprofile-color-bg;
@@ -119,52 +119,24 @@ $owprofile-tabs-height: 37px;
// All Users Page
.o_wprofile_all_users_nav {
margin: auto;
background: linear-gradient(90deg, #875A7B 20%, #62495B 80%) !important;
a {
color: #FFFFFF;
}
nav {
.breadcrumb-item::before {
font-weight: bold;
color: #FFFFFF;
opacity: 0.8;
}
.breadcrumb-item {
a {
font-weight: bold;
color: #FFFFFF;
opacity: 0.8;
transition: opacity linear .3s;
}
&.active {
a {
opacity: 1.0;
}
}
}
ol {
background-color: transparent;
}
}
}
border-width: 1px 0;
.o_wprofile_all_users_header {
@include media-breakpoint-up(sm) {
min-height: 200px;
margin-bottom: -60px;
&, .o_wprofile_course_nav_search {
background-color: rgba(white, 0.05);
border-color: rgba(white, 0.1);
border-style: solid;
}
margin: auto;
background: linear-gradient(90deg, #875A7B 20%, #62495B 80%) !important;
> div:first-child {
margin: auto;
width: 100%;
max-width: 1140px;
padding: 32px 32px 0px 32px;
.o_wprofile_course_nav_search {
border-width: 0 1px;
}
.breadcrumb-item.active a, .breadcrumb-item a:hover {
color: white;
top: 48px;
padding-top: 0px;
height: 250px;
}
.breadcrumb-item a, .breadcrumb-item + .breadcrumb-item::before, .o_wprofile_course_nav_search input::placeholder {
color: rgba(white, 0.8);
}
}
@@ -9,6 +9,74 @@
</xpath>
</template>
<!-- Sub nav -->
<template id="user_profile_sub_nav" name="User profile subnav">
<div class="o_wprofile_all_users_nav">
<div class="container">
<div class="row align-items-center justify-content-between">
<!-- Desktop Mode -->
<nav aria-label="breadcrumb" class="col d-none d-md-flex">
<ol class="breadcrumb bg-transparent mb-0 pl-0 py-0">
<li class="breadcrumb-item">
<a t-att-href="home_url or '/'">Home</a>
</li>
<li t-attf-class="breadcrumb-item #{'active' if not view_user else ''}">
<a href="/profile/users">Users</a>
</li>
<li t-if="view_user" class="breadcrumb-item active">
<a><t t-esc="view_user"/></a>
</li>
</ol>
</nav>
<div class="col d-none d-md-flex flex-row align-items-center justify-content-end">
<!-- search -->
<form t-attf-action="/profile/users" role="search" method="get">
<div class="input-group o_wprofile_course_nav_search ml-1 position-relative">
<span class="input-group-prepend">
<button class="btn btn-link text-white rounded-0 pr-1" type="submit" aria-label="Search" title="Search">
<i class="fa fa-search"></i>
</button>
</span>
<input type="text" class="form-control border-0 rounded-0 bg-transparent text-white" name="search" placeholder="Search users"/>
</div>
</form>
</div>
<!-- Mobile Mode -->
<div class="col d-md-none py-1">
<div class="btn-group w-100 position-relative" role="group" aria-label="Mobile sub-nav">
<div class="btn-group w-100 ml-2">
<a class="btn bg-black-25 text-white dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Nav</a>
<ul class="dropdown-menu">
<a class="dropdown-item" t-att-href="home_url or '/'">Home</a>
<a class="dropdown-item" href="/profile/users">&#9492; Users</a>
<a t-if="view_user" class="dropdown-item">&#9492; <t t-esc="view_user"/></a>
</ul>
</div>
<div class="btn-group ml-1 position-static mr-2">
<a class="btn bg-black-25 text-white dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-right w-100" style="right: 10px;">
<form class="px-3" t-attf-action="/profile/users" role="search" method="get">
<div class="input-group">
<input type="text" class="form-control" name="search" placeholder="Search courses"/>
<span class="input-group-append">
<button class="btn btn-primary" type="submit" aria-label="Search" title="Search">
<i class="fa fa-search"/>
</button>
</span>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<!--
Single User Profile Page
@@ -126,8 +194,12 @@
</template>
<template id="user_profile_header" name="Profile Page Header">
<div class="o_wprofile_header o_wprofile_gradient position-relative text-white pb-3 pb-md-0 pt-2 pt-md-5">
<div class="container">
<div class="o_wprofile_header o_wprofile_gradient position-relative text-white">
<t t-call="website_profile.user_profile_sub_nav">
<t t-set="view_user"><t t-esc="user.name"/></t>
</t>
<div class="container pb-3 pb-md-0 pt-2 pt-md-5">
<div class="row">
<!-- ==== Header Left ==== -->
<div class="col-12 col-md-4 col-lg-3">
@@ -169,13 +241,13 @@
</template>
<template id="user_profile_content" name="Profile Page Content">
<div class="o_wprofile_content container">
<div class="container">
<div class="row">
<!-- ========== SIDEBAR ========== -->
<div class="col-12 col-md-4 col-lg-3 mt-3 mt-md-0">
<div class="bg-white px-3 py-2 py-md-3 mb-3 mb-md-5">
<div class="o_wprofile_sidebar_top d-flex justify-content-between">
<div class="d-flex justify-content-between">
<div t-if="user.rank_id" class="d-flex align-items-center">
<small class="font-weight-bold mr-2">Rank:</small>
<img t-attf-src="/web/image/gamification.karma.rank/#{user.rank_id.id}/image_small" height="16" alt="" class="mr-1"/>
@@ -383,43 +455,10 @@
</template>
<template id="users_page_header" name="Users Page Header">
<div class="o_wprofile_all_users_nav">
<div class="o_wprofile_all_users_header o_wprofile_gradient mb-n5 pb-5">
<t t-call="website_profile.user_profile_sub_nav"/>
<div class="container">
<div class="row align-items-center justify-content-between">
<!-- nav -->
<nav aria-label="breadcrumb" class="col-md-8 col-xs-12">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a t-att-href="home_url or '/'">Home</a>
</li>
<li t-att-class="'breadcrumb-item active'">
<a href="#">Users</a>
</li>
</ol>
</nav>
<div class="col-md-4 col-xs-12 d-flex flex-row align-items-center">
<!-- karma / profile -->
<a t-if="not is_public_user" t-att-href="'/profile/user/%s' % user_id.id" class="font-weight-bold mr-3">
<i class="fa fa-diamond" /> <t t-esc="user_id.karma"/>
</a>
<!-- search -->
<form t-attf-action="/profile/users" role="search" method="get">
<div class="input-group">
<input type="text" class="form-control" name="search" placeholder="Search in Users" t-att-value="search"/>
<span class="input-group-append">
<button class="btn btn-primary" type="submit" aria-label="Search" title="Search">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="o_wprofile_all_users_header o_wprofile_gradient text-white">
<div class="container">
<h1 class="py-5">All Users</h1>
<h1 class="py-4 text-white">All Users</h1>
</div>
</div>
</template>
@@ -500,24 +539,20 @@
</template>
<template id="email_validation_banner">
<div t-if="not validation_email_sent and not is_public_user and user.karma == 0" class="alert alert-danger alert-dismissable" role="alert">
<t t-set="send_alert_classes" t-value="send_alert_classes if send_alert_classes else 'alert alert-danger alert-dismissable'"/>
<t t-set="done_alert_classes" t-value="done_alert_classes if done_alert_classes else 'alert alert-success alert-dismissable'"/>
<div t-if="not validation_email_sent and not is_public_user and user.karma == 0" t-att-class="send_alert_classes" role="alert">
<button type="button" class="close validation_email_close" data-dismiss="alert" aria-label="Close">&amp;times;</button>
<div>
<p>
It appears your email has not been verified.
<a class="send_validation_email" href="#" t-att-data-redirect_url="redirect_url">
<span t-esc="send_validation_email_message"/></a>
</p>
</div>
It appears your email has not been verified.<br/>
<a class="send_validation_email alert-link" href="#" t-att-data-redirect_url="redirect_url">
<span t-esc="send_validation_email_message"/>
</a>
</div>
<div t-if="validation_email_done" class="alert alert-success alert-dismissable" role="status">
<div t-if="validation_email_done" t-att-class="done_alert_classes" role="status">
<button type="button" class="close validated_email_close" data-dismiss="alert" aria-label="Close">&amp;times;</button>
<div>
<p>
<span id="email_validated_message">Congratulations! Your email has just been validated.</span>
<span t-esc="additional_validated_email_message"/>
</p>
</div>
<span id="email_validated_message">Congratulations! Your email has just been validated.</span>
<span t-esc="additional_validated_email_message"/>
</div>
</template>
@@ -44,17 +44,17 @@
It can alse be used to modify a message
-->
<t t-name="website_rating.PopupComposer">
<div class="row align-items-center">
<div class="col">
<div class="d-flex flex-wrap align-items-center">
<div class="text-nowrap">
<t t-call="website_rating.rating_stars_static">
<t t-set="val" t-value="widget.rating_avg || 0"/>
<t t-set="inline_mode" t-value="true"/>
</t>
<t t-if="widget.rating_total">
<small class="font-weight-bold">(<t t-esc="widget.rating_total"/> ratings)</small>
<small>(<t t-esc="widget.rating_total"/> ratings)</small>
</t>
</div>
<button t-if="widget.options['display_composer']" type="button" class="btn btn-primary col" data-toggle="modal" data-target="#ratingpopupcomposer">
<button t-if="widget.options['display_composer']" type="button" class="btn btn-sm btn-primary mx-3" data-toggle="modal" data-target="#ratingpopupcomposer">
<t t-if="widget.options['display_composer']">
<t t-if="widget.options['default_message_id']">
Modify your review
@@ -13,7 +13,7 @@
<i class="fa fa-star-half-o" role="img" aria-label="Half a star" title="Half a star"></i>
</t>
<t t-foreach="_.range(0, empty_star)" t-as="num" role="img" t-attf-aria-label="#{empty_star} on 5" t-attf-title="#{empty_star} on 5">
<i class="fa fa-star-o"></i>
<i class="fa fa-star text-black-25"></i>
</t>
</div>
</t>
@@ -73,7 +73,7 @@
<i class="fa fa-star-half-o" role="img" aria-label="Half a star" title="Half a star"></i>
</t>
<t t-foreach="_.range(0, empty_star)" t-as="num" role="img" t-attf-aria-label="#{empty_star} on 5" t-attf-title="#{empty_star} on 5">
<i class="fa fa-star-o"></i>
<i class="fa fa-star-o text-black-25"></i>
</t>
</div>
<div class="rate_text">
@@ -30,7 +30,7 @@
<i class="fa fa-star-half-o" role="img"></i>
</t>
<t t-foreach="range(0, empty_star)" t-as="num" role="img">
<i class="fa fa-star-o"></i>
<i class="fa fa-star text-black-25"></i>
</t>
<t t-if="rating_count">
(<t t-esc="rating_count"/>)
+5 -4
View File
@@ -63,12 +63,12 @@ class WebsiteSlides(WebsiteProfile):
slide.action_set_viewed(quiz_attempts_inc=quiz_attempts_inc)
return True
def _set_completed_slide(self, slide, quiz_attempts_inc=False):
def _set_completed_slide(self, slide):
# 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)
slide.action_set_completed()
return True
def _get_slide_detail(self, slide):
@@ -624,6 +624,7 @@ class WebsiteSlides(WebsiteProfile):
return fetch_res
slide = fetch_res['slide']
quiz_info = self._get_slide_quiz_info(slide)
slide_completed = slide.user_membership_id.sudo().completed
return {
'questions': [{
'id': question.id,
@@ -631,7 +632,7 @@ class WebsiteSlides(WebsiteProfile):
'answers': [{
'id': answer.id,
'text_value': answer.text_value,
'is_correct': answer.is_correct,
'is_correct': answer.is_correct if slide_completed else None
} for answer in question.answer_ids],
} for question in slide.question_ids],
'quizAttemptsCount': quiz_info['quiz_attempts_count'],
@@ -666,7 +667,7 @@ class WebsiteSlides(WebsiteProfile):
rank_progress = {}
if not user_bad_answers:
slide._action_set_quiz_done()
slide.action_set_completed(quiz_attempts_inc=True)
slide.action_set_completed()
lower_bound = request.env.user.rank_id.karma_min
upper_bound = request.env.user.next_rank_id.karma_min
rank_progress = {
+4 -12
View File
@@ -451,34 +451,26 @@ class Slide(models.Model):
'quiz_attempts_count': 1 if quiz_attempts_inc else 0,
'vote': 0} for new_slide in new_slides])
def action_set_completed(self, quiz_attempts_inc=False):
def action_set_completed(self):
if not all(slide.channel_id.is_member for slide in self):
raise UserError(_('You cannot mark a slide as completed if you are not among its members.'))
return self._action_set_completed(self.env.user.partner_id, quiz_attempts_inc=quiz_attempts_inc)
return self._action_set_completed(self.env.user.partner_id)
def _action_set_completed(self, target_partner, quiz_attempts_inc=False):
def _action_set_completed(self, target_partner):
self_sudo = self.sudo()
SlidePartnerSudo = self.env['slide.slide.partner'].sudo()
existing_sudo = SlidePartnerSudo.search([
('slide_id', 'in', self.ids),
('partner_id', '=', target_partner.id)
])
if quiz_attempts_inc:
for existing_slide in existing_sudo:
existing_slide.write({
'completed': True,
'quiz_attempts_count': existing_slide.quiz_attempts_count + 1
})
else:
existing_sudo.write({'completed': True})
existing_sudo.write({'completed': True})
new_slides = self_sudo - existing_sudo.mapped('slide_id')
SlidePartnerSudo.create([{
'slide_id': new_slide.id,
'channel_id': new_slide.channel_id.id,
'partner_id': target_partner.id,
'quiz_attempts_count': 1 if quiz_attempts_inc else 0,
'vote': 0,
'completed': True} for new_slide in new_slides])
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.3 KiB

@@ -181,7 +181,7 @@ odoo.define('website_slides.fullscreen', function (require) {
*/
setSlideCompleted: function (slideId) {
var $elem = this.$('.fa-circle-thin[data-slide-id="'+slideId+'"]');
$elem.removeClass('fa-circle-thin').addClass('fa-check-circle text-success bg-white o_wslides_slide_completed rounded-circle');
$elem.removeClass('fa-circle-thin').addClass('fa-check text-success o_wslides_slide_completed');
},
/**
* Updates the progressbar whenever a lesson is completed
@@ -236,7 +236,6 @@ odoo.define('website_slides.fullscreen', function (require) {
*/
_onClickTab: function (ev) {
ev.stopPropagation();
ev.preventDefault();
var $elem = $(ev.currentTarget);
var isQuiz = $elem.data('isQuiz');
var slideID = parseInt($elem.data('id'));
@@ -412,8 +411,10 @@ odoo.define('website_slides.fullscreen', function (require) {
_pushUrlState: function (){
var urlParts = window.location.pathname.split('/');
urlParts[urlParts.length-1] = this.get('slide').slug;
var url = _.str.sprintf('%s?fullscreen=1', urlParts.join('/'));
history.pushState(null, '', url);
var url = urlParts.join('/');
this.$('.o_wslides_fs_exit_fullscreen').attr('href', url);
var fullscreenUrl = _.str.sprintf('%s?fullscreen=1', url);
history.pushState(null, '', fullscreenUrl);
},
/**
* Render the current slide content using specific mecanism according to slide type:
@@ -484,8 +485,7 @@ odoo.define('website_slides.fullscreen', function (require) {
_onChangeSlide: function () {
var self = this;
var slide = this.get('slide');
return this._fetchSlideContent().then(function() { // update title and render content
self.$('.o_wslides_fs_slide_title').html(QWeb.render('website.slides.fullscreen.title', {widget: self}));
return this._fetchSlideContent().then(function() { // render content
return self._renderSlide();
}).then(function() {
if (slide._autoSetDone && !session.is_website_user) { // no useless RPC call
@@ -117,7 +117,7 @@ odoo.define('website_slides.quiz', function (require) {
_renderAnswers: function () {
var self = this;
this.$('input[type=radio]').each(function () {
$(this).prop('disabled', self.slide.readonly);
$(this).prop('disabled', self.slide.readonly || self.slide.completed);
});
},
@@ -127,24 +127,26 @@ odoo.define('website_slides.quiz', function (require) {
*/
_renderAnswersHighlighting: function () {
var self = this;
this.$('li.o_wslides_quiz_answer').each(function () {
this.$('a.o_wslides_quiz_answer').each(function () {
var $answer = $(this);
var answerId = $answer.data('answerId');
if (_.contains(self.quiz.goodAnswers, answerId)) {
$answer.removeClass('border-danger').addClass('border border-success');
$answer.removeClass('list-group-item-danger').addClass('list-group-item-success');
$answer.find('i.fa').addClass('d-none');
$answer.find('i.fa-check-circle').removeClass('d-none');
}
else if (_.contains(self.quiz.badAnswers, answerId)) {
$answer.removeClass('border-success').addClass('border border-danger');
$answer.removeClass('list-group-item-success').addClass('list-group-item-danger');
$answer.find('i.fa').addClass('d-none');
$answer.find('i.fa-times-circle').removeClass('d-none');
$answer.find('label input').prop('checked', false);
}
else {
$answer.removeClass('border border-danger border-success');
$answer.find('i.fa').addClass('d-none');
$answer.find('i.fa-circle').removeClass('d-none');
if (!self.slide.completed) {
$answer.removeClass('list-group-item-danger list-group-item-success');
$answer.find('i.fa').addClass('d-none');
$answer.find('i.fa-circle').removeClass('d-none');
}
}
});
},
@@ -195,12 +197,13 @@ odoo.define('website_slides.quiz', function (require) {
self._alertShow(data.error);
} else {
self.quiz = _.extend(self.quiz, data);
self._renderAnswersHighlighting();
self._renderValidationInfo();
if (data.completed) {
self._renderSuccessModal(data);
self.slide.completed = true;
self.trigger_up('slide_completed', {slide: self.slide, completion: data.channel_completion});
}
self._renderAnswersHighlighting();
self._renderValidationInfo();
}
});
},
@@ -216,7 +219,7 @@ odoo.define('website_slides.quiz', function (require) {
* @param OdooEvent ev
*/
_onAnswerClick: function (ev) {
if (! this.slide.readonly) {
if (! this.slide.readonly && ! this.slide.completed) {
$(ev.currentTarget).find('input[type=radio]').prop('checked', true);
}
this._alertHide();
@@ -295,7 +298,7 @@ odoo.define('website_slides.quiz', function (require) {
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');
this.$('#o_wslides_lesson_aside_slide_check_' + slide.id).addClass('text-success fa-check').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));
@@ -29,16 +29,18 @@ sAnimations.registry.websiteSlidesCourseSlidesList = sAnimations.Class.extend({
*/
_bindSortable: function () {
this.$('ul.o_wslides_js_slides_list_container').sortable({
handle: '.fa-arrows',
handle: '.o_wslides_slides_list_drag',
stop: this._reorderCategories.bind(this),
items: '.o_wslides_slide_list_category'
items: '.o_wslides_slide_list_category',
placeholder: 'o_wslides_slides_list_slide_hilight position-relative mb-1'
});
this.$('.o_wslides_js_slides_list_container ul').sortable({
handle: '.fa-arrows',
handle: '.o_wslides_slides_list_drag',
connectWith: '.o_wslides_js_slides_list_container ul',
stop: this._reorderSlides.bind(this),
items: '.o_wslides_slides_list_slide:not(.o_wslides_js_slides_list_empty)'
items: '.o_wslides_slides_list_slide:not(.o_wslides_js_slides_list_empty)',
placeholder: 'o_wslides_slides_list_slide_hilight position-relative mb-1'
});
},
@@ -32,7 +32,6 @@ $(document).ready(function () {
this.$('canvas').show();
this.$('#page_count').text(this.pdf_viewer.pdf_page_total);
this.$('#PDFViewerLoader').hide();
this.$('#PDFViewerLoader').toggleClass('d-flex');
if (this.pdf_viewer.pdf_page_total > 1) {
this.$('.o_slide_navigation_buttons').removeClass('hide');
}
@@ -44,16 +43,19 @@ $(document).ready(function () {
on_rendered_page: function (pageNumber) {
if (pageNumber) {
this.$('#page_number').val(pageNumber);
this.navUpdate(pageNumber);
}
},
// page switching
render_page: function (pageNumber) {
this.pdf_viewer.renderPage(pageNumber).then(this.on_rendered_page.bind(this));
this.navUpdate(pageNumber);
},
change_page: function () {
var pageAsked = parseInt(this.$('#page_number').val(), 10);
if (1 <= pageAsked && pageAsked <= this.pdf_viewer.pdf_page_total) {
this.pdf_viewer.changePage(pageAsked).then(this.on_rendered_page.bind(this));
this.navUpdate(pageAsked);
} else {
// if page number out of range, reset the page_counter to the actual page
this.$('#page_number').val(this.pdf_viewer.pdf_page_current);
@@ -77,23 +79,28 @@ $(document).ready(function () {
if (pageNum) {
self.on_rendered_page(pageNum);
}
self.$("#slide_suggest").hide();
self.$("#slide_suggest").addClass('d-none');
});
},
first: function () {
var self = this;
this.pdf_viewer.firstPage().then(function (pageNum) {
self.on_rendered_page(pageNum);
self.$("#slide_suggest").hide();
self.$("#slide_suggest").addClass('d-none');
});
},
last: function () {
var self = this;
this.pdf_viewer.lastPage().then(function (pageNum) {
self.on_rendered_page(pageNum);
self.$("#slide_suggest").hide();
self.$("#slide_suggest").addClass('d-none');
});
},
navUpdate: function (pageNum) {
this.$('#first').toggleClass('disabled', pageNum < 3 );
this.$('#previous').toggleClass('disabled', pageNum < 2 );
this.$('#next, #last').removeClass('disabled');
},
// full screen mode
fullscreen: function () {
this.pdf_viewer.toggleFullScreen();
@@ -105,7 +112,8 @@ $(document).ready(function () {
},
// display suggestion displayed after last slide
display_suggested_slides: function () {
this.$("#slide_suggest").show();
this.$("#slide_suggest").removeClass('d-none');
this.$('#next, #last').addClass('disabled');
},
};
@@ -60,7 +60,6 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({
linkedin: 'https://www.linkedin.com/countserv/count/share?url=',
twitter: 'https://cdn.api.twitter.com/1/urls/count.json?url=',
facebook: 'https://graph.facebook.com/?id=',
gplus: 'https://clients6.google.com/rpc',
};
}
@@ -82,42 +81,15 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({
*/
_updateStatistics: function (socialSite, slideURL) {
var self = this;
if (socialSite === 'gplus') {
$.ajax({
url: self.socialURLs['gplus'],
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify([{
method: 'pos.plusones.get',
id: 'p',
params: {
nolog: true,
id: slideURL,
source: 'widget',
userId: '@viewer',
groupId: '@self'
},
// TDE NOTE: should there be a key here ?
jsonrpc: '2.0',
apiVersion: 'v1'
}]),
success: function (data) {
$('#google-badge').text(data[0].result.metadata.globalCounts.count || 0);
$('#total-share').text(parseInt($('#total-share').text()) + parseInt($('#google-badge').text()));
},
});
} else {
$.ajax({
url: self.socialURLs[socialSite] + slideURL,
dataType: 'jsonp',
success: function (data) {
var shareCount = (socialSite === 'facebook' ? data.shares : data.count) || 0;
$('#' + socialSite + '-badge').text(shareCount);
$('#total-share').text(parseInt($('#total-share').text()) + parseInt($('#' + socialSite + '-badge').text()));
},
});
}
$.ajax({
url: self.socialURLs[socialSite] + slideURL,
dataType: 'jsonp',
success: function (data) {
var shareCount = (socialSite === 'facebook' ? data.shares : data.count) || 0;
$('#' + socialSite + '-badge').text(shareCount);
$('#total-share').text(parseInt($('#total-share').text()) + parseInt($('#' + socialSite + '-badge').text()));
},
});
},
//--------------------------------------------------------------------------
@@ -4,10 +4,10 @@ $o-wslides-tabs-height: 36px;
.o_wslides_fs_main {
@include o-position-absolute(0,0,0,0);
z-index: 2000;
background-image: linear-gradient(120deg, $o-wslides-color-dark2, $o-wslides-color-dark3);
.o_wslides_slide_fs_header {
background-image: linear-gradient(120deg, $o-wslides-color-dark1, $o-wslides-color-dark2);
padding-bottom: 3px;
background-image: linear-gradient(-6deg, $o-wslides-color-dark1, $o-wslides-color-dark2);
height: 50px;
> div > a {
@@ -24,29 +24,22 @@ $o-wslides-tabs-height: 36px;
}
&.active{
background-color: transparent;
background-color: $o-wslides-color-dark1;
color: #fff;
}
}
}
.o_wslides_fs_container {
background-color: $o-wslides-color-dark2;
}
.o_wslides_fs_content {
.o_wslides_fs_player, .o_wslides_fs_sidebar, .o_wslides_fs_sidebar_content {
transition: all .2s ease-in;
}
.o_wslides_fs_sidebar {
transition: all .2s ease-in;
background-image: linear-gradient(160deg, $o-wslides-color-dark1, $o-wslides-color-dark2);
box-shadow: 5px 0 15px rgba(black, 0.2);
position: relative;
.o_wslides_fs_sidebar_content {
min-width: $o-wslides-fs-side-width;
transition: all .2s ease-in;
}
.o_wslides_fs_toggle_sidebar {
@@ -57,6 +50,7 @@ $o-wslides-tabs-height: 36px;
@include media-breakpoint-down (md) {
@include o-position-absolute(0, auto, 0, 0);
box-shadow: 5px 0 15px rgba(black, 0.2);
&.o_wslides_fs_sidebar_hidden {
display: none;
@@ -82,6 +76,7 @@ $o-wslides-tabs-height: 36px;
.o_wslides_fs_sidebar_section {
background-color: rgba($o-wslides-color-dark3, 0.3);
margin-bottom: 1px;
}
.o_wslides_fs_sidebar_section_slides li {
@@ -97,48 +92,9 @@ $o-wslides-tabs-height: 36px;
}
}
i.o_wslides_slide_completed{
@include size(13px);
box-shadow: inset 0 0 0 1px theme-color('success');
}
.o_wslides_fs_slide_name {
line-height: 1;
}
}
}
// quizz
.o_wslides_fs_quiz_container {
background-color: $gray-200;
height: 100%;
overflow: scroll;
overflow-x: hidden;
width: 100%;
.o_wslides_js_lesson_quiz_question {
li {
font-size: 1.2rem;
}
.o_wslides_quiz_answer {
&:hover {
cursor: pointer;
}
label {
font-size: 1.4rem;
i.fa-circle {
}
input:checked + i.fa-circle {
color: $primary !important;
overflow: hidden;
}
}
}
}
}
}
@@ -1,10 +1,5 @@
// FIXME may be useless (check initial code here: https://github.com/odoo/odoo/blob/51be5bbfb38db784cb3406877cc0e8806b1bf55a/addons/website_slides/static/src/less/website_slides.less#L1)
$nav-tabs-border-color: #dddddd !default;
$body-bg: #FFFFFF !default;
$MAX-Z-INDEX : 2147483647 !default;
$gray-50: #f4f4f4 !default;
$o-enterprise-radient-color: #62495B !default;
$o-wslides-tabs-height: 36px;
$o-wslides-color-bg: desaturate(map-get($grays, "200"), 80%);
$o-wslides-color-dark1: #47525f;
$o-wslides-color-dark2: #1f262d;
@@ -12,20 +7,31 @@ $o-wslides-color-dark3: #101216;
$o-wslides-fs-side-width: 300px;
// Common to new slides pages
// **************************************************
.o_wslides_gradient {
background-image: linear-gradient(120deg, #875A7B, darken(#875A7B, 10%));
}
// Common to new slides pages
// **************************************************
.o_wslides_course_pict {
@include size(100%, 30%);
padding-top: 30%;
background-size: cover;
background-position: center;
@include media-breakpoint-up(md) {
@include size(100%);
padding-top: 100%;
}
}
.o_wslides_wrap {
background-color: desaturate(map-get($grays, "200"), 80%);
background-color: $o-wslides-color-bg;
.o_wslides_home_nav {
top: -40px;
@include media-breakpoint-up(md) {
@include media-breakpoint-up(lg) {
font-size: 1rem;
.o_wslides_nav_navbar_right {
@@ -50,33 +56,22 @@ $o-wslides-fs-side-width: 300px;
}
.o_wslides_js_lesson_quiz_question {
li {
font-size: 1.2rem;
.list-group-item {
font-size: 1rem;
input:checked + i.fa-circle {
color: $primary !important;
}
}
.o_wslides_quiz_answer {
&:hover {
cursor: pointer;
}
label {
font-size: 1.4rem;
i.fa-circle {
}
input:checked + i.fa-circle {
color: $primary !important;
overflow: hidden;
}
}
&.disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
// tools
// ****************************************
.text_small_caps {
font-variant: small-caps;
}
@@ -85,55 +80,29 @@ $o-wslides-fs-side-width: 300px;
opacity: 0.5;
}
.bg-brand {
background-color: $o-enterprise-color;
}
// Truncate text descriptions to a specific number of lines.
// If '-webkit-line-clamp' is not supported, a less effective
// 'line-height' fallback will be used instead.
$truncate-limits: 2, 3, 5, 10;
.progress {
overflow: visible;
.progress-bar {
background-color: $primary;
position: relative;
span {
background-color: $primary;
position: absolute;
bottom: -20px;
font-size: 10px;
line-height: 10px;
padding: 2px 3px 2px 4px;
right: -1.4em;
border-radius: 2px;
}
span:after {
bottom: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-color: rgba(255, 255, 255, 0);
border-bottom-color: #00A09D;
border-width: 5px;
margin-left: -5px;
}
@each $limit in $truncate-limits {
.o_wslides_desc_truncate_#{$limit} {
$line-height: 1.3;
max-height: $limit * $line-height * 1em;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
line-height: $line-height;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: $limit;
}
}
}
// New home page
// **************************************************
.o_wslides_home_main {
.o_wprofile_next_rank_card {
background-color: transparent !important;
}
.o_wslides_home_aside_loggedin {
@include media-breakpoint-up(lg) {
background: none;
@@ -145,177 +114,188 @@ $o-wslides-fs-side-width: 300px;
// New course page
// **************************************************
.o_wslides_course_nav {
margin: auto;
background: linear-gradient(150deg, #875A7B 20%, #62495B 80%) !important;
opacity: 0.95;
@mixin o-wslides-tabs($tab-active-color: $o-wslides-color-bg) {
margin-top: $o-wslides-tabs-height * -1;
border-bottom: 0;
a {
color: #FFFFFF;
}
.nav-link {
border-radius: 0;
border-width: 0 1px;
@include o-hover-text-color(rgba(white, 0.8), white);
small a {
color: #000000;
}
nav {
.breadcrumb-item::before {
font-weight: bold;
color: #FFFFFF;
opacity: 0.8;
&, &:hover {
border-color: #875A7B;
background: transparent;
}
.breadcrumb-item {
a {
font-weight: bold;
color: #FFFFFF;
opacity: 0.8;
transition: opacity linear .3s;
}
&.active {
a {
opacity: 1.0;
}
}
}
ol {
background-color: transparent;
&.active {
color: $headings-color;
background: $tab-active-color;
border-color: $tab-active-color;
}
}
}
.o_wslides_course_header {
margin: auto;
background: linear-gradient(150deg, #875A7B 20%, #62495B 80%) !important;
border-bottom: 48px solid #66445e;
.o_wslides_course_header_container {
position: relative;
top: 48px;
padding-top: 0px;
.o_wslides_course_header_aside {
max-width: 286px;
img {
width: 100%;
max-width: 256px;
}
}
.o_wslides_course_header_content {
font-size: 16px;
color: #FFFFFF;
.o_wslides_course_header_nav {
ul.o_wslides_nav_tabs {
border-bottom: 0px;
li.nav-item {
margin-bottom: 0px;
}
a.nav-link {
color: white;
border-radius: 0px;
height: 48px;
font-weight: bold;
padding-top: 12px;
text-align: center;
width: 120px;
&:hover {
border: 0px;
border-radius: 0px;
background-color: #875A7B;
}
&.active {
color: #212529;
background-color: #f2f2f2;
border: 0px;
}
}
}
}
}
@mixin o-wslides-header-bar() {
&:before {
content: "";
@include o-position-absolute(auto, 0, 0, 0);
height: $o-wslides-tabs-height;
background: rgba(black, 0.2);
}
}
.o_wslides_course_nav {
@include o-position-absolute(0,0,auto,0);
border-width: 1px 0;
&, .o_wslides_course_nav_search {
background-color: rgba(white, 0.05);
border-color: rgba(white, 0.1);
border-style: solid;
}
.o_wslides_course_nav_search {
border-width: 0 1px;
}
.breadcrumb-item.active a, .breadcrumb-item a:hover {
color: white;
}
.breadcrumb-item a, .breadcrumb-item + .breadcrumb-item::before, .o_wslides_course_nav_search input::placeholder {
color: rgba(white, 0.8);
}
}
.o_wslides_course_header {
@include media-breakpoint-up(md) {
@include o-wslides-header-bar();
}
}
.o_wslides_course_doc_header {
@include o-wslides-header-bar();
}
.o_wslides_course_main {
.o_wslides_course_content_aside {
max-width: 286px;
.bg-white {
max-width: 256px;
background-color: white;
padding-bottom: 8px;
> div.row {
padding-left: 15px;
padding-right: 15px;
}
.o_wslides_nav_tabs {
@include media-breakpoint-up(md) {
@include o-wslides-tabs();
}
@include media-breakpoint-only(xs) {
overflow-x: auto;
overflow-y: hidden;
line-height: 1.51;
li {
white-space: nowrap;
}
}
}
}
// Slides list reordering widget
.o_wslides_slides_list {
.o_wslides_slides_list_slide {
&.o_not_editable {
height: 0px;
.o_wslides_doc_nav_tabs {
@include o-wslides-tabs($gray-100);
}
.o_wslides_tabs_content {
@include media-breakpoint-down(sm) {
background-color: $nav-tabs-link-active-bg;
padding:0 ($grid-gutter-width * 0.5);
}
&:nth-child(odd) {
background-color: $gray-50;
@include media-breakpoint-only(xs) {
margin: 0 ($grid-gutter-width * -0.5);
}
}
// Slides list reordering widget
.o_wslides_slides_list {
.o_wslides_slide_list_category_header {
z-index: 1;
& + ul {
z-index: 0;
}
}
&:nth-child(even) {
background-color: $gray-100;
.o_text_link {
text-decoration: none!important;
> * {
text-decoration: none!important;
color: map-get($grays, "600");
}
&:hover > * {
color: inherit;
}
}
.o_wslides_slides_list_slide_controls {
i:hover {
color: $primary !important;
cursor: pointer;
.o_wslides_slides_list_drag {
cursor: pointer;
i { opacity: 0.4; }
&:hover i { opacity: 1; }
}
.o_wslides_slide_list_category_header, .o_wslides_slides_list_slide {
border: 1px solid $border-color;
}
.o_wslides_slides_list_slide_hilight {
background-color: #1252F3;
height: 1px;
z-index: 3;
&:before, &:after {
content: "";
@include size(6px);
display: block;
border-radius: 100%;
background-color: inherit;
@include o-position-absolute(-2px, -2px);
}
&:after {
right: auto;
left: -2px;
}
}
}
}
// New lesson page
// New lesson page (not fullscreens)
// **************************************************
.o_wslides_lesson_header {
background: linear-gradient(150deg, $o-enterprise-color 20%, $o-enterprise-radient-color 80%);
margin: auto;
.o_wslides_lesson_header_container {
a:hover {
text-decoration: none;
}
.fa-trophy {
font-size: 2em;
}
}
}
.o_wslides_lesson_main {
.o_wslides_lesson_aside {
.o_wslides_lesson_aside_list,
.o_wslides_lesson_aside_doc {
border: 0;
border-bottom: 3px solid $border-color;
position: relative;
top: -50px;
.o_wslides_lesson_aside_collapse.collapsed {
transform: rotate(90deg);
}
.nav-tabs .nav-link {
border-top: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
.o_wslides_lesson_aside_list {
@include media-breakpoint-up (lg) {
top: -58px;
}
}
.o_wslides_lesson_aside_list {
.o_wslides_lesson_aside_list_link {
text-decoration: none;
@include o-hover-text-color($gray-600, $headings-color );
.o_wslides_lesson_link_name {
line-height: 1.2;
}
&.active {
background-color: $gray-200;
box-shadow:inset 2px 0 theme-color('primary');
}
&:hover .o_wslides_lesson_link_name {
color: $headings-color;
}
}
}
@@ -338,6 +318,29 @@ $o-wslides-fs-side-width: 300px;
}
}
// Modals
// **************************************************
.o_wslides_quiz_modal {
@include media-breakpoint-up (sm) {
.modal-body {
overflow: visible!important;
}
.modal-content {
height: 461px;
.o_wslides_quiz_modal_hero {
margin-left: -30px;
position: absolute;
margin-top: -45px;
}
}
}
}
// Embed PDFViewer
// **************************************************
#PDFViewer.o_wslides_fs_pdf_viewer {
@@ -361,28 +364,10 @@ $o-wslides-fs-side-width: 300px;
}
}
// Slide display
div.embed-responsive {
iframe.o_wslides_iframe_viewer {
position: relative;
}
}
// PDF Viewer Share bar
.oe_slides_share_bar{
padding: 10px 0;
}
.oe_slides_panel_footer #page_number {
width: 45px;
}
.oe_show_footer {
z-index: $MAX-Z-INDEX; // Looks terrible but seems necessary due to fullscreen & canvas in PDFSlidesViewer
}
// Upload Modal
.o_wslides_select_type {
cursor: pointer;
}
@@ -1,83 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="slide.slide.quiz">
<div class="o_wslides_fs_quiz_container h-100 w-100">
<div class="mx-5">
<div class="o_wslides_fs_quiz_container o_wslides_wrap h-100 w-100 overflow-auto pb-5">
<div class="container">
<div t-if="widget.slide.completed" class="row">
<div class="o_wslides_js_lesson_quiz_validation col py-2 bg-100 mb-2 border-bottom"/>
</div>
<div t-foreach="widget.quiz.questions" t-as="question"
class="o_wslides_js_lesson_quiz_question mt-3" t-att-data-question-id="question.id" t-att-data-title="question.question">
<div class="h3">
t-attf-class="o_wslides_js_lesson_quiz_question my-3 #{widget.slide.completed ? 'disabled' : ''}"
t-att-data-question-id="question.id" t-att-data-title="question.question">
<div class="h4">
<small class="text-muted"><span t-esc="question_index+1"/>. </small> <span t-esc="question.question"/>
</div>
<ul class="bg-white list-unstyled">
<div class="list-group">
<t t-foreach="question.answers" t-as="answer">
<li t-att-data-answer-id="answer.id"
<a t-att-data-answer-id="answer.id" href="#"
t-att-data-text="answer.text_value"
class="o_wslides_quiz_answer pt-2 pb-2 border-bottom rounded d-flex align-items-center">
t-attf-class="o_wslides_quiz_answer list-group-item d-flex align-items-center #{widget.slide.completed ? 'disabled bg-transparent' : 'list-group-item-action' } #{widget.slide.completed &amp;&amp; answer.is_correct ? 'list-group-item-success' : '' }">
<label class="mb-0 d-flex align-items-center justify-content-center mr-3 ml-3">
<label class="my-0 d-flex align-items-center justify-content-center mr-2">
<input type="radio"
t-att-name="question.id"
t-att-value="answer.id"
class="d-none"/>
<i class="fa fa-circle text-muted"></i>
<i t-att-class="'fa fa-circle text-400' + (!(widget.slide.completed &amp;&amp; answer.is_correct) ? '' : ' d-none')"></i>
<i class="fa fa-times-circle text-danger d-none"></i>
<i class="fa fa-check-circle text-success d-none"></i>
<i t-att-class="'fa fa-check-circle text-success' + (widget.slide.completed &amp;&amp; answer.is_correct ? '' : ' d-none')"></i>
</label>
<span t-esc="answer.text_value"/>
</li>
</a>
</t>
</ul>
</div>
</div>
<div class="alert alert-danger o_wslides_js_lesson_quiz_error d-none" role="alert">
<div class="alert alert-danger o_wslides_js_lesson_quiz_error mt-2 d-none" role="alert">
<span></span>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&amp;times;</span>
<span>&amp;times;</span>
</button>
</div>
<div class="o_wslides_js_lesson_quiz_validation"/>
<div t-if="!widget.slide.completed" class="o_wslides_js_lesson_quiz_validation border-top pt-3"/>
</div>
</div>
</t>
<t t-name="slide.slide.quiz.validation">
<t t-if="widget.readonly">
<button class="btn btn-primary" role="button" title="Join" aria-label="Join" disabled="disabled">Join course to take quiz</button>
<span role="button" title="Succeed and gain karma" aria-label="Succeed and gain karma"
class="badge badge-pill badge-warning text-white font-weight-bold ml-3 px-2 py-1">+ <t t-esc="widget.quiz.quizKarmaGain"/> XP</span>
</t>
<t t-else="">
<button t-if="! widget.slide.completed" role="button" title="Check answers" aria-label="Check answers"
class="btn btn-primary text-uppercase font-weight-bold o_wslides_js_lesson_quiz_submit">Check your answers</button>
<button t-if="widget.slide.completed" role="button" title="Quiz done" aria-label="Quiz done" disabled="disabled"
class="btn btn-primary text-uppercase font-weight-bold">Done !</button>
<span t-if="! widget.slide.completed" role="button" title="Succeed and gain karma" aria-label="Succeed and gain karma"
class="badge badge-pill badge-warning text-white font-weight-bold ml-3 px-2 py-1">+ <t t-esc="widget.quiz.quizKarmaGain"/> XP</span>
<span t-if="widget.slide.completed" role="button" title="Gained karma" aria-label="Gained karma"
class="badge badge-pill badge-success text-white font-weight-bold ml-3 px-2 py-1">+ <t t-esc="widget.quiz.quizKarmaWon"/> XP</span>
<button t-if="widget.slide.completed &amp;&amp; widget.slide.hasNext"
class="btn btn-primary ml-3 o_wslides_quiz_continue">Continue</button>
</t>
<div t-if="widget.readonly" class="alert alert-info">
<b>Join course to take quiz</b>
<span class="my-0 h4" style="line-height: 1">
<span title="Succeed and gain karma" aria-label="Succeed and gain karma" class="badge badge-pill badge-warning text-white font-weight-bold ml-3 px-2 py-1">
+ <t t-esc="widget.quiz.quizKarmaGain"/> XP
</span>
</span>
</div>
<div t-else="" class="d-flex align-items-center justify-content-between">
<div t-att-class="'d-flex align-items-center' + (widget.slide.completed ? ' alert alert-success my-0 py-1 px-3' : '')">
<button t-if="! widget.slide.completed" role="button" title="Check answers" aria-label="Check answers"
class="btn btn-primary text-uppercase font-weight-bold o_wslides_js_lesson_quiz_submit">Check your answers</button>
<b t-else="" class="my-0 h5">Done !</b>
<span class="my-0 h5" style="line-height: 1">
<span role="button" title="Succeed and gain karma" aria-label="Succeed and gain karma" class="badge badge-pill badge-warning text-white font-weight-bold ml-3 px-2">
+ <t t-esc="widget.quiz.quizKarmaGain"/> XP
</span>
</span>
</div>
<button t-if="widget.slide.completed &amp;&amp; widget.slide.hasNext" class="btn btn-primary o_wslides_quiz_continue">
Continue <i class="fa fa-chevron-right ml-1"/>
</button>
</div>
</t>
<t t-name="slide.slide.quiz.finish">
<div class="modal o_wslides_quiz_modal" tabindex="-1" role="dialog" id="slides_quiz_modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<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">
<div class="w-50 o_wslides_gradient"/>
<div class="w-50 d-flex flex-column p-3">
<h1>Amazing!</h1>
<div class="pb-3">
<span class="pb-2">You gained <span class="badge badge-pill badge-success text-white font-weight-bold"><t t-esc="widget.quiz.quizKarmaWon"/> XP !</span> !</span>
<div class="progress">
<div class="progress-bar" role="progressbar" t-att-aria-valuenow="widget.quiz.rankProgress.progress" aria-valuemin="0" aria-valuemax="100"
t-attf-style="heigth: 8px; width: #{widget.quiz.rankProgress.progress}%"/>
<button type="button" class="close position-absolute" data-dismiss="modal" aria-label="Close" style="right: 5px">&#215;</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="mt-3 display-4 font-weight-bold">Amazing!</h1>
<div class="pb-3">
<h4 class="pb-2 d-flex">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="progress" style="height: 8px">
<div class="progress-bar" role="progressbar" t-att-aria-valuenow="widget.quiz.rankProgress.progress" aria-valuemin="0" aria-valuemax="100"
t-attf-style="width: #{widget.quiz.rankProgress.progress}%"/>
</div>
<small t-if="widget.quiz.rankProgress.lowerBound" class="float-left text-primary font-weight-bold"><t t-esc="widget.quiz.rankProgress.lowerBound"/></small>
<small t-if="widget.quiz.rankProgress.upperBound" class="float-right font-weight-bold"><t t-esc="widget.quiz.rankProgress.upperBound"/></small>
</div>
<small t-if="widget.quiz.rankProgress.lowerBound" class="float-left"><t t-esc="widget.quiz.rankProgress.lowerBound"/></small>
<small t-if="widget.quiz.rankProgress.upperBound" class="float-right"><t t-esc="widget.quiz.rankProgress.upperBound"/></small>
<div class="pb-3" t-raw="widget.quiz.rankProgress.motivational"/>
</div>
<div class="pb-3" t-raw="widget.quiz.rankProgress.motivational"/>
<button t-if="widget.slide.hasNext" type="button" class="btn btn-light o_wslides_quiz_btn align-self-end">Next <i class="fa fa-chevron-right"/></button>
<t t-if="widget.slide.hasNext">
<button type="button" class="btn btn-light border o_wslides_quiz_btn align-self-end">Next <i class="fa fa-chevron-right"/></button>
</t>
<t t-else="">
<!-- TODO: end course if no slide left -->
<a type="button" class="btn btn-light border align-self-end">End course</a>
</t>
</div>
</div>
</div>
@@ -1,28 +1,14 @@
<templates id="template" xml:space="preserve">
<t t-name="website.slides.fullscreen.title">
<t t-if="!widget.get('slide').isQuiz">
<i t-if="widget.get('slide').type == 'document'" class="fa fa-file-pdf-o mr-2"></i>
<i t-if="widget.get('slide').type == 'infographic'" class="fa fa-file-picture-o mr-2"></i>
<i t-if="widget.get('slide').type == 'video'" class="fa fa-play-circle mr-2"></i>
<i t-if="widget.get('slide').type == 'webpage'" class="fa fa-file-text mr-2"></i>
<i t-if="widget.get('slide').type == 'quiz'" class="fa fa-question-circle mr-2 text"></i>
<span class="o_wslides_fs_slide_title_span" t-esc="widget.get('slide').name"/>
</t>
<t t-else="">
<span><i class="fa fa-flag-checkered"></i>Quiz: <span t-esc="widget.get('slide').name"/></span>
</t>
</t>
<t t-name="website.slides.fullscreen.content">
<t t-if="_.contains(['document', 'presentation'], widget.get('slide').type)">
<div class="embed-responsive embed-responsive-4by3 embed-responsive-item h-100">
<iframe t-att-src="widget.get('slide').embedUrl" class="o_wslides_iframe_viewer h-100 w-100" allowFullScreen="true" frameborder="0"></iframe>
<div class="embed-responsive h-100">
<iframe t-att-src="widget.get('slide').embedUrl" class="o_wslides_iframe_viewer" allowFullScreen="true" frameborder="0"/>
</div>
</t>
<t t-if="widget.get('slide').type === 'infographic'">
<div class="w-100 h-100 text-center">
<img t-att-src="'/web/image/slide.slide/'+ widget.get('slide').id +'/image'" class="img-fluid" style="height: 100%" alt="Slide image"/>
<div class="o_wslides_fs_player w-100 h-100 overflow-auto d-flex align-items-start justify-content-center">
<img t-att-src="'/web/image/slide.slide/'+ widget.get('slide').id +'/image'" class="img-fluid position-relative m-auto" alt="Slide image"/>
</div>
</t>
</t>
@@ -13,15 +13,16 @@
Slide Type Selection template
-->
<t t-name="website.slide.upload.modal.select">
<div class="d-flex flex-wrap justify-content-between align-items-stretch text-primary p-1 mt-4">
<t t-foreach="widget.slide_type_data" t-as="slide_type">
<div class="row p-1 mt-4">
<div t-foreach="widget.slide_type_data" t-as="slide_type" class="col-6 col-md-3">
<t t-set="type_data" t-value="widget.slide_type_data[slide_type]"/>
<div class="content-type d-flex flex-column align-items-center p-1 mb-4 o_wslides_select_type" t-att-data-slide-type="slide_type">
<i t-attf-class="fa #{type_data['icon']} mb-2" style="font-size:4rem;"></i>
<a href="#" t-att-data-slide-type="slide_type"
class="content-type d-flex flex-column align-items-center mb-4 o_wslides_select_type btn rounded border text-600 p-3">
<i t-attf-class="fa #{type_data['icon']} mb-2 fa-3x"/>
<t t-esc="type_data['label']"/>
</div>
</t>
</a>
</div>
</div>
</t>
@@ -6,9 +6,9 @@
<div class="o_wslides_course_nav">
<div class="container">
<div class="row align-items-center justify-content-between">
<!-- nav -->
<nav aria-label="breadcrumb" class="col-md-6 col-xs-12">
<ol class="breadcrumb">
<!-- Desktop Mode -->
<nav aria-label="breadcrumb" class="col d-none d-md-flex">
<ol class="breadcrumb bg-transparent mb-0 pl-0 py-0">
<li class="breadcrumb-item">
<a href="/slides">Home</a>
</li>
@@ -29,42 +29,63 @@
</li>
</ol>
</nav>
<div class="col-md-6 col-xs-12 d-flex flex-row align-items-center justify-content-end">
<!-- karma / profile -->
<a t-if="not is_public_user" t-att-href="'/profile/user/%s?channel_id=%s' % (user.id, channel.id)" class="font-weight-bold mr-3">
<i class="fa fa-diamond" /> <t t-esc="user_id.karma"/>
</a>
<div class="col d-none d-md-flex flex-row align-items-center justify-content-end">
<!-- search -->
<form t-attf-action="/slides/#{slug(channel)}" role="search" method="get">
<div class="input-group">
<input type="text" class="form-control" name="search" t-attf-placeholder="Search in #{channel.name}" t-att-value="search"/>
<span class="input-group-append">
<button class="btn btn-primary" type="submit" aria-label="Search" title="Search">
<form t-attf-action="/slides/all" role="search" method="get">
<div class="input-group o_wslides_course_nav_search ml-1 position-relative">
<span class="input-group-prepend">
<button class="btn btn-link text-white rounded-0 pr-1" type="submit" aria-label="Search" title="Search">
<i class="fa fa-search"></i>
</button>
</span>
<input type="text" class="form-control border-0 rounded-0 bg-transparent text-white" name="search" placeholder="Search courses"/>
</div>
</form>
<!-- sort / filter -->
<small class="dropdown float-right ml-3">
<h6 class="m-0">
<button class="btn btn-primary dropdown-toggle" type="button" id="slidesChannelDropdownSort"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<t t-if="sorting == 'most_voted'">Most Voted</t>
<t t-elif="sorting == 'most_viewed'">Most Viewed</t>
<t t-else="">Newest</t>
</button>
<div class="dropdown-menu" aria-labelledby="slidesChannelDropdownSort" role="menu">
<div role="separator" class="dropdown-header">Sort by</div>
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('debug', 'slide_type', sorting='latest'))"
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'latest' else '')">Newest</a>
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('debug', 'slide_type', sorting='most_voted'))"
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'most_voted' else '')">Most Voted</a>
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('debug', 'slide_type', sorting='most_viewed'))"
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'most_viewed' else '')">Most Viewed</a>
</div>
<!-- Mobile Mode -->
<div class="col d-md-none py-1">
<div class="btn-group w-100 position-relative" role="group" aria-label="Mobile sub-nav">
<div class="btn-group w-100">
<a class="btn bg-black-25 text-white dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Nav</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="/slides">Home</a>
<a t-att-class="'dropdown-item %s' % ('active' if not search_category and not search_tag and not search_slide_type else '')" t-att-href="'/slides/%s' % slug(channel)">
&#9492;<span class="ml-1" t-esc="channel.name"/>
</a>
<a class="dropdown-item active" t-att-aria-current="'page' and search_category" t-if="search_category" t-att-href="'/slides/%s/category/%s' % (slug(channel), slug(search_category))">
&#9492;<span class="ml-1" t-esc="search_category.name"/>
</a>
<a class="dropdown-item active" t-att-aria-current="'page' and search_tag" t-if="search_tag" t-att-href="'/slides/%s/tag/%s' % (slug(channel), slug(search_tag))">
&#9492;<span class="ml-1" t-esc="search_tag.name"/>
</a>
<a class="dropdown-item active" t-att-aria-current="'page' and search_uncategorized" t-if="search_uncategorized" t-att-href="'/slides/%s?search_uncategorized=1' % (slug(channel))">
&#9492;<span class="ml-1">Uncategorized</span>
</a>
<a class="dropdown-item active" t-att-aria-current="'page' and search_slide_type" t-if="search_slide_type" t-att-href="'/slides/%s?slide_type=%s' % (slug(channel), search_slide_type)">
&#9492;<span class="ml-1" t-esc="slide_types[search_slide_type]"/>
</a>
</div>
</h6>
</small>
</div>
<div class="btn-group ml-1 position-static">
<a class="btn bg-black-25 text-white dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-right w-100" style="right: 10px;">
<form class="px-3" t-attf-action="/slides/#{slug(channel)}" role="search" method="get">
<div class="input-group">
<input type="text" class="form-control" name="search" placeholder="Search courses"/>
<span class="input-group-append">
<button class="btn btn-primary" type="submit" aria-label="Search" title="Search">
<i class="fa fa-search"/>
</button>
</span>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -81,61 +102,118 @@
<t t-call="website.layout">
<div class="wrap o_wslides_wrap">
<t t-set="main_object" t-value="channel"/>
<t t-call="website_slides.course_nav"/>
<div class="o_wslides_course_header">
<div class="container o_wslides_course_header_container">
<div class="row align-items-end d-flex">
<div class="col-md-4 d-none d-sm-block o_wslides_course_header_aside">
<div t-field="channel.image" widget="image" t-options="{'widget': 'image'}"/>
<div t-attf-class="o_wslides_course_header o_wslides_gradient position-relative text-white pb-md-0 pt-2 pt-md-5 #{'pb-3' if channel.channel_type == 'training' else 'o_wslides_course_doc_header pb-5'}">
<t t-call="website_slides.course_nav"/>
<div class="container mt-5 mt-md-3 mt-xl-4">
<div class="row align-items-end align-items-md-stretch">
<!-- ==== Header Left ==== -->
<div class="col-12 col-md-4 col-lg-3">
<div class="d-flex align-items-start justify-content-around h-100">
<div class="o_wslides_course_pict d-inline-block mb-2 mt-3 my-md-0" t-attf-style="background-image:url(/web/image/slide.channel/#{channel.id}/image)"/>
</div>
</div>
<div class="col-md-8 col-xs-12 align-self-stretch d-flex flex-column o_wslides_course_header_content">
<div class="row">
<h3 class="col-12"><span class="font-weight-bold" t-field="channel.name"/></h3>
<div class="col-12" t-field="channel.description"/>
<div class="col-xs-12 col-md-6 mt8" t-if="channel.allow_comment">
<t t-call="website_rating.rating_stars_static_popup_composer">
<t t-set="rating_avg" t-value="rating_avg"/>
<t t-set="rating_total" t-value="rating_count"/>
<t t-set="object" t-value="channel"/>
<t t-set="hash" t-value="message_post_hash"/>
<t t-set="pid" t-value="message_post_pid"/>
<t t-set="default_message_id" t-value="last_message_id"/>
<t t-set="default_message" t-value="last_message"/>
<t t-set="default_rating_value" t-value="last_rating_value"/>
<t t-set="force_submit_url" t-value="'/slides/mail/update_comment' if last_message_id else False"/>
<t t-set="disable_composer" t-value="not channel.can_review"/>
</t>
<!-- ==== Header Right ==== -->
<div class="col-12 col-md-8 col-lg-9 d-flex flex-column">
<div class="d-flex flex-column">
<h1 t-field="channel.name"/>
<p class="mb-0 mb-xl-3" t-field="channel.description"/>
<div t-if="channel.channel_type == 'documentation'" class="my-1">
<button role="button" class="btn text-white pl-0" title="Share Channel"
aria-label="Share Channel"
data-toggle="modal" data-target="#slideChannelShareModal">
<i class="fa fa-share-square"></i> Share
</button>
</div>
</div>
<div class="row mt-auto o_wslides_course_header_nav">
<div class="col-xs-12 col-md-8">
<ul class="nav nav-tabs o_wslides_nav_tabs" id="profile_extra_info_tablist" role="tablist">
<li class="nav-item o_wlides_course_header_nav_home">
<a t-att-class="'nav-link %s' % ('' if search_slide_type else 'active')" id="home-tab" data-toggle="pill" href="#home" role="tab" aria-controls="home" aria-selected="true">
<i class="fa fa-home"/> Course
</a>
</li>
<li class="nav-item" t-if="channel.allow_comment">
<a class="nav-link" id="review-tab" data-toggle="pill" href="#review" role="tab" aria-controls="review" aria-selected="false">Review</a>
</li>
</ul>
</div>
<div class="d-flex flex-column justify-content-center h5 flex-grow-1 mb-md-5" t-if="channel.allow_comment">
<t t-call="website_rating.rating_stars_static_popup_composer">
<t t-set="btn_classes" t-value="'btn-warning'"/>
<t t-set="rating_avg" t-value="rating_avg"/>
<t t-set="rating_total" t-value="rating_count"/>
<t t-set="object" t-value="channel"/>
<t t-set="hash" t-value="message_post_hash"/>
<t t-set="pid" t-value="message_post_pid"/>
<t t-set="default_message_id" t-value="last_message_id"/>
<t t-set="default_message" t-value="last_message"/>
<t t-set="default_rating_value" t-value="last_rating_value"/>
<t t-set="force_submit_url" t-value="'/slides/mail/update_comment' if last_message_id else False"/>
<t t-set="disable_composer" t-value="not channel.can_review"/>
</t>
</div>
</div>
</div>
</div>
</div>
<div class="container o_wslides_course_main">
<div class="tab-content" id="courseMainTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
<t t-if="channel.channel_type == 'training'" t-call="website_slides.course_slides_list"/>
<t t-if="channel.channel_type == 'documentation'" t-call="website_slides.course_slides_cards"/>
</div>
<div class="tab-pane fade" id="review" role="tabpanel" aria-labelledby="review-tab">
<div class="row">
<div class="o_wslides_course_main">
<!-- ========== TRAINING COURSE ========== -->
<div t-if="channel.channel_type == 'training'" class="container">
<div class="row">
<!-- Training Sidebar -->
<div class="col-12 col-md-4 col-lg-3 mt-3 mt-md-0">
<t t-call="website_slides.course_sidebar"/>
<div class="col-lg-8">
</div>
<!-- Training Content -->
<div class="col-12 col-md-8 col-lg-9">
<ul class="nav nav-tabs o_wslides_nav_tabs flex-nowrap" role="tablist" id="profile_extra_info_tablist">
<li class="nav-item o_wslides_course_header_nav_home">
<a t-att-class="'nav-link %s' % ('' if search_slide_type else 'active')" id="home-tab" data-toggle="pill" href="#home" role="tab" aria-controls="home" aria-selected="true">
<i class="fa fa-home"/> Course
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="review-tab" data-toggle="pill" href="#review" role="tab" aria-controls="review" aria-selected="false">Review</a>
</li>
</ul>
<div class="tab-content py-4 o_wslides_tabs_content mb-4" id="courseMainTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
<t t-if="channel.channel_type == 'training'" t-call="website_slides.course_slides_list"/>
</div>
<div class="tab-pane fade" id="review" role="tabpanel" aria-labelledby="review-tab">
<t t-call="portal.message_thread">
<t t-set="object" t-value="channel"/>
<t t-set="hash" t-value="message_post_hash"/>
<t t-set="pid" t-value="message_post_pid"/>
<t t-set="display_rating" t-value="True"/>
<t t-set="disable_composer" t-value="True"/>
</t>
</div>
</div>
</div>
</div>
</div>
<!-- ========== DOCUMENTATION COURSE ========== -->
<t t-if="channel.channel_type == 'documentation'">
<div class="container">
<div class="row">
<div class="col-12 col-md-8 offset-md-4 col-lg-9 offset-lg-3">
<ul class="nav nav-tabs o_wslides_nav_tabs o_wslides_doc_nav_tabs flex-nowrap" role="tablist" id="profile_extra_info_tablist">
<li class="nav-item o_wslides_course_header_nav_home">
<a class="nav-link active" id="home-tab" data-toggle="pill" href="#home" role="tab" aria-controls="home" aria-selected="true">
<i class="fa fa-home"/> Course
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="review-tab" data-toggle="pill" href="#review" role="tab" aria-controls="review" aria-selected="false">Review</a>
</li>
</ul>
</div>
</div>
</div>
<div class="tab-content pb-5" id="courseMainTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
<t t-if="channel.channel_type == 'documentation'" t-call="website_slides.course_slides_cards"/>
</div>
<div class="tab-pane fade" id="review" role="tabpanel" aria-labelledby="review-tab">
<div class="container pt-4">
<t t-call="portal.message_thread">
<t t-set="object" t-value="channel"/>
<t t-set="hash" t-value="message_post_hash"/>
@@ -146,19 +224,20 @@
</div>
</div>
</div>
</div>
</t>
</div>
</div>
</t>
</template>
<template id="course_sidebar" name="Course Sidebar (infos, CTA)">
<!-- Channel presentation, aka general information + CTAs -->
<div class="col-lg-4 col-xs-12 o_wslides_course_content_aside">
<div class="bg-white">
<div class="row justify-content-center o_wslides_js_course_join">
<!-- Training-only: Channel sidebar (aka general information + CTAs) -->
<div class="bg-white px-3 py-2 py-md-3 mb-3 mb-md-5">
<div class="o_wslides_sidebar_top d-flex justify-content-between">
<div class="o_wslides_js_course_join flex-grow-1">
<a t-if="not channel.is_member and channel.enroll == 'public'" role="button"
class="col-10 mt8 btn btn-primary o_wslides_js_course_join_link"
class="btn btn-primary btn-block o_wslides_js_course_join_link"
title="Start Course" aria-label="Start Course Channel"
t-att-href="'#'"
t-att-data-channel-id="channel.id">
@@ -167,62 +246,40 @@
<t t-else="">Join Course</t>
</span>
</a>
<t t-if="not channel.is_member and channel.enroll == 'invite'">
<a role="button" class="col-10 mt8 btn btn-light" t-att-href="'#'">
<span class="cta-title text_small_caps">Private Course</span>
</a>
<div t-if="not channel.is_member and channel.enroll == 'invite'" class="text-center">
<div class="alert my-0 bg-100 p-2">Private Course</div>
<div t-if="channel.enroll_msg" t-field="channel.enroll_msg"/>
<span t-if="not channel.enroll_msg">Contact website administrator.</span>
</t>
<span t-if="channel.is_member" class="col-10 mt8 btn btn-primary">
<i class="fa fa-chevron-right"></i>
<span class="cta-title text_small_caps">Already member</span>
</span>
<small t-if="not channel.enroll_msg">Contact website administrator.</small>
</div>
<div t-if="channel.is_member" class="d-flex align-items-center alert my-0 px-2 px-xl-3 bg-100">
<t t-call="website_slides.slides_misc_user_image">
<t t-set="img_class" t-value="'rounded-circle mr-1'"/>
<t t-set="img_style" t-value="'height: 1.4em'"/>
</t>
<h6 class="d-flex flex-grow-1 my-0">You're enrolled</h6>
<i class="fa fa-check"/>
</div>
</div>
<div class="row mt8">
<span class="col-5">Last Update</span>
<span class="col"><t t-esc="channel.slide_last_update" t-options="{'widget': 'date'}"/></span>
</div>
<div class="row mt8">
<span class="col-5">Members</span>
<span class="col" t-esc="channel.members_count"/>
</div>
<t t-if="channel.channel_type == 'documentation'">
<div class="row mt8"><div class="col"><hr/></div></div>
<t t-set="slide_type_keys" t-value="slide_types.keys()"/>
<t t-foreach="slide_type_keys" t-as="slide_type_key">
<div class="row mt8 align-items-center">
<span class="col-5">
<t t-if="search_category">
<a t-att-href="'/slides/%s/category/%s?%s' % (slug(channel), slug(search_category), keep_query('debug', slide_type=slide_type_key))"
t-att-class="'%s' % ('active' if search_slide_type == slide_type_key else '')">
<t t-esc="slide_types[slide_type_key]"/>
</a>
</t>
<t t-else="">
<a t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('debug', slide_type=slide_type_key))"
t-att-class="'%s' % ('active' if search_slide_type == slide_type_key else '')">
<t t-esc="slide_types[slide_type_key]"/>
</a>
</t>
</span>
<span class="col">
<t t-if="search_category">
<span class="badge badge-pill badge-info" t-esc="search_category['nbr_%s' % slide_type_key]"/>
</t>
<t t-else="">
<span class="badge badge-pill badge-info" t-esc="channel['nbr_%s' % slide_type_key]"/>
</t>
</span>
</div>
</t>
</t>
<div class="row mt8"><div class="col"><hr/></div></div>
<div class="row justify-content-center mt8">
<button role="button" class="btn btn-primary col-10" title="Share Channel"
<button class="btn btn-sm d-md-none bg-white ml-1 border" type="button" data-toggle="collapse" data-target="#o_wslides_sidebar_collapse" aria-expanded="false" aria-controls="o_wslides_sidebar_collapse">More info</button>
</div>
<div id="o_wslides_sidebar_collapse" class="collapse d-md-block">
<table class="table table-sm mt-3">
<tr>
<th class="border-top-0">Last Update</th>
<td class="border-top-0"><t t-esc="channel.slide_last_update" t-options="{'widget': 'date'}"/></td>
</tr>
<tr>
<th>Members</th>
<td><t t-esc="channel.members_count"/></td>
</tr>
</table>
<div class="mt-3">
<button role="button" class="btn btn-link btn-block" title="Share Channel"
aria-label="Share Channel"
data-toggle="modal" data-target="#slideChannelShareModal">
<i class="fa fa-share-square"></i> Share
<i class="fa fa-share-square fa-fw"/> Share
</button>
<div class="modal fade" id="slideChannelShareModal" tabindex="-1" role="dialog" aria-labelledby="slideChannelShareModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
@@ -248,13 +305,14 @@
</div>
</div>
</div>
<div t-if="channel.can_upload" class="row justify-content-center mt8">
<a role="button" class="btn btn-primary o_wslides_js_slide_upload col-10" title="Upload Presentation"
<div t-if="channel.can_upload" class="justify-content-center mt-1">
<a role="button" class="btn btn-link btn-block o_wslides_js_slide_upload" title="Upload Presentation"
aria-label="Upload Presentation" href="#"
t-att-data-channel-id="channel.id"
t-att-data-can-upload="channel.can_upload"
t-att-data-can-publish="channel.can_publish">
<i class="fa fa-cloud-upload"></i> Upload
<i class="fa fa-cloud-upload fa-fw"/> Upload
</a>
</div>
</div>
@@ -262,168 +320,273 @@
</template>
<template id="course_slides_list" name="Training Course content: list">
<div class="row">
<t t-call="website_slides.course_sidebar"/>
<div class="col-lg-8 mt-3 mb-5 o_wslides_slides_list" t-att-data-channel-id="channel.id">
<ul class="o_wslides_js_slides_list_container border-bottom list-unstyled">
<t t-set="j" t-value="0"/>
<t t-foreach="category_data" t-as="category">
<t t-set="category_record" t-value="category['category'] if category['id'] else None"/>
<t t-set="category_id" t-value="category['id'] if category['id'] else None"/>
<li t-if="category['total_slides'] or channel.can_publish" class="o_wslides_slide_list_category"
t-att-data-category-id="category_id">
<div t-att-data-category-id="category_id"
t-att-class="'text-muted bg-white border-bottom font-weight-bold pt-0 pb-0 pl-2 pr-2 d-flex justify-content-between align-items-center %s' % ('o_wslides_js_category' if category_id else '')">
<div class="pt-2 pb-2 d-flex align-items-center">
<i t-if="channel.can_publish and category_id" class="fa fa-arrows mr-3"></i>
<t t-if="category_record">
<span t-field="category_record.name"/>
</t>
<t t-else="">
<span>Uncategorized</span>
</t>
<div class="mb-5 o_wslides_slides_list" t-att-data-channel-id="channel.id">
<ul class="o_wslides_js_slides_list_container list-unstyled">
<t t-set="j" t-value="0"/>
<t t-foreach="category_data" t-as="category">
<t t-set="category_id" t-value="category['id'] if category['id'] else None"/>
<li t-if="category['total_slides'] or channel.can_publish" t-att-class="'o_wslides_slide_list_category mb-2' if category_id else 'mb-3'" t-att-data-category-id="category_id">
<div t-att-data-category-id="category_id"
t-att-class="'o_wslides_slide_list_category_header position-relative d-flex justify-content-between align-items-center %s' % ('o_wslides_js_category bg-white shadow-sm border-bottom-0' if category_id and channel.can_upload else 'border-0 py-1')">
<div t-att-class="'d-flex align-items-center pl-3 %s' % ('o_wslides_slides_list_drag' if channel.can_publish else '')">
<div t-if="channel.can_publish and category_id" class="o_wslides_slides_list_drag py-2 pr-3">
<i class="fa fa-bars"/>
</div>
<span t-if="category_id" t-att-class="'text-muted' if not channel.can_upload else ''" t-esc="category['name']"/>
<em t-elif="channel.can_publish" class="text-muted mb-1">Uncategorized</em>
<small t-if="not category['total_slides']" class="ml-1 text-muted"><b>(empty)</b></small>
</div>
<div t-if="category_id" class="o_text_link d-flex border-left">
<a t-if="channel.can_upload"
class="mr-2 pt-2 pb-2 border-left o_wslides_js_slide_upload"
class="o_wslides_js_slide_upload px-3 py-2"
role="button"
aria-label="Upload Presentation"
href="#"
style="text-decoration: none;"
t-att-data-channel-id="channel.id"
t-att-data-category-id="category_id"
t-att-data-can-upload="channel.can_upload"
t-att-data-can-publish="channel.can_publish">
<i class="fa fa-plus ml-2"></i> Add content
<i class="fa fa-plus mr-1"/> <span class="d-none d-md-inline-block">Add content</span>
</a>
</div>
<ul t-att-data-category-id="category_id" class="list-unstyled">
<li t-att-class="('text-muted font-italic o_wslides_slides_list_slide o_wslides_js_slides_list_empty justify-content-between align-items-center p-2 %s') % ('d-none' if category['total_slides'] else 'd-flex')">
<div class="ml-2">
<span>Empty category</span>
</div>
</li>
<li class="o_wslides_slides_list_slide o_not_editable"></li>
<t t-foreach="category['slides']" t-as="slide">
<t t-call="website_slides.course_slides_list_slide" />
<t t-set="j" t-value="j+1"/>
</t>
</ul>
</li>
</t>
</ul>
<div t-if="channel.can_upload" class="o_wslides_content_actions">
<a class="o_wslides_js_slide_upload mr-2 border btn btn-light text-muted font-weight-bold"
role="button"
aria-label="Upload Presentation"
href="#"
t-att-data-channel-id="channel.id"
t-att-data-can-upload="channel.can_upload"
t-att-data-can-publish="channel.can_publish"><i class="fa fa-plus"></i> Add Content</a>
<a class="o_wslides_js_slide_section_add border btn btn-light text-muted font-weight-bold" t-attf-channel_id="#{channel.id}"
href="#" role="button"
groups="website.group_website_publisher"><i class="fa fa-folder-o"></i> Add Section</a>
</div>
</div>
<ul t-att-data-category-id="category_id" class="list-unstyled pb-1 border-top">
<li class="o_wslides_slides_list_slide o_not_editable border-0"/>
<li class="o_wslides_js_slides_list_empty border-0"/>
<t t-foreach="category['slides']" t-as="slide">
<t t-call="website_slides.course_slides_list_slide" />
<t t-set="j" t-value="j+1"/>
</t>
</ul>
</li>
</t>
</ul>
<div t-if="channel.can_upload" class="o_wslides_content_actions">
<a class="o_wslides_js_slide_upload mr-1 border btn btn-light text-muted"
role="button"
aria-label="Upload Presentation"
href="#"
t-att-data-channel-id="channel.id"
t-att-data-can-upload="channel.can_upload"
t-att-data-can-publish="channel.can_publish"><i class="fa fa-plus mr-1"/>Add Content</a>
<a class="o_wslides_js_slide_section_add border btn btn-light text-muted" t-attf-channel_id="#{channel.id}"
href="#" role="button"
groups="website.group_website_publisher"><i class="fa fa-folder-o mr-1"/>Add Section</a>
</div>
<div t-field="channel.description_html"/>
</div>
<div t-field="channel.description_html"/>
</template>
<template id="course_slides_list_slide" name="Slide template for a training channel">
<li t-att-index="j" t-att-data-slide-id="slide.id" t-att-data-category-id="category_id"
class="o_wslides_slides_list_slide d-flex align-items-center px-2 py-0">
<div t-if="channel.can_publish" class="border-right pt-2 pb-2">
<i class="fa fa-arrows mr-2 text-muted"></i>
<li t-att-index="j" t-att-data-slide-id="slide.id" t-att-data-category-id="category_id" t-attf-class="o_wslides_slides_list_slide bg-white-50 border-top-0 d-flex align-items-center pl-2 #{'py-1 pr-2' if not channel.can_upload else ''}">
<div t-if="channel.can_publish" class=" o_wslides_slides_list_drag border-right p-2">
<i class="fa fa-bars mr-2"></i>
</div>
<a t-if="slide.is_preview or channel.is_member or channel.can_publish" class="o_wslides_js_slides_list_slide_link font-weight-bold mr-auto"
t-attf-href="/slides/slide/#{slug(slide)}">
<t t-call="website_slides.slide_icon">
<t t-set="icon_class" t-value="'pt-2 pb-2 ml-2 mr-2'"/>
</t>
<t t-call="website_slides.slide_icon">
<t t-set="icon_class" t-value="'py-2 mx-2'"/>
</t>
<a t-if="slide.is_preview or channel.is_member or channel.can_publish" class="o_wslides_js_slides_list_slide_link mr-auto" t-attf-href="/slides/slide/#{slug(slide)}">
<span t-field="slide.name"/>
</a>
<span t-else="" class="text-muted mr-auto">
<t t-call="website_slides.slide_icon">
<t t-set="icon_class" t-value="'pt-2 pb-2 ml-2 mr-2'"/>
</t>
<span t-else="" class="mr-auto">
<span t-esc="slide.name"/>
</span>
<t t-if="slide.question_ids">
<span t-att-class="'badge text-white font-weight-bold %s' % ('badge-success' if channel_progress[slide.id].get('completed') else 'badge-warning')">
<i class="fa fa-flag mr-2"></i>
<div class="d-flex flex-wrap">
<span t-if="slide.question_ids" t-att-class="'badge font-weight-bold px-2 py-1 m-1 %s' % ('badge-success' if channel_progress[slide.id].get('completed') else 'badge-warning')">
<i t-attf-class="fa fa-fw #{'fa-check' if channel_progress[slide.id].get('completed') else 'fa-flag'}"/>
<t t-esc="channel_progress[slide.id].get('quiz_karma_won', 0) if channel_progress[slide.id].get('completed') else channel_progress[slide.id].get('quiz_karma_gain', 0)"/> xp
</span>
</t>
<span class="badge badge-danger ml-2" t-if="not slide.website_published">Unpublished</span>
<span class="badge badge-info ml-2" t-if="slide.is_preview">Free preview</span>
<span class="badge badge-danger font-weight-normal px-2 py-1 m-1" t-if="not slide.website_published">Unpublished</span>
<span class="badge badge-success font-weight-normal px-2 py-1 m-1" t-if="slide.is_preview and not channel.is_member">Free preview</span>
</div>
<div t-if="channel.is_member or channel.can_publish" class="pt-2 pb-2 border-left ml-2 mr-2 pl-2 d-flex align-items-center o_wslides_slides_list_slide_controls">
<t t-if="channel.is_member">
<i t-if="not channel_progress[slide.id].get('completed')" class="check-done fa fa-check-circle text-muted mr-2"></i>
<i t-if="channel_progress[slide.id].get('completed')" class="check-done text-primary fa fa-check-circle mr-2"></i>
<i t-if="not channel_progress[slide.id].get('completed')" class="check-done fa fa-circle-o text-500 px-2"></i>
<i t-else="" class="check-done text-success fa fa-check-circle px-2"></i>
</t>
<a t-if="channel.can_publish and not slide.slide_type == 'webpage'" t-attf-href="/web#id=#{slide.id}&amp;action=#{slide_action}&amp;model=slide.slide&amp;view_type=form">
<i class="fa fa-pencil text-muted mr-2"></i>
</a>
<a t-if="channel.can_publish and slide.slide_type == 'webpage'" t-attf-href="/slides/slide/#{slug(slide)}?enable_editor=1">
<i class="fa fa-pencil text-muted mr-2"></i>
</a>
<i t-if="channel.can_publish" t-att-data-slide-id="slide.id" class="fa fa-trash text-muted o_wslides_js_slide_archive"></i>
<span t-if="channel.can_publish" class="d-none d-md-inline-block">
<a t-if="slide.slide_type == 'webpage'" class="px-2 o_text_link text-primary" target="_blank" t-attf-href="/slides/slide/#{slug(slide)}?enable_editor=1"><span class="fa fa-pencil"/></a>
<a t-else="" class="px-2 o_text_link text-primary" target="_blank" t-attf-href="/web#id=#{slide.id}&amp;action=#{slide_action}&amp;model=slide.slide&amp;view_type=form"><span class="fa fa-pencil"/></a>
<a href="#" t-att-data-slide-id="slide.id" class="o_text_link text-danger px-2 o_wslides_js_slide_archive"><span class="fa fa-trash"/></a>
</span>
</div>
</li>
</template>
<!-- ======= Documentation Course content: cards / categories======= -->
<template id="course_slides_cards" name="Documentation Course content: cards / categories">
<div t-if="not search" class="row mb-5">
<t t-call="website_slides.course_sidebar"/>
<div class="col-lg-8">
<div class="mt-3 w-100">
<h5 class="m-0"> Featured lesson</h5>
<hr class="mt-2"/>
<nav class="navbar navbar-expand-lg navbar-light mb-4 border-bottom">
<div class="container">
<a class="navbar-brand d-lg-none" href="#">Filter &amp; order</a>
<div class="form-inline ml-auto d-lg-none" t-if="search_slide_type or search">
<a t-att-href="'/slides/%s' % (slug(channel))" class="btn btn-info mr-3">
<i class="fa fa-eraser mr-1"/>Clear filters
</a>
</div>
<div class="row" t-if="slide_promoted">
<div class="col-4">
<img class="img img-fluid" style=""
t-att-src="'/slides/slide/%s/get_image?field=image_large' % slide_promoted.id"
t-att-alt="slide_promoted.name"/>
</div>
<div class="col-8">
<h3 class="w-100" t-att-title="slide_promoted.name">
<a t-if="slide_promoted.is_preview or channel.is_member or channel.can_publish"
t-attf-href="/slides/slide/#{slug(slide_promoted)}" class="font-weight-bold text-muted" t-field="slide_promoted.name"/>
<span t-else="" class="font-weight-bold text-muted" t-field="slide_promoted.name"/>
</h3>
<div t-field="slide_promoted.description"/>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-lg-auto align-items-lg-center">
<t t-set="slide_type_keys" t-value="slide_types.keys()"/>
<t t-foreach="slide_type_keys" t-as="slide_type_key">
<t t-if="search_category">
<li t-if="search_category['nbr_%s' % slide_type_key] > 0" class="nav-item">
<a t-att-href="'/slides/%s/category/%s?%s' % (slug(channel), slug(search_category), keep_query('debug', slide_type=slide_type_key))"
t-att-class="'nav-link d-flex align-items-center justify-content-between pl-0 mr-1 %s' % ('active' if search_slide_type == slide_type_key else '')">
<t t-esc="slide_types[slide_type_key]"/>
<span t-attf-class="badge badge-pill ml-1 #{'badge-info' if search_slide_type == slide_type_key else 'bg-400'}" t-esc="search_category['nbr_%s' % slide_type_key]"/>
</a>
</li>
</t>
<t t-else="">
<li t-if="channel['nbr_%s' % slide_type_key] > 0" class="nav-item">
<a t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('debug', slide_type=slide_type_key))"
t-att-class="'nav-link d-flex align-items-center justify-content-between pl-0 mr-1 %s' % ('active' if search_slide_type == slide_type_key else '')">
<t t-esc="slide_types[slide_type_key]"/>
<span t-attf-class="badge badge-pill ml-1 #{'badge-info' if search_slide_type == slide_type_key else 'bg-400'}" t-esc="channel['nbr_%s' % slide_type_key]"/>
</a>
</li>
</t>
</t>
</ul>
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown ml-lg-auto">
<a class="nav-link dropdown-toggle dropdown-toggle align-items-center d-flex" type="button" id="slidesChannelDropdownSort"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" href="#">
<b>Order by</b>
<span class="d-none d-xl-inline">:
<t t-if="sorting == 'most_voted'">Most Voted</t>
<t t-elif="sorting == 'most_viewed'">Most Viewed</t>
<t t-else="">Newest</t>
</span>
</a>
<div class="dropdown-menu" aria-labelledby="slidesChannelDropdownSort" role="menu">
<h6 class="dropdown-header">Sort by</h6>
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('debug', 'slide_type', sorting='latest'))"
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'latest' else '')">Newest</a>
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('debug', 'slide_type', sorting='most_voted'))"
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'most_voted' else '')">Most Voted</a>
<a role="menuitem" t-att-href="'/slides/%s?%s' % (slug(channel), keep_query('debug', 'slide_type', sorting='most_viewed'))"
t-att-class="'dropdown-item %s' % ('active' if sorting and sorting == 'most_viewed' else '')">Most Viewed</a>
</div>
</li>
</ul>
<div class="form-inline mr-3">
<a t-if="search_slide_type or search" t-att-href="'/slides/%s' % (slug(channel))" class="btn btn-sm btn-info ml-1">
<i class="fa fa-eraser mr-1"/>Clear filters
</a>
</div>
<form t-attf-action="/slides/#{slug(channel)}" role="search" method="get" class="form-inline my-2 my-lg-0">
<div class="input-group position-relative">
<input type="text" class="form-control border" name="search" placeholder="Search in content" t-att-value="search"/>
<div class="input-group-append">
<button class="btn border" type="submit" aria-label="Search" title="Search">
<i class="fa fa-search"/>
</button>
</div>
</div>
</form>
</div>
</div>
</nav>
<div t-if="channel.can_upload" class="text-right container pb-2">
<a class="btn btn-primary py-1 o_wslides_js_slide_upload"
title="Upload Presentation" role="button"
aria-label="Upload Presentation" href="#"
t-att-data-channel-id="channel.id"
t-att-data-can-upload="channel.can_upload"
t-att-data-can-publish="channel.can_publish">
<i class="fa fa-cloud-upload mr-1"/>Upload new content
</a>
</div>
<div t-if="search and not category_data" class="row mt16 justify-content-end">
<div class="col-12">
<p class="text-center">No content was found using your search <span class="font-weight-bold" t-esc="search"/>.</p>
</div>
</div>
<t t-foreach="category_data" t-as="category">
<div class="mb-5" t-if="(category['slides'] or channel.can_publish) and (search_category and search_category.id == category['id'] or not search_category)">
<div class="row align-items-center">
<div class="col">
<t t-if="category['id']">
<a t-att-href="'/slides/%s/category/%s' % (slug(channel), category['slug_name'])" class="float-right">View all</a>
</t>
<t t-else="">
<a t-att-href="'/slides/%s?uncategorized=1' % (slug(channel))" class="float-right">View all</a>
</t>
<h5 class="m-0"><t t-esc="category['name']"/></h5>
<hr class="mt-2"/>
</div>
</div>
<div class="row mx-n2 mt8">
<t t-foreach="category['slides']" t-as="slide">
<div class="col-md-3 col-sm-6 px-2 col-xs-12 d-flex flex-grow-1" t-call="website_slides.lesson_card"/>
<!-- Featured lesson -->
<div t-if="not search and not search_slide_type and slide_promoted" class="container mb-3">
<div class="card">
<div class="card-body d-flex flex-column flex-lg-row">
<t t-set="image_url" t-value="'/web/image/slide.slide/%s/image' % slide_promoted.id"/>
<t t-if="slide_promoted.is_preview or channel.is_member or is_slides_publisher">
<a t-attf-href="/slides/slide/#{slug(slide_promoted)}" class="w-100 w-lg-50 mr-0 mr-lg-4 mb-3 mb-lg-0 flex-shrink-0 rounded border">
<div t-attf-style="background-image:url(#{image_url}); background-size: cover; background-position:center; padding-bottom: 35%;" class="h-lg-100"/>
</a>
</t>
<t t-else="">
<div class="w-100 w-lg-50 mr-0 mr-lg-4 mb-3 mb-lg-0 flex-shrink-0 rounded border">
<div t-attf-style="background-image:url(#{image_url}); background-size: cover; background-position:center; padding-bottom: 35%;" class="h-lg-100"/>
</div>
</t>
<div>
<a t-if="slide_promoted.is_preview or channel.is_member or is_slides_publisher"
t-attf-href="/slides/slide/#{slug(slide_promoted)}"
class="h4 d-block" t-att-title="slide_promoted.name" t-field="slide_promoted.name"/>
<h4 t-else="" class="text-muted" t-field="slide_promoted.name"/>
<div t-if="slide_promoted.tag_ids" class="border-top mt-2 pt-1">
<t t-foreach="slide_promoted.tag_ids" t-as="tag">
<a t-att-href="'/slides/%s/tag/%s' % (slug(slide_promoted.channel_id), slug(tag))" class="badge badge-light" t-esc="tag.name"/>
</t>
</div>
<div class="o_wslides_desc_truncate_10 mt-3" t-field="slide_promoted.description"/>
</div>
</div>
</div>
</t>
<div class="row">
<div class="col" t-field="channel.description_html"/>
</div>
<div class="container py-2">
<t t-if="search">
<t t-set="search_results_number" t-value="0"/>
<t t-foreach="category_data" t-as="category">
<t t-set="search_results_number" t-value="search_results_number + category['total_slides']"/>
</t>
<div t-if="search_results_number == 0" class="alert alert-info mt-4 mb-5 text-center">
No content was found using your search <span class="font-weight-bold" t-esc="search"/>.
</div>
</t>
<t t-foreach="category_data" t-as="category">
<div class="mb-2" t-if="(category['slides'] or channel.can_publish) and (search_category and search_category.id == category['id'] or not search_category)">
<div class="d-flex align-items-center justify-content-between border-bottom pb-2 mb-3" t-if="category['name'] != 'Uncategorized'">
<h5 class="m-0"><t t-esc="category['name']"/></h5>
<a t-if="category['id']" t-att-href="'/slides/%s/category/%s' % (slug(channel), category['slug_name'])">View all</a>
<a t-else="" t-att-href="'/slides/%s?uncategorized=1' % (slug(channel))">View all</a>
</div>
<div class="row mx-n2">
<t t-foreach="category['slides']" t-as="slide">
<t t-if="(slide.id != slide_promoted.id) and (slide_promoted and not search) ">
<div class="col-12 col-sm-6 col-lg-3 px-2 d-flex flex-grow-1" t-call="website_slides.lesson_card"/>
</t>
<t t-elif="search_slide_type or search">
<div class="col-12 col-sm-6 col-lg-3 px-2 d-flex flex-grow-1" t-call="website_slides.lesson_card"/>
</t>
</t>
</div>
</div>
</t>
<div class="row">
<div class="col" t-field="channel.description_html"/>
</div>
<t t-if="search_category">
<div class="form-inline justify-content-center">
<t t-call="website_profile.pager_nobox"></t>
</div>
</t>
</div>
<t t-if="search_category">
<div class="form-inline justify-content-center pb-5">
@@ -434,18 +597,26 @@
<template id='lesson_card' name="Lesson Card">
<div class="card w-100 o_wslides_lesson_card mb-4">
<t t-set="lesson_image" t-value="'/slides/slide/%s/get_image?field=image_large' % slide.id"/>
<t t-set="can_access" t-value="slide.is_preview or channel.is_member or channel.can_publish"/>
<a t-if="can_access" t-attf-href="/slides/slide/#{slug(slide)}" t-title="slide.name">
<div class="card-img-top" t-attf-style="padding-top: 50%; background-image: url(#{lesson_image}); background-size: cover; background-position:center"/>
</a>
<t t-else="">
<div class="card-img-top" t-attf-style="padding-top: 50%; background-image: url(#{lesson_image}); background-size: cover; background-position:center"/>
<t t-if="slide.image">
<t t-set="lesson_image" t-value="'/web/image/slide.slide/%s/image' % slide.id"/>
<a t-if="can_access" t-attf-href="/slides/slide/#{slug(slide)}" t-title="slide.name">
<div class="card-img-top border-bottom" t-attf-style="padding-top: 50%; background-image: url(#{lesson_image}); background-size: cover; background-position:center"/>
</a>
<div t-else="" class="card-img-top border-bottom" t-attf-style="padding-top: 50%; background-image: url(#{lesson_image}); background-size: cover; background-position:center"/>
</t>
<t t-else="">
<a t-if="can_access" t-attf-href="/slides/slide/#{slug(slide)}" t-title="slide.name">
<div class="card-img-top border-bottom o_wslides_gradient" t-attf-style="padding-top: 50%;"/>
</a>
<div t-else="" class="card-img-top border-bottom o_wslides_gradient" t-attf-style="padding-top: 50%;"/>
</t>
<div class="card-body">
<a t-if="can_access" class="card-title h5" t-attf-href="/slides/slide/#{slug(slide)}" t-esc="slide.name"/>
<span t-else="" class="card-title h5 text-muted" t-esc="slide.name"/>
<div class="card-subtitle mb-2 text-muted">
<div class="card-subtitle mb-2 text-muted" t-if="slide.is_preview or (not slide.is_published and user.has_group('website.group_website_publisher'))">
<t t-if="slide.is_preview">
<span class="badge badge-info">Free preview</span>
</t>
@@ -453,8 +624,8 @@
<span class="badge badge-danger">Unpublished</span>
</t>
</div>
<div class="card-text mt-1">
<div class="font-weight-light oe_no_empty" t-field="slide.description"/>
<div class="card-text pt-2">
<div class="o_wslides_desc_truncate_3 font-weight-light oe_no_empty" t-field="slide.description"/>
<div t-if="slide.tag_ids" class="border-top mt-2 pt-1">
<t t-foreach="slide.tag_ids" t-as="tag">
<a t-att-href="'/slides/%s/tag/%s' % (slug(slide.channel_id), slug(tag))" class="badge badge-light" t-esc="tag.name"/>
@@ -11,7 +11,7 @@
<h1 class="display-3 mb-0">Reach new heights</h1>
<h2 class="mb-4">Start your online course today !</h2>
<div class="row mt-1 mb-3">
<div class="col-lg-4">
<div class="col-lg-6">
<p>Skill up and have an impact! Your business career starts here. Time to start a course.</p>
</div>
<div class="col-lg-3">
@@ -22,28 +22,33 @@
</div>
</section>
<div class="container mt16 o_wslides_home_nav position-relative">
<nav class="navbar navbar-expand-md navbar-light shadow-sm" style="background: white!important">
<button class="navbar-toggler" type="button"
<nav class="navbar navbar-expand-lg navbar-light shadow-sm" style="background: white!important">
<form method="GET" class="form-inline o_wslides_nav_navbar_right order-lg-3" t-attf-action="/slides/all" role="search">
<div class="input-group">
<input type="search" name="search" class="form-control" placeholder="Search courses" aria-label="Search" t-att-value="search_term"/>
<div class="input-group-append">
<button class="btn border border-left-0 oe_search_button" type="submit" aria-label="Search" title="Search">
<i class="fa fa-search"/>
</button>
</div>
</div>
</form>
<button class="navbar-toggler px-2 order-1" type="button"
data-toggle="collapse" data-target="#navbarSlidesHomepage"
aria-controls="navbarSlidesHomepage" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"/>
</button>
<div class="collapse navbar-collapse" id="navbarSlidesHomepage">
<div class="navbar-nav">
<div class="collapse navbar-collapse order-2" id="navbarSlidesHomepage">
<div class="navbar-nav pt-3 pt-lg-0">
<a class="nav-link nav-link mr-md-2 o_wslides_home_all_slides" href="/slides/all"><i class="fa fa-graduation-cap mr-1"/>All courses</a>
</div>
<div class="navbar-nav o_wslides_nav_navbar_right">
<t t-if="is_public_user">
<a class="nav-link nav-link" href="/web/login?redirect=/slides/all?my=1"><i class="fa fa-file mr-1"/>My courses</a>
</t><t t-else="">
<a class="nav-link nav-link" href="/slides/all?my=1"><i class="fa fa-file mr-1"/>My courses</a>
</t>
</div>
</div>
</nav>
<div class="o_wprofile_email_validation_container mb16 mt16">
<div class="o_wprofile_email_validation_container">
<t t-call="website_profile.email_validation_banner">
<t t-set="redirect_url" t-value="'/slides'"/>
<t t-set="send_alert_classes" t-value="'alert alert-danger alert-dismissable mt-4 mb-0'"/>
<t t-set="done_alert_classes" t-value="'alert alert-success alert-dismissable mt-4 mb-0'"/>
<t t-set="send_validation_email_message" t-value="'Click here to send a verification email allowing you to participate to the eLearning.'"/>
<t t-set="additional_validated_email_message" t-value="' You may now participate to our eLearning.'"/>
</t>
@@ -73,10 +78,10 @@
<t t-set="img_style" t-value="'height: 22px'"/>
</t>
<h5 t-esc="user.name" class="d-flex flex-grow-1 mb-0"/>
<a class="d-none d-lg-block" t-att-href="'/profile/user/%s' % user.id">Edit</a>
<a class="d-none d-lg-block" t-att-href="'/profile/user/%s' % user.id">View</a>
<a class="d-lg-none btn btn-sm bg-white border" href="#" data-toggle="collapse" data-target="#o_wslides_home_aside_content">More info</a>
</div>
<hr class="d-none d-lg-block mt-2"/>
<hr class="d-none d-lg-block mt-2 pt-2 mb-1"/>
</div>
<div id="o_wslides_home_aside_content" class="collapse d-lg-block">
<div class="row mb-5 mt-3 mt-lg-0">
@@ -94,12 +99,12 @@
<div class="col-lg-9 pr-lg-5 order-lg-1">
<t t-if="channels_my">
<t t-set="void_count" t-value="3 - len(channels_my[:3])"/>
<div class="o_wslides_home_content_section mb-5">
<div class="o_wslides_home_content_section mb-3">
<div class="row o_wslides_home_content_section_title align-items-center">
<div class="col">
<a href="slides/all" class="float-right">View all</a>
<h5 class="m-0">Complete latest courses</h5>
<hr class="mt-2"/>
<a href="/slides/all?my=1" class="float-right">View all</a>
<h5 class="m-0">My courses</h5>
<hr class="mt-2 pb-1 mb-1"/>
</div>
</div>
<div class="row mx-n2 mt8">
@@ -109,12 +114,12 @@
</div>
</div>
</t>
<div class="o_wslides_home_content_section mb-5">
<div class="o_wslides_home_content_section mb-3">
<div class="row o_wslides_home_content_section_title align-items-center">
<div class="col">
<a href="slides/all" class="float-right">View all</a>
<h5 class="m-0">Most popular courses</h5>
<hr class="mt-2"/>
<hr class="mt-2 pb-1 mb-1"/>
</div>
</div>
<div class="row mx-n2 mt8">
@@ -123,12 +128,12 @@
</t>
</div>
</div>
<div class="o_wslides_home_content_section mb-5">
<div class="o_wslides_home_content_section mb-3">
<div class="row o_wslides_home_content_section_title align-items-center">
<div class="col">
<a href="slides/all" class="float-right">View all</a>
<h5 class="m-0">Newest courses</h5>
<hr class="mt-2"/>
<hr class="mt-2 pb-1 mb-1"/>
</div>
</div>
<div class="row mx-n2 mt8">
@@ -142,8 +147,14 @@
</div>
<section class="s_banner" style="background-image: url(/website_slides/static/src/img/banner_heroes_default.svg); background-size: cover; background-position: right bottom">
<div class="container py-5">
<h2 class="text-white mb-4">Meet the people who transformed their company</h2>
<a href="/profile/users" class="btn btn-primary btn-lg">Go meet them</a>
<div class="row align-items-center">
<div class="col-12 col-md">
<h2 class="my-4 text-white">Meet the people who transformed their company</h2>
</div>
<div class="col-12 col-md-4">
<a href="/profile/users" class="btn btn-primary btn-lg">Go meet them</a>
</div>
</div>
</div>
</section>
</div>
@@ -203,10 +214,10 @@
<form method="GET" class="form-inline o_wslides_nav_navbar_right">
<div class="input-group">
<input type="search" name="search" class="form-control"
placeholder="Search something" aria-label="Search"
placeholder="Search courses" aria-label="Search"
t-att-value="search_term"/>
<div class="input-group-append">
<button class="btn border oe_search_button" type="submit" aria-label="Search" title="Search">
<button class="btn border border-left-0 oe_search_button" type="submit" aria-label="Search" title="Search">
<i class="fa fa-search"/>
</button>
</div>
@@ -233,15 +244,13 @@
</div>
</div>
<section class="s_banner bg-900" style="background-image: url(&quot;/website/static/src/img/backgrounds/people.jpg&quot;); background-size: cover; background-position: 65% 55%">
<section class="s_banner bg-900" style="background-image: url(/website_slides/static/src/img/banner_heroes_default.svg); background-size: cover; background-position: right bottom">
<div class="container py-5">
<h1 class="display-3 mb-0">Meet the people who transformed their company</h1>
<h2 class="mb-4">Nobody gave me a real text so instead of a lorem ipsum I put that one.</h2>
<div class="row mt-1 mb-3">
<div class="col-lg-4">
<p>Nobody gave me a real text so instead of a lorem ipsum I put that one.</p>
<div class="row align-items-center">
<div class="col-12 col-md">
<h2 class="my-4">Meet the people who transformed their company</h2>
</div>
<div class="col-lg-3">
<div class="col-12 col-md-4">
<a href="/profile/users" class="btn btn-primary btn-lg">Go meet them</a>
</div>
</div>
@@ -255,20 +264,23 @@
<div class="card w-100 o_wslides_course_card mb-4">
<t t-set="course_image" t-value="'/web/image/slide.channel/%s/image_large' % channel.id"/>
<a t-attf-href="/slides/#{slug(channel)}" t-title="channel.name">
<div class="card-img-top" t-attf-style="padding-top: 50%; background-image: url(#{course_image}); background-size: cover; background-position:center"/>
<div t-if="channel.image_large" class="card-img-top" t-attf-style="padding-top: 50%; background-image: url(#{course_image}); background-size: cover; background-position:center"/>
<div t-else="" class="o_wslides_gradient card-img-top position-relative" style="padding-top: 50%; opacity: 0.8">
<i class="fa fa-graduation-cap fa-2x mr-3 mb-3 position-absolute text-white-75" style="right:0; bottom: 0"/>
</div>
</a>
<div class="card-body">
<a class="card-title h5" t-attf-href="/slides/#{slug(channel)}" t-esc="channel.name"/>
<div class="card-body p-3">
<a class="card-title h5 o_wslides_desc_truncate_2" t-attf-href="/slides/#{slug(channel)}" t-esc="channel.name"/>
<div class="card-text mt-1">
<div class="font-weight-light oe_no_empty" t-field="channel.description"/>
<div t-if="channel.tag_ids" class="border-top mt-2 pt-1">
<div class="font-weight-light o_wslides_desc_truncate_3" t-field="channel.description"/>
<div t-if="channel.tag_ids" class="mt-2 pt-1 o_wslides_desc_truncate_2">
<t t-foreach="channel.tag_ids" t-as="tag">
<a t-att-href="'/slides/all?channel_tag_id=%s' % tag.id" class="badge badge-light" t-esc="tag.name"/>
</t>
</div>
</div>
</div>
<div class="card-footer border-top-0 text-600">
<div class="card-footer border-top-0 text-600 px-3">
<div class="d-flex justify-content-between align-items-center">
<small class="font-weight-bold" t-field="channel.total_time" t-options='{"widget": "float_time"}'/>
<div class="d-flex flex-grow-1 justify-content-end">
@@ -324,7 +336,7 @@
<div class="col">
<a href="/profile/users" class="float-right">View all</a>
<h5 class="m-0">Heroes of the week</h5>
<hr class="mt-2"/>
<hr class="mt-2 pt-2"/>
</div>
</div>
<div class="row">
@@ -349,7 +361,9 @@
<div style="line-height:1.3">
<span class="font-weight-bold" t-esc="user.name"/>
<div class="d-flex align-items-center">
<span class="text-muted" t-esc="user.rank_id.name"/><span class="ml8 mr8">&#8226;</span><span t-esc="user.karma" class="badge badge-success"/>
<t t-esc="user.rank_id.name"/>
<span class="text-500 mx-2">&#8226;</span>
<span class="badge badge-success"><t t-esc="user.karma"/> xp</span>
</div>
</div>
</div>
@@ -6,27 +6,31 @@
<t t-call="website.layout">
<t t-set="main_object" t-value="slide"/>
<div class="wrap o_wslides_wrap">
<t t-call="website_slides.course_nav">
<t t-set="channel" t-value="slide.channel_id"/>
</t>
<div class="o_wslides_lesson_header">
<div class="container o_wslides_lesson_header_container pt-3 pb-3">
<div class="row align-items-end d-flex">
<div class="col-md-9 offset-md-3 col-xs-12">
<h3 class="font-weight-bold w-100">
<a t-att-href="'/slides/%s' % (slug(slide.channel_id))"
class="text-white"
t-field="slide.channel_id.name"/>
</h3>
<div t-if="not is_public_user" class="d-flex align-items-center">
<div class="progress w-50" style="height: 8px;">
<div class="progress-bar rounded" role="progressbar"
<div class="o_wslides_lesson_header o_wslides_gradient position-relative text-white pb-0 pt-2 pt-md-5">
<t t-call="website_slides.course_nav">
<t t-set="channel" t-value="slide.channel_id"/>
</t>
<div class="container o_wslides_lesson_header_container mt-5 mt-md-3 mt-xl-4">
<div class="row align-items-end align-items-md-stretch">
<div t-attf-class="col-12 col-lg-9 d-flex flex-column #{'offset-lg-3' if slide.channel_id.channel_type == 'training' else ''}">
<h2 class="font-weight-medium w-100">
<a t-att-href="'/slides/%s' % (slug(slide.channel_id))" class="text-white text-decoration-none" t-field="slide.channel_id.name"/>
</h2>
<div t-if="slide.channel_id.channel_type == 'documentation'" class="mb-3 small">
<span class="font-weight-normal">Last update:</span>
<t t-esc="slide.date_published" t-options="{'widget': 'date'}"/>
</div>
<div t-else="" class="d-flex align-items-center pb-3">
<div class="progress w-50 bg-black-25" style="height: 10px;">
<div class="progress-bar rounded-left" role="progressbar"
t-att-aria-valuenow="slide.channel_id.completion" aria-valuemin="0" aria-valuemax="100"
t-attf-style="width: #{slide.channel_id.completion}%;">
<span><t t-esc="slide.channel_id.completion"/> %</span>
</div>
</div>
<i t-att-class="'fa fa-trophy m-0 ml-2 p-0 %s' % ('text-success' if slide.channel_id.completed else 'text-warning')"></i>
<i t-att-class="'fa fa-trophy m-0 ml-2 p-0 %s' % ('text-warning' if slide.channel_id.completed else 'text-black-50')"></i>
<small class="ml-2 text-white-50"><t t-esc="slide.channel_id.completion"/> %</small>
</div>
</div>
</div>
@@ -34,13 +38,11 @@
</div>
<div class="container o_wslides_lesson_main">
<div class="row">
<div class="col-lg-3 o_wslides_lesson_aside">
<t t-if="slide.channel_id.channel_type == 'training'"
t-call="website_slides.slide_aside_training"/>
<t t-if="slide.channel_id.channel_type == 'documentation'"
t-call="website_slides.slide_aside_documentation"/>
<div t-attf-class="o_wslides_lesson_aside col-lg-3 #{'order-2' if slide.channel_id.channel_type == 'documentation' else ''}">
<t t-if="slide.channel_id.channel_type == 'training'" t-call="website_slides.slide_aside_training"/>
<t t-if="slide.channel_id.channel_type == 'documentation'" t-call="website_slides.slide_aside_documentation"/>
</div>
<div class="col-lg-9 o_wslides_lesson_content">
<div t-attf-class="o_wslides_lesson_content col-lg-9 #{'order-1' if slide.channel_id.channel_type == 'documentation' else ''}">
<t t-call="website_slides.slide_content_detailed"/>
</div>
</div>
@@ -51,14 +53,14 @@
<!-- Slide: sidebar documentation mode -->
<template id="slide_aside_documentation" name="Slide: Sidebar in Documentation">
<div class="o_wslides_lesson_aside_doc bg-white">
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item"><a aria-controls="related" href="#related" class="nav-link active" data-toggle="tab">Related</a></li>
<li class="nav-item"><a aria-controls="most_viewed" href="#most_viewed" class="nav-link" data-toggle="tab">Most Viewed</a></li>
<div class="o_wslides_lesson_aside_doc position-relative bg-white pb-1 my-3 border-bottom">
<ul class="nav nav-tabs nav-fill" role="tablist">
<li class="nav-item"><a aria-controls="related" href="#related" class="nav-link rounded-0 border-top-0 border-left-0 py-2 active" data-toggle="tab">Related</a></li>
<li class="nav-item"><a aria-controls="most_viewed" href="#most_viewed" class="nav-link rounded-0 border-top-0 border-right-0 py-2" data-toggle="tab">Most Viewed</a></li>
</ul>
<div class="tab-content">
<div role="tabpanel" id="related" class="tab-pane active">
<ul class="list-unstyled card-body px-2 py-0">
<div role="tabpanel" id="related" class="tab-pane active bg-100">
<ul class="list-group list-group-flush">
<t t-set="related_slides_list" t-value="list(related_slides)"/>
<t t-if="not related_slides_list">
No presentation available.
@@ -68,8 +70,8 @@
</t>
</ul>
</div>
<div role="tabpanel" id="most_viewed" class="tab-pane">
<ul class="list-unstyled card-body px-2 py-0">
<div role="tabpanel" id="most_viewed" class="tab-pane bg-100">
<ul class="list-group list-group-flush">
<t t-set="most_viewed_slides_list" t-value="list(most_viewed_slides)"/>
<t t-if="not list(most_viewed_slides_list)">
No presentation available.
@@ -85,27 +87,30 @@
<!-- Slide sub-template: display an item in a list of related slides (Related, Most Viewed, ...) -->
<template id="slide_aside_card" name="Related Slide">
<li class="media mt-2 row">
<t t-set="slide_image" t-value="'/web/image/slide.slide/%s/image_medium' % aside_slide.id"/>
<a t-att-href="'/slides/slide/%s' % (slug(aside_slide))" t-att-title="aside_slide.name" class="col-4">
<div class="img" t-attf-style="padding-top: 50%; background-image: url(#{slide_image}); background-size: cover; background-position:center"/>
</a>
<div class="media-body col-8 pl-0">
<a t-att-href="'/slides/slide/%s' % (slug(aside_slide))">
<h6 t-esc="aside_slide.name" class="mb-1"/>
</a>
<small class="text-muted">
<a class="list-group-item list-group-item-action d-flex align-items-start px-2" t-att-href="'/slides/slide/%s' % (slug(aside_slide))">
<t t-set="slide_image" t-value="'/web/image/slide.slide/%s/image' % aside_slide.id"/>
<div t-if="aside_slide.image" class="flex-shrink-0 mr-1 border" t-attf-style="width: 20%; padding-top: 20%; background-image: url(#{slide_image}); background-size: cover; background-position:center"/>
<div t-else="" class="o_wslides_gradient flex-shrink-0 mr-1" t-attf-style="width: 20%; padding-top: 20%;"/>
<div class="overflow-hidden d-flex flex-column justify-content-start">
<h6 t-esc="aside_slide.name" class="o_wslides_desc_truncate_2 mb-1" style="line-height: 1.15"/>
<small class="text-600">
<t t-esc="aside_slide.total_views"/> Views &#8226; <timeago class="timeago" t-att-datetime="aside_slide.create_date"></timeago>
</small>
</div>
</li>
</a>
</template>
<!-- Slide: sidebar training mode -->
<template id="slide_aside_training" name="Slide: Sidebar in Training">
<div class="o_wslides_lesson_aside_list bg-white">
<h5 class="bg-100 text-600 pl-2 py-2 border-bottom">Course content</h5>
<ul class="p-0 list-unstyled">
<div class="o_wslides_lesson_aside_list position-relative bg-white border-bottom mt-4">
<div class="bg-100 text-600 h6 my-0 text-decoration-none border-bottom d-flex align-items-center justify-content-between">
<span class="p-2">Course content</span>
<a href="#collapse_slide_aside" data-toggle="collapse" class="d-lg-none p-2 text-decoration-none o_wslides_lesson_aside_collapse">
<i class="fa fa-chevron-down d-lg-none"/>
</a>
</div>
<ul id="collapse_slide_aside" class="list-unstyled my-0 pb-3 collapse d-lg-block">
<t t-set="i" t-value="0"/>
<t t-if="uncategorized_slides" t-call="website_slides.slide_aside_training_category">
<t t-set="category_slide_ids" t-value="uncategorized_slides"/>
@@ -120,45 +125,49 @@
</template>
<template id="slide_aside_training_category" name="Category item for the slide detailed view list">
<li class="mt-3">
<li class="o_wslides_fs_sidebar_section mt-2">
<a t-att-href="('#collapse-%s') % (category.id if category else 0)" data-toggle="collapse" role="button" aria-expanded="true"
class="o_wslides_lesson_aside_list_link pl-2 text-600"
class="o_wslides_lesson_aside_list_link pl-2 text-600 text-uppercase text-decoration-none py-1 small d-block"
t-att-aria-controls="('collapse-%s') % (category.id if category else 0)">
<t t-if="category">
<span t-field="category.name" class="text-uppercase"/>
<b t-field="category.name"/>
</t>
<t t-else="">
<span class="text-uppercase">Uncategorized</span>
<b>Uncategorized</b>
</t>
</a>
<ul class="collapse show p-0 m-0 list-unstyled" t-att-id="('collapse-%s') % (category.id if category else 0)" >
<t t-foreach="category_slide_ids" t-as="aside_slide">
<li class="p-0">
<li class="p-0 pb-1">
<a t-att-href="'/slides/slide/%s' % (slug(aside_slide))"
t-att-class="'o_wslides_lesson_aside_list_link d-flex align-items-center pl-2 %s' % ('bg-200 border-left border-primary' if aside_slide == slide else '')">
<i t-att-id="'o_wslides_lesson_aside_slide_check_%s' % (aside_slide.id)"
t-att-class="'mr-2 fa %s' % ('text-success fa-check-circle' if channel_progress[aside_slide.id].get('completed') else 'text-600 fa-circle-o')">
</i>
<t t-call="website_slides.slide_icon">
<t t-set="icon_class" t-value="'mr-2 %s' % ('text-800' if aside_slide == slide else 'text-600')"/>
<t t-set="slide" t-value="aside_slide"/>
</t>
<span t-esc="aside_slide.name" t-att-class="'mr-2 %s' % ('text-800' if aside_slide == slide else 'text-600')"/>
<span t-if="aside_slide.question_ids"
t-att-class="'ml-auto badge badge-pill %s' % ('badge-success' if channel_progress[aside_slide.id].get('completed') else 'badge-light text-600')">
<t t-esc="channel_progress[aside_slide.id].get('quiz_karma_won') if channel_progress[aside_slide.id].get('completed') else channel_progress[aside_slide.id].get('quiz_karma_gain')"/> xp
</span>
t-att-class="'o_wslides_lesson_aside_list_link d-flex align-items-top px-2 pt-1 text-decoration-none %s' % ('bg-100 py-1 active' if aside_slide == slide else '')">
<div t-if="aside_slide.channel_id.is_member" >
<i t-att-id="'o_wslides_lesson_aside_slide_check_%s' % (aside_slide.id)"
t-att-class="'mr-1 fa fa-fw %s' % ('text-success fa-check-circle' if channel_progress[aside_slide.id].get('completed') else 'text-600 fa-circle-o')">
</i>
</div>
<div class="o_wslides_lesson_link_name">
<span t-esc="aside_slide.name" class="mr-2"/>
</div>
<div class="ml-auto" t-if="aside_slide.question_ids">
<span t-att-class="'badge badge-pill %s' % ('badge-success' if channel_progress[aside_slide.id].get('completed') else 'badge-light text-600')">
<t t-esc="channel_progress[aside_slide.id].get('quiz_karma_won') if channel_progress[aside_slide.id].get('completed') else channel_progress[aside_slide.id].get('quiz_karma_gain')"/> xp
</span>
</div>
</a>
<ul t-if="aside_slide.link_ids or aside_slide.question_ids" class="list-group ml-5 list-unstyled">
<ul t-if="aside_slide.link_ids or aside_slide.question_ids" class="list-group px-2 mb-1 list-unstyled">
<t t-foreach="aside_slide.link_ids" t-as="resource">
<a t-attf-href="#{resource.link}" target="new">
<li><small><i class="fa fa-link mr-1"></i><span t-field="resource.name"/></small></li>
</a>
<li class="pl-4">
<a t-attf-href="#{resource.link}" target="new" class="text-decoration-none small">
<i class="fa fa-link mr-1"/><span t-field="resource.name"/>
</a>
</li>
</t>
<a t-if="aside_slide.question_ids" t-att-href="'/slides/slide/%s#lessonQuiz' % (slug(aside_slide))"
class="o_wslides_lesson_aside_list_link text-600">
<li><small><i class="fa fa-flag-o text-warning"></i> Quiz</small></li>
</a>
<li class="pl-4">
<a t-if="aside_slide.question_ids and aside_slide.slide_type != 'quiz'" t-att-href="'/slides/slide/%s#lessonQuiz' % (slug(aside_slide))" class="o_wslides_lesson_aside_list_link text-decoration-none small text-600">
<i class="fa fa-flag text-warning"/> Quiz
</a>
</li>
</ul>
</li>
</t>
@@ -168,13 +177,16 @@
<!-- Slide: all its content, not fullscreen mode -->
<template id="slide_content_detailed" name="Slide: Detailed Content">
<div class="row">
<div class="col-12 d-flex mt-3">
<t t-set="is_training_channel" t-value="slide.channel_id.channel_type == 'training'"/>
<div class="row align-items-center my-3">
<div class="col-12 col-md order-2 order-md-1 d-flex">
<div class="d-flex align-items-center">
<h5 class="m-0 ml-2">
<t t-call="website_slides.slide_icon"/>
<h4 class="my-0">
<t t-call="website_slides.slide_icon">
<t t-set="icon_class">mr-1</t>
</t>
<span t-field="slide.name"/>
</h5>
</h4>
<span t-if="slide.question_ids"
t-att-class="'ml-2 badge %s' % ('badge-success' if channel_progress[slide.id].get('completed') else 'badge-info')">
<span t-if="channel_progress[slide.id].get('completed')">
@@ -185,13 +197,15 @@
<span>XP</span>
</span>
</div>
<div class="ml-auto">
</div>
<div class="col-12 col-md order-1 order-md-2 text-nowrap flex-grow-0 d-flex justify-content-end mb-3 mb-md-0">
<div class="btn-group flex-grow-1 flex-sm-0" role="group" aria-label="Lesson Nav">
<a t-att-class="'btn btn-light border %s' % ('disabled' if not previous_slide else '')"
role="button" t-att-aria-disabled="'disabled' if not previous_slide else None"
t-att-href="'/slides/slide/%s' % (slug(previous_slide)) if previous_slide else '#'">
<i class="fa fa-chevron-left mr-2"></i> Prev
<i class="fa fa-chevron-left mr-2"></i> <span class="d-none d-sm-inline-block">Prev</span>
</a>
<t t-set="allow_done_btn" t-value="slide.slide_type in ['infographic', 'presentation', 'document', 'webpage'] and not slide.question_ids and not channel_progress[slide.id].get('completed')"/>
<t t-set="allow_done_btn" t-value="slide.slide_type in ['infographic', 'presentation', 'document', 'webpage', 'video'] and not slide.question_ids and not channel_progress[slide.id].get('completed') and slide.channel_id.is_member"/>
<a t-att-class="'btn btn-primary border text-white %s' % ('disabled' if not allow_done_btn else '')"
role="button" t-att-aria-disabled="'true' if not allow_done_btn else None"
t-att-href="'/slides/slide/%s/set_completed?%s' % (slide.id, 'next_slide_id=%s' % (next_slide.id) if next_slide else '') if allow_done_btn else '#'">
@@ -200,20 +214,21 @@
<a t-att-class="'btn btn-light border %s' % ('disabled' if not next_slide else '')"
role="button" t-att-aria-disabled="'disabled' if not next_slide else None"
t-att-href="'/slides/slide/%s' % (slug(next_slide)) if next_slide else '#'">
Next <i class="fa fa-chevron-right ml-2"></i>
<span class="d-none d-sm-inline-block">Next</span> <i class="fa fa-chevron-right ml-2"></i>
</a>
<a t-att-class="'btn btn-light border ml-2 %s' % ('disabled' if slide.channel_id.channel_type != 'training' else '')"
role="button" t-att-aria-disabled="'disabled' if slide.channel_id.channel_type != 'training' else None"
t-att-href="'/slides/slide/%s?fullscreen=1' % (slug(slide)) if slide.channel_id.channel_type == 'training' else '#'"><i class="fa fa-desktop mr-2"></i> Fullscreen</a>
</div>
</div>
<div t-if="slide.tag_ids" class="col">
<t t-foreach="slide.tag_ids" t-as="tag">
<a t-att-href="'/slides/%s/tag/%s' % (slug(slide.channel_id), slug(tag))" class="badge badge-light" t-esc="tag.name"/>
</t>
<a t-if="is_training_channel" class="btn btn-light border ml-2" role="button" t-att-href="'/slides/slide/%s?fullscreen=1' % (slug(slide))">
<i class="fa fa-desktop mr-2"/>
<span class="d-none d-sm-inline-block">Fullscreen</span>
</a>
</div>
</div>
<div class="row o_wslides_lesson_content_type">
<div t-if="slide.tag_ids" class="pb-2">
<t t-foreach="slide.tag_ids" t-as="tag">
<a t-att-href="'/slides/%s/tag/%s' % (slug(slide.channel_id), slug(tag))" class="badge badge-light py-1 px-2" t-esc="tag.name"/>
</t>
</div>
<div class="o_wslides_lesson_content_type">
<img t-if="slide.slide_type == 'infographic'"
t-attf-src="/web/image/slide.slide/#{slide.id}/image" class="img-fluid" style="width:100%" t-att-alt="slide.name"/>
<div t-if="slide.slide_type in ('presentation', 'document')" class="embed-responsive embed-responsive-4by3 embed-responsive-item mb8" style="height: 600px;">
@@ -222,7 +237,7 @@
<div t-if="slide.slide_type == 'video' and slide.document_id" class="embed-responsive embed-responsive-16by9 embed-responsive-item mb8">
<t t-raw="slide.embed_code"/>
</div>
<div t-if="slide.slide_type == 'webpage'" class="bg-white">
<div t-if="slide.slide_type == 'webpage'" class="bg-white p-3">
<div t-field="slide.html_content"/>
</div>
</div>
@@ -230,33 +245,33 @@
<t t-call="website_slides.lesson_content_quiz"/>
</div>
<div class="row mt-3 mb-3">
<div class="col d-flex align-items-start">
<div class="col-12 col-md d-flex align-items-start mb-4 mb-md-0" t-if="len(slide.link_ids)">
<span t-if="slide.link_ids" class="text-muted font-weight-bold mr-3">External sources</span>
<div class="text-muted mr-auto border-left pl-3">
<t t-foreach="slide.link_ids" t-as="link">
<a t-att-href="link.link" t-esc="link.name"/><br />
</t>
</div>
<t t-if="slide.channel_id.allow_comment and slide.channel_id.channel_type == 'documentation'">
<span class="text-muted font-weight-bold mr-3">Rating</span>
<div class="text-muted border-left pl-3">
<div class="o_wslides_js_slide_like mr-2">
<span t-att-class="('o_wslides_js_slide_like_up %s') % ('disabled' if not slide.channel_id.can_vote else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id">
<i class="fa fa-thumbs-up fa-1x" role="img" aria-label="Likes" title="Likes"></i>
<span t-esc="slide.likes"/>
</span>
<span t-att-class="('o_wslides_js_slide_like_down ml-3 %s') % ('disabled' if not slide.channel_id.can_vote else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id">
<i class="fa fa-thumbs-down fa-1x" role="img" aria-label="Dislikes" title="Dislikes"></i>
<span t-esc="slide.dislikes"/>
</span>
</div>
</div>
<div t-if="slide.channel_id.allow_comment and slide.channel_id.channel_type == 'documentation'"
class="col-12 col-md d-flex align-items-start justify-content-md-end mb-2 mb-md-0">
<span class="text-muted font-weight-bold mr-3">Rating</span>
<div class="text-muted border-left pl-3">
<div class="o_wslides_js_slide_like mr-2">
<span t-att-class="('o_wslides_js_slide_like_up %s') % ('disabled' if not slide.channel_id.can_vote else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id">
<i class="fa fa-thumbs-up fa-1x" role="img" aria-label="Likes" title="Likes"></i>
<span t-esc="slide.likes"/>
</span>
<span t-att-class="('o_wslides_js_slide_like_down ml-3 %s') % ('disabled' if not slide.channel_id.can_vote else '')" tabindex="0" data-toggle="popover" t-att-data-slide-id="slide.id">
<i class="fa fa-thumbs-down fa-1x" role="img" aria-label="Dislikes" title="Dislikes"></i>
<span t-esc="slide.dislikes"/>
</span>
</div>
</t>
</div>
</div>
</div>
<div class="row mb-5">
<ul class="col-lg-12 nav nav-tabs o_wslides_lesson_nav" role="tablist">
<div class="mb-5">
<ul class="nav nav-tabs o_wslides_lesson_nav" role="tablist">
<li class="nav-item">
<a href="#about" aria-controls="about" class="nav-link active" role="tab" data-toggle="tab">
<i class="fa fa-home"></i> About
@@ -267,7 +282,7 @@
<i class="fa fa-comments-o"></i> Comments
</a>
</li>
<li class="nav-item">
<li class="nav-item" t-if="slide.index_content">
<a href="#transcript" aria-controls="transcript" class="nav-link" role="tab" data-toggle="tab">
<i class="fa fa-align-justify"></i> Transcript
</a>
@@ -283,7 +298,7 @@
</a>
</li>
</ul>
<div class="col tab-content mt-3">
<div class="tab-content mt-3">
<div role="tabpanel" t-att-class="not comments and 'tab-pane fade in show active' or 'tab-pane fade'" id="about">
<div t-field="slide.description"/>
</div>
@@ -294,59 +309,75 @@
<t t-set="display_rating" t-value="False"/>
</t>
</div>
<div role="tabpanel" class="tab-pane fade oe_slides_transcript" id="transcript">
<t t-if="slide.index_content">
<t t-foreach="slide.index_content.split('\n')" t-as="line">
<p t-esc="line"></p>
</t>
<div role="tabpanel" class="tab-pane fade oe_slides_transcript" id="transcript" t-if="slide.index_content">
<t t-foreach="slide.index_content.split('\n')" t-as="line">
<p t-esc="line"></p>
</t>
</div>
<div role="tabpanel" class="tab-pane fade" id="statistic" t-att-slide-url="slide.website_url">
<div class="row">
<div class="col-lg-4 d-flex flex-column">
<span class="font-weight-bold mb-3 mt-3">Views</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" t-esc="slide.total_views"/>
<span class="mr-5 ml-auto">Total Views</span>
</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" t-esc="slide.slide_views"/>
<span class="mr-5 ml-auto">Members Views</span>
</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" t-esc="slide.public_views"/>
<span class="mr-5 ml-auto">Public Views</span>
</span>
<div class="col-12 col-md">
<table class="table table-sm">
<tbody>
<tr>
<th colspan="2" class="border-top-0">Views</th>
</tr>
<tr class="border-top-0">
<th class="border-top-0"><span t-esc="slide.total_views"/></th>
<td class="border-top-0 w-100">Total Views</td>
</tr>
<tr>
<th><span t-esc="slide.slide_views"/></th>
<td>Members Views</td>
</tr>
<tr>
<th><span t-esc="slide.public_views"/></th>
<td>Public Views</td>
</tr>
</tbody>
</table>
</div>
<div class="col-lg-4 d-flex flex-column">
<span class="font-weight-bold mb-3 mt-3">Actions</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" t-esc="slide.likes"/>
<span class="mr-5 ml-auto">Likes</span>
</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" t-esc="slide.dislikes"/>
<span class="mr-5 ml-auto">Dislikes</span>
</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" t-esc="len(slide.website_message_ids)"/>
<span class="mr-5 ml-auto">Comments</span>
</span>
<div t-if="slide.channel_id.allow_comment" class="col-12 col-md">
<table class="table table-sm">
<tbody>
<tr>
<th colspan="2" class="border-top-0">Actions</th>
</tr>
<tr class="border-top-0">
<th class="border-top-0"><span t-esc="slide.likes"/></th>
<td class="border-top-0 w-100">Likes</td>
</tr>
<tr>
<th><span t-esc="slide.dislikes"/></th>
<td>Dislikes</td>
</tr>
<tr>
<th><span t-esc="len(slide.website_message_ids)"/></th>
<td>Comments</td>
</tr>
</tbody>
</table>
</div>
<div class="col-lg-4 d-flex flex-column">
<span class="font-weight-bold mb-3 mt-3">Share Count</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" id="facebook-badge">0</span>
<span class="mr-5 ml-auto">Facebook</span>
</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" id="twitter-badge">0</span>
<span class="mr-5 ml-auto">Twitter</span>
</span>
<span class="d-flex pl-3">
<span class="badge badge-pill" id="linkedin-badge">0</span>
<span class="mr-5 ml-auto">LinkedIn</span>
</span>
<div class="col-12 col-md">
<table class="table table-sm">
<tbody>
<tr>
<th colspan="2" class="border-top-0">Share count</th>
</tr>
<tr class="border-top-0">
<th class="border-top-0"><span id="facebook-badge">0</span></th>
<td class="border-top-0 w-100">Facebook</td>
</tr>
<tr>
<th><span id="twitter-badge">0</span></th>
<td>Twitter</td>
</tr>
<tr>
<th><span id="linkedin-badge"/></th>
<td>LinkedIn</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@@ -358,14 +389,18 @@
<t t-call="website_slides.slide_social_media">
<t t-set="slide" t-value="slide"/>
</t>
<t t-call="website_slides.slide_social_email">
<t t-set="slide" t-value="slide"/>
</t>
<t t-if="not slide.document_id">
<t t-call="website_slides.slide_social_embed">
<t t-set="slide" t-value="slide"/>
</t>
</t>
<div class="row">
<div t-attf-class="col-12 #{'col-lg-6' if slide.embed_code else ''}">
<t t-call="website_slides.slide_social_email">
<t t-set="slide" t-value="slide"/>
</t>
</div>
<div class="col-12 col-lg-6" t-if="slide.embed_code">
<t t-call="website_slides.slide_social_embed">
<t t-set="slide" t-value="slide"/>
</t>
</div>
</div>
</t>
</div>
</div>
@@ -374,12 +409,13 @@
<!-- Slide sub-tempalte: render a quiz serverside. Should be sync with JS qweb template "slide.slide.quiz" -->
<template id="lesson_content_quiz" name="Lesson: Quiz specific content">
<t t-set="slide_completed" t-value="channel_progress[slide.id].get('completed')"/>
<div class="o_wslides_js_lesson_quiz col" id="lessonQuiz"
t-att-data-id="slide.id"
t-att-data-name="slide.name"
t-att-data-slide-type="slide.slide_type"
t-att-data-readonly="not channel_progress[slide.id]"
t-att-data-completed="channel_progress[slide.id].get('completed')"
t-att-data-readonly="not slide.channel_id.is_member"
t-att-data-completed="1 if slide_completed else 0"
t-att-data-quiz-attempts-count="quiz_attempts_count"
t-att-data-quiz-karma-max="quiz_karma_max"
t-att-data-quiz-karma-gain="quiz_karma_gain"
@@ -388,44 +424,45 @@
t-att-data-next-slide-url="'/slides/slide/%s' % (slug(next_slide)) if next_slide else None">
<div t-foreach="slide.question_ids" t-as="question"
class="o_wslides_js_lesson_quiz_question mt-3" t-att-data-question-id="question.id" t-att-data-title="question.question">
<div class="h3">
<div class="h4">
<small class="text-muted"><span t-esc="question_index+1"/>. </small> <span t-esc="question.question"/>
</div>
<ul class="bg-white list-unstyled">
<div class="list-group">
<t t-foreach="question.answer_ids" t-as="answer">
<li t-att-data-answer-id="answer.id"
<a t-att-data-answer-id="answer.id" href="#"
t-att-data-text="answer.text_value"
class="o_wslides_quiz_answer pt-2 pb-2 border-bottom rounded d-flex align-items-center">
<label class="mb-0 d-flex align-items-center justify-content-center mr-3 ml-3">
t-att-class="'o_wslides_quiz_answer list-group-item list-group-item-action d-flex align-items-center %s' % ('list-group-item-success' if slide_completed and answer.is_correct else '')">
<label class="my-0 d-flex align-items-center justify-content-center mr-2">
<input type="radio"
t-att-name="question.id"
t-att-value="answer.id"
class="d-none"/>
<i class="fa fa-circle text-muted"></i>
class="d-none"
t-att-disabled="True if not slide.channel_id.is_member or slide_completed else ''"/>
<i t-att-class="'fa fa-circle text-400 %s' % ('d-none' if slide_completed and answer.is_correct else '')"/>
<i class="fa fa-times-circle text-danger d-none"></i>
<i class="fa fa-check-circle text-success d-none"></i>
<i t-att-class="'fa fa-check-circle text-success %s' % ('d-none' if not (slide_completed and answer.is_correct) else '')"></i>
</label>
<span t-esc="answer.text_value"/>
</li>
</a>
</t>
</ul>
</div>
</div>
<div class="alert alert-danger o_wslides_js_lesson_quiz_error d-none" role="alert">
<div class="alert alert-danger o_wslides_js_lesson_quiz_error mt-2 d-none" role="alert">
<span></span>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&amp;times;</span>
</button>
</div>
<div class="o_wslides_js_lesson_quiz_validation"/>
<div class="o_wslides_js_lesson_quiz_validation pt-3"/>
</div>
</template>
<!-- Slide sub-template: share: send by email -->
<template id='slide_social_email' name="Share by Email">
<h4 class="mt-3">Share with a friend</h4>
<t t-if="not is_public_user">
<h5 class="mt-4">Share by mail</h5>
<div t-if="not is_public_user" class="form-inline">
<form class="form-group oe_slide_js_share_email" role="form">
<div class="input-group col-lg-6">
<div class="input-group">
<input type="email" class="form-control" placeholder="your-friend@domain.com"/>
<span class="input-group-append">
<button class="btn btn-primary" type="button"
@@ -436,18 +473,18 @@
</button>
</span>
</div>
<span class="form-text">Send presentation through email</span>
<span class="form-text text-muted d-block w-100">Send presentation through email</span>
</form>
</t>
<t t-if="is_public_user">
<p>Please <a t-attf-href="/web?redirect=#{request.httprequest.url}"> login </a> to send this <t t-esc="slide.slide_type"/> by email!</p>
</t>
</div>
<div t-if="is_public_user" class="alert alert-info d-inline-block">
<p class="mb-0">Please <a t-attf-href="/web?redirect=#{request.httprequest.url}" class="font-weight-bold"> login </a> to share this <t t-esc="slide.slide_type"/> by email.</p>
</div>
</template>
<!-- Slide sub-template: share: embed in your website -->
<template id="slide_social_embed" name="Share on Your Website">
<div class="oe_slide_js_embed_code_widget">
<h4 class="mt0">Embed in your website</h4>
<div class="oe_slide_js_embed_code_widget mt-4">
<h5 class="mt0">Embed in your website</h5>
<div class="form-group">
<textarea class="form-control slide_embed_code" readonly="readonly" onClick="this.select();"><t t-esc="slide.embed_code"/></textarea>
</div>
@@ -74,7 +74,7 @@
</div>
</div>
<t t-if="slide.slide_type in ('presentation', 'document')">
<div id="PDFViewerLoader" class="oe_slides_loader d-flex justify-content-center align-items-center position-absolute h-100 w-100">
<div id="PDFViewerLoader" class="oe_slides_loader position-absolute mt-3 mr-3" style="right:0">
<div class="toast show">
<div class="toast-header">
<i class="fa fa-circle-o-notch fa-spin mr-2"/><b>Loading...</b>
@@ -8,20 +8,17 @@
<div class="o_wslides_slide_fs_header d-flex flex-shrink-0 text-white">
<div class="d-flex">
<a class="o_wslides_fs_toggle_sidebar d-flex align-items-center px-3" href="#" title="Lessons">
<a class="o_wslides_fs_toggle_sidebar d-flex align-items-center px-3 active" href="#" title="Lessons">
<i class="fa fa-bars"/><span class="d-none d-md-inline-block ml-1">Lessons</span>
</a>
<a class="o_wslides_fs_review d-flex align-items-center px-3" t-att-href="slide.channel_id.website_url" title="Reviews" t-if="slide.channel_id.allow_comment">
<i class="fa fa-pencil"/><span class="d-none d-md-inline-block ml-1">Write a review</span>
</a>
</div>
<div class="o_wslides_fs_slide_title flex-grow-1 d-flex align-items-center px-2 px-md-3">
<t t-call="website_slides.slide_icon">
<t t-set="icon_class" t-value="'mr-2 text'"/>
</t>
<span class="o_wslides_fs_slide_title_span" t-esc="slide.name"/>
</div>
<div class="d-flex">
<div class="d-flex ml-auto">
<a class="d-flex align-items-center px-3 o_wslides_fs_exit_fullscreen" t-attf-href="/slides/slide/#{slug(slide)}">
<i class="fa fa-sign-out d-md-none"/><span class="d-none d-md-inline-block ml-1">Exit Fullscreen</span>
</a>
<a class="d-flex align-items-center px-3" t-attf-href="/slides/#{slug(slide.channel_id)}">
<i class="fa fa-sign-out d-md-none"/><span class="d-none d-md-inline-block ml-1">Back to course</span>
</a>
@@ -70,19 +67,15 @@
<template id="slide_fullscreen_sidebar_category" name="Slides category template for fullscreen view side bar">
<li class="o_wslides_fs_sidebar_section py-2 px-3 mb-2">
<a class="text-uppercase text-500 py-1 small d-block" t-attf-id="category-collapse-#{category.id if category else 0}" data-toggle="collapse" role="button" aria-expanded="true" t-att-href="('#collapse-%s') % (category.id if category else 0)" t-attf-aria-controls="collapse-#{category.id if category else 0}">
<t t-if="category">
<b t-field="category.name"/>
</t>
<t t-else="">
<b >Uncategorized</b>
</t>
<li class="o_wslides_fs_sidebar_section py-2 px-3">
<a t-if="category" class="text-uppercase text-500 py-1 small d-block" t-attf-id="category-collapse-#{category.id if category else 0}" data-toggle="collapse" role="button" aria-expanded="true" t-att-href="('#collapse-%s') % (category.id if category else 0)" t-attf-aria-controls="collapse-#{category.id if category else 0}">
<b t-field="category.name"/>
</a>
<ul class="o_wslides_fs_sidebar_section_slides collapse show position-relative px-0 pb-1 my-0 mx-n3" t-att-id="('collapse-%s') % (category.id if category else 0)">
<t t-foreach="slides" t-as="slide">
<t t-set="slide_completed" t-value="channel_progress[slide.id].get('completed')"/>
<li t-att-class="'o_wslides_fs_sidebar_list_item d-flex align-items-top py-2 %s text-truncate' % ('active' if slide.id == current_slide.id else '')"
<t t-set="is_member" t-value="slide.channel_id.is_member"/>
<li t-att-class="'o_wslides_fs_sidebar_list_item d-flex align-items-top py-1 %s' % ('active' if slide.id == current_slide.id else '')"
t-att-data-id="slide.id"
t-att-data-name="slide.name"
t-att-data-type="slide.slide_type"
@@ -91,25 +84,21 @@
t-att-data-is-quiz="0"
t-att-data-completed="1 if slide_completed else 0"
t-att-data-embed-code="slide.embed_code if slide.slide_type in ['video', 'document', 'presentation', 'infographic'] else False"
t-att-data-readonly="not channel_progress[slide.id]"
t-att-data-readonly="not is_member"
>
<span class="ml-3 pt-1">
<i t-if="not slide_completed" class="fa fa-circle-thin overflow-hidden d-flex align-items-center justify-content-center" t-att-data-slide-id="slide.id"/>
<i t-if="slide_completed" class="o_wslides_slide_completed fa fa-check-circle rounded-circle text-success bg-white border border-success overflow-hidden d-flex align-items-center justify-content-center" t-att-data-slide-id="slide.id"/>
<span class="ml-3">
<i t-if="slide_completed and is_member" class="o_wslides_slide_completed fa fa-check fa-fw text-success" t-att-data-slide-id="slide.id"/>
<i t-if="not slide_completed and is_member" class="fa fa-circle-thin fa-fw" t-att-data-slide-id="slide.id"/>
</span>
<div class="ml-2">
<a class="d-block pt-1" href="#">
<div class="d-flex ">
<t t-call="website_slides.slide_icon">
<t t-set="icon_class" t-value="'mr-1 fw-fw'"/>
<t t-set="slide" t-value="slide"/>
</t>
<div class="o_wslides_fs_slide_name" t-esc="slide.name"/>
</div>
</a>
<ul class="list-unstyled w-100 pt-2 small" t-if="slide.link_ids or (slide.question_ids and not slide.slide_type =='quiz')" >
<li t-if="slide.link_ids" t-foreach="slide.link_ids" t-as="link" class="pl-0 mb-1">
<a class="o_wslides_fs_slide_link" t-att-href="link.link" target="new">
<a class="o_wslides_fs_slide_link" t-att-href="link.link" target="_blank">
<i class="fa fa-link mr-2"/><span t-esc="link.name"/>
</a>
</li>
@@ -119,7 +108,9 @@
t-att-data-type="slide.slide_type"
t-att-data-slug="slug(slide)"
t-att-data-has-question="1 if slide.question_ids else 0"
t-att-data-is-quiz="1">
t-att-data-is-quiz="1"
t-att-data-completed="1 if slide_completed else 0"
t-att-data-readonly="not is_member">
<a class="o_wslides_fs_slide_quiz" href="#" t-att-index="i">
<i class="fa fa-flag-checkered text-warning mr-2"/>Quiz
</a>
@@ -37,7 +37,10 @@
<div class="card-body o_wprofile_slides_course_card_body p-0 d-flex"
t-attf-onclick="location.href='/slides/#{slug(course.channel_id)}';">
<div class="pl-5 pr-4 rounded-left" t-attf-style="background-image:url(/web/image/slide.channel/#{course.channel_id.id}/image); background-size: cover; background-position: center"/>
<div t-if="course.channel_id.image" class="pl-5 pr-4 rounded-left" t-attf-style="background-image:url(/web/image/slide.channel/#{course.channel_id.id}/image); background-size: cover; background-position: center"/>
<div t-else="" class="o_wslides_gradient pl-5 pr-4 rounded-left position-relative" style="opacity: 0.8">
<i class="fa fa-graduation-cap fa-fw mr-2 mt-3 position-absolute text-white-75" style="right:0; top: 0"/>
</div>
<div class="p-2 w-100">
<h5 class="mt-0 mb-1" t-field="course.channel_id.name"/>
@@ -3,22 +3,28 @@
<!-- Share on social networks -->
<template id='slides_share' name="Slides Media Share">
<div>
<a t-attf-href="https://www.facebook.com/sharer/sharer.php?u=#{record.website_url}" class="o_slides_social_share" social-key="facebook" aria-label="Share on Facebook" title="Share on Facebook"><i class="fa fa-facebook-square fa-2x"/></a>
<a t-attf-href="https://twitter.com/intent/tweet?text=#{record.name}&amp;url=#{record.website_url}" class="o_slides_social_share" social-key="twitter" aria-label="Share on Twitter" title="Share on Twitter"><i class="fa fa-twitter fa-2x"/></a>
<a t-attf-href="http://www.linkedin.com/shareArticle?mini=true&amp;url=#{record.website_url}&amp;title=#{record.name}&amp;" social-key="linkedin" class="o_slides_social_share" aria-label="Share on LinkedIn" title="Share on LinkedIn"><i class="fa fa-linkedin fa-2x"/></a>
<div class="btn-group" role="group">
<a t-attf-href="https://www.facebook.com/sharer/sharer.php?u=#{record.website_url}" class="btn border bg-white o_slides_social_share" social-key="facebook" aria-label="Share on Facebook" title="Share on Facebook"><i class="fa fa-facebook-square fa-fw"/></a>
<a t-attf-href="https://twitter.com/intent/tweet?text=#{record.name}&amp;url=#{record.website_url}" class="btn border bg-white o_slides_social_share" social-key="twitter" aria-label="Share on Twitter" title="Share on Twitter"><i class="fa fa-twitter fa-fw"/></a>
<a t-attf-href="http://www.linkedin.com/shareArticle?mini=true&amp;url=#{record.website_url}&amp;title=#{record.name}&amp;" social-key="linkedin" class="btn border bg-white o_slides_social_share" aria-label="Share on LinkedIn" title="Share on LinkedIn"><i class="fa fa-linkedin fa-fw"/></a>
</div>
</template>
<!-- Share: social media -->
<template id='slide_social_media' name="Share on Social Networks">
<h4 class="mt0">Share on Social Networks</h4>
<t t-call="website_slides.slides_share">
<t t-set="record" t-value="slide"/>
</t>
<h4 class="mt-3">Share Link</h4>
<input type="text" class="form-control" t-att-value="slide.website_url" readonly="readonly" onClick="this.select();"/>
<span class="form-text">Use permanent link to share in social media</span>
<div class="row">
<div class="col-12 col-lg-6 mb-4">
<h5 class="mt-0 mb-2">Share on Social Networks</h5>
<t t-call="website_slides.slides_share">
<t t-set="record" t-value="slide"/>
</t>
</div>
<div class="col-12 col-lg-6">
<h5 class="mt-0 mb-2">Share Link</h5>
<input type="text" class="form-control" t-att-value="slide.website_url" readonly="readonly" onClick="this.select();"/>
<span class="form-text text-muted">Use permanent link to share in social media</span>
</div>
</div>
</template>
<!-- Website edit page -->
@@ -2,7 +2,7 @@
<odoo><data>
<template id='course_main' inherit_id="website_slides.course_main">
<!-- Channel main template: add link to forum -->
<xpath expr="//li[hasclass('o_wlides_course_header_nav_home')]" position="after">
<xpath expr="//li[hasclass('o_wslides_course_header_nav_home')]" position="after">
<li class="nav-item" t-if="channel.forum_id">
<a t-att-href="'/forum/%s' % (slug(channel.forum_id))"
t-att-class="'nav-link'" target="new">Forum</a>
@@ -29,10 +29,10 @@ class WebsiteSlides(WebsiteSlides):
# Utils
# ---------------------------------------------------
def _set_completed_slide(self, slide, quiz_attempts_inc=False):
def _set_completed_slide(self, slide):
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)
return super(WebsiteSlides, self)._set_completed_slide(slide)
def _get_valid_slide_post_values(self):
result = super(WebsiteSlides, self)._get_valid_slide_post_values()
@@ -4,7 +4,11 @@
<t t-name="website.slides.fullscreen.certification">
<div class="justify-content-center align-self-center">
<div t-if="widget.get('slide').type === 'certification' &amp;&amp; !widget.get('slide').completed" class="">
<a class="btn btn-primary" t-att-href="'/slides_survey/slide/get_certification_url?slide_id=' + widget.get('slide').id" target="_blank"><i class="fa fa-trophy"/> Pass Certification</a>
<a class="btn btn-primary" t-att-href="'/slides_survey/slide/get_certification_url?slide_id=' + widget.get('slide').id" target="_blank">
<i class="fa fa-trophy"/>
<span t-if="widget.get('slide').isMember"> Pass Certification</span>
<span t-else="">Test Certification</span>
</a>
</div>
<div class="" t-if="widget.get('slide').type === 'certification' &amp;&amp; widget.get('slide').completed">
<a role="button" class="btn btn-primary" t-att-href="'/survey/' + widget.get('slide').certificationId + '/get_certification'">