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');
},