diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index bdfb0d49f8854cf73477102e2f99c6438e464360..22abb5ded9cb004a2c83d3b75a37228b95927b4f 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -68,13 +68,24 @@ class WebsiteSlides(WebsiteProfile): return True def _get_slide_detail(self, slide): + base_domain = request.website.website_domain() if slide.channel_id.channel_type == 'documentation': - most_viewed_slides = slide._get_most_viewed_slides(self.SLIDES_PER_ASIDE) - related_slides = slide._get_related_slides(self.SLIDES_PER_ASIDE) - uncategorized_slides = request.env['slide.slide'] + base_domain = expression.AND([base_domain, [('website_published', '=', True), ('id', '!=', slide.id)]]) + related_domain = expression.AND([base_domain, [('channel_id', '=', slide.channel_id.id)]]) + + most_viewed_slides = request.env['slide.slide'].search(base_domain, limit=self.SLIDES_PER_ASIDE, order='total_views desc') + related_slides = request.env['slide.slide'].search(related_domain, limit=self.SLIDES_PER_ASIDE) + uncategorized_slides, channel_slides = request.env['slide.slide'], request.env['slide.slide'] else: + if slide.channel_id.can_publish: + related_domain = expression.AND([base_domain, [('channel_id', '=', slide.channel_id.id)]]) + else: + related_domain = expression.AND([base_domain, [('channel_id', '=', slide.channel_id.id), ('website_published', '=', True)]]) + channel_slides = request.env['slide.slide'].search(related_domain) most_viewed_slides, related_slides = request.env['slide.slide'], request.env['slide.slide'] - uncategorized_slides = slide.channel_id.slide_ids.filtered(lambda slide: not slide.category_id) + # temporarily kept for fullscreen, to remove asap + uncategorized_domain = expression.AND([base_domain, [('channel_id', '=', slide.channel_id.id), ('category_id', '=', False)]]) + uncategorized_slides = request.env['slide.slide'].search(uncategorized_domain) channel_slides_ids = slide.channel_id.slide_ids.ids slide_index = channel_slides_ids.index(slide.id) @@ -89,9 +100,9 @@ class WebsiteSlides(WebsiteProfile): 'previous_slide': previous_slide, 'next_slide': next_slide, 'uncategorized_slides': uncategorized_slides, + 'channel_slides': channel_slides, # user 'user': request.env.user, - 'user_progress': self._get_user_progress(slide.channel_id)['user_progress'], 'is_public_user': request.website.is_public_user(), # rating and comments 'comments': slide.website_message_ids or [], @@ -104,46 +115,15 @@ class WebsiteSlides(WebsiteProfile): 'message_post_pid': request.env.user.partner_id.id, }) - if slide.question_ids: - values.update(self._get_slide_quiz_info(slide)) - return values def _get_slide_quiz_info(self, slide, quiz_done=False): - gains = [slide.quiz_first_attempt_reward, - slide.quiz_second_attempt_reward, - slide.quiz_third_attempt_reward, - slide.quiz_fourth_attempt_reward] - result = { - 'quiz_karma_max': gains[0], # what could be gained if succeed at first try - 'quiz_karma_gain': gains[0], # what would be gained at next test - 'quiz_karma_won': 0, # what has been gained - 'quiz_attempts_count': 0, # number of attempts - } - if slide.user_membership_id: - if slide.user_membership_id.quiz_attempts_count: - result['quiz_karma_gain'] = gains[slide.user_membership_id.quiz_attempts_count] if slide.user_membership_id.quiz_attempts_count <= len(gains) else gains[-1] - result['quiz_attempts_count'] = slide.user_membership_id.quiz_attempts_count - if quiz_done or slide.user_membership_id.completed: - result['quiz_karma_won'] = gains[slide.user_membership_id.quiz_attempts_count-1] if slide.user_membership_id.quiz_attempts_count < len(gains) else gains[-1] - return result + return slide._compute_quiz_info(request.env.user.partner_id, quiz_done=quiz_done)[slide.id] # CHANNEL UTILITIES # -------------------------------------------------- - def _get_user_progress(self, channel): - user_progress = { - slide_partner.slide_id.id: slide_partner - for slide_partner in request.env['slide.slide.partner'].sudo().search([ - ('channel_id', '=', channel.id), - ('partner_id', '=', request.env.user.partner_id.id) - ]) - } - return { - 'user_progress': user_progress - } - - def _get_channel_progress(self, channel): + def _get_channel_progress(self, channel, include_quiz=False): """ Replacement to user_progress. Both may exist in some transient state. """ slides = request.env['slide.slide'].sudo().search([('channel_id', '=', channel.id)]) channel_progress = dict((sid, dict()) for sid in slides.ids) @@ -161,6 +141,11 @@ class WebsiteSlides(WebsiteProfile): slide_partner.slide_id.quiz_fourth_attempt_reward] channel_progress[slide_partner.slide_id.id]['quiz_gain'] = gains[slide_partner.quiz_attempts_count] if slide_partner.quiz_attempts_count < len(gains) else gains[-1] + if include_quiz: + quiz_info = slides._compute_quiz_info(request.env.user.partner_id, quiz_done=False) + for slide_id, slide_info in quiz_info.items(): + channel_progress[slide_id].update(slide_info) + return channel_progress def _extract_channel_tag_search(self, **post): @@ -531,11 +516,15 @@ class WebsiteSlides(WebsiteProfile): self._set_viewed_slide(slide) values = self._get_slide_detail(slide) - values['channel_progress'] = self._get_channel_progress(slide.channel_id) + # quiz-specific: update with karma and quiz information + if slide.question_ids: + values.update(self._get_slide_quiz_info(slide)) + # sidebar: update with user channel progress + values['channel_progress'] = self._get_channel_progress(slide.channel_id, include_quiz=True) if 'fullscreen' in kwargs: return request.render("website_slides.slide_fullscreen", values) - return request.render("website_slides.slide_detail_view", values) + return request.render("website_slides.slide_main", values) @http.route('''/slides/slide/<model("slide.slide"):slide>/pdf_content''', type='http', auth="public", website=True, sitemap=False) @@ -590,7 +579,9 @@ class WebsiteSlides(WebsiteProfile): @http.route('/slides/slide/<model("slide.slide"):slide>/set_completed', website=True, type="http", auth="user") def slide_set_completed_and_redirect(self, slide, next_slide_id=None): self._set_completed_slide(slide) - next_slide = request.env['slide.slide'].browse(next_slide_id) if next_slide_id else None + next_slide = None + if next_slide_id: + next_slide = self._fetch_slide(next_slide_id).get('slide', None) return werkzeug.utils.redirect("/slides/slide/%s" % (slug(next_slide) if next_slide else slug(slide))) @http.route('/slides/slide/set_completed', website=True, type="json", auth="public") diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index 5990a6dc30ef2cbacbdb84cad01b47c01cbbaf01..53378df947cbe0d345efa31bf519ed1bee3348c3 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -342,22 +342,6 @@ class Slide(models.Model): # Business Methods # --------------------------------------------------------- - def _get_related_slides(self, limit=20): - # TDE FIXME: should build a smarter domain - domain = request.website.website_domain() - domain += [('website_published', '=', True), ('id', '!=', self.id)] - if self.category_id: - domain += [('category_id', '=', self.category_id.id)] - for record in self.search(domain, limit=limit): - yield record - - def _get_most_viewed_slides(self, limit=20): - # TDE FIXME: should build a smarter domain - domain = request.website.website_domain() - domain += [('website_published', '=', True), ('id', '!=', self.id)] - for record in self.search(domain, limit=limit, order='total_views desc'): - yield record - def _post_publication(self): base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') for slide in self.filtered(lambda slide: slide.website_published and slide.channel_id.publish_template_id): @@ -504,6 +488,36 @@ class Slide(models.Model): return self.env.user.sudo().add_karma(points) + def _compute_quiz_info(self, target_partner, quiz_done=False): + result = dict.fromkeys(self.ids, False) + slide_partners = self.env['slide.slide.partner'].sudo().search([ + ('slide_id', 'in', self.ids), + ('partner_id', '=', target_partner.id) + ]) + slide_partners_map = dict((sp.slide_id.id, sp) for sp in slide_partners) + for slide in self: + if not slide.question_ids: + gains = [0] + else: + gains = [slide.quiz_first_attempt_reward, + slide.quiz_second_attempt_reward, + slide.quiz_third_attempt_reward, + slide.quiz_fourth_attempt_reward] + result[slide.id] = { + 'quiz_karma_max': gains[0], # what could be gained if succeed at first try + 'quiz_karma_gain': gains[0], # what would be gained at next test + 'quiz_karma_won': 0, # what has been gained + 'quiz_attempts_count': 0, # number of attempts + } + slide_partner = slide_partners_map.get(slide.id) + if slide.question_ids and slide_partner: + if slide_partner.quiz_attempts_count: + result[slide.id]['quiz_karma_gain'] = gains[slide_partner.quiz_attempts_count] if slide_partner.quiz_attempts_count <= len(gains) else gains[-1] + result[slide.id]['quiz_attempts_count'] = slide_partner.quiz_attempts_count + if quiz_done or slide_partner.completed: + result[slide.id]['quiz_karma_won'] = gains[slide_partner.quiz_attempts_count-1] if slide_partner.quiz_attempts_count < len(gains) else gains[-1] + return result + # -------------------------------------------------- # Parsing methods # -------------------------------------------------- diff --git a/addons/website_slides/static/src/js/slides_share.js b/addons/website_slides/static/src/js/slides_share.js index 1dfaa3aee4196a9562e8360e6d04d9d57c955120..4ac2ee81809e6abe27bd8665d849269d50d447a3 100644 --- a/addons/website_slides/static/src/js/slides_share.js +++ b/addons/website_slides/static/src/js/slides_share.js @@ -129,13 +129,14 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({ * @param {Object} ev */ _onSlidesSocialShare: function (ev) { + var self = this; ev.preventDefault(); var key = $(ev.currentTarget).attr('social-key'); var popUpURL = $(ev.currentTarget).attr('href'); var popUp = window.open(popUpURL, 'Share Dialog', 'width=626,height=436'); $(window).on('focus', function () { if (popUp.closed) { - this._updateStatistics(key, this.slide_url); + self._updateStatistics(key, self.slide_url); $(window).off('focus'); } }); diff --git a/addons/website_slides/static/src/scss/slide_slide.scss b/addons/website_slides/static/src/scss/slide_slide.scss deleted file mode 100644 index 2aeac35b889684cb7c7ed9e2f2707d841ac02afc..0000000000000000000000000000000000000000 --- a/addons/website_slides/static/src/scss/slide_slide.scss +++ /dev/null @@ -1,156 +0,0 @@ -.o_wslides_slide_header { - background-color: #62495B; - height: 200px; -} - -.o_wslides_slide_header_container { - width: 1000px; - margin: 0 auto; - height: 100%; -} - -.o_wslides_slide_header_box{ - display: flex; - height: 100%; - width: 50%; - flex-direction: column; - justify-content: flex-end; - padding-bottom: 50px; - - a { - color: #fff; - font-size: 2.5rem; - text-decoration: none !important; - } -} - - -.o_wslides_slide_content_list { - position: absolute; - top: 140px; - left: 80px; - background-color: #fff; - height: 500px; - z-index: 200; -} - -.o_wslides_slide_list{ - background-color: #fff; - list-style: none; - height: 100%; - padding: 0; - overflow: auto; - border: 1px solid #ccc; - border-left: none; - box-sizing: border-box; - flex: 1; - - a { - text-decoration: none; - color: $text-muted; - } - - a .active{ - background-color: #eee !important; - } -} - -.o_wslides_slide_content_list_section{ - border-bottom: 1px solid #fff; - color: #9B9B9B; - text-transform: uppercase; - padding: 10px 15px; -} - -.o_wslides_slide_content_list_slide{ - color: #666666; - padding: 10px 15px; -} - -.o_wslides_slide_list_cell{ - word-wrap: none; - padding: 0.5rem 1rem;; - height: 40px; - box-sizing: border-box; - display: flex; - align-items: center; - text-decoration: none !important; -} - -.o_wslides_slide_list_cell:hover{ - background-color: #eee; - cursor: pointer; -} - -.o_wslides_slide_list_cell:active{ - background-color: #eee; - cursor: pointer; -} - - -.o_wslides_slide_content_list_header { - padding: 10px 15px; - font-size: 1.2rem; - background-color: #F7F7F7; - color: #6F6F6F; -} - -.o_wslides_slide_button { - color: #666; - text-decoration: none; - border:1px solid #B9B9B9; - padding: 5px 10px; - width: 50px; - text-align: center; - text-transform: uppercase; - margin: 0; - border-radius: 3px; -} - -.o_wslides_slide_button_fullscreen { - color: #666; - text-decoration: none; - border:1px solid #B9B9B9; - padding: 5px 10px; - text-align: center; - text-transform: uppercase; - margin: 0; - border-radius: 3px; -} - -.o_wslides_slide_button_done { - color: #fff; - text-transform: uppercase; - background-color: $primary; - text-decoration: none; - padding: 10px 15px; - width: 50px; - text-align: center; - border-radius: 3px; - margin: 0; -} - -.o_wslides_slide_title { - width: 60%; - display: flex; - align-items: center; - - h1 { - font-size: 1.5rem; - } - - .o_wslides_slide_points { - margin-left: 20px; - padding: 5px 10px; - background-color: #DC9D45; - border-radius: 10px; - color: #fff; - font-weight: bold; - } -} - -.o_wslides_slide_documentation_sidebar { - position: absolute; - top: 300px; - left: 30px; -} \ No newline at end of file diff --git a/addons/website_slides/static/src/scss/website_slides.scss b/addons/website_slides/static/src/scss/website_slides.scss index 35ffa9547d42b488dd03330eafb95d0553de0f6b..4e83de3b44de1deb1c8adabd9ad1870f3e9cc4a8 100644 --- a/addons/website_slides/static/src/scss/website_slides.scss +++ b/addons/website_slides/static/src/scss/website_slides.scss @@ -3,17 +3,11 @@ $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; // Common to new slides pages // ************************************************** -.o_wslides_container { - margin: auto; - width: 100%; - max-width: 1140px; - padding: 0px 32px 0px 32px; -} - .o_wslides_wrap { background-color: desaturate(map-get($grays, "200"), 80%); @@ -84,16 +78,13 @@ $gray-50: #f4f4f4 !default; .progress { overflow: visible; - margin-bottom: 0em; - height: 4px; .progress-bar { - background-color: #00A09D; + background-color: $primary; position: relative; - border-radius: 4px; span { - background-color: #00A09D; + background-color: $primary; position: absolute; bottom: -20px; font-size: 10px; @@ -275,6 +266,64 @@ $gray-50: #f4f4f4 !default; // New lesson page // ************************************************** +.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; + + .nav-tabs .nav-link { + border-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; + } + } + + .o_wslides_lesson_aside_list { + .o_wslides_lesson_aside_list_link { + text-decoration: none; + + &.active { + background-color: $gray-200; + } + } + } + } + + .o_wslides_lesson_content { + .o_wslides_lesson_nav { + .nav-link { + background-color: transparent; + border: 0; + border-bottom: 1px solid $border-color; + color: $gray-600; + + &.active { + border-bottom: 1px solid $success; + color: $gray-800; + } + } + } + } +} // Old brol to clean someday // ************************************************** diff --git a/addons/website_slides/static/src/xml/slide_quiz.xml b/addons/website_slides/static/src/xml/slide_quiz.xml index 6d778be9b2c34e2a2bda9965d7f19e13125decdf..f512985a3af3e243de91c37f18d1a2a4f6959c3b 100644 --- a/addons/website_slides/static/src/xml/slide_quiz.xml +++ b/addons/website_slides/static/src/xml/slide_quiz.xml @@ -69,8 +69,9 @@ <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 o_wslide_progress_bar"> - <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 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}%"/> </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> diff --git a/addons/website_slides/views/assets.xml b/addons/website_slides/views/assets.xml index 742bac7c8ea1beb98c5a74f3ab6ead8e2a5d8ad3..b4aa5dff9d2cbca4de82fbf4d2225ef0a5c81f3b 100644 --- a/addons/website_slides/views/assets.xml +++ b/addons/website_slides/views/assets.xml @@ -6,7 +6,6 @@ <xpath expr="//link[last()]" position="after"> <link rel="stylesheet" type="text/scss" href="/website_slides/static/src/scss/website_slides.scss" t-ignore="true"/> <link rel="stylesheet" type="text/scss" href="/website_slides/static/src/scss/website_slides_profile.scss"/> - <link rel="stylesheet" type="text/scss" href="/website_slides/static/src/scss/slide_slide.scss" t-ignore="true"/> <link rel="stylesheet" type="text/scss" href="/website_slides/static/src/scss/slides_slide_fullscreen.scss" t-ignore="true"/> </xpath> <xpath expr="//script[last()]" position="after"> diff --git a/addons/website_slides/views/website_slides_templates_course.xml b/addons/website_slides/views/website_slides_templates_course.xml index d9e7b8c48af984d3ed5c5a68a4bf28eeb026fd8e..f3bb816b327e409aecdc8bd8ad1efe9c9542ac49 100644 --- a/addons/website_slides/views/website_slides_templates_course.xml +++ b/addons/website_slides/views/website_slides_templates_course.xml @@ -29,7 +29,7 @@ </li> </ol> </nav> - <div class="col-md-6 col-xs-12 d-flex flex-row align-items-center"> + <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"/> diff --git a/addons/website_slides/views/website_slides_templates_homepage.xml b/addons/website_slides/views/website_slides_templates_homepage.xml index de99ad1eef83d7a7b566d2a4bb0869424c6373b8..108221a7ab02bc5c61131479d23c8927ce960cfe 100644 --- a/addons/website_slides/views/website_slides_templates_homepage.xml +++ b/addons/website_slides/views/website_slides_templates_homepage.xml @@ -260,8 +260,8 @@ <t t-if="channel.is_member and channel.completed"> <span class="badge badge-pill badge-success pull-right py-1 px-2"><i class="fa fa-check"/> Completed</span> </t> - <div t-elif="channel.is_member" class="progress w-50"> - <div class="progress-bar" role="progressbar" t-att-aria-valuenow="channel.completion" aria-valuemin="0" aria-valuemax="100" t-attf-style="width:#{channel.completion}%;"/> + <div t-elif="channel.is_member" class="progress w-50" style="height: 4px;"> + <div class="progress-bar rounded" role="progressbar" t-att-aria-valuenow="channel.completion" aria-valuemin="0" aria-valuemax="100" t-attf-style="width:#{channel.completion}%;"/> </div> <small t-else=""><b t-esc="channel.total_slides"/> steps</small> </div> diff --git a/addons/website_slides/views/website_slides_templates_lesson.xml b/addons/website_slides/views/website_slides_templates_lesson.xml index 12e9fad96114b992d33469a0e5811cc64e3a9fb0..7e4b97cfecc743b7c99e5430f53692a59b9c3b1f 100644 --- a/addons/website_slides/views/website_slides_templates_lesson.xml +++ b/addons/website_slides/views/website_slides_templates_lesson.xml @@ -2,432 +2,378 @@ <odoo><data> <!-- Slide: main template: detailed view --> -<template id="slide_detail_view" name="Slide Detailed View"> +<template id="slide_main" name="Slide Detailed View"> <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="wrap o_wslides_wrap"> - <div class="o_wslides_slide_header"> - <div class="o_wslides_slide_header_container"> - <div class="o_wslides_slide_header_box"> - <a t-attf-href="/slides/#{slug(slide.channel_id)}" t-field="slide.channel_id.name"/> - - <div t-if="slide.channel_id.channel_type == 'training'" class="d-flex align-items-end"> - <div class="progress"> - <div class="progress-bar" role="progressbar" - t-att-aria-valuenow="slide.channel_id.completion" aria-valuemin="0" aria-valuemax="100" - t-att-style="'width: %s' % (slide.channel_id.completion)"/> + <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 class="d-flex align-items-center"> + <div class="progress w-50" style="height: 8px;"> + <div class="progress-bar rounded" 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-warning' if slide.channel_id.completed else 'text-light')"></i> </div> - <i class="fa fa-trophy ml-2 mb-0 p-0" style="font-size:1.8rem; color: #cdcdcd;"></i> </div> </div> </div> </div> - <div t-if="slide.channel_id.channel_type == 'training'" class="o_wslides_slide_content_list"> - <ul class="o_wslides_slide_list"> - <li> - <div class="o_wslides_slide_content_list_header"> - Course content - </div> - </li> - <t t-set="i" t-value="0"/> - <t t-if="uncategorized_slides" t-call="website_slides.slide_detail_list_category_view"> - <t t-set="category_slide_ids" t-value="uncategorized_slides" /> + <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> + <div class="col-lg-9 o_wslides_lesson_content"> + <t t-call="website_slides.slide_content_detailed"/> + </div> + </div> + </div> + </div> + </t> +</template> + +<!-- 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> + </ul> + <div class="tab-content"> + <div role="tabpanel" id="related" class="tab-pane active"> + <ul class="list-unstyled card-body px-2 py-0"> + <t t-set="related_slides_list" t-value="list(related_slides)"/> + <t t-if="not related_slides_list"> + No presentation available. </t> - <t t-foreach="slide.channel_id.category_ids" t-as="category"> - <t t-call="website_slides.slide_detail_list_category_view"> - <t t-set="category_slide_ids" t-value="category.slide_ids"/> - </t> + <t t-else="" t-foreach="related_slides_list" t-as="aside_slide"> + <t t-call="website_slides.slide_aside_card"/> </t> </ul> </div> - <div class="o_wslides_slide_header_container d-flex justify-content-between mt-4 mb-3"> - <div class="o_wslides_slide_title"> - <h1 t-field="slide.name"/> - <span t-if="slide.question_ids" t-attf-class="o_wslides_slide_points ml-2 #{'quiz-points-won' if slide.id in user_progress and user_progress[slide.id].completed else ''}"> - <span t-if="slide.id in user_progress and user_progress[slide.id].quiz_attempts_count == 0" id="quiz-points" t-esc="slide.quiz_first_attempt_reward"/> - <span t-if="slide.id in user_progress and user_progress[slide.id].quiz_attempts_count == 1" id="quiz-points" t-esc="slide.quiz_second_attempt_reward"/> - <span t-if="slide.id in user_progress and user_progress[slide.id].quiz_attempts_count == 2" id="quiz-points" t-esc="slide.quiz_third_attempt_reward"/> - <span t-if="slide.id in user_progress and user_progress[slide.id].quiz_attempts_count > 2" id="quiz-points" t-esc="slide.quiz_fourth_attempt_reward"/> - points - </span> - </div> - <div> - <t t-if="previous_slide"> - <a class="o_wslides_slide_button" t-attf-href="/slides/slide/#{slug(previous_slide)}">Prev</a> + <div role="tabpanel" id="most_viewed" class="tab-pane"> + <ul class="list-unstyled card-body px-2 py-0"> + <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. </t> - <a t-if="slide.slide_type in ('webpage', 'video', 'document', 'iconographic') and not slide.question_ids and (slide.id in user_progress and not user_progress[slide.id].completed)" - t-att-href="'/slides/slide/%s/set_completed?%s' % (slide.id, 'next_slide_id=%s' % next_slide.id if next_slide else '')" - class="o_wslides_slide_button_done">Set Done</a> - <t t-if="next_slide"> - <a class="o_wslides_slide_button" t-attf-href="/slides/slide/#{slug(next_slide)}">Next</a> + <t t-else="" t-foreach="most_viewed_slides_list" t-as="aside_slide"> + <t t-call="website_slides.slide_aside_card"/> </t> - <a t-if="slide.channel_id.channel_type == 'training'" t-attf-href="/slides/slide/#{slug(slide)}?fullscreen=1" class="o_wslides_slide_button_fullscreen ml-2"><i class="fa fa-desktop mr-2"></i>Fullscreen</a> - </div> - </div> - <div class="o_wslides_slide_header_container mt16"> - <div class="row"> - <div style="width:100%;"> - <div class="o_w_slides_slide_detail_container" style="width: 100%;"> - <t t-if="slide.slide_type == 'infographic'"> - <img t-attf-src="/web/image/slide.slide/#{slide.id}/image" class="img-fluid" style="width:100%" alt="Slide image"/> - </t> - <div style="height: 600px;" t-if="slide.slide_type in ('presentation', 'document')" class="embed-responsive embed-responsive-4by3 embed-responsive-item mb8"> - <t t-raw="slide.embed_code"/> - </div> - <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="border border-light rounded"> - <div t-field="slide.html_content"/> - </div> - <t t-if="slide.question_ids" t-call="website_slides.lesson_content_quiz"/> - <div class="row mt-3"> - <div class="col-lg-6"> - <div clas="row"> - <div class="col-lg-8" t-if="slide.tag_ids"> - <t t-foreach="slide.tag_ids" t-as="slide_tag"> - <a t-attf-href="/slides/#{slug(slide.channel_id)}/tag/#{slug(slide_tag)}" t-attf-class="badge badge-secondary ml4 mb4 float-right #{search_tag and search_tag.id == slide_tag.id and 'badge-primary' ''}" t-field="slide_tag.name"/> - </t> - </div> - </div> - </div> - </div> - <div class="row"> - <div class="col-md-8 col-12"> - <div class="float-left"> - <a t-attf-href="/slides/#{slug(slide.channel_id)}" t-attf-title="Channel #{slide.channel_id.name}" t-attf-aria-label="Channel #{slide.channel_id.name}"> - <i class="fa fa-circle-o fa-5x" style="color: #875A7B;font-weight: bold;"></i> - </a> - </div> - <div style="margin-left: 80px"> - <p> - <a t-attf-href="/slides/#{slug(slide.channel_id)}" t-esc="slide.channel_id.name"/> - <t t-if="slide and slide.category_id"> - <span> / </span> - <a t-attf-href="/slides/#{slug(slide.channel_id)}/category/#{slug(slide.category_id)}" t-esc="slide.category_id.name"/> - </t> - </p> - <div> - <t t-call="website_mail.follow"> - <t t-set="email" t-value="user.email"/> - <t t-set="object" t-value="slide.channel_id"/> - </t> - </div> - </div> - </div> - <div class="col-md-4 d-none d-md-block"> - <div class="text-right"> - <b class="h3 text-muted"><t t-esc="slide.total_views"/></b> <span class="text-muted small">views</span> - </div> - <!-- progress bar of like/dislike --> - <div class="progress mb0" style="height: 2px;" t-if="slide.likes + slide.dislikes > 0"> - <div class="progress-bar" role="progressbar" t-attf-aria-valuenow="#{slide.likes}" aria-valuemin="0" - t-attf-aria-valuemax="#{slide.likes + slide.dislikes}" - t-attf-style="width: #{(slide.likes*100)/(slide.likes + slide.dislikes)}%;"> - <span class="sr-only"><t t-esc="slide.likes"/> Likes</span> - </div> - </div> - <div class="progress mb0" style="height: 2px;" t-if="slide.likes + slide.dislikes == 0"> - <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"> - <span class="sr-only"><t t-esc="slide.likes"/> Likes</span> - </div> - </div> - - <div class="mt8"> - <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="slide"/> - <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> - </div> - - <!-- LikeButton widget --> - <div t-if="slide.channel_id.channel_type == 'documentation' and slide.channel_id.allow_comment" class="text-muted mt4"> - <div class="float-right mb16 text-right o_wslides_js_slide_like"> - <span - class="o_wslides_js_slide_like_up" - t-att-data-slide-id="slide.id" - tabindex="0" - data-toggle="popover"> - <i class="fa fa-thumbs-up fa-1x" role="img" aria-label="Likes" title="Likes"/> - <span t-esc="slide.likes"/> - </span> - <span - class="o_wslides_js_slide_like_down" - t-att-data-slide-id="slide.id" - tabindex="0" - data-toggle="popover"> - <i class="fa fa-thumbs-down fa-1x" role="img" aria-label="Dislikes" title="Dislikes"/> - <span t-esc="slide.dislikes"/> - </span> - </div> - </div> - </div> - </div> - <div class="mt8 mb32"> - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item"> - <a href="#about" aria-controls="about" t-attf-class="nav-link#{not comments and ' active' or ''}" role="tab" data-toggle="tab"> - <i class="fa fa-home"></i> About - </a> - </li> - <li class="nav-item"> - <a href="#share" aria-controls="share" class="nav-link" role="tab" data-toggle="tab"> - <i class="fa fa-share-alt"></i> Share - </a> - </li> - <li t-if="slide.channel_id.allow_comment" class="nav-item"> - <a href="#discuss" aria-controls="discuss" t-attf-class="nav-link#{comments and ' active' or ''}" role="tab" data-toggle="tab"> - <i class="fa fa-comments-o"></i> Comments - </a> - </li> - <li t-if="not slide.channel_id.allow_comment" class="nav-item"> - <a href="#discuss" aria-controls="discuss" t-attf-class="nav-link#{comments and ' active' or ''}" role="tab" data-toggle="tab"> - <i class="fa fa-star"></i> Ratings - </a> - </li> - <li class="nav-item"> - <a href="#transcript" aria-controls="transcript" class="nav-link" role="tab" data-toggle="tab"> - <i class="fa fa-align-justify"></i> Transcript - </a> - </li> - <li class="nav-item"> - <a href="#statistic" aria-controls="statistic" class="nav-link" role="tab" data-toggle="tab"> - <i class="fa fa-bar-chart"></i> Statistics - </a> - </li> - <li class="nav-item" t-if="slide.link_ids"> - <a href="#external-links" aria-controls="external-links" class="nav-link" role="tab" data-toggle="tab"> - <i class="fa fa-link"></i> External Links - </a> - </li> - </ul> - <div class="tab-content" style="padding: 20px 5px 5px 5px; word-wrap: break-word;"> - <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> - <div role="tabpanel" class="tab-pane fade" t-if="slide.website_published" id="share"> - <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> - <div role="tabpanel" class="tab-pane fade" t-if="not slide.website_published" id="share"> - <h4><i class="fa fa-info-circle"></i> - The social sharing module will be unlocked when a moderator will allow your publication. - </h4> - </div> - <div role="tabpanel" t-att-class="comments and 'tab-pane fade in show active' or 'tab-pane fade'" id="discuss"> - <t t-call="portal.message_thread"> - <t t-set="object" t-value="slide"/> - <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="slide.channel_id.channel_type == 'training'"/> - </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> - </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"> - <h4 class="mt0 oe_slides_statistics_title">Views</h4> - <ul class="list-group"> - <li class="list-group-item"> - <span class="badge badge-pill"><t t-esc="slide.total_views"/></span> - <i class="fa fa-play"></i> Total Views - </li> - <li class="list-group-item"> - <span class="badge badge-pill"><t t-esc="slide.slide_views"/></span> - <i class="fa fa-circle-o"></i> Website Views - </li> - <li class="list-group-item" t-if="not slide.document_id"> - <span class="badge badge-pill"><t t-esc="slide.public_views"/></span> - <i class="fa fa-code"></i> Public Views - </li> - </ul> - </div> - - <div class="col-lg-4"> - <h4 class="mt0 oe_slides_statistics_title">Actions</h4> - <ul class="list-group"> - <li class="list-group-item"> - <span class="badge badge-pill" id="total-share">0</span> - <i class="fa fa-share-alt"></i> Social Shares - </li> - <li class="list-group-item"> - <span class="badge badge-pill"><t t-esc="slide.likes"/></span> - <i class="fa fa-thumbs-up"></i> Likes - </li> - <li class="list-group-item"> - <span class="badge badge-pill"><t t-esc="slide.dislikes"/></span> - <i class="fa fa-thumbs-down"></i> Dislikes - </li> - <li class="list-group-item"> - <span class="badge badge-pill"><t t-esc="len(slide.website_message_ids)"/></span> - <i class="fa fa-comments-o"></i> Comments - </li> - </ul> - </div> - - <div class="col-lg-4"> - <h4 class="mt0 oe_slides_statistics_title">Share count</h4> - <ul class="list-group"> - <li class="list-group-item"> - <span class="badge badge-pill" id="facebook-badge">0</span> - <i class="fa fa-facebook-square"></i> Facebook - </li> - <li class="list-group-item"> - <span class="badge badge-pill" id="twitter-badge">0</span> - <i class="fa fa-twitter-square"></i> Twitter - </li> - <li class="list-group-item"> - <span class="badge badge-pill" id="linkedin-badge">0</span> - <i class="fa fa-linkedin-square"></i> LinkedIn - </li> - <li class="list-group-item"> - <span class="badge badge-pill" id="google-badge">0</span> - <i class="fa fa-google-plus-square"></i> Google+ - </li> - </ul> - </div> - </div> - <div class="row" t-if="not slide.document_id and slide.embedcount_ids"> - <div class="col-lg-12"> - <h4 class="mt0"> Embeds - <span class="badge badge-pill float-right"> - <t t-esc="len(slide.embedcount_ids)"/> - </span> - </h4> - <ul class="list-group" style="height: 150px;overflow: auto;"> - <li class="list-group-item" t-foreach="slide.embedcount_ids" t-as="count"> - <span class="badge badge-pill"><t t-esc="count.count_views"/></span> - <t t-esc="count.url"/> - </li> - </ul> - </div> - </div> - </div> - <div role="tabpanel" class="tab-pane fade oe_slides_transcript" id="external-links" t-if="slide.link_ids"> - <ul> - <t t-foreach="slide.link_ids" t-as="link"> - <li><a t-att-href="link.link" target="_blank"><t t-esc="link.name"/></a></li> - </t> - </ul> - </div> - </div> - </div> - </div> - </div> - <div t-if="slide.channel_id.channel_type == 'documentation'" class="col-xl-4 col-lg-4 col-md-12 col-12"> - <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> - </ul> - <div class="tab-content"> - <div role="tabpanel" id="related" class="tab-pane active mt4"> - <div class="card"> - <ul class="list-unstyled card-body"> - <t t-set="related_slides_list" t-value="list(related_slides)"/> - <t t-if="not related_slides_list"> - No presentation available. - </t> - <t t-else="" t-foreach="related_slides_list" t-as="related_slide"> - <t t-call="website_slides.related_slides"/> - </t> - </ul> - </div> - </div> - <div role="tabpanel" id="most_viewed" class="tab-pane mt4"> - <div class="card"> - <ul class="list-unstyled card-body"> - <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. - </t> - <t t-else="" t-foreach="most_viewed_slides_list" t-as="related_slide"> - <t t-call="website_slides.related_slides"/> - </t> - </ul> - </div> - </div> - </div> - </div> + </ul> </div> </div> + </div> +</template> + +<!-- 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"> + <t t-esc="aside_slide.total_views"/> Views • <timeago class="timeago" t-att-datetime="aside_slide.create_date"></timeago> + </small> </div> - </t> + </li> +</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"> + <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"/> + </t> + <t t-foreach="slide.channel_id.category_ids" t-as="category"> + <t t-call="website_slides.slide_aside_training_category"> + <t t-set="category_slide_ids" t-value="category.slide_ids"/> + </t> + </t> + </ul> + </div> </template> -<template id="slide_detail_list_category_view" name="Category item for the slide detailed view list"> - <a data-toggle="collapse" t-att-href="('#collapse-%s') % (category.id if category else 0)" role="button" aria-expanded="true" t-att-aria-controls="('collapse-%s') % (category.id if category else 0)"> - <li class="o_wslides_slide_content_list_section"> +<template id="slide_aside_training_category" name="Category item for the slide detailed view list"> + <li class="mt-3"> + <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" + t-att-aria-controls="('collapse-%s') % (category.id if category else 0)"> <t t-if="category"> - <span t-field="category.name"/> + <span t-field="category.name" class="text-uppercase"/> </t> <t t-else=""> - <span>Uncategorized</span> + <span class="text-uppercase">Uncategorized</span> </t> - </li> - </a> - <ul class="collapse show p-0 m-0" t-att-id="('collapse-%s') % (category.id if category else 0)" > - <t t-foreach="category_slide_ids" t-as="course_slide"> - <li class="o_wslides_slide_content_list_slide"> - <a t-attf-href="/slides/slide/#{slug(course_slide)}" t-att-index="i" t-att-slide_id="course_slide.id"> - <div t-attf-index="#{i}" t-attf-slide_id="#{course_slide.id}" t-attf-class="#{'active' if slide.id == course_slide.id else ''} d-flex justify-content-between"> - <div> - <t t-call="website_slides.slide_icon"> - <t t-set="slide" t-value="course_slide" /> - </t> - <t t-esc="course_slide.name"/> - </div> - <div class="o_wslides_slides_list_slide_controls mr-2"> - <i t-attf-id="check-#{course_slide.id}" t-if="course_slide.id in user_progress and not user_progress[course_slide.id].completed" class="check-done fa fa-check-circle text-muted mr-1"></i> - <i t-attf-id="check-#{course_slide.id}" t-if="course_slide.id in user_progress and user_progress[course_slide.id].completed" class="check-done text-primary fa fa-check-circle mr-1"></i> - </div> - </div> - </a> - <ul t-if="course_slide.link_ids" class="list-group"> - <t t-foreach="course_slide.link_ids" t-as="resource"> - <a t-attf-href="#{resource.link}" target="new"> - <li><div><i class="fa fa-link"></i><span t-field="resource.link"/></div></li> + </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"> + <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_max')"/> + </span> + </a> + <ul t-if="aside_slide.link_ids or aside_slide.question_ids" class="list-group ml-5 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> + </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> - </t> - </ul> + </ul> + </li> + </t> + </ul> + </li> +</template> + +<!-- 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"> + <div class="d-flex align-items-center"> + <h5 class="m-0 ml-2"> + <t t-call="website_slides.slide_icon"/> + <span t-field="slide.name"/> + </h5> + <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')"> + <i class="fa fa-check-circle"/> + <t t-esc="channel_progress[slide.id].get('quiz_karma_won', 0)"/> + </span> + <span t-else="" t-esc="channel_progress[slide.id].get('quiz_karma_gain', 0)"/> + <span>XP</span> + </span> + </div> + <div class="ml-auto"> + <a class="btn btn-light border" role="button" + t-att-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</a> + <a class="btn btn-primary border text-white" role="button" + t-att-disabled="'disabled' if slide.question_ids or channel_progress[slide.id].get('completed') else None" + t-att-href="None if (channel_progress[slide.id].get('completed') or slide.question_ids) else '/slides/slide/%s/set_completed?%s' % (slide.id, 'next_slide_id=%s' % (next_slide.id) if next_slide else '')"> + Set Done + </a> + <a class="btn btn-light border" role="button" + t-att-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></a> + <a class="btn btn-light border ml-2" role="button" + t-att-disabled="'disabled' if slide.channel_id.channel_type != 'training' else None" + t-att-href="'/slides/slide/%s?fullscreen=1' % (slug(slide))"><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> + </div> + </div> + <div class="row 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;"> + <t t-raw="slide.embed_code"/> + </div> + <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-field="slide.html_content"/> + </div> + </div> + <div class="row" t-if="slide.question_ids"> + <t t-call="website_slides.lesson_content_quiz"/> + </div> + <div class="row mt-3 mb-3"> + <div class="col d-flex align-items-start"> + <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> + + <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 class="o_wslides_js_slide_like_up" 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 class="o_wslides_js_slide_like_down ml-3" 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> + </div> + <div class="row mb-5"> + <ul class="col-lg-12 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 + </a> + </li> + <li t-if="slide.channel_id.allow_comment" class="nav-item"> + <a href="#discuss" aria-controls="discuss" class="nav-link" role="tab" data-toggle="tab"> + <i class="fa fa-comments-o"></i> Comments + </a> </li> - <t t-set="i" t-value="i+1"/> - </t> - </ul> + <li class="nav-item"> + <a href="#transcript" aria-controls="transcript" class="nav-link" role="tab" data-toggle="tab"> + <i class="fa fa-align-justify"></i> Transcript + </a> + </li> + <li class="nav-item"> + <a href="#statistic" aria-controls="statistic" class="nav-link" role="tab" data-toggle="tab"> + <i class="fa fa-bar-chart"></i> Statistics + </a> + </li> + <li class="nav-item"> + <a href="#share" aria-controls="share" class="nav-link" role="tab" data-toggle="tab"> + <i class="fa fa-share-alt"></i> Share + </a> + </li> + </ul> + <div class="col 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> + <div role="tabpanel" t-att-class="comments and 'tab-pane fade in show active' or 'tab-pane fade'" id="discuss"> + <t t-call="portal.message_thread"> + <t t-set="object" t-value="slide"/> + <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="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> + </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> + <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> + <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> + </div> + </div> + <div role="tabpanel" class="tab-pane fade" t-if="slide.website_published" id="share"> + <h4 t-if="not slide.website_published"><i class="fa fa-info-circle"></i> + The social sharing module will be unlocked when a moderator will allow your publication. + </h4> + <t t-if="slide.website_published"> + <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> + </t> + </div> + </div> + </div> </template> <!-- 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"> - <div class="o_wslides_js_lesson_quiz" + <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 slide.id in user_progress" - t-att-data-completed="slide.id in user_progress and user_progress[slide.id].completed" + t-att-data-readonly="not channel_progress[slide.id]" + t-att-data-completed="channel_progress[slide.id].get('completed')" 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" @@ -468,21 +414,6 @@ </div> </template> -<!-- Slide sub-template: display an item in a list of related slides (Related, Most Viewed, ...) --> -<template id="related_slides" name="Related Slide"> - <li class="media mt-3"> - <a t-attf-href="/slides/slide/#{slug(related_slide)}" class="mr-3"> - <img class="oe_slides_apart_small" t-attf-src="/web/image/slide.slide/#{related_slide.id}/image_small" alt="related_slide.name"/> - </a> - <div class="media-body"> - <a t-attf-href="/slides/slide/#{slug(related_slide)}"><h6 t-esc="related_slide.name" class="mb-1"/></a> - <small class="text-muted"> - <t t-esc="related_slide.total_views"/> Views . <timeago class="timeago" t-att-datetime="related_slide.create_date"></timeago> - </small> - </div> - </li> -</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> diff --git a/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml b/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml index a505f8c78e02d18fe5f58a1ac20a97dafb039dbf..1361559c23f62373427a0e8d3259c959bb90543b 100644 --- a/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml +++ b/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml @@ -73,14 +73,14 @@ <li t-att-index="i" t-att-data-slide-id="course_slide.id" t-attf-class="#{'active' if slide.id == course_slide.id else ''}"> <span> <span class="o_wslides_top_line"></span> - <i t-attf-id="check-#{course_slide.id}" t-if="not course_slide.id in user_progress or not user_progress[course_slide.id].completed" class="check-done fa fa-circle-thin"></i> - <i t-attf-id="check-#{course_slide.id}" t-if="course_slide.id in user_progress and user_progress[course_slide.id].completed" class="check-done o_wslides_slide_completed fa fa-check-circle"></i> + <i t-attf-id="check-#{course_slide.id}" t-if="not channel_progress[course_slide.id].get('completed')" class="check-done fa fa-circle-thin"></i> + <i t-attf-id="check-#{course_slide.id}" t-if="channel_progress[course_slide.id].get('completed')" class="check-done o_wslides_slide_completed fa fa-check-circle"></i> <span class="o_wslides_bottom_line"></span> </span> <a t-att-index="i" t-att-data-slide-id="course_slide.id"> <div t-attf-index="#{i}" t-att-data-slug="slug(course_slide)" - t-att-data-done="course_slide.id in user_progress and user_progress[course_slide.id].completed" + t-att-data-done="channel_progress[course_slide.id].get('completed')" t-att-data-id="course_slide.id" t-att-data-readonly="not course_slide.channel_id.is_member" t-att-data-name="course_slide.name" diff --git a/addons/website_slides_survey/__manifest__.py b/addons/website_slides_survey/__manifest__.py index 71d793d7e6a0f1045dfea633a21eed18c3058d2b..e54847bb6b573b20ef7cf8e6cf312cf89e52bc3a 100644 --- a/addons/website_slides_survey/__manifest__.py +++ b/addons/website_slides_survey/__manifest__.py @@ -14,7 +14,7 @@ 'views/slide_channel_views.xml', 'views/slide_slide_views.xml', 'views/website_slides_templates_course.xml', - 'views/website_slides_templates.xml', + 'views/website_slides_templates_lesson.xml', 'views/website_slides_templates_homepage.xml', 'views/survey_templates.xml', 'views/website_profile.xml', diff --git a/addons/website_slides_survey/views/website_slides_templates.xml b/addons/website_slides_survey/views/website_slides_templates_lesson.xml similarity index 86% rename from addons/website_slides_survey/views/website_slides_templates.xml rename to addons/website_slides_survey/views/website_slides_templates_lesson.xml index 84d9b348fecd19ded3c3ba77bce9bdaca433716b..8d6a4d1f1231d5c55e0c68ce2344b9e4f476fc8f 100644 --- a/addons/website_slides_survey/views/website_slides_templates.xml +++ b/addons/website_slides_survey/views/website_slides_templates_lesson.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <odoo> <data> - <template id="slide_detail_view_inherit_survey" inherit_id="website_slides.slide_detail_view"> - <xpath expr="//div[hasclass('o_w_slides_slide_detail_container')]/div[hasclass('row')]" position="before"> + <template id="slide_content_detailed" inherit_id="website_slides.slide_content_detailed"> + <xpath expr="//div[hasclass('o_wslides_lesson_content_type')]" position="inside"> <t t-if="not test_entry" t-set="begin_certification_label" t-value="'Begin certification'" /> <t t-if="test_entry" t-set="begin_certification_label" t-value="'Test certification'" /> <div t-if="slide.slide_type == 'certification' and not quizz_passed" class="mb8">