summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
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