From 58e064d0782a91f760b29aac14e43460dd87ecf0 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Fri, 30 Aug 2013 16:48:24 +0200 Subject: [PATCH 1/7] Added sessions server-side bzr revid: nicolas.vanhoren@openerp.com-20130830144824-xabc1du6qss9wjv2 --- addons/im/im.py | 43 ++++++++++++++++++++++++++++++++++++------- addons/im/watcher.py | 5 +++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index 534991b8fc8..f34a66fc56f 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -140,19 +140,23 @@ class im_message(osv.osv): _order = "date desc" _columns = { - 'message': fields.char(string="Message", size=200, required=True), + 'message': fields.text(string="Message", required=True), 'from_id': fields.many2one("im.user", "From", required= True, ondelete='cascade'), - 'to_id': fields.many2one("im.user", "To", required=True, select=True, ondelete='cascade'), + 'session_id': fields.many2one("im.session", "Session", required=True, select=True, ondelete='cascade'), + 'to_id': fields.many2many("im.user", "To"), 'date': fields.datetime("Date", required=True, select=True), + 'technical': fields.boolean("Technical Message"), } _defaults = { 'date': lambda *args: datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT), + 'technical': False, } def get_messages(self, cr, uid, last=None, users_watch=None, uuid=None, context=None): assert_uuid(uuid) users_watch = users_watch or [] + session_ids = session_ids or [] # complex stuff to determine the last message to show users = self.pool.get("im.user") @@ -165,8 +169,8 @@ class im_message(osv.osv): last = c_user.im_last_received or -1 # how fun it is to always need to reorder results from read - mess_ids = self.search(cr, openerp.SUPERUSER_ID, [['id', '>', last], ['to_id', '=', my_id]], order="id", context=context) - mess = self.read(cr, openerp.SUPERUSER_ID, mess_ids, ["id", "message", "from_id", "date"], context=context) + mess_ids = self.search(cr, openerp.SUPERUSER_ID, ["&", ['id', '>', last], "|", ['from_id', '=', my_id], ['to_id', 'in', [my_id]]], order="id", context=context) + mess = self.read(cr, openerp.SUPERUSER_ID, mess_ids, ["id", "message", "from_id", "session_id", "date"], context=context) index = {} for i in xrange(len(mess)): index[mess[i]["id"]] = mess[i] @@ -179,13 +183,38 @@ class im_message(osv.osv): users_status = users.read(cr, openerp.SUPERUSER_ID, users_watch, ["im_status"], context=context) return {"res": mess, "last": last, "dbname": cr.dbname, "users_status": users_status} - def post(self, cr, uid, message, to_user_id, uuid=None, context=None): + def post(self, cr, uid, message, to_session_id, uuid=None, context=None): assert_uuid(uuid) my_id = self.pool.get('im.user').get_my_id(cr, uid, uuid) - self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id, 'to_id': to_user_id}, context=context) - notify_channel(cr, "im_channel", {'type': 'message', 'receiver': to_user_id}) + session = self.pool.get('im.session').browse(cr, uid, to_session_id, context) + to_ids = [x.id for x in session.user_ids if x != my_id] + self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id, 'to_id': to_ids}, context=context) + notify_channel(cr, "im_channel", {'type': 'message', 'receivers': to_user_id}) return False +class im_session(osv.osv): + _name = 'im.session' + _columns = { + 'user_ids': fields.many2many('im.user'), + } + + # Todo: reuse existing sessions if possible + def session_get(self, cr, uid, user_to, uuid=None, context=None): + my_id = self.pool.get("im.user").get_my_id(cr, uid, uuid, context=context) + session_id = None + if user_to: + # FP Note: does the ORM allows something better than this? == on many2many + sids = self.search(cr, uid, [('user_ids', 'in', [user_to]), ('user_ids', 'in', [my_id])], context=context, limit=1) + for session in self.browse(cr, uid, sids, context=context): + if len(session.user_ids) == 2: + session_id = session.id + break + if not session_id: + session_id = self.create(cr, uid, { + 'user_ids': [(6, 0, (user_to, uid))] + }, context=context) + return self.read(cr, uid, session_id, context=context) + class im_user(osv.osv): _name = "im.user" diff --git a/addons/im/watcher.py b/addons/im/watcher.py index b8cb74df5ba..c733b189778 100644 --- a/addons/im/watcher.py +++ b/addons/im/watcher.py @@ -51,8 +51,9 @@ class ImWatcher(object): def handle_message(self, message): if message["type"] == "message": - for waiter in self.users.get(message["receiver"], {}).values(): - waiter.set() + for receiver in message["receivers"]: + for waiter in self.users.get(receiver, {}).values(): + waiter.set() else: #type status for waiter in self.users_watch.get(message["user"], {}).values(): waiter.set() From 4dc6ac8da488cde4b56766bc0ed12ea3fb052133 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 2 Sep 2013 11:31:04 +0200 Subject: [PATCH 2/7] wip bzr revid: nicolas.vanhoren@openerp.com-20130902093104-pmeo49m2u5mud8bb --- addons/im/im.py | 7 +- addons/im/security/im_security.xml | 21 ++- addons/im/security/ir.model.access.csv | 3 +- addons/im/static/src/js/im.js | 5 +- addons/im/static/src/js/im_common.js | 140 +++++++++++------- addons/im/static/src/xml/im_common.xml | 4 +- addons/im_livechat/im_livechat.py | 3 +- addons/im_livechat/im_livechat_view.xml | 2 + .../security/im_livechat_security.xml | 2 + 9 files changed, 116 insertions(+), 71 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index f34a66fc56f..919a196db2e 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -143,7 +143,7 @@ class im_message(osv.osv): 'message': fields.text(string="Message", required=True), 'from_id': fields.many2one("im.user", "From", required= True, ondelete='cascade'), 'session_id': fields.many2one("im.session", "Session", required=True, select=True, ondelete='cascade'), - 'to_id': fields.many2many("im.user", "To"), + 'to_id': fields.many2many("im.user", "im_message_users", 'message_id', 'user_id', 'To'), 'date': fields.datetime("Date", required=True, select=True), 'technical': fields.boolean("Technical Message"), } @@ -156,7 +156,6 @@ class im_message(osv.osv): def get_messages(self, cr, uid, last=None, users_watch=None, uuid=None, context=None): assert_uuid(uuid) users_watch = users_watch or [] - session_ids = session_ids or [] # complex stuff to determine the last message to show users = self.pool.get("im.user") @@ -188,8 +187,8 @@ class im_message(osv.osv): my_id = self.pool.get('im.user').get_my_id(cr, uid, uuid) session = self.pool.get('im.session').browse(cr, uid, to_session_id, context) to_ids = [x.id for x in session.user_ids if x != my_id] - self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id, 'to_id': to_ids}, context=context) - notify_channel(cr, "im_channel", {'type': 'message', 'receivers': to_user_id}) + self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id, 'to_id': to_ids, 'session_id': to_session_id}, context=context) + notify_channel(cr, "im_channel", {'type': 'message', 'receivers': to_ids}) return False class im_session(osv.osv): diff --git a/addons/im/security/im_security.xml b/addons/im/security/im_security.xml index a964855ccf9..c99b7ec96e1 100644 --- a/addons/im/security/im_security.xml +++ b/addons/im/security/im_security.xml @@ -5,11 +5,11 @@ Can only read messages that you sent or messages sent to you - ["|", ('to_id.user_id', '=', user.id), ('from_id.user_id', '=', user.id)] - - + ["|", ('to_id.user_id', 'in', [user.id]), ('from_id.user_id', '=', user.id)] + + @@ -17,10 +17,21 @@ [('user_id', '=', user.id)] - - + + + + + + Can modify sessions if you are in it. + + + [('user_ids', 'in', [user.id])] + + + + diff --git a/addons/im/security/ir.model.access.csv b/addons/im/security/ir.model.access.csv index db3fe77f690..87593f28ea2 100644 --- a/addons/im/security/ir.model.access.csv +++ b/addons/im/security/ir.model.access.csv @@ -1,3 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_im_message,im.message,model_im_message,base.group_user,1,0,1,0 -access_im_user,im.user,model_im_user,,1,1,1,0 \ No newline at end of file +access_im_user,im.user,model_im_user,,1,1,1,0 +access_im_session,im.session,model_im_session,base.group_user,1,1,1,0 \ No newline at end of file diff --git a/addons/im/static/src/js/im.js b/addons/im/static/src/js/im.js index 63ab694a723..4f49464693c 100644 --- a/addons/im/static/src/js/im.js +++ b/addons/im/static/src/js/im.js @@ -125,7 +125,10 @@ this.shown = ! this.shown; }, activate_user: function(user) { - this.c_manager.activate_user(user, true); + var self = this; + im_common.connection.model("im.session").call("session_get", [user.get("id"), self.c_manager.me.get("uuid")]).then(function(session) { + self.c_manager.activate_session(session.id, true); + }); }, }); diff --git a/addons/im/static/src/js/im_common.js b/addons/im/static/src/js/im_common.js index 9e5e13a9099..6d88764b1d8 100644 --- a/addons/im/static/src/js/im_common.js +++ b/addons/im/static/src/js/im_common.js @@ -67,7 +67,6 @@ function declare($, _, openerp) { this.set("right_offset", 0); this.set("bottom_offset", 0); this.conversations = []; - this.users = {}; this.on("change:right_offset", this, this.calc_positions); this.on("change:bottom_offset", this, this.calc_positions); this.set("window_focus", true); @@ -178,12 +177,7 @@ function declare($, _, openerp) { self.get_user(el.id).set(el); }); self.last = result.last; - var user_ids = _.pluck(_.pluck(result.res, "from_id"), 0); - self.ensure_users(user_ids).then(function() { - _.each(result.res, function(mes) { - var user = self.get_user(mes.from_id[0]); - self.received_message(mes, user); - }); + self.received_messages(result.res).then(function() { self.poll(); }); }, function(unused, e) { @@ -217,32 +211,41 @@ function declare($, _, openerp) { openerp.webclient.set_title_part("im_messages", this.get("waiting_messages") === 0 ? undefined : _.str.sprintf(_t("%d Messages"), this.get("waiting_messages"))); }, - activate_user: function(user, focus) { - var conv = this.users[user.get('id')]; + activate_session: function(session_id, focus) { + var conv = _.find(this.conversations, function(conv) {return conv.session_id == session_id;}); + var def = $.when(); if (! conv) { - conv = new im_common.Conversation(this, user, this.me, this.options); - conv.appendTo($("body")); - conv.on("destroyed", this, function() { - this.conversations = _.without(this.conversations, conv); - delete this.users[conv.user.get('id')]; + conv = new im_common.Conversation(this, this, session_id, this.options); + def = conv.appendTo($("body")).then(_.bind(function() { + conv.on("destroyed", this, function() { + this.conversations = _.without(this.conversations, conv); + this.calc_positions(); + }); + this.conversations.push(conv); this.calc_positions(); - }); - this.conversations.push(conv); - this.users[user.get('id')] = conv; - this.calc_positions(); + }, this)); } - if (focus) - conv.focus(); - return conv; + if (focus) { + def = def.then(function() { + conv.focus(); + }); + } + return def.then(function() {return conv}); }, - received_message: function(message, user) { - if (! this.get("window_focus")) { - this.set("waiting_messages", this.get("waiting_messages") + 1); + received_messages: function(messages) { + var self = this; + if (! this.get("window_focus") && messages.length >= 1) { + this.set("waiting_messages", this.get("waiting_messages") + messages.length); this.ting.play(); this.create_ting(); } - var conv = this.activate_user(user); - conv.received_message(message); + var defs = []; + _.each(messages, function(message) { + defs.push(self.activate_session(message.session_id[0]).then(function(conv) { + return conv.received_message(message); + })); + }); + return $.when.apply($, defs); }, calc_positions: function() { var current = this.get("right_offset"); @@ -267,39 +270,52 @@ function declare($, _, openerp) { "click .oe_im_chatview_close": "destroy", "click .oe_im_chatview_header": "show_hide" }, - init: function(parent, user, me, options) { + init: function(parent, c_manager, session_id, options) { this._super(parent); - this.options = options; - this.me = me; - this.user = user; - this.user.add_watcher(); + this.c_manager = c_manager; + this.options = options || {}; + this.session_id = session_id; this.set("right_position", 0); this.set("bottom_position", 0); this.shown = true; this.set("pending", 0); this.inputPlaceholder = this.options.defaultInputPlaceholder; + this.users = []; + this.others = []; }, start: function() { - this.$().append(openerp.qweb.render("im_common.conversation", {widget: this, to_url: _.bind(im_common.connection.url, im_common.connection)})); - var change_status = function() { - this.$().toggleClass("oe_im_chatview_disconnected_status", this.user.get("im_status") === false); - this.$(".oe_im_chatview_online").toggle(this.user.get("im_status") === true); - this._go_bottom(); - }; - this.user.on("change:im_status", this, change_status); - change_status.call(this); + var self = this; + var user_ids; + return im_common.connection.model("im.session").call("read", [self.session_id]).then(function(session) { + user_ids = _.without(session.user_ids, self.c_manager.me.get("id")); + return self.c_manager.ensure_users(session.user_ids); + }).then(function() { + self.users = _.map(user_ids, function(id) {return self.c_manager.get_user(id);}); + _.each(self.users, function(user) { + user.add_watcher(); + }); + // TODO: correctly display status + self.$().append(openerp.qweb.render("im_common.conversation", {widget: self, to_url: _.bind(im_common.connection.url, im_common.connection)})); + var change_status = function() { + self.$().toggleClass("oe_im_chatview_disconnected_status", self.users[0].get("im_status") === false); + self.$(".oe_im_chatview_online").toggle(self.users[0].get("im_status") === true); + self._go_bottom(); + }; + self.users[0].on("change:im_status", self, change_status); + change_status.call(self); - this.on("change:right_position", this, this.calc_pos); - this.on("change:bottom_position", this, this.calc_pos); - this.full_height = this.$().height(); - this.calc_pos(); - this.on("change:pending", this, _.bind(function() { - if (this.get("pending") === 0) { - this.$(".oe_im_chatview_nbr_messages").text(""); - } else { - this.$(".oe_im_chatview_nbr_messages").text("(" + this.get("pending") + ")"); - } - }, this)); + self.on("change:right_position", self, self.calc_pos); + self.on("change:bottom_position", self, self.calc_pos); + self.full_height = self.$().height(); + self.calc_pos(); + self.on("change:pending", self, _.bind(function() { + if (self.get("pending") === 0) { + self.$(".oe_im_chatview_nbr_messages").text(""); + } else { + self.$(".oe_im_chatview_nbr_messages").text("(" + self.get("pending") + ")"); + } + }, self)); + }); }, show_hide: function() { if (this.shown) { @@ -326,7 +342,14 @@ function declare($, _, openerp) { } else { this.set("pending", this.get("pending") + 1); } - this._add_bubble(this.user, message.message, openerp.str_to_datetime(message.date)); + this.c_manager.ensure_users([message.from_id[0]]).then(_.bind(function() { + var user = this.c_manager.get_user(message.from_id[0]); + if (! _.contains(this.users, user) && ! _.contains(this.others, user)) { + this.others.push(user); + user.add_watcher(); + } + this._add_bubble(user, message.message, openerp.str_to_datetime(message.date)); + }, this)); }, send_message: function(e) { if(e && e.which !== 13) { @@ -339,17 +362,15 @@ function declare($, _, openerp) { this.$("input").val(""); var send_it = _.bind(function() { var model = im_common.connection.model("im.message"); - return model.call("post", [mes, this.user.get('id')], {uuid: this.me.get("uuid"), context: {}}); + return model.call("post", [mes, this.session_id], {uuid: this.c_manager.me.get("uuid"), context: {}}); }, this); var tries = 0; - send_it().then(_.bind(function() { - this._add_bubble(this.me, mes, new Date()); - }, this), function(error, e) { + send_it().then(_.bind(function() {}, function(error, e) { e.preventDefault(); tries += 1; if (tries < 3) return send_it(); - }); + })); }, _add_bubble: function(user, item, date) { var items = [item]; @@ -378,7 +399,12 @@ function declare($, _, openerp) { this.show_hide(); }, destroy: function() { - this.user.remove_watcher(); + _.each(this.users, function(user) { + user.remove_watcher(); + }) + _.each(this.others, function(user) { + user.remove_watcher(); + }) this.trigger("destroyed"); return this._super(); } diff --git a/addons/im/static/src/xml/im_common.xml b/addons/im/static/src/xml/im_common.xml index 4286d0c9710..0cf788aab49 100644 --- a/addons/im/static/src/xml/im_common.xml +++ b/addons/im/static/src/xml/im_common.xml @@ -4,12 +4,12 @@
- +
- +
diff --git a/addons/im_livechat/im_livechat.py b/addons/im_livechat/im_livechat.py index a47f87a9fd2..cec546c8b8c 100644 --- a/addons/im_livechat/im_livechat.py +++ b/addons/im_livechat/im_livechat.py @@ -198,7 +198,7 @@ class im_livechat_channel(osv.osv): self.write(cr, uid, ids, {'user_ids': [(3, uid)]}) return True - +""" class im_message(osv.osv): _inherit = 'im.message' @@ -244,3 +244,4 @@ class im_message(osv.osv): 'direction': fields.function(_direction, type="selection", selection=[("s2c", "Support Member to Customer"), ("c2s", "Customer to Support Member")], string='Direction', store=False), } +""" diff --git a/addons/im_livechat/im_livechat_view.xml b/addons/im_livechat/im_livechat_view.xml index 65401f3b88f..a5e3de898ae 100644 --- a/addons/im_livechat/im_livechat_view.xml +++ b/addons/im_livechat/im_livechat_view.xml @@ -120,6 +120,7 @@ + diff --git a/addons/im_livechat/security/im_livechat_security.xml b/addons/im_livechat/security/im_livechat_security.xml index 9088d0ed3db..b7185584394 100644 --- a/addons/im_livechat/security/im_livechat_security.xml +++ b/addons/im_livechat/security/im_livechat_security.xml @@ -21,6 +21,7 @@ + From 9a8fe95a5cf616a9d9ec69e3b9ffb6261fddc465 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 2 Sep 2013 11:51:51 +0200 Subject: [PATCH 3/7] Get back a working version bzr revid: nicolas.vanhoren@openerp.com-20130902095151-0etexao0jbdiymry --- addons/im/im.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index 919a196db2e..aa659e9bcd0 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -186,9 +186,9 @@ class im_message(osv.osv): assert_uuid(uuid) my_id = self.pool.get('im.user').get_my_id(cr, uid, uuid) session = self.pool.get('im.session').browse(cr, uid, to_session_id, context) - to_ids = [x.id for x in session.user_ids if x != my_id] - self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id, 'to_id': to_ids, 'session_id': to_session_id}, context=context) - notify_channel(cr, "im_channel", {'type': 'message', 'receivers': to_ids}) + to_ids = [x.id for x in session.user_ids if x.id != my_id] + self.create(cr, openerp.SUPERUSER_ID, {"message": message, 'from_id': my_id, 'to_id': [(6, 0, to_ids)], 'session_id': to_session_id}, context=context) + notify_channel(cr, "im_channel", {'type': 'message', 'receivers': [my_id] + to_ids}) return False class im_session(osv.osv): From 9071d01a289e202f86f20e8799c229878cfa0ccc Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 2 Sep 2013 14:23:11 +0200 Subject: [PATCH 4/7] wip bzr revid: nicolas.vanhoren@openerp.com-20130902122311-gopkikbta9dg7cne --- addons/im/im.py | 6 +- addons/im/security/im_security.xml | 11 ---- addons/im/security/ir.model.access.csv | 2 +- addons/im_livechat/im_livechat.py | 61 +++++-------------- .../static/ext/static/js/livesupport.js | 9 ++- 5 files changed, 22 insertions(+), 67 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index aa659e9bcd0..b9bb957fce2 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -203,14 +203,14 @@ class im_session(osv.osv): session_id = None if user_to: # FP Note: does the ORM allows something better than this? == on many2many - sids = self.search(cr, uid, [('user_ids', 'in', [user_to]), ('user_ids', 'in', [my_id])], context=context, limit=1) + sids = self.search(cr, openerp.SUPERUSER_ID, [('user_ids', 'in', [user_to]), ('user_ids', 'in', [my_id])], context=context, limit=1) for session in self.browse(cr, uid, sids, context=context): if len(session.user_ids) == 2: session_id = session.id break if not session_id: - session_id = self.create(cr, uid, { - 'user_ids': [(6, 0, (user_to, uid))] + session_id = self.create(cr, openerp.SUPERUSER_ID, { + 'user_ids': [(6, 0, [user_to, my_id])] }, context=context) return self.read(cr, uid, session_id, context=context) diff --git a/addons/im/security/im_security.xml b/addons/im/security/im_security.xml index c99b7ec96e1..d6b854c8a98 100644 --- a/addons/im/security/im_security.xml +++ b/addons/im/security/im_security.xml @@ -22,16 +22,5 @@ - - - Can modify sessions if you are in it. - - - [('user_ids', 'in', [user.id])] - - - - - diff --git a/addons/im/security/ir.model.access.csv b/addons/im/security/ir.model.access.csv index 87593f28ea2..651aa68c1bb 100644 --- a/addons/im/security/ir.model.access.csv +++ b/addons/im/security/ir.model.access.csv @@ -1,4 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_im_message,im.message,model_im_message,base.group_user,1,0,1,0 access_im_user,im.user,model_im_user,,1,1,1,0 -access_im_session,im.session,model_im_session,base.group_user,1,1,1,0 \ No newline at end of file +access_im_session,im.session,model_im_session,,1,0,0,0 \ No newline at end of file diff --git a/addons/im_livechat/im_livechat.py b/addons/im_livechat/im_livechat.py index cec546c8b8c..c8060b3fe92 100644 --- a/addons/im_livechat/im_livechat.py +++ b/addons/im_livechat/im_livechat.py @@ -75,7 +75,7 @@ class LiveChatController(http.Controller): def available(self, db, channel): reg, uid = self._auth(db) with reg.cursor() as cr: - return reg.get('im_livechat.channel').get_available_user(cr, uid, channel) > 0 + return len(reg.get('im_livechat.channel').get_available_users(cr, uid, channel)) > 0 class im_livechat_channel(osv.osv): _name = 'im_livechat.channel' @@ -159,7 +159,7 @@ class im_livechat_channel(osv.osv): 'image': _get_default_image, } - def get_available_user(self, cr, uid, channel_id, context=None): + def get_available_users(self, cr, uid, channel_id, context=None): channel = self.browse(cr, openerp.SUPERUSER_ID, channel_id, context=context) im_user_ids = self.pool.get("im.user").search(cr, uid, [["user_id", "in", [user.id for user in channel.user_ids]]], context=context) users = [] @@ -167,9 +167,17 @@ class im_livechat_channel(osv.osv): imuser = self.pool.get("im.user").browse(cr, uid, iuid, context=context) if imuser.im_status: users.append(imuser) + return users + + def get_session(self, cr, uid, channel_id, uuid, context=None): + my_id = self.pool.get("im.user").get_my_id(cr, uid, uuid, context=context) + users = self.get_available_users(cr, uid, channel_id, context=context) if len(users) == 0: return False - return random.choice(users).id + user_id = random.choice(users).id + session = self.pool.get("im.session").session_get(cr, uid, user_id, uuid, context=context) + self.pool.get("im.session").write(cr, openerp.SUPERUSER_ID, session.get("id"), {'channel_id': channel_id}, context=context) + return session.get("id") def test_channel(self, cr, uid, channel, context=None): if not channel: @@ -198,50 +206,9 @@ class im_livechat_channel(osv.osv): self.write(cr, uid, ids, {'user_ids': [(3, uid)]}) return True -""" -class im_message(osv.osv): - _inherit = 'im.message' - - def _support_member(self, cr, uid, ids, name, arg, context=None): - res = {} - for record in self.browse(cr, uid, ids, context=context): - res[record.id] = False - if record.to_id.user_id and record.from_id.user_id: - continue - elif record.to_id.user_id: - res[record.id] = record.to_id.user_id.id - elif record.from_id.user_id: - res[record.id] = record.from_id.user_id.id - return res - - def _customer(self, cr, uid, ids, name, arg, context=None): - res = {} - for record in self.browse(cr, uid, ids, context=context): - res[record.id] = False - if record.to_id.uuid and record.from_id.uuid: - continue - elif record.to_id.uuid: - res[record.id] = record.to_id.id - elif record.from_id.uuid: - res[record.id] = record.from_id.id - return res - - def _direction(self, cr, uid, ids, name, arg, context=None): - res = {} - for record in self.browse(cr, uid, ids, context=context): - res[record.id] = False - if not not record.to_id.user_id and not not record.from_id.user_id: - continue - elif not not record.to_id.user_id: - res[record.id] = "c2s" - elif not not record.from_id.user_id: - res[record.id] = "s2c" - return res +class im_session(osv.osv): + _inherit = 'im.session' _columns = { - 'support_member_id': fields.function(_support_member, type='many2one', relation='res.users', string='Support Member', store=True, select=True), - 'customer_id': fields.function(_customer, type='many2one', relation='im.user', string='Customer', store=True, select=True), - 'direction': fields.function(_direction, type="selection", selection=[("s2c", "Support Member to Customer"), ("c2s", "Customer to Support Member")], - string='Direction', store=False), + 'channel_id': fields.many2one("im.user", "Channel"), } -""" diff --git a/addons/im_livechat/static/ext/static/js/livesupport.js b/addons/im_livechat/static/ext/static/js/livesupport.js index fd5cecfe7d9..dc579345705 100644 --- a/addons/im_livechat/static/ext/static/js/livesupport.js +++ b/addons/im_livechat/static/ext/static/js/livesupport.js @@ -92,7 +92,7 @@ define(["openerp", "im_common", "underscore", "require", "jquery", setTimeout(function() { def.reject(); }, 5000); - def.then(_.bind(this.chat, this), function() { + return def.then(_.bind(this.chat, this), function() { im_common.notification(_t("It seems the connection to the server is encountering problems, please try again later.")); }); }, @@ -100,13 +100,12 @@ define(["openerp", "im_common", "underscore", "require", "jquery", var self = this; if (this.manager.conversations.length > 0) return; - im_common.connection.model("im_livechat.channel").call("get_available_user", [this.channel]).then(function(user_id) { - if (! user_id) { + im_common.connection.model("im_livechat.channel").call("get_session", [this.channel, this.manager.me.get("uuid")]).then(function(session_id) { + if (! session_id) { im_common.notification(_t("None of our collaborators seems to be available, please try again later.")); return; } - self.manager.ensure_users([user_id]).then(function() { - var conv = self.manager.activate_user(self.manager.get_user(user_id), true); + self.manager.activate_session(session_id, true).then(function(conv) { if (self.options.defaultMessage) { conv.received_message({message: self.options.defaultMessage, date: openerp.datetime_to_str(new Date())}); From f958499b9e0b4fadb41a382ea82ebf08548f4d1a Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 2 Sep 2013 14:27:19 +0200 Subject: [PATCH 5/7] make live support work again bzr revid: nicolas.vanhoren@openerp.com-20130902122719-ezxkjlkc7d2812jr --- addons/im_livechat/static/ext/static/js/livesupport.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/im_livechat/static/ext/static/js/livesupport.js b/addons/im_livechat/static/ext/static/js/livesupport.js index dc579345705..5ccdbd66cb7 100644 --- a/addons/im_livechat/static/ext/static/js/livesupport.js +++ b/addons/im_livechat/static/ext/static/js/livesupport.js @@ -107,8 +107,11 @@ define(["openerp", "im_common", "underscore", "require", "jquery", } self.manager.activate_session(session_id, true).then(function(conv) { if (self.options.defaultMessage) { - conv.received_message({message: self.options.defaultMessage, - date: openerp.datetime_to_str(new Date())}); + conv.received_message({ + message: self.options.defaultMessage, + date: openerp.datetime_to_str(new Date()), + from_id: [conv.users[0].get("id"), "Unknown"] + }); } }); }); From 2689878df51433d32018e0ff5d1057461866a68a Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 2 Sep 2013 14:58:56 +0200 Subject: [PATCH 6/7] Put logged users on top in the search panel bzr revid: nicolas.vanhoren@openerp.com-20130902125856-6ft2711c0sr29j83 --- addons/im/im.py | 3 ++- addons/im/static/src/js/im.js | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index b9bb957fce2..ce31c24f969 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -229,7 +229,8 @@ class im_user(osv.osv): def search_users(self, cr, uid, text_search, fields, limit, context=None): my_id = self.get_my_id(cr, uid, None, context) - found = self.search(cr, uid, [["name", "ilike", text_search], ["id", "<>", my_id], ["uuid", "=", False]], limit=limit, context=context) + found = self.search(cr, uid, [["name", "ilike", text_search], ["id", "<>", my_id], ["uuid", "=", False]], + order="name asc", limit=limit, context=context) return self.read(cr, uid, found, fields, context=context) def im_connect(self, cr, uid, uuid=None, context=None): diff --git a/addons/im/static/src/js/im.js b/addons/im/static/src/js/im.js index 4f49464693c..cad3c6dff0b 100644 --- a/addons/im/static/src/js/im.js +++ b/addons/im/static/src/js/im.js @@ -86,12 +86,15 @@ var users = new instance.web.Model("im.user"); var self = this; return this.user_search_dm.add(users.call("search_users", [this.get("current_search"), ["name", "user_id", "uuid", "im_status"], - USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(result) { - self.c_manager.add_to_user_cache(result); + USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(users) { + var logged_users = _.filter(users, function(u) { return !!u.im_status; }); + var non_logged_users = _.filter(users, function(u) { return !u.im_status; }); + users = logged_users.concat(non_logged_users); + self.c_manager.add_to_user_cache(users); self.$(".oe_im_input").val(""); var old_users = self.users; self.users = []; - _.each(result, function(user) { + _.each(users, function(user) { var widget = new instance.im.UserWidget(self, self.c_manager.get_user(user.id)); widget.appendTo(self.$(".oe_im_users")); widget.on("activate_user", self, self.activate_user); From 1f9d21552b47b2c326dbeb2a7f1a2b946e8a8297 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 2 Sep 2013 15:56:01 +0200 Subject: [PATCH 7/7] Re-enabled history of live chat bzr revid: nicolas.vanhoren@openerp.com-20130902135601-4hyeq0y1l1icgpno --- addons/im/im.py | 8 ++++++++ addons/im_livechat/im_livechat_view.xml | 9 +++------ addons/im_livechat/security/im_livechat_security.xml | 4 +--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/addons/im/im.py b/addons/im/im.py index ce31c24f969..c47d0d9be7e 100644 --- a/addons/im/im.py +++ b/addons/im/im.py @@ -193,8 +193,16 @@ class im_message(osv.osv): class im_session(osv.osv): _name = 'im.session' + + def _calc_name(self, cr, uid, ids, something, something_else, context=None): + res = {} + for obj in self.browse(cr, uid, ids, context=context): + res[obj.id] = ", ".join([x.name for x in obj.user_ids]) + return res + _columns = { 'user_ids': fields.many2many('im.user'), + "name": fields.function(_calc_name, string="Name", type='char'), } # Todo: reuse existing sessions if possible diff --git a/addons/im_livechat/im_livechat_view.xml b/addons/im_livechat/im_livechat_view.xml index a5e3de898ae..1fccc1b301c 100644 --- a/addons/im_livechat/im_livechat_view.xml +++ b/addons/im_livechat/im_livechat_view.xml @@ -120,12 +120,11 @@ - diff --git a/addons/im_livechat/security/im_livechat_security.xml b/addons/im_livechat/security/im_livechat_security.xml index b7185584394..b93798f96a9 100644 --- a/addons/im_livechat/security/im_livechat_security.xml +++ b/addons/im_livechat/security/im_livechat_security.xml @@ -21,18 +21,16 @@ -