odoo-addon-mail-gateway 16.0.1.3.0__py3-none-any.whl → 17.0.1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of odoo-addon-mail-gateway might be problematic. Click here for more details.

Files changed (91) hide show
  1. odoo/addons/mail_gateway/README.rst +31 -24
  2. odoo/addons/mail_gateway/__init__.py +0 -1
  3. odoo/addons/mail_gateway/__manifest__.py +6 -14
  4. odoo/addons/mail_gateway/controllers/discuss.py +2 -2
  5. odoo/addons/mail_gateway/controllers/gateway.py +3 -0
  6. odoo/addons/mail_gateway/hooks.py +3 -3
  7. odoo/addons/mail_gateway/i18n/es.po +68 -406
  8. odoo/addons/mail_gateway/i18n/it.po +5 -336
  9. odoo/addons/mail_gateway/i18n/mail_gateway.pot +149 -84
  10. odoo/addons/mail_gateway/models/__init__.py +4 -3
  11. odoo/addons/mail_gateway/models/{mail_channel.py → discuss_channel.py} +30 -8
  12. odoo/addons/mail_gateway/models/ir_websocket.py +1 -1
  13. odoo/addons/mail_gateway/models/mail_gateway.py +4 -4
  14. odoo/addons/mail_gateway/models/mail_gateway_abstract.py +2 -2
  15. odoo/addons/mail_gateway/models/mail_message.py +9 -8
  16. odoo/addons/mail_gateway/models/mail_notification.py +3 -3
  17. odoo/addons/mail_gateway/models/mail_thread.py +40 -8
  18. odoo/addons/mail_gateway/models/res_partner.py +10 -18
  19. odoo/addons/mail_gateway/models/res_users.py +0 -1
  20. odoo/addons/mail_gateway/models/res_users_settings.py +12 -0
  21. odoo/addons/mail_gateway/readme/CONTRIBUTORS.md +2 -0
  22. odoo/addons/mail_gateway/readme/{CREDITS.rst → CREDITS.md} +2 -1
  23. odoo/addons/mail_gateway/readme/DESCRIPTION.md +8 -0
  24. odoo/addons/mail_gateway/readme/USAGE.md +12 -0
  25. odoo/addons/mail_gateway/security/ir.model.access.csv +4 -2
  26. odoo/addons/mail_gateway/security/security.xml +9 -9
  27. odoo/addons/mail_gateway/static/description/index.html +23 -16
  28. odoo/addons/mail_gateway/static/src/components/chatter/chatter.esm.js +15 -0
  29. odoo/addons/mail_gateway/static/src/components/chatter/chatter.xml +36 -22
  30. odoo/addons/mail_gateway/static/src/components/composer/composer.esm.js +108 -0
  31. odoo/addons/mail_gateway/static/src/components/gateway_follower/gateway_follower.esm.js +35 -22
  32. odoo/addons/mail_gateway/static/src/components/gateway_follower/gateway_follower.xml +3 -5
  33. odoo/addons/mail_gateway/static/src/components/message/message.xml +15 -15
  34. odoo/addons/mail_gateway/static/src/components/message/message_patch.esm.js +67 -0
  35. odoo/addons/mail_gateway/static/src/components/message_notification_popover_content/message_notification_popover_content.xml +3 -7
  36. odoo/addons/mail_gateway/static/src/core/common/composer_model_patch.esm.js +23 -0
  37. odoo/addons/mail_gateway/static/src/core/common/discuss_app_model_patch.esm.js +31 -0
  38. odoo/addons/mail_gateway/static/src/core/common/message_actions.esm.js +23 -0
  39. odoo/addons/mail_gateway/static/src/core/common/message_model_patch.esm.js +21 -0
  40. odoo/addons/mail_gateway/static/src/core/common/notification_model_patch.esm.js +35 -0
  41. odoo/addons/mail_gateway/static/src/core/common/persona_model_patch.esm.js +12 -0
  42. odoo/addons/mail_gateway/static/src/core/common/store_service_patch.esm.js +14 -0
  43. odoo/addons/mail_gateway/static/src/core/common/thread_model_patch.esm.js +49 -0
  44. odoo/addons/mail_gateway/static/src/core/common/thread_service_patch.esm.js +19 -0
  45. odoo/addons/mail_gateway/static/src/core/web/discuss_app_category_model_patch.esm.js +21 -0
  46. odoo/addons/mail_gateway/static/src/core/web/discuss_sidebar_categories.esm.js +16 -0
  47. odoo/addons/mail_gateway/static/src/core/web/discuss_sidebar_category_item_patch.xml +12 -0
  48. odoo/addons/mail_gateway/static/src/core/web/gateway_core_web_service.esm.js +40 -0
  49. odoo/addons/mail_gateway/static/src/models/gateway.esm.js +21 -14
  50. odoo/addons/mail_gateway/static/src/models/gateway_channel.esm.js +21 -13
  51. odoo/addons/mail_gateway/static/src/models/gateway_follower.esm.js +24 -0
  52. odoo/addons/mail_gateway/views/mail_gateway.xml +4 -4
  53. odoo/addons/mail_gateway/views/mail_guest_views.xml +15 -0
  54. odoo/addons/mail_gateway/wizards/mail_compose_gateway_message.py +19 -4
  55. odoo/addons/mail_gateway/wizards/mail_compose_gateway_message.xml +1 -2
  56. odoo/addons/mail_gateway/wizards/mail_guest_manage.py +2 -3
  57. odoo/addons/mail_gateway/wizards/mail_guest_manage.xml +2 -2
  58. odoo/addons/mail_gateway/wizards/mail_message_gateway_link.py +1 -2
  59. odoo/addons/mail_gateway/wizards/mail_message_gateway_send.py +0 -1
  60. {odoo_addon_mail_gateway-16.0.1.3.0.dist-info → odoo_addon_mail_gateway-17.0.1.0.1.dist-info}/METADATA +38 -30
  61. odoo_addon_mail_gateway-17.0.1.0.1.dist-info/RECORD +74 -0
  62. {odoo_addon_mail_gateway-16.0.1.3.0.dist-info → odoo_addon_mail_gateway-17.0.1.0.1.dist-info}/WHEEL +1 -1
  63. odoo_addon_mail_gateway-17.0.1.0.1.dist-info/top_level.txt +1 -0
  64. odoo/addons/mail_gateway/i18n/es_VE.po +0 -879
  65. odoo/addons/mail_gateway/readme/CONTRIBUTORS.rst +0 -2
  66. odoo/addons/mail_gateway/readme/DESCRIPTION.rst +0 -5
  67. odoo/addons/mail_gateway/readme/USAGE.rst +0 -9
  68. odoo/addons/mail_gateway/static/src/components/composer/composer.xml +0 -24
  69. odoo/addons/mail_gateway/static/src/components/discuss_sidebar/discuss_sidebar.xml +0 -17
  70. odoo/addons/mail_gateway/static/src/models/channel.esm.js +0 -33
  71. odoo/addons/mail_gateway/static/src/models/channel_member_view.esm.js +0 -39
  72. odoo/addons/mail_gateway/static/src/models/chatter.esm.js +0 -41
  73. odoo/addons/mail_gateway/static/src/models/composer.esm.js +0 -32
  74. odoo/addons/mail_gateway/static/src/models/composer_gateway_follower.esm.js +0 -32
  75. odoo/addons/mail_gateway/static/src/models/composer_view.esm.js +0 -103
  76. odoo/addons/mail_gateway/static/src/models/discuss.esm.js +0 -51
  77. odoo/addons/mail_gateway/static/src/models/discuss_sidebar_category.esm.js +0 -128
  78. odoo/addons/mail_gateway/static/src/models/discuss_sidebar_category_item.esm.js +0 -51
  79. odoo/addons/mail_gateway/static/src/models/gateway_channel_view.esm.js +0 -15
  80. odoo/addons/mail_gateway/static/src/models/guest.esm.js +0 -10
  81. odoo/addons/mail_gateway/static/src/models/message.esm.js +0 -76
  82. odoo/addons/mail_gateway/static/src/models/message_action.esm.js +0 -45
  83. odoo/addons/mail_gateway/static/src/models/message_action_list.esm.js +0 -37
  84. odoo/addons/mail_gateway/static/src/models/message_action_view.esm.js +0 -91
  85. odoo/addons/mail_gateway/static/src/models/message_view.esm.js +0 -13
  86. odoo/addons/mail_gateway/static/src/models/messaging_initializer.esm.js +0 -24
  87. odoo/addons/mail_gateway/static/src/models/notification.esm.js +0 -20
  88. odoo/addons/mail_gateway/static/src/models/partner.esm.js +0 -11
  89. odoo/addons/mail_gateway/static/src/models/thread.esm.js +0 -77
  90. odoo_addon_mail_gateway-16.0.1.3.0.dist-info/RECORD +0 -78
  91. odoo_addon_mail_gateway-16.0.1.3.0.dist-info/top_level.txt +0 -1
