diff --git a/addons/im_livechat/i18n/im_livechat.pot b/addons/im_livechat/i18n/im_livechat.pot index 9dc148a7586..e0b80293241 100644 --- a/addons/im_livechat/i18n/im_livechat.pot +++ b/addons/im_livechat/i18n/im_livechat.pot @@ -59,6 +59,15 @@ msgstr "" msgid "% of Happiness" msgstr "" +#. module: im_livechat +#. odoo-python +#: code:addons/im_livechat/models/discuss_channel.py:0 +#, python-format +msgid "" +"%(new_line)sType %(bold_start)s:shortcut%(bold_end)s to insert a canned " +"response in your message." +msgstr "" + #. module: im_livechat #. odoo-python #: code:addons/im_livechat/models/chatbot_script_step.py:0 @@ -1802,13 +1811,6 @@ msgstr "" msgid "Treated sessions" msgstr "" -#. module: im_livechat -#. odoo-python -#: code:addons/im_livechat/models/discuss_channel.py:0 -#, python-format -msgid "Type :shortcut to insert a canned response in your message.
" -msgstr "" - #. module: im_livechat #: model:ir.model.fields,field_description:im_livechat.field_im_livechat_channel_rule__regex_url msgid "URL Regex" @@ -1868,8 +1870,8 @@ msgid "User's raw answer" msgstr "" #. module: im_livechat -#. odoo-python #. odoo-javascript +#. odoo-python #: code:addons/im_livechat/controllers/main.py:0 #: code:addons/im_livechat/controllers/main.py:0 #: code:addons/im_livechat/models/im_livechat_channel.py:0 diff --git a/addons/im_livechat/models/discuss_channel.py b/addons/im_livechat/models/discuss_channel.py index 01cfaddd6e1..5dc702bcc45 100644 --- a/addons/im_livechat/models/discuss_channel.py +++ b/addons/im_livechat/models/discuss_channel.py @@ -83,7 +83,9 @@ class DiscussChannel(models.Model): def _execute_command_help_message_extra(self): msg = super()._execute_command_help_message_extra() if self.channel_type == 'livechat': - return msg + _("Type :shortcut to insert a canned response in your message.
") + return msg + html_escape( + _("%(new_line)sType %(bold_start)s:shortcut%(bold_end)s to insert a canned response in your message.") + ) % {"bold_start": Markup(""), "bold_end": Markup(""), "new_line": Markup("
")} return msg def execute_command_history(self, **kwargs): diff --git a/addons/im_livechat/tests/test_get_discuss_channel.py b/addons/im_livechat/tests/test_get_discuss_channel.py index d5e168a1494..1cc1aefce6a 100644 --- a/addons/im_livechat/tests/test_get_discuss_channel.py +++ b/addons/im_livechat/tests/test_get_discuss_channel.py @@ -6,11 +6,12 @@ from unittest.mock import patch, PropertyMock from odoo import fields from odoo.addons.im_livechat.tests.common import TestImLivechatCommon +from odoo.addons.mail.tests.common import MailCommon from odoo.tests.common import tagged @tagged("post_install", "-at_install") -class TestGetDiscussChannel(TestImLivechatCommon): +class TestGetDiscussChannel(TestImLivechatCommon, MailCommon): def test_get_discuss_channel(self): """For a livechat with 5 available operators, we open 5 channels 5 times (25 channels total). For every 5 channels opening, we check that all operators were assigned. @@ -193,3 +194,36 @@ class TestGetDiscussChannel(TestImLivechatCommon): with freeze_time(fields.Datetime.to_string(fields.datetime.now() + timedelta(days=1))): member_of_operator._gc_unpin_livechat_sessions() self.assertTrue(member_of_operator.is_pinned, "unread channel should not be unpinned after autovacuum") + + def test_channel_command_help_in_livechat(self): + """Ensures the command '/help' works in a livechat""" + channel_info = self.make_jsonrpc_request( + "/im_livechat/get_session", + { + "anonymous_name": "visitor", + "channel_id": self.livechat_channel.id, + "previous_operator_id": self.operators[1].partner_id.id + }, + ) + channel = self.env["discuss.channel"].browse(channel_info["id"]) + self.env['bus.bus'].sudo().search([]).unlink() + with self.assertBus( + [(self.env.cr.dbname, "res.partner", self.env.user.partner_id.id)], + [ + { + "type": "discuss.channel/transient_message", + "payload": { + "body": + "You are in a private conversation with @Paul and @Visitor." + "

Type @username to mention someone, and grab their attention." + "
Type #channel to mention a channel." + "
Type /command to execute a command." + "
Type :shortcut to insert a canned response in your message." + "
", + "model": "discuss.channel", + "res_id": channel.id, + }, + }, + ], + ): + channel.execute_command_help() diff --git a/addons/mail/i18n/mail.pot b/addons/mail/i18n/mail.pot index dd23db4e677..2f40e2b49d3 100644 --- a/addons/mail/i18n/mail.pot +++ b/addons/mail/i18n/mail.pot @@ -94,6 +94,17 @@ msgstr "" msgid "%(name)s: %(message)s)" msgstr "" +#. module: mail +#. odoo-python +#: code:addons/mail/models/discuss/discuss_channel.py:0 +#, python-format +msgid "" +"%(new_line)s%(new_line)sType %(bold_start)s@username%(bold_end)s to mention " +"someone, and grab their attention.%(new_line)sType " +"%(bold_start)s#channel%(bold_end)s to mention a channel.%(new_line)sType " +"%(bold_start)s/command%(bold_end)s to execute a command." +msgstr "" + #. module: mail #. odoo-javascript #: code:addons/mail/static/src/discuss/core/web/discuss_core_web_service.js:0 @@ -321,17 +332,6 @@ msgid "" "model" msgstr "" -#. module: mail -#. odoo-python -#: code:addons/mail/models/discuss/discuss_channel.py:0 -#, python-format -msgid "" -"

\n" -" Type @username to mention someone, and grab their attention.
\n" -" Type #channel to mention a channel.
\n" -" Type /command to execute a command.
" -msgstr "" - #. module: mail #: model_terms:ir.ui.view,arch_db:mail.view_document_file_kanban msgid "" @@ -1084,13 +1084,6 @@ msgstr "" msgid "And 1 other member." msgstr "" -#. module: mail -#. odoo-python -#: code:addons/mail/models/discuss/discuss_channel.py:0 -#, python-format -msgid "Anonymous" -msgstr "" - #. module: mail #: model:ir.model.fields,field_description:mail.field_mail_activity_plan__res_model_id #: model:ir.model.fields,field_description:mail.field_mail_activity_schedule__res_model_id @@ -9964,6 +9957,13 @@ msgid "" "continue?" msgstr "" +#. module: mail +#. odoo-python +#: code:addons/mail/models/discuss/discuss_channel.py:0 +#, python-format +msgid "You are alone in a private conversation." +msgstr "" + #. module: mail #. odoo-python #: code:addons/mail/models/discuss/discuss_channel.py:0 @@ -9975,14 +9975,14 @@ msgstr "" #. odoo-python #: code:addons/mail/models/discuss/discuss_channel.py:0 #, python-format -msgid "You are in a private conversation with @%s." +msgid "You are in a private conversation with %(member_names)s." msgstr "" #. module: mail #. odoo-python #: code:addons/mail/models/discuss/discuss_channel.py:0 #, python-format -msgid "You are in channel #%s." +msgid "You are in channel %(bold_start)s#%(channel_name)s%(bold_end)s." msgstr "" #. module: mail diff --git a/addons/mail/models/discuss/discuss_channel.py b/addons/mail/models/discuss/discuss_channel.py index f5e5f91eaed..b5b1260fd75 100644 --- a/addons/mail/models/discuss/discuss_channel.py +++ b/addons/mail/models/discuss/discuss_channel.py @@ -2,6 +2,7 @@ import base64 import logging +from babel.lists import format_list from collections import defaultdict from hashlib import sha512 from secrets import choice @@ -12,7 +13,7 @@ from odoo.addons.base.models.avatar_mixin import get_hsl_from_seed from odoo.exceptions import UserError, ValidationError from odoo.osv import expression from odoo.tools import html_escape, get_lang -from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT +from odoo.tools.misc import babel_locale_parse, DEFAULT_SERVER_DATETIME_FORMAT _logger = logging.getLogger(__name__) @@ -1207,22 +1208,41 @@ class Channel(models.Model): }) def execute_command_help(self, **kwargs): - partner = self.env.user.partner_id if self.channel_type == 'channel': - msg = _("You are in channel #%s.", html_escape(self.name)) + msg = html_escape(_("You are in channel %(bold_start)s#%(channel_name)s%(bold_end)s.")) % { + "bold_start": Markup(""), + "bold_end": Markup(""), + "channel_name": self.name, + } else: all_channel_members = self.env['discuss.channel.member'].with_context(active_test=False) - channel_members = all_channel_members.search([('partner_id', '!=', partner.id), ('channel_id', '=', self.id)]) - msg = _("You are in a private conversation with @%s.", _(" @").join(html_escape(member.partner_id.name or member.guest_id.name) for member in channel_members) if channel_members else _("Anonymous")) + channel_members = all_channel_members.search([("is_self", "=", False), ("channel_id", "=", self.id)], order='id asc') + if channel_members: + member_names = Markup( + format_list( + [f"@%(member_{member.id})s" for member in channel_members], + locale=babel_locale_parse(get_lang(self.env).code), + ) + ) % { + f"member_{member.id}": member.partner_id.name or member.guest_id.name for member in channel_members + } + msg = html_escape(_("You are in a private conversation with %(member_names)s.")) % { + "member_names": member_names, + } + else: + msg = _("You are alone in a private conversation.") msg += self._execute_command_help_message_extra() - - self._send_transient_message(partner, msg) + self._send_transient_message(self.env.user.partner_id, msg) def _execute_command_help_message_extra(self): - msg = _("""

- Type @username to mention someone, and grab their attention.
- Type #channel to mention a channel.
- Type /command to execute a command.
""") + msg = html_escape( + _( + "%(new_line)s" + "%(new_line)sType %(bold_start)s@username%(bold_end)s to mention someone, and grab their attention." + "%(new_line)sType %(bold_start)s#channel%(bold_end)s to mention a channel." + "%(new_line)sType %(bold_start)s/command%(bold_end)s to execute a command." + ) + ) % {"bold_start": Markup(""), "bold_end": Markup(""), "new_line": Markup("
")} return msg def execute_command_leave(self, **kwargs): diff --git a/addons/mail/tests/discuss/test_discuss_channel.py b/addons/mail/tests/discuss/test_discuss_channel.py index f1a86835968..41482936e22 100644 --- a/addons/mail/tests/discuss/test_discuss_channel.py +++ b/addons/mail/tests/discuss/test_discuss_channel.py @@ -402,3 +402,63 @@ class TestChannelInternals(MailCommon): member_of_correspondent = self.env['discuss.channel.member'].search([('channel_id', '=', chat.id), ('partner_id', '=', self.test_partner.id)]) self.assertTrue(member_of_current_user.is_pinned) self.assertFalse(member_of_correspondent.is_pinned) + + @users("employee") + def test_channel_command_help_in_channel(self): + """Ensures the command '/help' works in a channel""" + channel = self.env["discuss.channel"].browse(self.test_channel.ids) + channel.name = "R&D" + self.env['bus.bus'].sudo().search([]).unlink() + with self.assertBus( + [(self.env.cr.dbname, "res.partner", self.env.user.partner_id.id)], + [ + { + "type": "discuss.channel/transient_message", + "payload": { + "body": + "" + "You are in channel #<strong>R&D</strong>." + "

Type @username to mention someone, and grab their attention." + "
Type #channel to mention a channel." + "
Type /command to execute a command." + "
", + "model": "discuss.channel", + "res_id": channel.id, + }, + }, + ], + ): + channel.execute_command_help() + + @users("employee") + def test_channel_command_help_in_group(self): + """Ensures the command '/help' works in a group""" + self.partner_employee_nomail.name = f"{self.partner_employee_nomail.name}" + # Guarantee that the channel member ids in the group are in order. + test_group = self.env['discuss.channel'].create({ + 'name': 'Private Channel', + 'channel_type': 'group', + 'channel_partner_ids': [(6, 0, self.user_admin.partner_id.id)] + }) + test_group.add_members(self.partner_employee_nomail.ids) + self.env['bus.bus'].sudo().search([]).unlink() + with self.assertBus( + [(self.env.cr.dbname, "res.partner", self.env.user.partner_id.id)], + [ + { + "type": "discuss.channel/transient_message", + "payload": { + "body": + "" + "You are in a private conversation with @Mitchell Admin and @<strong>Evita Employee NoEmail</strong>." + "

Type @username to mention someone, and grab their attention." + "
Type #channel to mention a channel." + "
Type /command to execute a command." + "
", + "model": "discuss.channel", + "res_id": test_group.id, + }, + }, + ], + ): + test_group.execute_command_help()