From 33ac65c805c30fafac4e2cf5490c57c7eaf74b4a Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Mon, 30 Nov 2015 10:30:02 +0100 Subject: [PATCH] [FIX] mail: redirection handling in chat windows - clicking on a channel mention (or a user) from a chat window opens a new chat window for that channel - clicking on any other link in a chat window correctly opens the corresponding document 2 minor changes were required: - use do_show() instead of on_reverse_breadcrumb() to update control panel and url in client action, as other actions can be stacked over the client action, e.g. by clicking on a document link in a chat window. In that case, the on_reverse_breadcrumb callback wouldn't be set, and thus the control panel and url wouldn't be updated by coming back to client action using the breadcrumbs. - channel_join() now checks whether or not the channel has already been joined (i.e. if it is in the JS cache) before performing the RPC. This check was performed by each caller, so this simplifies the code. --- addons/mail/static/src/js/chat_manager.js | 55 ++++++++++++--- addons/mail/static/src/js/chat_window.js | 10 +-- addons/mail/static/src/js/chatter.js | 7 +- addons/mail/static/src/js/client_action.js | 74 ++++----------------- addons/mail/static/src/js/window_manager.js | 13 ++++ 5 files changed, 80 insertions(+), 79 deletions(-) diff --git a/addons/mail/static/src/js/chat_manager.js b/addons/mail/static/src/js/chat_manager.js index e8a2ad3951e..adf1b5f6b57 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 //---------------------------------------------------------------------------------- @@ -399,7 +400,7 @@ 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(); @@ -638,15 +639,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 +678,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..6166c4bce3d 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'); diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js index d29312cf6f6..d812d2093ad 100644 --- a/addons/mail/static/src/js/chatter.js +++ b/addons/mail/static/src/js/chatter.js @@ -781,12 +781,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 e4908188122..a1ecb7b8003 100644 --- a/addons/mail/static/src/js/client_action.js +++ b/addons/mail/static/src/js/client_action.js @@ -179,14 +179,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) { @@ -364,7 +361,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'); @@ -382,6 +378,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, @@ -478,6 +475,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 @@ -487,56 +493,6 @@ 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; chat_manager @@ -604,8 +560,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/window_manager.js b/addons/mail/static/src/js/window_manager.js index 22eb60f9180..65bc7ba8e91 100644 --- a/addons/mail/static/src/js/window_manager.js +++ b/addons/mail/static/src/js/window_manager.js @@ -43,6 +43,19 @@ function open_chat (session) { 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'))