@@ -7,13 +7,13 @@ from odoo import fields, models
7
7
  class MailNotification(models.Model):
8
8
  _inherit = "mail.notification"
9
9
 
10
- gateway_channel_id = fields.Many2one("mail.channel")
10
+ gateway_channel_id = fields.Many2one("discuss.channel")
11
11
  notification_type = fields.Selection(
12
12
  selection_add=[("gateway", "Gateway")], ondelete={"gateway": "cascade"}
13
13
  )
14
14
  gateway_message_id = fields.Char(readonly=True)
15
15
  gateway_failure_reason = fields.Text(
16
- readonly=1,
16
+ readonly=True,
17
17
  help="Failure reason. This is usually the exception thrown by the"
18
18
  " email server, stored to ease the debugging of mailing issues.",
19
19
  )
@@ -26,7 +26,7 @@ class MailNotification(models.Model):
26
26
 
27
27
  def _notification_format(self):
28
28
  result = super()._notification_format()
29
- for record, formatted_value in zip(self, result):
29
+ for record, formatted_value in zip(self, result, strict=True):
30
30
  formatted_value["gateway_type"] = record.gateway_type
31
31
  formatted_value["channel_name"] = record.gateway_channel_id.name
32
32
  return result
@@ -6,6 +6,18 @@ from odoo import models
6
6
  class MailThread(models.AbstractModel):
