[MERGE] Sync with trunk
bzr revid: tde@openerp.com-20130902142003-zbjek0sxe9yaub95
This commit is contained in:
commit
07a32dae60
|
@ -140,14 +140,17 @@ class im_message(osv.osv):
|
||||||
_order = "date desc"
|
_order = "date desc"
|
||||||
|
|
||||||
_columns = {
|
_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'),
|
'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", "im_message_users", 'message_id', 'user_id', 'To'),
|
||||||
'date': fields.datetime("Date", required=True, select=True),
|
'date': fields.datetime("Date", required=True, select=True),
|
||||||
|
'technical': fields.boolean("Technical Message"),
|
||||||
}
|
}
|
||||||
|
|
||||||
_defaults = {
|
_defaults = {
|
||||||
'date': lambda *args: datetime.datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
'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):
|
def get_messages(self, cr, uid, last=None, users_watch=None, uuid=None, context=None):
|
||||||
|
@ -165,8 +168,8 @@ class im_message(osv.osv):
|
||||||
last = c_user.im_last_received or -1
|
last = c_user.im_last_received or -1
|
||||||
|
|
||||||
# how fun it is to always need to reorder results from read
|
# 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_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", "date"], context=context)
|
mess = self.read(cr, openerp.SUPERUSER_ID, mess_ids, ["id", "message", "from_id", "session_id", "date"], context=context)
|
||||||
index = {}
|
index = {}
|
||||||
for i in xrange(len(mess)):
|
for i in xrange(len(mess)):
|
||||||
index[mess[i]["id"]] = mess[i]
|
index[mess[i]["id"]] = mess[i]
|
||||||
|
@ -179,13 +182,46 @@ class im_message(osv.osv):
|
||||||
users_status = users.read(cr, openerp.SUPERUSER_ID, users_watch, ["im_status"], context=context)
|
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}
|
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)
|
assert_uuid(uuid)
|
||||||
my_id = self.pool.get('im.user').get_my_id(cr, uid, 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)
|
session = self.pool.get('im.session').browse(cr, uid, to_session_id, context)
|
||||||
notify_channel(cr, "im_channel", {'type': 'message', 'receiver': to_user_id})
|
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
|
return False
|
||||||
|
|
||||||
|
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
|
||||||
|
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, 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, openerp.SUPERUSER_ID, {
|
||||||
|
'user_ids': [(6, 0, [user_to, my_id])]
|
||||||
|
}, context=context)
|
||||||
|
return self.read(cr, uid, session_id, context=context)
|
||||||
|
|
||||||
class im_user(osv.osv):
|
class im_user(osv.osv):
|
||||||
_name = "im.user"
|
_name = "im.user"
|
||||||
|
|
||||||
|
@ -201,7 +237,8 @@ class im_user(osv.osv):
|
||||||
|
|
||||||
def search_users(self, cr, uid, text_search, fields, limit, context=None):
|
def search_users(self, cr, uid, text_search, fields, limit, context=None):
|
||||||
my_id = self.get_my_id(cr, uid, None, context)
|
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)
|
return self.read(cr, uid, found, fields, context=context)
|
||||||
|
|
||||||
def im_connect(self, cr, uid, uuid=None, context=None):
|
def im_connect(self, cr, uid, uuid=None, context=None):
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
<field name="name">Can only read messages that you sent or messages sent to you</field>
|
<field name="name">Can only read messages that you sent or messages sent to you</field>
|
||||||
<field name="model_id" ref="model_im_message"/>
|
<field name="model_id" ref="model_im_message"/>
|
||||||
<field name="groups" eval="[(6,0,[ref('base.group_user')])]"/>
|
<field name="groups" eval="[(6,0,[ref('base.group_user')])]"/>
|
||||||
<field name="domain_force">["|", ('to_id.user_id', '=', user.id), ('from_id.user_id', '=', user.id)]</field>
|
<field name="domain_force">["|", ('to_id.user_id', 'in', [user.id]), ('from_id.user_id', '=', user.id)]</field>
|
||||||
<field name="perm_unlink" eval="0"/>
|
|
||||||
<field name="perm_write" eval="0"/>
|
|
||||||
<field name="perm_read" eval="1"/>
|
<field name="perm_read" eval="1"/>
|
||||||
|
<field name="perm_write" eval="0"/>
|
||||||
<field name="perm_create" eval="0"/>
|
<field name="perm_create" eval="0"/>
|
||||||
|
<field name="perm_unlink" eval="0"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="users_rule_1" model="ir.rule">
|
<record id="users_rule_1" model="ir.rule">
|
||||||
|
@ -17,10 +17,10 @@
|
||||||
<field name="model_id" ref="model_im_user"/>
|
<field name="model_id" ref="model_im_user"/>
|
||||||
<field name="groups" eval="[(6,0,[ref('base.group_user')])]"/>
|
<field name="groups" eval="[(6,0,[ref('base.group_user')])]"/>
|
||||||
<field name="domain_force">[('user_id', '=', user.id)]</field>
|
<field name="domain_force">[('user_id', '=', user.id)]</field>
|
||||||
<field name="perm_unlink" eval="1"/>
|
|
||||||
<field name="perm_write" eval="1"/>
|
|
||||||
<field name="perm_read" eval="0"/>
|
<field name="perm_read" eval="0"/>
|
||||||
|
<field name="perm_write" eval="1"/>
|
||||||
<field name="perm_create" eval="1"/>
|
<field name="perm_create" eval="1"/>
|
||||||
|
<field name="perm_unlink" eval="1"/>
|
||||||
</record>
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
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_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_user,im.user,model_im_user,,1,1,1,0
|
||||||
|
access_im_session,im.session,model_im_session,,1,0,0,0
|
|
|
@ -86,12 +86,15 @@
|
||||||
var users = new instance.web.Model("im.user");
|
var users = new instance.web.Model("im.user");
|
||||||
var self = this;
|
var self = this;
|
||||||
return this.user_search_dm.add(users.call("search_users", [this.get("current_search"), ["name", "user_id", "uuid", "im_status"],
|
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) {
|
USERS_LIMIT], {context:new instance.web.CompoundContext()})).then(function(users) {
|
||||||
self.c_manager.add_to_user_cache(result);
|
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("");
|
self.$(".oe_im_input").val("");
|
||||||
var old_users = self.users;
|
var old_users = self.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));
|
var widget = new instance.im.UserWidget(self, self.c_manager.get_user(user.id));
|
||||||
widget.appendTo(self.$(".oe_im_users"));
|
widget.appendTo(self.$(".oe_im_users"));
|
||||||
widget.on("activate_user", self, self.activate_user);
|
widget.on("activate_user", self, self.activate_user);
|
||||||
|
@ -125,7 +128,10 @@
|
||||||
this.shown = ! this.shown;
|
this.shown = ! this.shown;
|
||||||
},
|
},
|
||||||
activate_user: function(user) {
|
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);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,6 @@ function declare($, _, openerp) {
|
||||||
this.set("right_offset", 0);
|
this.set("right_offset", 0);
|
||||||
this.set("bottom_offset", 0);
|
this.set("bottom_offset", 0);
|
||||||
this.conversations = [];
|
this.conversations = [];
|
||||||
this.users = {};
|
|
||||||
this.on("change:right_offset", this, this.calc_positions);
|
this.on("change:right_offset", this, this.calc_positions);
|
||||||
this.on("change:bottom_offset", this, this.calc_positions);
|
this.on("change:bottom_offset", this, this.calc_positions);
|
||||||
this.set("window_focus", true);
|
this.set("window_focus", true);
|
||||||
|
@ -178,12 +177,7 @@ function declare($, _, openerp) {
|
||||||
self.get_user(el.id).set(el);
|
self.get_user(el.id).set(el);
|
||||||
});
|
});
|
||||||
self.last = result.last;
|
self.last = result.last;
|
||||||
var user_ids = _.pluck(_.pluck(result.res, "from_id"), 0);
|
self.received_messages(result.res).then(function() {
|
||||||
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.poll();
|
self.poll();
|
||||||
});
|
});
|
||||||
}, function(unused, e) {
|
}, function(unused, e) {
|
||||||
|
@ -217,32 +211,41 @@ function declare($, _, openerp) {
|
||||||
openerp.webclient.set_title_part("im_messages", this.get("waiting_messages") === 0 ? undefined :
|
openerp.webclient.set_title_part("im_messages", this.get("waiting_messages") === 0 ? undefined :
|
||||||
_.str.sprintf(_t("%d Messages"), this.get("waiting_messages")));
|
_.str.sprintf(_t("%d Messages"), this.get("waiting_messages")));
|
||||||
},
|
},
|
||||||
activate_user: function(user, focus) {
|
activate_session: function(session_id, focus) {
|
||||||
var conv = this.users[user.get('id')];
|
var conv = _.find(this.conversations, function(conv) {return conv.session_id == session_id;});
|
||||||
|
var def = $.when();
|
||||||
if (! conv) {
|
if (! conv) {
|
||||||
conv = new im_common.Conversation(this, user, this.me, this.options);
|
conv = new im_common.Conversation(this, this, session_id, this.options);
|
||||||
conv.appendTo($("body"));
|
def = conv.appendTo($("body")).then(_.bind(function() {
|
||||||
conv.on("destroyed", this, function() {
|
conv.on("destroyed", this, function() {
|
||||||
this.conversations = _.without(this.conversations, conv);
|
this.conversations = _.without(this.conversations, conv);
|
||||||
delete this.users[conv.user.get('id')];
|
this.calc_positions();
|
||||||
|
});
|
||||||
|
this.conversations.push(conv);
|
||||||
this.calc_positions();
|
this.calc_positions();
|
||||||
});
|
}, this));
|
||||||
this.conversations.push(conv);
|
|
||||||
this.users[user.get('id')] = conv;
|
|
||||||
this.calc_positions();
|
|
||||||
}
|
}
|
||||||
if (focus)
|
if (focus) {
|
||||||
conv.focus();
|
def = def.then(function() {
|
||||||
return conv;
|
conv.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return def.then(function() {return conv});
|
||||||
},
|
},
|
||||||
received_message: function(message, user) {
|
received_messages: function(messages) {
|
||||||
if (! this.get("window_focus")) {
|
var self = this;
|
||||||
this.set("waiting_messages", this.get("waiting_messages") + 1);
|
if (! this.get("window_focus") && messages.length >= 1) {
|
||||||
|
this.set("waiting_messages", this.get("waiting_messages") + messages.length);
|
||||||
this.ting.play();
|
this.ting.play();
|
||||||
this.create_ting();
|
this.create_ting();
|
||||||
}
|
}
|
||||||
var conv = this.activate_user(user);
|
var defs = [];
|
||||||
conv.received_message(message);
|
_.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() {
|
calc_positions: function() {
|
||||||
var current = this.get("right_offset");
|
var current = this.get("right_offset");
|
||||||
|
@ -267,39 +270,52 @@ function declare($, _, openerp) {
|
||||||
"click .oe_im_chatview_close": "destroy",
|
"click .oe_im_chatview_close": "destroy",
|
||||||
"click .oe_im_chatview_header": "show_hide"
|
"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._super(parent);
|
||||||
this.options = options;
|
this.c_manager = c_manager;
|
||||||
this.me = me;
|
this.options = options || {};
|
||||||
this.user = user;
|
this.session_id = session_id;
|
||||||
this.user.add_watcher();
|
|
||||||
this.set("right_position", 0);
|
this.set("right_position", 0);
|
||||||
this.set("bottom_position", 0);
|
this.set("bottom_position", 0);
|
||||||
this.shown = true;
|
this.shown = true;
|
||||||
this.set("pending", 0);
|
this.set("pending", 0);
|
||||||
this.inputPlaceholder = this.options.defaultInputPlaceholder;
|
this.inputPlaceholder = this.options.defaultInputPlaceholder;
|
||||||
|
this.users = [];
|
||||||
|
this.others = [];
|
||||||
},
|
},
|
||||||
start: function() {
|
start: function() {
|
||||||
this.$().append(openerp.qweb.render("im_common.conversation", {widget: this, to_url: _.bind(im_common.connection.url, im_common.connection)}));
|
var self = this;
|
||||||
var change_status = function() {
|
var user_ids;
|
||||||
this.$().toggleClass("oe_im_chatview_disconnected_status", this.user.get("im_status") === false);
|
return im_common.connection.model("im.session").call("read", [self.session_id]).then(function(session) {
|
||||||
this.$(".oe_im_chatview_online").toggle(this.user.get("im_status") === true);
|
user_ids = _.without(session.user_ids, self.c_manager.me.get("id"));
|
||||||
this._go_bottom();
|
return self.c_manager.ensure_users(session.user_ids);
|
||||||
};
|
}).then(function() {
|
||||||
this.user.on("change:im_status", this, change_status);
|
self.users = _.map(user_ids, function(id) {return self.c_manager.get_user(id);});
|
||||||
change_status.call(this);
|
_.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);
|
self.on("change:right_position", self, self.calc_pos);
|
||||||
this.on("change:bottom_position", this, this.calc_pos);
|
self.on("change:bottom_position", self, self.calc_pos);
|
||||||
this.full_height = this.$().height();
|
self.full_height = self.$().height();
|
||||||
this.calc_pos();
|
self.calc_pos();
|
||||||
this.on("change:pending", this, _.bind(function() {
|
self.on("change:pending", self, _.bind(function() {
|
||||||
if (this.get("pending") === 0) {
|
if (self.get("pending") === 0) {
|
||||||
this.$(".oe_im_chatview_nbr_messages").text("");
|
self.$(".oe_im_chatview_nbr_messages").text("");
|
||||||
} else {
|
} else {
|
||||||
this.$(".oe_im_chatview_nbr_messages").text("(" + this.get("pending") + ")");
|
self.$(".oe_im_chatview_nbr_messages").text("(" + self.get("pending") + ")");
|
||||||
}
|
}
|
||||||
}, this));
|
}, self));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
show_hide: function() {
|
show_hide: function() {
|
||||||
if (this.shown) {
|
if (this.shown) {
|
||||||
|
@ -326,7 +342,14 @@ function declare($, _, openerp) {
|
||||||
} else {
|
} else {
|
||||||
this.set("pending", this.get("pending") + 1);
|
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) {
|
send_message: function(e) {
|
||||||
if(e && e.which !== 13) {
|
if(e && e.which !== 13) {
|
||||||
|
@ -339,17 +362,15 @@ function declare($, _, openerp) {
|
||||||
this.$("input").val("");
|
this.$("input").val("");
|
||||||
var send_it = _.bind(function() {
|
var send_it = _.bind(function() {
|
||||||
var model = im_common.connection.model("im.message");
|
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);
|
}, this);
|
||||||
var tries = 0;
|
var tries = 0;
|
||||||
send_it().then(_.bind(function() {
|
send_it().then(_.bind(function() {}, function(error, e) {
|
||||||
this._add_bubble(this.me, mes, new Date());
|
|
||||||
}, this), function(error, e) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
tries += 1;
|
tries += 1;
|
||||||
if (tries < 3)
|
if (tries < 3)
|
||||||
return send_it();
|
return send_it();
|
||||||
});
|
}));
|
||||||
},
|
},
|
||||||
_add_bubble: function(user, item, date) {
|
_add_bubble: function(user, item, date) {
|
||||||
var items = [item];
|
var items = [item];
|
||||||
|
@ -378,7 +399,12 @@ function declare($, _, openerp) {
|
||||||
this.show_hide();
|
this.show_hide();
|
||||||
},
|
},
|
||||||
destroy: function() {
|
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");
|
this.trigger("destroyed");
|
||||||
return this._super();
|
return this._super();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
<t t-name="im_common.conversation">
|
<t t-name="im_common.conversation">
|
||||||
<div class="oe_im_chatview_header">
|
<div class="oe_im_chatview_header">
|
||||||
<img t-att-src="to_url('/im/static/src/img/green.png')" class="oe_im_chatview_online"/>
|
<img t-att-src="to_url('/im/static/src/img/green.png')" class="oe_im_chatview_online"/>
|
||||||
<t t-esc="widget.user.get('name')"/>
|
<t t-esc="widget.users[0].get('name')"/>
|
||||||
<scan class="oe_im_chatview_nbr_messages" />
|
<scan class="oe_im_chatview_nbr_messages" />
|
||||||
<button class="oe_im_chatview_close">×</button>
|
<button class="oe_im_chatview_close">×</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_im_chatview_disconnected">
|
<div class="oe_im_chatview_disconnected">
|
||||||
<t t-esc='widget.user.get("name") + _t(" is offline. He/She will receive your messages on his/her next connection.")'/>
|
<t t-esc='widget.users[0].get("name") + _t(" is offline. He/She will receive your messages on his/her next connection.")'/>
|
||||||
</div>
|
</div>
|
||||||
<div class="oe_im_chatview_content">
|
<div class="oe_im_chatview_content">
|
||||||
<div></div>
|
<div></div>
|
||||||
|
|
|
@ -51,8 +51,9 @@ class ImWatcher(object):
|
||||||
|
|
||||||
def handle_message(self, message):
|
def handle_message(self, message):
|
||||||
if message["type"] == "message":
|
if message["type"] == "message":
|
||||||
for waiter in self.users.get(message["receiver"], {}).values():
|
for receiver in message["receivers"]:
|
||||||
waiter.set()
|
for waiter in self.users.get(receiver, {}).values():
|
||||||
|
waiter.set()
|
||||||
else: #type status
|
else: #type status
|
||||||
for waiter in self.users_watch.get(message["user"], {}).values():
|
for waiter in self.users_watch.get(message["user"], {}).values():
|
||||||
waiter.set()
|
waiter.set()
|
||||||
|
|
|
@ -75,7 +75,7 @@ class LiveChatController(http.Controller):
|
||||||
def available(self, db, channel):
|
def available(self, db, channel):
|
||||||
reg, uid = self._auth(db)
|
reg, uid = self._auth(db)
|
||||||
with reg.cursor() as cr:
|
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):
|
class im_livechat_channel(osv.osv):
|
||||||
_name = 'im_livechat.channel'
|
_name = 'im_livechat.channel'
|
||||||
|
@ -159,7 +159,7 @@ class im_livechat_channel(osv.osv):
|
||||||
'image': _get_default_image,
|
'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)
|
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)
|
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 = []
|
users = []
|
||||||
|
@ -167,9 +167,17 @@ class im_livechat_channel(osv.osv):
|
||||||
imuser = self.pool.get("im.user").browse(cr, uid, iuid, context=context)
|
imuser = self.pool.get("im.user").browse(cr, uid, iuid, context=context)
|
||||||
if imuser.im_status:
|
if imuser.im_status:
|
||||||
users.append(imuser)
|
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:
|
if len(users) == 0:
|
||||||
return False
|
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):
|
def test_channel(self, cr, uid, channel, context=None):
|
||||||
if not channel:
|
if not channel:
|
||||||
|
@ -198,49 +206,9 @@ class im_livechat_channel(osv.osv):
|
||||||
self.write(cr, uid, ids, {'user_ids': [(3, uid)]})
|
self.write(cr, uid, ids, {'user_ids': [(3, uid)]})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
class im_session(osv.osv):
|
||||||
class im_message(osv.osv):
|
_inherit = 'im.session'
|
||||||
_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
|
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'support_member_id': fields.function(_support_member, type='many2one', relation='res.users', string='Support Member', store=True, select=True),
|
'channel_id': fields.many2one("im.user", "Channel"),
|
||||||
'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),
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@
|
||||||
<field name="name">History</field>
|
<field name="name">History</field>
|
||||||
<field name="res_model">im.message</field>
|
<field name="res_model">im.message</field>
|
||||||
<field name="view_mode">list</field>
|
<field name="view_mode">list</field>
|
||||||
<field name="domain">["|", ('to_id.user_id', '=', None), ('from_id.user_id', '=', None)]</field>
|
<field name="domain">[('session_id.channel_id', '!=', None)]</field>
|
||||||
</record>
|
</record>
|
||||||
<menuitem name="History" parent="im_livechat" id="history" action="action_history" groups="group_im_livechat_manager"/>
|
<menuitem name="History" parent="im_livechat" id="history" action="action_history" groups="group_im_livechat_manager"/>
|
||||||
|
|
||||||
|
@ -133,10 +133,9 @@
|
||||||
<field name="model">im.message</field>
|
<field name="model">im.message</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree string="History">
|
<tree string="History">
|
||||||
|
<field name="session_id"/>
|
||||||
<field name="date"/>
|
<field name="date"/>
|
||||||
<field name="support_member_id"/>
|
<field name="from_id"/>
|
||||||
<field name="customer_id"/>
|
|
||||||
<field name="direction"/>
|
|
||||||
<field name="message"/>
|
<field name="message"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<field name="name">Live Support Managers can read messages from live support</field>
|
<field name="name">Live Support Managers can read messages from live support</field>
|
||||||
<field name="model_id" ref="im.model_im_message"/>
|
<field name="model_id" ref="im.model_im_message"/>
|
||||||
<field name="groups" eval="[(6,0,[ref('im_livechat.group_im_livechat_manager')])]"/>
|
<field name="groups" eval="[(6,0,[ref('im_livechat.group_im_livechat_manager')])]"/>
|
||||||
<field name="domain_force">["|", ('to_id.user_id', '=', None), ('from_id.user_id', '=', None)]</field>
|
<field name="domain_force">[('session_id.channel_id', '!=', None)]</field>
|
||||||
<field name="perm_unlink" eval="0"/>
|
<field name="perm_unlink" eval="0"/>
|
||||||
<field name="perm_write" eval="0"/>
|
<field name="perm_write" eval="0"/>
|
||||||
<field name="perm_read" eval="1"/>
|
<field name="perm_read" eval="1"/>
|
||||||
|
|
|
@ -92,7 +92,7 @@ define(["openerp", "im_common", "underscore", "require", "jquery",
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
def.reject();
|
def.reject();
|
||||||
}, 5000);
|
}, 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."));
|
im_common.notification(_t("It seems the connection to the server is encountering problems, please try again later."));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -100,16 +100,18 @@ define(["openerp", "im_common", "underscore", "require", "jquery",
|
||||||
var self = this;
|
var self = this;
|
||||||
if (this.manager.conversations.length > 0)
|
if (this.manager.conversations.length > 0)
|
||||||
return;
|
return;
|
||||||
im_common.connection.model("im_livechat.channel").call("get_available_user", [this.channel]).then(function(user_id) {
|
im_common.connection.model("im_livechat.channel").call("get_session", [this.channel, this.manager.me.get("uuid")]).then(function(session_id) {
|
||||||
if (! user_id) {
|
if (! session_id) {
|
||||||
im_common.notification(_t("None of our collaborators seems to be available, please try again later."));
|
im_common.notification(_t("None of our collaborators seems to be available, please try again later."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.manager.ensure_users([user_id]).then(function() {
|
self.manager.activate_session(session_id, true).then(function(conv) {
|
||||||
var conv = self.manager.activate_user(self.manager.get_user(user_id), true);
|
|
||||||
if (self.options.defaultMessage) {
|
if (self.options.defaultMessage) {
|
||||||
conv.received_message({message: self.options.defaultMessage,
|
conv.received_message({
|
||||||
date: openerp.datetime_to_str(new Date())});
|
message: self.options.defaultMessage,
|
||||||
|
date: openerp.datetime_to_str(new Date()),
|
||||||
|
from_id: [conv.users[0].get("id"), "Unknown"]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue