diff --git a/addons/im_livechat/tests/test_message.py b/addons/im_livechat/tests/test_message.py index d1b44d340a4..16dd79de8e4 100644 --- a/addons/im_livechat/tests/test_message.py +++ b/addons/im_livechat/tests/test_message.py @@ -64,6 +64,7 @@ class TestImLivechatMessage(TransactionCase): 'module_icon': '/mail/static/description/icon.png', 'needaction_partner_ids': [], 'notifications': [], + 'pinned_at': False, 'rating': { 'id': record_rating.id, 'ratingImageUrl': record_rating.rating_image_url, diff --git a/addons/mail/controllers/discuss.py b/addons/mail/controllers/discuss.py index 64a4231e08d..182786efcf3 100644 --- a/addons/mail/controllers/discuss.py +++ b/addons/mail/controllers/discuss.py @@ -213,8 +213,8 @@ class DiscussController(http.Controller): # -------------------------------------------------------------------------- @http.route('/mail/inbox/messages', methods=['POST'], type='json', auth='user') - def discuss_inbox_messages(self, before=None, after=None, limit=30, **kwargs): - return request.env['mail.message']._message_fetch(domain=[('needaction', '=', True)], before=before, after=after, limit=limit).message_format() + def discuss_inbox_messages(self, before=None, after=None, limit=30, around=None, **kwargs): + return request.env['mail.message']._message_fetch(domain=[('needaction', '=', True)], before=before, after=after, around=around, limit=limit).message_format() @http.route('/mail/history/messages', methods=['POST'], type='json', auth='user') def discuss_history_messages(self, before=None, after=None, limit=30, **kwargs): @@ -406,16 +406,22 @@ class DiscussController(http.Controller): raise NotFound() @http.route('/mail/channel/messages', methods=['POST'], type='json', auth='public') - def mail_channel_messages(self, channel_id, before=None, after=None, limit=30, **kwargs): + def mail_channel_messages(self, channel_id, before=None, after=None, limit=30, around=None, **kwargs): channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id)) - messages = channel_member_sudo.env['mail.message']._message_fetch(domain=[ + domain = [ ('res_id', '=', channel_id), ('model', '=', 'mail.channel'), ('message_type', '!=', 'user_notification'), - ], before=before, after=after, limit=limit) - if not request.env.user._is_public(): + ] + messages = channel_member_sudo.env['mail.message']._message_fetch(domain=domain, before=before, after=after, around=around, limit=limit) + if not request.env.user._is_public() and not around: messages.set_message_done() - return messages.message_format() + return messages.sorted('id', reverse=True).message_format() + + @http.route('/mail/channel/pinned_messages', methods=['POST'], type='json', auth='public') + def mail_channel_pins(self, channel_id, **kwargs): + channel_member_sudo = request.env['mail.channel.member']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id)) + return channel_member_sudo.channel_id.pinned_message_ids.sorted(key='pinned_at', reverse=True).message_format() @http.route('/mail/channel/set_last_seen_message', methods=['POST'], type='json', auth='public') def mail_channel_mark_as_seen(self, channel_id, last_message_id, allow_older=False, **kwargs): @@ -451,12 +457,12 @@ class DiscussController(http.Controller): return thread._get_mail_thread_data(request_list) @http.route('/mail/thread/messages', methods=['POST'], type='json', auth='user') - def mail_thread_messages(self, thread_model, thread_id, before=None, after=None, limit=30, **kwargs): + def mail_thread_messages(self, thread_model, thread_id, before=None, after=None, around=None, limit=30, **kwargs): messages = request.env['mail.message']._message_fetch(domain=[ ('res_id', '=', int(thread_id)), ('model', '=', thread_model), ('message_type', '!=', 'user_notification'), - ], before=before, after=after, limit=limit) + ], before=before, after=after, around=around, limit=limit) if not request.env.user._is_public(): messages.set_message_done() return messages.message_format() diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py index 38cb666a8d0..a8a66035d45 100644 --- a/addons/mail/models/mail_channel.py +++ b/addons/mail/models/mail_channel.py @@ -6,6 +6,7 @@ import logging from collections import defaultdict from hashlib import sha512 from secrets import choice +from markupsafe import Markup from odoo import _, api, fields, models, tools, Command from odoo.addons.base.models.avatar_mixin import get_hsl_from_seed @@ -65,6 +66,7 @@ class Channel(models.Model): channel_member_ids = fields.One2many( 'mail.channel.member', 'channel_id', string='Members', groups='base.group_user') + pinned_message_ids = fields.One2many('mail.message', 'res_id', domain=lambda self: [('model', '=', 'mail.channel'), ('pinned_at', '!=', False)], string='Pinned Messages') rtc_session_ids = fields.One2many('mail.channel.rtc.session', 'channel_id', groups="base.group_system") is_member = fields.Boolean('Is Member', compute='_compute_is_member', search='_search_is_member') member_count = fields.Integer(string="Member Count", compute='_compute_member_count', compute_sudo=True) @@ -744,6 +746,46 @@ class Channel(models.Model): # - when a message is posted on a channel (to the channel, using _notify() method) # ------------------------------------------------------------ + def set_message_pin(self, message_id, pinned): + """ (Un)pin a message on the channel and send a notification to the + members. + :param message_id: id of the message to be pinned. + :param pinned: whether the message should be pinned or unpinned. + """ + self.ensure_one() + message_to_update = self.env['mail.message'].search([ + ['id', '=', message_id], + ['model', '=', 'mail.channel'], + ['res_id', '=', self.id], + ['pinned_at', '=' if pinned else '!=', False] + ]) + if not message_to_update: + return + message_to_update.write({'pinned_at': fields.datetime.now() if pinned else False}) + self.env['bus.bus']._sendone(self, 'mail.record/insert', { + 'Message': { + 'id': message_id, + 'pinned_at': fields.Datetime.to_string(message_to_update.pinned_at), + } + }) + if pinned: + notification_text = ''' +
+ Pinned messages +
+