diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index 0494ae698c3e7c790e230e306d82af9f2d74c993..d6e1caceb93f27abb069cfb9c28457ff54043153 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -164,7 +164,8 @@ class WebsiteSlides(WebsiteProfile): if not request.env.user._is_public() and channel.is_member: slide_partners = request.env['slide.slide.partner'].sudo().search([ ('channel_id', '=', channel.id), - ('partner_id', '=', request.env.user.partner_id.id) + ('partner_id', '=', request.env.user.partner_id.id), + ('slide_id.active', '=', True) ]) for slide_partner in slide_partners: channel_progress[slide_partner.slide_id.id].update(slide_partner.read()[0]) @@ -666,9 +667,9 @@ class WebsiteSlides(WebsiteProfile): return slide.is_preview @http.route(['/slides/slide/send_share_email'], type='json', auth='user', website=True) - def slide_send_share_email(self, slide_id, email): + def slide_send_share_email(self, slide_id, email, fullscreen=False): slide = request.env['slide.slide'].browse(int(slide_id)) - result = slide._send_share_email(email) + result = slide._send_share_email(email, fullscreen) return result # -------------------------------------------------- diff --git a/addons/website_slides/data/mail_data.xml b/addons/website_slides/data/mail_data.xml index 226e2111e33578318ec8bc33e5f046dbb4dd392e..e00ddd2f78b9d696baf081a5319e002a7c1d1f7a 100644 --- a/addons/website_slides/data/mail_data.xml +++ b/addons/website_slides/data/mail_data.xml @@ -38,12 +38,12 @@ Hello<br/><br/> ${ctx['user'].name} shared the ${object.slide_type} <strong>${object.name}</strong> with you! <div style="margin: 16px 8px 16px 8px; text-align: center;"> - <a href="${object.website_url}"> + <a href="${(object.website_url + '?fullscreen=1') if ctx['fullscreen'] else object.website_url | safe}"> <img alt="${object.name}" src="${ctx['base_url']}/web/image/slide.slide/${object.id}/image" style="height:auto; width:150px; margin: 16px;"/> </a> </div> <div style="margin: 16px 8px 16px 8px; text-align: center;"> - <a href="${object.website_url}" + <a href="${(object.website_url + '?fullscreen=1') if ctx['fullscreen'] else object.website_url | safe}" style="background-color: #875a7b; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px;">View <strong>${object.name}</strong></a> </div> </p> diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index 8c06b195ff221f427822e8f41b65e62677b24ac0..b7e0eb55495afc2a606f3c07687701649c727cf6 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -356,15 +356,24 @@ class Slide(models.Model): ) return True - def _send_share_email(self, email): + def _generate_signed_token(self, partner_id): + """ Lazy generate the acces_token and return it signed by the given partner_id + :rtype tuple (string, int) + :return (signed_token, partner_id) + """ + if not self.access_token: + self.write({'access_token': self._default_access_token()}) + return self._sign_token(partner_id) + + def _send_share_email(self, email, fullscreen): # TDE FIXME: template to check mail_ids = [] base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') for record in self: if self.env.user.has_group('base.group_portal'): - mail_ids.append(self.channel_id.share_template_id.with_context(user=self.env.user, email=email, base_url=base_url).sudo().send_mail(record.id, notif_layout='mail.mail_notification_light', email_values={'email_from': self.env['res.company'].catchall or self.env['res.company'].email})) + mail_ids.append(self.channel_id.share_template_id.with_context(user=self.env.user, email=email, base_url=base_url, fullscreen=fullscreen).sudo().send_mail(record.id, notif_layout='mail.mail_notification_light', email_values={'email_from': self.env['res.company'].catchall or self.env['res.company'].email})) else: - mail_ids.append(self.channel_id.share_template_id.with_context(user=self.env.user, email=email, base_url=base_url).send_mail(record.id, notif_layout='mail.mail_notification_light')) + mail_ids.append(self.channel_id.share_template_id.with_context(user=self.env.user, email=email, base_url=base_url, fullscreen=fullscreen).send_mail(record.id, notif_layout='mail.mail_notification_light')) return mail_ids def action_like(self): diff --git a/addons/website_slides/static/src/js/slides_course_fullscreen_player.js b/addons/website_slides/static/src/js/slides_course_fullscreen_player.js index 42fce775674d120097b451718340433119441ce6..22e8b126b2d8eb3f55c16ba39a1710ec4b2b3355 100644 --- a/addons/website_slides/static/src/js/slides_course_fullscreen_player.js +++ b/addons/website_slides/static/src/js/slides_course_fullscreen_player.js @@ -7,11 +7,14 @@ odoo.define('website_slides.fullscreen', function (require) { var core = require('web.core'); var config = require('web.config'); var QWeb = core.qweb; + var _t = core._t; var session = require('web.session'); var Quiz = require('website_slides.quiz'); + var Dialog = require('web.Dialog'); + /** * Helper: Get the slide dict matching the given criteria @@ -276,6 +279,104 @@ odoo.define('website_slides.fullscreen', function (require) { }, }); + var ShareDialog = Dialog.extend({ + template: 'website.slide.share.modal', + events: { + 'click .o_wslides_js_share_email button': '_onShareByEmailClick', + 'click a.o_wslides_js_social_share': '_onSlidesSocialShare', + 'click .o_clipboard_button': '_onShareLinkCopy', + }, + + init: function (parent, options, slide) { + options = _.defaults(options || {}, { + title: "Share", + buttons: [{text: "Cancel", close: true}], + size: 'medium', + }); + this._super(parent, options); + this.slide = slide; + this.session = session; + }, + + _onShareByEmailClick: function() { + var form = this.$('.o_wslides_js_share_email'); + var input = form.find('input'); + var slideID = form.find('button').data('slide-id'); + if (input.val() && input[0].checkValidity()) { + form.removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid'); + this._rpc({ + route: '/slides/slide/send_share_email', + params: { + slide_id: slideID, + email: input.val(), + fullscreen: true + }, + }).then(function () { + form.html('<div class="alert alert-info" role="alert">' + _t('<strong>Thank you!</strong> Mail has been sent.') + '</div>'); + }); + } else { + form.addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid'); + input.focus(); + } + }, + + _onSlidesSocialShare: function (ev) { + ev.preventDefault(); + var popUpURL = $(ev.currentTarget).attr('href'); + window.open(popUpURL, 'Share Dialog', 'width=626,height=436'); + }, + + _onShareLinkCopy: function (ev) { + ev.preventDefault(); + var $clipboardBtn = this.$('.o_clipboard_button'); + $clipboardBtn.tooltip({title: "Copied !", trigger: "manual", placement: "bottom"}); + var self = this; + var clipboard = new ClipboardJS('.o_clipboard_button', { + target: function () { + return self.$('.o_wslides_js_share_link')[0]; + }, + container: this.el + }); + clipboard.on('success', function () { + clipboard.destroy(); + $clipboardBtn.tooltip('show'); + _.delay(function () { + $clipboardBtn.tooltip("hide"); + }, 800); + }); + clipboard.on('error', function (e) { + console.log(e); + clipboard.destroy(); + }) + }, + + }); + + var ShareButton = publicWidget.Widget.extend({ + events: { + "click .o_wslides_fs_share": '_onClickShareSlide' + }, + + init: function (el, slide) { + var result = this._super.apply(this, arguments); + this.slide = slide; + return result; + }, + + _openDialog: function() { + return new ShareDialog(this, {}, this.slide).open(); + }, + + _onClickShareSlide: function (ev) { + ev.preventDefault(); + this._openDialog(); + }, + + _onChangeSlide: function (currentSlide) { + this.slide = currentSlide; + } + + }); /** * This widget's purpose is to show content of a course, naviguating through contents @@ -315,6 +416,7 @@ odoo.define('website_slides.fullscreen', function (require) { this.set('slide', slide); this.sidebar = new Sidebar(this, this.slides, slide); + this.shareButton = new ShareButton(this, slide); return result; }, /** @@ -339,6 +441,7 @@ odoo.define('website_slides.fullscreen', function (require) { attachTo: function (){ var defs = [this._super.apply(this, arguments)]; defs.push(this.sidebar.attachTo(this.$('.o_wslides_fs_sidebar'))); + defs.push(this.shareButton.attachTo(this.$('.o_wslides_slide_fs_header'))); return $.when.apply($, defs); }, //-------------------------------------------------------------------------- @@ -517,6 +620,7 @@ odoo.define('website_slides.fullscreen', function (require) { isQuiz: slideData.isQuiz || false, }); this.set('slide', newSlide); + this.shareButton._onChangeSlide(newSlide); }, /** * Triggered when subwidget has mark the slide as done, and the UI need to be adapted. @@ -570,7 +674,7 @@ odoo.define('website_slides.fullscreen', function (require) { publicWidget.registry.websiteSlidesFullscreenPlayer = publicWidget.Widget.extend({ selector: '.o_wslides_fs_main', - xmlDependencies: ['/website_slides/static/src/xml/website_slides_fullscreen.xml'], + xmlDependencies: ['/website_slides/static/src/xml/website_slides_fullscreen.xml', '/website_slides/static/src/xml/website_slides_share.xml'], start: function (){ var proms = [this._super.apply(this, arguments)]; var fullscreen = new Fullscreen(this, this._getSlides(), this._getCurrentSlideID(), this._extractChannelData()); diff --git a/addons/website_slides/static/src/js/slides_share.js b/addons/website_slides/static/src/js/slides_share.js index d89cdfcb4bf8f3c53921b1d306cb5ea94ee90a2d..d23b48c5c9a731df0e84fdb2a165686fa20f4ad4 100644 --- a/addons/website_slides/static/src/js/slides_share.js +++ b/addons/website_slides/static/src/js/slides_share.js @@ -41,7 +41,8 @@ var ShareMail = publicWidget.Widget.extend({ publicWidget.registry.websiteSlidesShare = publicWidget.Widget.extend({ selector: '#wrapwrap', events: { - 'click a.o_slides_social_share': '_onSlidesSocialShare', + 'click a.o_wslides_js_social_share': '_onSlidesSocialShare', + 'click .o_clipboard_button': '_onShareLinkCopy', }, /** @@ -73,5 +74,29 @@ publicWidget.registry.websiteSlidesShare = publicWidget.Widget.extend({ } }); }, + + _onShareLinkCopy: function (ev) { + ev.preventDefault(); + var $clipboardBtn = this.$('.o_clipboard_button'); + $clipboardBtn.tooltip({title: "Copied !", trigger: "manual", placement: "bottom"}); + var self = this; + var clipboard = new ClipboardJS('.o_clipboard_button', { + target: function () { + return self.$('.o_wslides_js_share_link')[0]; + }, + container: this.el + }); + clipboard.on('success', function () { + clipboard.destroy(); + $clipboardBtn.tooltip('show'); + _.delay(function () { + $clipboardBtn.tooltip("hide"); + }, 800); + }); + clipboard.on('error', function (e) { + console.log(e); + clipboard.destroy(); + }) + }, }); }); diff --git a/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss b/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss index 36a173dc2550009f9ab06436a0b485cc180018c1..fe6914d25f5fbe4eb32cdbd2b10678d884330695 100644 --- a/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss +++ b/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss @@ -1,7 +1,7 @@ .o_wslides_fs_main { @include o-position-absolute(0,0,0,0); - z-index: 2000; + z-index: 1040; background-image: linear-gradient(120deg, $o-wslides-color-dark2, $o-wslides-color-dark3); .o_wslides_slide_fs_header { diff --git a/addons/website_slides/static/src/xml/website_slides_share.xml b/addons/website_slides/static/src/xml/website_slides_share.xml new file mode 100644 index 0000000000000000000000000000000000000000..7aa115918db00856d6af6146a0d9139e358be1d3 --- /dev/null +++ b/addons/website_slides/static/src/xml/website_slides_share.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<templates xml:space="preserve"> + + <t t-name="website.slide.share.modal"> + <div> + <t t-call="website.slide.share.socialmedia"/> + </div> + </t> + + <t t-name="website.slide.share.socialmedia"> + <div class="row"> + <div class="col-12 col-lg-6 mb-4"> + <h5 class="mt-0 mb-2">Share on Social Networks</h5> + <div class="btn-group" role="group"> + <a t-attf-href="https://www.facebook.com/sharer/sharer.php?u=#{window.location.href}" class="btn border bg-white o_wslides_js_social_share" social-key="facebook" aria-label="Share on Facebook" title="Share on Facebook"><i class="fa fa-facebook-square fa-fw"/></a> + <a t-attf-href="https://twitter.com/intent/tweet?text=#{widget.slide.name}&url=#{window.location.href}" class="btn border bg-white o_wslides_js_social_share" social-key="twitter" aria-label="Share on Twitter" title="Share on Twitter"><i class="fa fa-twitter fa-fw"/></a> + <a t-attf-href="http://www.linkedin.com/shareArticle?mini=true&url=#{window.location.href}&title=#{widget.slide.name}&" social-key="linkedin" class="btn border bg-white o_wslides_js_social_share" aria-label="Share on LinkedIn" title="Share on LinkedIn"><i class="fa fa-linkedin fa-fw"/></a> + </div> + </div> + <div class="col-12 col-lg-6"> + <h5 class="mt-0 mb-2">Share Link</h5> + <div class="input-group"> + <input type="text" class="form-control o_wslides_js_share_link" t-att-value="window.location.href" readonly="readonly" onClick="this.select();" /> + <div class="input-group-append"> + <button class="btn btn-sm btn-primary o_clipboard_button" style="border-top-right-radius: 4px;border-bottom-right-radius: 4px;" > + <span class="fa fa-clipboard"> Copy Link</span> + </button> + </div> + </div> + </div> + <div t-attf-class="col-12 col-lg-6"> + <t t-call="website.slide.share.email"/> + </div> + </div> + </t> + + <t t-name="website.slide.share.email"> + <h5 class="mt-4">Share by mail</h5> + <div t-if="!widget.session.is_website_user" class="form-inline"> + <form class="form-group o_wslides_js_share_email" role="form"> + <div class="input-group"> + <input type="email" class="form-control" placeholder="your-friend@domain.com"/> + <span class="input-group-append"> + <button class="btn btn-primary" type="button" + data-loading-text="Sending..." + t-attf-data-slide-id="#{widget.slide.id}" + style="border-top-right-radius: 4px;border-bottom-right-radius: 4px;"> + <i class="fa fa-envelope-o"/> Send Email + </button> + </span> + </div> + </form> + </div> + <div t-if="widget.session.is_website_user" class="alert alert-info d-inline-block"> + <p class="mb-0">Please <a t-attf-href="/web?redirect=#{window.location.href}" class="font-weight-bold"> login </a> to share this <t t-esc="widget.slide.type"/> by email.</p> + </div> + </t> + +</templates> \ No newline at end of file diff --git a/addons/website_slides/views/website_slides_templates_course.xml b/addons/website_slides/views/website_slides_templates_course.xml index 6fbdde87bc5cf0b946d913e405d2a5837f41f88b..bfde708c6dfccf6a1ebaeb432d62717f1de44c2d 100644 --- a/addons/website_slides/views/website_slides_templates_course.xml +++ b/addons/website_slides/views/website_slides_templates_course.xml @@ -307,8 +307,15 @@ <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 class="input-group"> + <input type="text" class="form-control o_wslides_js_share_link" readonly="readonly" onclick="this.select();" + t-att-value="channel.website_url"/> + <div class="input-group-append"> + <button class="btn btn-sm btn-primary o_clipboard_button" > + <span class="fa fa-clipboard"> Copy Text</span> + </button> + </div> + </div> </div> </div> </div> diff --git a/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml b/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml index 43b5f3483752d766cbd093d7bd952249e8730a20..0b28617a206ed832e117dfc25f2059dfc5a49ef4 100644 --- a/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml +++ b/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml @@ -20,6 +20,9 @@ <a class="o_wslides_fs_review d-flex align-items-center px-3" t-att-href="slide.channel_id.website_url + '?active_tab=review'" title="Reviews" t-if="slide.channel_id.allow_comment"> <i class="fa fa-pencil"/><span class="d-none d-md-inline-block ml-1">Write a review</span> </a> + <a class="o_wslides_fs_share d-flex align-items-center px-3" href="#" title="Share"> + <i class="fa fa-share-alt"/><span class="d-none d-md-inline-block ml-1">Share</span> + </a> </div> <div class="d-flex ml-auto"> <a class="d-flex align-items-center px-3 o_wslides_fs_exit_fullscreen" t-attf-href="/slides/slide/#{slug(slide)}"> diff --git a/addons/website_slides/views/website_slides_templates_utils.xml b/addons/website_slides/views/website_slides_templates_utils.xml index d510f2ed5191d365b57dc824c939f3b95783bf7b..580b54023cb6b227d6c18f97a0b4e4dd58fed560 100644 --- a/addons/website_slides/views/website_slides_templates_utils.xml +++ b/addons/website_slides/views/website_slides_templates_utils.xml @@ -4,9 +4,9 @@ <!-- Share on social networks --> <template id='slides_share' name="Slides Media Share"> <div class="btn-group" role="group"> - <a t-attf-href="https://www.facebook.com/sharer/sharer.php?u=#{record.website_url}" class="btn border bg-white o_slides_social_share" social-key="facebook" aria-label="Share on Facebook" title="Share on Facebook"><i class="fa fa-facebook-square fa-fw"/></a> - <a t-attf-href="https://twitter.com/intent/tweet?text=#{record.name}&url=#{record.website_url}" class="btn border bg-white o_slides_social_share" social-key="twitter" aria-label="Share on Twitter" title="Share on Twitter"><i class="fa fa-twitter fa-fw"/></a> - <a t-attf-href="http://www.linkedin.com/shareArticle?mini=true&url=#{record.website_url}&title=#{record.name}&" social-key="linkedin" class="btn border bg-white o_slides_social_share" aria-label="Share on LinkedIn" title="Share on LinkedIn"><i class="fa fa-linkedin fa-fw"/></a> + <a t-attf-href="https://www.facebook.com/sharer/sharer.php?u=#{record.website_url}" class="btn border bg-white o_wslides_js_social_share" social-key="facebook" aria-label="Share on Facebook" title="Share on Facebook"><i class="fa fa-facebook-square fa-fw"/></a> + <a t-attf-href="https://twitter.com/intent/tweet?text=#{record.name}&url=#{record.website_url}" class="btn border bg-white o_wslides_js_social_share" social-key="twitter" aria-label="Share on Twitter" title="Share on Twitter"><i class="fa fa-twitter fa-fw"/></a> + <a t-attf-href="http://www.linkedin.com/shareArticle?mini=true&url=#{record.website_url}&title=#{record.name}&" social-key="linkedin" class="btn border bg-white o_wslides_js_social_share" aria-label="Share on LinkedIn" title="Share on LinkedIn"><i class="fa fa-linkedin fa-fw"/></a> </div> </template> @@ -21,7 +21,14 @@ </div> <div class="col-12 col-lg-6"> <h5 class="mt-0 mb-2">Share Link</h5> - <input type="text" class="form-control" t-att-value="slide.website_url" readonly="readonly" onClick="this.select();"/> + <div class="input-group"> + <input type="text" class="form-control o_wslides_js_share_link" id="shareLink" t-att-value="slide.website_url" readonly="readonly" onClick="this.select();"/> + <div class="input-group-append"> + <button class="btn btn-sm btn-primary o_clipboard_button" data-clipboard-target="#shareLink"> + <span class="fa fa-clipboard"> Copy Text</span> + </button> + </div> + </div> <span class="form-text text-muted">Use permanent link to share in social media</span> </div> </div>