summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorThibault Delavallée <tde@odoo.com>2019-02-19 10:41:15 +0000
committerThibault Delavallée <tde@odoo.com>2019-02-20 12:09:01 +0000
commit9ae7f5a2612a2e69a32d33dca5ba78775a8b09a9 (patch)
tree7ec70d946e415eda585be1cb673d4570d7c36795 /addons
parentdb6e8f368cd275bef012e21cfe7a7a39dbc607c4 (diff)
[IMP] website_slides: perform some code linting and re-order frontend templates
Purpose is to perform some linting in code. No functional change should occur with this commit, only some code move. Diff may appear huge but it is just because some files are split. This cleaning allow to better understand code and templates architecture now that eLearning feature has landed in Odoo Community. It will ease future additions, modifications and fixes. Containing : * [REF] make some internal slide-related methods private as they are not intended to be called by outside world; * [MOV] new channel invite wizard in wizard folder; * [MOV] split frontend templates in some files to better locate code. There is now files for homepage, course, lesson, embed and utils in addition to slide-related profile template; * [REM] dead (unused) templates; Commit linked to task ID 1941250 and PR #31272.
Diffstat (limited to 'addons')
-rw-r--r--addons/website_slides/__init__.py1
-rw-r--r--addons/website_slides/__manifest__.py10
-rw-r--r--addons/website_slides/controllers/__init__.py1
-rw-r--r--addons/website_slides/controllers/main.py6
-rw-r--r--addons/website_slides/models/__init__.py2
-rw-r--r--addons/website_slides/models/slide_channel.py75
-rw-r--r--addons/website_slides/models/slide_slide.py54
-rw-r--r--addons/website_slides/views/website_slides_templates_course.xml420
-rw-r--r--addons/website_slides/views/website_slides_templates_lesson.xml (renamed from addons/website_slides/views/website_slides_templates.xml)475
-rw-r--r--addons/website_slides/views/website_slides_templates_lesson_embed.xml (renamed from addons/website_slides/views/website_slides_embed_templates.xml)0
-rw-r--r--addons/website_slides/views/website_slides_templates_utils.xml41
-rw-r--r--addons/website_slides/wizard/__init__.py4
-rw-r--r--addons/website_slides/wizard/slide_channel_invite.py (renamed from addons/website_slides/models/slide_channel_invite.py)0
-rw-r--r--addons/website_slides/wizard/slide_channel_invite_views.xml (renamed from addons/website_slides/views/slide_channel_invite_views.xml)0
14 files changed, 541 insertions, 548 deletions
diff --git a/addons/website_slides/__init__.py b/addons/website_slides/__init__.py
index 7d34c7c054a..88710707227 100644
--- a/addons/website_slides/__init__.py
+++ b/addons/website_slides/__init__.py
@@ -3,3 +3,4 @@
from . import controllers
from . import models
+from . import wizard
diff --git a/addons/website_slides/__manifest__.py b/addons/website_slides/__manifest__.py
index 32b4f407e67..a5df3cf0cef 100644
--- a/addons/website_slides/__manifest__.py
+++ b/addons/website_slides/__manifest__.py
@@ -25,16 +25,18 @@ Share and Publish Videos, Presentations and Documents'
'data': [
'views/assets.xml',
'views/res_config_settings_views.xml',
- 'views/website_slides_templates_homepage.xml',
- 'views/website_slides_templates.xml',
- 'views/website_slides_embed_templates.xml',
'views/slide_slide_views.xml',
'views/slide_channel_partner_views.xml',
'views/slide_channel_views.xml',
'views/slide_channel_tag_views.xml',
- 'views/slide_channel_invite_views.xml',
'views/website_slides_menu_views.xml',
+ 'views/website_slides_templates_homepage.xml',
+ 'views/website_slides_templates_course.xml',
+ 'views/website_slides_templates_lesson.xml',
+ 'views/website_slides_templates_lesson_embed.xml',
'views/website_slides_templates_profile.xml',
+ 'views/website_slides_templates_utils.xml',
+ 'wizard/slide_channel_invite_views.xml',
'data/ir_data.xml',
'data/gamification_data.xml',
'data/mail_data.xml',
diff --git a/addons/website_slides/controllers/__init__.py b/addons/website_slides/controllers/__init__.py
index acf000fd92c..5f151657861 100644
--- a/addons/website_slides/controllers/__init__.py
+++ b/addons/website_slides/controllers/__init__.py
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import mail
from . import main
diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py
index 50cea64c078..f0248462994 100644
--- a/addons/website_slides/controllers/main.py
+++ b/addons/website_slides/controllers/main.py
@@ -53,8 +53,8 @@ class WebsiteSlides(WebsiteProfile):
return True
def _get_slide_detail(self, slide):
- most_viewed_slides = slide.get_most_viewed_slides(self._slides_per_list)
- related_slides = slide.get_related_slides(self._slides_per_list)
+ most_viewed_slides = slide._get_most_viewed_slides(self._slides_per_list)
+ related_slides = slide._get_related_slides(self._slides_per_list)
values = {
'slide': slide,
'most_viewed_slides': most_viewed_slides,
@@ -521,7 +521,7 @@ class WebsiteSlides(WebsiteProfile):
@http.route(['/slides/slide/send_share_email'], type='json', auth='user', website=True)
def slide_send_share_email(self, slide_id, email):
slide = request.env['slide.slide'].browse(int(slide_id))
- result = slide.send_share_email(email)
+ result = slide._send_share_email(email)
return result
# --------------------------------------------------
diff --git a/addons/website_slides/models/__init__.py b/addons/website_slides/models/__init__.py
index 2768668e3e4..9a55188c7ae 100644
--- a/addons/website_slides/models/__init__.py
+++ b/addons/website_slides/models/__init__.py
@@ -1,11 +1,11 @@
# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import gamification_challenge
from . import slide_slide
from . import slide_question
from . import slide_channel
from . import slide_channel_tag
-from . import slide_channel_invite
from . import res_config_settings
from . import website
from . import res_users
diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py
index 766fde193a0..edb496a14e8 100644
--- a/addons/website_slides/models/slide_channel.py
+++ b/addons/website_slides/models/slide_channel.py
@@ -259,41 +259,6 @@ class Channel(models.Model):
if channel.id: # avoid to perform a slug on a not yet saved record in case of an onchange.
channel.website_url = '%s/slides/%s' % (base_url, slug(channel))
- @api.multi
- def action_redirect_to_members(self):
- action = self.env.ref('website_slides.slide_channel_partner_action').read()[0]
- action['view_mode'] = 'tree'
- action['domain'] = [('channel_id', 'in', self.ids)]
- if len(self) == 1:
- action['context'] = {'default_channel_id': self.id}
-
- return action
-
- @api.multi
- def action_channel_invite(self):
- self.ensure_one()
-
- if self.enroll != 'invite':
- raise UserError(_("You cannot send invitations for channels that are not set as 'invite'."))
-
- template = self.env.ref('website_slides.mail_template_slide_channel_invite', raise_if_not_found=False)
-
- local_context = dict(
- self.env.context,
- default_channel_id=self.id,
- default_use_template=bool(template),
- default_template_id=template and template.id or False,
- notif_layout='mail.mail_notification_light',
- )
- return {
- 'type': 'ir.actions.act_window',
- 'view_type': 'form',
- 'view_mode': 'form',
- 'res_model': 'slide.channel.invite',
- 'target': 'new',
- 'context': local_context,
- }
-
# ---------------------------------------------------------
# ORM Overrides
# ---------------------------------------------------------
@@ -364,6 +329,41 @@ class Channel(models.Model):
# Business / Actions
# ---------------------------------------------------------
+ @api.multi
+ def action_redirect_to_members(self):
+ action = self.env.ref('website_slides.slide_channel_partner_action').read()[0]
+ action['view_mode'] = 'tree'
+ action['domain'] = [('channel_id', 'in', self.ids)]
+ if len(self) == 1:
+ action['context'] = {'default_channel_id': self.id}
+
+ return action
+
+ @api.multi
+ def action_channel_invite(self):
+ self.ensure_one()
+
+ if self.visibility != 'invite':
+ raise UserError(_("You cannot send invitations for channels that are not set as 'invite'."))
+
+ template = self.env.ref('website_slides.mail_template_slide_channel_invite', raise_if_not_found=False)
+
+ local_context = dict(
+ self.env.context,
+ default_channel_id=self.id,
+ default_use_template=bool(template),
+ default_template_id=template and template.id or False,
+ notif_layout='mail.mail_notification_light',
+ )
+ return {
+ 'type': 'ir.actions.act_window',
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'slide.channel.invite',
+ 'target': 'new',
+ 'context': local_context,
+ }
+
def action_add_member(self, **member_values):
""" Adds the logged in user in the channel members.
(see '_action_add_members' for more info)
@@ -413,11 +413,6 @@ class Channel(models.Model):
for channel in self:
channel._action_add_members(channel.mapped('enroll_group_ids.users.partner_id'))
- def list_all(self):
- return {
- 'channels': [{'id': channel.id, 'name': channel.name, 'website_url': channel.website_url} for channel in self.search([])]
- }
-
# ---------------------------------------------------------
# Rating Mixin API
# ---------------------------------------------------------
diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py
index fe022f83b31..24e043be6e3 100644
--- a/addons/website_slides/models/slide_slide.py
+++ b/addons/website_slides/models/slide_slide.py
@@ -77,17 +77,6 @@ class SlideTag(models.Model):
class Slide(models.Model):
- """ This model represents actual presentations. Those must be one of four
- types:
-
- - Presentation
- - Document
- - Infographic
- - Video
- - Webpage
-
- Slide has various statistics like view count, embed count, like, dislikes """
-
_name = 'slide.slide'
_inherit = ['mail.thread', 'website.seo.metadata', 'website.published.mixin', 'rating.mixin']
_description = 'Slides'
@@ -99,10 +88,6 @@ class Slide(models.Model):
}
_order = 'category_sequence asc, sequence asc'
- _sql_constraints = [
- ('exclusion_html_content_and_url', "CHECK(html_content IS NULL OR url IS NULL)", "A slide is either filled with a document url or HTML content. Not both.")
- ]
-
def _default_access_token(self):
return str(uuid.uuid4())
@@ -161,13 +146,17 @@ class Slide(models.Model):
likes = fields.Integer('Likes', compute='_compute_user_info', store=True)
dislikes = fields.Integer('Dislikes', compute='_compute_user_info', store=True)
user_vote = fields.Integer('User vote', compute='_compute_user_info')
- embed_code = fields.Text('Embed Code', readonly=True, compute='_get_embed_code')
+ embed_code = fields.Text('Embed Code', readonly=True, compute='_compute_embed_code')
# views
embedcount_ids = fields.One2many('slide.embed', 'slide_id', string="Embed Count")
slide_views = fields.Integer('# of Website Views', store=True, compute="_compute_slide_views")
public_views = fields.Integer('# of Public Views')
total_views = fields.Integer("Total # Views", default="0", compute='_compute_total', store=True)
+ _sql_constraints = [
+ ('exclusion_html_content_and_url', "CHECK(html_content IS NULL OR url IS NULL)", "A slide is either filled with a document url or HTML content. Not both.")
+ ]
+
@api.depends('slide_views', 'public_views')
def _compute_total(self):
for record in self:
@@ -216,7 +205,8 @@ class Slide(models.Model):
self.env['slide.slide.partner']
)
- def _get_embed_code(self):
+ @api.depends('document_id', 'slide_type', 'mime_type')
+ def _compute_embed_code(self):
base_url = request and request.httprequest.url_root or self.env['ir.config_parameter'].sudo().get_param('web.base.url')
if base_url[-1] == '/':
base_url = base_url[:-1]
@@ -235,7 +225,7 @@ class Slide(models.Model):
record.embed_code = False
@api.onchange('url')
- def on_change_url(self):
+ def _on_change_url(self):
self.ensure_one()
if self.url:
res = self._parse_document_url(self.url)
@@ -250,6 +240,7 @@ class Slide(models.Model):
@api.multi
@api.depends('name')
def _compute_website_url(self):
+ # TDE FIXME: clena this link.tracker strange stuff
super(Slide, self)._compute_website_url()
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
for slide in self:
@@ -321,6 +312,10 @@ class Slide(models.Model):
self._post_publication()
return res
+ # ---------------------------------------------------------
+ # Mail/Rating
+ # ---------------------------------------------------------
+
@api.multi
def get_access_action(self, access_uid=None):
""" Instead of the classic form view, redirect to website if it is published. """
@@ -335,10 +330,6 @@ class Slide(models.Model):
}
return super(Slide, self).get_access_action(access_uid)
- # ---------------------------------------------------------
- # Business Methods
- # ---------------------------------------------------------
-
@api.multi
def _notify_get_groups(self, message, groups):
""" Add access button to everyone if the document is active. """
@@ -350,7 +341,12 @@ class Slide(models.Model):
return groups
- def get_related_slides(self, limit=20):
+ # ---------------------------------------------------------
+ # 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:
@@ -358,7 +354,8 @@ class Slide(models.Model):
for record in self.search(domain, limit=limit):
yield record
- def get_most_viewed_slides(self, limit=20):
+ 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'):
@@ -387,10 +384,13 @@ class Slide(models.Model):
self.write({'access_token': self._default_access_token()})
return self._sign_token(partner_id)
- @api.one
- def send_share_email(self, email):
+ def _send_share_email(self, email):
+ # TDE FIXME: template to check
+ mail_ids = []
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
- return self.channel_id.share_template_id.with_context(email=email, base_url=base_url).send_mail(self.id, notif_layout='mail.mail_notification_light')
+ for record in self:
+ mail_ids.append(self.channel_id.share_template_id.with_context(email=email, base_url=base_url).send_mail(record.id, notif_layout='mail.mail_notification_light'))
+ return mail_ids
def action_like(self):
self.check_access_rights('read')
diff --git a/addons/website_slides/views/website_slides_templates_course.xml b/addons/website_slides/views/website_slides_templates_course.xml
new file mode 100644
index 00000000000..5df196a2e1b
--- /dev/null
+++ b/addons/website_slides/views/website_slides_templates_course.xml
@@ -0,0 +1,420 @@
+<?xml version="1.0" ?>
+<odoo><data>
+
+<!-- Channels sub-template: header -->
+<template id="course_nav" name="Course Navigation Header">
+ <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-6">
+ <ol class="breadcrumb">
+ <li class="breadcrumb-item">
+ <a href="/slides">Home</a>
+ </li>
+ <li t-att-class="'breadcrumb-item %s' % ('active' if not search_category and not search_tag and not search_slide_type else '')">
+ <a t-att-href="'/slides/%s' % slug(channel)"><span t-esc="channel.name"/></a>
+ </li>
+ <li class="breadcrumb-item active" t-att-aria-current="'page' and search_category" t-if="search_category">
+ <a t-att-href="'/slides/%s/category/%s' % (slug(channel), slug(search_category))"><span t-esc="search_category.name"/></a>
+ </li>
+ <li class="breadcrumb-item active" t-att-aria-current="'page' and search_tag" t-if="search_tag">
+ <a t-att-href="'/slides/%s/tag/%s' % (slug(channel), slug(search_tag))"><span t-esc="search_tag.name"/></a>
+ </li>
+ <li class="breadcrumb-item active" t-att-aria-current="'page' and search_slide_type" t-if="search_slide_type">
+ <a t-att-href="'/slides/%s?slide_type=%s' % (slug(channel), search_slide_type)"><span t-esc="slide_types[search_slide_type]"/></a>
+ </li>
+ </ol>
+ </nav>
+ <div class="col-6 d-flex flex-row align-items-center">
+ <!-- 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>
+ <!-- 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">
+ <i class="fa fa-search"></i>
+ </button>
+ </span>
+ </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>
+ </h6>
+ </small>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+<!-- Channel main template -->
+<template id='course_main' name="Course Main">
+ <t t-set="head">
+ <t t-call-assets="web.pdf_js_lib" t-css="false"/>
+ <script type="text/javascript" src="/website_slides/static/lib/pdfslidesviewer/PDFSlidesViewer.js"></script>
+ </t>
+ <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="row o_wslides_course_header">
+ <div class="col-lg-12 o_wslides_container o_wslides_course_header_container">
+ <div class="row align-items-end">
+ <div class="col o_wslides_course_header_aside main_image">
+ <div t-field="channel.image" widget="image" t-options="{'widget': 'image'}"/>
+ </div>
+ <div class="col-8 o_wslides_course_header_content">
+ <h3 class="row"><span class="font-weight-bold col" t-field="channel.name"/></h3>
+ <div class="row">
+ <div class="col-12 o_wslides_course_description" t-field="channel.description"/>
+ <div class="col-6 mt8 mb64">
+ <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>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="row o_wslides_course_content">
+ <div class="col-lg-12 o_wslides_container o_wslides_content_container">
+ <div class="row justify-content-end o_wslides_course_content_nav">
+ <div class="col-8">
+ <ul class="nav nav-tabs o_wslides_nav_tabs" role="tablist" id="profile_extra_info_tablist">
+ <li class="nav-item o_wslides_nav_tabs_item_home">
+ <a t-att-href="'/slides/%s%s?%s' % (slug(channel), '/%s' % slug(category) if category else '', keep_query('debug'))"
+ t-att-class="'nav-link o_wslides_navlink %s' % ('' if search_slide_type else 'active')">
+ <i class="fa fa-home"/> Home</a>
+ </li>
+ <li class="nav-item">
+ <a t-att-href="'/slides/%s' % (slug(channel))"
+ t-att-class="'nav-link o_wslides_navlink'">Review</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <div class="row o_wslides_course_content_main">
+ <!-- Channel presentation, aka general information + CTAs -->
+ <div class="col-4 o_wslides_course_content_aside">
+ <div class="row justify-content-center mt8 o_wslides_join_channel">
+ <a t-if="not channel.is_member and channel.enroll == 'public'" role="button"
+ class="col-10 btn btn-primary o_wslides_join_channel_link"
+ title="Start Course" aria-label="Start Course Channel"
+ t-att-href="'#'"
+ t-att-data-channel-id="channel.id">
+ <span class="cta-title text_small_caps">
+ <t t-if="channel.channel_type == 'documentation'">Start Course</t>
+ <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 btn btn-light" t-att-href="'#'">
+ <span class="cta-title text_small_caps">Private Course</span>
+ </a>
+ <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 btn btn-primary">
+ <i class="fa fa-chevron-right"></i>
+ <span class="cta-title text_small_caps">Already member</span>
+ </span>
+ </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>
+ <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_%ss' % slide_type_key]"/>
+ </t>
+ <t t-else="">
+ <span class="badge badge-pill badge-info" t-esc="channel['nbr_%ss' % slide_type_key]"/>
+ </t>
+ </span>
+ </div>
+ </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"
+ aria-label="Share Channel"
+ data-toggle="modal" data-target="#slideChannelShareModal">
+ <i class="fa fa-share-square"></i> Share
+ </button>
+ <div class="modal fade" id="slideChannelShareModal" tabindex="-1" role="dialog" aria-labelledby="slideChannelShareModalLabel" aria-hidden="true">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title" id="slideChannelShareModalLabel">
+ Share
+ </h5>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span>&amp;times;</span>
+ </button>
+ </div>
+ <div class="modal-body">
+ <h5>Share on Social Networks</h5>
+ <t t-call="website_slides.slides_share">
+ <t t-set="record" t-value="channel"/>
+ </t>
+ <h5 class="mt16">Share Link</h5>
+ <input type="text" class="form-control" readonly="readonly" onclick="this.select();"
+ t-att-value="channel.website_url"/>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <div t-if="channel.can_upload" class="row justify-content-center mt8 mb8">
+ <a role="button" class="btn btn-primary oe_slide_js_upload col-10" 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
+ </a>
+ </div>
+ </div>
+ <!-- training mode ==============================================-->
+ <div t-if="channel.channel_type == 'training'" style="width:70%;" class="d-flex align-items-center ml-4 justify-content-center">
+ <div class="course-content oe_js_course_slides_list" style="width: 100%">
+ <ul>
+ <t t-set="i" t-value="1"/>
+ <t t-set="j" t-value="0"/>
+ <t t-foreach="channel.category_ids" t-as="category">
+ <li t-attf-class="#{'section-draggable' if user == user_id else ''}" t-attf-category_id="#{category.id}">
+ <div t-attf-category_id="#{category.id}" class="course-section text-muted font-weight-bold pt-0 pb-0 pl-2 pr-2 d-flex justify-content-between align-items-center">
+ <div style="width:50%;" class="d-flex align-items-center">
+ <i t-if="channel.user_id == user" class="fa fa-arrows mr-3 text-muted"></i>
+ <div class="mr-2">Section <span class="section-index" t-esc="i"/>:</div>
+ <span t-field="category.name"/>
+ </div>
+ <!-- <a t-if="channel.user_id == user" title="Add content to this section" class="mr-2 p-0 oe_slide_js_add_slide" href="#" t-attf-channel_id="#{channel.id}" t-attf-category_id="#{category.id}">+</a> -->
+ <a class="mr-2 oe_slide_js_upload"
+ role="button"
+ aria-label="Upload Presentation"
+ href="#"
+ style="font-size: 1.5rem;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">+</a>
+ <t t-set="i" t-value="i+1"/>
+ </div>
+ <ul t-attf-category_id="#{category.id}" >
+ <t t-foreach="category.slide_ids" t-as="slide">
+ <li t-att-index="j" t-attf-slide_id="#{slide.id}" t-attf-category_id="#{category.id}" t-attf-class="#{'content-slide slide-draggable d-flex justify-content-between align-items-center p-2' if channel.user_id == user else 'content-slide d-flex justify-content-between align-items-center p-2'}">
+ <div class="content-slide-infos ml-2">
+ <i t-if="channel.user_id == user" class="fa fa-arrows mr-2 text-muted"></i>
+ <i t-if="slide.slide_type == 'document'" class="fa fa-file-pdf-o mr-2 text-muted"></i>
+ <i t-if="slide.slide_type == 'infographic'" class="fa fa-file-picture-o mr-2 text-muted"></i>
+ <i t-if="slide.slide_type == 'video'" class="fa fa-play-circle mr-2 text-muted"></i>
+ <i t-if="slide.slide_type == 'link'" class="fa fa-file-code-o mr-2 text-muted"></i>
+ <i t-if="slide.slide_type == 'webpage'" class="fa fa-file-text mr-2 text-muted"></i>
+ <i t-if="slide.slide_type == 'quiz'" class="fa fa-question-circle mr-2 text-muted"></i>
+ <i t-if="slide.slide_type == 'certification'" class="fa fa-trophy mr-2 text-muted"></i>
+ <a class="link-to-slide" t-attf-href="/slides/slide/#{slug(slide)}"><span t-field="slide.name"/></a>
+ </div>
+ <div class="content-slide-controls mr-2">
+ <i t-if="not slide.id in user_progress or not user_progress[slide.id].completed" class="check-done fa fa-check-circle text-muted mr-1"></i>
+ <i t-if="slide.id in user_progress and user_progress[slide.id].completed" class="check-done text-primary fa fa-check-circle mr-1"></i>
+ <a t-if="channel.user_id == user 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-1"></i></a>
+ <a t-if="channel.user_id == user and slide.slide_type == 'webpage'" t-attf-href="/slides/slide/#{slug(slide)}?enable_editor=1"><i class="fa fa-pencil text-muted mr-1"></i></a>
+ <i t-if="channel.user_id == user" t-attf-slide_id="#{slide.id}" class="fa fa-trash text-muted oe_slide_js_delete_slide"></i>
+ </div>
+ </li>
+ <t t-set="j" t-value="j+1"/>
+ </t>
+ </ul>
+ </li>
+ </t>
+ </ul>
+ <div t-if="channel.user_id == user" class="content-actions">
+ <a class="mr-2 oe_slide_js_upload"
+ 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">Add Content</a>
+ <a class="oe_slide_js_add_section" t-attf-channel_id="#{channel.id}" href="#">Add Section</a>
+ </div>
+ </div>
+ </div>
+ <!-- Channel content, aka slides (lessons in documentation mode) -->
+ <div t-if="channel.channel_type == 'documentation'" class="col-8 mt24 ml32 o_wslides_channel_content_promoted">
+ <div class="row mt16 align-items-center">
+ <div class="col">
+ <h3><i class="fa fa-plus-square"/> Featured lesson</h3>
+ <hr/>
+ </div>
+ </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">
+ <div class="row">
+ <h3 class="col-6" t-att-title="slide_promoted.name">
+ <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="font-weight-bold text-muted" t-field="slide_promoted.name"/>
+ </t>
+ <t t-else="">
+ <span class="font-weight-bold text-muted" t-field="slide_promoted.name"/>
+ </t>
+ </h3>
+ <div class="col-12" t-field="slide_promoted.description"/>
+ </div>
+ </div>
+ </div>
+ </div>
+ <!-- Channel content, aka slides (lessons in documentation mode) -->
+ <div t-if="channel.channel_type == 'documentation'" class="col-12">
+ <div class="tab-content mt16" id="slideChannelContent">
+ <div class="tab-pane active" role="tabpanel" aria-labelledby="profile-tab" id="slideChannelContentAbout">
+ <t t-foreach="category_data" t-as="category">
+ <div class="row mt16 align-items-center">
+ <div class="col">
+ <a t-att-href="'/slides/%s/category/%s' % (slug(channel), category['id'])" class="float-right">
+ View all
+ </a>
+ <h3><i class="fa fa-plus-square"/> <t t-esc="category['name']"/></h3>
+ <hr/>
+ </div>
+ </div>
+ <t t-call="website_slides.slides_grid_view">
+ <t t-set="slides" t-value="category['slides']"/>
+ </t>
+ </t>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </t>
+</template>
+
+<!-- Embedded template: display a list of slides in a grid view -->
+<template id='slides_grid_view' name="Slides (Grid View)">
+ <div class="row o_wslides_row mt8">
+ <div class="col-lg-3 col-md-6 col-12" t-foreach="slides" t-as="slide">
+ <div class="card o_wslides_lesson_card">
+ <img class="card-img-top img-fuild" style="max-height: 160px;"
+ t-att-src="'/slides/slide/%s/get_image?field=image_large' % slide.id"
+ t-att-alt="slide.name"/>
+ <div class="card-body">
+ <h5 class="card-title" t-att-title="slide.name">
+ <t t-if="slide.is_preview or channel.is_member or is_slides_publisher">
+ <a t-attf-href="/slides/slide/#{slug(slide)}" t-esc="slide.name"/>
+ </t>
+ <t t-else="">
+ <span class="text-muted" t-esc="slide.name"/>
+ </t>
+ </h5>
+ <h6 class="card-subtitle mb-2 text-muted">
+ <t t-if="user.has_group('website.group_website_publisher')">
+ <i class="fa fa-globe float-right o_wslides_slide_manage_publish"></i>
+ <i class="fa fa-pencil float-right o_wslides_slide_manage_edit"></i>
+ <i class="fa fa-trash float-right o_wslides_slide_manage_unlink"></i>
+ </t>
+ <t t-if="slide.is_preview">
+ <span class="badge badge-info">Free preview</span>
+ </t>
+ <t t-if="not slide.is_published and user.has_group('website.group_website_publisher')">
+ <span class="badge badge-danger">Unpublished</span>
+ </t>
+ </h6>
+ <div class="card-text">
+ <div class="text-muted oe_no_empty" t-field="slide.description"/>
+ <div t-if="slide.tag_ids">
+ <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-secondary">
+ <t t-esc="tag.name"/>
+ </a>
+ </t>
+ </div>
+ </div>
+ </div>
+ <div class="card-footer">
+ <!-- CHECKME: like only if logged -->
+ <div class="float-right text-right o_wslides_like">
+ <span class="o_wslides_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_like_down" 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>
+ <small class="text-muted">
+ <t t-call="website_slides.slides_misc_float_time">
+ <t t-set="value" t-value="slide.completion_time"/>
+ </t>
+<!-- <t t-esc="slide.total_views"/> Views
+ <timeago class="timeago" t-att-datetime="slide.create_date"></timeago> -->
+ </small>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+
+</data></odoo>
diff --git a/addons/website_slides/views/website_slides_templates.xml b/addons/website_slides/views/website_slides_templates_lesson.xml
index 7f0bc0d9553..3b3600b6e47 100644
--- a/addons/website_slides/views/website_slides_templates.xml
+++ b/addons/website_slides/views/website_slides_templates_lesson.xml
@@ -1,454 +1,7 @@
<?xml version="1.0" ?>
-<odoo>
-<data>
-
-<!-- Tools template: share on social networkds -->
-<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>
-</template>
-
-<!-- Channels: no channel found -->
-<template id="channel_not_found" name="Private Presentation">
- <t t-call="website.layout">
- <div class="container">
- <div class="oe_structure">
- <t t-if="search_term">
- <h2>No channel found when searching "<i><t t-esc="search_term"/></i>".</h2>
- </t>
- <t t-else="">
- <h2>No channel created or published yet.</h2>
- </t>
- </div>
- </div>
- </t>
-</template>
-
-<!-- Channels sub-template: header -->
-<template id="course_nav" name="Course Navigation Header">
- <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-6">
- <ol class="breadcrumb">
- <li class="breadcrumb-item">
- <a href="/slides">Home</a>
- </li>
- <li t-att-class="'breadcrumb-item %s' % ('active' if not search_category and not search_tag and not search_slide_type else '')">
- <a t-att-href="'/slides/%s' % slug(channel)"><span t-esc="channel.name"/></a>
- </li>
- <li class="breadcrumb-item active" t-att-aria-current="'page' and search_category" t-if="search_category">
- <a t-att-href="'/slides/%s/category/%s' % (slug(channel), slug(search_category))"><span t-esc="search_category.name"/></a>
- </li>
- <li class="breadcrumb-item active" t-att-aria-current="'page' and search_tag" t-if="search_tag">
- <a t-att-href="'/slides/%s/tag/%s' % (slug(channel), slug(search_tag))"><span t-esc="search_tag.name"/></a>
- </li>
- <li class="breadcrumb-item active" t-att-aria-current="'page' and search_slide_type" t-if="search_slide_type">
- <a t-att-href="'/slides/%s?slide_type=%s' % (slug(channel), search_slide_type)"><span t-esc="slide_types[search_slide_type]"/></a>
- </li>
- </ol>
- </nav>
- <div class="col-6 d-flex flex-row align-items-center">
- <!-- 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>
- <!-- 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">
- <i class="fa fa-search"></i>
- </button>
- </span>
- </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>
- </h6>
- </small>
- </div>
- </div>
- </div>
- </div>
-</template>
-
-<!-- Channel main template -->
-<template id='course_main' name="Course Main">
- <t t-set="head">
- <t t-call-assets="web.pdf_js_lib" t-css="false"/>
- <script type="text/javascript" src="/website_slides/static/lib/pdfslidesviewer/PDFSlidesViewer.js"></script>
- </t>
- <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="row o_wslides_course_header">
- <div class="col-lg-12 o_wslides_container o_wslides_course_header_container">
- <div class="row align-items-end">
- <div class="col o_wslides_course_header_aside main_image">
- <div t-field="channel.image" widget="image" t-options="{'widget': 'image'}"/>
- </div>
- <div class="col-8 o_wslides_course_header_content">
- <h3 class="row"><span class="font-weight-bold col" t-field="channel.name"/></h3>
- <div class="row">
- <div class="col-12 o_wslides_course_description" t-field="channel.description"/>
- <div class="col-6 mt8 mb64">
- <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>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="row o_wslides_course_content">
- <div class="col-lg-12 o_wslides_container o_wslides_content_container">
- <div class="row justify-content-end o_wslides_course_content_nav">
- <div class="col-8">
- <ul class="nav nav-tabs o_wslides_nav_tabs" role="tablist" id="profile_extra_info_tablist">
- <li class="nav-item o_wslides_nav_tabs_item_home">
- <a t-att-href="'/slides/%s%s?%s' % (slug(channel), '/%s' % slug(category) if category else '', keep_query('debug'))"
- t-att-class="'nav-link o_wslides_navlink %s' % ('' if search_slide_type else 'active')">
- <i class="fa fa-home"/> Home</a>
- </li>
- <li class="nav-item">
- <a t-att-href="'/slides/%s' % (slug(channel))"
- t-att-class="'nav-link o_wslides_navlink'">Review</a>
- </li>
- </ul>
- </div>
- </div>
- <div class="row o_wslides_course_content_main">
- <!-- Channel presentation, aka general information + CTAs -->
- <div class="col-4 o_wslides_course_content_aside">
- <div class="row justify-content-center mt8 o_wslides_join_channel">
- <a t-if="not channel.is_member and channel.enroll == 'public'" role="button"
- class="col-10 btn btn-primary o_wslides_join_channel_link"
- title="Start Course" aria-label="Start Course Channel"
- t-att-href="'#'"
- t-att-data-channel-id="channel.id">
- <span class="cta-title text_small_caps">
- <t t-if="channel.channel_type == 'documentation'">Start Course</t>
- <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 btn btn-light" t-att-href="'#'">
- <span class="cta-title text_small_caps">Private Course</span>
- </a>
- <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 btn btn-primary">
- <i class="fa fa-chevron-right"></i>
- <span class="cta-title text_small_caps">Already member</span>
- </span>
- </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>
- <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_%ss' % slide_type_key]"/>
- </t>
- <t t-else="">
- <span class="badge badge-pill badge-info" t-esc="channel['nbr_%ss' % slide_type_key]"/>
- </t>
- </span>
- </div>
- </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"
- aria-label="Share Channel"
- data-toggle="modal" data-target="#slideChannelShareModal">
- <i class="fa fa-share-square"></i> Share
- </button>
- <div class="modal fade" id="slideChannelShareModal" tabindex="-1" role="dialog" aria-labelledby="slideChannelShareModalLabel" aria-hidden="true">
- <div class="modal-dialog" role="document">
- <div class="modal-content">
- <div class="modal-header">
- <h5 class="modal-title" id="slideChannelShareModalLabel">
- Share
- </h5>
- <button type="button" class="close" data-dismiss="modal" aria-label="Close">
- <span>&amp;times;</span>
- </button>
- </div>
- <div class="modal-body">
- <h5>Share on Social Networks</h5>
- <t t-call="website_slides.slides_share">
- <t t-set="record" t-value="channel"/>
- </t>
- <h5 class="mt16">Share Link</h5>
- <input type="text" class="form-control" readonly="readonly" onclick="this.select();"
- t-att-value="channel.website_url"/>
- </div>
- </div>
- </div>
- </div>
-
- </div>
- <div t-if="channel.can_upload" class="row justify-content-center mt8 mb8">
- <a role="button" class="btn btn-primary oe_slide_js_upload col-10" 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
- </a>
- </div>
- </div>
- <!-- training mode ==============================================-->
- <div t-if="channel.channel_type == 'training'" style="width:70%;" class="d-flex align-items-center ml-4 justify-content-center">
- <div class="course-content oe_js_course_slides_list" style="width: 100%">
- <ul>
- <t t-set="i" t-value="1"/>
- <t t-set="j" t-value="0"/>
- <t t-foreach="channel.category_ids" t-as="category">
- <li t-attf-class="#{'section-draggable' if user == user_id else ''}" t-attf-category_id="#{category.id}">
- <div t-attf-category_id="#{category.id}" class="course-section text-muted font-weight-bold pt-0 pb-0 pl-2 pr-2 d-flex justify-content-between align-items-center">
- <div style="width:50%;" class="d-flex align-items-center">
- <i t-if="channel.user_id == user" class="fa fa-arrows mr-3 text-muted"></i>
- <div class="mr-2">Section <span class="section-index" t-esc="i"/>:</div>
- <span t-field="category.name"/>
- </div>
- <!-- <a t-if="channel.user_id == user" title="Add content to this section" class="mr-2 p-0 oe_slide_js_add_slide" href="#" t-attf-channel_id="#{channel.id}" t-attf-category_id="#{category.id}">+</a> -->
- <a class="mr-2 oe_slide_js_upload"
- role="button"
- aria-label="Upload Presentation"
- href="#"
- style="font-size: 1.5rem;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">+</a>
- <t t-set="i" t-value="i+1"/>
- </div>
- <ul t-attf-category_id="#{category.id}" >
- <t t-foreach="category.slide_ids" t-as="slide">
- <li t-att-index="j" t-attf-slide_id="#{slide.id}" t-attf-category_id="#{category.id}" t-attf-class="#{'content-slide slide-draggable d-flex justify-content-between align-items-center p-2' if channel.user_id == user else 'content-slide d-flex justify-content-between align-items-center p-2'}">
- <div class="content-slide-infos ml-2">
- <i t-if="channel.user_id == user" class="fa fa-arrows mr-2 text-muted"></i>
- <i t-if="slide.slide_type == 'document'" class="fa fa-file-pdf-o mr-2 text-muted"></i>
- <i t-if="slide.slide_type == 'infographic'" class="fa fa-file-picture-o mr-2 text-muted"></i>
- <i t-if="slide.slide_type == 'video'" class="fa fa-play-circle mr-2 text-muted"></i>
- <i t-if="slide.slide_type == 'link'" class="fa fa-file-code-o mr-2 text-muted"></i>
- <i t-if="slide.slide_type == 'webpage'" class="fa fa-file-text mr-2 text-muted"></i>
- <i t-if="slide.slide_type == 'quiz'" class="fa fa-question-circle mr-2 text-muted"></i>
- <i t-if="slide.slide_type == 'certification'" class="fa fa-trophy mr-2 text-muted"></i>
- <a class="link-to-slide" t-attf-href="/slides/slide/#{slug(slide)}"><span t-field="slide.name"/></a>
- </div>
- <div class="content-slide-controls mr-2">
- <i t-if="not slide.id in user_progress or not user_progress[slide.id].completed" class="check-done fa fa-check-circle text-muted mr-1"></i>
- <i t-if="slide.id in user_progress and user_progress[slide.id].completed" class="check-done text-primary fa fa-check-circle mr-1"></i>
- <a t-if="channel.user_id == user 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-1"></i></a>
- <a t-if="channel.user_id == user and slide.slide_type == 'webpage'" t-attf-href="/slides/slide/#{slug(slide)}?enable_editor=1"><i class="fa fa-pencil text-muted mr-1"></i></a>
- <i t-if="channel.user_id == user" t-attf-slide_id="#{slide.id}" class="fa fa-trash text-muted oe_slide_js_delete_slide"></i>
- </div>
- </li>
- <t t-set="j" t-value="j+1"/>
- </t>
- </ul>
- </li>
- </t>
- </ul>
- <div t-if="channel.user_id == user" class="content-actions">
- <a class="mr-2 oe_slide_js_upload"
- 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">Add Content</a>
- <a class="oe_slide_js_add_section" t-attf-channel_id="#{channel.id}" href="#">Add Section</a>
- </div>
- </div>
- </div>
- <!-- Channel content, aka slides (lessons in documentation mode) -->
- <div t-if="channel.channel_type == 'documentation'" class="col-8 mt24 ml32 o_wslides_channel_content_promoted">
- <div class="row mt16 align-items-center">
- <div class="col">
- <h3><i class="fa fa-plus-square"/> Featured lesson</h3>
- <hr/>
- </div>
- </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">
- <div class="row">
- <h3 class="col-6" t-att-title="slide_promoted.name">
- <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="font-weight-bold text-muted" t-field="slide_promoted.name"/>
- </t>
- <t t-else="">
- <span class="font-weight-bold text-muted" t-field="slide_promoted.name"/>
- </t>
- </h3>
- <div class="col-12" t-field="slide_promoted.description"/>
- </div>
- </div>
- </div>
- </div>
- <!-- Channel content, aka slides (lessons in documentation mode) -->
- <div t-if="channel.channel_type == 'documentation'" class="col-12">
- <div class="tab-content mt16" id="slideChannelContent">
- <div class="tab-pane active" role="tabpanel" aria-labelledby="profile-tab" id="slideChannelContentAbout">
- <t t-foreach="category_data" t-as="category">
- <div class="row mt16 align-items-center">
- <div class="col">
- <a t-att-href="'/slides/%s/category/%s' % (slug(channel), category['id'])" class="float-right">
- View all
- </a>
- <h3><i class="fa fa-plus-square"/> <t t-esc="category['name']"/></h3>
- <hr/>
- </div>
- </div>
- <t t-call="website_slides.slides_grid_view">
- <t t-set="slides" t-value="category['slides']"/>
- </t>
- </t>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </t>
-</template>
-
-<!-- Embedded template: display a list of slides in a grid view -->
-<template id='slides_grid_view' name="Slides (Grid View)">
- <div class="row o_wslides_row mt8">
- <div class="col-lg-3 col-md-6 col-12" t-foreach="slides" t-as="slide">
- <div class="card o_wslides_lesson_card">
- <img class="card-img-top img-fuild" style="max-height: 160px;"
- t-att-src="'/slides/slide/%s/get_image?field=image_large' % slide.id"
- t-att-alt="slide.name"/>
- <div class="card-body">
- <h5 class="card-title" t-att-title="slide.name">
- <t t-if="slide.is_preview or channel.is_member or is_slides_publisher">
- <a t-attf-href="/slides/slide/#{slug(slide)}" t-esc="slide.name"/>
- </t>
- <t t-else="">
- <span class="text-muted" t-esc="slide.name"/>
- </t>
- </h5>
- <h6 class="card-subtitle mb-2 text-muted">
- <t t-if="user.has_group('website.group_website_publisher')">
- <i class="fa fa-globe float-right o_wslides_slide_manage_publish"></i>
- <i class="fa fa-pencil float-right o_wslides_slide_manage_edit"></i>
- <i class="fa fa-trash float-right o_wslides_slide_manage_unlink"></i>
- </t>
- <t t-if="slide.is_preview">
- <span class="badge badge-info">Free preview</span>
- </t>
- <t t-if="not slide.is_published and user.has_group('website.group_website_publisher')">
- <span class="badge badge-danger">Unpublished</span>
- </t>
- </h6>
- <div class="card-text">
- <div class="text-muted oe_no_empty" t-field="slide.description"/>
- <div t-if="slide.tag_ids">
- <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-secondary">
- <t t-esc="tag.name"/>
- </a>
- </t>
- </div>
- </div>
- </div>
- <div class="card-footer">
- <!-- CHECKME: like only if logged -->
- <div class="float-right text-right o_wslides_like">
- <span class="o_wslides_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_like_down" 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>
- <small class="text-muted">
- <t t-call="website_slides.slides_misc_float_time">
- <t t-set="value" t-value="slide.completion_time"/>
- </t>
-<!-- <t t-esc="slide.total_views"/> Views
- <timeago class="timeago" t-att-datetime="slide.create_date"></timeago> -->
- </small>
- </div>
- </div>
- </div>
- </div>
-</template>
+<odoo><data>
<!-- Slide: main template: detailed view -->
-<template id="slide_edit_options" inherit_id="website.user_navbar" name="Edit Slide Options">
- <xpath expr="//li[@id='edit-page-menu']" position="after">
- <t t-if="main_object._name == 'slide.slide'" t-set="action" t-value="'website_slides.action_slides_slides'" />
- </xpath>
-</template>
<template id="slide_detail_view" name="Slide Detailed View">
<t t-call="website.layout">
<t t-set="main_object" t-value="slide"/>
@@ -1004,19 +557,6 @@
</li>
</template>
-
-<!-- Slide sub-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>
-</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>
@@ -1057,15 +597,4 @@
</div>
</template>
-<!-- User Navbar -->
-<template id="user_navbar_inherit_website_slides" inherit_id="website.user_navbar">
- <xpath expr="//div[@id='o_new_content_menu_choices']//div[@name='module_website_slides']" position="attributes">
- <attribute name="name"/>
- <attribute name="t-att-data-module-id"/>
- <attribute name="t-att-data-module-shortdesc"/>
- <attribute name="groups">website.group_website_designer</attribute>
- </xpath>
-</template>
-
-</data>
-</odoo>
+</data></odoo>
diff --git a/addons/website_slides/views/website_slides_embed_templates.xml b/addons/website_slides/views/website_slides_templates_lesson_embed.xml
index 059d2898a7e..059d2898a7e 100644
--- a/addons/website_slides/views/website_slides_embed_templates.xml
+++ b/addons/website_slides/views/website_slides_templates_lesson_embed.xml
diff --git a/addons/website_slides/views/website_slides_templates_utils.xml b/addons/website_slides/views/website_slides_templates_utils.xml
new file mode 100644
index 00000000000..57d5c2fced5
--- /dev/null
+++ b/addons/website_slides/views/website_slides_templates_utils.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" ?>
+<odoo><data>
+
+<!-- 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>
+</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>
+</template>
+
+<!-- Website edit page -->
+<template id="slide_edit_options" inherit_id="website.user_navbar" name="Edit Slide Options">
+ <xpath expr="//li[@id='edit-page-menu']" position="after">
+ <t t-if="main_object._name == 'slide.slide'" t-set="action" t-value="'website_slides.action_slides_slides'" />
+ </xpath>
+</template>
+
+<!-- User Navbar -->
+<template id="user_navbar_inherit_website_slides" inherit_id="website.user_navbar">
+ <xpath expr="//div[@id='o_new_content_menu_choices']//div[@name='module_website_slides']" position="attributes">
+ <attribute name="name"/>
+ <attribute name="t-att-data-module-id"/>
+ <attribute name="t-att-data-module-shortdesc"/>
+ <attribute name="groups">website.group_website_designer</attribute>
+ </xpath>
+</template>
+
+</data></odoo>
diff --git a/addons/website_slides/wizard/__init__.py b/addons/website_slides/wizard/__init__.py
new file mode 100644
index 00000000000..4020988908b
--- /dev/null
+++ b/addons/website_slides/wizard/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import slide_channel_invite
diff --git a/addons/website_slides/models/slide_channel_invite.py b/addons/website_slides/wizard/slide_channel_invite.py
index 094e82f57b4..094e82f57b4 100644
--- a/addons/website_slides/models/slide_channel_invite.py
+++ b/addons/website_slides/wizard/slide_channel_invite.py
diff --git a/addons/website_slides/views/slide_channel_invite_views.xml b/addons/website_slides/wizard/slide_channel_invite_views.xml
index cdb9ddd79bf..cdb9ddd79bf 100644
--- a/addons/website_slides/views/slide_channel_invite_views.xml
+++ b/addons/website_slides/wizard/slide_channel_invite_views.xml