[PORT] porting js code to comply with OWL
This commit is contained in:
parent
881c70f7dd
commit
d45941df4d
@ -242,6 +242,8 @@ class MailMessage(models.Model):
|
|||||||
failed_trackings = self.mail_tracking_ids.filtered(
|
failed_trackings = self.mail_tracking_ids.filtered(
|
||||||
lambda x: x.state in self.get_failed_states()
|
lambda x: x.state in self.get_failed_states()
|
||||||
)
|
)
|
||||||
|
if not failed_trackings or not self.mail_tracking_needs_action:
|
||||||
|
return
|
||||||
failed_partners = failed_trackings.mapped("partner_id")
|
failed_partners = failed_trackings.mapped("partner_id")
|
||||||
failed_recipients = failed_partners.name_get()
|
failed_recipients = failed_partners.name_get()
|
||||||
if self.author_id:
|
if self.author_id:
|
||||||
@ -305,3 +307,9 @@ class MailMessage(models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def get_failed_messsage_info(self, ids, model):
|
||||||
|
msg_ids = self.search([('res_id', '=', ids), ('model', '=', model)])
|
||||||
|
res = [msg._prepare_dict_failed_message() for msg in msg_ids.sorted("date", reverse=True) if msg._prepare_dict_failed_message()]
|
||||||
|
return res
|
||||||
|
30
mail_tracking/static/src/js/chatter.js
Normal file
30
mail_tracking/static/src/js/chatter.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
odoo.define('mail_tracking/static/src/js/chatter.js', function (require) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const ChatterContainer = require('mail/static/src/components/chatter_container/chatter_container.js');
|
||||||
|
const { attr } = require('mail/static/src/model/model_field.js');
|
||||||
|
const { registerInstancePatchModel,registerFieldPatchModel, registerClassPatchModel,
|
||||||
|
} = 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,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
139
mail_tracking/static/src/js/discuss/discuss.js
Normal file
139
mail_tracking/static/src/js/discuss/discuss.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
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._super(...arguments);
|
||||||
|
this.messaging.update({
|
||||||
|
failedmsg: [
|
||||||
|
['create', {
|
||||||
|
id: 'failedmsg',
|
||||||
|
isServerPinned: true,
|
||||||
|
model: 'mail.box',
|
||||||
|
name: this.env._t("Failed"),
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
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]
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
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,95 @@
|
|||||||
|
odoo.define('mail_tracking/static/src/js/failed_message/mail_failed_box.js', function(require) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const components = {
|
||||||
|
Message: require('mail/static/src/components/message/message.js'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const useShouldUpdateBasedOnProps = require('mail/static/src/component_hooks/use_should_update_based_on_props/use_should_update_based_on_props.js');
|
||||||
|
const useStore = require('mail/static/src/component_hooks/use_store/use_store.js');
|
||||||
|
|
||||||
|
const chatter = require('mail/static/src/components/chatter/chatter.js');
|
||||||
|
|
||||||
|
const {
|
||||||
|
Component,
|
||||||
|
useState
|
||||||
|
} = 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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
@ -1,322 +1,60 @@
|
|||||||
/* Copyright 2019 Alexandre Díaz
|
odoo.define('mail_tracking/static/src/js/failed_message/thread.js', function(require) {
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
|
'use strict';
|
||||||
odoo.define("mail_tracking.FailedMessageThread", function (require) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var AbstractField = require("web.AbstractField");
|
const components = {
|
||||||
var BasicModel = require("web.BasicModel");
|
Message: require('mail/static/src/components/message/message.js'),
|
||||||
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;
|
const useShouldUpdateBasedOnProps = require('mail/static/src/component_hooks/use_should_update_based_on_props/use_should_update_based_on_props.js');
|
||||||
|
const useStore = require('mail/static/src/component_hooks/use_store/use_store.js');
|
||||||
|
|
||||||
/**
|
const chatter = require('mail/static/src/components/chatter/chatter.js');
|
||||||
* Helper method to fetch failed messages
|
|
||||||
*
|
const {
|
||||||
* @private
|
Component,
|
||||||
* @param {Object} widget
|
useState
|
||||||
* @param {Array} ids
|
} = owl;
|
||||||
* @returns {Array}
|
|
||||||
*/
|
const {
|
||||||
function _readMessages(widget, ids) {
|
registerInstancePatchModel,
|
||||||
if (!ids.length) {
|
registerFieldPatchModel,
|
||||||
return $.when([]);
|
} = 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]
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
var context = widget.record && widget.record.getContext();
|
|
||||||
return widget
|
|
||||||
._rpc({
|
|
||||||
model: "mail.message",
|
|
||||||
method: "get_failed_messages",
|
|
||||||
args: [ids],
|
|
||||||
context: context || widget.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 data for 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 FailedMessage = AbstractField.extend({
|
registerFieldPatchModel('mail.thread', 'mail_tracking/static/src/js/failed_message/thread.js', {
|
||||||
className: "o_mail_failed_message",
|
messagefailed: one2many('mail.message.failed', {
|
||||||
events: {
|
inverse: 'thread',
|
||||||
"click .o_failed_message_retry": "_onRetryFailedMessage",
|
}),
|
||||||
"click .o_failed_message_reviewed": "_onMarkFailedMessageReviewed",
|
|
||||||
},
|
|
||||||
specialData: "_fetchSpecialFailedMessages",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides to reference failed messages in a easy way
|
|
||||||
*
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
init: function () {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
this.failed_messages = this.record.specialData[this.name] || [];
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overrides to listen bus notifications
|
|
||||||
*
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
start: function () {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
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: "set_need_action_done",
|
|
||||||
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 === "toggle_tracking_status") {
|
|
||||||
// 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(
|
|
||||||
$.proxy(this, "_reload", {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];
|
|
||||||
// Search fields using 'mail_failed_messsage' widget.
|
|
||||||
// Only one field can exists using the widget, the last
|
|
||||||
// found wins.
|
|
||||||
if (_.contains(mailWidgets, fieldInfo.widget)) {
|
|
||||||
// Add field as "mail field" shared with Chatter
|
|
||||||
this.mailFields[fieldInfo.widget] = fieldName;
|
|
||||||
// Avoid fetch x2many data, this will be done by widget
|
|
||||||
fieldInfo.__no_fetch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Update renderParmans mailFields to include the found field
|
|
||||||
// using 'mail_failed_messsage' widget. This info is used by the
|
|
||||||
// renderers [In Odoo vanilla by the form renderer to initialize
|
|
||||||
// Chatter widget].
|
|
||||||
_.extend(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 failed messages 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 {
|
|
||||||
// Workaround to avoid trigger reload event twice (once for
|
|
||||||
// mail_failed_message and again with empty 'fieldNames'.
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
MailThread.include({
|
|
||||||
/**
|
|
||||||
* 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 = false;
|
|
||||||
this._disabledOptions.displayReviewedButton = false;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return FailedMessage;
|
|
||||||
});
|
|
@ -1,167 +1,48 @@
|
|||||||
/* Copyright 2016 Antonio Espinosa - <antonio.espinosa@tecnativa.com>
|
odoo.define('mail_tracking/static/src/js/mail_tracking.js', function(require) {
|
||||||
Copyright 2018 David Vidal - <david.vidal@tecnativa.com>
|
'use strict';
|
||||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */
|
|
||||||
|
|
||||||
odoo.define("mail_tracking.partner_tracking", function (require) {
|
const {
|
||||||
"use strict";
|
registerClassPatchModel,
|
||||||
|
registerFieldPatchModel,
|
||||||
|
registerInstancePatchModel,
|
||||||
|
} = require('mail/static/src/model/model_core.js');
|
||||||
|
const {
|
||||||
|
attr
|
||||||
|
} = require('mail/static/src/model/model_field.js');
|
||||||
|
|
||||||
var core = require("web.core");
|
registerClassPatchModel('mail.message', 'mail_tracking/static/src/js/mail_tracking.js', {
|
||||||
var ActionManager = require("web.ActionManager");
|
convertData(data) {
|
||||||
var AbstractMessage = require("mail.model.AbstractMessage");
|
const data2 = this._super(data);
|
||||||
var Message = require("mail.model.Message");
|
if ('partner_trackings' in data) {
|
||||||
var ThreadWidget = require("mail.widget.Thread");
|
data2.partner_trackings = data.partner_trackings;
|
||||||
|
}
|
||||||
var _t = core._t;
|
return data2;
|
||||||
|
|
||||||
AbstractMessage.include({
|
|
||||||
/**
|
|
||||||
* Messages do not have any PartnerTrackings.
|
|
||||||
*
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
hasPartnerTrackings: function () {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Messages do not have any email Cc values.
|
|
||||||
*
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
hasEmailCc: function () {
|
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Message.include({
|
registerFieldPatchModel('mail.message', 'mail_tracking/static/src/js/mail_tracking.js', {
|
||||||
init: function (parent, data) {
|
partner_trackings: attr(),
|
||||||
this._super.apply(this, arguments);
|
});
|
||||||
this._partnerTrackings = data.partner_trackings || [];
|
|
||||||
this._emailCc = data.email_cc || [];
|
|
||||||
this._trackNeedsAction = data.track_needs_action || false;
|
registerInstancePatchModel('mail.model', 'mail_tracking/static/src/js/mail_tracking.js', {
|
||||||
|
|
||||||
|
|
||||||
|
hasPartnerTrackings() {
|
||||||
|
return _.some(this.__values.partner_trackings);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
hasEmailCc() {
|
||||||
* State whether this message contains some PartnerTrackings values
|
|
||||||
*
|
|
||||||
* @override
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
hasPartnerTrackings: function () {
|
|
||||||
return _.some(this._partnerTrackings);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* State whether this message contains some email Cc values
|
|
||||||
*
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
hasEmailCc: function () {
|
|
||||||
return _.some(this._emailCc);
|
return _.some(this._emailCc);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
getPartnerTrackings: function() {
|
||||||
* Get the PartnerTrackings values of this message
|
|
||||||
* If this message has no PartnerTrackings values, returns []
|
|
||||||
*
|
|
||||||
* @override
|
|
||||||
* @returns {Object[]}
|
|
||||||
*/
|
|
||||||
getPartnerTrackings: function () {
|
|
||||||
if (!this.hasPartnerTrackings()) {
|
if (!this.hasPartnerTrackings()) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return this._partnerTrackings;
|
return this.__values.partner_trackings;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
})
|
||||||
* Get the email Cc values of this message
|
|
||||||
* If this message has no email Cc values, returns []
|
|
||||||
*
|
|
||||||
* @returns {Array}
|
|
||||||
*/
|
|
||||||
getEmailCc: function () {
|
|
||||||
if (!this.hasEmailCc()) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return this._emailCc;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
});
|
||||||
* Check if the email is an Cc
|
|
||||||
* If this message has no email Cc values, returns false
|
|
||||||
*
|
|
||||||
* @param {String} email
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
isEmailCc: function (email) {
|
|
||||||
if (!this.hasEmailCc()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return _.some(this._emailCc, function (item) {
|
|
||||||
return item[0] === email;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleTrackingStatus: function () {
|
|
||||||
return this._rpc({
|
|
||||||
model: "mail.message",
|
|
||||||
method: "toggle_tracking_status",
|
|
||||||
args: [[this.id]],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
ThreadWidget.include({
|
|
||||||
events: _.extend(ThreadWidget.prototype.events, {
|
|
||||||
"click .o_mail_action_tracking_partner": "on_tracking_partner_click",
|
|
||||||
"click .o_mail_action_tracking_status": "on_tracking_status_click",
|
|
||||||
}),
|
|
||||||
on_tracking_partner_click: function (event) {
|
|
||||||
var partner_id = this.$el.find(event.currentTarget).data("partner");
|
|
||||||
var state = {
|
|
||||||
model: "res.partner",
|
|
||||||
id: partner_id,
|
|
||||||
title: _t("Tracking partner"),
|
|
||||||
};
|
|
||||||
event.preventDefault();
|
|
||||||
this.action_manager.do_push_state(state);
|
|
||||||
var action = {
|
|
||||||
type: "ir.actions.act_window",
|
|
||||||
view_type: "form",
|
|
||||||
view_mode: "form",
|
|
||||||
res_model: "res.partner",
|
|
||||||
views: [[false, "form"]],
|
|
||||||
target: "current",
|
|
||||||
res_id: partner_id,
|
|
||||||
};
|
|
||||||
this.do_action(action);
|
|
||||||
},
|
|
||||||
on_tracking_status_click: function (event) {
|
|
||||||
var tracking_email_id = $(event.currentTarget).data("tracking");
|
|
||||||
var state = {
|
|
||||||
model: "mail.tracking.email",
|
|
||||||
id: tracking_email_id,
|
|
||||||
title: _t("Message tracking"),
|
|
||||||
};
|
|
||||||
event.preventDefault();
|
|
||||||
this.action_manager.do_push_state(state);
|
|
||||||
var 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,
|
|
||||||
};
|
|
||||||
this.do_action(action);
|
|
||||||
},
|
|
||||||
init: function () {
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
this.action_manager = this.findAncestor(function (ancestor) {
|
|
||||||
return ancestor instanceof ActionManager;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
67
mail_tracking/static/src/js/message.js
Normal file
67
mail_tracking/static/src/js/message.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
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');
|
||||||
|
var core = require('web.core');
|
||||||
|
var _t = core._t;
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
});
|
67
mail_tracking/static/src/js/models/thread.js
Normal file
67
mail_tracking/static/src/js/models/thread.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
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,
|
||||||
|
many2many,
|
||||||
|
many2one
|
||||||
|
} = require('mail/static/src/model/model_field.js');
|
||||||
|
const {
|
||||||
|
clear
|
||||||
|
} = require('mail/static/src/model/model_field_command.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,44 +1,38 @@
|
|||||||
<?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-name="mail_tracking.SidebarFailedCounter">
|
<xpath expr="//t[@t-elif='thread === env.messaging.moderation']"
|
||||||
<span
|
position="after">
|
||||||
t-attf-class="o_mail_sidebar_failed badge badge-pill #{(counter ? '' : 'd-none')}"
|
<t t-elif="thread === env.messaging.failedmsg">
|
||||||
>
|
<div class="o_ThreadIcon_mailboxModeration fa fa-exclamation"/>
|
||||||
<t t-esc="counter" />
|
|
||||||
</span>
|
|
||||||
</t>
|
|
||||||
|
|
||||||
<t t-name="mail_tracking.SidebarFailed">
|
|
||||||
<div
|
|
||||||
t-attf-class="o_mail_discuss_title_main o_mail_discuss_item #{(activeThreadID === 'mailbox_failed') ? 'o_active': ''}"
|
|
||||||
data-thread-id="mailbox_failed"
|
|
||||||
>
|
|
||||||
<span class="o_thread_name"><i class="fa fa-exclamation mr8" />Failed</span>
|
|
||||||
<t t-set="counter" t-value="failedCounter" />
|
|
||||||
<t t-call="mail_tracking.SidebarFailedCounter" />
|
|
||||||
</div>
|
|
||||||
</t>
|
|
||||||
|
|
||||||
<t t-extend="mail.widget.Thread.Empty">
|
|
||||||
<t t-jquery="t:last-child" t-operation="after">
|
|
||||||
<t t-if="thread.getID() === 'mailbox_failed'">
|
|
||||||
<div
|
|
||||||
class="o_thread_title"
|
|
||||||
>Congratulations, you don't have any failed messages</div>
|
|
||||||
<div>Failed messages appear here.</div>
|
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</xpath>
|
||||||
</t>
|
</t>
|
||||||
|
<t t-inherit="mail.Message" t-inherit-mode="extension">
|
||||||
<t t-extend="mail.discuss.ControlButtons">
|
<xpath expr="//div[hasclass('o_Message_originThread')]"
|
||||||
<t t-jquery="div" t-operation="append">
|
position="inside">
|
||||||
<button
|
<t t-if="message.isFailed">
|
||||||
type="button"
|
<span t-attf-class="o_thread_icons">
|
||||||
class="btn btn-secondary o_mail_discuss_button_set_all_reviewed"
|
<a
|
||||||
title="Mark all as reviewed"
|
href="#"
|
||||||
>Set all as reviewed</button>
|
class="btn btn-link btn-success o_thread_icon text-muted btn-sm o_failed_message_reviewed o_activity_link"
|
||||||
</t>
|
t-on-click="_onMarkFailedMessageReviewed"
|
||||||
|
t-att-data-message-id="message.id"
|
||||||
|
>
|
||||||
|
<i class="fa fa-check"/>
|
||||||
|
Set as Reviewed
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
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-att-data-message-id="message.id"
|
||||||
|
>
|
||||||
|
<i class="fa fa-retweet"/>
|
||||||
|
Retry
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</t>
|
||||||
|
</xpath>
|
||||||
</t>
|
</t>
|
||||||
|
</templates>
|
||||||
</templates>
|
|
@ -1,86 +1,107 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<templates xml:space="preserve">
|
<templates xml:space="preserve">
|
||||||
|
<t t-name="mail_tracking.MessageFailedBox" owl="1">
|
||||||
<t t-name="mail_tracking.failed_message_items">
|
<div class="o_ActivityBox">
|
||||||
<div
|
<t t-if="chatter and chatter.thread and chatter.thread.messagefailed.length > 0">
|
||||||
class="o_thread_date_separator o_border_dashed collapsed"
|
<a role="button" class="o_ActivityBox_title btn" t-on-click="_onClickTitle">
|
||||||
data-toggle="collapse"
|
<hr class="o_ActivityBox_titleLine"/>
|
||||||
data-target="#o_chatter_failed_message"
|
<span class="o_ActivityBox_titleText">
|
||||||
>
|
<i class="fa fa-fw" t-att-class="chatter.isMessageFailedBoxVisible ? 'fa-caret-down' : 'fa-caret-right'"/>
|
||||||
<a role="button" class="o_thread_date btn">
|
Failed messages
|
||||||
<i class="fa fa-fw fa-caret-down" />
|
</span>
|
||||||
Failed messages
|
<t t-if="!chatter.isMessageFailedBoxVisible">
|
||||||
<small class="o_chatter_failed_message_summary ml8">
|
<span class="o_ActivityBox_titleBadges">
|
||||||
<span class="badge rounded-circle badge-danger"><t
|
<t t-if="chatter.thread.messagefailed.length > 0">
|
||||||
t-esc="nbFailedMessages"
|
<span class="o_ActivityBox_titleBadge badge rounded-circle badge-danger">
|
||||||
/></span>
|
<t t-esc="chatter.thread.messagefailed.length"/>
|
||||||
</small>
|
</span>
|
||||||
|
</t>
|
||||||
|
</span>
|
||||||
|
</t>
|
||||||
|
<hr class="o_ActivityBox_titleLine"/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
<t t-if="chatter.isMessageFailedBoxVisible and chatter.thread.messagefailed">
|
||||||
<div id="o_chatter_failed_message" class="in collapse">
|
<div class="o_ActivityList">
|
||||||
<t t-foreach="failed_messages" t-as="message">
|
<t t-foreach="chatter.thread.messagefailed" t-as="messagefailed" t-key="messagefailed.localId">
|
||||||
<div class="o_thread_message" style="margin-bottom: 10px">
|
<div class="o_Activity">
|
||||||
<div class="o_thread_message_sidebar">
|
<t t-if="messagefailed">
|
||||||
<div class="o_avatar_stack">
|
<div class="o_Activity_sidebar">
|
||||||
<img
|
<div class="o_Activity_user">
|
||||||
t-attf-src="/web/image/res.partner/#{message.author[0]}/image_small"
|
<t t-if="messagefailed.author">
|
||||||
class="o_thread_message_avatar rounded-circle mb8"
|
<img class="o_Activity_userAvatar"
|
||||||
t-att-title="message.author[1]"
|
t-attf-src="/web/image/res.users/{{ messagefailed.author_id }}/image_128"
|
||||||
t-att-alt="message.author[1]"
|
t-att-alt="messagefailed.author"/>
|
||||||
/>
|
</t>
|
||||||
<i
|
<div class="o_Activity_iconContainer bg-danger-full"
|
||||||
t-att-class="'o_avatar_icon fa fa-exclamation bg-danger-full'"
|
>
|
||||||
title="Failed"
|
<i class="o_Activity_icon fa fa-exclamation"/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="o_thread_message_core">
|
<div class="o_Activity_core">
|
||||||
<div class="o_mail_info text-muted">
|
<div class="o_Activity_info">
|
||||||
<strong class="o_thread_author">
|
<div class="o_Activity_dueDateText"
|
||||||
<t t-esc="message.author[1]" />
|
t-att-class="{}"
|
||||||
</strong>
|
>
|
||||||
- <small
|
<t t-esc="messagefailed.author"/>
|
||||||
class="o_mail_timestamp"
|
</div>
|
||||||
t-att-title="message.date.format(date_format)"
|
<t t-if="messagefailed.date">
|
||||||
><t t-esc="message.hour" /></small>
|
<div class="o_Activity_summary text-muted">
|
||||||
<span t-attf-class="o_thread_icons">
|
<t t-esc="messagefailed.date"/>
|
||||||
<a
|
</div>
|
||||||
|
</t>
|
||||||
|
<span t-attf-class="o_thread_icons">
|
||||||
|
<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-att-data-message-id="message.id"
|
t-att-data-message-id="messagefailed.id"
|
||||||
>
|
>
|
||||||
<i class="fa fa-check" /> Set as Reviewed
|
<i class="fa fa-check" /> Set as Reviewed
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
class="btn btn-link btn-default o_thread_icon text-muted btn-sm o_failed_message_retry"
|
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-att-data-message-id="message.id"
|
t-att-data-message-id="messagefailed.id"
|
||||||
>
|
>
|
||||||
<i class="fa fa-retweet" /> Retry
|
<i class="fa fa-retweet" /> Retry
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<br />
|
</div>
|
||||||
<strong class="text-danger">Failed Recipients:</strong>
|
<div class="o_Activity_info">
|
||||||
<t t-foreach="message.failed_recipients" t-as="recipient">
|
<strong class="text-danger">Failed Recipients:</strong>
|
||||||
<t t-if="!recipient_first">
|
<t t-foreach="messagefailed.failed_recipients" t-as="recipient">
|
||||||
-
|
<t t-if="!recipient_first">
|
||||||
</t>
|
-
|
||||||
<a
|
</t>
|
||||||
class="o_mail_action_tracking_partner"
|
<a
|
||||||
t-att-data-partner="recipient[0]"
|
class="o_mail_action_tracking_partner"
|
||||||
t-attf-href="#model=res.partner&id=#{recipient[0]}"
|
t-att-data-partner="recipient[1]"
|
||||||
>
|
t-attf-href="#model=res.partner&id={{recipient[0]}}"
|
||||||
<t t-esc="recipient[1]" />
|
>
|
||||||
</a>
|
<t t-esc="recipient[1]"/>
|
||||||
</t>
|
</a>
|
||||||
</div>
|
</t>
|
||||||
<div class="o_thread_message_note small">
|
</div>
|
||||||
<t t-raw="message.body" />
|
<div class="o_thread_message_note small">
|
||||||
</div>
|
<t t-raw="messagefailed.body"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
</t>
|
</t>
|
||||||
</div>
|
</t>
|
||||||
</t>
|
</div>
|
||||||
|
</t>
|
||||||
</templates>
|
<t t-inherit="mail.Chatter" t-inherit-mode="extension">
|
||||||
|
<xpath expr="//div[hasclass('o_Chatter_scrollPanel')]/t[@t-if='chatter.isAttachmentBoxVisible']" position="before">
|
||||||
|
<t t-if="chatter.thread">
|
||||||
|
<MessageFailedBox
|
||||||
|
class="o_Chatter_activityBox"
|
||||||
|
chatterLocalId="chatter.localId"
|
||||||
|
/>
|
||||||
|
</t>
|
||||||
|
</xpath>
|
||||||
|
</t>
|
||||||
|
</templates>
|
@ -4,7 +4,7 @@
|
|||||||
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). -->
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<t t-name="mail.tracking.status">
|
<t t-name="mail.tracking.status" owl="1">
|
||||||
<t t-if="tracking['isCc']">
|
<t t-if="tracking['isCc']">
|
||||||
<span class="mail_tracking_cc">
|
<span class="mail_tracking_cc">
|
||||||
<i class="fa fa-cc" />
|
<i class="fa fa-cc" />
|
||||||
@ -54,9 +54,8 @@
|
|||||||
</span>
|
</span>
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
|
<t t-inherit="mail.Message" t-inherit-mode="extension">
|
||||||
<t t-extend="mail.widget.Thread.Message">
|
<xpath expr="//div[hasclass('o_Message_header')]" position="after">
|
||||||
<t t-jquery="p.o_mail_info" t-operation="after">
|
|
||||||
<t t-if="message.hasPartnerTrackings() || message.hasEmailCc()">
|
<t t-if="message.hasPartnerTrackings() || message.hasEmailCc()">
|
||||||
<p class="o_mail_tracking">
|
<p class="o_mail_tracking">
|
||||||
<strong>To:</strong>
|
<strong>To:</strong>
|
||||||
@ -68,7 +67,7 @@
|
|||||||
<a
|
<a
|
||||||
t-attf-class="o_mail_action_tracking_partner #{tracking['isCc'] ? 'o_mail_cc' : ''}"
|
t-attf-class="o_mail_action_tracking_partner #{tracking['isCc'] ? 'o_mail_cc' : ''}"
|
||||||
t-att-data-partner="tracking['partner_id']"
|
t-att-data-partner="tracking['partner_id']"
|
||||||
t-attf-href="#model=res.partner&id=#{tracking['partner_id']}"
|
t-attf-href="#model=res.partner&id={{tracking['partner_id']}}"
|
||||||
>
|
>
|
||||||
<t t-esc="tracking['recipient']" />
|
<t t-esc="tracking['recipient']" />
|
||||||
</a>
|
</a>
|
||||||
@ -92,13 +91,14 @@
|
|||||||
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"
|
||||||
|
t-on-click="_onTrackingStatusClick"
|
||||||
>
|
>
|
||||||
<t t-call="mail.tracking.status" />
|
<t t-call="mail.tracking.status" />
|
||||||
</span>
|
</span>
|
||||||
</t>
|
</t>
|
||||||
</p>
|
</p>
|
||||||
</t>
|
</t>
|
||||||
</t>
|
|
||||||
</t>
|
|
||||||
|
|
||||||
|
</xpath>
|
||||||
|
</t>
|
||||||
</template>
|
</template>
|
||||||
|
@ -22,12 +22,28 @@
|
|||||||
/>
|
/>
|
||||||
<script
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="/mail_tracking/static/src/js/failed_message/discuss.js"
|
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
|
<script
|
||||||
type="text/javascript"
|
type="text/javascript"
|
||||||
src="/mail_tracking/static/src/js/failed_message/thread.js"
|
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>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
Loading…
Reference in New Issue
Block a user