diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index 11b5fb0edeb..d85a9a15296 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -35,28 +35,6 @@ 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) @@ -234,21 +212,19 @@ class WebsiteSlides(http.Controller): 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.check_access_rights('read') - slide.check_access_rule('read') - check = self._check_session_slide_vote(slide, upvote=upvote) - if check is False: + slide_users = request.env['slide.users'].sudo().search([ + ('slide_id', '=', slide_id), + ('user_id', '=', request.env.uid) + ]) + if (upvote and slide_users.vote == 1) or (not upvote and slide_users.vote == -1): 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 + slide = request.env['slide.slide'].browse(int(slide_id)) + if upvote: + slide.action_like() else: - slide.sudo().dislikes += 1 - return {'state': check, 'likes': slide.likes, 'dislikes': slide.dislikes} + slide.action_dislike() + slide.invalidate_cache() + return slide.read(['likes', 'dislikes', 'user_vote'])[0] @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/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index 6f1df65d99b..2337e41aab4 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -19,6 +19,16 @@ from odoo.http import request from odoo.addons.http_routing.models.ir_http import url_for +class SlideUsersRelation(models.Model): + _name = 'slide.users' + _description = 'Slide / Users decorated m2m' + _table = 'slide_users' + + slide_id = fields.Many2one('slide.slide', index=True, required=True) + user_id = fields.Many2one('res.users', index=True, required=True) + vote = fields.Integer('Vote', default=0) + + class EmbeddedSlide(models.Model): """ Embedding in third party websites. Track view count, generate statistics. """ _name = 'slide.embed' @@ -93,6 +103,10 @@ class Slide(models.Model): image = fields.Binary('Image', attachment=True) image_medium = fields.Binary('Medium', compute="_get_image", store=True, attachment=True) image_thumb = fields.Binary('Thumbnail', compute="_get_image", store=True, attachment=True) + # subscribers + user_ids = fields.Many2many('res.users', 'slide_users', 'slide_id', 'user_id', + string='Subscribers', groups='base.group_system') + slide_user_ids = fields.One2many('slide.users', 'slide_id', string='Subscribers information', groups='base.group_system') @api.depends('image') def _get_image(self): @@ -135,8 +149,9 @@ class Slide(models.Model): # website website_id = fields.Many2one(related='channel_id.website_id', readonly=True) date_published = fields.Datetime('Publish Date') - likes = fields.Integer('Likes') - dislikes = fields.Integer('Dislikes') + 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') # views embedcount_ids = fields.One2many('slide.embed', 'slide_id', string="Embed Count") slide_views = fields.Integer('# of Website Views') @@ -148,6 +163,24 @@ class Slide(models.Model): for record in self: record.total_views = record.slide_views + record.embed_views + @api.depends('slide_user_ids.vote') + def _compute_user_info(self): + slide_data = dict.fromkeys(self.ids, dict({'likes': 0, 'dislikes': 0, 'user_vote': False})) + slide_users = self.env['slide.users'].sudo().search([ + ('slide_id', 'in', self.ids) + ]) + for slide_user in slide_users: + if slide_user.vote == 1: + slide_data[slide_user.slide_id.id]['likes'] += 1 + if slide_user.user_id == self.env.user: + slide_data[slide_user.slide_id.id]['user_vote'] = 1 + elif slide_user.vote == -1: + slide_data[slide_user.slide_id.id]['dislikes'] += 1 + if slide_user.user_id == self.env.user: + slide_data[slide_user.slide_id.id]['user_vote'] = -1 + for slide_sudo in self.sudo(): + slide_sudo.update(slide_data[slide_sudo.id]) + embed_code = fields.Text('Embed Code', readonly=True, compute='_get_embed_code') def _get_embed_code(self): @@ -305,6 +338,43 @@ class Slide(models.Model): 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') + def action_like(self): + self.check_access_rights('read') + self.check_access_rule('read') + return self._action_vote(upvote=True) + + def action_dislike(self): + self.check_access_rights('read') + self.check_access_rule('read') + return self._action_vote(upvote=False) + + def _action_vote(self, upvote=True): + """ Private implementation of voting. It does not check for any real access + rights; public methods should grant access before calling this method. + + :param upvote: if True, is a like; if False, is a dislike + """ + self_sudo = self.sudo() + SlideUsersSudo = self.env['slide.users'].sudo() + slide_users = SlideUsersSudo.search([ + ('slide_id', 'in', self.ids), + ('user_id', '=', self.env.uid) + ]) + new_slides = self_sudo - slide_users.mapped('slide_id') + + for slide_user in slide_users: + if upvote: + new_vote = 0 if slide_user.vote == -1 else 1 + else: + new_vote = 0 if slide_user.vote == 1 else -1 + slide_user.vote = new_vote + + for new_slide in new_slides: + new_vote = 1 if upvote else -1 + new_slide.write({ + 'slide_user_ids': [(0, 0, {'vote': new_vote, 'user_id': self.env.uid})] + }) + # -------------------------------------------------- # Parsing methods # -------------------------------------------------- diff --git a/addons/website_slides/security/ir.model.access.csv b/addons/website_slides/security/ir.model.access.csv index 07d087f7db9..38588d920d1 100644 --- a/addons/website_slides/security/ir.model.access.csv +++ b/addons/website_slides/security/ir.model.access.csv @@ -2,6 +2,8 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_slide_slide_public,slide.slide.public,model_slide_slide,base.group_public,1,0,0,0 access_slide_slide_portal,slide.slide.portal,model_slide_slide,base.group_portal,1,0,0,0 access_slide_slide_user,slide.slide.user,model_slide_slide,base.group_user,1,1,1,1 +access_slide_users_all,slide.users.all,model_slide_users,,0,0,0,0 +access_slide_users_system,slide.users.system,model_slide_users,base.group_system,1,1,1,1 access_slide_tag_public,slide.tag.public,model_slide_tag,base.group_public,1,0,0,0 access_slide_tag_portal,slide.tag.portal,model_slide_tag,base.group_portal,1,0,0,0 access_slide_tag_user,slide.tag.user,model_slide_tag,base.group_user,1,1,1,1