From 9ae7f5a2612a2e69a32d33dca5ba78775a8b09a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= <tde@odoo.com> Date: Tue, 19 Feb 2019 10:41:15 +0000 Subject: [PATCH] [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. --- addons/website_slides/__init__.py | 1 + addons/website_slides/__manifest__.py | 10 +- addons/website_slides/controllers/__init__.py | 1 + addons/website_slides/controllers/main.py | 6 +- addons/website_slides/models/__init__.py | 2 +- addons/website_slides/models/slide_channel.py | 75 ++- addons/website_slides/models/slide_slide.py | 54 +- .../views/website_slides_templates_course.xml | 420 ++++++++++++++++ ...ml => website_slides_templates_lesson.xml} | 475 +----------------- ...website_slides_templates_lesson_embed.xml} | 0 .../views/website_slides_templates_utils.xml | 41 ++ addons/website_slides/wizard/__init__.py | 4 + .../slide_channel_invite.py | 0 .../slide_channel_invite_views.xml | 0 14 files changed, 541 insertions(+), 548 deletions(-) create mode 100644 addons/website_slides/views/website_slides_templates_course.xml rename addons/website_slides/views/{website_slides_templates.xml => website_slides_templates_lesson.xml} (57%) rename addons/website_slides/views/{website_slides_embed_templates.xml => website_slides_templates_lesson_embed.xml} (100%) create mode 100644 addons/website_slides/views/website_slides_templates_utils.xml create mode 100644 addons/website_slides/wizard/__init__.py rename addons/website_slides/{models => wizard}/slide_channel_invite.py (100%) rename addons/website_slides/{views => wizard}/slide_channel_invite_views.xml (100%) diff --git a/addons/website_slides/__init__.py b/addons/website_slides/__init__.py index 7d34c7c054ab..887107072278 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 32b4f407e675..a5df3cf0cefa 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 acf000fd92cc..5f1516578614 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 50cea64c0781..f02484629949 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 2768668e3e41..9a55188c7aed 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 766fde193a0f..edb496a14e8d 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 fe022f83b31c..24e043be6e30 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 000000000000..5df196a2e1b4 --- /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>&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}&action=#{slide_action}&model=slide.slide&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 similarity index 57% rename from addons/website_slides/views/website_slides_templates.xml rename to addons/website_slides/views/website_slides_templates_lesson.xml index 7f0bc0d95536..3b3600b6e470 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}&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&url=#{record.website_url}&title=#{record.name}&" 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>&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}&action=#{slide_action}&model=slide.slide&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 similarity index 100% rename from addons/website_slides/views/website_slides_embed_templates.xml rename to 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 000000000000..57d5c2fced5d --- /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}&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&url=#{record.website_url}&title=#{record.name}&" 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 000000000000..4020988908bf --- /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 similarity index 100% rename from addons/website_slides/models/slide_channel_invite.py rename to 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 similarity index 100% rename from addons/website_slides/views/slide_channel_invite_views.xml rename to addons/website_slides/wizard/slide_channel_invite_views.xml -- GitLab