[MIG] mail_tracking: Migration to 15.0
This commit is contained in:
parent
021689d073
commit
680eee8074
@ -7,7 +7,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Email tracking",
|
"name": "Email tracking",
|
||||||
"summary": "Email tracking system for all mails sent",
|
"summary": "Email tracking system for all mails sent",
|
||||||
"version": "14.0.2.0.2",
|
"version": "15.0.1.0.0",
|
||||||
"category": "Social Network",
|
"category": "Social Network",
|
||||||
"website": "https://github.com/OCA/social",
|
"website": "https://github.com/OCA/social",
|
||||||
"author": ("Tecnativa, " "Odoo Community Association (OCA)"),
|
"author": ("Tecnativa, " "Odoo Community Association (OCA)"),
|
||||||
@ -19,18 +19,30 @@
|
|||||||
"data/tracking_data.xml",
|
"data/tracking_data.xml",
|
||||||
"security/mail_tracking_email_security.xml",
|
"security/mail_tracking_email_security.xml",
|
||||||
"security/ir.model.access.csv",
|
"security/ir.model.access.csv",
|
||||||
"views/assets.xml",
|
|
||||||
"views/mail_tracking_email_view.xml",
|
"views/mail_tracking_email_view.xml",
|
||||||
"views/mail_tracking_event_view.xml",
|
"views/mail_tracking_event_view.xml",
|
||||||
"views/mail_message_view.xml",
|
"views/mail_message_view.xml",
|
||||||
"views/res_partner_view.xml",
|
"views/res_partner_view.xml",
|
||||||
],
|
],
|
||||||
"qweb": [
|
"assets": {
|
||||||
"static/src/xml/mail_tracking.xml",
|
"web.assets_backend": [
|
||||||
"static/src/xml/failed_message/common.xml",
|
"mail_tracking/static/src/css/mail_tracking.scss",
|
||||||
"static/src/xml/failed_message/thread.xml",
|
"mail_tracking/static/src/css/failed_message.scss",
|
||||||
"static/src/xml/failed_message/discuss.xml",
|
"mail_tracking/static/src/js/mail_tracking.esm.js",
|
||||||
],
|
"mail_tracking/static/src/js/message.esm.js",
|
||||||
|
"mail_tracking/static/src/js/failed_message/mail_failed_box.esm.js",
|
||||||
|
"mail_tracking/static/src/js/failed_message/thread.esm.js",
|
||||||
|
"mail_tracking/static/src/js/models/thread.esm.js",
|
||||||
|
"mail_tracking/static/src/js/chatter.esm.js",
|
||||||
|
"mail_tracking/static/src/js/discuss/discuss.esm.js",
|
||||||
|
],
|
||||||
|
"web.assets_qweb": [
|
||||||
|
"mail_tracking/static/src/xml/mail_tracking.xml",
|
||||||
|
"mail_tracking/static/src/xml/failed_message/common.xml",
|
||||||
|
"mail_tracking/static/src/xml/failed_message/thread.xml",
|
||||||
|
"mail_tracking/static/src/xml/failed_message/discuss.xml",
|
||||||
|
],
|
||||||
|
},
|
||||||
"demo": ["demo/demo.xml"],
|
"demo": ["demo/demo.xml"],
|
||||||
"pre_init_hook": "pre_init_hook",
|
"pre_init_hook": "pre_init_hook",
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,8 @@ import werkzeug
|
|||||||
import odoo
|
import odoo
|
||||||
from odoo import SUPERUSER_ID, api, http
|
from odoo import SUPERUSER_ID, api, http
|
||||||
|
|
||||||
from odoo.addons.mail.controllers.main import MailController
|
from odoo.addons.mail.controllers.discuss import DiscussController
|
||||||
|
from odoo.addons.mail.controllers.mail import MailController
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -26,11 +27,10 @@ def db_env(dbname):
|
|||||||
cr = http.request.cr
|
cr = http.request.cr
|
||||||
if not cr:
|
if not cr:
|
||||||
cr = odoo.sql_db.db_connect(dbname).cursor()
|
cr = odoo.sql_db.db_connect(dbname).cursor()
|
||||||
with api.Environment.manage():
|
yield api.Environment(cr, SUPERUSER_ID, {})
|
||||||
yield api.Environment(cr, SUPERUSER_ID, {})
|
|
||||||
|
|
||||||
|
|
||||||
class MailTrackingController(MailController):
|
class MailTrackingController(MailController, DiscussController):
|
||||||
def _request_metadata(self):
|
def _request_metadata(self):
|
||||||
"""Prepare remote info metadata"""
|
"""Prepare remote info metadata"""
|
||||||
request = http.request.httprequest
|
request = http.request.httprequest
|
||||||
@ -59,8 +59,8 @@ class MailTrackingController(MailController):
|
|||||||
res = env["mail.tracking.email"].event_process(
|
res = env["mail.tracking.email"].event_process(
|
||||||
http.request, kw, metadata, event_type=event_type
|
http.request, kw, metadata, event_type=event_type
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
_logger.warning(e)
|
||||||
if not res or res == "NOT FOUND":
|
if not res or res == "NOT FOUND":
|
||||||
return werkzeug.exceptions.NotAcceptable()
|
return werkzeug.exceptions.NotAcceptable()
|
||||||
return res
|
return res
|
||||||
@ -89,8 +89,8 @@ class MailTrackingController(MailController):
|
|||||||
)
|
)
|
||||||
elif tracking_email.state in ("sent", "delivered"):
|
elif tracking_email.state in ("sent", "delivered"):
|
||||||
tracking_email.event_create("open", metadata)
|
tracking_email.event_create("open", metadata)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
_logger.warning(e)
|
||||||
|
|
||||||
# Always return GIF blank image
|
# Always return GIF blank image
|
||||||
response = werkzeug.wrappers.Response()
|
response = werkzeug.wrappers.Response()
|
||||||
@ -106,3 +106,12 @@ class MailTrackingController(MailController):
|
|||||||
{"failed_counter": http.request.env["mail.message"].get_failed_count()}
|
{"failed_counter": http.request.env["mail.message"].get_failed_count()}
|
||||||
)
|
)
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
@http.route("/mail/failed/messages", methods=["POST"], type="json", auth="user")
|
||||||
|
def discuss_failed_messages(self, max_id=None, min_id=None, limit=30, **kwargs):
|
||||||
|
return http.request.env["mail.message"]._message_fetch(
|
||||||
|
domain=[("is_failed_message", "=", True)],
|
||||||
|
max_id=max_id,
|
||||||
|
min_id=min_id,
|
||||||
|
limit=limit,
|
||||||
|
)
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data>
|
|
||||||
|
|
||||||
<!-- Message with CC -->
|
<!-- Message with CC -->
|
||||||
<record id="mail_message_cc" model="mail.message">
|
<record id="mail_message_cc" model="mail.message">
|
||||||
<field name="model">res.partner</field>
|
<field name="model">res.partner</field>
|
||||||
@ -9,17 +7,17 @@
|
|||||||
<field name="message_type">comment</field>
|
<field name="message_type">comment</field>
|
||||||
<field name="subtype_id" ref="mail.mt_comment" />
|
<field name="subtype_id" ref="mail.mt_comment" />
|
||||||
<field
|
<field
|
||||||
name="email_cc"
|
name="email_cc"
|
||||||
>acc@testmail.com,wood.corner26@example.com,toni.rhodes11@example.com</field>
|
>acc@testmail.com,wood.corner26@example.com,toni.rhodes11@example.com</field>
|
||||||
<field name="mail_tracking_needs_action">1</field>
|
<field name="mail_tracking_needs_action">1</field>
|
||||||
<field name="body"><![CDATA[<p>This is a message with CC</p>]]></field>
|
<field name="body"><![CDATA[<p>This is a message with CC</p>]]></field>
|
||||||
<field name="email_from">wood.corner26@example.com</field>
|
<field name="email_from">wood.corner26@example.com</field>
|
||||||
<field name="author_id" ref="base.res_partner_1" />
|
<field name="author_id" ref="base.res_partner_1" />
|
||||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]" />
|
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]" />
|
||||||
<field
|
<field
|
||||||
name="notification_ids"
|
name="notification_ids"
|
||||||
eval="[(0, 0, {'res_partner_id': ref('base.partner_demo')})]"
|
eval="[(0, 0, {'res_partner_id': ref('base.partner_demo')})]"
|
||||||
/>
|
/>
|
||||||
<field name="subject">Message with CC</field>
|
<field name="subject">Message with CC</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@ -45,9 +43,9 @@
|
|||||||
<field name="author_id" ref="base.res_partner_1" />
|
<field name="author_id" ref="base.res_partner_1" />
|
||||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]" />
|
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]" />
|
||||||
<field
|
<field
|
||||||
name="notification_ids"
|
name="notification_ids"
|
||||||
eval="[(0, 0, {'res_partner_id': ref('base.partner_demo')})]"
|
eval="[(0, 0, {'res_partner_id': ref('base.partner_demo')})]"
|
||||||
/>
|
/>
|
||||||
<field name="subject">Failed Message</field>
|
<field name="subject">Failed Message</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@ -73,9 +71,9 @@
|
|||||||
<field name="author_id" ref="base.res_partner_10" />
|
<field name="author_id" ref="base.res_partner_10" />
|
||||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]" />
|
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]" />
|
||||||
<field
|
<field
|
||||||
name="notification_ids"
|
name="notification_ids"
|
||||||
eval="[(0, 0, {'res_partner_id': ref('base.partner_demo')})]"
|
eval="[(0, 0, {'res_partner_id': ref('base.partner_demo')})]"
|
||||||
/>
|
/>
|
||||||
<field name="subject">Failed Message</field>
|
<field name="subject">Failed Message</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@ -101,9 +99,9 @@
|
|||||||
<field name="author_id" ref="base.partner_admin" />
|
<field name="author_id" ref="base.partner_admin" />
|
||||||
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]" />
|
<field name="partner_ids" eval="[(6, 0, [ref('base.partner_demo')])]" />
|
||||||
<field
|
<field
|
||||||
name="notification_ids"
|
name="notification_ids"
|
||||||
eval="[(0, 0, {'res_partner_id': ref('base.partner_demo')})]"
|
eval="[(0, 0, {'res_partner_id': ref('base.partner_demo')})]"
|
||||||
/>
|
/>
|
||||||
<field name="subject">Failed Message</field>
|
<field name="subject">Failed Message</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@ -116,6 +114,4 @@
|
|||||||
<field name="state">error</field>
|
<field name="state">error</field>
|
||||||
<field name="time" eval="DateTime.today().strftime('%Y-%m-%d %H:%M')" />
|
<field name="time" eval="DateTime.today().strftime('%Y-%m-%d %H:%M')" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</data>
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
@ -224,9 +224,9 @@ class MailMessage(models.Model):
|
|||||||
|
|
||||||
return list(filter(_filter_alias, mail_list))
|
return list(filter(_filter_alias, mail_list))
|
||||||
|
|
||||||
def message_format(self):
|
def message_format(self, format_reply=True):
|
||||||
"""Preare values to be used by the chatter widget"""
|
"""Preare values to be used by the chatter widget"""
|
||||||
res = super().message_format()
|
res = super().message_format(format_reply)
|
||||||
mail_message_ids = {m.get("id") for m in res if m.get("id")}
|
mail_message_ids = {m.get("id") for m in res if m.get("id")}
|
||||||
mail_messages = self.browse(mail_message_ids)
|
mail_messages = self.browse(mail_message_ids)
|
||||||
tracking_statuses = mail_messages.tracking_status()
|
tracking_statuses = mail_messages.tracking_status()
|
||||||
@ -273,13 +273,8 @@ class MailMessage(models.Model):
|
|||||||
"""
|
"""
|
||||||
self.check_access_rule("read")
|
self.check_access_rule("read")
|
||||||
self.write({"mail_tracking_needs_action": False})
|
self.write({"mail_tracking_needs_action": False})
|
||||||
notification = {
|
self.env["bus.bus"]._sendone(
|
||||||
"type": "toggle_tracking_status",
|
self.env.user.partner_id, "toggle_tracking_status", self.ids
|
||||||
"message_ids": self.ids,
|
|
||||||
"needs_actions": False,
|
|
||||||
}
|
|
||||||
self.env["bus.bus"].sendone(
|
|
||||||
(self._cr.dbname, "res.partner", self.env.user.partner_id.id), notification
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
|
@ -49,13 +49,9 @@ class MailResendMessage(models.TransientModel):
|
|||||||
tracking_ids.sudo().write({"state": False})
|
tracking_ids.sudo().write({"state": False})
|
||||||
# Send bus notifications to update Discuss and
|
# Send bus notifications to update Discuss and
|
||||||
# mail_failed_messages widget
|
# mail_failed_messages widget
|
||||||
notification = {
|
self.env["bus.bus"]._sendone(
|
||||||
"type": "toggle_tracking_status",
|
self.env.user.partner_id.id,
|
||||||
"message_ids": [self.mail_message_id.id],
|
"toggle_tracking_status",
|
||||||
"needs_actions": False,
|
self.mail_message_id.id,
|
||||||
}
|
|
||||||
self.env["bus.bus"].sendone(
|
|
||||||
(self._cr.dbname, "res.partner", self.env.user.partner_id.id),
|
|
||||||
notification,
|
|
||||||
)
|
)
|
||||||
super().resend_mail_action()
|
return super().resend_mail_action()
|
||||||
|
@ -30,7 +30,6 @@ class MailTrackingEmail(models.Model):
|
|||||||
# - state: Search and group_by in tree view
|
# - state: Search and group_by in tree view
|
||||||
name = fields.Char(string="Subject", readonly=True, index=True)
|
name = fields.Char(string="Subject", readonly=True, index=True)
|
||||||
display_name = fields.Char(
|
display_name = fields.Char(
|
||||||
string="Display name",
|
|
||||||
readonly=True,
|
readonly=True,
|
||||||
store=True,
|
store=True,
|
||||||
compute="_compute_tracking_display_name",
|
compute="_compute_tracking_display_name",
|
||||||
@ -38,10 +37,8 @@ class MailTrackingEmail(models.Model):
|
|||||||
timestamp = fields.Float(
|
timestamp = fields.Float(
|
||||||
string="UTC timestamp", readonly=True, digits="MailTracking Timestamp"
|
string="UTC timestamp", readonly=True, digits="MailTracking Timestamp"
|
||||||
)
|
)
|
||||||
time = fields.Datetime(string="Time", readonly=True, index=True)
|
time = fields.Datetime(readonly=True, index=True)
|
||||||
date = fields.Date(
|
date = fields.Date(readonly=True, compute="_compute_date", store=True)
|
||||||
string="Date", readonly=True, compute="_compute_date", store=True
|
|
||||||
)
|
|
||||||
mail_message_id = fields.Many2one(
|
mail_message_id = fields.Many2one(
|
||||||
string="Message", comodel_name="mail.message", readonly=True, index=True
|
string="Message", comodel_name="mail.message", readonly=True, index=True
|
||||||
)
|
)
|
||||||
@ -71,7 +68,6 @@ class MailTrackingEmail(models.Model):
|
|||||||
("bounced", "Bounced"),
|
("bounced", "Bounced"),
|
||||||
("soft-bounced", "Soft bounced"),
|
("soft-bounced", "Soft bounced"),
|
||||||
],
|
],
|
||||||
string="State",
|
|
||||||
index=True,
|
index=True,
|
||||||
readonly=True,
|
readonly=True,
|
||||||
default=False,
|
default=False,
|
||||||
@ -97,10 +93,10 @@ class MailTrackingEmail(models.Model):
|
|||||||
"bounced by recipient Mail Exchange (MX) server.\n",
|
"bounced by recipient Mail Exchange (MX) server.\n",
|
||||||
)
|
)
|
||||||
error_smtp_server = fields.Char(string="Error SMTP server", readonly=True)
|
error_smtp_server = fields.Char(string="Error SMTP server", readonly=True)
|
||||||
error_type = fields.Char(string="Error type", readonly=True)
|
error_type = fields.Char(readonly=True)
|
||||||
error_description = fields.Char(string="Error description", readonly=True)
|
error_description = fields.Char(readonly=True)
|
||||||
bounce_type = fields.Char(string="Bounce type", readonly=True)
|
bounce_type = fields.Char(readonly=True)
|
||||||
bounce_description = fields.Char(string="Bounce description", readonly=True)
|
bounce_description = fields.Char(readonly=True)
|
||||||
tracking_event_ids = fields.One2many(
|
tracking_event_ids = fields.One2many(
|
||||||
string="Tracking events",
|
string="Tracking events",
|
||||||
comodel_name="mail.tracking.event",
|
comodel_name="mail.tracking.event",
|
||||||
@ -126,10 +122,11 @@ class MailTrackingEmail(models.Model):
|
|||||||
return records
|
return records
|
||||||
|
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
super().write(vals)
|
res = super().write(vals)
|
||||||
state = vals.get("state")
|
state = vals.get("state")
|
||||||
if state and state in self.env["mail.message"].get_failed_states():
|
if state and state in self.env["mail.message"].get_failed_states():
|
||||||
self.mapped("mail_message_id").write({"mail_tracking_needs_action": True})
|
self.mapped("mail_message_id").write({"mail_tracking_needs_action": True})
|
||||||
|
return res
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def email_is_bounced(self, email):
|
def email_is_bounced(self, email):
|
||||||
|
@ -14,7 +14,7 @@ class MailTrackingEvent(models.Model):
|
|||||||
_rec_name = "event_type"
|
_rec_name = "event_type"
|
||||||
_description = "MailTracking event"
|
_description = "MailTracking event"
|
||||||
|
|
||||||
recipient = fields.Char(string="Recipient", readonly=True)
|
recipient = fields.Char(readonly=True)
|
||||||
recipient_address = fields.Char(
|
recipient_address = fields.Char(
|
||||||
string="Recipient email address",
|
string="Recipient email address",
|
||||||
readonly=True,
|
readonly=True,
|
||||||
@ -25,10 +25,8 @@ class MailTrackingEvent(models.Model):
|
|||||||
timestamp = fields.Float(
|
timestamp = fields.Float(
|
||||||
string="UTC timestamp", readonly=True, digits="MailTracking Timestamp"
|
string="UTC timestamp", readonly=True, digits="MailTracking Timestamp"
|
||||||
)
|
)
|
||||||
time = fields.Datetime(string="Time", readonly=True)
|
time = fields.Datetime(readonly=True)
|
||||||
date = fields.Date(
|
date = fields.Date(readonly=True, compute="_compute_date", store=True)
|
||||||
string="Date", readonly=True, compute="_compute_date", store=True
|
|
||||||
)
|
|
||||||
tracking_email_id = fields.Many2one(
|
tracking_email_id = fields.Many2one(
|
||||||
string="Message",
|
string="Message",
|
||||||
readonly=True,
|
readonly=True,
|
||||||
@ -38,7 +36,6 @@ class MailTrackingEvent(models.Model):
|
|||||||
index=True,
|
index=True,
|
||||||
)
|
)
|
||||||
event_type = fields.Selection(
|
event_type = fields.Selection(
|
||||||
string="Event type",
|
|
||||||
selection=[
|
selection=[
|
||||||
("sent", "Sent"),
|
("sent", "Sent"),
|
||||||
("delivered", "Delivered"),
|
("delivered", "Delivered"),
|
||||||
@ -56,7 +53,7 @@ class MailTrackingEvent(models.Model):
|
|||||||
smtp_server = fields.Char(string="SMTP server", readonly=True)
|
smtp_server = fields.Char(string="SMTP server", readonly=True)
|
||||||
url = fields.Char(string="Clicked URL", readonly=True)
|
url = fields.Char(string="Clicked URL", readonly=True)
|
||||||
ip = fields.Char(string="User IP", readonly=True)
|
ip = fields.Char(string="User IP", readonly=True)
|
||||||
user_agent = fields.Char(string="User agent", readonly=True)
|
user_agent = fields.Char(readonly=True)
|
||||||
mobile = fields.Boolean(string="Is mobile?", readonly=True)
|
mobile = fields.Boolean(string="Is mobile?", readonly=True)
|
||||||
os_family = fields.Char(string="Operating system family", readonly=True)
|
os_family = fields.Char(string="Operating system family", readonly=True)
|
||||||
ua_family = fields.Char(string="User agent family", readonly=True)
|
ua_family = fields.Char(string="User agent family", readonly=True)
|
||||||
@ -64,9 +61,9 @@ class MailTrackingEvent(models.Model):
|
|||||||
user_country_id = fields.Many2one(
|
user_country_id = fields.Many2one(
|
||||||
string="User country", readonly=True, comodel_name="res.country"
|
string="User country", readonly=True, comodel_name="res.country"
|
||||||
)
|
)
|
||||||
error_type = fields.Char(string="Error type", readonly=True)
|
error_type = fields.Char(readonly=True)
|
||||||
error_description = fields.Char(string="Error description", readonly=True)
|
error_description = fields.Char(readonly=True)
|
||||||
error_details = fields.Text(string="Error details", readonly=True)
|
error_details = fields.Text(readonly=True)
|
||||||
|
|
||||||
@api.depends("recipient")
|
@api.depends("recipient")
|
||||||
def _compute_recipient_address(self):
|
def _compute_recipient_address(self):
|
||||||
|
32
mail_tracking/static/src/js/chatter.esm.js
Normal file
32
mail_tracking/static/src/js/chatter.esm.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
import {attr} from "@mail/model/model_field";
|
||||||
|
import {
|
||||||
|
registerFieldPatchModel,
|
||||||
|
registerInstancePatchModel,
|
||||||
|
} from "@mail/model/model_core";
|
||||||
|
|
||||||
|
registerInstancePatchModel(
|
||||||
|
"mail.chatter",
|
||||||
|
"mail/static/src/models/chatter/chatter.js",
|
||||||
|
{
|
||||||
|
async refresh() {
|
||||||
|
this._super(...arguments);
|
||||||
|
this.thread.refreshMessagefailed();
|
||||||
|
},
|
||||||
|
toggleMessageFailedBoxVisibility() {
|
||||||
|
this.update({
|
||||||
|
isMessageFailedBoxVisible: !this.isMessageFailedBoxVisible,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_onThreadIdOrThreadModelChanged() {
|
||||||
|
this._super(...arguments);
|
||||||
|
this.thread.refreshMessagefailed();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
registerFieldPatchModel("mail.chatter", "mail/static/src/models/chatter/chatter.js", {
|
||||||
|
isMessageFailedBoxVisible: attr({
|
||||||
|
default: true,
|
||||||
|
}),
|
||||||
|
});
|
@ -1,38 +0,0 @@
|
|||||||
odoo.define("mail_tracking/static/src/js/chatter.js", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const {attr} = require("mail/static/src/model/model_field.js");
|
|
||||||
const {
|
|
||||||
registerInstancePatchModel,
|
|
||||||
registerFieldPatchModel,
|
|
||||||
} = require("mail/static/src/model/model_core.js");
|
|
||||||
|
|
||||||
registerInstancePatchModel(
|
|
||||||
"mail.chatter",
|
|
||||||
"mail/static/src/models/chatter/chatter.js",
|
|
||||||
{
|
|
||||||
async refresh() {
|
|
||||||
this._super(...arguments);
|
|
||||||
this.thread.refreshMessagefailed();
|
|
||||||
},
|
|
||||||
toggleMessageFailedBoxVisibility() {
|
|
||||||
this.update({
|
|
||||||
isMessageFailedBoxVisible: !this.isMessageFailedBoxVisible,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
_onThreadIdOrThreadModelChanged() {
|
|
||||||
this._super(...arguments);
|
|
||||||
this.thread.refreshMessagefailed();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
registerFieldPatchModel(
|
|
||||||
"mail.chatter",
|
|
||||||
"mail/static/src/models/chatter/chatter.js",
|
|
||||||
{
|
|
||||||
isMessageFailedBoxVisible: attr({
|
|
||||||
default: true,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
156
mail_tracking/static/src/js/discuss/discuss.esm.js
Normal file
156
mail_tracking/static/src/js/discuss/discuss.esm.js
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
import {attr, many2one, one2one} from "@mail/model/model_field";
|
||||||
|
import {insertAndReplace, replace} from "@mail/model/model_field_command";
|
||||||
|
import {
|
||||||
|
registerClassPatchModel,
|
||||||
|
registerFieldPatchModel,
|
||||||
|
registerInstancePatchModel,
|
||||||
|
} from "@mail/model/model_core";
|
||||||
|
|
||||||
|
registerInstancePatchModel(
|
||||||
|
"mail.messaging_initializer",
|
||||||
|
"mail/static/src/models/messaging_initializer/messaging_initializer.js",
|
||||||
|
{
|
||||||
|
async start() {
|
||||||
|
this.messaging.update({
|
||||||
|
failedmsg: insertAndReplace({
|
||||||
|
id: "failedmsg",
|
||||||
|
isServerPinned: true,
|
||||||
|
model: "mail.box",
|
||||||
|
name: this.env._t("Failed"),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
return this._super(...arguments);
|
||||||
|
},
|
||||||
|
async _init({
|
||||||
|
channels,
|
||||||
|
companyName,
|
||||||
|
current_partner,
|
||||||
|
currentGuest,
|
||||||
|
current_user_id,
|
||||||
|
current_user_settings,
|
||||||
|
mail_failures = [],
|
||||||
|
menu_id,
|
||||||
|
needaction_inbox_counter = 0,
|
||||||
|
partner_root,
|
||||||
|
public_partners,
|
||||||
|
shortcodes = [],
|
||||||
|
starred_counter = 0,
|
||||||
|
failed_counter = 0,
|
||||||
|
}) {
|
||||||
|
const discuss = this.messaging.discuss;
|
||||||
|
// Partners first because the rest of the code relies on them
|
||||||
|
this._initPartners({
|
||||||
|
currentGuest,
|
||||||
|
current_partner,
|
||||||
|
current_user_id,
|
||||||
|
partner_root,
|
||||||
|
public_partners,
|
||||||
|
});
|
||||||
|
// Mailboxes after partners and before other initializers that might
|
||||||
|
// manipulate threads or messages
|
||||||
|
this._initMailboxes({
|
||||||
|
needaction_inbox_counter,
|
||||||
|
starred_counter,
|
||||||
|
failed_counter,
|
||||||
|
});
|
||||||
|
// Init mail user settings
|
||||||
|
if (current_user_settings) {
|
||||||
|
this._initResUsersSettings(current_user_settings);
|
||||||
|
} else {
|
||||||
|
this.messaging.update({
|
||||||
|
userSetting: insertAndReplace({
|
||||||
|
id: -1, // Fake id for guest
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Various suggestions in no particular order
|
||||||
|
this._initCannedResponses(shortcodes);
|
||||||
|
// FIXME: guests should have (at least some) commands available
|
||||||
|
if (!this.messaging.isCurrentUserGuest) {
|
||||||
|
this._initCommands();
|
||||||
|
}
|
||||||
|
// Channels when the rest of messaging is ready
|
||||||
|
await this.async(() => this._initChannels(channels));
|
||||||
|
// Failures after channels
|
||||||
|
this._initMailFailures(mail_failures);
|
||||||
|
discuss.update({menu_id});
|
||||||
|
// Company related data
|
||||||
|
this.messaging.update({companyName});
|
||||||
|
},
|
||||||
|
|
||||||
|
_initMailboxes({needaction_inbox_counter, starred_counter, failed_counter}) {
|
||||||
|
this.messaging.inbox.update({counter: needaction_inbox_counter});
|
||||||
|
this.messaging.starred.update({counter: starred_counter});
|
||||||
|
this.messaging.failedmsg.update({counter: failed_counter});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
registerFieldPatchModel(
|
||||||
|
"mail.messaging",
|
||||||
|
"mail/static/src/models/messaging/messaging.js",
|
||||||
|
{
|
||||||
|
failedmsg: one2one("mail.thread"),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
registerInstancePatchModel(
|
||||||
|
"mail.thread_cache",
|
||||||
|
"mail/static/src/models/thread_cache/thread_cache.js",
|
||||||
|
{
|
||||||
|
_extendMessageDomain(domain) {
|
||||||
|
const thread = this.thread;
|
||||||
|
if (thread === this.env.messaging.failedmsg) {
|
||||||
|
return domain.concat([["is_failed_message", "=", true]]);
|
||||||
|
}
|
||||||
|
return this._super(...arguments);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
registerFieldPatchModel("mail.message", "mail/static/src/models/message/message.js", {
|
||||||
|
messagingFailedmsg: many2one("mail.thread", {
|
||||||
|
related: "messaging.failedmsg",
|
||||||
|
}),
|
||||||
|
isFailed: attr({
|
||||||
|
default: false,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
registerClassPatchModel("mail.message", "mail/static/src/models/message/message.js", {
|
||||||
|
convertData(data) {
|
||||||
|
const data2 = this._super(data);
|
||||||
|
if ("is_failed_message" in data) {
|
||||||
|
data2.isFailed = data.is_failed_message;
|
||||||
|
}
|
||||||
|
return data2;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
registerInstancePatchModel(
|
||||||
|
"mail.message",
|
||||||
|
"mail/static/src/models/message/message.js",
|
||||||
|
{
|
||||||
|
_computeThreads() {
|
||||||
|
const threads = [];
|
||||||
|
if (this.isHistory && this.messaging.history) {
|
||||||
|
threads.push(this.messaging.history);
|
||||||
|
}
|
||||||
|
if (this.isNeedaction && this.messaging.inbox) {
|
||||||
|
threads.push(this.messaging.inbox);
|
||||||
|
}
|
||||||
|
if (this.isStarred && this.messaging.starred) {
|
||||||
|
threads.push(this.messaging.starred);
|
||||||
|
}
|
||||||
|
if (this.isFailed && this.messaging.failedmsg) {
|
||||||
|
threads.push(this.messaging.failedmsg);
|
||||||
|
}
|
||||||
|
if (this.originThread) {
|
||||||
|
threads.push(this.originThread);
|
||||||
|
}
|
||||||
|
return replace(threads);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
@ -1,148 +0,0 @@
|
|||||||
odoo.define("mail_tracking/static/src/js/discuss/discuss.js", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const {attr} = require("mail/static/src/model/model_field.js");
|
|
||||||
const {
|
|
||||||
registerInstancePatchModel,
|
|
||||||
registerFieldPatchModel,
|
|
||||||
registerClassPatchModel,
|
|
||||||
} = require("mail/static/src/model/model_core.js");
|
|
||||||
const {one2one, many2one} = require("mail/static/src/model/model_field.js");
|
|
||||||
|
|
||||||
registerInstancePatchModel(
|
|
||||||
"mail.messaging_initializer",
|
|
||||||
"mail/static/src/models/messaging_initializer/messaging_initializer.js",
|
|
||||||
{
|
|
||||||
async start() {
|
|
||||||
this.messaging.update({
|
|
||||||
failedmsg: [
|
|
||||||
[
|
|
||||||
"create",
|
|
||||||
{
|
|
||||||
id: "failedmsg",
|
|
||||||
isServerPinned: true,
|
|
||||||
model: "mail.box",
|
|
||||||
name: this.env._t("Failed"),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return this._super(...arguments);
|
|
||||||
},
|
|
||||||
async _init({
|
|
||||||
channel_slots,
|
|
||||||
commands = [],
|
|
||||||
current_partner,
|
|
||||||
current_user_id,
|
|
||||||
mail_failures = {},
|
|
||||||
mention_partner_suggestions = [],
|
|
||||||
menu_id,
|
|
||||||
moderation_channel_ids = [],
|
|
||||||
moderation_counter = 0,
|
|
||||||
needaction_inbox_counter = 0,
|
|
||||||
partner_root,
|
|
||||||
public_partner,
|
|
||||||
public_partners,
|
|
||||||
shortcodes = [],
|
|
||||||
starred_counter = 0,
|
|
||||||
failed_counter = 0,
|
|
||||||
}) {
|
|
||||||
const discuss = this.messaging.discuss;
|
|
||||||
// Partners first because the rest of the code relies on them
|
|
||||||
this._initPartners({
|
|
||||||
current_partner,
|
|
||||||
current_user_id,
|
|
||||||
moderation_channel_ids,
|
|
||||||
partner_root,
|
|
||||||
public_partner,
|
|
||||||
public_partners,
|
|
||||||
});
|
|
||||||
// Mailboxes after partners and before other initializers that might
|
|
||||||
// manipulate threads or messages
|
|
||||||
this._initMailboxes({
|
|
||||||
moderation_channel_ids,
|
|
||||||
moderation_counter,
|
|
||||||
needaction_inbox_counter,
|
|
||||||
starred_counter,
|
|
||||||
failed_counter,
|
|
||||||
});
|
|
||||||
// Various suggestions in no particular order
|
|
||||||
this._initCannedResponses(shortcodes);
|
|
||||||
this._initCommands(commands);
|
|
||||||
this._initMentionPartnerSuggestions(mention_partner_suggestions);
|
|
||||||
// Channels when the rest of messaging is ready
|
|
||||||
await this.async(() => this._initChannels(channel_slots));
|
|
||||||
// Failures after channels
|
|
||||||
this._initMailFailures(mail_failures);
|
|
||||||
discuss.update({menu_id});
|
|
||||||
},
|
|
||||||
|
|
||||||
_initMailboxes({
|
|
||||||
moderation_channel_ids,
|
|
||||||
moderation_counter,
|
|
||||||
needaction_inbox_counter,
|
|
||||||
starred_counter,
|
|
||||||
failed_counter,
|
|
||||||
}) {
|
|
||||||
this.env.messaging.inbox.update({counter: needaction_inbox_counter});
|
|
||||||
this.env.messaging.starred.update({counter: starred_counter});
|
|
||||||
this.env.messaging.failedmsg.update({counter: failed_counter});
|
|
||||||
if (moderation_channel_ids.length > 0) {
|
|
||||||
this.messaging.moderation.update({
|
|
||||||
counter: moderation_counter,
|
|
||||||
isServerPinned: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
registerFieldPatchModel(
|
|
||||||
"mail.messaging",
|
|
||||||
"mail/static/src/models/messaging/messaging.js",
|
|
||||||
{
|
|
||||||
failedmsg: one2one("mail.thread"),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
registerInstancePatchModel(
|
|
||||||
"mail.thread_cache",
|
|
||||||
"mail/static/src/models/thread_cache/thread_cache.js",
|
|
||||||
{
|
|
||||||
_extendMessageDomain(domain) {
|
|
||||||
const thread = this.thread;
|
|
||||||
if (thread === this.env.messaging.failedmsg) {
|
|
||||||
return domain.concat([["is_failed_message", "=", true]]);
|
|
||||||
}
|
|
||||||
return this._super(...arguments);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
registerFieldPatchModel(
|
|
||||||
"mail.message",
|
|
||||||
"mail/static/src/models/message/message.js",
|
|
||||||
{
|
|
||||||
messagingFailedmsg: many2one("mail.thread", {
|
|
||||||
related: "messaging.failedmsg",
|
|
||||||
}),
|
|
||||||
isFailed: attr({
|
|
||||||
default: false,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
registerClassPatchModel(
|
|
||||||
"mail.message",
|
|
||||||
"mail/static/src/models/message/message.js",
|
|
||||||
{
|
|
||||||
convertData(data) {
|
|
||||||
const data2 = this._super(data);
|
|
||||||
if ("is_failed_message" in data) {
|
|
||||||
data2.isFailed = data.is_failed_message;
|
|
||||||
}
|
|
||||||
return data2;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
@ -0,0 +1,62 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
// const chatter = require("mail/static/src/models/chatter/chatter.js");
|
||||||
|
// const useStore = require("mail/static/src/component_hooks/use_store/use_store.js");
|
||||||
|
import {registerMessagingComponent} from "@mail/utils/messaging_component";
|
||||||
|
const {Component} = owl;
|
||||||
|
|
||||||
|
export class MessageFailedBox extends Component {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get chatter() {
|
||||||
|
// return this.env.models["mail.chatter"].get(this.props.chatterLocalId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
_onClickTitle() {
|
||||||
|
this.chatter.toggleMessageFailedBoxVisibility();
|
||||||
|
}
|
||||||
|
_markFailedMessageReviewed(id) {
|
||||||
|
return this.env.services.rpc({
|
||||||
|
model: "mail.message",
|
||||||
|
method: "set_need_action_done",
|
||||||
|
args: [[id]],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_onRetryFailedMessage(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var messageID = $(event.currentTarget).data("message-id");
|
||||||
|
const thread = this.chatter.thread;
|
||||||
|
var self = this;
|
||||||
|
this.env.bus.trigger("do-action", {
|
||||||
|
action: "mail.mail_resend_message_action",
|
||||||
|
options: {
|
||||||
|
additional_context: {
|
||||||
|
mail_message_to_resend: messageID,
|
||||||
|
},
|
||||||
|
on_close: () => {
|
||||||
|
self.trigger("reload", {keepChanges: true});
|
||||||
|
thread.refresh();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_onMarkFailedMessageReviewed(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var messageID = $(event.currentTarget).data("message-id");
|
||||||
|
this._markFailedMessageReviewed(messageID);
|
||||||
|
this.trigger("reload", {keepChanges: true});
|
||||||
|
this.chatter.thread.refreshMessagefailed();
|
||||||
|
this.chatter.thread.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(MessageFailedBox, {
|
||||||
|
props: {
|
||||||
|
chatterLocalId: String,
|
||||||
|
},
|
||||||
|
template: "mail_tracking.MessageFailedBox",
|
||||||
|
});
|
||||||
|
|
||||||
|
registerMessagingComponent(MessageFailedBox);
|
@ -1,76 +0,0 @@
|
|||||||
odoo.define(
|
|
||||||
"mail_tracking/static/src/js/failed_message/mail_failed_box.js",
|
|
||||||
function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const chatter = require("mail/static/src/components/chatter/chatter.js");
|
|
||||||
const useStore = require("mail/static/src/component_hooks/use_store/use_store.js");
|
|
||||||
|
|
||||||
const {Component} = owl;
|
|
||||||
|
|
||||||
class MessageFailedBox extends Component {
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
useStore((props) => {
|
|
||||||
const chatter = this.env.models["mail.chatter"].get(
|
|
||||||
props.chatterLocalId
|
|
||||||
);
|
|
||||||
const thread = chatter && chatter.thread;
|
|
||||||
return {
|
|
||||||
chatter: chatter ? chatter.__state : undefined,
|
|
||||||
thread: thread && thread.__state,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get chatter() {
|
|
||||||
return this.env.models["mail.chatter"].get(this.props.chatterLocalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onClickTitle() {
|
|
||||||
this.chatter.toggleMessageFailedBoxVisibility();
|
|
||||||
}
|
|
||||||
_markFailedMessageReviewed(id) {
|
|
||||||
return this.env.services.rpc({
|
|
||||||
model: "mail.message",
|
|
||||||
method: "set_need_action_done",
|
|
||||||
args: [[id]],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_onRetryFailedMessage(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var messageID = $(event.currentTarget).data("message-id");
|
|
||||||
const thread = this.chatter.thread;
|
|
||||||
var self = this;
|
|
||||||
this.env.bus.trigger("do-action", {
|
|
||||||
action: "mail.mail_resend_message_action",
|
|
||||||
options: {
|
|
||||||
additional_context: {
|
|
||||||
mail_message_to_resend: messageID,
|
|
||||||
},
|
|
||||||
on_close: () => {
|
|
||||||
self.trigger("reload", {keepChanges: true});
|
|
||||||
thread.refresh();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_onMarkFailedMessageReviewed(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var messageID = $(event.currentTarget).data("message-id");
|
|
||||||
this._markFailedMessageReviewed(messageID);
|
|
||||||
this.trigger("reload", {keepChanges: true});
|
|
||||||
this.chatter.thread.refreshMessagefailed();
|
|
||||||
this.chatter.thread.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MessageFailedBox.template = "mail_tracking.MessageFailedBox";
|
|
||||||
MessageFailedBox.props = {
|
|
||||||
chatterLocalId: String,
|
|
||||||
};
|
|
||||||
chatter.components = Object.assign({}, chatter.components, {
|
|
||||||
MessageFailedBox,
|
|
||||||
});
|
|
||||||
return MessageFailedBox;
|
|
||||||
}
|
|
||||||
);
|
|
58
mail_tracking/static/src/js/failed_message/thread.esm.js
Normal file
58
mail_tracking/static/src/js/failed_message/thread.esm.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
import {
|
||||||
|
registerFieldPatchModel,
|
||||||
|
registerInstancePatchModel,
|
||||||
|
} from "@mail/model/model_core";
|
||||||
|
import {one2many} from "@mail/model/model_field";
|
||||||
|
|
||||||
|
registerInstancePatchModel(
|
||||||
|
"mail.thread",
|
||||||
|
"mail_tracking/static/src/js/failed_message/thread.js",
|
||||||
|
{
|
||||||
|
async refreshMessagefailed() {
|
||||||
|
var id = this.__values.id;
|
||||||
|
var model = this.__values.model;
|
||||||
|
const messagefailedData = await this.async(() =>
|
||||||
|
this.env.services.rpc(
|
||||||
|
{
|
||||||
|
model: "mail.message",
|
||||||
|
method: "get_failed_messsage_info",
|
||||||
|
args: [id, model],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
shadow: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const messagefailed = this.messaging.models["mail.message.failed"].insert(
|
||||||
|
messagefailedData.map((messageData) =>
|
||||||
|
this.messaging.models["mail.message.failed"].convertData(
|
||||||
|
messageData
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
this.update({
|
||||||
|
messagefailed: [["replace", messagefailed]],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_computeFetchMessagesUrl() {
|
||||||
|
switch (this) {
|
||||||
|
case this.messaging.failedmsg:
|
||||||
|
return "/mail/failed/messages";
|
||||||
|
}
|
||||||
|
return this._super();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
registerFieldPatchModel(
|
||||||
|
"mail.thread",
|
||||||
|
"mail_tracking/static/src/js/failed_message/thread.js",
|
||||||
|
{
|
||||||
|
messagefailed: one2many("mail.message.failed", {
|
||||||
|
inverse: "thread",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
);
|
@ -1,50 +0,0 @@
|
|||||||
odoo.define("mail_tracking/static/src/js/failed_message/thread.js", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const {
|
|
||||||
registerInstancePatchModel,
|
|
||||||
registerFieldPatchModel,
|
|
||||||
} = require("mail/static/src/model/model_core.js");
|
|
||||||
const {one2many} = require("mail/static/src/model/model_field.js");
|
|
||||||
|
|
||||||
registerInstancePatchModel(
|
|
||||||
"mail.thread",
|
|
||||||
"mail_tracking/static/src/js/failed_message/thread.js",
|
|
||||||
{
|
|
||||||
async refreshMessagefailed() {
|
|
||||||
var id = this.__values.id;
|
|
||||||
var model = this.__values.model;
|
|
||||||
const messagefailedData = await this.async(() =>
|
|
||||||
this.env.services.rpc(
|
|
||||||
{
|
|
||||||
model: "mail.message",
|
|
||||||
method: "get_failed_messsage_info",
|
|
||||||
args: [id, model],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
shadow: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const messagefailed = this.env.models["mail.message.failed"].insert(
|
|
||||||
messagefailedData.map((messageData) =>
|
|
||||||
this.env.models["mail.message.failed"].convertData(messageData)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this.update({
|
|
||||||
messagefailed: [["replace", messagefailed]],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
registerFieldPatchModel(
|
|
||||||
"mail.thread",
|
|
||||||
"mail_tracking/static/src/js/failed_message/thread.js",
|
|
||||||
{
|
|
||||||
messagefailed: one2many("mail.message.failed", {
|
|
||||||
inverse: "thread",
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
51
mail_tracking/static/src/js/mail_tracking.esm.js
Normal file
51
mail_tracking/static/src/js/mail_tracking.esm.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
import {
|
||||||
|
registerClassPatchModel,
|
||||||
|
registerFieldPatchModel,
|
||||||
|
registerInstancePatchModel,
|
||||||
|
} from "@mail/model/model_core";
|
||||||
|
import {attr} from "@mail/model/model_field";
|
||||||
|
|
||||||
|
registerClassPatchModel(
|
||||||
|
"mail.message",
|
||||||
|
"mail_tracking/static/src/js/mail_tracking.js",
|
||||||
|
{
|
||||||
|
convertData(data) {
|
||||||
|
const data2 = this._super(data);
|
||||||
|
if ("partner_trackings" in data) {
|
||||||
|
data2.partner_trackings = data.partner_trackings;
|
||||||
|
}
|
||||||
|
return data2;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
registerFieldPatchModel(
|
||||||
|
"mail.message",
|
||||||
|
"mail_tracking/static/src/js/mail_tracking.js",
|
||||||
|
{
|
||||||
|
partner_trackings: attr(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
registerInstancePatchModel(
|
||||||
|
"mail.model",
|
||||||
|
"mail_tracking/static/src/js/mail_tracking.js",
|
||||||
|
{
|
||||||
|
hasPartnerTrackings() {
|
||||||
|
return _.some(this.__values.partner_trackings);
|
||||||
|
},
|
||||||
|
|
||||||
|
hasEmailCc() {
|
||||||
|
return _.some(this._emailCc);
|
||||||
|
},
|
||||||
|
|
||||||
|
getPartnerTrackings: function () {
|
||||||
|
if (!this.hasPartnerTrackings()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return this.__values.partner_trackings;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
@ -1,53 +0,0 @@
|
|||||||
odoo.define("mail_tracking/static/src/js/mail_tracking.js", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const {
|
|
||||||
registerClassPatchModel,
|
|
||||||
registerFieldPatchModel,
|
|
||||||
registerInstancePatchModel,
|
|
||||||
} = require("mail/static/src/model/model_core.js");
|
|
||||||
const {attr} = require("mail/static/src/model/model_field.js");
|
|
||||||
|
|
||||||
registerClassPatchModel(
|
|
||||||
"mail.message",
|
|
||||||
"mail_tracking/static/src/js/mail_tracking.js",
|
|
||||||
{
|
|
||||||
convertData(data) {
|
|
||||||
const data2 = this._super(data);
|
|
||||||
if ("partner_trackings" in data) {
|
|
||||||
data2.partner_trackings = data.partner_trackings;
|
|
||||||
}
|
|
||||||
return data2;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
registerFieldPatchModel(
|
|
||||||
"mail.message",
|
|
||||||
"mail_tracking/static/src/js/mail_tracking.js",
|
|
||||||
{
|
|
||||||
partner_trackings: attr(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
registerInstancePatchModel(
|
|
||||||
"mail.model",
|
|
||||||
"mail_tracking/static/src/js/mail_tracking.js",
|
|
||||||
{
|
|
||||||
hasPartnerTrackings() {
|
|
||||||
return _.some(this.__values.partner_trackings);
|
|
||||||
},
|
|
||||||
|
|
||||||
hasEmailCc() {
|
|
||||||
return _.some(this._emailCc);
|
|
||||||
},
|
|
||||||
|
|
||||||
getPartnerTrackings: function () {
|
|
||||||
if (!this.hasPartnerTrackings()) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return this.__values.partner_trackings;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
55
mail_tracking/static/src/js/message.esm.js
Normal file
55
mail_tracking/static/src/js/message.esm.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
|
||||||
|
import {Message} from "@mail/components/message/message";
|
||||||
|
import {patch} from "web.utils";
|
||||||
|
|
||||||
|
patch(Message.prototype, "mail_tracking/static/src/js/message.js", {
|
||||||
|
constructor() {
|
||||||
|
this._super(...arguments);
|
||||||
|
},
|
||||||
|
_onTrackingStatusClick(event) {
|
||||||
|
var tracking_email_id = $(event.currentTarget).data("tracking");
|
||||||
|
event.preventDefault();
|
||||||
|
return this.env.bus.trigger("do-action", {
|
||||||
|
action: {
|
||||||
|
type: "ir.actions.act_window",
|
||||||
|
view_type: "form",
|
||||||
|
view_mode: "form",
|
||||||
|
res_model: "mail.tracking.email",
|
||||||
|
views: [[false, "form"]],
|
||||||
|
target: "new",
|
||||||
|
res_id: tracking_email_id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// For discuss
|
||||||
|
_onMarkFailedMessageReviewed(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var messageID = $(event.currentTarget).data("message-id");
|
||||||
|
this._markFailedMessageReviewed(messageID);
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
|
_onRetryFailedMessage(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var messageID = $(event.currentTarget).data("message-id");
|
||||||
|
this.env.bus.trigger("do-action", {
|
||||||
|
action: "mail.mail_resend_message_action",
|
||||||
|
options: {
|
||||||
|
additional_context: {
|
||||||
|
mail_message_to_resend: messageID,
|
||||||
|
},
|
||||||
|
on_close: () => {
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_markFailedMessageReviewed(id) {
|
||||||
|
return this.env.services.rpc({
|
||||||
|
model: "mail.message",
|
||||||
|
method: "set_need_action_done",
|
||||||
|
args: [[id]],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
@ -1,58 +0,0 @@
|
|||||||
odoo.define("mail_tracking/static/src/js/message.js", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const Message = require("mail/static/src/components/message/message.js");
|
|
||||||
const MessageList = require("mail/static/src/components/message_list/message_list.js");
|
|
||||||
|
|
||||||
class MessageTracking extends Message {
|
|
||||||
constructor(parent, props) {
|
|
||||||
super(parent, props);
|
|
||||||
}
|
|
||||||
_onTrackingStatusClick(event) {
|
|
||||||
var tracking_email_id = $(event.currentTarget).data("tracking");
|
|
||||||
event.preventDefault();
|
|
||||||
return this.env.bus.trigger("do-action", {
|
|
||||||
action: {
|
|
||||||
type: "ir.actions.act_window",
|
|
||||||
view_type: "form",
|
|
||||||
view_mode: "form",
|
|
||||||
res_model: "mail.tracking.email",
|
|
||||||
views: [[false, "form"]],
|
|
||||||
target: "new",
|
|
||||||
res_id: tracking_email_id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// For discuss
|
|
||||||
_onMarkFailedMessageReviewed(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var messageID = $(event.currentTarget).data("message-id");
|
|
||||||
this._markFailedMessageReviewed(messageID);
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
_onRetryFailedMessage(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var messageID = $(event.currentTarget).data("message-id");
|
|
||||||
this.env.bus.trigger("do-action", {
|
|
||||||
action: "mail.mail_resend_message_action",
|
|
||||||
options: {
|
|
||||||
additional_context: {
|
|
||||||
mail_message_to_resend: messageID,
|
|
||||||
},
|
|
||||||
on_close: () => {
|
|
||||||
window.location.reload();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_markFailedMessageReviewed(id) {
|
|
||||||
return this.env.services.rpc({
|
|
||||||
model: "mail.message",
|
|
||||||
method: "set_need_action_done",
|
|
||||||
args: [[id]],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MessageList.components.Message = MessageTracking;
|
|
||||||
});
|
|
53
mail_tracking/static/src/js/models/thread.esm.js
Normal file
53
mail_tracking/static/src/js/models/thread.esm.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/** @odoo-module **/
|
||||||
|
import {registerNewModel} from "@mail/model/model_core";
|
||||||
|
import {attr, many2one} from "@mail/model/model_field";
|
||||||
|
|
||||||
|
function factory(dependencies) {
|
||||||
|
class MessageFailed extends dependencies["mail.model"] {
|
||||||
|
static convertData(data) {
|
||||||
|
const data2 = {};
|
||||||
|
if ("author" in data) {
|
||||||
|
if (!data.author) {
|
||||||
|
data2.author = [["unlink-all"]];
|
||||||
|
} else {
|
||||||
|
data2.author = data.author[1];
|
||||||
|
data2.author_id = data.author[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("body" in data) {
|
||||||
|
data2.body = data.body;
|
||||||
|
}
|
||||||
|
if ("date" in data) {
|
||||||
|
data2.date = data.date;
|
||||||
|
}
|
||||||
|
if ("failed_recipients" in data) {
|
||||||
|
data2.failed_recipients = data.failed_recipients;
|
||||||
|
}
|
||||||
|
if ("id" in data) {
|
||||||
|
data2.id = data.id;
|
||||||
|
}
|
||||||
|
return data2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageFailed.fields = {
|
||||||
|
thread: many2one("mail.thread", {
|
||||||
|
inverse: "messagefailed",
|
||||||
|
}),
|
||||||
|
body: attr(),
|
||||||
|
author: attr(),
|
||||||
|
author_id: attr(),
|
||||||
|
date: attr(),
|
||||||
|
failed_recipients: attr(),
|
||||||
|
id: attr({
|
||||||
|
readonly: true,
|
||||||
|
required: true,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageFailed.modelName = "mail.message.failed";
|
||||||
|
MessageFailed.identifyingFields = ["id"];
|
||||||
|
return MessageFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
registerNewModel("mail.message.failed", factory);
|
@ -1,53 +0,0 @@
|
|||||||
odoo.define("mail_tracking/static/src/js/models/thread.js", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const {registerNewModel} = require("mail/static/src/model/model_core.js");
|
|
||||||
const {attr, many2one} = require("mail/static/src/model/model_field.js");
|
|
||||||
|
|
||||||
function factory(dependencies) {
|
|
||||||
class MessageFailed extends dependencies["mail.model"] {
|
|
||||||
static convertData(data) {
|
|
||||||
const data2 = {};
|
|
||||||
if ("author" in data) {
|
|
||||||
if (!data.author) {
|
|
||||||
data2.author = [["unlink-all"]];
|
|
||||||
} else {
|
|
||||||
data2.author = data.author[1];
|
|
||||||
data2.author_id = data.author[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ("body" in data) {
|
|
||||||
data2.body = data.body;
|
|
||||||
}
|
|
||||||
if ("date" in data) {
|
|
||||||
data2.date = data.date;
|
|
||||||
}
|
|
||||||
if ("failed_recipients" in data) {
|
|
||||||
data2.failed_recipients = data.failed_recipients;
|
|
||||||
}
|
|
||||||
if ("id" in data) {
|
|
||||||
data2.id = data.id;
|
|
||||||
}
|
|
||||||
return data2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageFailed.fields = {
|
|
||||||
thread: many2one("mail.thread", {
|
|
||||||
inverse: "messagefailed",
|
|
||||||
}),
|
|
||||||
body: attr(),
|
|
||||||
author: attr(),
|
|
||||||
author_id: attr(),
|
|
||||||
date: attr(),
|
|
||||||
failed_recipients: attr(),
|
|
||||||
id: attr(),
|
|
||||||
};
|
|
||||||
|
|
||||||
MessageFailed.modelName = "mail.message.failed";
|
|
||||||
|
|
||||||
return MessageFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerNewModel("mail.message.failed", factory);
|
|
||||||
});
|
|
@ -1,24 +1,42 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<templates>
|
<templates>
|
||||||
<t t-inherit="mail.ThreadIcon" t-inherit-mode="extension">
|
<t t-inherit="mail.ThreadIcon" t-inherit-mode="extension">
|
||||||
<xpath
|
<xpath expr="//t[@t-elif='thread === messaging.history']" position="after">
|
||||||
expr="//t[@t-elif='thread === env.messaging.moderation']"
|
<t t-elif="thread === messaging.failedmsg">
|
||||||
position="after"
|
|
||||||
>
|
|
||||||
<t t-elif="thread === env.messaging.failedmsg">
|
|
||||||
<div class="o_ThreadIcon_mailboxModeration fa fa-exclamation" />
|
<div class="o_ThreadIcon_mailboxModeration fa fa-exclamation" />
|
||||||
</t>
|
</t>
|
||||||
</xpath>
|
</xpath>
|
||||||
</t>
|
</t>
|
||||||
|
|
||||||
|
<t t-inherit="mail.DiscussSidebar" t-inherit-mode="extension">
|
||||||
|
<xpath
|
||||||
|
expr="//div[hasclass('o_DiscussSidebar_categoryMailbox')]"
|
||||||
|
position="inside"
|
||||||
|
>
|
||||||
|
<DiscussSidebarMailbox threadLocalId="messaging.failedmsg.localId" />
|
||||||
|
</xpath>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<t t-inherit="mail.MessageList" t-inherit-mode="extension">
|
||||||
|
<t t-elif="threadView.thread === messaging.history" position="after">
|
||||||
|
<t t-elif="threadView.thread === messaging.failedmsg">
|
||||||
|
<div class="o_MessageList_emptyTitle o-neutral-face-icon">
|
||||||
|
No failed messages
|
||||||
|
</div>
|
||||||
|
Failed messages will be appeared here.
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
|
||||||
<t t-inherit="mail.Message" t-inherit-mode="extension">
|
<t t-inherit="mail.Message" t-inherit-mode="extension">
|
||||||
<xpath expr="//div[hasclass('o_Message_originThread')]" position="inside">
|
<xpath expr="//div[hasclass('o_Message_originThread')]" position="inside">
|
||||||
<t t-if="message.isFailed">
|
<t t-if="messageView.message.isFailed">
|
||||||
<span t-attf-class="o_thread_icons">
|
<span t-attf-class="o_thread_icons">
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
class="btn btn-link btn-success o_thread_icon text-muted btn-sm o_failed_message_reviewed o_activity_link"
|
class="btn btn-link btn-success o_thread_icon text-muted btn-sm o_failed_message_reviewed o_activity_link"
|
||||||
t-on-click="_onMarkFailedMessageReviewed"
|
t-on-click="_onMarkFailedMessageReviewed"
|
||||||
t-att-data-message-id="message.id"
|
t-att-data-message-id="messageView.message.id"
|
||||||
>
|
>
|
||||||
<i class="fa fa-check" />
|
<i class="fa fa-check" />
|
||||||
Set as Reviewed
|
Set as Reviewed
|
||||||
@ -27,7 +45,7 @@
|
|||||||
href="#"
|
href="#"
|
||||||
class="btn btn-link btn-success o_thread_icon text-muted btn-sm o_failed_message_retry o_activity_link"
|
class="btn btn-link btn-success o_thread_icon text-muted btn-sm o_failed_message_retry o_activity_link"
|
||||||
t-on-click="_onRetryFailedMessage"
|
t-on-click="_onRetryFailedMessage"
|
||||||
t-att-data-message-id="message.id"
|
t-att-data-message-id="messageView.message.id"
|
||||||
>
|
>
|
||||||
<i class="fa fa-retweet" />
|
<i class="fa fa-retweet" />
|
||||||
Retry
|
Retry
|
||||||
|
@ -54,12 +54,17 @@
|
|||||||
</span>
|
</span>
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
<t t-inherit="mail.Message" t-inherit-mode="extension">
|
<t t-name="mail.MessageTracking" t-inherit="mail.Message" t-inherit-mode="extension">
|
||||||
<xpath expr="//div[hasclass('o_Message_header')]" position="after">
|
<xpath expr="//div[hasclass('o_Message_header')]" position="after">
|
||||||
<t t-if="message.hasPartnerTrackings() || message.hasEmailCc()">
|
<t
|
||||||
|
t-if="messageView.message.hasPartnerTrackings() || messageView.message.hasEmailCc()"
|
||||||
|
>
|
||||||
<p class="o_mail_tracking">
|
<p class="o_mail_tracking">
|
||||||
<strong>To:</strong>
|
<strong>To:</strong>
|
||||||
<t t-foreach="message.getPartnerTrackings()" t-as="tracking">
|
<t
|
||||||
|
t-foreach="messageView.message.getPartnerTrackings()"
|
||||||
|
t-as="tracking"
|
||||||
|
>
|
||||||
<t t-if="!tracking_first">
|
<t t-if="!tracking_first">
|
||||||
-
|
-
|
||||||
</t>
|
</t>
|
||||||
@ -91,6 +96,7 @@
|
|||||||
class="mail_tracking o_mail_action_tracking_status"
|
class="mail_tracking o_mail_action_tracking_status"
|
||||||
t-att-data-tracking="tracking['tracking_id']"
|
t-att-data-tracking="tracking['tracking_id']"
|
||||||
t-att-title="title_status"
|
t-att-title="title_status"
|
||||||
|
type="button"
|
||||||
t-on-click="_onTrackingStatusClick"
|
t-on-click="_onTrackingStatusClick"
|
||||||
>
|
>
|
||||||
<t t-call="mail.tracking.status" />
|
<t t-call="mail.tracking.status" />
|
||||||
|
@ -88,7 +88,8 @@ class TestMailTracking(TransactionCase):
|
|||||||
"body": "<p>This is a test message</p>",
|
"body": "<p>This is a test message</p>",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
message._moderate_accept()
|
if message.is_thread_message():
|
||||||
|
self.env[message.model].browse(message.res_id)._notify_thread(message)
|
||||||
# Search tracking created
|
# Search tracking created
|
||||||
tracking_email = self.env["mail.tracking.email"].search(
|
tracking_email = self.env["mail.tracking.email"].search(
|
||||||
[
|
[
|
||||||
@ -138,7 +139,10 @@ class TestMailTracking(TransactionCase):
|
|||||||
"body": "<p>This is a test message</p>",
|
"body": "<p>This is a test message</p>",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
message.with_context(do_not_send_copy=True)._moderate_accept()
|
if message.is_thread_message():
|
||||||
|
self.env[message.model].browse(message.res_id).with_context(
|
||||||
|
do_not_send_copy=True
|
||||||
|
)._notify_thread(message)
|
||||||
# Search tracking created
|
# Search tracking created
|
||||||
tracking_email = self.env["mail.tracking.email"].search(
|
tracking_email = self.env["mail.tracking.email"].search(
|
||||||
[
|
[
|
||||||
@ -203,7 +207,8 @@ class TestMailTracking(TransactionCase):
|
|||||||
"body": "<p>This is another test message</p>",
|
"body": "<p>This is another test message</p>",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
message._moderate_accept()
|
if message.is_thread_message():
|
||||||
|
self.env[message.model].browse(message.res_id)._notify_thread(message)
|
||||||
recipients = self.recipient._message_get_suggested_recipients()
|
recipients = self.recipient._message_get_suggested_recipients()
|
||||||
self.assertEqual(len(recipients[self.recipient.id]), 3)
|
self.assertEqual(len(recipients[self.recipient.id]), 3)
|
||||||
self._check_partner_trackings_cc(message)
|
self._check_partner_trackings_cc(message)
|
||||||
@ -257,7 +262,8 @@ class TestMailTracking(TransactionCase):
|
|||||||
"body": "<p>This is another test message</p>",
|
"body": "<p>This is another test message</p>",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
message._moderate_accept()
|
if message.is_thread_message():
|
||||||
|
self.env[message.model].browse(message.res_id)._notify_thread(message)
|
||||||
recipients = self.recipient._message_get_suggested_recipients()
|
recipients = self.recipient._message_get_suggested_recipients()
|
||||||
self.assertEqual(len(recipients[self.recipient.id]), 4)
|
self.assertEqual(len(recipients[self.recipient.id]), 4)
|
||||||
self._check_partner_trackings_to(message)
|
self._check_partner_trackings_to(message)
|
||||||
@ -316,7 +322,8 @@ class TestMailTracking(TransactionCase):
|
|||||||
"body": "<p>This is a test message</p>",
|
"body": "<p>This is a test message</p>",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
message._moderate_accept()
|
if message.is_thread_message():
|
||||||
|
self.env[message.model].browse(message.res_id)._notify_thread(message)
|
||||||
# Search tracking created
|
# Search tracking created
|
||||||
tracking_email = self.env["mail.tracking.email"].search(
|
tracking_email = self.env["mail.tracking.email"].search(
|
||||||
[
|
[
|
||||||
@ -330,7 +337,7 @@ class TestMailTracking(TransactionCase):
|
|||||||
wizard = (
|
wizard = (
|
||||||
self.env["mail.resend.message"]
|
self.env["mail.resend.message"]
|
||||||
.sudo()
|
.sudo()
|
||||||
.with_context({"mail_message_to_resend": message.id})
|
.with_context(mail_message_to_resend=message.id)
|
||||||
.create({})
|
.create({})
|
||||||
)
|
)
|
||||||
# Check failed recipient)s
|
# Check failed recipient)s
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<!-- Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
|
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
|
||||||
<odoo>
|
|
||||||
<template
|
|
||||||
id="assets_backend"
|
|
||||||
name="mail_tracking assets"
|
|
||||||
inherit_id="web.assets_backend"
|
|
||||||
>
|
|
||||||
<xpath expr="." position="inside">
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="/mail_tracking/static/src/css/mail_tracking.scss"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="stylesheet"
|
|
||||||
href="/mail_tracking/static/src/css/failed_message.scss"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/mail_tracking/static/src/js/mail_tracking.js"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/mail_tracking/static/src/js/message.js"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/mail_tracking/static/src/js/failed_message/mail_failed_box.js"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/mail_tracking/static/src/js/failed_message/thread.js"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/mail_tracking/static/src/js/models/thread.js"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/mail_tracking/static/src/js/chatter.js"
|
|
||||||
/>
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="/mail_tracking/static/src/js/discuss/discuss.js"
|
|
||||||
/>
|
|
||||||
</xpath>
|
|
||||||
</template>
|
|
||||||
</odoo>
|
|
@ -3,74 +3,78 @@
|
|||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="view_mail_tracking_email_form">
|
<record model="ir.ui.view" id="view_mail_tracking_email_form">
|
||||||
<field name="name">mail.tracking.email.form</field>
|
<field name="name">mail.tracking.email.form</field>
|
||||||
<field name="model">mail.tracking.email</field>
|
<field name="model">mail.tracking.email</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="MailTracking event" create="false" edit="false" delete="false">
|
<form
|
||||||
<header>
|
string="MailTracking event"
|
||||||
<field name="state" widget="statusbar" />
|
create="false"
|
||||||
</header>
|
edit="false"
|
||||||
<sheet>
|
delete="false"
|
||||||
<group>
|
>
|
||||||
<field name="name" />
|
<header>
|
||||||
</group>
|
<field name="state" widget="statusbar" />
|
||||||
<group>
|
</header>
|
||||||
|
<sheet>
|
||||||
<group>
|
<group>
|
||||||
<field name="mail_message_id" />
|
<field name="name" />
|
||||||
<field name="mail_id" />
|
|
||||||
<field name="partner_id" />
|
|
||||||
<field name="recipient" />
|
|
||||||
<field name="sender" />
|
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="timestamp" />
|
<group>
|
||||||
<field name="time" />
|
<field name="mail_message_id" />
|
||||||
<field name="date" />
|
<field name="mail_id" />
|
||||||
|
<field name="partner_id" />
|
||||||
|
<field name="recipient" />
|
||||||
|
<field name="sender" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="timestamp" />
|
||||||
|
<field name="time" />
|
||||||
|
<field name="date" />
|
||||||
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
<group attrs="{'invisible': [('bounce_type', '=', False)]}">
|
||||||
<group attrs="{'invisible': [('bounce_type', '=', False)]}">
|
<field name="bounce_type" />
|
||||||
<field name="bounce_type" />
|
<field name="bounce_description" />
|
||||||
<field name="bounce_description" />
|
</group>
|
||||||
</group>
|
<group attrs="{'invisible': [('error_type', '=', False)]}">
|
||||||
<group attrs="{'invisible': [('error_type', '=', False)]}">
|
<field
|
||||||
<field
|
|
||||||
name="error_smtp_server"
|
name="error_smtp_server"
|
||||||
attrs="{'invisible': [('error_smtp_server', '=', False)]}"
|
attrs="{'invisible': [('error_smtp_server', '=', False)]}"
|
||||||
/>
|
/>
|
||||||
<field name="error_type" />
|
<field name="error_type" />
|
||||||
<field name="error_description" />
|
<field name="error_description" />
|
||||||
</group>
|
</group>
|
||||||
<label for="tracking_event_ids" />
|
<label for="tracking_event_ids" />
|
||||||
<div>
|
<div>
|
||||||
<field name="tracking_event_ids">
|
<field name="tracking_event_ids">
|
||||||
<tree
|
<tree
|
||||||
string="Tracking events"
|
|
||||||
decoration-muted="event_type == 'deferral'"
|
decoration-muted="event_type == 'deferral'"
|
||||||
decoration-danger="event_type in ('hard_bounce', 'soft_bounce', 'spam', 'reject')"
|
decoration-danger="event_type in ('hard_bounce', 'soft_bounce', 'spam', 'reject')"
|
||||||
decoration-info="event_type in ('unsub', 'click', 'open')"
|
decoration-info="event_type in ('unsub', 'click', 'open')"
|
||||||
>
|
>
|
||||||
<field name="time" />
|
<field name="time" />
|
||||||
<field name="event_type" />
|
<field name="event_type" />
|
||||||
<field name="ip" />
|
<field name="ip" />
|
||||||
<field name="url" />
|
<field name="url" />
|
||||||
<field name="user_country_id" string="Country" />
|
<field name="user_country_id" string="Country" />
|
||||||
<field name="os_family" string="OS" />
|
<field name="os_family" string="OS" />
|
||||||
<field name="ua_family" string="User agent" />
|
<field name="ua_family" string="User agent" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</div>
|
</div>
|
||||||
</sheet>
|
</sheet>
|
||||||
</form>
|
<footer />
|
||||||
</field>
|
</form>
|
||||||
</record>
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="view_mail_tracking_email_tree">
|
<record model="ir.ui.view" id="view_mail_tracking_email_tree">
|
||||||
<field name="name">mail.tracking.email.tree</field>
|
<field name="name">mail.tracking.email.tree</field>
|
||||||
<field name="model">mail.tracking.email</field>
|
<field name="model">mail.tracking.email</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree
|
<tree
|
||||||
string="MailTracking emails"
|
|
||||||
create="false"
|
create="false"
|
||||||
edit="false"
|
edit="false"
|
||||||
delete="false"
|
delete="false"
|
||||||
@ -79,101 +83,105 @@
|
|||||||
decoration-danger="state in ('rejected', 'spam', 'bounced', 'soft-bounced', 'error')"
|
decoration-danger="state in ('rejected', 'spam', 'bounced', 'soft-bounced', 'error')"
|
||||||
decoration-info="state == 'unsub'"
|
decoration-info="state == 'unsub'"
|
||||||
>
|
>
|
||||||
<field name="time" />
|
<field name="time" />
|
||||||
<field name="date" invisible="1" />
|
<field name="date" invisible="1" />
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="sender" string="Sender" />
|
<field name="sender" string="Sender" />
|
||||||
<field name="recipient" string="Recipient" />
|
<field name="recipient" string="Recipient" />
|
||||||
<field name="state" />
|
<field name="state" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="view_mail_tracking_email_search">
|
<record model="ir.ui.view" id="view_mail_tracking_email_search">
|
||||||
<field name="name">mail.tracking.email.search</field>
|
<field name="name">mail.tracking.email.search</field>
|
||||||
<field name="model">mail.tracking.email</field>
|
<field name="model">mail.tracking.email</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search string="MailTracking email search">
|
<search string="MailTracking email search">
|
||||||
<field
|
<field
|
||||||
name="display_name"
|
name="display_name"
|
||||||
string="Email"
|
string="Email"
|
||||||
filter_domain="['|', ('sender', 'ilike', self), ('recipient', 'ilike', self)]"
|
filter_domain="['|', ('sender', 'ilike', self), ('recipient', 'ilike', self)]"
|
||||||
/>
|
/>
|
||||||
<field
|
<field
|
||||||
name="sender"
|
name="sender"
|
||||||
string="Sender"
|
string="Sender"
|
||||||
filter_domain="[('sender', 'ilike', self)]"
|
filter_domain="[('sender', 'ilike', self)]"
|
||||||
/>
|
/>
|
||||||
<field
|
<field
|
||||||
name="recipient_address"
|
name="recipient_address"
|
||||||
string="Recipient Address"
|
string="Recipient Address"
|
||||||
filter_domain="[('recipient_address', '=', self)]"
|
filter_domain="[('recipient_address', '=', self)]"
|
||||||
/>
|
/>
|
||||||
<field name="name" string="Subject" />
|
<field name="name" string="Subject" />
|
||||||
<field name="time" string="Time" />
|
<field name="time" string="Time" />
|
||||||
<field name="date" string="Date" />
|
<field name="date" string="Date" />
|
||||||
<filter name="sent" string="Sent" domain="[('state', 'in', ('sent',))]" />
|
<filter
|
||||||
<filter
|
name="sent"
|
||||||
|
string="Sent"
|
||||||
|
domain="[('state', 'in', ('sent',))]"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
name="deferred"
|
name="deferred"
|
||||||
string="Deferred"
|
string="Deferred"
|
||||||
domain="[('state', '=', 'deferred')]"
|
domain="[('state', '=', 'deferred')]"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
name="delivered"
|
name="delivered"
|
||||||
string="Delivered"
|
string="Delivered"
|
||||||
domain="[('state', 'in', ('delivered', 'opened'))]"
|
domain="[('state', 'in', ('delivered', 'opened'))]"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
name="unsub"
|
name="unsub"
|
||||||
string="Unsubscribed"
|
string="Unsubscribed"
|
||||||
domain="[('state', '=', 'unsub')]"
|
domain="[('state', '=', 'unsub')]"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
name="exception"
|
name="exception"
|
||||||
string="Failed"
|
string="Failed"
|
||||||
domain="[('state', 'in', ('error', 'rejected', 'spam', 'bounced', 'soft-bounced'))]"
|
domain="[('state', 'in', ('error', 'rejected', 'spam', 'bounced', 'soft-bounced'))]"
|
||||||
/>
|
/>
|
||||||
<separator />
|
<separator />
|
||||||
<group expand="0" string="Group By">
|
<group expand="0" string="Group By">
|
||||||
<filter
|
<filter
|
||||||
string="State"
|
string="State"
|
||||||
name="group_by_state"
|
name="group_by_state"
|
||||||
domain="[]"
|
domain="[]"
|
||||||
context="{'group_by': 'state'}"
|
context="{'group_by': 'state'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="Subject"
|
string="Subject"
|
||||||
name="group_by_subject"
|
name="group_by_subject"
|
||||||
domain="[]"
|
domain="[]"
|
||||||
context="{'group_by': 'name'}"
|
context="{'group_by': 'name'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="Sender"
|
string="Sender"
|
||||||
name="group_by_sender"
|
name="group_by_sender"
|
||||||
domain="[]"
|
domain="[]"
|
||||||
context="{'group_by': 'sender'}"
|
context="{'group_by': 'sender'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="Month"
|
string="Month"
|
||||||
name="group_by_month"
|
name="group_by_month"
|
||||||
domain="[]"
|
domain="[]"
|
||||||
context="{'group_by': 'date'}"
|
context="{'group_by': 'date'}"
|
||||||
/>
|
/>
|
||||||
</group>
|
</group>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<record id="action_view_mail_tracking_email" model="ir.actions.act_window">
|
<record id="action_view_mail_tracking_email" model="ir.actions.act_window">
|
||||||
<field name="name">MailTracking emails</field>
|
<field name="name">MailTracking emails</field>
|
||||||
<field name="res_model">mail.tracking.email</field>
|
<field name="res_model">mail.tracking.email</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="search_view_id" ref="view_mail_tracking_email_search" />
|
<field name="search_view_id" ref="view_mail_tracking_email_search" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Add menu entry in Settings/Email -->
|
<!-- Add menu entry in Settings/Email -->
|
||||||
<menuitem
|
<menuitem
|
||||||
name="Tracking emails"
|
name="Tracking emails"
|
||||||
id="menu_mail_tracking_email"
|
id="menu_mail_tracking_email"
|
||||||
parent="base.menu_email"
|
parent="base.menu_email"
|
||||||
|
@ -3,66 +3,70 @@
|
|||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="view_mail_tracking_event_form">
|
<record model="ir.ui.view" id="view_mail_tracking_event_form">
|
||||||
<field name="name">mail.tracking.event.form</field>
|
<field name="name">mail.tracking.event.form</field>
|
||||||
<field name="model">mail.tracking.event</field>
|
<field name="model">mail.tracking.event</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="MailTracking event" create="false" edit="false" delete="false">
|
<form
|
||||||
<sheet>
|
string="MailTracking event"
|
||||||
<group>
|
create="false"
|
||||||
|
edit="false"
|
||||||
|
delete="false"
|
||||||
|
>
|
||||||
|
<sheet>
|
||||||
<group>
|
<group>
|
||||||
<field name="tracking_email_id" />
|
<group>
|
||||||
<field name="recipient" />
|
<field name="tracking_email_id" />
|
||||||
<field name="event_type" />
|
<field name="recipient" />
|
||||||
|
<field name="event_type" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="timestamp" />
|
||||||
|
<field name="time" />
|
||||||
|
<field name="date" />
|
||||||
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group attrs="{'invisible': [('event_type', 'not in', ('sent',))]}">
|
||||||
<field name="timestamp" />
|
<field name="smtp_server" />
|
||||||
<field name="time" />
|
|
||||||
<field name="date" />
|
|
||||||
</group>
|
</group>
|
||||||
</group>
|
<group
|
||||||
<group attrs="{'invisible': [('event_type', 'not in', ('sent',))]}">
|
|
||||||
<field name="smtp_server" />
|
|
||||||
</group>
|
|
||||||
<group
|
|
||||||
attrs="{'invisible': [('event_type', 'not in', ('open', 'click'))]}"
|
attrs="{'invisible': [('event_type', 'not in', ('open', 'click'))]}"
|
||||||
>
|
>
|
||||||
<field name="url" />
|
<field name="url" />
|
||||||
</group>
|
</group>
|
||||||
<group
|
<group
|
||||||
attrs="{'invisible': [('event_type', 'not in', ('open', 'click'))]}"
|
attrs="{'invisible': [('event_type', 'not in', ('open', 'click'))]}"
|
||||||
>
|
>
|
||||||
<group>
|
<group>
|
||||||
<field name="mobile" />
|
<field name="mobile" />
|
||||||
<field name="ip" />
|
<field name="ip" />
|
||||||
<field name="user_country_id" />
|
<field name="user_country_id" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="user_agent" />
|
||||||
|
<field name="ua_family" />
|
||||||
|
<field name="ua_type" />
|
||||||
|
<field name="os_family" />
|
||||||
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group
|
||||||
<field name="user_agent" />
|
|
||||||
<field name="ua_family" />
|
|
||||||
<field name="ua_type" />
|
|
||||||
<field name="os_family" />
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
<group
|
|
||||||
string="Error"
|
string="Error"
|
||||||
attrs="{'invisible': [('error_type', '=', False)]}"
|
attrs="{'invisible': [('error_type', '=', False)]}"
|
||||||
>
|
>
|
||||||
<field name="error_type" />
|
<field name="error_type" />
|
||||||
<field name="error_description" />
|
<field name="error_description" />
|
||||||
<field name="error_details" />
|
<field name="error_details" />
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="view_mail_tracking_event_tree">
|
<record model="ir.ui.view" id="view_mail_tracking_event_tree">
|
||||||
<field name="name">mail.tracking.event.tree</field>
|
<field name="name">mail.tracking.event.tree</field>
|
||||||
<field name="model">mail.tracking.event</field>
|
<field name="model">mail.tracking.event</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree
|
<tree
|
||||||
string="MailTracking events"
|
|
||||||
create="false"
|
create="false"
|
||||||
edit="false"
|
edit="false"
|
||||||
delete="false"
|
delete="false"
|
||||||
@ -70,125 +74,133 @@
|
|||||||
decoration-danger="event_type in ('hard_bounce', 'soft_bounce', 'spam', 'reject')"
|
decoration-danger="event_type in ('hard_bounce', 'soft_bounce', 'spam', 'reject')"
|
||||||
decoration-info="event_type in ('unsub', 'click', 'open')"
|
decoration-info="event_type in ('unsub', 'click', 'open')"
|
||||||
>
|
>
|
||||||
<field name="time" />
|
<field name="time" />
|
||||||
<field name="tracking_email_id" />
|
<field name="tracking_email_id" />
|
||||||
<field name="recipient" />
|
<field name="recipient" />
|
||||||
<field name="event_type" />
|
<field name="event_type" />
|
||||||
<field
|
<field
|
||||||
name="error_details"
|
name="error_details"
|
||||||
invisible="not context.get('event_error_filter', False)"
|
invisible="not context.get('event_error_filter', False)"
|
||||||
/>
|
/>
|
||||||
<field name="date" invisible="1" />
|
<field name="date" invisible="1" />
|
||||||
<field name="ip" />
|
<field name="ip" />
|
||||||
<field name="url" />
|
<field name="url" />
|
||||||
<field name="user_country_id" string="Country" />
|
<field name="user_country_id" string="Country" />
|
||||||
<field name="os_family" string="OS" />
|
<field name="os_family" string="OS" />
|
||||||
<field name="ua_family" string="User agent" />
|
<field name="ua_family" string="User agent" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.ui.view" id="view_mail_tracking_event_search">
|
<record model="ir.ui.view" id="view_mail_tracking_event_search">
|
||||||
<field name="name">mail.tracking.event.search</field>
|
<field name="name">mail.tracking.event.search</field>
|
||||||
<field name="model">mail.tracking.event</field>
|
<field name="model">mail.tracking.event</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search string="MailTracking event search">
|
<search string="MailTracking event search">
|
||||||
<field
|
<field
|
||||||
name="tracking_email_id"
|
name="tracking_email_id"
|
||||||
string="Message"
|
string="Message"
|
||||||
filter_domain="[('tracking_email_id', 'ilike', self)]"
|
filter_domain="[('tracking_email_id', 'ilike', self)]"
|
||||||
/>
|
/>
|
||||||
<field name="recipient" string="Recipient" />
|
<field name="recipient" string="Recipient" />
|
||||||
<field name="time" string="Time" />
|
<field name="time" string="Time" />
|
||||||
<field name="date" string="Date" />
|
<field name="date" string="Date" />
|
||||||
<field name="ip" string="IP" />
|
<field name="ip" string="IP" />
|
||||||
<field name="url" string="URL" />
|
<field name="url" string="URL" />
|
||||||
<filter name="sent" string="Sent" domain="[('event_type', '=', 'sent')]" />
|
<filter
|
||||||
<filter
|
name="sent"
|
||||||
|
string="Sent"
|
||||||
|
domain="[('event_type', '=', 'sent')]"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
name="delivered"
|
name="delivered"
|
||||||
string="Delivered"
|
string="Delivered"
|
||||||
domain="[('event_type', '=', 'delivered')]"
|
domain="[('event_type', '=', 'delivered')]"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
name="click"
|
name="click"
|
||||||
string="Click"
|
string="Click"
|
||||||
domain="[('event_type', '=', 'click')]"
|
domain="[('event_type', '=', 'click')]"
|
||||||
/>
|
/>
|
||||||
<filter name="open" string="Open" domain="[('event_type', '=', 'open')]" />
|
<filter
|
||||||
<filter
|
name="open"
|
||||||
|
string="Open"
|
||||||
|
domain="[('event_type', '=', 'open')]"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
name="unsub"
|
name="unsub"
|
||||||
string="Unsubscribe"
|
string="Unsubscribe"
|
||||||
domain="[('event_type', '=', 'unsub')]"
|
domain="[('event_type', '=', 'unsub')]"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
name="bounce"
|
name="bounce"
|
||||||
string="Bounce"
|
string="Bounce"
|
||||||
domain="[('event_type', 'in', ('hard_bounce', 'soft_bounce'))]"
|
domain="[('event_type', 'in', ('hard_bounce', 'soft_bounce'))]"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
name="exception"
|
name="exception"
|
||||||
string="Failed"
|
string="Failed"
|
||||||
domain="[('event_type', 'in', ('reject', 'spam'))]"
|
domain="[('event_type', 'in', ('reject', 'spam'))]"
|
||||||
context="{'event_error_filter': True}"
|
context="{'event_error_filter': True}"
|
||||||
/>
|
/>
|
||||||
<separator />
|
<separator />
|
||||||
<group expand="0" string="Group By">
|
<group expand="0" string="Group By">
|
||||||
<filter
|
<filter
|
||||||
string="Type"
|
string="Type"
|
||||||
name="group_by_type"
|
name="group_by_type"
|
||||||
domain="[]"
|
domain="[]"
|
||||||
context="{'group_by': 'event_type'}"
|
context="{'group_by': 'event_type'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="Message"
|
string="Message"
|
||||||
name="group_by_message"
|
name="group_by_message"
|
||||||
domain="[]"
|
domain="[]"
|
||||||
context="{'group_by': 'tracking_email_id'}"
|
context="{'group_by': 'tracking_email_id'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="OS"
|
string="OS"
|
||||||
name="group_by_os"
|
name="group_by_os"
|
||||||
domain="[('os_family', '!=', False)]"
|
domain="[('os_family', '!=', False)]"
|
||||||
context="{'group_by': 'os_family'}"
|
context="{'group_by': 'os_family'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="User agent"
|
string="User agent"
|
||||||
name="group_by_user_agent"
|
name="group_by_user_agent"
|
||||||
domain="[('ua_family', '!=', False)]"
|
domain="[('ua_family', '!=', False)]"
|
||||||
context="{'group_by': 'ua_family'}"
|
context="{'group_by': 'ua_family'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="User agent type"
|
string="User agent type"
|
||||||
name="group_by_user_agent_type"
|
name="group_by_user_agent_type"
|
||||||
domain="[('ua_type', '!=', False)]"
|
domain="[('ua_type', '!=', False)]"
|
||||||
context="{'group_by': 'ua_type'}"
|
context="{'group_by': 'ua_type'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="Country"
|
string="Country"
|
||||||
name="group_by_country"
|
name="group_by_country"
|
||||||
domain="[('user_country_id', '!=', False)]"
|
domain="[('user_country_id', '!=', False)]"
|
||||||
context="{'group_by': 'user_country_id'}"
|
context="{'group_by': 'user_country_id'}"
|
||||||
/>
|
/>
|
||||||
<filter
|
<filter
|
||||||
string="Month"
|
string="Month"
|
||||||
name="group_by_date"
|
name="group_by_date"
|
||||||
domain="[]"
|
domain="[]"
|
||||||
context="{'group_by': 'date'}"
|
context="{'group_by': 'date'}"
|
||||||
/>
|
/>
|
||||||
</group>
|
</group>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="action_view_mail_tracking_event" model="ir.actions.act_window">
|
<record id="action_view_mail_tracking_event" model="ir.actions.act_window">
|
||||||
<field name="name">MailTracking events</field>
|
<field name="name">MailTracking events</field>
|
||||||
<field name="res_model">mail.tracking.event</field>
|
<field name="res_model">mail.tracking.event</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="search_view_id" ref="view_mail_tracking_event_search" />
|
<field name="search_view_id" ref="view_mail_tracking_event_search" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Add menu entry in Settings/Email -->
|
<!-- Add menu entry in Settings/Email -->
|
||||||
<menuitem
|
<menuitem
|
||||||
name="Tracking events"
|
name="Tracking events"
|
||||||
id="menu_mail_tracking_event"
|
id="menu_mail_tracking_event"
|
||||||
parent="base.menu_email"
|
parent="base.menu_email"
|
||||||
|
Loading…
Reference in New Issue
Block a user