mirror of https://github.com/OCA/social.git
fixup! [IMP] mail_tracking: Failed Messages to 12.0
parent
9a18de6229
commit
322a3e0437
|
@ -31,8 +31,9 @@
|
||||||
],
|
],
|
||||||
"qweb": [
|
"qweb": [
|
||||||
"static/src/xml/mail_tracking.xml",
|
"static/src/xml/mail_tracking.xml",
|
||||||
"static/src/xml/failed_message.xml",
|
"static/src/xml/failed_message/common.xml",
|
||||||
"static/src/xml/discuss.xml",
|
"static/src/xml/failed_message/widget.xml",
|
||||||
|
"static/src/xml/failed_message/discuss.xml",
|
||||||
],
|
],
|
||||||
'demo': [
|
'demo': [
|
||||||
'demo/demo.xml',
|
'demo/demo.xml',
|
||||||
|
|
|
@ -1,575 +0,0 @@
|
||||||
/* Copyright 2019 Alexandre Díaz
|
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
|
|
||||||
odoo.define('mail_tracking.FailedMessage', function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var AbstractField = require('web.AbstractField');
|
|
||||||
var BasicModel = require('web.BasicModel');
|
|
||||||
var BasicView = require('web.BasicView');
|
|
||||||
var Chatter = require('mail.Chatter');
|
|
||||||
var Discuss = require('mail.Discuss');
|
|
||||||
var MailManager = require('mail.Manager');
|
|
||||||
var Mailbox = require('mail.model.Mailbox');
|
|
||||||
var MailManagerNotif = require('mail.Manager.Notification');
|
|
||||||
var AbstractMessage = require('mail.model.AbstractMessage');
|
|
||||||
var Message = require('mail.model.Message');
|
|
||||||
var utils = require('mail.utils');
|
|
||||||
var core = require('web.core');
|
|
||||||
var field_registry = require('web.field_registry');
|
|
||||||
var time = require('web.time');
|
|
||||||
|
|
||||||
var QWeb = core.qweb;
|
|
||||||
var _t = core._t;
|
|
||||||
|
|
||||||
var FAILED_STATES = [
|
|
||||||
'error', 'rejected', 'spam', 'bounced', 'soft-bounced',
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
/* COMMON */
|
|
||||||
AbstractMessage.include({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract method to be implemented
|
|
||||||
*
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
isFailed: function () {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Message.include({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init
|
|
||||||
*
|
|
||||||
* @param {Widget} parent
|
|
||||||
* @param {Object} data
|
|
||||||
*/
|
|
||||||
init: function (parent, data) {
|
|
||||||
this._isFailedMessage = data.is_failed_message;
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of the abstract method
|
|
||||||
*
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
isFailed: function () {
|
|
||||||
return _.contains(this._threadIDs, 'mailbox_failed');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds/Remove message to/from failed thread
|
|
||||||
*
|
|
||||||
* @param {Boolean} failed
|
|
||||||
*/
|
|
||||||
setFailed: function (failed) {
|
|
||||||
if (failed) {
|
|
||||||
this._addThread('mailbox_failed');
|
|
||||||
} else {
|
|
||||||
this.removeThread('mailbox_failed');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process message mailbox
|
|
||||||
*/
|
|
||||||
_processMailboxes: function () {
|
|
||||||
this.setFailed(this._isFailedMessage);
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
MailManagerNotif.include({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle partner notification
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} data
|
|
||||||
*/
|
|
||||||
_handlePartnerNotification: function (data) {
|
|
||||||
if (data.type === 'toggle_tracking_status') {
|
|
||||||
this._handlePartnerToggleFailedNotification(data);
|
|
||||||
} else {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle partner toggle failed notification
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} data
|
|
||||||
*/
|
|
||||||
_handlePartnerToggleFailedNotification: function (data) {
|
|
||||||
var self = this;
|
|
||||||
var failed = this.getMailbox('failed');
|
|
||||||
_.each(data.message_ids, function (messageID) {
|
|
||||||
var message = _.find(self._messages, function (msg) {
|
|
||||||
return msg.getID() === messageID;
|
|
||||||
});
|
|
||||||
if (message) {
|
|
||||||
message.setFailed(data.needs_actions);
|
|
||||||
if (message.isFailed() === false) {
|
|
||||||
self._removeMessageFromThread(
|
|
||||||
'mailbox_failed', message);
|
|
||||||
} else {
|
|
||||||
self._addMessageToThreads(message, []);
|
|
||||||
var channelFailed = self.getMailbox('failed');
|
|
||||||
channelFailed.invalidateCaches();
|
|
||||||
}
|
|
||||||
self._mailBus.trigger('update_message', message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data.needs_actions) {
|
|
||||||
// Increase failed counter if message is marked as failed
|
|
||||||
failed.incrementMailboxCounter(data.message_ids.length);
|
|
||||||
} else {
|
|
||||||
// Decrease failed counter if message is remove from failed
|
|
||||||
failed.decrementMailboxCounter(data.message_ids.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._mailBus.trigger('update_failed', failed.getMailboxCounter());
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/* DISCUSS */
|
|
||||||
Discuss.include({
|
|
||||||
events: _.extend({}, Discuss.prototype.events, {
|
|
||||||
'click .o_failed_message_retry': '_onRetryFailedMessage',
|
|
||||||
'click .o_failed_message_reviewed': '_onMarkFailedMessageReviewed',
|
|
||||||
}),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sidebar QWeb button params
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {Object}
|
|
||||||
*/
|
|
||||||
_sidebarQWebParams: function () {
|
|
||||||
var failed = this.call('mail_service', 'getMailbox', 'failed');
|
|
||||||
return {
|
|
||||||
activeThreadID: this._thread ? this._thread.getID() : undefined,
|
|
||||||
failedCounter: failed.getMailboxCounter(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render sidebar failed button
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {jQueryElementt}
|
|
||||||
*/
|
|
||||||
_renderSidebar: function () {
|
|
||||||
var $sidebar = this._super.apply(this, arguments);
|
|
||||||
// Because Odoo implementation isn't designed to be inherited
|
|
||||||
// properly we inject failed button using jQuery.
|
|
||||||
var $failed_item = $(QWeb.render('mail_tracking.SidebarFailed',
|
|
||||||
this._sidebarQWebParams()));
|
|
||||||
$failed_item.insertAfter(
|
|
||||||
$sidebar.find(".o_mail_discuss_title_main").filter(":last"));
|
|
||||||
return $sidebar;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message Updated
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} message
|
|
||||||
* @param {String} type
|
|
||||||
*/
|
|
||||||
_onMessageUpdated: function (message, type) {
|
|
||||||
var self = this;
|
|
||||||
var currentThreadID = this._thread.getID();
|
|
||||||
if (currentThreadID === 'mailbox_failed' && !message.isFailed()) {
|
|
||||||
this._thread.fetchMessages(this.domain)
|
|
||||||
.then(function () {
|
|
||||||
var options = self._getThreadRenderingOptions();
|
|
||||||
self._threadWidget.removeMessageAndRender(
|
|
||||||
message.getID(), self._thread, options)
|
|
||||||
.then(function () {
|
|
||||||
self._updateButtonStatus(
|
|
||||||
!self._thread.hasMessages(), type);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Workaround to avoid calling '_fetchAndRenderThread' when
|
|
||||||
// it's not really needed.
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get thread rendering options
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {Object}
|
|
||||||
*/
|
|
||||||
_getThreadRenderingOptions: function () {
|
|
||||||
var values = this._super.apply(this, arguments);
|
|
||||||
if (this._thread.getID() === 'mailbox_failed') {
|
|
||||||
values.displayEmailIcons = true;
|
|
||||||
values.displayReplyIcons = false;
|
|
||||||
values.displayRetryButton = true;
|
|
||||||
values.displayReviewedButton = true;
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start listening events
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_startListening: function () {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
this.call('mail_service', 'getMailBus')
|
|
||||||
.on('update_failed', this, this._throttledUpdateThreads);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Handlers
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param {Event} event
|
|
||||||
*/
|
|
||||||
_onRetryFailedMessage: function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var messageID = $(event.currentTarget).data('message-id');
|
|
||||||
this.do_action('mail.mail_resend_message_action', {
|
|
||||||
additional_context: {
|
|
||||||
mail_message_to_resend: messageID,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param {Event} event
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
_onMarkFailedMessageReviewed: function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var messageID = $(event.currentTarget).data('message-id');
|
|
||||||
return this._rpc({
|
|
||||||
model: 'mail.message',
|
|
||||||
method: 'toggle_tracking_status',
|
|
||||||
args: [[messageID]],
|
|
||||||
context: this.getSession().user_context,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
MailManager.include({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create mailbox entry
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} data
|
|
||||||
*/
|
|
||||||
_updateMailboxesFromServer: function (data) {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
this._addMailbox({
|
|
||||||
id: 'failed',
|
|
||||||
name: _t("Failed"),
|
|
||||||
mailboxCounter: data.failed_counter || 0,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Mailbox.include({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get thread domain
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {Array}
|
|
||||||
*/
|
|
||||||
_getThreadDomain: function () {
|
|
||||||
if (this._id === 'mailbox_failed') {
|
|
||||||
// Workaround to avoid throw an exception
|
|
||||||
return [
|
|
||||||
['mail_tracking_ids.state', 'in', FAILED_STATES],
|
|
||||||
['mail_tracking_needs_action', '=', true],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return this._super.apply(this, arguments);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/* FAILED MESSAGES CHATTER WIDGET */
|
|
||||||
/**
|
|
||||||
* Get messages with selected ids
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} self
|
|
||||||
* @param {Array} ids
|
|
||||||
* @returns {Array}
|
|
||||||
*/
|
|
||||||
function _readMessages (self, ids) {
|
|
||||||
if (!ids.length) {
|
|
||||||
return $.when([]);
|
|
||||||
}
|
|
||||||
var context = self.record && self.record.getContext();
|
|
||||||
return self._rpc({
|
|
||||||
model: 'mail.message',
|
|
||||||
method: 'get_failed_messages',
|
|
||||||
args: [ids],
|
|
||||||
context: context || self.getSession().user_context,
|
|
||||||
}).then(function (messages) {
|
|
||||||
// Convert date to moment
|
|
||||||
_.each(messages, function (msg) {
|
|
||||||
msg.date = moment(time.auto_str_to_date(msg.date));
|
|
||||||
msg.hour = utils.timeFromNow(msg.date);
|
|
||||||
});
|
|
||||||
return messages;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicModel.include({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch special failed messages
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} record
|
|
||||||
* @param {String} fieldName
|
|
||||||
* @returns {Array}
|
|
||||||
*/
|
|
||||||
_fetchSpecialFailedMessages: function (record, fieldName) {
|
|
||||||
var localID = record._changes && fieldName in record._changes
|
|
||||||
? record._changes[fieldName] : record.data[fieldName];
|
|
||||||
return _readMessages(this, this.localData[localID].res_ids);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
var AbstractFailedMessagesField = AbstractField.extend({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract method to be implemented
|
|
||||||
*
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
_markFailedMessageReviewed: function () {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
var FailedMessage = AbstractFailedMessagesField.extend({
|
|
||||||
className: 'o_mail_failed_message',
|
|
||||||
events: {
|
|
||||||
'click .o_failed_message_retry': '_onRetryFailedMessage',
|
|
||||||
'click .o_failed_message_reviewed': '_onMarkFailedMessageReviewed',
|
|
||||||
},
|
|
||||||
specialData: '_fetchSpecialFailedMessages',
|
|
||||||
|
|
||||||
init: function () {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
this.failed_messages = this.record.specialData[this.name];
|
|
||||||
this.call(
|
|
||||||
'bus_service', 'onNotification', this, this._onNotification);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get message qweb parameters
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {Object}
|
|
||||||
*/
|
|
||||||
_failedItemsQWebParams: function () {
|
|
||||||
return {
|
|
||||||
failed_messages: this.failed_messages,
|
|
||||||
nbFailedMessages: this.failed_messages.length,
|
|
||||||
date_format: time.getLangDateFormat(),
|
|
||||||
datetime_format: time.getLangDatetimeFormat(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render failed message
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_render: function () {
|
|
||||||
if (this.failed_messages.length) {
|
|
||||||
this.$el.html(QWeb.render(
|
|
||||||
'mail_tracking.failed_message_items',
|
|
||||||
this._failedItemsQWebParams()));
|
|
||||||
} else {
|
|
||||||
this.$el.empty();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Object} record
|
|
||||||
*/
|
|
||||||
_reset: function (record) {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
this.failed_messages = this.record.specialData[this.name];
|
|
||||||
this.res_id = record.res_id;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reload
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Array} fieldsToReload
|
|
||||||
*/
|
|
||||||
_reload: function (fieldsToReload) {
|
|
||||||
this.trigger_up('reload_mail_fields', fieldsToReload);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark failed message as reviewed
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Int} id
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
_markFailedMessageReviewed: function (id) {
|
|
||||||
return this._rpc({
|
|
||||||
model: 'mail.message',
|
|
||||||
method: 'toggle_tracking_status',
|
|
||||||
args: [[id]],
|
|
||||||
context: this.record.getContext(),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// Handlers
|
|
||||||
/**
|
|
||||||
* Listen notification to launch reload process
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Array} notifs
|
|
||||||
*/
|
|
||||||
_onNotification: function (notifs) {
|
|
||||||
var self = this;
|
|
||||||
_.each(notifs, function (notif) {
|
|
||||||
var model = notif[0][1];
|
|
||||||
if (model === 'res.partner') {
|
|
||||||
var data = notif[1];
|
|
||||||
if (data.type === 'update_failed_messages') {
|
|
||||||
// Update failed messages
|
|
||||||
self._reload({failed_message: true});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle retry failed message event
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Event} event
|
|
||||||
*/
|
|
||||||
_onRetryFailedMessage: function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var messageID = $(event.currentTarget).data('message-id');
|
|
||||||
this.do_action('mail.mail_resend_message_action', {
|
|
||||||
additional_context: {
|
|
||||||
mail_message_to_resend: messageID,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle mark message as reviewed event
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Event} event
|
|
||||||
*/
|
|
||||||
_onMarkFailedMessageReviewed: function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var messageID = $(event.currentTarget).data('message-id');
|
|
||||||
this._markFailedMessageReviewed(messageID).then(
|
|
||||||
this._reload.bind(this, {failed_message: true}));
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
field_registry.add('mail_failed_message', FailedMessage);
|
|
||||||
|
|
||||||
var mailWidgets = ['mail_failed_message'];
|
|
||||||
BasicView.include({
|
|
||||||
init: function () {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
// Adds mail_failed_message as valid mail widget
|
|
||||||
var fieldsInfo = this.fieldsInfo[this.viewType];
|
|
||||||
for (var fieldName in fieldsInfo) {
|
|
||||||
var fieldInfo = fieldsInfo[fieldName];
|
|
||||||
if (_.contains(mailWidgets, fieldInfo.widget)) {
|
|
||||||
this.mailFields[fieldInfo.widget] = fieldName;
|
|
||||||
fieldInfo.__no_fetch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Object.assign(this.rendererParams.mailFields, this.mailFields);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Chatter.include({
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Widget} parent
|
|
||||||
* @param {Object} record
|
|
||||||
* @param {Object} mailFields
|
|
||||||
* @param {Object} options
|
|
||||||
*/
|
|
||||||
init: function (parent, record, mailFields, options) {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
// Initialize mail_failed_message widget
|
|
||||||
if (mailFields.mail_failed_message) {
|
|
||||||
this.fields.failed_message = new FailedMessage(
|
|
||||||
this, mailFields.mail_failed_message, record, options);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
_render: function () {
|
|
||||||
var self = this;
|
|
||||||
return this._super.apply(this, arguments).then(function () {
|
|
||||||
if (self.fields.failed_message) {
|
|
||||||
self.fields.failed_message.$el.insertBefore(
|
|
||||||
self.$el.find('.o_mail_thread'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle reload fields event
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Event} event
|
|
||||||
*/
|
|
||||||
_onReloadMailFields: function (event) {
|
|
||||||
if (this.fields.failed_message && event.data.failed_message) {
|
|
||||||
this.trigger_up('reload', {
|
|
||||||
fieldNames: [this.fields.failed_message.name],
|
|
||||||
keepChanges: true,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Workarround to avoid trigger reload event two times.
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return FailedMessage;
|
|
||||||
|
|
||||||
});
|
|
|
@ -0,0 +1,312 @@
|
||||||
|
/* Copyright 2019 Alexandre Díaz
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
|
||||||
|
odoo.define('mail_tracking.FailedMessageDiscuss', function (require) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// To be considered:
|
||||||
|
// - One message can be displayed in many threads
|
||||||
|
// - A thread can be a mailbox, channel, ...
|
||||||
|
// - A mailbox it's a type of thread that it's displayed on top of
|
||||||
|
// the discuss menu, has a counter, etc...
|
||||||
|
|
||||||
|
var MailManagerNotif = require('mail.Manager.Notification');
|
||||||
|
var AbstractMessage = require('mail.model.AbstractMessage');
|
||||||
|
var Message = require('mail.model.Message');
|
||||||
|
var Discuss = require('mail.Discuss');
|
||||||
|
var MailManager = require('mail.Manager');
|
||||||
|
var Mailbox = require('mail.model.Mailbox');
|
||||||
|
var core = require('web.core');
|
||||||
|
|
||||||
|
var QWeb = core.qweb;
|
||||||
|
var _t = core._t;
|
||||||
|
|
||||||
|
/* The states to consider a message as failed message */
|
||||||
|
var FAILED_STATES = [
|
||||||
|
'error', 'rejected', 'spam', 'bounced', 'soft-bounced',
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
AbstractMessage.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract declaration to know if a message its included on the
|
||||||
|
* failed mailbox. By default should be false.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
isFailed: function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Message.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to store information from server
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
init: function (parent, data) {
|
||||||
|
this._isFailedMessage = data.is_failed_message;
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation to know if a message its included on the
|
||||||
|
* failed mailbox.
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
isFailed: function () {
|
||||||
|
return _.contains(this._threadIDs, 'mailbox_failed');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds/Remove message to/from failed mailbox
|
||||||
|
*
|
||||||
|
* @param {Boolean} failed
|
||||||
|
*/
|
||||||
|
setFailed: function (failed) {
|
||||||
|
if (failed) {
|
||||||
|
this._addThread('mailbox_failed');
|
||||||
|
} else {
|
||||||
|
this.removeThread('mailbox_failed');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to update if the message need be show in 'failed' mailbox
|
||||||
|
* thread
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
_processMailboxes: function () {
|
||||||
|
this.setFailed(this._isFailedMessage);
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
MailManagerNotif.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to handle changes in the 'mail_tracking_needs_action' flag
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
_handlePartnerNotification: function (data) {
|
||||||
|
if (data.type === 'toggle_tracking_status') {
|
||||||
|
this._handlePartnerToggleFailedNotification(data);
|
||||||
|
} else {
|
||||||
|
// Workaround to avoid call '_handlePartnerChannelNotification'
|
||||||
|
// because this is related with the failed mailbox, not a
|
||||||
|
// channel.
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method update messages in the failed mailbox when the flag
|
||||||
|
* 'mail_tracking_needs_action' is toggled. This can remove/add
|
||||||
|
* the message from/to failed mailbox and update mailbox counter.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} data
|
||||||
|
*/
|
||||||
|
_handlePartnerToggleFailedNotification: function (data) {
|
||||||
|
var self = this;
|
||||||
|
var failed = this.getMailbox('failed');
|
||||||
|
_.each(data.message_ids, function (messageID) {
|
||||||
|
var message = _.find(self._messages, function (msg) {
|
||||||
|
return msg.getID() === messageID;
|
||||||
|
});
|
||||||
|
if (message) {
|
||||||
|
message.setFailed(data.needs_actions);
|
||||||
|
if (message.isFailed() === false) {
|
||||||
|
self._removeMessageFromThread(
|
||||||
|
'mailbox_failed', message);
|
||||||
|
} else {
|
||||||
|
self._addMessageToThreads(message, []);
|
||||||
|
var channelFailed = self.getMailbox('failed');
|
||||||
|
channelFailed.invalidateCaches();
|
||||||
|
}
|
||||||
|
self._mailBus.trigger('update_message', message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.needs_actions) {
|
||||||
|
// Increase failed counter if message is marked as failed
|
||||||
|
failed.incrementMailboxCounter(data.message_ids.length);
|
||||||
|
} else {
|
||||||
|
// Decrease failed counter if message is remove from failed
|
||||||
|
failed.decrementMailboxCounter(data.message_ids.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger event to refresh threads
|
||||||
|
this._mailBus.trigger('update_failed', failed.getMailboxCounter());
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Discuss.include({
|
||||||
|
events: _.extend({}, Discuss.prototype.events, {
|
||||||
|
'click .o_failed_message_retry': '_onRetryFailedMessage',
|
||||||
|
'click .o_failed_message_reviewed': '_onMarkFailedMessageReviewed',
|
||||||
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paramaters used to render 'failed' mailbox entry in Discuss
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
_sidebarQWebParams: function () {
|
||||||
|
var failed = this.call('mail_service', 'getMailbox', 'failed');
|
||||||
|
return {
|
||||||
|
activeThreadID: this._thread ? this._thread.getID() : undefined,
|
||||||
|
failedCounter: failed.getMailboxCounter(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render 'failed' mailbox menu entry in Discuss
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {jQueryElementt}
|
||||||
|
*/
|
||||||
|
_renderSidebar: function () {
|
||||||
|
var $sidebar = this._super.apply(this, arguments);
|
||||||
|
// Because Odoo implementation isn't designed to be inherited
|
||||||
|
// properly, we inject 'failed' button using jQuery.
|
||||||
|
var $failed_item = $(QWeb.render('mail_tracking.SidebarFailed',
|
||||||
|
this._sidebarQWebParams()));
|
||||||
|
$failed_item.insertAfter(
|
||||||
|
$sidebar.find(".o_mail_discuss_title_main").filter(":last"));
|
||||||
|
return $sidebar;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to update messages in 'failed' mailbox thread
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
_onMessageUpdated: function (message, type) {
|
||||||
|
var self = this;
|
||||||
|
var currentThreadID = this._thread.getID();
|
||||||
|
if (currentThreadID === 'mailbox_failed' && !message.isFailed()) {
|
||||||
|
this._thread.fetchMessages(this.domain)
|
||||||
|
.then(function () {
|
||||||
|
var options = self._getThreadRenderingOptions();
|
||||||
|
self._threadWidget.removeMessageAndRender(
|
||||||
|
message.getID(), self._thread, options)
|
||||||
|
.then(function () {
|
||||||
|
self._updateButtonStatus(
|
||||||
|
!self._thread.hasMessages(), type);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Workaround to avoid call '_fetchAndRenderThread' and refetch
|
||||||
|
// thread messages.
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to hide reply in the 'failed' mailbox, as this feature does
|
||||||
|
* not necessary in that channel. It also show retry and
|
||||||
|
* 'set as reviewed'.
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
_getThreadRenderingOptions: function () {
|
||||||
|
var values = this._super.apply(this, arguments);
|
||||||
|
if (this._thread.getID() === 'mailbox_failed') {
|
||||||
|
values.displayEmailIcons = true;
|
||||||
|
values.displayReplyIcons = false;
|
||||||
|
values.displayRetryButton = true;
|
||||||
|
values.displayReviewedButton = true;
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to listen event that refresh thread messages
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
_startListening: function () {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
this.call('mail_service', 'getMailBus')
|
||||||
|
.on('update_failed', this, this._throttledUpdateThreads);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
/**
|
||||||
|
* Open the resend mail.resend.message wizard
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Event} event
|
||||||
|
*/
|
||||||
|
_onRetryFailedMessage: function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var messageID = $(event.currentTarget).data('message-id');
|
||||||
|
this.do_action('mail.mail_resend_message_action', {
|
||||||
|
additional_context: {
|
||||||
|
mail_message_to_resend: messageID,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle 'mail_tracking_needs_action' flag
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Event} event
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
_onMarkFailedMessageReviewed: function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var messageID = $(event.currentTarget).data('message-id');
|
||||||
|
return this._rpc({
|
||||||
|
model: 'mail.message',
|
||||||
|
method: 'toggle_tracking_status',
|
||||||
|
args: [[messageID]],
|
||||||
|
context: this.getSession().user_context,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
MailManager.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to add the 'failed' mailbox
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
_updateMailboxesFromServer: function (data) {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
this._addMailbox({
|
||||||
|
id: 'failed',
|
||||||
|
name: _t("Failed"),
|
||||||
|
mailboxCounter: data.failed_counter || 0,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Mailbox.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to add domain for 'failed' mailbox thread
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
_getThreadDomain: function () {
|
||||||
|
if (this._id === 'mailbox_failed') {
|
||||||
|
return [
|
||||||
|
['mail_tracking_ids.state', 'in', FAILED_STATES],
|
||||||
|
['mail_tracking_needs_action', '=', true],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// Workaround to avoid throw 'Missing domain' exception
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,311 @@
|
||||||
|
/* Copyright 2019 Alexandre Díaz
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
|
||||||
|
odoo.define('mail_tracking.FailedMessage', function (require) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var AbstractField = require('web.AbstractField');
|
||||||
|
var BasicModel = require('web.BasicModel');
|
||||||
|
var BasicView = require('web.BasicView');
|
||||||
|
var Chatter = require('mail.Chatter');
|
||||||
|
var MailThread = require('mail.widget.Thread');
|
||||||
|
var utils = require('mail.utils');
|
||||||
|
var core = require('web.core');
|
||||||
|
var field_registry = require('web.field_registry');
|
||||||
|
var time = require('web.time');
|
||||||
|
|
||||||
|
var QWeb = core.qweb;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to fetch failed messages
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} self
|
||||||
|
* @param {Array} ids
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
|
function _readMessages (self, ids) {
|
||||||
|
if (!ids.length) {
|
||||||
|
return $.when([]);
|
||||||
|
}
|
||||||
|
var context = self.record && self.record.getContext();
|
||||||
|
return self._rpc({
|
||||||
|
model: 'mail.message',
|
||||||
|
method: 'get_failed_messages',
|
||||||
|
args: [ids],
|
||||||
|
context: context || self.getSession().user_context,
|
||||||
|
}).then(function (messages) {
|
||||||
|
// Convert date to moment
|
||||||
|
_.each(messages, function (msg) {
|
||||||
|
msg.date = moment(time.auto_str_to_date(msg.date));
|
||||||
|
msg.hour = utils.timeFromNow(msg.date);
|
||||||
|
});
|
||||||
|
return messages;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicModel.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the failed messages displayed by the 'mail_failed_message'
|
||||||
|
* field widget in form views.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} record
|
||||||
|
* @param {String} fieldName
|
||||||
|
* @returns {Array}
|
||||||
|
*/
|
||||||
|
_fetchSpecialFailedMessages: function (record, fieldName) {
|
||||||
|
var localID = record._changes && fieldName in record._changes
|
||||||
|
? record._changes[fieldName] : record.data[fieldName];
|
||||||
|
return _readMessages(this, this.localData[localID].res_ids);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var AbstractFailedMessagesField = AbstractField.extend({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark failed message as reviewed. By default should be don't reviewed.
|
||||||
|
*
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
_markFailedMessageReviewed: function () {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
var FailedMessage = AbstractFailedMessagesField.extend({
|
||||||
|
className: 'o_mail_failed_message',
|
||||||
|
events: {
|
||||||
|
'click .o_failed_message_retry': '_onRetryFailedMessage',
|
||||||
|
'click .o_failed_message_reviewed': '_onMarkFailedMessageReviewed',
|
||||||
|
},
|
||||||
|
specialData: '_fetchSpecialFailedMessages',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to listen bus notifications
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
init: function () {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
this.failed_messages = this.record.specialData[this.name];
|
||||||
|
this.call(
|
||||||
|
'bus_service', 'onNotification', this, this._onNotification);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paremeters used to render widget
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
_failedItemsQWebParams: function () {
|
||||||
|
return {
|
||||||
|
failed_messages: this.failed_messages,
|
||||||
|
nbFailedMessages: this.failed_messages.length,
|
||||||
|
date_format: time.getLangDateFormat(),
|
||||||
|
datetime_format: time.getLangDatetimeFormat(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_render: function () {
|
||||||
|
if (this.failed_messages.length) {
|
||||||
|
this.$el.html(QWeb.render(
|
||||||
|
'mail_tracking.failed_message_items',
|
||||||
|
this._failedItemsQWebParams()));
|
||||||
|
} else {
|
||||||
|
this.$el.empty();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset widget data using selected record
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} record
|
||||||
|
*/
|
||||||
|
_reset: function (record) {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
this.failed_messages = this.record.specialData[this.name];
|
||||||
|
this.res_id = record.res_id;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger event to reload mail widgets
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} fieldsToReload
|
||||||
|
*/
|
||||||
|
_reload: function (fieldsToReload) {
|
||||||
|
this.trigger_up('reload_mail_fields', fieldsToReload);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark failed message as reviewed
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Int} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
_markFailedMessageReviewed: function (id) {
|
||||||
|
return this._rpc({
|
||||||
|
model: 'mail.message',
|
||||||
|
method: 'toggle_tracking_status',
|
||||||
|
args: [[id]],
|
||||||
|
context: this.record.getContext(),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
/**
|
||||||
|
* Listen bus notification to launch reload process.
|
||||||
|
* This bus notification is received when the user uses
|
||||||
|
* 'mail.resend.message' wizard.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} notifs
|
||||||
|
*/
|
||||||
|
_onNotification: function (notifs) {
|
||||||
|
var self = this;
|
||||||
|
_.each(notifs, function (notif) {
|
||||||
|
var model = notif[0][1];
|
||||||
|
if (model === 'res.partner') {
|
||||||
|
var data = notif[1];
|
||||||
|
if (data.type === 'update_failed_messages') {
|
||||||
|
// Reload 'mail_failed_message' widget
|
||||||
|
self._reload({failed_message: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle retry failed message event to open the mail.resend.message
|
||||||
|
* wizard.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Event} event
|
||||||
|
*/
|
||||||
|
_onRetryFailedMessage: function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var messageID = $(event.currentTarget).data('message-id');
|
||||||
|
this.do_action('mail.mail_resend_message_action', {
|
||||||
|
additional_context: {
|
||||||
|
mail_message_to_resend: messageID,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle mark message as reviewed event
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Event} event
|
||||||
|
*/
|
||||||
|
_onMarkFailedMessageReviewed: function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var messageID = $(event.currentTarget).data('message-id');
|
||||||
|
this._markFailedMessageReviewed(messageID).then(
|
||||||
|
this._reload.bind(this, {failed_message: true}));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
field_registry.add('mail_failed_message', FailedMessage);
|
||||||
|
|
||||||
|
var mailWidgets = ['mail_failed_message'];
|
||||||
|
BasicView.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to add 'mail_failed_message' widget as "mail widget" used
|
||||||
|
* in Chatter.
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
init: function () {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
var fieldsInfo = this.fieldsInfo[this.viewType];
|
||||||
|
for (var fieldName in fieldsInfo) {
|
||||||
|
var fieldInfo = fieldsInfo[fieldName];
|
||||||
|
if (_.contains(mailWidgets, fieldInfo.widget)) {
|
||||||
|
this.mailFields[fieldInfo.widget] = fieldName;
|
||||||
|
fieldInfo.__no_fetch = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.assign(this.rendererParams.mailFields, this.mailFields);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Chatter.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to initialize 'mail_failed_message' widget.
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
init: function (parent, record, mailFields, options) {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
// Initialize mail_failed_message widget
|
||||||
|
if (mailFields.mail_failed_message) {
|
||||||
|
this.fields.failed_message = new FailedMessage(
|
||||||
|
this, mailFields.mail_failed_message, record, options);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects widget before the chatter
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
_render: function () {
|
||||||
|
var self = this;
|
||||||
|
return this._super.apply(this, arguments).then(function () {
|
||||||
|
if (self.fields.failed_message) {
|
||||||
|
self.fields.failed_message.$el.insertBefore(
|
||||||
|
self.$el.find('.o_mail_thread'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to reload 'mail_failed_message' widget
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
_onReloadMailFields: function (event) {
|
||||||
|
if (this.fields.failed_message && event.data.failed_message) {
|
||||||
|
this.trigger_up('reload', {
|
||||||
|
fieldNames: [this.fields.failed_message.name],
|
||||||
|
keepChanges: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Workarround to avoid trigger reload event two times (one for
|
||||||
|
// mail_failed_message and other with empty 'fieldNames'.
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
MailThread.include({
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides to show 'retry' & 'Set as reviewed' buttons in the Chatter
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
*/
|
||||||
|
init: function () {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
this._enabledOptions.displayRetryButton = true;
|
||||||
|
this._enabledOptions.displayReviewedButton = true;
|
||||||
|
this._disabledOptions.displayRetryButton = true;
|
||||||
|
this._disabledOptions.displayReviewedButton = true;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return FailedMessage;
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<templates>
|
||||||
|
|
||||||
|
<t t-extend="mail.widget.Thread.Message">
|
||||||
|
<t t-jquery="span[t-attf-class=o_thread_icons]" t-operation="append">
|
||||||
|
<a t-if="message.isFailed() && options.displayRetryButton" class="btn btn-link o_thread_icon btn-success text-success btn-sm o_failed_message_reviewed o_activity_link mr8" t-att-data-message-id="message.getID()">
|
||||||
|
<i class="fa fa-check"/> Set as Reviewed
|
||||||
|
</a>
|
||||||
|
<a t-if="message.isFailed() && options.displayReviewedButton" class="btn btn-link o_thread_icon btn-default text-warning btn-sm o_failed_message_retry" t-att-data-message-id="message.getID()">
|
||||||
|
<i class="fa fa-retweet"/> Retry
|
||||||
|
</a>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
</templates>
|
|
@ -25,15 +25,4 @@
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
|
|
||||||
<t t-extend="mail.widget.Thread.Message">
|
|
||||||
<t t-jquery="span[t-attf-class=o_thread_icons]" t-operation="append">
|
|
||||||
<a t-if="message.isFailed() && options.displayRetryButton" class="btn btn-link btn-success text-success btn-sm o_failed_message_reviewed o_activity_link mr8" t-att-data-message-id="message.getID()">
|
|
||||||
<i class="fa fa-check"/> Set as Reviewed
|
|
||||||
</a>
|
|
||||||
<a t-if="message.isFailed() && options.displayReviewedButton" class="btn btn-link btn-default text-warning btn-sm o_failed_message_retry" t-att-data-message-id="message.getID()">
|
|
||||||
<i class="fa fa-retweet"/> Retry
|
|
||||||
</a>
|
|
||||||
</t>
|
|
||||||
</t>
|
|
||||||
|
|
||||||
</templates>
|
</templates>
|
|
@ -28,10 +28,10 @@
|
||||||
</strong>
|
</strong>
|
||||||
- <small class="o_mail_timestamp" t-att-title="message.date.format(date_format)"><t t-esc="message.hour"/></small>
|
- <small class="o_mail_timestamp" t-att-title="message.date.format(date_format)"><t t-esc="message.hour"/></small>
|
||||||
<span t-attf-class="o_thread_icons">
|
<span t-attf-class="o_thread_icons">
|
||||||
<a href="#" class="btn btn-link btn-success text-success btn-sm o_failed_message_reviewed o_activity_link" t-att-data-message-id="message.id">
|
<a href="#" class="btn btn-link btn-success o_thread_icon text-success btn-sm o_failed_message_reviewed o_activity_link" t-att-data-message-id="message.id">
|
||||||
<i class="fa fa-check"/> Set as Reviewed
|
<i class="fa fa-check"/> Set as Reviewed
|
||||||
</a>
|
</a>
|
||||||
<a href="#" class="btn btn-link btn-default text-warning btn-sm o_failed_message_retry" t-att-data-message-id="message.id">
|
<a href="#" class="btn btn-link btn-default o_thread_icon text-warning btn-sm o_failed_message_retry" t-att-data-message-id="message.id">
|
||||||
<i class="fa fa-retweet"/> Retry
|
<i class="fa fa-retweet"/> Retry
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
|
@ -13,7 +13,9 @@
|
||||||
<script type="text/javascript"
|
<script type="text/javascript"
|
||||||
src="/mail_tracking/static/src/js/mail_tracking.js"/>
|
src="/mail_tracking/static/src/js/mail_tracking.js"/>
|
||||||
<script type="text/javascript"
|
<script type="text/javascript"
|
||||||
src="/mail_tracking/static/src/js/failed_message.js"/>
|
src="/mail_tracking/static/src/js/failed_message/discuss.js"/>
|
||||||
|
<script type="text/javascript"
|
||||||
|
src="/mail_tracking/static/src/js/failed_message/widget.js"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
Loading…
Reference in New Issue