diff --git a/addons/live_support/static/ext/static/audio/Ting.mp3 b/addons/live_support/static/ext/static/audio/Ting.mp3
new file mode 100644
index 00000000000..6fd090a89ce
Binary files /dev/null and b/addons/live_support/static/ext/static/audio/Ting.mp3 differ
diff --git a/addons/live_support/static/ext/static/audio/Ting.ogg b/addons/live_support/static/ext/static/audio/Ting.ogg
new file mode 100644
index 00000000000..8d17ea85bd3
Binary files /dev/null and b/addons/live_support/static/ext/static/audio/Ting.ogg differ
diff --git a/addons/live_support/static/ext/static/js/livesupport.js b/addons/live_support/static/ext/static/js/livesupport.js
index 658b9980aa6..988bb05a363 100644
--- a/addons/live_support/static/ext/static/js/livesupport.js
+++ b/addons/live_support/static/ext/static/js/livesupport.js
@@ -1,15 +1,218 @@
-define(["nova", "jquery", "underscore", "oeclient"], function(nova, $, _, oeclient) {
+define(["nova", "jquery", "underscore", "oeclient", "require"], function(nova, $, _, oeclient, require) {
var livesupport = {};
+ var te = new nova.TemplateEngine();
+ var connection;
+
livesupport.main = function(server_url, db, login, password) {
- console.log("hello");
- var connection = new oeclient.Connection(new oeclient.JsonpRPCConnector(server_url), db, login, password);
- var userModel = connection.getModel("res.users");
- userModel.call("search", [[["login", "=", "admin"]]]).then(function(result) {
- console.log(result);
+ te.loadFile(require.toUrl("./livesupport_templates.html")).then(function() {
+ connection = new oeclient.Connection(new oeclient.JsonpRPCConnector(server_url), db, login, password);
+ // don't know
});
};
+ var ERROR_DELAY = 5000;
+
+ livesupport.ImUser = nova.Class.$extend({
+ __include__: [nova.DynamicProperties],
+ __init__: function(parent, user_rec) {
+ nova.DynamicProperties.__init__.call(this, parent);
+ //user_rec.image_url = instance.session.url('/web/binary/image', {model:'res.users', field: 'image_small', id: user_rec.id});
+ this.set(user_rec);
+ this.set("watcher_count", 0);
+ this.on("change:watcher_count", this, function() {
+ if (this.get("watcher_count") === 0)
+ this.destroy();
+ });
+ },
+ destroy: function() {
+ this.trigger("destroyed");
+ nova.DynamicProperties.destroy.call(this);
+ },
+ add_watcher: function() {
+ this.set("watcher_count", this.get("watcher_count") + 1);
+ },
+ remove_watcher: function() {
+ this.set("watcher_count", this.get("watcher_count") - 1);
+ },
+ });
+
+ livesupport.ConversationManager = nova.Class.$extend({
+ __include__: [nova.DynamicProperties],
+ init: function(parent) {
+ nova.DynamicProperties.__init__.call(this, parent);
+ this.set("right_offset", 0);
+ this.conversations = [];
+ this.users = {};
+ this.on("change:right_offset", this, this.calc_positions);
+ this.set("window_focus", true);
+ this.set("waiting_messages", 0);
+ this.focus_hdl = _.bind(function() {
+ this.set("window_focus", true);
+ }, this);
+ $(window).bind("focus", this.focus_hdl);
+ this.blur_hdl = _.bind(function() {
+ this.set("window_focus", false);
+ }, this);
+ $(window).bind("blur", this.blur_hdl);
+ this.on("change:window_focus", this, this.window_focus_change);
+ this.window_focus_change();
+ this.on("change:waiting_messages", this, this.messages_change);
+ this.messages_change();
+ this.create_ting();
+ },
+ create_ting: function() {
+ this.ting = new Audio(new Audio().canPlayType("audio/ogg; codecs=vorbis") ?
+ require.toUrl("../audio/Ting.ogg") :
+ require.toUrl("../audio/Ting.mp3")
+ ));
+ },
+ window_focus_change: function() {
+ if (this.get("window_focus")) {
+ this.set("waiting_messages", 0);
+ }
+ },
+ messages_change: function() {
+ /*if (! instance.webclient.set_title_part)
+ return;
+ instance.webclient.set_title_part("im_messages", this.get("waiting_messages") === 0 ? undefined :
+ _.str.sprintf(_t("%d Messages"), this.get("waiting_messages")));*/
+ },
+ set_me: function(me) {
+ this.me = me;
+ },
+ activate_user: function(user) {
+ if (this.users[user.get('id')]) {
+ return this.users[user.get('id')];
+ }
+ var conv = new livesupport.Conversation(this, user, this.me);
+ conv.appendTo($("body"));
+ conv.on("destroyed", this, function() {
+ this.conversations = _.without(this.conversations, conv);
+ delete this.users[conv.user.get('id')];
+ this.calc_positions();
+ });
+ this.conversations.push(conv);
+ this.users[user.get('id')] = conv;
+ this.calc_positions();
+ return conv;
+ },
+ received_message: function(message, user) {
+ if (! this.get("window_focus")) {
+ this.set("waiting_messages", this.get("waiting_messages") + 1);
+ this.ting.play();
+ this.create_ting();
+ }
+ var conv = this.activate_user(user);
+ conv.received_message(message);
+ },
+ calc_positions: function() {
+ var current = this.get("right_offset");
+ _.each(_.range(this.conversations.length), function(i) {
+ this.conversations[i].set("right_position", current);
+ current += this.conversations[i].$().outerWidth(true);
+ }, this);
+ },
+ destroy: function() {
+ $(window).unbind("blur", this.blur_hdl);
+ $(window).unbind("focus", this.focus_hdl);
+ nova.DynamicProperties.destroy.call(this);
+ },
+ });
+
+ livesupport.Conversation = instance.web.Widget.extend({
+ tagClass: "oe_im_chatview",
+ events: {
+ "keydown input": "send_message",
+ "click .oe_im_chatview_close": "destroy",
+ "click .oe_im_chatview_header": "show_hide",
+ },
+ init: function(parent, user, me) {
+ this._super(parent);
+ this.me = me;
+ this.user = user;
+ this.user.add_watcher();
+ this.set("right_position", 0);
+ this.shown = true;
+ },
+ render: function() {
+ this.$().append(te.conversation({widget: this}));
+ 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);
+
+ this.on("change:right_position", this, this.calc_pos);
+ this.full_height = this.$().height();
+ this.calc_pos();
+ },
+ show_hide: function() {
+ if (this.shown) {
+ this.$().animate({
+ height: this.$(".oe_im_chatview_header").outerHeight(),
+ });
+ } else {
+ this.$().animate({
+ height: this.full_height,
+ });
+ }
+ this.shown = ! this.shown;
+ },
+ calc_pos: function() {
+ this.$().css("right", this.get("right_position"));
+ },
+ received_message: function(message) {
+ this._add_bubble(this.user, message.message, message.date);
+ },
+ send_message: function(e) {
+ if(e && e.which !== 13) {
+ return;
+ }
+ var mes = this.$("input").val();
+ this.$("input").val("");
+ var send_it = _.bind(function() {
+ var model = new connection.getModel("im.message");
+ return model.call("post", [mes, this.user.get('id')], {context: {}});
+ }, this);
+ var tries = 0;
+ send_it().then(_.bind(function() {
+ this._add_bubble(this.me, mes, new Date());
+ }, this), function(error, e) {
+ e.preventDefault();
+ tries += 1;
+ if (tries < 3)
+ return send_it();
+ });
+ },
+ _add_bubble: function(user, item, date) {
+ var items = [item];
+ if (user === this.last_user) {
+ this.last_bubble.remove();
+ items = this.last_items.concat(items);
+ }
+ this.last_user = user;
+ this.last_items = items;
+ date = "" + date; // TODO
+
+ this.last_bubble = $(te.conversation_bubble({"items": items, "user": user, "time": date}));
+ $(this.$(".oe_im_chatview_content").children()[0]).append(this.last_bubble);
+ this._go_bottom();
+ },
+ _go_bottom: function() {
+ this.$(".oe_im_chatview_content").scrollTop($(this.$(".oe_im_chatview_content").children()[0]).height());
+ },
+ destroy: function() {
+ this.user.remove_watcher();
+ this.trigger("destroyed");
+ return this._super();
+ },
+ });
+
+
+
return livesupport;
});
diff --git a/addons/live_support/static/ext/static/js/livesupport_templates.html b/addons/live_support/static/ext/static/js/livesupport_templates.html
new file mode 100644
index 00000000000..8fa0b1a2170
--- /dev/null
+++ b/addons/live_support/static/ext/static/js/livesupport_templates.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+
\ No newline at end of file