7
7
  _inherit = "mail.thread"
8
8
 
9
+ def _get_message_create_valid_field_names(self):
10
+ # Add gateway fields
11
+ field_names = super()._get_message_create_valid_field_names()
12
+ field_names.update(
13
+ {"gateway_type", "gateway_notifications", "gateway_message_id"}
14
+ )
15
+ return field_names
16
+
17
+ def _get_notify_valid_parameters(self):
18
+ notify_valid_parameters = super()._get_notify_valid_parameters()
19
+ return notify_valid_parameters | {"gateway_notifications"}
20
+
9
21
  def _notify_thread_by_email(self, message, recipients_data, **kwargs):
10
22
  partners_data = [r for r in recipients_data if r["notif"] == "gateway"]
11
23
  if partners_data:
@@ -25,7 +37,7 @@ class MailThread(models.AbstractModel):
25
37
  )
26
38
 
27
39
  def _notify_get_recipients(self, message, msg_vals, **kwargs):
28
- if "gateway_notifications" in kwargs:
40
+ if kwargs.get("gateway_notifications"):
29
41
  result = []
30
42
  for notification in kwargs["gateway_notifications"]:
31
43
  if not notification.get("channel_type"):
@@ -56,30 +68,50 @@ class MailThread(models.AbstractModel):
56
68
  return result
57
69
  return super()._notify_get_recipients(message, msg_vals, **kwargs)
58
70
 
71
+ def _get_mail_thread_data(self, request_list):
72
+ data = super()._get_mail_thread_data(request_list)
73
+ data["gateway_followers"] = [
74
+ f["partner"]
75
+ for f in data.get("followers", [])
76
+ if f["partner"]["gateway_channels"]
77
+ ]
78
+ return data
79
+
59
80
  def _check_can_update_message_content(self, messages):
60
81
  # We can delete the messages comming from a gateway on not channels
61
- if self._name != "mail.channel":
82
+ if self._name != "discuss.channel":
62
83
  new_messages = messages.filtered(lambda r: not r.gateway_message_ids)
63
84
  else:
64
85
  new_messages = messages
65
86
  return super()._check_can_update_message_content(new_messages)
66
87
 
67
88
  def _message_update_content(
68
- self, message, body, attachment_ids=None, strict=True, **kwargs
89
+ self,
90
+ message,
91
+ body,
92
+ attachment_ids=None,
93
+ partner_ids=None,
94
+ strict=True,
95
+ **kwargs,
69
96
  ):
70
97
  result = super()._message_update_content(
71
- message, body, attachment_ids=attachment_ids, strict=strict, **kwargs
98
+ message=message,
99
+ body=body,
100
+ attachment_ids=attachment_ids,
101
+ partner_ids=partner_ids,
102
+ strict=strict,
103
+ **kwargs,
72
104
  )
73
105
  if body == "":
74
106
  # Unlink the message
75
- for gateway_message in message.gateway_message_ids:
76
- gateway_message.gateway_message_id = False
107
+ for gateway_msg in message.gateway_message_ids:
108
+ gateway_msg.gateway_message_id = False
77
109
  self.env["bus.bus"]._sendone(
78
110
  self.env.user.partner_id,
79
111
  "mail.message/insert",
80
112
  {
81
- "id": gateway_message.id,
82
- "gateway_thread_data": gateway_message.sudo().gateway_thread_data,
113
+ "id": gateway_msg.id,
114
+ "gateway_thread_data": gateway_msg.sudo().gateway_thread_data,
83
115
  },
84
116
  )
85
117
  return result
@@ -1,7 +1,7 @@
1
1
  # Copyright 2024 Dixmit
2
2
  # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3
3
 
4
- from odoo import fields, models
4
+ from odoo import api, fields, models
5
5
 
6
6
 
7
7
  class ResPartner(models.Model):
@@ -30,13 +30,13 @@ class ResPartner(models.Model):
30
30
  def _get_channels_as_member(self):
31
31
  channels = super()._get_channels_as_member()
32
32
  if self.env.user.has_group("mail_gateway.gateway_user"):
