From ddccd33bae51499cb1872ebef75760e75d50a5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= <tde@odoo.com> Date: Wed, 6 Feb 2019 12:31:23 +0000 Subject: [PATCH] [IMP] website_slides: improve upload slide screen Slide upload access is a bit cleaned. A can_publish field is added controlling who can publish slides. Currently website publishers are allowed to publish content. Not publishers people allowed to upload cannot publish their own content. It stays in a submitted non published state. This commit is linked to task ID 1937411 and PR #30847. --- addons/website_slides/controllers/main.py | 19 +++++++++++-- addons/website_slides/models/slide_channel.py | 2 ++ addons/website_slides/models/slide_slide.py | 18 +++++++++--- .../static/src/js/slides_upload.js | 28 +++++++++++-------- .../static/src/xml/website_slides.xml | 5 ++-- .../views/website_slides_templates.xml | 9 ++++-- 6 files changed, 57 insertions(+), 24 deletions(-) diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index b271bd9dbd47..5da8e5fa6390 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -293,16 +293,29 @@ class WebsiteSlides(http.Controller): values['category_id'] = post['category_id'][0] # handle exception during creation of slide and sent error notification to the client - # otherwise client slide create dialog box continue processing even server fail to create a slide. + # otherwise client slide create dialog box continue processing even server fail to create a slide try: - slide_id = request.env['slide.slide'].create(values) + channel = request.env['slide.channel'].browse(values['channel_id']) + can_upload = channel.can_upload + can_publish = channel.can_publish + except (UserError, AccessError) as e: + _logger.error(e) + return {'error': e.name} + else: + if not can_upload: + return {'error': _('You cannot upload on this channel.')} + + try: + values['user_id'] = request.env.uid + values['website_published'] = values.get('website_published', False) and can_publish + slide = request.env['slide.slide'].sudo().create(values) except (UserError, AccessError) as e: _logger.error(e) return {'error': e.name} except Exception as e: _logger.error(e) 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)} + return {'url': "/slides/slide/%s" % (slide.id)} @http.route(['/slides/tag/search_read'], type='json', auth='user', methods=['POST'], website=True) def slide_tag_search_read(self, fields, domain): diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index 15d9d7a6fe64..300cb84f1f32 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -106,6 +106,7 @@ class Channel(models.Model): string='Upload Groups', help="Groups allowed to upload presentations in this channel. If void, every user can upload.") # not stored access fields, depending on each user can_upload = fields.Boolean('Can Upload', compute='_compute_access') + can_publish = fields.Boolean('Can Publish', compute='_compute_access') @api.depends('custom_slide_id', 'promote_strategy', 'slide_ids.likes', 'slide_ids.total_views', "slide_ids.date_published") @@ -164,6 +165,7 @@ class Channel(models.Model): @api.depends('visibility', 'partner_ids', 'upload_group_ids') def _compute_access(self): 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)) + self.can_publish = self.can_upload and self.env.user.has_group('website.group_website_publisher') @api.multi @api.depends('name') diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index ac74567e66bd..12adf7125fb9 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -92,6 +92,7 @@ class Slide(models.Model): # description name = fields.Char('Title', required=True, translate=True) active = fields.Boolean(default=True) + user_id = fields.Many2one('res.users', string='Uploaded by', default=lambda self: self.env.uid) description = fields.Text('Description', translate=True) channel_id = fields.Many2one('slide.channel', string="Channel", required=True) category_id = fields.Many2one('slide.category', string="Category", domain="[('channel_id', '=', channel_id)]") @@ -218,6 +219,12 @@ class Slide(models.Model): @api.model def create(self, values): + # Do not publish slide if user has not publisher rights + channel = self.env['slide.channel'].browse(values['channel_id']) + if not channel.can_publish: + values['website_published'] = False + values['date_published'] = False + if not values.get('index_content'): values['index_content'] = values.get('description') if values.get('slide_type') == 'infographic' and not values.get('image'): @@ -228,15 +235,18 @@ class Slide(models.Model): doc_data = self._parse_document_url(values['url']).get('values', dict()) for key, value in doc_data.items(): values.setdefault(key, value) - # Do not publish slide if user has not publisher rights - if not self.user_has_groups('website.group_website_publisher'): - values['website_published'] = False + slide = super(Slide, self).create(values) - slide._post_publication() + + if slide.website_published: + slide._post_publication() return slide @api.multi def write(self, values): + if values.get('website_published') and any(not slide.channel_id.can_publish for slide in self): + values.pop('website_published') + if values.get('url') and values['url'] != self.url: doc_data = self._parse_document_url(values['url']).get('values', dict()) for key, value in doc_data.items(): diff --git a/addons/website_slides/static/src/js/slides_upload.js b/addons/website_slides/static/src/js/slides_upload.js index 5db2c3c5326e..30dc8c9547a0 100644 --- a/addons/website_slides/static/src/js/slides_upload.js +++ b/addons/website_slides/static/src/js/slides_upload.js @@ -24,11 +24,14 @@ var SlideDialog = Widget.extend({ /** * @override * @param {Object} el - * @param {number} channel_id + * @param {Object} data holding channelId and optionally upload and publish control parameters */ - init: function (el, channelID) { - this._super(el, channelID); - this.channel_id = parseInt(channelID, 10); + init: function (el, data) { + this._super(el, data); + this.channelId = parseInt(data.channelId, 10); + this.canUpload = data.canUpload === 'True'; + this.canPublish = data.canPublish === 'True'; + console.log(this.channelId, this.canUpload, this.canPublish); this.file = {}; this.index_content = ''; }, @@ -56,7 +59,7 @@ var SlideDialog = Widget.extend({ return this._rpc({ model: 'slide.slide', method: 'search_count', - args: [[['channel_id', '=', self.channel_id], ['name', '=', fileName]]], + args: [[['channel_id', '=', self.channelId], ['name', '=', fileName]]], }); }, /** @@ -156,7 +159,7 @@ var SlideDialog = Widget.extend({ route: '/slides/category/search_read', params: { fields: ['name'], - domain: [['channel_id', '=', self.channel_id]], + domain: [['channel_id', '=', self.channelId]], } }); })); @@ -224,7 +227,7 @@ var SlideDialog = Widget.extend({ _getValue: function () { var canvas = this.$('#data_canvas')[0], values = { - 'channel_id': this.channel_id || '', + 'channel_id': this.channelId || '', 'name': this.$('#name').val(), 'url': this.$('#url').val(), 'description': this.$('#description').val(), @@ -418,7 +421,7 @@ var SlideDialog = Widget.extend({ var self = this, value = { 'url': $(ev.target).val(), - 'channel_id': self.channel_id + 'channel_id': self.channelId }; this.$('.alert-warning').remove(); this.is_valid_url = false; @@ -454,7 +457,7 @@ sAnimations.registry.websiteSlidesUpload = sAnimations.Class.extend({ start: function () { // Automatically open the upload dialog if requested from query string if ($.deparam.querystring().enable_slide_upload !== undefined) { - this._openDialog(this.$el.attr('channel_id')); + this._openDialog(this.$el); } return this._super.apply(this, arguments); }, @@ -463,8 +466,9 @@ sAnimations.registry.websiteSlidesUpload = sAnimations.Class.extend({ // Private //-------------------------------------------------------------------------- - _openDialog: function (channelID) { - new SlideDialog(this, channelID).appendTo(document.body); + _openDialog: function ($element) { + var data = $element.data(); + new SlideDialog(this, data).appendTo(document.body); }, //-------------------------------------------------------------------------- @@ -476,7 +480,7 @@ sAnimations.registry.websiteSlidesUpload = sAnimations.Class.extend({ * @param {Event} ev */ _onUploadClick: function (ev) { - this._openDialog($(ev.currentTarget).attr('channel_id')); + this._openDialog($(ev.currentTarget)); }, }); }); diff --git a/addons/website_slides/static/src/xml/website_slides.xml b/addons/website_slides/static/src/xml/website_slides.xml index 5d9f8366a0ca..4283291b9566 100644 --- a/addons/website_slides/static/src/xml/website_slides.xml +++ b/addons/website_slides/static/src/xml/website_slides.xml @@ -67,8 +67,9 @@ </main> <footer class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Discard</button> - <button type="button" data-loading-text="Loading..." class="btn btn-primary save">Save as Draft</button> - <button type="button" data-loading-text="Loading..." data-published="true" class="btn btn-primary save">Save and Publish</button> + <button type="button" data-loading-text="Loading..." t-if="widget.canUpload && widget.canPublish" class="btn btn-primary save">Save as Draft</button> + <button type="button" data-loading-text="Loading..." t-if="widget.canUpload && ! widget.canPublish" class="btn btn-primary save">Submit</button> + <button type="button" data-loading-text="Loading..." t-if="widget.canUpload && widget.canPublish" data-published="true" class="btn btn-primary save">Publish</button> </footer> </div> </div> diff --git a/addons/website_slides/views/website_slides_templates.xml b/addons/website_slides/views/website_slides_templates.xml index 42458fb47d86..d7446b5dc632 100644 --- a/addons/website_slides/views/website_slides_templates.xml +++ b/addons/website_slides/views/website_slides_templates.xml @@ -108,9 +108,12 @@ <t t-if="category"> / <a t-attf-href="/slides/#{slug(channel)}/category/#{slug(category)}" t-esc="category.name"/> </t> - <!-- Public user has not right to create/write on slide --> <t t-if="channel.can_upload"> - <a role="button" class="btn btn-primary oe_slide_js_upload" title="Upload Presentation" t-attf-channel_id="#{channel.id}" aria-label="Upload Presentation" href="#"> + <a role="button" class="btn btn-primary oe_slide_js_upload" 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> </t> @@ -286,7 +289,7 @@ </p> <p> <!-- Public user has not right to create/write on slide--> - <a role="button" t-if="channel.can_upload" class="btn btn-primary oe_slide_js_upload" t-attf-channel_id="#{channel.id}" aria-label="Upload Presentation" title="Upload Presentation" href="#"> + <a role="button" t-if="channel.can_upload" class="btn btn-primary oe_slide_js_upload" t-attf-channel-id="#{channel.id}" aria-label="Upload Presentation" title="Upload Presentation" href="#"> <i class="fa fa-cloud-upload"></i> Upload </a> </p> -- GitLab