diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index 9764cdde19e..db4088d193f 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -17,6 +17,7 @@ from odoo.addons.website_profile.controllers.main import WebsiteProfile from odoo.exceptions import AccessError, ValidationError, UserError, MissingError from odoo.http import request from odoo.osv import expression +from odoo.tools import email_split _logger = logging.getLogger(__name__) @@ -730,6 +731,14 @@ class WebsiteSlides(WebsiteProfile): return {'url': "/slides/%s" % (slug(channel))} + @http.route(['/slides/channel/send_share_email'], type='json', auth='user', website=True) + def slide_channel_send_share_email(self, channel_id, emails): + if not email_split(emails): + return False + channel = request.env['slide.channel'].browse(int(channel_id)) + channel._send_share_email(emails) + return True + @http.route(['/slides/channel/subscribe'], type='json', auth='user', website=True) def slide_channel_subscribe(self, channel_id): return request.env['slide.channel'].browse(channel_id).message_subscribe(partner_ids=[request.env.user.partner_id.id]) @@ -921,10 +930,12 @@ 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, fullscreen=False): + def slide_send_share_email(self, slide_id, emails, fullscreen=False): + if not email_split(emails): + return False slide = request.env['slide.slide'].browse(int(slide_id)) - result = slide._send_share_email(email, fullscreen) - return result + slide._send_share_email(emails, fullscreen) + return True # -------------------------------------------------- # TAGS SECTION diff --git a/addons/website_slides/data/mail_template_data.xml b/addons/website_slides/data/mail_template_data.xml index ce7f59e01e3..52e5fd00184 100644 --- a/addons/website_slides/data/mail_template_data.xml +++ b/addons/website_slides/data/mail_template_data.xml @@ -95,6 +95,39 @@ {{ object.partner_id.lang }} + + Channel Shared + + {{ user.name }} shared a Course + {{ user.email_formatted }} + +
+

+ Hello

+ Mitchell Admin shared the document with you! +

+ + + +
+
+ + View Document +
+ +
+ --
Mitchell Admin
+
+

