diff --git a/addons/mail/views/mail_activity_views.xml b/addons/mail/views/mail_activity_views.xml index addf80362ee..fdbfa3a5bdd 100644 --- a/addons/mail/views/mail_activity_views.xml +++ b/addons/mail/views/mail_activity_views.xml @@ -114,7 +114,7 @@ - + diff --git a/addons/mail/views/mail_followers_views.xml b/addons/mail/views/mail_followers_views.xml index ebcf7d0e44a..3dbd0ba7b1a 100644 --- a/addons/mail/views/mail_followers_views.xml +++ b/addons/mail/views/mail_followers_views.xml @@ -10,7 +10,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/addons/mail/views/mail_message_views.xml b/addons/mail/views/mail_message_views.xml index 723ec9fa33e..6bb1bab6f49 100644 --- a/addons/mail/views/mail_message_views.xml +++ b/addons/mail/views/mail_message_views.xml @@ -12,7 +12,7 @@ - + @@ -37,7 +37,7 @@ - + diff --git a/addons/rating/models/mail_thread.py b/addons/rating/models/mail_thread.py index b0c229181df..3d89a33a6cf 100644 --- a/addons/rating/models/mail_thread.py +++ b/addons/rating/models/mail_thread.py @@ -10,11 +10,13 @@ class MailThread(models.AbstractModel): @api.returns('mail.message', lambda value: value.id) def message_post(self, **kwargs): rating_value = kwargs.pop('rating_value', False) + rating_feedback = kwargs.pop('rating_feedback', False) message = super(MailThread, self).message_post(**kwargs) if rating_value: ir_model = self.env['ir.model'].sudo().search([('model', '=', self._name)]) self.env['rating.rating'].create({ 'rating': float(rating_value) if rating_value is not None else False, + 'feedback': rating_feedback, 'res_model_id': ir_model.id, 'res_id': self.id, 'message_id': message.id, diff --git a/addons/rating/models/rating.py b/addons/rating/models/rating.py index bc16bff69c1..04f8c474e14 100644 --- a/addons/rating/models/rating.py +++ b/addons/rating/models/rating.py @@ -13,7 +13,6 @@ RATING_LIMIT_MIN = 1 class Rating(models.Model): - _name = "rating.rating" _description = "Rating" _order = 'write_date desc' @@ -50,7 +49,10 @@ class Rating(models.Model): ('highly_dissatisfied', 'Highly dissatisfied'), ('no_rating', 'No Rating yet')], string='Rating', store=True, compute='_compute_rating_text', readonly=True) feedback = fields.Text('Comment', help="Reason of the rating") - message_id = fields.Many2one('mail.message', string="Linked message", help="Associated message when posting a review. Mainly used in website addons.", index=True) + message_id = fields.Many2one( + 'mail.message', string="Linked message", + index=True, ondelete='cascade', + help="Associated message when posting a review. Mainly used in website addons.") access_token = fields.Char('Security Token', default=_default_access_token, help="Access token to set the rating of the value") consumed = fields.Boolean(string="Filled Rating", help="Enabled if the rating has been filled.") diff --git a/addons/rating/security/ir.model.access.csv b/addons/rating/security/ir.model.access.csv index 7d09058e2a7..6af5f1f5205 100644 --- a/addons/rating/security/ir.model.access.csv +++ b/addons/rating/security/ir.model.access.csv @@ -2,3 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_rating_user,rating.rating.user,rating.model_rating_rating,base.group_user,1,1,1,0 access_rating_public,rating.rating.public,rating.model_rating_rating,base.group_public,1,1,1,0 access_rating_portal,rating.rating.portal,rating.model_rating_rating,base.group_portal,1,1,1,0 +rating_rating_access_system,rating.rating.access.system,rating.model_rating_rating,base.group_system,1,1,1,1 diff --git a/addons/website_rating/controllers/portal_chatter.py b/addons/website_rating/controllers/portal_chatter.py index c252d2f73e7..f2b2b5a3033 100644 --- a/addons/website_rating/controllers/portal_chatter.py +++ b/addons/website_rating/controllers/portal_chatter.py @@ -11,9 +11,15 @@ class PortalChatter(PortalChatter): def _portal_post_filter_params(self): fields = super(PortalChatter, self)._portal_post_filter_params() - fields.append('rating_value') + fields += ['rating_value', 'rating_feedback'] return fields + @http.route() + def portal_chatter_post(self, res_model, res_id, message, redirect=None, attachment_ids='', attachment_tokens='', **kwargs): + if kwargs.get('rating_value'): + kwargs['rating_feedback'] = kwargs.pop('rating_feedback', message) + return super(PortalChatter, self).portal_chatter_post(res_model, res_id, message, redirect=redirect, attachment_ids=attachment_ids, attachment_tokens=attachment_tokens, **kwargs) + @http.route() def portal_chatter_init(self, res_model, res_id, domain=False, limit=False, **kwargs): result = super(PortalChatter, self).portal_chatter_init(res_model, res_id, domain=domain, limit=limit, **kwargs) diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index 33e9ad1ca20..20e62300ff4 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -211,7 +211,11 @@ class Channel(models.Model): @api.depends('slide_ids.slide_type', 'slide_ids.is_published', 'slide_ids.completion_time', 'slide_ids.likes', 'slide_ids.dislikes', 'slide_ids.total_views', 'slide_ids.is_category', 'slide_ids.active') def _compute_slides_statistics(self): - result = dict((cid, dict(total_views=0, total_votes=0, total_time=0)) for cid in self.ids) + default_vals = dict(total_views=0, total_votes=0, total_time=0, total_slides=0) + keys = ['nbr_%s' % slide_type for slide_type in self.env['slide.slide']._fields['slide_type'].get_values(self.env)] + default_vals.update(dict((key, 0) for key in keys)) + + result = dict((cid, dict(default_vals)) for cid in self.ids) read_group_res = self.env['slide.slide'].read_group( [('active', '=', True), ('is_published', '=', True), ('channel_id', 'in', self.ids), ('is_category', '=', False)], ['channel_id', 'slide_type', 'likes', 'dislikes', 'total_views', 'completion_time'], @@ -229,7 +233,7 @@ class Channel(models.Model): result[cid].update(cdata) for record in self: - record.update(result.get(record.id, {})) + record.update(result.get(record.id, default_vals)) def _compute_slides_statistics_type(self, read_group_res): """ Compute statistics based on all existing slide types """ diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index f890c7d1451..2a17ade329d 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -197,6 +197,8 @@ class Slide(models.Model): Lists are manually sorted because when adding a new browse record order will not be correct as the added slide would actually end up at the first place no matter its sequence.""" + self.category_id = False # initialize whatever the state + channel_slides = {} for slide in self: if slide.channel_id.id not in channel_slides: diff --git a/addons/website_slides/static/src/js/slides_course_quiz.js b/addons/website_slides/static/src/js/slides_course_quiz.js index f5b56297fe8..89076268c6a 100644 --- a/addons/website_slides/static/src/js/slides_course_quiz.js +++ b/addons/website_slides/static/src/js/slides_course_quiz.js @@ -95,7 +95,7 @@ odoo.define('website_slides.quiz', function (require) { } else if (alert_code === 'public_user') { message = _t("You must be logged to submit the quiz."); } - this.$('.o_wslides_js_lesson_quiz_error span').html(message); + this.$('.o_wslides_js_lesson_quiz_error span:first').html(message); this.$('.o_wslides_js_lesson_quiz_error').removeClass('d-none'); },