summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/js
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2015-12-10 13:05:58 +0100
committerChristophe Simonis <chs@odoo.com>2015-12-10 13:05:58 +0100
commit82a495eed52a9f42e5b88caa52c20a85f8d81ce3 (patch)
tree6c5e8cc0247d5fe08d24e9abae38fe353fbebc56 /addons/mail/static/src/js
parent0bc2ddae784bf80c4c809d8b7f6d642d576f92a1 (diff)
parent4022493c0b85f966e499b6c03ac7cce5556f15e6 (diff)
[MERGE] forward port of branch saas-7 up to 4022493
Diffstat (limited to 'addons/mail/static/src/js')
-rw-r--r--addons/mail/static/src/js/chat_manager.js232
-rw-r--r--addons/mail/static/src/js/chat_window.js13
-rw-r--r--addons/mail/static/src/js/chatter.js44
-rw-r--r--addons/mail/static/src/js/client_action.js80
-rw-r--r--addons/mail/static/src/js/composer.js7
-rw-r--r--addons/mail/static/src/js/thread.js8
-rw-r--r--addons/mail/static/src/js/window_manager.js17
7 files changed, 229 insertions, 172 deletions
diff --git a/addons/mail/static/src/js/chat_manager.js b/addons/mail/static/src/js/chat_manager.js
index e8a2ad3951e..2261b961410 100644
--- a/addons/mail/static/src/js/chat_manager.js
+++ b/addons/mail/static/src/js/chat_manager.js
@@ -15,6 +15,7 @@ var preview_msg_max_size = 50;
var MessageModel = new Model('mail.message', session.context);
var ChannelModel = new Model('mail.channel', session.context);
+var UserModel = new Model('res.users', session.context);
// Private model
//----------------------------------------------------------------------------------
@@ -26,6 +27,42 @@ var emoji_substitutions = {};
var needaction_counter = 0;
var mention_partner_suggestions = [];
var discuss_ids = {};
+var global_unread_counter = 0;
+
+// Window focus/unfocus, beep and title
+//----------------------------------------------------------------------------------
+var beep = (function () {
+ if (typeof(Audio) === "undefined") {
+ return function () {};
+ }
+ var audio = new Audio();
+ var ext = audio.canPlayType("audio/ogg; codecs=vorbis") ? ".ogg" : ".mp3";
+ audio.src = session.url("/mail/static/src/audio/ting" + ext);
+ return function () { audio.play(); };
+})();
+
+bus.on("window_focus", null, function() {
+ global_unread_counter = 0;
+ notify();
+});
+
+function increment_global_unread_counter () {
+ if (!bus.is_odoo_focused()) {
+ global_unread_counter++;
+ notify(bus.is_master);
+ }
+}
+
+function notify (play_sound) {
+ var title;
+ if (global_unread_counter > 0) {
+ title = _.str.sprintf(_t("%d Messages"), global_unread_counter);
+ if (play_sound) {
+ beep();
+ }
+ }
+ web_client.set_title_part("_chat", title);
+}
// Message and channel manipulation helpers
//----------------------------------------------------------------------------------
@@ -41,18 +78,21 @@ function add_message (data, options) {
messages.splice(_.sortedIndex(messages, msg, 'id'), 0, msg);
_.each(msg.channel_ids, function (channel_id) {
var channel = chat_manager.get_channel(channel_id);
-
+ var is_chat = channel && !_.contains(["public", "private"], channel.type);
if (channel) {
add_to_cache(msg, []);
if (options.domain && options.domain !== []) {
add_to_cache(msg, options.domain);
}
+ if (options.increment_unread) {
+ update_channel_unread_counter(channel, channel.unread_counter+1);
+ }
}
if (channel && channel.hidden) {
channel.hidden = false;
chat_manager.bus.trigger('new_channel', channel);
}
- if (channel && !_.contains(["public", "private"], channel.type) && (options.show_notification)) {
+ if (is_chat && options.show_notification) {
var query = { is_displayed: false };
chat_manager.bus.trigger('anyone_listening', channel, query);
if (!query.is_displayed) {
@@ -66,6 +106,9 @@ function add_message (data, options) {
web_client.do_notify(title, trunc_text(msg.body, preview_msg_max_size));
}
}
+ if (is_chat && options.increment_unread && (!msg.author_id || msg.author_id[0] !== session.partner_id)) {
+ increment_global_unread_counter();
+ }
});
if (!options.silent) {
chat_manager.bus.trigger('new_message', msg);
@@ -147,6 +190,13 @@ function make_message (data) {
msg.email_from || _t('Anonymous');
}
+ // Don't redirect on author clicked of self-posted messages
+ if (msg.author_id && msg.author_id[0] === session.partner_id) {
+ msg.author_redirect = false;
+ } else {
+ msg.author_redirect = true;
+ }
+
// Compute the avatar_url
if (msg.author_id && msg.author_id[0]) {
msg.avatar_src = "/web/image/res.partner/" + msg.author_id[0] + "/image_small";
@@ -169,39 +219,6 @@ function add_channel_to_message (message, channel_id) {
message.channel_ids = _.uniq(message.channel_ids);
}
-function post_channel_message (data) {
- return ChannelModel.call('message_post', [data.channel_id], {
- message_type: 'comment',
- content_subtype: 'html',
- partner_ids: data.partner_ids,
- body: _.str.trim(data.content),
- subtype: 'mail.mt_comment',
- attachment_ids: data.attachment_ids,
- });
-}
-
-function post_document_message (model_name, res_id, data) {
- var values = {
- attachment_ids: data.attachment_ids,
- body: _.str.trim(data.content),
- content_subtype: data.content_subtype,
- context: data.context,
- message_type: data.message_type,
- partner_ids: data.partner_ids,
- subtype: data.subtype,
- subtype_id: data.subtype_id,
- };
-
- var model = new Model(model_name);
- return model.call('message_post', [res_id], values).then(function (msg_id) {
- return MessageModel.call('message_format', [msg_id]).then(function (msgs) {
- msgs[0].model = model_name;
- msgs[0].res_id = res_id;
- add_message(msgs[0]);
- });
- });
-}
-
function add_channel (data, options) {
options = typeof options === "object" ? options : {};
var channel = chat_manager.get_channel(data.id);
@@ -399,19 +416,13 @@ function on_needaction_notification (message) {
function on_channel_notification (message) {
var def;
- if ((message.channel_ids.length === 1) && !chat_manager.get_channel(message.channel_ids[0])) {
+ if (message.channel_ids.length === 1) {
def = chat_manager.join_channel(message.channel_ids[0], {autoswitch: false});
} else {
def = $.when();
}
def.then(function () {
- _.each(message.channel_ids, function (channel_id) {
- var channel = chat_manager.get_channel(channel_id);
- if (channel) {
- update_channel_unread_counter(channel, channel.unread_counter+1);
- }
- });
- add_message(message, { show_notification: true });
+ add_message(message, { show_notification: true, increment_unread: true });
invalidate_caches(message.channel_ids);
});
}
@@ -508,35 +519,75 @@ function on_chat_session_notification (chat_session) {
// Public interface
//----------------------------------------------------------------------------------
var chat_manager = {
- post_message: post_channel_message,
- post_message_in_document: post_document_message,
+ post_message: function (data, options) {
+ options = options || {};
+ var msg = {
+ partner_ids: data.partner_ids,
+ body: _.str.trim(data.content),
+ attachment_ids: data.attachment_ids,
+ };
+ if ('channel_id' in options) {
+ // post a message in a channel
+ return ChannelModel.call('message_post', [options.channel_id], _.extend(msg, {
+ message_type: 'comment',
+ content_subtype: 'html',
+ subtype: 'mail.mt_comment',
+ }));
+ }
+ if ('model' in options && 'res_id' in options) {
+ // post a message in a chatter
+ _.extend(msg, {
+ content_subtype: data.content_subtype,
+ context: data.context,
+ message_type: data.message_type,
+ subtype: data.subtype,
+ subtype_id: data.subtype_id,
+ });
+
+ var model = new Model(options.model);
+ return model.call('message_post', [options.res_id], msg).then(function (msg_id) {
+ return MessageModel.call('message_format', [msg_id]).then(function (msgs) {
+ msgs[0].model = options.model;
+ msgs[0].res_id = options.res_id;
+ add_message(msgs[0]);
+ });
+ });
+ }
+ },
get_messages: function (options) {
- if ('channel_id' in options) { // channel message
- var channel = this.get_channel(options.channel_id);
+ var channel;
+
+ if ('channel_id' in options && options.load_more) {
+ // get channel messages, force load_more
+ channel = this.get_channel(options.channel_id);
+ return fetch_from_channel(channel, {domain: options.domain || {}, load_more: true});
+ }
+ if ('channel_id' in options) {
+ // channel message, check in cache first
+ channel = this.get_channel(options.channel_id);
var channel_cache = get_channel_cache(channel, options.domain);
if (channel_cache.loaded) {
return $.when(channel_cache.messages);
} else {
return fetch_from_channel(channel, {domain: options.domain});
}
- } else { // chatter message
}
- },
- fetch: function (channel, domain) {
- return fetch_from_channel(channel, {domain: domain});
- },
- fetch_more: function (channel, domain) {
- return fetch_from_channel(channel, {domain: domain, load_more: true});
- },
- /**
- * Fetches chatter messages from their ids
- */
- fetch_messages: function (message_ids, options) {
- return fetch_document_messages(message_ids, options).then(function(result) {
- chat_manager.mark_as_read(message_ids);
- return result;
- });
+ if ('ids' in options) {
+ // get messages from their ids (chatter is the main use case)
+ return fetch_document_messages(options.ids, options).then(function(result) {
+ chat_manager.mark_as_read(options.ids);
+ return result;
+ });
+ }
+ if ('model' in options && 'res_id' in options) {
+ // get messages for a chatter, when it doesn't know the ids (use
+ // case is when using the full composer)
+ var domain = [['model', '=', options.model], ['res_id', '=', options.res_id]];
+ MessageModel.call('message_fetch', [domain], {limit: 30}).then(function (msgs) {
+ return _.map(msgs, add_message);
+ });
+ }
},
toggle_star_status: function (message_id) {
var msg = _.findWhere(messages, { id: message_id });
@@ -549,7 +600,8 @@ var chat_manager = {
mark_as_read: function (message_ids) {
var ids = _.filter(message_ids, function (id) {
var message = _.findWhere(messages, {id: id});
- return message.is_needaction;
+ // If too many messages, not all are fetched, and some might not be found
+ return !message || message.is_needaction;
});
if (ids.length) {
return MessageModel.call('set_message_done', [ids]);
@@ -638,15 +690,21 @@ var chat_manager = {
},
join_channel: function (channel_id, options) {
if (channel_id in channel_defs) {
+ // prevents concurrent calls to channel_join_and_get_info
return channel_defs[channel_id];
}
- var def = ChannelModel
- .call('channel_join_and_get_info', [[channel_id]])
- .then(function (result) {
- add_channel(result, options);
- });
- channel_defs[channel_id] = def;
- return def;
+ var channel = this.get_channel(channel_id);
+ if (channel) {
+ // channel already joined
+ channel_defs[channel_id] = $.when(channel);
+ } else {
+ channel_defs[channel_id] = ChannelModel
+ .call('channel_join_and_get_info', [[channel_id]])
+ .then(function (result) {
+ return add_channel(result, options);
+ });
+ }
+ return channel_defs[channel_id];
},
unsubscribe: function (channel) {
@@ -671,6 +729,38 @@ var chat_manager = {
channel.is_folded = !channel.is_folded;
});
},
+ /**
+ * Special redirection handling for given model and id
+ *
+ * If the model is res.partner, and there is a user associated with this
+ * partner which isn't the current user, open the DM with this user.
+ * Otherwhise, open the record's form view, if this is not the current user's.
+ */
+ redirect: function (res_model, res_id, dm_redirection_callback) {
+ var self = this;
+ var redirect_to_document = function (res_model, res_id) {
+ web_client.do_action({
+ type:'ir.actions.act_window',
+ view_type: 'form',
+ view_mode: 'form',
+ res_model: res_model,
+ views: [[false, 'form']],
+ res_id: res_id,
+ });
+ };
+ if (res_model === "res.partner") {
+ var domain = [["partner_id", "=", res_id]];
+ UserModel.call("search", [domain]).then(function (user_ids) {
+ if (user_ids.length && user_ids[0] !== session.uid) {
+ self.create_channel(res_id, 'dm').then(dm_redirection_callback || function () {});
+ } else if (!user_ids.length) {
+ redirect_to_document(res_model, res_id);
+ }
+ });
+ } else {
+ redirect_to_document(res_model, res_id);
+ }
+ },
};
// Initialization
diff --git a/addons/mail/static/src/js/chat_window.js b/addons/mail/static/src/js/chat_window.js
index 3936ef956e1..e9fcaa9fe09 100644
--- a/addons/mail/static/src/js/chat_window.js
+++ b/addons/mail/static/src/js/chat_window.js
@@ -37,9 +37,9 @@ return Widget.extend({
display_needactions: false,
display_stars: this.options.display_stars,
});
- this.thread.on('toggle_star_status', this, function (message_id) {
- this.trigger('toggle_star_status', message_id);
- });
+ this.thread.on('toggle_star_status', null, this.trigger.bind(this, 'toggle_star_status'));
+ this.thread.on('redirect_to_channel', null, this.trigger.bind(this, 'redirect_to_channel'));
+ this.thread.on('redirect', null, this.trigger.bind(this, 'redirect'));
this.fold();
var def = this.thread.appendTo(this.$content);
@@ -67,8 +67,8 @@ return Widget.extend({
height: this.folded ? "28px" : "333px"
});
},
- toggle_fold: function () {
- this.folded = !this.folded;
+ toggle_fold: function (fold) {
+ this.folded = _.isBoolean(fold) ? fold : !this.folded;
if (!this.folded) {
this.unread_msgs = 0;
this.trigger('messages_read');
@@ -82,10 +82,9 @@ return Widget.extend({
content: this.$input.val(),
attachment_ids: [],
partner_ids: [],
- channel_id: this.channel_id,
};
this.$input.val('');
- this.trigger('post_message', message);
+ this.trigger('post_message', message, this.channel_id);
}
},
on_click_close: function (event) {
diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js
index d29312cf6f6..c99e958929e 100644
--- a/addons/mail/static/src/js/chatter.js
+++ b/addons/mail/static/src/js/chatter.js
@@ -189,14 +189,9 @@ var Followers = form_common.AbstractField.extend({
},
fetch_followers: function (value_) {
- var self = this;
this.value = value_ || [];
return ajax.jsonRpc('/mail/read_followers', 'call', {'follower_ids': this.value})
- .then(function (followers) {
- self.trigger('followers_update', followers);
- self.display_followers(followers);
- self.fetch_generic();
- })
+ .then(this.proxy('display_followers'), this.proxy('fetch_generic'))
.then(this.proxy('display_buttons'))
.then(this.proxy('fetch_subtypes'));
},
@@ -237,6 +232,7 @@ var Followers = form_common.AbstractField.extend({
display_followers: function (records) {
var self = this;
this.followers = records || this.followers;
+ this.trigger('followers_update', this.followers);
// clean and display title
var $followers_list = this.$('.o_followers_list').empty();
@@ -272,25 +268,25 @@ var Followers = form_common.AbstractField.extend({
}
},
- /** Fetch subtypes, only if current user is follower */
+ /** Fetch subtypes, only if current user is follower or if follower_id is given, i.e. if
+ * the current user is editing the subtypes of another follower
+ */
fetch_subtypes: function (follower_id) {
var self = this;
var dialog = false;
if (follower_id) {
dialog = true;
- }
- else {
+ } else {
this.$('.o_subtypes_list ul').empty();
- if (! this.message_is_follower) {
+ if (!this.message_is_follower) {
this.$('.o_subtypes_list > .dropdown-toggle').attr('disabled', true);
return;
- }
- else {
+ } else {
this.$('.o_subtypes_list > .dropdown-toggle').attr('disabled', false);
}
}
- if (this.follower_id) {
+ if (this.follower_id || follower_id) {
return ajax.jsonRpc('/mail/read_subscription_data', 'call', {
res_model: this.view.model,
res_id: this.view.datarecord.id,
@@ -305,7 +301,6 @@ var Followers = form_common.AbstractField.extend({
/** Display subtypes: {'name': default, followed} */
display_subtypes:function (data, dialog) {
- var self = this;
var old_parent_model;
var $list;
if (dialog) {
@@ -316,10 +311,10 @@ var Followers = form_common.AbstractField.extend({
$list.empty();
this.data_subtype = data;
- this.records_length = $.map(data, function(value, index) { return index; }).length;
+ this.records_length = _.map(data, function(value, index) { return index; }).length;
if (this.records_length > 1) {
- self.display_followers();
+ this.display_followers();
}
_.each(data, function (record) {
@@ -674,6 +669,8 @@ var ChatterComposer = ChatComposer.extend({
}, {
on_close: function() {
self.trigger('need_refresh');
+ var parent = self.getParent();
+ chat_manager.get_messages({model: parent.model, res_id: parent.res_id});
},
});
});
@@ -719,6 +716,7 @@ var Chatter = form_common.AbstractField.extend({
display_order: ChatThread.ORDER.DESC,
display_document_link: false,
display_needactions: false,
+ squash_close_messages: false,
});
this.thread.on('load_more_messages', this, this.load_more_messages);
this.thread.on('toggle_star_status', this, function (message_id) {
@@ -741,15 +739,18 @@ var Chatter = form_common.AbstractField.extend({
fetch_and_render_thread: function (ids, options) {
var self = this;
- return chat_manager.fetch_messages(ids, options).then(function (raw_messages) {
+ options = options || {};
+ options.ids = ids;
+ return chat_manager.get_messages(options).then(function (raw_messages) {
self.thread.render(raw_messages, {display_load_more: raw_messages.length < ids.length});
});
},
on_post_message: function (message) {
var self = this;
+ var options = {model: this.model, res_id: this.res_id};
chat_manager
- .post_message_in_document(this.model, this.res_id, message)
+ .post_message(message, options)
.then(function () {
self.close_composer();
if (message.partner_ids.length) {
@@ -781,12 +782,7 @@ var Chatter = form_common.AbstractField.extend({
on_channel_redirect: function (channel_id) {
var self = this;
- var def;
- var channel = chat_manager.get_channel(channel_id);
- // If not registered to 'channel' yet, do it
- if (!channel) {
- def = chat_manager.join_channel(channel_id);
- }
+ var def = chat_manager.join_channel(channel_id);
$.when(def).then(function () {
// Execute Discuss client action with 'channel' as default channel
var discuss_ids = chat_manager.get_discuss_ids();
diff --git a/addons/mail/static/src/js/client_action.js b/addons/mail/static/src/js/client_action.js
index b96e9af6777..ae032b4ece1 100644
--- a/addons/mail/static/src/js/client_action.js
+++ b/addons/mail/static/src/js/client_action.js
@@ -190,14 +190,11 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
});
this.$buttons.on('click', '.o_mail_chat_button_unstar_all', chat_manager.unstar_all);
- this.thread.on('redirect', this, this.on_redirect);
+ this.thread.on('redirect', this, function (res_model, res_id) {
+ chat_manager.redirect(res_model, res_id, this.set_channel.bind(this));
+ });
this.thread.on('redirect_to_channel', this, function (channel_id) {
- var channel = chat_manager.get_channel(channel_id);
- if (channel) {
- this.set_channel(channel);
- } else {
- chat_manager.join_channel(channel_id);
- }
+ chat_manager.join_channel(channel_id).then(this.set_channel.bind(this));
});
this.thread.on('load_more_messages', this, this.load_more_messages);
this.thread.on('mark_as_read', this, function (message_id) {
@@ -375,7 +372,6 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
self.$buttons
.find('.o_mail_chat_button_unstar_all')
.toggle(channel.id === "channel_starred");
- self.update_cp();
self.$('.o_chat_composer').toggle(channel.type !== 'static');
@@ -393,6 +389,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
self.$('.o_mail_chat_sidebar').hide();
}
+ self.update_cp();
self.action_manager.do_push_state({
action: self.action.id,
active_id: self.channel.id,
@@ -466,7 +463,7 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
var oldest_msg_selector = '.o_thread_message[data-message-id="' + oldest_msg_id + '"]';
var offset = -framework.getPosition(document.querySelector(oldest_msg_selector)).top;
return chat_manager
- .fetch_more(this.channel, this.domain)
+ .get_messages({channel_id: this.channel.id, domain: this.domain, load_more: true})
.then(function(result) {
if (self.messages_separator_position === 'top') {
self.messages_separator_position = undefined; // reset value to re-compute separator position
@@ -489,6 +486,15 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
});
},
+ do_show: function () {
+ this._super.apply(this, arguments);
+ this.update_cp();
+ this.action_manager.do_push_state({
+ action: this.action.id,
+ active_id: this.channel.id,
+ });
+ },
+
on_search: function (domains) {
var result = pyeval.sync_eval_domains_and_contexts({
domains: domains
@@ -498,60 +504,10 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
this.fetch_and_render_thread();
},
- /**
- * Callback performed on o_mail_redirect element clicked
- *
- * If the model is res.partner, and there is a user associated with this
- * partner which isn't the current user, open the DM with this user.
- * Otherwhise, open the record's form view.
- */
- on_redirect: function (res_model, res_id) {
- var self = this;
- var redirect_to_document = function (res_model, res_id) {
- self.action_manager.do_push_state({
- model: res_model,
- id: res_id,
- });
- self.do_action({
- type:'ir.actions.act_window',
- view_type: 'form',
- view_mode: 'form',
- res_model: res_model,
- views: [[false, 'form']],
- res_id: res_id,
- }, {
- on_reverse_breadcrumb: self.on_reverse_breadcrumb,
- });
- };
-
- if (res_model === "res.partner") {
- var domain = [["partner_id", "=", res_id]];
- new Model('res.users').call("search", [domain]).then(function (user_ids) {
- if (user_ids.length && user_ids[0] !== session.uid) {
- chat_manager.create_channel(res_id, 'dm').then(function (channel) {
- if (!self.channel || self.channel.id !== channel.id) {
- self.set_channel(channel);
- }
- });
- } else {
- redirect_to_document(res_model, res_id);
- }
- });
- } else {
- redirect_to_document(res_model, res_id);
- }
- },
- on_reverse_breadcrumb: function () {
- this.update_cp(); // do not reload the client action, just display it, but a refresh of the control panel is needed.
- this.action_manager.do_push_state({
- action: this.action.id,
- active_id: this.channel.id,
- });
- },
on_post_message: function (message) {
- message.channel_id = this.channel.id;
+ var options = {channel_id: this.channel.id};
chat_manager
- .post_message(message)
+ .post_message(message, options)
.fail(function () {
// todo: display notification
});
@@ -615,8 +571,6 @@ var ChatAction = Widget.extend(ControlPanelMixin, {
res_id: this.channel.id,
views: [[false, 'form']],
target: 'current'
- }, {
- on_reverse_breadcrumb: this.on_reverse_breadcrumb,
});
},
});
diff --git a/addons/mail/static/src/js/composer.js b/addons/mail/static/src/js/composer.js
index 24257d1a72a..971c2e99c69 100644
--- a/addons/mail/static/src/js/composer.js
+++ b/addons/mail/static/src/js/composer.js
@@ -23,6 +23,7 @@ var accented_letters_mapping = {
'oe': 'œ',
'u': '[ùúûűü]',
'y': '[ýÿ]',
+ ' ': '[()\\[\\]]',
};
// The MentionManager allows the Composer to register listeners. For each
@@ -218,7 +219,8 @@ var MentionManager = Widget.extend({
*/
generate_links: function (s) {
var self = this;
- var mention_link = "<a href='#' class='%s' data-oe-id='%s' data-oe-model='%s'>%s%s</a>";
+ var base_href = session.url("/web");
+ var mention_link = "<a href='%s' class='%s' data-oe-id='%s' data-oe-model='%s' target='_blank'>%s%s</a>";
_.each(this.listeners, function (listener) {
var selection = listener.selection;
if (selection.length) {
@@ -229,7 +231,8 @@ var MentionManager = Widget.extend({
var match = matches[i];
var end_index = match.index + match[0].length;
var match_name = match[0].substring(1);
- var processed_text = _.str.sprintf(mention_link, listener.redirect_classname, selection[i].id, listener.model, listener.delimiter, match_name);
+ var href = base_href + _.str.sprintf("#model=%s&id=%s", listener.model, selection[i].id);
+ var processed_text = _.str.sprintf(mention_link, href, listener.redirect_classname, selection[i].id, listener.model, listener.delimiter, match_name);
var subtext = s.substring(start_index, end_index).replace(match[0], processed_text);
substrings.push(subtext);
start_index = end_index;
diff --git a/addons/mail/static/src/js/thread.js b/addons/mail/static/src/js/thread.js
index a1f8fc8a076..86b34255cf7 100644
--- a/addons/mail/static/src/js/thread.js
+++ b/addons/mail/static/src/js/thread.js
@@ -34,8 +34,9 @@ var Thread = Widget.extend({
this.$('.o_thread_message').removeClass('o_thread_selected_message');
$(event.currentTarget).toggleClass('o_thread_selected_message', !selected);
},
- "click span.oe_mail_expand": function (event) {
+ "click .oe_mail_expand": function (event) {
event.preventDefault();
+ event.stopPropagation();
var $source = $(event.currentTarget);
$source.parents('.o_thread_message_core').find('.o_mail_body_short').toggle();
$source.parents('.o_thread_message_core').find('.o_mail_body_long').toggle();
@@ -118,12 +119,13 @@ var Thread = Widget.extend({
msg.hour = msg.date.fromNow();
} else if (date === moment().subtract(1, 'days').format('YYYY-MM-DD')) {
msg.day = _t("Yesterday");
- msg.hour = msg.date.format('hh:mm');
+ msg.hour = msg.date.format('LT');
} else {
msg.day = msg.date.format('LL');
- msg.hour = msg.date.format('hh:mm');
+ msg.hour = msg.date.format('LT');
}
+ msg.display_subject = message.subject && message.message_type !== 'notification' && !(message.model && (message.model !== 'mail.channel'));
return msg;
},
diff --git a/addons/mail/static/src/js/window_manager.js b/addons/mail/static/src/js/window_manager.js
index 22eb60f9180..5a62c15ed8b 100644
--- a/addons/mail/static/src/js/window_manager.js
+++ b/addons/mail/static/src/js/window_manager.js
@@ -37,12 +37,25 @@ function open_chat (session) {
chat_manager.fold_channel(channel_id);
});
- chat_session.window.on("post_message", null, function (message) {
- chat_manager.post_message(message);
+ chat_session.window.on("post_message", null, function (message, channel_id) {
+ chat_manager.post_message(message, {channel_id: channel_id});
});
chat_session.window.on("messages_read", null, function () {
chat_manager.mark_channel_as_seen(channel);
});
+ chat_session.window.on("redirect", null, function (res_model, res_id) {
+ chat_manager.redirect(res_model, res_id, open_chat);
+ });
+ chat_session.window.on("redirect_to_channel", null, function (channel_id) {
+ var session = _.findWhere(chat_sessions, {id: channel_id});
+ if (!session) {
+ chat_manager.join_channel(channel_id).then(function (channel) {
+ chat_manager.detach_channel(channel);
+ });
+ } else {
+ session.window.toggle_fold(false);
+ }
+ });
chat_sessions.push(chat_session);
chat_session.window.appendTo($('body'))