From a912c093040312eac72287baff4320bb382e3f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 25 Jan 2019 12:46:31 +0000 Subject: [PATCH 1/6] [FIX] website_slides: fix various calls undefined methods Several places call 'this' whether it is not linked to the current object. Use self instead. This commit is linked to task ID 1933820 and PR #30553. --- addons/website_slides/static/src/js/slides_share.js | 3 ++- addons/website_slides/static/src/js/slides_upload.js | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/addons/website_slides/static/src/js/slides_share.js b/addons/website_slides/static/src/js/slides_share.js index b90f7398ab0..cc10629e191 100644 --- a/addons/website_slides/static/src/js/slides_share.js +++ b/addons/website_slides/static/src/js/slides_share.js @@ -50,6 +50,7 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({ * @param {Object} parent */ start: function (parent) { + var self = this; var defs = [this._super.apply(this, arguments)]; defs.push(new ShareMail(this).attachTo($('.oe_slide_js_share_email'))); @@ -64,7 +65,7 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({ } _.each(socialURLs, function (value, key) { - this._updateStatistics(key, slideURL); + self._updateStatistics(key, slideURL); }); return $.when.apply($, defs); diff --git a/addons/website_slides/static/src/js/slides_upload.js b/addons/website_slides/static/src/js/slides_upload.js index dd1c9a6f3a1..e47749f7ab9 100644 --- a/addons/website_slides/static/src/js/slides_upload.js +++ b/addons/website_slides/static/src/js/slides_upload.js @@ -53,7 +53,6 @@ var SlideDialog = Widget.extend({ * @param {string} file_name */ _checkUniqueSlide: function (fileName) { - var self = this; return this._rpc({ model: 'slide.slide', method: 'search_count', @@ -148,7 +147,7 @@ var SlideDialog = Widget.extend({ var self = this; $('#category_id').select2(this._select2Wrapper(_t('Category'), false, function () { - return this._rpc({ + return self._rpc({ model: 'slide.category', method: 'search_read', args: [], @@ -175,8 +174,9 @@ var SlideDialog = Widget.extend({ * @private */ _setTagIds: function () { + var self = this; $('#tag_ids').select2(this._select2Wrapper(_t('Tags'), true, function () { - return this._rpc({ + return self._rpc({ model: 'slide.tag', method: 'search_read', args: [], From d3e462b279e9ecd24bf78d0707e2c297e48bff8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 25 Jan 2019 13:03:55 +0000 Subject: [PATCH 2/6] [FIX] website_slides: fix statistics computation Statistics computation section is a bit broken as some variables are incorrectly defined or propagated. This commit is linked to task ID 1933820 and PR #30553. --- .../website_slides/static/src/js/slides_share.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/addons/website_slides/static/src/js/slides_share.js b/addons/website_slides/static/src/js/slides_share.js index cc10629e191..1dfaa3aee41 100644 --- a/addons/website_slides/static/src/js/slides_share.js +++ b/addons/website_slides/static/src/js/slides_share.js @@ -55,8 +55,8 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({ defs.push(new ShareMail(this).attachTo($('.oe_slide_js_share_email'))); if ($('div#statistic').length) { - var slideURL = $('div#statistic').attr('slide-url'); - var socialURLs = { + this.slideURL = $('div#statistic').attr('slide-url'); + this.socialURLs = { linkedin: 'https://www.linkedin.com/countserv/count/share?url=', twitter: 'https://cdn.api.twitter.com/1/urls/count.json?url=', facebook: 'https://graph.facebook.com/?id=', @@ -64,9 +64,9 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({ }; } - _.each(socialURLs, function (value, key) { - self._updateStatistics(key, slideURL); - }); + _.each(this.socialURLs, function (value, key) { + self._updateStatistics(key, self.slideURL); + }); return $.when.apply($, defs); }, @@ -81,9 +81,10 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({ * @param {string} slide_url */ _updateStatistics: function (socialSite, slideURL) { + var self = this; if (socialSite === 'gplus') { $.ajax({ - url: this.social_urls['gplus'], + url: self.socialURLs['gplus'], type: 'POST', dataType: 'json', contentType: 'application/json', @@ -108,7 +109,7 @@ sAnimations.registry.websiteSlidesShare = sAnimations.Class.extend({ }); } else { $.ajax({ - url: this.social_urls[socialSite] + slideURL, + url: self.socialURLs[socialSite] + slideURL, dataType: 'jsonp', success: function (data) { var shareCount = (socialSite === 'facebook' ? data.shares : data.count) || 0; From 2db50e579663a7be16697f9ff0a0e0baab361a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 25 Jan 2019 15:07:35 +0000 Subject: [PATCH 3/6] [FIX] website_slides: quickly fix pdf viewer not appearing Pdf viewer does not display or is incorrectly displayed. This commit proposes a minimal fix to at least display the iframe holding the pdf viewer. This will be improved with eLearning improvements for slides. This commit is linked to task ID 1933820 and PR #30553. --- addons/website_slides/static/src/scss/website_slides.scss | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/website_slides/static/src/scss/website_slides.scss b/addons/website_slides/static/src/scss/website_slides.scss index f67344fdbb6..658d973a5a0 100644 --- a/addons/website_slides/static/src/scss/website_slides.scss +++ b/addons/website_slides/static/src/scss/website_slides.scss @@ -153,6 +153,13 @@ textarea.o_slides_comment { padding: 10px; } +// Slide display +div.embed-responsive { + iframe.o_wslides_iframe_viewer { + position: relative; + } +} + // PDF Viewer Share bar .oe_slides_share_bar{ padding: 10px 0; From c5da7b8aeb8b5de224bd9c142908f742b759eb16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 25 Jan 2019 16:47:20 +0000 Subject: [PATCH 4/6] [IMP] website_slides: improve like / dislike Like / dislike of slides is fixed and improved to make a tri-state like behavior. Future commit will change this implementation in order to use a relationship table between users and slides as we are moving towards the eLearning platform. Let us have this simple implementation currently and rewrite it in a near future. This commit is linked to task ID 1933820 and PR #30553. --- addons/website_slides/controllers/main.py | 48 ++++++++++--- .../static/src/js/slides_like.js | 71 ++++++++++--------- .../static/src/scss/website_slides.scss | 2 +- .../views/website_slides_templates.xml | 16 ++--- 4 files changed, 81 insertions(+), 56 deletions(-) diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index f04a61c4903..6a3e52727dc 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -35,6 +35,28 @@ class WebsiteSlides(http.Controller): request.session[slide_key] = viewed_slides return True + def _check_session_slide_vote(self, slide, upvote=True): + if not request.session.get('__wslides_upvote'): + request.session['__wslides_upvote'] = [] + if not request.session.get('__wslides_downvote'): + request.session['__wslides_downvote'] = [] + if upvote and slide.id in request.session['__wslides_upvote']: + return False + if not upvote and slide.id in request.session['__wslides_downvote']: + return False + if upvote and slide.id in request.session['__wslides_downvote']: + request.session['__wslides_downvote'].remove(slide.id) + return 0 + if not upvote and slide.id in request.session['__wslides_upvote']: + request.session['__wslides_upvote'].remove(slide.id) + return 0 + if upvote: + request.session['__wslides_upvote'].append(slide.id) + return 1 + if not upvote: + request.session['__wslides_downvote'].append(slide.id) + return -1 + 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) @@ -209,16 +231,24 @@ class WebsiteSlides(http.Controller): # JSONRPC @http.route('/slides/slide/like', type='json', auth="user", website=True) - def slide_like(self, slide_id): + def slide_like(self, slide_id, upvote): + if request.website.is_public_user(): + return {'error': 'public_user'} slide = request.env['slide.slide'].browse(int(slide_id)) - slide.likes += 1 - return slide.likes - - @http.route('/slides/slide/dislike', type='json', auth="user", website=True) - def slide_dislike(self, slide_id): - slide = request.env['slide.slide'].browse(int(slide_id)) - slide.dislikes += 1 - return slide.dislikes + slide.check_access_rights('read') + slide.check_access_rule('read') + check = self._check_session_slide_vote(slide, upvote=upvote) + if check is False: + return {'error': 'vote_done'} + if check == 1: + slide.sudo().likes += 1 + elif check == 0 and upvote: + slide.sudo().dislikes -= 1 + elif check == 0 and not upvote: + slide.sudo().likes -= 1 + else: + slide.sudo().dislikes += 1 + return {'state': check, 'likes': slide.likes, 'dislikes': slide.dislikes} @http.route(['/slides/slide/send_share_email'], type='json', auth='user', website=True) def slide_send_share_email(self, slide_id, email): diff --git a/addons/website_slides/static/src/js/slides_like.js b/addons/website_slides/static/src/js/slides_like.js index e5ad9e22d7b..c32f484a713 100644 --- a/addons/website_slides/static/src/js/slides_like.js +++ b/addons/website_slides/static/src/js/slides_like.js @@ -11,42 +11,14 @@ var _t = core._t; var LikeButton = Widget.extend({ events: { - 'click': '_onClick', + 'click .o_wslides_like_up': '_onClickUp', + 'click .o_wslides_like_down': '_onClickDown', }, //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- - /** - * @private - * @param {Object} ev - */ - _applyAction: function (ev) { - var button = $(ev.currentTarget); - var slideID = button.data('slide-id'); - var userID = button.data('user-id'); - var isPublic = button.data('public-user'); - var href = button.data('href'); - if (isPublic) { - this._popoverAlert(button, _.str.sprintf(_t('Please login to vote this slide'), (document.URL))); - } else { - var target = button.find('.fa'); - if (localStorage.getItem('slide_vote_' + slideID) !== userID.toString()) { - this._rpc({ - route: href, - params: { - slide_id: slideID, - }, - }).then(function (data) { - target.text(data); - localStorage.setItem('slide_vote_' + slideID, userID); - }); - } else { - this._popoverAlert(button, _t('You have already voted for this slide')); - } - } - }, /** * @private * @param {Object} $el @@ -71,8 +43,38 @@ var LikeButton = Widget.extend({ /** * @private */ - _onClick: function () { - this._applyAction(); + _onClick: function (slideId, voteType) { + var self = this; + this._rpc({ + route: '/slides/slide/like', + params: { + slide_id: slideId, + upvote: voteType === 'like', + }, + }).then(function (data) { + if (! data.error) { + self.$el.find('span.o_wslides_like_up span').text(data.likes); + self.$el.find('span.o_wslides_like_down span').text(data.dislikes); + } else { + if (data.error === 'public_user') { + self._popoverAlert(self.$el, _.str.sprintf(_t('Please login to vote this slide'), (document.URL))); + } else if (data.error === 'vote_done') { + self._popoverAlert(self.$el, _t('You have already voted for this slide')); + } else { + self._popoverAlert(self.$el, _t('Unknown error')); + } + } + }); + }, + + _onClickUp: function (event) { + var slideId = $(event.currentTarget).data('slide-id'); + return this._onClick(slideId, 'like'); + }, + + _onClickDown: function (event) { + var slideId = $(event.currentTarget).data('slide-id'); + return this._onClick(slideId, 'dislike'); }, }); @@ -83,10 +85,9 @@ sAnimations.registry.websiteSlidesLike = sAnimations.Class.extend({ * @override * @param {Object} parent */ - start: function (parent) { + start: function () { var defs = [this._super.apply(this, arguments)]; - defs.push(new LikeButton(this).attachTo($('.oe_slide_js_like'))); - defs.push(new LikeButton(this).attachTo($('.oe_slide_js_unlike'))); + defs.push(new LikeButton(this).attachTo($('.o_wslides_like'))); return $.when.apply($, defs); }, }); diff --git a/addons/website_slides/static/src/scss/website_slides.scss b/addons/website_slides/static/src/scss/website_slides.scss index 658d973a5a0..e39e803c877 100644 --- a/addons/website_slides/static/src/scss/website_slides.scss +++ b/addons/website_slides/static/src/scss/website_slides.scss @@ -84,7 +84,7 @@ img.oe_slides_promote_image { border-bottom: 1px solid $nav-tabs-border-color; } -.oe_slide_js_like, .oe_slide_js_unlike{ +.o_wslides_like_up, .o_wslides_like_down { cursor: pointer; color: $link-color; } diff --git a/addons/website_slides/views/website_slides_templates.xml b/addons/website_slides/views/website_slides_templates.xml index 393123f9e05..c2f34ebb6e0 100644 --- a/addons/website_slides/views/website_slides_templates.xml +++ b/addons/website_slides/views/website_slides_templates.xml @@ -436,28 +436,22 @@
-
+
- + - +
From f7666537800625cb4f26324bbde00e29b0497aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 28 Jan 2019 10:30:54 +0000 Subject: [PATCH 5/6] [FIX][IMP] slide: do not propose to create tags / category if no right This commit is linked to task ID 1933820 and PR #30553. --- addons/website_slides/controllers/main.py | 16 +++++++++ .../static/src/js/slides_upload.js | 34 ++++++++++--------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index 6a3e52727dc..f15ad7eb690 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -326,6 +326,22 @@ class WebsiteSlides(http.Controller): return {'error': _('Internal server error, please try again later or contact administrator.\nHere is the error message: %s') % e} return {'url': "/slides/slide/%s" % (slide_id.id)} + @http.route(['/slides/tag/search_read'], type='json', auth='user', methods=['POST'], website=True) + def slide_tag_search_read(self, fields, domain): + can_create = request.env['slide.tag'].check_access_rights('create', raise_exception=False) + return { + 'read_results': request.env['slide.tag'].search_read(domain, fields), + 'can_create': can_create, + } + + @http.route(['/slides/category/search_read'], type='json', auth='user', methods=['POST'], website=True) + def slide_category_search_read(self, fields, domain): + can_create = request.env['slide.category'].check_access_rights('create', raise_exception=False) + return { + 'read_results': request.env['slide.category'].search_read(domain, fields), + 'can_create': can_create, + } + # -------------------------------------------------- # EMBED IN THIRD PARTY WEBSITES # -------------------------------------------------- diff --git a/addons/website_slides/static/src/js/slides_upload.js b/addons/website_slides/static/src/js/slides_upload.js index e47749f7ab9..5db2c3c5326 100644 --- a/addons/website_slides/static/src/js/slides_upload.js +++ b/addons/website_slides/static/src/js/slides_upload.js @@ -106,12 +106,16 @@ var SlideDialog = Widget.extend({ if (_.filter(_.union(addedTags, data), function (tag) { return tag.text.toLowerCase().localeCompare(term.toLowerCase()) === 0; }).length === 0) { - return { - id: _.uniqueId('tag_'), - create: true, - tag: term, - text: _.str.sprintf(_t("Create new tag '%s'"), term), - }; + if (this.opts.can_create) { + return { + id: _.uniqueId('tag_'), + create: true, + tag: term, + text: _.str.sprintf(_t("Create new tag '%s'"), term), + }; + } else { + return undefined; + } } }, fill_data: function (query, data) { @@ -129,8 +133,9 @@ var SlideDialog = Widget.extend({ // fetch data only once and store it if (!this.selection_data) { this.fetch_rpc_fnc().then(function (data) { - that.fill_data(query, data); - that.selection_data = data; + that.can_create = data.can_create; + that.fill_data(query, data.read_results); + that.selection_data = data.read_results; }); } else { this.fill_data(query, this.selection_data); @@ -148,10 +153,8 @@ var SlideDialog = Widget.extend({ $('#category_id').select2(this._select2Wrapper(_t('Category'), false, function () { return self._rpc({ - model: 'slide.category', - method: 'search_read', - args: [], - kwargs: { + route: '/slides/category/search_read', + params: { fields: ['name'], domain: [['channel_id', '=', self.channel_id]], } @@ -177,11 +180,10 @@ var SlideDialog = Widget.extend({ var self = this; $('#tag_ids').select2(this._select2Wrapper(_t('Tags'), true, function () { return self._rpc({ - model: 'slide.tag', - method: 'search_read', - args: [], - kwargs: { + route: '/slides/tag/search_read', + params: { fields: ['name'], + domain: [], } }); })); From 088041f79d0945a82472ca6a9b387f2fde771981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 28 Jan 2019 12:44:11 +0000 Subject: [PATCH 6/6] [FIX][IMP] channel: improve can_upload / can_see computation on channel Purpose of this commit is to clean a bit interface of slides * separate can_see from can_upload; * correctly set can_see on partial visibility channels; * remove upload button for portal users as they have no rights to upload a document and this is not supported in any way; This commit is linked to task ID 1933820 and PR #30553. --- addons/website_slides/controllers/main.py | 6 +++--- addons/website_slides/models/slide_channel.py | 4 ++-- addons/website_slides/views/website_slides_templates.xml | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index f15ad7eb690..11b5fb0edeb 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -65,7 +65,7 @@ class WebsiteSlides(http.Controller): 'most_viewed_slides': most_viewed_slides, 'related_slides': related_slides, 'user': request.env.user, - 'is_public_user': request.env.user == request.website.user_id, + 'is_public_user': request.website.is_public_user(), 'comments': slide.channel_id.can_see_full and slide.website_message_ids or [], 'private': not slide.channel_id.can_see_full, } @@ -88,7 +88,7 @@ class WebsiteSlides(http.Controller): return request.render('website_slides.channels', { 'channels': channels, 'user': request.env.user, - 'is_public_user': request.env.user == request.website.user_id + 'is_public_user': request.website.is_public_user(), }) def sitemap_slide(env, rule, qs): @@ -164,7 +164,7 @@ class WebsiteSlides(http.Controller): 'sorting': sorting, 'user': user, 'pager': pager, - 'is_public_user': user == request.website.user_id, + 'is_public_user': request.website.is_public_user(), 'display_channel_settings': not request.httprequest.cookies.get('slides_channel_%s' % (channel.id), False) and channel.can_see_full, } if search: diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index fb56ca97b25..fae545c87e9 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -127,9 +127,9 @@ class Channel(models.Model): @api.one @api.depends('visibility', 'group_ids', 'upload_group_ids') def _compute_access(self): - self.can_see = self.visibility in ['public', 'private'] or bool(self.group_ids & self.env.user.groups_id) + self.can_see = self.visibility in ['public', 'partial'] or bool(self.group_ids & self.env.user.groups_id) self.can_see_full = self.visibility == 'public' or bool(self.group_ids & self.env.user.groups_id) - self.can_upload = self.can_see and (not self.upload_group_ids or bool(self.upload_group_ids & self.env.user.groups_id)) + self.can_upload = not self.env.user.share and (not self.upload_group_ids or bool(self.upload_group_ids & self.env.user.groups_id)) @api.multi @api.depends('name') diff --git a/addons/website_slides/views/website_slides_templates.xml b/addons/website_slides/views/website_slides_templates.xml index c2f34ebb6e0..129ce77f965 100644 --- a/addons/website_slides/views/website_slides_templates.xml +++ b/addons/website_slides/views/website_slides_templates.xml @@ -88,7 +88,7 @@ / - + Upload @@ -233,13 +233,13 @@

No presentation published yet.

The is empty. - + Upload PDF presentations, documents, videos or infographic using the button below.

- + Upload