+
+
+ +
+ Channel: Invite by email diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index d7be60fe5d3..f445d146aa8 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -251,7 +251,11 @@ class Channel(models.Model): help="Defines the email your Attendees will receive each time you upload new content.", default=lambda self: self.env['ir.model.data']._xmlid_to_res_id('website_slides.slide_template_published'), domain=[('model', '=', 'slide.slide')]) - share_template_id = fields.Many2one( + share_channel_template_id = fields.Many2one( + 'mail.template', string='Channel Share Template', + help='Email template used when sharing a channel', + default=lambda self: self.env['ir.model.data']._xmlid_to_res_id('website_slides.mail_template_channel_shared')) + share_slide_template_id = fields.Many2one( 'mail.template', string='Share Template', help="Email template used when sharing a slide", default=lambda self: self.env['ir.model.data']._xmlid_to_res_id('website_slides.slide_template_shared')) @@ -752,6 +756,23 @@ class Channel(models.Model): if removed_channel_partner_domain: self.env['slide.channel.partner'].sudo().search(removed_channel_partner_domain).unlink() + def _send_share_email(self, emails): + """ Share channel through emails.""" + mail_ids = [] + for record in self: + template = record.share_channel_template_id.with_context( + user=self.env.user, + email=emails, + base_url=record.get_base_url(), + ) + email_values = {'email_to': emails} + if self.env.user.has_group('base.group_portal'): + template = template.sudo() + email_values['email_from'] = self.env.company.catchall_formatted or self.env.company.email_formatted + + mail_ids.append(template.send_mail(record.id, email_layout_xmlid='mail.mail_notification_light', email_values=email_values)) + return mail_ids + def action_view_slides(self): action = self.env["ir.actions.actions"]._for_xml_id("website_slides.slide_slide_action") action['context'] = { diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index 31fa287f9c0..ac3bc91b808 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -804,7 +804,7 @@ class Slide(models.Model): # TDE FIXME: template to check mail_ids = [] for record in self: - template = record.channel_id.share_template_id.with_context( + template = record.channel_id.share_slide_template_id.with_context( user=self.env.user, email=email, base_url=record.get_base_url(), 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 32433f09a60..8f33cb85dac 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 @@ -368,12 +368,13 @@ 'click .o_wslides_js_share_email button': '_onShareByEmailClick', 'click a.o_wslides_js_social_share': '_onSlidesSocialShare', 'click .o_clipboard_button': '_onShareLinkCopy', + 'keypress .o_wslides_js_share_email input': '_onKeypress', }, init: function (parent, options, slide) { options = _.defaults(options || {}, { - title: "Share", - buttons: [{text: "Cancel", close: true}], + title: _t("Share This Content"), + buttons: [{text: "Close", close: true}], size: 'medium', }); this._super(parent, options); @@ -381,23 +382,48 @@ this.session = session; }, - _onShareByEmailClick: function() { + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Send the email(s) on 'Enter' key + * + * @private + * @param {Event} ev + */ + _onKeypress: function (ev) { + if (ev.keyCode === $.ui.keyCode.ENTER) { + ev.preventDefault(); + this._onShareByEmailClick(); + } + }, + + _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()) { + if (input.val()) { form.removeClass('o_has_error').find('.form-control, .form-select').removeClass('is-invalid'); + var slideID = form.find('button').data('slide-id'); this._rpc({ route: '/slides/slide/send_share_email', params: { slide_id: slideID, - email: input.val(), + emails: input.val(), fullscreen: true }, - }).then(function () { - form.html(''); + }).then((action) => { + if (action) { + form.find('.alert-info').removeClass('d-none'); + form.find('.input-group').addClass('d-none'); + } else { + this.displayNotification({ message: _t('Please enter valid email(s)'), type: 'danger' }); + form.addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid'); + input.focus(); + } }); } else { + this.displayNotification({ message: _t('Please enter valid email(s)'), type: 'danger' }); form.addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid'); input.focus(); } @@ -405,6 +431,7 @@ _onSlidesSocialShare: function (ev) { ev.preventDefault(); + ev.stopPropagation(); var popUpURL = $(ev.currentTarget).attr('href'); window.open(popUpURL, 'Share Dialog', 'width=626,height=436'); }, @@ -506,6 +533,10 @@ var self = this; this.on('change:slide', this, this._onChangeSlide); this._toggleSidebar(); + const backendNavEl = document.querySelector('.o_frontend_to_backend_nav'); + if (backendNavEl) { + backendNavEl.remove(); + } return this._super.apply(this, arguments).then(function () { return self._onChangeSlide(); // trigger manually once DOM ready, since slide content is not rendered server side }); diff --git a/addons/website_slides/static/src/js/slides_embed.js b/addons/website_slides/static/src/js/slides_embed.js index 52356ce5d56..0083884a95b 100644 --- a/addons/website_slides/static/src/js/slides_embed.js +++ b/addons/website_slides/static/src/js/slides_embed.js @@ -227,22 +227,29 @@ $(function () { var widget = $('.oe_slide_js_share_email'); var input = widget.find('input'); var slideID = widget.find('button').data('slide-id'); - if (input.val() && input[0].checkValidity()) { + if (input.val()) { widget.removeClass('o_has_error').find('.form-control, .form-select').removeClass('is-invalid'); $.ajax({ type: "POST", dataType: 'json', url: '/slides/slide/send_share_email', contentType: "application/json; charset=utf-8", - data: JSON.stringify({'jsonrpc': "2.0", 'method': "call", "params": {'slide_id': slideID, 'email': input.val()}}), - success: function () { - widget.html($('')); - }, - error: function (data) { - console.error("ERROR ", data); + data: JSON.stringify({'jsonrpc': "2.0", 'method': "call", "params": {'slide_id': slideID, 'emails': input.val()}}), + success: function (action) { + if (action.result) { + widget.find('.alert-info').removeClass('d-none'); + widget.find('.input-group').addClass('d-none'); + } else { + widget.find('.alert-warning').removeClass('d-none'); + widget.find('.input-group').addClass('d-none'); + widget.addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid'); + input.focus(); + } }, }); } else { + widget.find('.alert-warning').removeClass('d-none'); + widget.find('.input-group').addClass('d-none'); widget.addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid'); input.focus(); } diff --git a/addons/website_slides/static/src/js/slides_share.js b/addons/website_slides/static/src/js/slides_share.js index e5f8966dc0a..80ca5361e07 100644 --- a/addons/website_slides/static/src/js/slides_share.js +++ b/addons/website_slides/static/src/js/slides_share.js @@ -7,31 +7,61 @@ import { _t } from 'web.core'; var ShareMail = publicWidget.Widget.extend({ events: { 'click button': '_sendMail', + 'keypress input': '_onKeypress', }, //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- + /** + * Send the email(s) on 'Enter' key + * + * @private + * @param {Event} ev + */ + _onKeypress: function (ev) { + if (ev.keyCode === $.ui.keyCode.ENTER) { + ev.preventDefault(); + this._sendMail(); + } + }, + /** * @private */ _sendMail: function () { - var self = this; - var input = this.$('input'); - var slideID = this.$('button').data('slide-id'); - if (input.val() && input[0].checkValidity()) { + const input = this.$('input'); + if (input.val()) { + const slideID = this.$('button').data('slide-id'); + const channelID = this.$('button').data('channel-id'); + const params = { + emails: input.val(), + }; + let route; + if (slideID) { + route = '/slides/slide/send_share_email'; + params.slide_id = slideID; + } else if (channelID) { + route = '/slides/channel/send_share_email'; + params.channel_id = channelID; + } this.$el.removeClass('o_has_error').find('.form-control, .form-select').removeClass('is-invalid'); this._rpc({ - route: '/slides/slide/send_share_email', - params: { - slide_id: slideID, - email: input.val(), - }, - }).then(function () { - self.$el.html($('')); + route, + params + }).then((action) => { + if (action) { + this.$('.alert-info').removeClass('d-none'); + this.$('.input-group').addClass('d-none'); + } else { + this.displayNotification({ message: _t('Please enter valid email(s)'), type: 'danger' }); + this.$el.addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid'); + input.focus(); + } }); } else { + this.displayNotification({ message: _t('Please enter valid email(s)'), type: 'danger' }); this.$el.addClass('o_has_error').find('.form-control, .form-select').addClass('is-invalid'); input.focus(); } @@ -66,6 +96,7 @@ publicWidget.registry.websiteSlidesShare = publicWidget.Widget.extend({ */ _onSlidesSocialShare: function (ev) { ev.preventDefault(); + ev.stopPropagation(); var popUpURL = $(ev.currentTarget).attr('href'); var popUp = window.open(popUpURL, 'Share Dialog', 'width=626,height=436'); $(window).on('focus', function () { @@ -100,3 +131,34 @@ publicWidget.registry.websiteSlidesShare = publicWidget.Widget.extend({ }) }, }); + +publicWidget.registry.websiteSlidesEmbedShare = publicWidget.Widget.extend({ + selector: '.oe_slide_js_embed_code_widget', + events: { + 'click .o_embed_clipboard_button': '_onShareLinkCopy', + }, + + _onShareLinkCopy: function (ev) { + ev.preventDefault(); + const $clipboardBtn = $(ev.currentTarget); + $clipboardBtn.tooltip({title: "Copied !", trigger: "manual", placement: "bottom"}); + const clipboard = new ClipboardJS('#' + $clipboardBtn[0].id, { + target: () => { + const share_embed_el = this.$('#wslides_share_embed_id_' + $clipboardBtn[0].id.split('id_')[1]); + return share_embed_el[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 689e0bf33d7..4fb858435f8 100644 --- a/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss +++ b/addons/website_slides/static/src/scss/slides_slide_fullscreen.scss @@ -80,7 +80,6 @@ .o_wslides_fs_sidebar_section_slides li { color: rgba(white, 0.8); - line-height: 1.3; &.active { box-shadow: inset 2px 0 0 map-get($theme-colors, 'primary'); @@ -91,8 +90,20 @@ } } - .o_wslides_fs_slide_name { - line-height: 1; + .o_wslides_sidebar_content { + line-height: unset; + i { + line-height: unset; + } + } + + .o_wslides_sidebar_done_button { + line-height: unset; + + button { + padding-top: 0; + border-top: 0; + } } } } diff --git a/addons/website_slides/static/src/scss/website_slides.scss b/addons/website_slides/static/src/scss/website_slides.scss index b0093963dc7..4dff653aa63 100644 --- a/addons/website_slides/static/src/scss/website_slides.scss +++ b/addons/website_slides/static/src/scss/website_slides.scss @@ -536,14 +536,17 @@ $line-height-truncate: 1.25em; .o_wslides_lesson_aside_list_link { @include o-hover-text-color($gray-600, $headings-color ); - .o_wslides_lesson_link_name { - line-height: 1.2; - } - &.active { box-shadow:inset 2px 0 map-get($theme-colors, 'primary'); } } + button { + padding-top: 0; + border-top: 0; + } + i { + line-height: unset; + } .o_wslides_button_complete { margin-left: 5px; } diff --git a/addons/website_slides/static/src/xml/website_slides_share.xml b/addons/website_slides/static/src/xml/website_slides_share.xml index 954868550ae..e82888b9039 100644 --- a/addons/website_slides/static/src/xml/website_slides_share.xml +++ b/addons/website_slides/static/src/xml/website_slides_share.xml @@ -8,42 +8,66 @@
-
-
Share on Social Networks
-
- - - -
-
-
+
Share Link
- -
-
+
+
Share on Social Media
+ +
+
-
Share by mail
+
Share by Email
- -
+
diff --git a/addons/website_slides/static/src/xml/website_slides_sidebar.xml b/addons/website_slides/static/src/xml/website_slides_sidebar.xml index 7b9e9ee0c67..7dca825271e 100644 --- a/addons/website_slides/static/src/xml/website_slides_sidebar.xml +++ b/addons/website_slides/static/src/xml/website_slides_sidebar.xml @@ -12,10 +12,10 @@ -
+
+
diff --git a/addons/website_slides/views/slide_channel_views.xml b/addons/website_slides/views/slide_channel_views.xml index 733139928d0..0a5a95c6d0d 100644 --- a/addons/website_slides/views/slide_channel_views.xml +++ b/addons/website_slides/views/slide_channel_views.xml @@ -109,7 +109,8 @@ - + + diff --git a/addons/website_slides/views/website_slides_templates_course.xml b/addons/website_slides/views/website_slides_templates_course.xml index 22c1456a232..55cd4211215 100644 --- a/addons/website_slides/views/website_slides_templates_course.xml +++ b/addons/website_slides/views/website_slides_templates_course.xml @@ -135,14 +135,6 @@

- -
- -
@@ -169,12 +161,6 @@

- - - - - -
@@ -243,11 +229,6 @@
- - - - - @@ -283,9 +264,14 @@
+ + + Share This Course + +
diff --git a/addons/website_slides/views/website_slides_templates_lesson.xml b/addons/website_slides/views/website_slides_templates_lesson.xml index f86a9d64b4a..6557239d599 100644 --- a/addons/website_slides/views/website_slides_templates_lesson.xml +++ b/addons/website_slides/views/website_slides_templates_lesson.xml @@ -113,7 +113,7 @@ - - - - - - diff --git a/addons/website_slides/views/website_slides_templates_lesson_embed.xml b/addons/website_slides/views/website_slides_templates_lesson_embed.xml index 55c47fa46bf..4b16990e068 100644 --- a/addons/website_slides/views/website_slides_templates_lesson_embed.xml +++ b/addons/website_slides/views/website_slides_templates_lesson_embed.xml @@ -28,7 +28,7 @@
- + Share 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 4f57bda0dc8..63341c1d1c9 100644 --- a/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml +++ b/addons/website_slides/views/website_slides_templates_lesson_fullscreen.xml @@ -36,13 +36,15 @@ + - - Share -
+ + + Share + Exit Fullscreen @@ -106,7 +108,7 @@ -
  • -
    +
    -
    +
    -
    +
    -
      +
      • diff --git a/addons/website_slides/views/website_slides_templates_utils.xml b/addons/website_slides/views/website_slides_templates_utils.xml index a7efdcea705..bae724f3cfa 100644 --- a/addons/website_slides/views/website_slides_templates_utils.xml +++ b/addons/website_slides/views/website_slides_templates_utils.xml @@ -8,24 +8,84 @@ t-value="record.website_share_url if 'website_share_url' in record else record.website_url"/> + + + + + + +