33
- channels |= self.env["mail.channel"].search(
33
+ channels |= self.env["discuss.channel"].search(
34
34
  [
35
35
  ("channel_type", "=", "gateway"),
36
36
  (
37
37
  "channel_member_ids",
38
38
  "in",
39
- self.env["mail.channel.member"]
39
+ self.env["discuss.channel.member"]
40
40
  .sudo()
41
41
  ._search(
42
42
  [
@@ -66,24 +66,16 @@ class ResPartnerGatewayChannel(models.Model):
66
66
  "res.company", related="gateway_id.company_id", store=True
67
67
  )
68
68
 
69
- def name_get(self):
69
+ @api.depends_context("mail_gateway_partner_info")
70
+ def _compute_display_name(self):
70
71
  # Be able to tell to which partner belongs the gateway partner channel
71
72
  # e.g.: picking it from a selector
72
- result = []
73
- origin = super().name_get()
74
- if not self.env.context.get("mail_gateway_partner_info", False):
75
- return origin
76
- origin_dict = dict(origin)
77
- for record in self:
78
- result.append(
79
- (
80
- record.id,
81
- "{} ({})".format(
82
- record.partner_id.display_name, origin_dict[record.id]
83
- ),
84
- )
73
+ if not self.env.context.get("mail_gateway_partner_info"):
74
+ return super()._compute_display_name()
75
+ for gateway_channel in self:
76
+ gateway_channel.display_name = (
77
+ f"{gateway_channel.partner_id.display_name} ({gateway_channel.name})"
85
78
  )
86
- return result
87
79
 
88
80
  _sql_constraints = [
89
81
  (
@@ -5,7 +5,6 @@ from odoo import fields, models
5
5
 
6
6
 
7
7
  class ResUsers(models.Model):
8
-
9
8
  _inherit = "res.users"
10
9
 
11
10
  gateway_ids = fields.Many2many("mail.gateway")
@@ -0,0 +1,12 @@
1
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
2
+ from odoo import fields, models
3
+
4
+
5
+ class ResUsersSettings(models.Model):
6
+ _inherit = "res.users.settings"
7
+
8
+ is_discuss_sidebar_category_gateway_open = fields.Boolean(
9
+ string="Gateway Category Open",
10
+ default=True,
11
+ help="The gateway category in the sidebar will be open",
12
+ )
@@ -0,0 +1,2 @@
1
+ - Enric Tobella
2
+ - Olga Marco
@@ -1 +1,2 @@
1
- This work has been funded by AEOdoo (Asociación Española de Odoo - https://www.aeodoo.org)
1
+ This work has been funded by AEOdoo (Asociación Española de Odoo -
2
+ <https://www.aeodoo.org>)
@@ -0,0 +1,8 @@
1
+ This module will allow you to integrate an external chat system in your
2
+ Odoo system. It requires extra modules with the specific configuration
3
+ of each chat system, like mail_gateway_telegram or
4
+ mail_gateway_whatsapp.
5
+
6
+ This way, a group of users can respond customers or any other set of
7
+ partners within Odoo, but the messages will be sent through the external
8
+ chat system.
@@ -0,0 +1,12 @@
1
+ When external messages are received, they will be directly sent to the
2
+ discuss menu. Answering to these messages will send the answer to the
3
+ external contact. We can assign this messages to any record using the
4
+ message actions. Also, we can assign the sender to a partner using the
5
+ followers menu and selecting the partner.
6
+
7
+ On a standard record associated to a partner with external chat, we can
8
+ send messages to the external contact directly selecting the methods of
9
+ the partner. To use this, we just need to use the
10
+
11
+ It is recomended to enable chatter notification to all users that will
12
+ receive messages from gateways.
@@ -3,8 +3,10 @@ access_res_partner_gateway_channel_portal,res.partner.gateway.channel.portal,mod
3
3
  access_res_partner_gateway_channel_user,res.partner.gateway.channel,model_res_partner_gateway_channel,base.group_user,1,0,0,0
4
4
  manage_res_partner_gateway_channel_user,res.partner.gateway.channel,model_res_partner_gateway_channel,gateway_user,1,1,1,1
5
5
  access_mail_message_gateway_send_user,mail.message.gateway.send,model_mail_message_gateway_send,base.group_user,1,1,1,0
6
- access_mail_gateway_all,mail.telegram.bot.all,model_mail_gateway,,1,0,0,0
7
- access_mail_guest_manage,mail.telegram.bot.all,model_mail_guest_manage,base.group_user,1,1,1,1
6
+ access_mail_gateway_portal,mail.gateway.portal,model_mail_gateway,base.group_portal,1,0,0,0
7
+ access_mail_gateway_public,mail.gateway.public,model_mail_gateway,base.group_public,1,0,0,0
8
+ access_mail_gateway_user,mail.gateway.user,model_mail_gateway,base.group_user,1,0,0,0
9
+ access_mail_guest_manage,mail.gateway.internal,model_mail_guest_manage,base.group_user,1,1,1,1
8
10
  access_mail_message_gateway_link,mail.message.link.all,model_mail_message_gateway_link,base.group_user,1,1,1,1
9
11
  access_mail_gateway_system,mail_gateway,model_mail_gateway,base.group_system,1,1,1,1
10
12
  access_mail_compose_gateway_message,access.mail.compose.gateway.message,model_mail_compose_gateway_message,base.group_user,1,1,1,0
@@ -11,13 +11,13 @@
11
11
  eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"
12
12
  />
13
13
  </record>
14
- <record id="mail_channel_gateway_rule" model="ir.rule">
15
- <field name="name">Mail.channel: access gateway</field>
16
- <field name="model_id" ref="mail.model_mail_channel" />
14
+ <record id="discuss_channel_gateway_rule" model="ir.rule">
15
+ <field name="name">discuss.channel: access gateway</field>
16
+ <field name="model_id" ref="mail.model_discuss_channel" />
17
17
  <field name="groups" eval="[(4, ref('mail_gateway.gateway_user'))]" />
18
18
  <field
19
19
  name="domain_force"
20
- >[('channel_type', '=', 'gateway'), '|', ('company_id', '=', False), ('company_id', 'in', company_ids) ]</field>
20
+ >[('channel_type', '=', 'gateway'), ('company_id', 'in', company_ids + [False]) ]</field>
21
21
  <field name="perm_read" eval="True" />
22
22
  <field name="perm_create" eval="False" />
23
23
  <field name="perm_write" eval="True" />
@@ -28,7 +28,7 @@
28
28
  <field name="model_id" ref="mail_gateway.model_mail_gateway" />
29
29
  <field
30
30
  name="domain_force"
31
- >['|', ('company_id', '=', False), ('company_id', 'in', company_ids) ]</field>
31
+ >[('company_id', 'in', company_ids + [False]) ]</field>
32
32
  <field name="perm_read" eval="True" />
33
33
  <field name="perm_create" eval="True" />
34
34
  <field name="perm_write" eval="True" />
@@ -39,17 +39,17 @@
39
39
  <field name="model_id" ref="mail_gateway.model_res_partner_gateway_channel" />
40
40
  <field
41
41
  name="domain_force"
42
- >['|', ('company_id', '=', False), ('company_id', 'in', company_ids) ]</field>
42
+ >[('company_id', 'in', company_ids + [False]) ]</field>
43
43
  <field name="perm_read" eval="True" />
44
44
  <field name="perm_create" eval="True" />
45
45
  <field name="perm_write" eval="True" />
46
46
  <field name="perm_unlink" eval="True" />
47
47
  </record>
48
- <record id="ir_rule_mail_channel_partner_group_user" model="ir.rule">
48
+ <record id="ir_rule_discuss_channel_partner_group_user" model="ir.rule">
49
49
  <field
50
50
  name="name"
51
- >mail.channel.member: write its own entries on gateway channels members</field>
52
- <field name="model_id" ref="mail.model_mail_channel_member" />
51
+ >discuss.channel.member: write its own entries on gateway channels members</field>
52
+ <field name="model_id" ref="mail.model_discuss_channel_member" />
53
53
  <field name="groups" eval="[(4, ref('mail_gateway.gateway_user'))]" />
54
54
  <field name="domain_force">[('channel_id.channel_type', '=', 'gateway')]</field>
55
55
  <field name="perm_read" eval="False" />
@@ -372,13 +372,16 @@ ul.auto-toc {
372
372
  !! This file is generated by oca-gen-addon-readme !!
373
373
  !! changes will be overwritten. !!
374
374
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
375
- !! source digest: sha256:cff2294334d6db807a724770b407b9c0b280e14970058bf4415703b93038290b
375
+ !! source digest: sha256:dd9cb533ce55e29e10867b506e532d6379d7cd12fba20203d82804176c6a8dfa
376
376
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
377
- <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/social/tree/16.0/mail_gateway"><img alt="OCA/social" src="https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/social-16-0/social-16-0-mail_gateway"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/social&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
378
- <p>This module will allow you to integrate an external chat system in your Odoo system.
379
- It requires extra modules with the specific configuration of each chat system, like <cite>mail_gateway_telegram</cite> or <cite>mail_gateway_whatsapp</cite>.</p>
380
- <p>This way, a group of users can respond customers or any other set
381
- of partners within Odoo, but the messages will be sent through the external chat system.</p>
377
+ <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/social/tree/17.0/mail_gateway"><img alt="OCA/social" src="https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/social-17-0/social-17-0-mail_gateway"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/social&amp;target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
378
+ <p>This module will allow you to integrate an external chat system in your
379
+ Odoo system. It requires extra modules with the specific configuration
380
+ of each chat system, like mail_gateway_telegram or
381
+ mail_gateway_whatsapp.</p>
382
+ <p>This way, a group of users can respond customers or any other set of
383
+ partners within Odoo, but the messages will be sent through the external
384
+ chat system.</p>
382
385
  <p><strong>Table of contents</strong></p>
383
386
  <div class="contents local topic" id="contents">
384
387
  <ul class="simple">
@@ -395,20 +398,23 @@ of partners within Odoo, but the messages will be sent through the external chat
395
398
  </div>
396
399
  <div class="section" id="usage">
397
400
  <h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
398
- <p>When external messages are received, they will be directly sent to the discuss menu.
399
- Answering to these messages will send the answer to the external contact.
400
- We can assign this messages to any record using the message actions.
401
- Also, we can assign the sender to a partner using the followers menu and selecting the partner.</p>
402
- <p>On a standard record associated to a partner with external chat, we can send messages to the external contact directly selecting the methods of the partner.
403
- To use this, we just need to use the</p>
404
- <p>It is recomended to enable chatter notification to all users that will receive messages from gateways.</p>
401
+ <p>When external messages are received, they will be directly sent to the
402
+ discuss menu. Answering to these messages will send the answer to the
403
+ external contact. We can assign this messages to any record using the
404
+ message actions. Also, we can assign the sender to a partner using the
405
+ followers menu and selecting the partner.</p>
406
+ <p>On a standard record associated to a partner with external chat, we can
407
+ send messages to the external contact directly selecting the methods of
408
+ the partner. To use this, we just need to use the</p>
409
+ <p>It is recomended to enable chatter notification to all users that will
410
+ receive messages from gateways.</p>
405
411
  </div>
406
412
  <div class="section" id="bug-tracker">
407
413
  <h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
408
414
  <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/social/issues">GitHub Issues</a>.
409
415
  In case of trouble, please check there if your issue has already been reported.
410
416
  If you spotted it first, help us to smash it by providing a detailed and welcomed
411
- <a class="reference external" href="https://github.com/OCA/social/issues/new?body=module:%20mail_gateway%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
417
+ <a class="reference external" href="https://github.com/OCA/social/issues/new?body=module:%20mail_gateway%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
412
418
  <p>Do not contact contributors directly about support or help with technical issues.</p>
413
419
  </div>
414
420
  <div class="section" id="credits">
@@ -429,7 +435,8 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
429
435
  </div>
430
436
  <div class="section" id="other-credits">
431
437
  <h3><a class="toc-backref" href="#toc-entry-6">Other credits</a></h3>
432
- <p>This work has been funded by AEOdoo (Asociación Española de Odoo - <a class="reference external" href="https://www.aeodoo.org">https://www.aeodoo.org</a>)</p>
438
+ <p>This work has been funded by AEOdoo (Asociación Española de Odoo -
439
+ <a class="reference external" href="https://www.aeodoo.org">https://www.aeodoo.org</a>)</p>
433
440
  </div>
434
441
  <div class="section" id="maintainers">
435
442
  <h3><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h3>
@@ -440,7 +447,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
440
447
  <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
441
448
  mission is to support the collaborative development of Odoo features and
442
449
  promote its widespread use.</p>
443
- <p>This module is part of the <a class="reference external" href="https://github.com/OCA/social/tree/16.0/mail_gateway">OCA/social</a> project on GitHub.</p>
450
+ <p>This module is part of the <a class="reference external" href="https://github.com/OCA/social/tree/17.0/mail_gateway">OCA/social</a> project on GitHub.</p>
444
451
  <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
445
452
  </div>
446
453
  </div>
@@ -0,0 +1,15 @@
1
+ /** @odoo-module **/
2
+ import {Chatter} from "@mail/core/web/chatter";
3
+ import {patch} from "@web/core/utils/patch";
4
+ import {GatewayFollower} from "../gateway_follower/gateway_follower.esm";
5
+
6
+ patch(Chatter, {
7
+ components: {...Chatter.components, GatewayFollower},
8
+ });
9
+
10
+ patch(Chatter.prototype, {
11
+ toggleComposer(mode = false) {
12
+ this.state.thread.composer.isGateway = mode === "gateway";
13
+ super.toggleComposer(mode);
14
+ },
15
+ });
@@ -3,38 +3,52 @@
3
3
 
4
4
  <t
5
5
  t-name="mail_gateway.ChatterTopbar"
6
- t-inherit="mail.ChatterTopbar"
6
+ t-inherit="mail.Chatter"
7
7
  t-inherit-mode="extension"
8
- owl="1"
9
8
  >
10
- <xpath
11
- expr="//button[hasclass('o_ChatterTopbar_buttonSendMessage')]"
12
- position="attributes"
13
- >
14
- <attribute name="t-att-class">{
15
- 'o-active btn-odoo': chatterTopbar.chatter.composerView and !chatterTopbar.chatter.composerView.composer.isLog and !chatterTopbar.chatter.composerView.composer.isGateway,
16
- 'btn-odoo': !chatterTopbar.chatter.composerView,
17
- 'btn-light': chatterTopbar.chatter.composerView and (chatterTopbar.chatter.composerView.composer.isLog or chatterTopbar.chatter.composerView.composer.isGateway),
18
- }</attribute>
19
- </xpath>
20
- <xpath
21
- expr="//button[hasclass('o_ChatterTopbar_buttonLogNote')]"
22
- position="after"
23
- >
9
+ <xpath expr="//button[hasclass('o-mail-Chatter-logNote')]" position="after">
24
10
  <button
25
- class="o_ChatterTopbar_button o_ChatterTopbar_buttonLogWhatsapp btn text-nowrap btn-light"
11
+ class="o-mail-Chatter-gateway btn text-nowrap me-1"
26
12
  type="button"
27
13
  t-att-class="{
28
- 'o-active btn-odoo': chatterTopbar.chatter.composerView and !chatterTopbar.chatter.composerView.composer.isLog and chatterTopbar.chatter.composerView.composer.isGateway,
29
- 'btn-odoo': !chatterTopbar.chatter.composerView,
30
- 'btn-light': !chatterTopbar.chatter.composerView or (chatterTopbar.chatter.composerView.composer.isLog or !chatterTopbar.chatter.composerView.composer.isGateway),
14
+ 'btn-primary active': state.composerType === 'gateway',
15
+ 'btn-secondary': state.composerType !== 'gateway',
16
+ 'my-2': !props.compactHeight
31
17
  }"
32
- t-att-disabled="!chatterTopbar.chatter.isTemporary and !chatterTopbar.chatter.hasWriteAccess"
33
- t-on-click="() => this.chatterTopbar.chatter.onClickGatewayMessage()"
18
+ t-on-click="() => this.toggleComposer('gateway')"
19
+ data-hotkey="shift+w"
34
20
  >
35
21
  <i class="fa fa-plane" role="img" aria-label="gateway" />
36
22
  <span> Gateway message</span>
37
23
  </button>
38
24
  </xpath>
25
+ <xpath expr="//SuggestedRecipientsList" position="before">
26
+ <t
27
+ t-if="state.composerType === 'gateway' and state.thread.gateway_followers.length"
28
+ >
29
+ <div
30
+ class="flex-shrink-0 px-3 pt-3 text-truncate small mb-2"
31
+ style="margin-left:48px"
32
+ >
33
+ <span class="fw-bold">To:</span>
34
+ <t
35
+ t-foreach="state.thread.gateway_followers"
36
+ t-as="gateway_follower"
37
+ t-key="gateway_follower.id"
38
+ >
39
+ <GatewayFollower
40
+ follower="gateway_follower"
41
+ composer="state.thread.composer"
42
+ />
43
+ </t>
44
+ </div>
45
+ </t>
46
+ <t t-set="type" t-value="type === 'gateway' ? 'gateway' : type" />
47
+ </xpath>
48
+ <xpath expr="//SuggestedRecipientsList" position="attributes">
49
+ <attribute
50
+ name="t-if"
51
+ >props.hasFollowers and state.composerType !== 'note' and state.composerType !== 'gateway'</attribute>
52
+ </xpath>
39
53
  </t>
40
54
  </templates>
@@ -0,0 +1,108 @@
1
+ /** @odoo-module **/
2
+ import {patch} from "@web/core/utils/patch";
3
+ import {Composer} from "@mail/core/common/composer";
4
+ import {_t} from "@web/core/l10n/translation";
5
+ import {prettifyMessageContent} from "@mail/utils/common/format";
6
+
7
+ patch(Composer.prototype, {
8
+ get SEND_TEXT() {
9
+ if (this.props.type === "gateway" && !this.props.composer.message) {
10
+ return _t("Send gateway");
11
+ }
12
+ return super.SEND_TEXT;
13
+ },
14
+ get placeholder() {
15
+ if (
16
+ this.thread?.model !== "discuss.channel" &&
17
+ !this.props.placeholder &&
18
+ this.props.type === "gateway"
19
+ ) {
20
+ return _t("Send a message to a gateway...");
21
+ }
22
+ return super.placeholder;
23
+ },
24
+ get isSendButtonDisabled() {
25
+ const isSendButtonDisabled = super.isSendButtonDisabled;
26
+ if (this.props.type !== "gateway") {
27
+ return isSendButtonDisabled;
28
+ }
29
+ return isSendButtonDisabled || !this.thread?.gateway_notifications.length;
30
+ },
31
+ onFocusin() {
32
+ super.onFocusin();
33
+ if (this.props.type !== "gateway") {
34
+ this.thread.gateway_notifications = [];
35
+ }
36
+ },
37
+ async onClickFullComposer() {
38
+ if (this.props.type !== "gateway") {
39
+ return super.onClickFullComposer(...arguments);
40
+ }
41
+ const attachmentIds = this.props.composer.attachments.map(
42
+ (attachment) => attachment.id
43
+ );
44
+ const body = this.props.composer.textInputContent;
45
+ const validMentions = this.store.user
46
+ ? this.messageService.getMentionsFromText(body, {
47
+ mentionedChannels: this.props.composer.mentionedChannels,
48
+ mentionedPartners: this.props.composer.mentionedPartners,
49
+ })
50
+ : undefined;
51
+ // Debugger
52
+ const context = {
53
+ default_attachment_ids: attachmentIds,
54
+ default_body: await prettifyMessageContent(body, validMentions),
55
+ default_model: this.thread.model,
56
+ default_partner_ids: this.thread.suggestedRecipients
57
+ .filter((recipient) => recipient.checked)
58
+ .map((recipient) => recipient.persona.id),
59
+ default_res_ids: [this.thread.id],
60
+ default_subtype_xmlid: "mail.mt_comment",
61
+ mail_post_autofollow: this.thread.hasWriteAccess,
62
+ default_wizard_partner_ids: Array.from(
63
+ new Set(
64
+ this.thread.gateway_followers.map((follower) => {
65
+ return follower.id;
66
+ })
67
+ )
68
+ ),
69
+ default_wizard_channel_ids: Array.from(
70
+ new Set(
71
+ this.thread.gateway_followers
72
+ .map((follower) => {
73
+ return follower.gateway_channels.map(
74
+ (channel) => channel?.id
75
+ );
76
+ })
77
+ .flat()
78
+ )
79
+ ),
80
+ };
81
+ const action = {
82
+ name: _t("Gateway message"),
83
+ type: "ir.actions.act_window",
84
+ res_model: "mail.compose.gateway.message",
85
+ view_mode: "form",
86
+ views: [[false, "form"]],
87
+ target: "new",
88
+ context: context,
89
+ };
90
+ const options = {
91
+ onClose: (...args) => {
92
+ // Args === [] : click on 'X'
93
+ // args === { special: true } : click on 'discard'
94
+ const isDiscard = args.length === 0 || args[0]?.special;
95
+ // Otherwise message is posted (args === [undefined])
96
+ if (!isDiscard && this.props.composer.thread.type === "mailbox") {
97
+ this.notifySendFromMailbox();
98
+ }
99
+ this.clear();
100
+ this.props.messageToReplyTo?.cancel();
101
+ if (this.thread) {
102
+ this.threadService.fetchNewMessages(this.thread);
103
+ }
104
+ },
105
+ };
106
+ await this.env.services.action.doAction(action, options);
107
+ },
108
+ });
@@ -1,31 +1,44 @@
1
1
  /** @odoo-module **/
2
+ import {Component} from "@odoo/owl";
2
3
 
3
- import {registerMessagingComponent} from "@mail/utils/messaging_component";
4
- import {useComponentToModel} from "@mail/component_hooks/use_component_to_model";
5
-
6
- const {Component} = owl;
7
-
8
- class GatewayFollowerView extends Component {
9
- /**
10
- * @override
11
- */
4
+ export class GatewayFollower extends Component {
5
+ static template = "mail_gateway.GatewayFollowerView";
6
+ static props = ["follower", "composer"];
12
7
  setup() {
13
- super.setup();
14
- useComponentToModel({fieldName: "component"});
8
+ this.channel = false;
9
+ this.follower_channel_ids = this.props.follower.gateway_channels.map(
10
+ (channel) => channel.id
11
+ );
12
+ this._clearGatewayNotifications();
15
13
  }
16
14
  get composerGatewayFollower() {
17
- return this.props.record;
15
+ return this.props.follower;
16
+ }
17
+ _getMessageData() {
18
+ return {
19
+ partner_id: this.props.follower.id,
20
+ channel_type: "gateway",
21
+ gateway_channel_id: this.channel,
22
+ };
23
+ }
24
+ _clearGatewayNotifications() {
25
+ this.props.composer.thread.gateway_notifications =
26
+ this.props.composer.thread.gateway_notifications.filter(
27
+ (gateway_notification) => {
28
+ return !this.follower_channel_ids.includes(
29
+ gateway_notification.gateway_channel_id
30
+ );
31
+ }
32
+ );
18
33
  }
19
34
  onChangeGatewayChannel(ev) {
20
- this.props.record.update({
21
- channel: parseInt(ev.target.options[ev.target.selectedIndex].value, 10),
22
- });
35
+ this.channel = parseInt(ev.target.options[ev.target.selectedIndex].value, 10);
36
+ if (this.channel) {
37
+ this.props.composer.thread.gateway_notifications.push(
38
+ this._getMessageData()
39
+ );
40
+ } else {
41
+ this._clearGatewayNotifications();
42
+ }
23
43
  }
24
44
  }
25
-
26
- Object.assign(GatewayFollowerView, {
27
- props: {record: Object},
28
- template: "mail_gateway.GatewayFollowerView",
29
- });
30
-
31
- registerMessagingComponent(GatewayFollowerView);