summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorPatrick Hoste <pko@odoo.com>2020-08-11 07:21:56 +0000
committerThibault Delavallée <tde@odoo.com>2020-08-11 10:21:30 +0000
commit255bb3abf38b03145b7d025fb8546530db4a7549 (patch)
treef3df1de9f81ab147c5915f8076858dddb30d465a /addons
parent2e7c398fb3dc8f423f55f23fd688459f09023d4d (diff)
[REF] website_slides: improve course frontend page
PURPOSE Improve onboarding and user experience and course frontend SPECIFICATIONS Overall improvements and onboarding : * new and improved default images for both course types; * preview / free preview badge update; * copy writing and spacing update; * allow to specifically choose a slide to promote. Display promoted slide is not optional anymore as configured in backend; * display a sample of lessons if no lesson in a course; LINKS Task ID-2241513 PR #55698
Diffstat (limited to 'addons')
-rw-r--r--addons/website_sale_slides/views/website_slides_templates.xml14
-rw-r--r--addons/website_slides/controllers/main.py8
-rw-r--r--addons/website_slides/models/slide_channel.py19
-rw-r--r--addons/website_slides/static/src/img/channel-training-default.jpgbin86095 -> 66505 bytes
-rw-r--r--addons/website_slides/views/slide_channel_views.xml4
-rw-r--r--addons/website_slides/views/website_slides_templates_course.xml114
6 files changed, 133 insertions, 26 deletions
diff --git a/addons/website_sale_slides/views/website_slides_templates.xml b/addons/website_sale_slides/views/website_slides_templates.xml
index 23fac6fe918..6d3e5bd3fe9 100644
--- a/addons/website_sale_slides/views/website_slides_templates.xml
+++ b/addons/website_sale_slides/views/website_slides_templates.xml
@@ -32,6 +32,20 @@
</xpath>
</template>
+<!-- Tweak "preview" badge: display Free Preview if payment-based course -->
+<template id="course_slides_list_slide"
+ name="Slide template for a training channel (Sale)"
+ inherit_id="website_slides.course_slides_list_slide">
+ <xpath expr="//a[@t-if='channel.can_upload']/span/span" position="replace">
+ <span t-if="channel.enroll == 'payment'">Free Preview</span>
+ <span t-else="">Preview</span>
+ </xpath>
+ <xpath expr="//t[@t-elif='slide.is_preview and not channel.is_member']/span/span" position="replace">
+ <span t-if="channel.enroll == 'payment'">Free Preview</span>
+ <span t-else="">Preview</span>
+ </xpath>
+</template>
+
<!-- FULLSCREEN -->
<template id="slide_fullscreen" inherit_id="website_slides.slide_fullscreen">
<xpath expr="//div[hasclass('o_wslides_fs_main')]" position="attributes">
diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py
index 68648b7ff9d..edad9c10419 100644
--- a/addons/website_slides/controllers/main.py
+++ b/addons/website_slides/controllers/main.py
@@ -406,7 +406,8 @@ class WebsiteSlides(WebsiteProfile):
# sorting criterion
if channel.channel_type == 'documentation':
- actual_sorting = sorting if sorting and sorting in request.env['slide.slide']._order_by_strategy else channel.promote_strategy
+ default_sorting = 'latest' if channel.promote_strategy in ['specific', 'none', False] else channel.promote_strategy
+ actual_sorting = sorting if sorting and sorting in request.env['slide.slide']._order_by_strategy else default_sorting
else:
actual_sorting = 'sequence'
order = request.env['slide.slide']._order_by_strategy[actual_sorting]
@@ -489,7 +490,10 @@ class WebsiteSlides(WebsiteProfile):
# of them but unreachable ones won't be clickable (+ slide controller will crash anyway)
# documentation mode may display less slides than content by category but overhead of
# computation is reasonable
- values['slide_promoted'] = request.env['slide.slide'].sudo().search(domain, limit=1, order=order)
+ if channel.promote_strategy == 'specific':
+ values['slide_promoted'] = channel.sudo().promoted_slide_id
+ else:
+ values['slide_promoted'] = request.env['slide.slide'].sudo().search(domain, limit=1, order=order)
limit_category_data = False
if channel.channel_type == 'documentation':
diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py
index b03b1a942e5..426265a2bd3 100644
--- a/addons/website_slides/models/slide_channel.py
+++ b/addons/website_slides/models/slide_channel.py
@@ -96,8 +96,8 @@ class Channel(models.Model):
description_short = fields.Text('Short Description', translate=True, help="The description that is displayed on the course card")
description_html = fields.Html('Detailed Description', translate=tools.html_translate, sanitize_attributes=False, sanitize_form=False)
channel_type = fields.Selection([
- ('documentation', 'Documentation'), ('training', 'Training')],
- string="Course type", default="documentation", required=True)
+ ('training', 'Training'), ('documentation', 'Documentation')],
+ string="Course type", default="training", required=True)
sequence = fields.Integer(default=10, help='Display order')
user_id = fields.Many2one('res.users', string='Responsible', default=lambda self: self.env.uid)
color = fields.Integer('Color Index', default=0, help='Used to decorate kanban view')
@@ -115,8 +115,17 @@ class Channel(models.Model):
promote_strategy = fields.Selection([
('latest', 'Latest Published'),
('most_voted', 'Most Voted'),
- ('most_viewed', 'Most Viewed')],
- string="Featured Content", default='latest', required=True)
+ ('most_viewed', 'Most Viewed'),
+ ('specific', 'Specific'),
+ ('none', 'None')],
+ string="Promoted Content", default='latest', required=False,
+ help='Depending the promote strategy, a slide will appear on the top of the course\'s page :\n'
+ ' * Latest Published : the slide created last.\n'
+ ' * Most Voted : the slide which have to most vote.\n'
+ ' * Most Viewed ; the slide which have been viewed the most.\n'
+ ' * Specific : You choose the slide to appear.\n'
+ ' * None : There won\'t be any slide showing.\n')
+ promoted_slide_id = fields.Many2one('slide.slide', string='Promoted Slide')
access_token = fields.Char("Security Token", copy=False, default=_default_access_token)
nbr_presentation = fields.Integer('Presentations', compute='_compute_slides_statistics', store=True)
nbr_document = fields.Integer('Documents', compute='_compute_slides_statistics', store=True)
@@ -131,7 +140,7 @@ class Channel(models.Model):
rating_avg_stars = fields.Float("Rating Average (Stars)", compute='_compute_rating_stats', digits=(16, 1), compute_sudo=True)
# configuration
allow_comment = fields.Boolean(
- "Allow rating on Course", default=False,
+ "Allow rating on Course", default=True,
help="If checked it allows members to either:\n"
" * like content and post comments on documentation course;\n"
" * post comment and review on training course;")
diff --git a/addons/website_slides/static/src/img/channel-training-default.jpg b/addons/website_slides/static/src/img/channel-training-default.jpg
index 5d8b9093590..6d1bf29387a 100644
--- a/addons/website_slides/static/src/img/channel-training-default.jpg
+++ b/addons/website_slides/static/src/img/channel-training-default.jpg
Binary files differ
diff --git a/addons/website_slides/views/slide_channel_views.xml b/addons/website_slides/views/slide_channel_views.xml
index c15edb495a9..e656c5e8309 100644
--- a/addons/website_slides/views/slide_channel_views.xml
+++ b/addons/website_slides/views/slide_channel_views.xml
@@ -107,6 +107,10 @@
<field name="visibility" widget="radio"/>
<field name="promote_strategy" widget="radio"
attrs="{'invisible': [('channel_type', '=', 'training')]}"/>
+ <field name="promoted_slide_id"
+ attrs="{'invisible': ['|', ('channel_type', '=', 'training'), ('promote_strategy', '!=', 'specific')],
+ 'required': [('channel_type', '!=', 'training'), ('promote_strategy', '=', 'specific')]}"
+ domain="[('channel_id', '=', active_id), ('is_category', '=', False)]"/>
</group>
</group>
<div attrs="{'invisible': [('enroll', '!=', 'invite')]}">
diff --git a/addons/website_slides/views/website_slides_templates_course.xml b/addons/website_slides/views/website_slides_templates_course.xml
index e6e547b9ba1..a294b9bd3cb 100644
--- a/addons/website_slides/views/website_slides_templates_course.xml
+++ b/addons/website_slides/views/website_slides_templates_course.xml
@@ -118,7 +118,11 @@
<!-- ==== Header Left ==== -->
<div class="col-12 col-md-4 col-lg-3">
<div class="d-flex align-items-end justify-content-around h-100">
- <div t-field="channel.image_1920" t-options='{"widget": "image", "class": "o_wslides_course_pict d-inline-block mb-2 mt-3 my-md-0"}' class="h-100"/>
+ <div t-if="channel.image_1920" t-field="channel.image_1920" t-options='{"widget": "image", "class": "o_wslides_course_pict d-inline-block mb-2 mt-3 my-md-0"}' class="h-100"/>
+ <div t-else="" class="h-100">
+ <img t-att-src="'/website_slides/static/src/img/channel-%s-default.jpg' % ('training' if channel.channel_type == 'training' else 'documentation')"
+ class="o_wslides_course_pict d-inline-block mb-2 mt-3 my-md-0"/>
+ </div>
</div>
</div>
@@ -128,7 +132,7 @@
<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">
+ <div t-if="channel.channel_type == 'documentation'" class="d-flex mb-md-5">
<button role="button" class="btn text-white pl-0" title="Share Channel"
aria-label="Share Channel"
data-toggle="modal" t-att-data-target="'#slideChannelShareModal_%s' % channel.id">
@@ -206,7 +210,7 @@
href="#"
t-att-data-channel-id="channel.id"
t-att-data-channel-tag-ids="channel.tag_ids.ids">
- <i class="fa fa-plus mr-1"/><span>Add Tag</span>
+ <span>Add Tag</span>
</a>
</div>
<t t-if="channel.channel_type == 'training'" t-call="website_slides.course_slides_list"/>
@@ -386,12 +390,12 @@
<li t-if="category['total_slides'] or channel.can_publish" t-att-class="'o_wslides_slide_list_category o_wslides_js_list_item mb-2' if category_id else 'mt-4'" t-att-data-slide-id="category_id" 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 mt8 %s' % ('o_wslides_js_category bg-white shadow-sm border-bottom-0' if category_id and channel.can_upload else 'border-0 py-1')">
+ t-att-class="'o_wslides_slide_list_category_header position-relative d-flex justify-content-between align-items-center mt8 %s %s' % ('bg-white shadow-sm border-bottom-0' if category_id else 'border-0', 'o_wslides_js_category py-0' if channel.can_upload else 'py-2')">
<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-field="category['category'].name"/>
+ <span t-if="category_id" t-field="category['category'].name"/>
<small t-if="not category['total_slides'] and category_id" class="ml-1 text-muted"><b>(empty)</b></small>
</div>
<div t-if="category_id" class="o_text_link d-flex border-left">
@@ -422,7 +426,7 @@
</t>
</ul>
<div t-if="channel.can_upload" class="o_wslides_content_actions btn-group">
- <a class="o_wslides_js_slide_upload mr-1 border btn btn-light bg-white"
+ <a class="o_wslides_js_slide_upload mr-1 border btn btn-primary"
role="button"
aria-label="Upload Presentation"
href="#"
@@ -435,10 +439,83 @@
href="#" role="button"
groups="website_slides.group_website_slides_officer"><i class="fa fa-folder-o mr-1"/><span>Add Section</span></a>
</div>
+ <t t-if="not channel.slide_ids and channel.can_publish">
+ <t t-call="website_slides.course_slides_list_sample"/>
+ </t>
</div>
<div t-field="channel.description_html"/>
</template>
+<template id="course_slides_list_sample" name="Course Sample Content">
+ <ul class="list-unstyled mt-3" style="opacity: 50%;">
+ <li class="o_wslides_slide_list_category mb-2">
+ <div class="o_wslides_slide_list_category_header position-relative d-flex justify-content-between align-items-center mt8 bg-white shadow-sm border-bottom-0 py-2">
+ <div class="d-flex align-items-center pl-3">
+ <span class="text-muted">Common tasks for a computer scientist</span>
+ </div>
+ </div>
+ <ul class="list-unstyled pb-1 border-top">
+ <li class="o_wslides_slides_list_slide bg-white-50 border-top-0 d-flex align-items-center pl-2 py-1 pr-2">
+ <i class="fa fa-file-text py-2 mx-2"/>
+ <div class="text-truncate mr-auto">
+ <span>Asking Question</span>
+ </div>
+ <div class="d-flex flex-row">
+ <span class="badge font-weight-bold px-2 py-1 m-1 badge-warning">
+ <i class="fa fa-fw fa-flag"/> 10 xp
+ </span>
+ </div>
+ </li>
+ <li class="o_wslides_slides_list_slide bg-white-50 border-top-0 d-flex align-items-center pl-2 py-1 pr-2">
+ <i class="fa fa-question-circle py-2 mx-2"/>
+ <div class="text-truncate mr-auto">
+ <span>Asking the right question</span>
+ </div>
+ </li>
+ <li class="o_wslides_slides_list_slide bg-white-50 border-top-0 d-flex align-items-center pl-2 py-1 pr-2">
+ <i class="fa fa-file-pdf-o py-2 mx-2"/>
+ <div class="text-truncate mr-auto">
+ <span>Answering Questions</span>
+ </div>
+ <div class="d-flex flex-row">
+ <span class="badge badge-info badge-arrow-right font-weight-normal px-2 py-1 m-1">New</span>
+ </div>
+ </li>
+ </ul>
+ </li>
+ <li class="o_wslides_slide_list_category mb-2">
+ <div class="o_wslides_slide_list_category_header position-relative d-flex justify-content-between align-items-center mt8 bg-white shadow-sm border-bottom-0 py-2">
+ <div class="d-flex align-items-center pl-3">
+ <span class="text-muted">Parts of computer science</span>
+ </div>
+ </div>
+ <ul class="list-unstyled pb-1 border-top">
+ <li class="o_wslides_slides_list_slide bg-white-50 border-top-0 d-flex align-items-center pl-2 py-1 pr-2">
+ <i class="fa fa-file-pdf-o py-2 mx-2"/>
+ <div class="text-truncate mr-auto">
+ <span>Mathematics</span>
+ </div>
+ </li>
+ <li class="o_wslides_slides_list_slide bg-white-50 border-top-0 d-flex align-items-center pl-2 py-1 pr-2">
+ <i class="fa fa-file-pdf-o py-2 mx-2"/>
+ <div class="text-truncate mr-auto">
+ <span>Science</span>
+ </div>
+ </li>
+ <li class="o_wslides_slides_list_slide bg-white-50 border-top-0 d-flex align-items-center pl-2 py-1 pr-2">
+ <i class="fa fa-play py-2 mx-2"/>
+ <div class="text-truncate mr-auto">
+ <span>Logic</span>
+ </div>
+ <div class="d-flex flex-row">
+ <span class="badge badge-success font-weight-normal px-2 py-1 m-1">Preview</span>
+ </div>
+ </li>
+ </ul>
+ </li>
+ </ul>
+</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" t-attf-class="o_wslides_slides_list_slide o_wslides_js_list_item 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">
@@ -458,12 +535,14 @@
<div class="d-flex flex-row">
<a name="o_wslides_list_slide_add_quizz" t-if="channel.can_upload and not slide.question_ids" t-attf-href="/slides/slide/#{slug(slide)}?quiz_quick_create">
- <span class="badge badge-light badge-hide border font-weight-normal px-2 py-1 m-1"><i class="fa fa-plus mr-1"/>Add Quiz</span>
+ <span class="badge badge-light badge-hide border font-weight-normal px-2 py-1 m-1">Add Quiz</span>
</a>
<a t-if="channel.can_upload" href="#">
- <span t-att-data-slide-id="slide.id" t-attf-class="o_wslides_js_slide_toggle_is_preview badge #{'badge-success py-1' if slide.is_preview else 'badge-light badge-hide border'} font-weight-normal px-2 m-1">Free preview</span>
+ <span t-att-data-slide-id="slide.id" t-attf-class="o_wslides_js_slide_toggle_is_preview badge #{'badge-success' if slide.is_preview else 'badge-light badge-hide border'} font-weight-normal px-2 py-1 m-1"><span>Preview</span></span>
</a>
- <span t-elif="slide.is_preview and not channel.is_member" class="badge badge-success font-weight-normal px-2 py-1 m-1">Free preview</span>
+ <t t-elif="slide.is_preview and not channel.is_member">
+ <span class="badge badge-success font-weight-normal px-2 py-1 m-1"><span>Preview</span></span>
+ </t>
<span t-if="slide.is_new_slide and not channel_progress[slide.id].get('completed')" class="badge badge-info badge-arrow-right font-weight-normal px-2 py-1 m-1">
New
</span>
@@ -481,7 +560,7 @@
</t>
<span t-if="channel.can_publish" class="d-none d-md-flex">
<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 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" title="Edit in backend"><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>
@@ -490,7 +569,7 @@
<!-- ======= Documentation Course content: cards / categories======= -->
<template id="course_promoted_slide" name="Documentation Course content: promoted slide">
- <div class="o_wslides_promoted_slide d-none">
+ <div class="o_wslides_promoted_slide">
<div t-if="not search and not search_slide_type and slide_promoted" class="container py-1 mb-2">
<div class="card flex-column flex-lg-row">
<t t-set="image_url" t-value="website.image_url(slide_promoted, 'image_1024')"/>
@@ -647,7 +726,9 @@
</div>
</div>
<!-- Featured lesson -->
- <t t-call="website_slides.course_promoted_slide"/>
+ <t t-if="channel.promote_strategy != 'none'">
+ <t t-call="website_slides.course_promoted_slide"/>
+ </t>
<div class="container py-2">
<t t-if="search">
@@ -708,13 +789,14 @@
</a>
<div t-else="" class="card-img-top border-bottom o_wslides_gradient" t-attf-style="padding-top: 50%;"/>
</t>
+ <i t-if="channel_progress[slide.id].get('completed')" class="position-absolute py-1 px-2 h5 fa fa-check-circle text-primary" style="right:0; top:0;"/>
<div class="card-body p-3">
<a t-if="can_access" class="card-title h5 mb-2o_wslides_desc_truncate_2" t-attf-href="/slides/slide/#{slug(slide)}#{query_string}" t-esc="slide.name"/>
<span t-else="" class="card-title h5 mb-2 o_wslides_desc_truncate_2 text-muted" t-esc="slide.name"/>
<div class="card-subtitle mb-2 text-muted" t-if="slide.is_preview or (not slide.is_published and user.has_group('website_slides.group_website_slides_officer'))">
<t t-if="slide.is_preview">
- <span class="badge badge-info">Free preview</span>
+ <span class="badge badge-info">Preview</span>
</t>
<t t-if="not slide.is_published and channel.can_publish">
<span class="badge badge-danger">Unpublished</span>
@@ -761,10 +843,4 @@
<i t-if="slide.slide_type == 'quiz'" t-att-class="'fa fa-question-circle %s' % icon_class"></i>
</template>
-<template name="Display Promoted Slide" id="display_promoted_slide" inherit_id="website_slides.course_promoted_slide" active="True" customize_show="True">
- <xpath expr="//div[hasclass('o_wslides_promoted_slide')]" position="attributes">
- <attribute name="class">o_wslides_promoted_slide</attribute>
- </xpath>
-</template>
-
</data></odoo>