summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/js/thread.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/mail/static/src/js/thread.js')
-rw-r--r--addons/mail/static/src/js/thread.js636
1 files changed, 369 insertions, 267 deletions
diff --git a/addons/mail/static/src/js/thread.js b/addons/mail/static/src/js/thread.js
index 54a36e169e4..7d4833e81cd 100644
--- a/addons/mail/static/src/js/thread.js
+++ b/addons/mail/static/src/js/thread.js
@@ -1,9 +1,11 @@
-odoo.define('mail.ChatThread', function (require) {
+odoo.define('mail.widget.Thread', function (require) {
"use strict";
+var DocumentViewer = require('mail.DocumentViewer');
+var mailUtils = require('mail.utils');
+
var core = require('web.core');
var time = require('web.time');
-var DocumentViewer = require('mail.DocumentViewer');
var Widget = require('web.Widget');
var QWeb = core.qweb;
@@ -14,60 +16,31 @@ var ORDER = {
DESC: -1,
};
-var read_more = _t('read more');
-var read_less = _t('read less');
-
-function time_from_now(date) {
- if (moment().diff(date, 'seconds') < 45) {
- return _t("now");
- }
- return date.fromNow();
-}
+var READ_MORE = _t("read more");
+var READ_LESS = _t("read less");
-var Thread = Widget.extend({
+/**
+ * This is a generic widget to render a chat thread
+ */
+var ThreadWidget = Widget.extend({
className: 'o_mail_thread',
events: {
- "click a": "on_click_redirect",
- "click img": "on_click_redirect",
- "click strong": "on_click_redirect",
- "click .o_thread_show_more": "on_click_show_more",
- "click .o_attachment_download": "_onAttachmentDownload",
- "click .o_attachment_view": "_onAttachmentView",
- "click .o_thread_message_needaction": function (event) {
- var messageId = $(event.currentTarget).data('message-id');
- this.trigger("mark_as_read", messageId);
- },
- "click .o_thread_message_moderation": "_onClickMessageModeration",
- "change .moderation_checkbox": "_onChangeModerationCheckbox",
- "click .o_thread_message_star": function (event) {
- var messageId = $(event.currentTarget).data('message-id');
- this.trigger("toggle_star_status", messageId);
- },
- "click .o_thread_message_email_exception": "_onClickMailException",
- "click .o_thread_message_reply": function (event) {
- this.selected_id = $(event.currentTarget).data('message-id');
- this.$('.o_thread_message').removeClass('o_thread_selected_message');
- this.$('.o_thread_message[data-message-id="' + this.selected_id + '"]')
- .addClass('o_thread_selected_message');
- this.trigger('select_message', this.selected_id);
- event.stopPropagation();
- },
- "click .oe_mail_expand": function (event) {
- event.preventDefault();
- var $message = $(event.currentTarget).parents('.o_thread_message');
- $message.addClass('o_message_expanded');
- this.expanded_msg_ids.push($message.data('message-id'));
- },
- "click .o_thread_message": function (event) {
- $(event.currentTarget).toggleClass('o_thread_selected_message');
- },
- "click": function () {
- if (this.selected_id) {
- this.unselect();
- this.trigger('unselect_message');
- }
- },
+ 'click a': '_onClickRedirect',
+ 'click img': '_onClickRedirect',
+ 'click strong': '_onClickRedirect',
+ 'click .o_thread_show_more': '_onClickShowMore',
+ 'click .o_attachment_download': '_onAttachmentDownload',
+ 'click .o_attachment_view': '_onAttachmentView',
+ 'click .o_thread_message_needaction': '_onClickMessageNeedaction',
+ 'click .o_thread_message_star': '_onClickMessageStar',
+ 'click .o_thread_message_reply': '_onClickMessageReply',
+ 'click .oe_mail_expand': '_onClickMailExpand',
+ 'click .o_thread_message': '_onClickMessage',
+ 'click': '_onClick',
+ 'click .o_thread_message_email_exception': '_onClickEmailException',
+ 'click .o_thread_message_moderation': '_onClickMessageModeration',
+ 'change .moderation_checkbox': '_onChangeModerationCheckbox',
},
/**
@@ -77,253 +50,315 @@ var Thread = Widget.extend({
*/
init: function (parent, options) {
this._super.apply(this, arguments);
- this.enabledOptions = _.defaults(options || {}, {
- display_order: ORDER.ASC,
- display_needactions: true,
- display_stars: true,
- display_document_link: true,
- display_avatar: true,
- squash_close_messages: true,
- display_email_icon: true,
- display_reply_icon: false,
+ // options when the thread is enabled (e.g. can send message,
+ // interact on messages, etc.)
+ this._enabledOptions = _.defaults(options || {}, {
+ displayOrder: ORDER.ASC,
+ displayMarkAsRead: true,
+ displayStars: true,
+ displayDocumentLinks: true,
+ displayAvatars: true,
+ squashCloseMessages: true,
+ displayEmailIcons: true,
+ displayReplyIcons: false,
loadMoreOnScroll: false,
});
- this.disabledOptions = {
- display_order: this.enabledOptions.display_order,
- display_needactions: false,
- display_stars: false,
- display_document_link: false,
- display_avatar: this.enabledOptions.display_avatar,
- squash_close_messages: false,
- display_email_icon: false,
- display_reply_icon: false,
- loadMoreOnScroll: this.enabledOptions.loadMoreOnScroll,
+ // options when the thread is disabled
+ this._disabledOptions = {
+ displayOrder: this._enabledOptions.displayOrder,
+ displayMarkAsRead: false,
+ displayStars: false,
+ displayDocumentLinks: false,
+ displayAvatars: this._enabledOptions.displayAvatars,
+ squashCloseMessages: false,
+ displayEmailIcons: false,
+ displayReplyIcons: false,
+ loadMoreOnScroll: this._enabledOptions.loadMoreOnScroll,
};
- this.expanded_msg_ids = [];
- this.selected_id = null;
+ this._selectedMessageID = null;
},
/**
- * @param {Object[]} messages
+ * @override
+ */
+ destroy: function () {
+ clearInterval(this._updateTimestampsInterval);
+ },
+
+ /**
+ * @param {mail.model.AbstractMessage[]} messages list of messages of the
+ * thread, ordered by increasing IDs (a higher ID means a more recent
+ * message).
* @param {Object} [options]
- * @param {integer} [options.display_order=ORDER.ASC]
- * @param {boolean} [options.display_load_more]
+ * @param {integer} [options.displayOrder=ORDER.ASC] order of displaying
+ * messages in the thread:
+ * - ORDER.ASC: last message is at the bottom of the thread
+ * - ORDER.DESC: last message is at the top of the thread
+ * @param {boolean} [options.displayLoadMore]
* @param {boolean} [options.isCreateMode]
- * @param {boolean} [options.squash_close_messages]
+ * @param {boolean} [options.squashCloseMessages]
*/
render: function (messages, options) {
var self = this;
- var msgs = _.map(messages, this._preprocessMessage.bind(this));
- var modeOptions = options.isCreateMode ? this.disabledOptions : this.enabledOptions;
- if (modeOptions.display_order === ORDER.DESC) {
- msgs.reverse();
+ // copy so that reverse do not alter order in the thread object
+ messages = _.clone(messages);
+
+ var modeOptions = options.isCreateMode ? this._disabledOptions :
+ this._enabledOptions;
+
+ // attachments ordered by messages order (increasing ID)
+ this.attachments = _.uniq(_.flatten(_.map(messages, function (message) {
+ return message.getAttachments();
+ })));
+
+ if (modeOptions.displayOrder === ORDER.DESC) {
+ messages.reverse();
}
- options = _.extend({}, modeOptions, options);
+ options = _.extend({}, modeOptions, options, {
+ selectedMessageID: this._selectedMessageID,
+ });
// Hide avatar and info of a message if that message and the previous
// one are both comments wrote by the same author at the same minute
// and in the same document (users can now post message in documents
// directly from a channel that follows it)
- var prev_msg;
- _.each(msgs, function (msg) {
- if (!prev_msg || (Math.abs(msg.date.diff(prev_msg.date)) > 60000) ||
- prev_msg.message_type !== 'comment' || msg.message_type !== 'comment' ||
- (prev_msg.author_id[0] !== msg.author_id[0]) || prev_msg.model !== msg.model ||
- prev_msg.res_id !== msg.res_id) {
- msg.display_author = true;
+ var prevMessage;
+ _.each(messages, function (message) {
+ if (
+ // is first message of thread
+ !prevMessage ||
+ // more than 1 min. elasped
+ (Math.abs(message.getDate().diff(prevMessage.getDate())) > 60000) ||
+ prevMessage.getType() !== 'comment' ||
+ message.getType() !== 'comment' ||
+ // from a different author
+ (prevMessage.getAuthorID() !== message.getAuthorID()) ||
+ (
+ // messages are linked to a document thread
+ (
+ prevMessage.isLinkedToDocumentThread() &&
+ message.isLinkedToDocumentThread()
+ ) &&
+ (
+ // are from different documents
+ prevMessage.getDocumentModel() !== message.getDocumentModel() ||
+ prevMessage.getDocumentID() !== message.getDocumentID()
+ )
+ )
+ ) {
+ message.displayAuthor(true);
} else {
- msg.display_author = !options.squash_close_messages;
- }
- if (msg.attachment_ids) {
- var sortedAttachments = _.partition(msg.attachment_ids, function (att) {
- return att.mimetype && att.mimetype.split('/')[0] === 'image';
- });
- msg.images = sortedAttachments[0];
- msg.others = sortedAttachments[1];
+ message.displayAuthor(!options.squashCloseMessages);
}
- prev_msg = msg;
+ prevMessage = message;
});
- this.$el.html(QWeb.render('mail.ChatThread', {
- messages: msgs,
+ this.$el.html(QWeb.render('mail.widget.Thread', {
+ messages: messages,
options: options,
ORDER: ORDER,
- date_format: time.getLangDatetimeFormat(),
+ dateFormat: time.getLangDatetimeFormat(),
}));
- this.attachments = _.uniq(_.flatten(_.map(messages, 'attachment_ids')));
-
- _.each(msgs, function (msg) {
- var $msg = self.$('.o_thread_message[data-message-id="'+ msg.id +'"]');
- $msg.find('.o_mail_timestamp').data('date', msg.date);
+ _.each(messages, function (message) {
+ var $message = self.$('.o_thread_message[data-message-id="'+ message.getID() +'"]');
+ $message.find('.o_mail_timestamp').data('date', message.getDate());
- self.insert_read_more($msg);
+ self._insertReadMore($message);
});
- if (!this.update_timestamps_interval) {
- this.update_timestamps_interval = setInterval(function () {
- self.update_timestamps();
+ if (!this._updateTimestampsInterval) {
+ this.updateTimestampsInterval = setInterval(function () {
+ self._updateTimestamps();
}, 1000*60);
}
},
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ getScrolltop: function () {
+ return this.$el.scrollTop();
+ },
+ /**
+ * State whether the bottom of the thread is visible or not,
+ * with a tolerance of 5 pixels
+ *
+ * @return {boolean}
+ */
+ isAtBottom: function () {
+ var fullHeight = this.el.scrollHeight;
+ var topHiddenHeight = this.$el.scrollTop();
+ var visibleHeight = this.$el.outerHeight();
+ var bottomHiddenHeight = fullHeight - topHiddenHeight - visibleHeight;
+ return bottomHiddenHeight < 5;
+ },
+ /**
+ * Removes a message and re-renders the thread
+ *
+ * @param {integer} [messageID] the id of the removed message
+ * @param {mail.model.AbstractMessage[]} [messages] the list of messages to
+ * display, without the removed one
+ * @param {Object} [options] options for the thread rendering
+ */
+ removeMessageAndRender: function (messageID, messages, options) {
+ var self = this;
+ var done = $.Deferred();
+ this.$('.o_thread_message[data-message-id="' + messageID + '"]')
+ .fadeOut({
+ done: function () {
+ self.render(messages, options);
+ done.resolve();
+ },
+ duration: 200,
+ });
+ return done;
+ },
+ /**
+ * Scroll to the bottom of the thread
+ */
+ scrollToBottom: function () {
+ this.$el.scrollTop(this.el.scrollHeight);
+ },
+ /**
+ * Scrolls the thread to a given message
+ *
+ * @param {integer} options.messageID the ID of the message to scroll to
+ * @param {integer} [options.duration]
+ * @param {boolean} [options.onlyIfNecessary]
+ */
+ scrollToMessage: function (options) {
+ var $target = this.$('.o_thread_message[data-message-id="' + options.messageID + '"]');
+ if (options.onlyIfNecessary) {
+ var delta = $target.parent().height() - $target.height();
+ var offset = delta < 0 ?
+ 0 :
+ delta - ($target.offset().top - $target.offsetParent().offset().top);
+ offset = - Math.min(offset, 0);
+ this.$el.scrollTo("+=" + offset + "px", options.duration);
+ } else if ($target.length) {
+ this.$el.scrollTo($target);
+ }
+ },
+ /**
+ * Scroll to the specific position in pixel
+ *
+ * If no position is provided, scroll to the bottom of the thread
+ *
+ * @param {integer} [position] distance from top to position in pixels.
+ * If not provided, scroll to the bottom.
+ */
+ scrollToPosition: function (position) {
+ if (position) {
+ this.$el.scrollTop(position);
+ } else {
+ this.scrollToBottom();
+ }
+ },
+ /**
+ * Toggle all the moderation checkboxes in the thread
+ *
+ * @param {boolean} checked if true, check the boxes,
+ * otherwise uncheck them.
+ */
+ toggleModerationCheckboxes: function (checked) {
+ this.$('.moderation_checkbox').prop('checked', checked);
+ },
+ /**
+ * Unselect the selected message
+ */
+ unselectMessage: function () {
+ this.$('.o_thread_message').removeClass('o_thread_selected_message');
+ this._selectedMessageID = null;
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
/**
* Modifies $element to add the 'read more/read less' functionality
- * All element nodes with "data-o-mail-quote" attribute are concerned.
+ * All element nodes with 'data-o-mail-quote' attribute are concerned.
* All text nodes after a ``#stopSpelling`` element are concerned.
* Those text nodes need to be wrapped in a span (toggle functionality).
* All consecutive elements are joined in one 'read more/read less'.
+ *
+ * @private
+ * @param {jQuery} $element
*/
- insert_read_more: function ($element) {
+ _insertReadMore: function ($element) {
var self = this;
var groups = [];
- var read_more_nodes;
+ var readMoreNodes;
// nodeType 1: element_node
// nodeType 3: text_node
var $children = $element.contents()
.filter(function () {
- return this.nodeType === 1 || this.nodeType === 3 && this.nodeValue.trim();
+ return this.nodeType === 1 ||
+ this.nodeType === 3 &&
+ this.nodeValue.trim();
});
_.each($children, function (child) {
var $child = $(child);
// Hide Text nodes if "stopSpelling"
- if (child.nodeType === 3 && $child.prevAll("[id*='stopSpelling']").length > 0) {
+ if (
+ child.nodeType === 3 &&
+ $child.prevAll('[id*="stopSpelling"]').length > 0
+ ) {
// Convert Text nodes to Element nodes
$child = $('<span>', {
text: child.textContent,
- "data-o-mail-quote": "1",
+ 'data-o-mail-quote': '1',
});
child.parentNode.replaceChild($child[0], child);
}
- // Create array for each "read more" with nodes to toggle
- if ($child.attr('data-o-mail-quote') || ($child.get(0).nodeName === 'BR' && $child.prev("[data-o-mail-quote='1']").length > 0)) {
- if (!read_more_nodes) {
- read_more_nodes = [];
- groups.push(read_more_nodes);
+ // Create array for each 'read more' with nodes to toggle
+ if (
+ $child.attr('data-o-mail-quote') ||
+ (
+ $child.get(0).nodeName === 'BR' &&
+ $child.prev('[data-o-mail-quote="1"]').length > 0
+ )
+ ) {
+ if (!readMoreNodes) {
+ readMoreNodes = [];
+ groups.push(readMoreNodes);
}
$child.hide();
- read_more_nodes.push($child);
+ readMoreNodes.push($child);
} else {
- read_more_nodes = undefined;
- self.insert_read_more($child);
+ readMoreNodes = undefined;
+ self._insertReadMore($child);
}
});
_.each(groups, function (group) {
// Insert link just before the first node
- var $read_more = $('<a>', {
- class: "o_mail_read_more",
- href: "#",
- text: read_more,
+ var $readMore = $('<a>', {
+ class: 'o_mail_read_more',
+ href: '#',
+ text: READ_MORE,
}).insertBefore(group[0]);
// Toggle All next nodes
- var is_read_more = true;
- $read_more.click(function (e) {
+ var isReadMore = true;
+ $readMore.click(function (e) {
e.preventDefault();
- is_read_more = !is_read_more;
+ isReadMore = !isReadMore;
_.each(group, function ($child) {
$child.hide();
- $child.toggle(!is_read_more);
+ $child.toggle(!isReadMore);
});
- $read_more.text(is_read_more ? read_more : read_less);
+ $readMore.text(isReadMore ? READ_MORE : READ_LESS);
});
});
},
- update_timestamps: function () {
- var isAtBottom = this.is_at_bottom();
- this.$('.o_mail_timestamp').each(function () {
- var date = $(this).data('date');
- $(this).html(time_from_now(date));
- });
- if (isAtBottom && !this.is_at_bottom()) {
- this.scroll_to();
- }
- },
- on_click_redirect: function (event) {
- // ignore inherited branding
- if ($(event.target).data('oe-field') !== undefined) {
- return;
- }
- var id = $(event.target).data('oe-id');
- if (id) {
- event.preventDefault();
- var model = $(event.target).data('oe-model');
- var options = model && (model !== 'mail.channel') ? {model: model, id: id} : {channel_id: id};
- this._redirect(options);
- }
- },
-
- on_click_show_more: function () {
- this.trigger('load_more_messages');
- },
-
- /**
- * Removes a message and re-renders the thread
- * @param {int} [message_id] the id of the removed message
- * @param {array} [messages] the list of messages to display, without the removed one
- * @param {object} [options] options for the thread rendering
- */
- remove_message_and_render: function (message_id, messages, options) {
- var self = this;
- var done = $.Deferred();
- this.$('.o_thread_message[data-message-id="' + message_id + '"]').fadeOut({
- done: function () { self.render(messages, options); done.resolve();},
- duration: 200,
- });
- return done;
- },
-
- /**
- * Scrolls the thread to a given message or offset if any, to bottom otherwise
- * @param {int} [options.id] optional: the id of the message to scroll to
- * @param {int} [options.offset] optional: the number of pixels to scroll
- */
- scroll_to: function (options) {
- options = options || {};
- if (options.id !== undefined) {
- var $target = this.$('.o_thread_message[data-message-id="' + options.id + '"]');
- if (options.only_if_necessary) {
- var delta = $target.parent().height() - $target.height();
- var offset = delta < 0 ? 0 : delta - ($target.offset().top - $target.offsetParent().offset().top);
- offset = - Math.min(offset, 0);
- this.$el.scrollTo("+=" + offset + "px", options);
- } else if ($target.length) {
- this.$el.scrollTo($target);
- }
- } else if (options.offset !== undefined) {
- this.$el.scrollTop(options.offset);
- } else {
- this.$el.scrollTop(this.el.scrollHeight);
- }
- },
- get_scrolltop: function () {
- return this.$el.scrollTop();
- },
- is_at_bottom: function () {
- return this.el.scrollHeight - this.$el.scrollTop() - this.$el.outerHeight() < 5;
- },
- unselect: function () {
- this.$('.o_thread_message').removeClass('o_thread_selected_message');
- this.selected_id = null;
- },
- destroy: function () {
- clearInterval(this.update_timestamps_interval);
- },
- /**
- * Toggle all the moderation checkboxes in the thread
- *
- * @param {boolean} checked if true, check the boxes,
- * otherwise uncheck them.
- */
- toggleModerationCheckboxes: function (checked) {
- this.$('.moderation_checkbox').prop('checked', checked);
- },
//--------------------------------------------------------------------------
// Private
@@ -331,49 +366,31 @@ var Thread = Widget.extend({
/**
* @private
- * @param {Object} message
- * @param {integer} [message.id]
- * @param {string} [message.model]
- * @param {string} [message.subject]
- * @param {string} [message.message_type]
- */
- _preprocessMessage: function (message) {
- var msg = _.extend({}, message);
-
- msg.date = moment.min(msg.date, moment());
- msg.hour = time_from_now(msg.date);
-
- var date = msg.date.format('YYYY-MM-DD');
- if (date === moment().format('YYYY-MM-DD')) {
- msg.day = _t("Today");
- } else if (date === moment().subtract(1, 'days').format('YYYY-MM-DD')) {
- msg.day = _t("Yesterday");
- } else {
- msg.day = msg.date.format('LL');
- }
-
- if (_.contains(this.expanded_msg_ids, message.id)) {
- msg.expanded = true;
- }
-
- msg.display_subject = message.subject && message.message_type !== 'notification' && !(message.model && (message.model !== 'mail.channel'));
- msg.is_selected = msg.id === this.selected_id;
- return msg;
- },
- /**
- * @private
* @param {Object} options
- * @param {integer} [options.channel_id]
+ * @param {integer} [options.channelID]
* @param {string} options.model
* @param {integer} options.id
*/
_redirect: _.debounce(function (options) {
- if ('channel_id' in options) {
- this.trigger('redirect_to_channel', options.channel_id);
+ if ('channelID' in options) {
+ this.trigger('redirect_to_channel', options.channelID);
} else {
this.trigger('redirect', options.model, options.id);
}
}, 500, true),
+ /**
+ * @private
+ */
+ _updateTimestamps: function () {
+ var isAtBottom = this.isAtBottom();
+ this.$('.o_mail_timestamp').each(function () {
+ var date = $(this).data('date');
+ $(this).html(mailUtils.timeFromNow(date));
+ });
+ if (isAtBottom && !this.isAtBottom()) {
+ this.scrollToBottom();
+ }
+ },
//--------------------------------------------------------------------------
// Handlers
@@ -407,30 +424,115 @@ var Thread = Widget.extend({
},
/**
* @private
+ */
+ _onClick: function () {
+ if (this._selectedMessageID) {
+ this.unselectMessage();
+ this.trigger('unselect_message');
+ }
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickEmailException: function (ev) {
+ var messageID = $(ev.currentTarget).data('message-id');
+ this.do_action('mail.mail_resend_message_action', {
+ additional_context: {
+ mail_message_to_resend: messageID
+ }
+ });
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickMailExpand: function (ev) {
+ ev.preventDefault();
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickMessage: function (ev) {
+ $(ev.currentTarget).toggleClass('o_thread_selected_message');
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickMessageNeedaction: function (ev) {
+ var messageID = $(ev.currentTarget).data('message-id');
+ this.trigger('mark_as_read', messageID);
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickMessageReply: function (ev) {
+ this._selectedMessageID = $(ev.currentTarget).data('message-id');
+ this.$('.o_thread_message').removeClass('o_thread_selected_message');
+ this.$('.o_thread_message[data-message-id="' + this._selectedMessageID + '"]')
+ .addClass('o_thread_selected_message');
+ this.trigger('select_message', this._selectedMessageID);
+ ev.stopPropagation();
+ },
+ /**
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onClickMessageStar: function (ev) {
+ var messageID = $(ev.currentTarget).data('message-id');
+ this.trigger('toggle_star_status', messageID);
+ },
+ /**
+ * @private
* @param {MouseEvent} ev
*/
- _onClickMessageModeration: function (ev) {
+ _onClickMessageModeration: function (ev) {
var $button = $(ev.currentTarget);
var messageID = $button.data('message-id');
var decision = $button.data('decision');
- this.trigger_up('message_moderation', { messageID: messageID, decision: decision });
+ this.trigger_up('message_moderation', {
+ messageID: messageID,
+ decision: decision,
+ });
},
/**
* @private
- * @param {MouseEvent} event
+ * @param {MouseEvent} ev
*/
- _onClickMailException: function (event) {
- var messageId = $(event.currentTarget).data('message-id');
- this.do_action('mail.mail_resend_message_action', {
- additional_context: {
- mail_message_to_resend: messageId
+ _onClickRedirect: function (ev) {
+ // ignore inherited branding
+ if ($(ev.target).data('oe-field') !== undefined) {
+ return;
+ }
+ var id = $(ev.target).data('oe-id');
+ if (id) {
+ ev.preventDefault();
+ var model = $(ev.target).data('oe-model');
+ var options;
+ if (model && (model !== 'mail.channel')) {
+ options = {
+ model: model,
+ id: id
+ };
+ } else {
+ options = { channelID: id };
}
- });
+ this._redirect(options);
+ }
+ },
+ /**
+ * @private
+ */
+ _onClickShowMore: function () {
+ this.trigger('load_more_messages');
},
});
-Thread.ORDER = ORDER;
+ThreadWidget.ORDER = ORDER;
-return Thread;
+return ThreadWidget;
});