From d598492dbd066ba2c4eea115d9af742814afc6b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 27 Feb 2012 09:50:05 +0100 Subject: [PATCH 01/18] [REF] Slighty cleaned ThreadDisplay widget code. Start now returns deferred from fetch_comments. bzr revid: tde@openerp.com-20120227085005-2vhuc8jdmeimu406 --- addons/mail/static/src/js/mail.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 84800358ada..5ac5caac095 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -18,7 +18,10 @@ openerp.mail = function(session) { this.res_model = params['res_model']; this.res_id = params['res_id']; this.uid = params['uid']; + this.limit = params['limit'] || 10; + this.offset = params['offset'] || 0; this.records = params['records'] || false; + // tmp this.map_hash = {'res.users': []}; /* DataSets */ this.ds = new session.web.DataSet(this, this.res_model); @@ -32,21 +35,19 @@ openerp.mail = function(session) { this.$element.find('button.oe_mail_button_comment').bind('click', function () { self.do_comment(); }); /* delegate links */ self.$element.find('div.oe_mail_thread_display').delegate('a', 'click', function (event) { - //console.log(event); var res_model = event.srcElement.dataset.resModel; var res_id = event.srcElement.dataset.resId; self.do_action({ type: 'ir.actions.act_window', res_model: res_model, res_id: parseInt(res_id), - //context: context, views: [[false, 'form']] }); }); /* display user, fetch comments */ this.display_current_user(); - if (this.records == false) this.fetch_comments(); - else this.display_comments(this.records); + if (this.records == false) return this.fetch_comments(); + else return this.display_comments(this.records); }, stop: function () { @@ -54,9 +55,7 @@ openerp.mail = function(session) { }, fetch_comments: function () { - var load_res = this.ds.call('message_load', [[this.res_id]]).then( - this.proxy('display_comments')); - return load_res; + return this.ds.call('message_load', [[this.res_id]]).then(this.proxy('display_comments')); }, display_current_user: function () { @@ -66,8 +65,8 @@ openerp.mail = function(session) { }, display_comments: function (records) { - this.$element.find('div.oe_mail_thread_display').empty(); var self = this; + this.$element.find('div.oe_mail_thread_display').empty(); /* WIP: map matched regexp -> records to browse with name */ _(records).each(function (record) { self.check_internal_links(record.body_text); @@ -137,9 +136,7 @@ openerp.mail = function(session) { }, thread_get_avatar_mini: function(model, field, id) { - id = id || ''; - var url = this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + id; - return url; + return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + id || ''; }, }); From 0c4099ba26858905e857575bde5a8bcf6f1bf3d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 27 Feb 2012 09:54:42 +0100 Subject: [PATCH 02/18] [FIX] Fixed error with undefined id when fetching the avatar. bzr revid: tde@openerp.com-20120227085442-5r4jb0bbor1zpulw --- addons/mail/static/src/js/mail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 5ac5caac095..c20eafd6c6b 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -136,7 +136,7 @@ openerp.mail = function(session) { }, thread_get_avatar_mini: function(model, field, id) { - return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + id || ''; + return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || ''); }, }); From d3dd68e08e6ed3cd9259639cbd49ec67534a9b55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 27 Feb 2012 12:07:54 +0100 Subject: [PATCH 03/18] [IMP] ThreadDisplay: now shows a "More button" (no action attached currently). Updated css for style. Emails are managed. Also refactored templates for cleaner architecture. bzr revid: tde@openerp.com-20120227110754-9v207ey8m3k5rv9j --- addons/mail/__openerp__.py | 1 + addons/mail/static/src/css/mail.css | 41 ++++++++++++--- addons/mail/static/src/js/mail.js | 65 +++++++++++++---------- addons/mail/static/src/xml/mail.xml | 80 +++++++++++++++++++---------- 4 files changed, 124 insertions(+), 63 deletions(-) diff --git a/addons/mail/__openerp__.py b/addons/mail/__openerp__.py index f8e7c74e5f8..a644caea5e7 100644 --- a/addons/mail/__openerp__.py +++ b/addons/mail/__openerp__.py @@ -72,6 +72,7 @@ The main features are: 'images/customer_history.jpeg', 'images/messages_form.jpeg', 'images/messages_list.jpeg', + 'static/src/img/email_icong.png', ], 'css': [ 'static/src/css/mail.css', diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index d4eb2373b66..be02336da41 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -77,8 +77,26 @@ } .oe_mail_thread_msg, .oe_mail_thread_act { + width: 80%; white-space: normal; margin-bottom: 5px; + border-bottom: 1px solid #D2D9E7; +} + +.notification { + background: #E0E0E0; +} + +.email { + background: #E0E0E0; +} + +.oe_mail_thread_msg_more { + margin-left: 20%; + margin-right: 40%; + border: 1px solid #D2D9E7; + background: #E0E0E0; + text-align: center; } .oe_mail_thread_msg:after, .oe_mail_thread_act:after { @@ -99,8 +117,8 @@ .oe_mail_msg_image { float: left; - width: 60px; - height: 60px; + width: 45px; + height: 40px; text-align: center; overflow: hidden; -moz-border-radius: 3px; @@ -115,14 +133,13 @@ } .oe_mail_msg_image img { - width: 60px; + width: 40px; height: auto; clip: rect(10px, 100px, 110px, 0px); } .oe_mail_msg_content { - width: 89%; - margin-left: 11%; + margin-left: 50px; } .oe_mail_msg_p { @@ -130,10 +147,18 @@ margin: 0; } +.oe_mail_msg_p_email_header { + border-bottom: 1px solid #D2D9E7; +} + .oe_mail_msg_body { } -.oe_mail_msg_author, .oe_mail_msg_author a { +.oe_mail_msg_author { + color: #747474; +} + +.oe_mail_msg_author a { color: #4E43E7; } @@ -141,6 +166,6 @@ color: #C03000; } -.oe_mail_msg_date, .oe_mail_msg_date a { - color: #4E43E7; +.oe_mail_msg_date { + color: #747474; } diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index c20eafd6c6b..31e1df75f35 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -20,6 +20,7 @@ openerp.mail = function(session) { this.uid = params['uid']; this.limit = params['limit'] || 10; this.offset = params['offset'] || 0; + this.cur_limit = this.limit; this.records = params['records'] || false; // tmp this.map_hash = {'res.users': []}; @@ -58,12 +59,6 @@ openerp.mail = function(session) { return this.ds.call('message_load', [[this.res_id]]).then(this.proxy('display_comments')); }, - display_current_user: function () { - $('
').html( - '' - ).appendTo(this.$element.find('div.oe_mail_msg_image')); - }, - display_comments: function (records) { var self = this; this.$element.find('div.oe_mail_thread_display').empty(); @@ -73,13 +68,23 @@ openerp.mail = function(session) { }); //console.log(this.map_hash); _(records).each(function (record) { - record.mini_url = self.thread_get_avatar_mini('res.users', 'avatar_mini', record.user_id[0]); + if (record.type == 'email') { record.mini_url = ('/mail/static/src/img/email_icon.png'); } + else { record.mini_url = self.thread_get_avatar_mini('res.users', 'avatar_mini', record.user_id[0]); } record.body_text = self.do_replace_internal_links(record.body_text); var render_res = session.web.qweb.render('ThreadMsg', { 'record': record, }); - $('
').html(render_res).appendTo(self.$element.find('div.oe_mail_thread_display')); + $(render_res).appendTo(self.$element.find('div.oe_mail_thread_display')); }); + // add and bind "more button" + $(session.web.qweb.render('MoreButton', {})).appendTo(self.$element.find('div.oe_mail_thread_display')); + this.$element.find('button.oe_mail_button_more').bind('click', function () { self.do_more(); }); + }, + + display_current_user: function () { + $('
').html( + '' + ).appendTo(this.$element.find('div.oe_mail_msg_image')); }, do_comment: function () { @@ -88,26 +93,8 @@ openerp.mail = function(session) { this.proxy('fetch_comments')); }, - /* check for internal links, and map them to limitate number of queries -- WIP, probably not useful */ - check_internal_links: function(string) { - /* shortcut to user: @login */ - var regex_login = new RegExp(/(^|\s)@(\w*[a-zA-Z_.]+\w*\s)/g); - var regex_res = regex_login.exec(string); - while (regex_res != null) { - var login = regex_res[2]; - this.map_hash['res.users'].push(login); - regex_res = regex_login.exec(string); - } - /* internal links: @res.model,name */ - var regex_intlink = new RegExp(/(^|\s)@(\w*[a-zA-Z_]+\w*)\.(\w+[a-zA-Z_]+\w*),(\w+)/g); - regex_res = regex_intlink.exec(string); - while (regex_res != null) { - var res_model = regex_res[2] + '.' + regex_res[3]; - var res_name = regex_res[4]; - if (! (res_model in this.map_hash)) { this.map_hash[res_model] = []; } - this.map_hash[res_model].push(res_name); - regex_res = regex_intlink.exec(string); - } + do_more: function () { + console.log('do more !'); }, do_replace_internal_links: function (string) { @@ -135,6 +122,28 @@ openerp.mail = function(session) { return string; }, + /* check for internal links, and map them to limitate number of queries -- WIP, probably not useful */ + check_internal_links: function(string) { + /* shortcut to user: @login */ + var regex_login = new RegExp(/(^|\s)@(\w*[a-zA-Z_.]+\w*\s)/g); + var regex_res = regex_login.exec(string); + while (regex_res != null) { + var login = regex_res[2]; + this.map_hash['res.users'].push(login); + regex_res = regex_login.exec(string); + } + /* internal links: @res.model,name */ + var regex_intlink = new RegExp(/(^|\s)@(\w*[a-zA-Z_]+\w*)\.(\w+[a-zA-Z_]+\w*),(\w+)/g); + regex_res = regex_intlink.exec(string); + while (regex_res != null) { + var res_model = regex_res[2] + '.' + regex_res[3]; + var res_name = regex_res[4]; + if (! (res_model in this.map_hash)) { this.map_hash[res_model] = []; } + this.map_hash[res_model].push(res_name); + regex_res = regex_intlink.exec(string); + } + }, + thread_get_avatar_mini: function(model, field, id) { return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || ''); }, diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 393ab9d49b3..9f0448a9469 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -25,6 +25,22 @@
+ +
+ Discussion about document (id: ) +
+
+
+
+ + +
+ +
+
+
Discussion about document (id: ) @@ -57,45 +73,55 @@
-
- +
+
- +
-

- - OpenERP System Notification - - - - - - - - - - Need action by - -
-
- -

+ + + + + +
+
+ + +

+ + OpenERP System Notification + + + + + + + + - Need action by + + wrote on +
+ +

- - -
- Discussion about document (id: ) -
-
-
+ + +

+ From: on
+ To:
+

+

+ +

From 1a79ad88b4186315096951cc7a424b568fdebfa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 27 Feb 2012 12:08:28 +0100 Subject: [PATCH 04/18] [ADD] Email icon (replace author avatar when message type is email). bzr revid: tde@openerp.com-20120227110828-x9k3pcb3b6y72hz0 --- addons/mail/static/src/img/email_icon.png | Bin 0 -> 2772 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 addons/mail/static/src/img/email_icon.png diff --git a/addons/mail/static/src/img/email_icon.png b/addons/mail/static/src/img/email_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6390d9e6e696cb65d48530ad4e4bdbe0b86fb751 GIT binary patch literal 2772 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 Date: Mon, 27 Feb 2012 17:04:42 +0100 Subject: [PATCH 05/18] [IMP] ThreadDisplay: 1/ body_text is escaped by hand and displayed as html, to preserver internal links 2/ basic version of fonctionality 'show more / show less' when messages are too long 3/ some code cleaning bzr revid: tde@openerp.com-20120227160442-43g2b2e1wcrjhufq --- addons/mail/static/src/js/mail.js | 160 +++++++++++++++++----------- addons/mail/static/src/xml/mail.xml | 25 +++-- 2 files changed, 113 insertions(+), 72 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 31e1df75f35..1879a117c1f 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -12,20 +12,31 @@ openerp.mail = function(session) { mail.ThreadDisplay = session.web.Widget.extend({ // QWeb template to use when rendering the object template: 'ThreadDisplay', - + + /** + * + * @params {Object} parent parent + * @params {Object} [params] + * @param {String} [params.res_model] res_model of mail.thread object + * @param {Number} [params.res_id] res_id of record + * @param {Number} [params.uid] user id + * @param {Number} [params.char_show_more=100] number of character to display before adding a "show more" + * @param {Number} [params.limit=10] maximum number of messages to fetch + * @param {Number} [params.offset=0] offset for fetchign messages + * @param {Number} [params.records=null] records to show instead of fetching messages + */ init: function(parent, params) { this._super(parent); - this.res_model = params['res_model']; - this.res_id = params['res_id']; - this.uid = params['uid']; - this.limit = params['limit'] || 10; - this.offset = params['offset'] || 0; - this.cur_limit = this.limit; - this.records = params['records'] || false; + console.log(parent); + this.params = params; + this.params.limit = this.params.limit || 10; + this.params.offset = this.params.offset || 0; + this.params.records = this.params.records || null; + this.params.char_show_more = this.params.char_show_more || 100; // tmp this.map_hash = {'res.users': []}; /* DataSets */ - this.ds = new session.web.DataSet(this, this.res_model); + this.ds = new session.web.DataSet(this, this.params.res_model); this.ds_users = new session.web.DataSet(this, 'res.users'); }, @@ -35,7 +46,7 @@ openerp.mail = function(session) { /* bind buttons */ this.$element.find('button.oe_mail_button_comment').bind('click', function () { self.do_comment(); }); /* delegate links */ - self.$element.find('div.oe_mail_thread_display').delegate('a', 'click', function (event) { + self.$element.find('div.oe_mail_thread_display').delegate('a.intlink', 'click', function (event) { var res_model = event.srcElement.dataset.resModel; var res_id = event.srcElement.dataset.resId; self.do_action({ @@ -47,38 +58,60 @@ openerp.mail = function(session) { }); /* display user, fetch comments */ this.display_current_user(); - if (this.records == false) return this.fetch_comments(); - else return this.display_comments(this.records); + if (this.records) return this.display_comments(this.records); + else return this.init_comments(); }, stop: function () { this._super.apply(this, arguments); }, - fetch_comments: function () { - return this.ds.call('message_load', [[this.res_id]]).then(this.proxy('display_comments')); + init_comments: function() { + var self = this; + this.params.offset = 0; + this.$element.find('div.oe_mail_thread_display').empty(); + return this.fetch_comments().then(function () { + self.$element.find('button.oe_mail_button_more').bind('click', function () { self.do_more(); }); + }); + }, + + fetch_comments: function (limit, offset) { + return this.ds.call('message_load', [[this.params.res_id], limit=(limit||this.params.limit), offset=(offset||this.params.offset)]).then( + this.proxy('display_comments')); }, display_comments: function (records) { var self = this; - this.$element.find('div.oe_mail_thread_display').empty(); /* WIP: map matched regexp -> records to browse with name */ _(records).each(function (record) { - self.check_internal_links(record.body_text); + //self.check_internal_links(record.body_text); }); //console.log(this.map_hash); _(records).each(function (record) { if (record.type == 'email') { record.mini_url = ('/mail/static/src/img/email_icon.png'); } else { record.mini_url = self.thread_get_avatar_mini('res.users', 'avatar_mini', record.user_id[0]); } + // body text manipulation + record.body_text = self.do_clean_text(record.body_text); + record.tr_body_text = self.truncate_string(record.body_text, self.params.char_show_more); record.body_text = self.do_replace_internal_links(record.body_text); - var render_res = session.web.qweb.render('ThreadMsg', { - 'record': record, + if (record.tr_body_text) record.tr_body_text = self.do_replace_internal_links(record.tr_body_text); + $(session.web.qweb.render('ThreadMsg', {'record': record})).appendTo(self.$element.find('div.oe_mail_thread_display')); + // truncated: hide full-text, show summary, add buttons + if (record.tr_body_text) { + var node = self.$element.find('span.oe_mail_msg_body:last').append('Show less'); + node.hide(); + node.find('a:last').click(function() { + node.hide(); new_node.show(); return false; }); - $(render_res).appendTo(self.$element.find('div.oe_mail_thread_display')); + self.$element.find('p.oe_mail_msg_p:last').append($('' + record.tr_body_text + 'Show more')); + var new_node = self.$element.find('span.oe_mail_msg_body_short:last'); + new_node.find('a:last').click(function() { + new_node.hide(); node.show(); return false; + }); + } }); - // add and bind "more button" - $(session.web.qweb.render('MoreButton', {})).appendTo(self.$element.find('div.oe_mail_thread_display')); - this.$element.find('button.oe_mail_button_more').bind('click', function () { self.do_more(); }); + // update offset for "More" buttons + this.params.offset += records.length; }, display_current_user: function () { @@ -89,64 +122,67 @@ openerp.mail = function(session) { do_comment: function () { var body_text = this.$element.find('textarea').val(); - return this.ds.call('message_append_note', [[this.res_id], 'Reply comment', body_text, type='comment']).then( - this.proxy('fetch_comments')); + return this.ds.call('message_append_note', [[this.params.res_id], 'Reply comment', body_text, type='comment']).then( + this.proxy('init_comments')); }, do_more: function () { - console.log('do more !'); + return this.fetch_comments(this.limit, this.offset); }, do_replace_internal_links: function (string) { var self = this; - /* internal links: @sale.order,32 */ - var regex_intlink = new RegExp(/(^|\s)@(\w*[a-zA-Z_]+\w*)\.(\w+[a-zA-Z_]+\w*),(\d+)/g); - var regex_res = regex_intlink.exec(string); - while (regex_res != null) { - var res_model = regex_res[2] + '.' + regex_res[3]; - var res_id = regex_res[4]; - string = string.replace(regex_res[0], '' + regex_res[1] + '' - + res_model + '(' + res_id + ')'); - regex_res = regex_intlink.exec(string); - } /* shortcut to user: @login */ - //var regex_login = new RegExp(/(^|\s)@(\w*[a-zA-Z_.]+\w*)/g); - //var regex_res = regex_login.exec(string); - //while (regex_res != null) { - //var res_model = regex_res[2] + '.' + regex_res[3]; - //var res_id = regex_res[4]; - //string = string.replace(regex_res[0], '' + regex_res[1] + '' - //+ res_model + '(' + res_id + ')'); - //regex_res = regex_intlink.exec(string); - //} - return string; - }, - - /* check for internal links, and map them to limitate number of queries -- WIP, probably not useful */ - check_internal_links: function(string) { - /* shortcut to user: @login */ - var regex_login = new RegExp(/(^|\s)@(\w*[a-zA-Z_.]+\w*\s)/g); + var regex_login = new RegExp(/(^|\s)@(\w*)/g); var regex_res = regex_login.exec(string); while (regex_res != null) { var login = regex_res[2]; - this.map_hash['res.users'].push(login); + var res_id = 1; + string = string.replace(regex_res[0], '@' + login + ''); regex_res = regex_login.exec(string); } - /* internal links: @res.model,name */ - var regex_intlink = new RegExp(/(^|\s)@(\w*[a-zA-Z_]+\w*)\.(\w+[a-zA-Z_]+\w*),(\w+)/g); - regex_res = regex_intlink.exec(string); - while (regex_res != null) { - var res_model = regex_res[2] + '.' + regex_res[3]; - var res_name = regex_res[4]; - if (! (res_model in this.map_hash)) { this.map_hash[res_model] = []; } - this.map_hash[res_model].push(res_name); - regex_res = regex_intlink.exec(string); - } + return string; }, + ///* check for internal links, and map them to limitate number of queries -- WIP, probably not useful */ + //check_internal_links: function(string) { + ///* shortcut to user: @login */ + ////var regex_login = new RegExp(/(^|\s)@(\w*[a-zA-Z_.]+\w*\s)/g); + //var regex_login = new RegExp(/(^|\s)@(\w*)/g); + //var regex_res = regex_login.exec(string); + //while (regex_res != null) { + //var login = regex_res[2]; + //this.map_hash['res.users'].push(login); + //regex_res = regex_login.exec(string); + //} + ///* internal links: #res.model,name */ + //var regex_intlink = new RegExp(/(^|\s)#(\w*[a-zA-Z_]+\w*)\.(\w+[a-zA-Z_]+\w*),(\w+)/g); + //regex_res = regex_intlink.exec(string); + //while (regex_res != null) { + //var res_model = regex_res[2] + '.' + regex_res[3]; + //var res_name = regex_res[4]; + //if (! (res_model in this.map_hash)) { this.map_hash[res_model] = []; } + //this.map_hash[res_model].push(res_name); + //regex_res = regex_intlink.exec(string); + //} + //}, + thread_get_avatar_mini: function(model, field, id) { return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || ''); }, + + truncate_string: function(string, max_length) { + var string_len = string.length; // TODO: check for whitespaces ? + if (string_len <= max_length) return false; + var new_string = string.slice(0, max_length); + return new_string; + }, + + do_clean_text: function (string) { + var html = $('
').text(string.replace(/\s+/g, ' ')).html().replace(new RegExp('<(/)?b\\s*>', 'gi'), '<$1b>'); + return html; + }, + }); diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 9f0448a9469..386197a0fce 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -32,14 +32,6 @@
- - -
- -
-
@@ -79,6 +71,11 @@
+
+
+ +
+
@@ -110,7 +107,7 @@ wrote on
- +

@@ -120,8 +117,16 @@ To:

- +

+ + +
+ +
+
From f48f10bcfa41c03439db4ee91d26be4d39772903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 27 Feb 2012 17:14:09 +0100 Subject: [PATCH 06/18] [REF] Cleaned a bit truncated message code bzr revid: tde@openerp.com-20120227161409-ej67dg04cy2deyjg --- addons/mail/static/src/css/mail.css | 3 ++- addons/mail/static/src/js/mail.js | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index be02336da41..653f71fc040 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -151,7 +151,8 @@ border-bottom: 1px solid #D2D9E7; } -.oe_mail_msg_body { +.oe_mail_msg_body a.reduce, .oe_mail_msg_body_short a.expand { + color: #4E43E7; } .oe_mail_msg_author { diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 1879a117c1f..3d7bca72190 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -95,16 +95,17 @@ openerp.mail = function(session) { record.tr_body_text = self.truncate_string(record.body_text, self.params.char_show_more); record.body_text = self.do_replace_internal_links(record.body_text); if (record.tr_body_text) record.tr_body_text = self.do_replace_internal_links(record.tr_body_text); + // render $(session.web.qweb.render('ThreadMsg', {'record': record})).appendTo(self.$element.find('div.oe_mail_thread_display')); // truncated: hide full-text, show summary, add buttons if (record.tr_body_text) { - var node = self.$element.find('span.oe_mail_msg_body:last').append('Show less'); + var node = self.$element.find('span.oe_mail_msg_body:last').append(' [ ... Show less]'); + self.$element.find('p.oe_mail_msg_p:last').append($('' + record.tr_body_text + ' [ ... Show more]')); + var new_node = self.$element.find('span.oe_mail_msg_body_short:last'); node.hide(); node.find('a:last').click(function() { node.hide(); new_node.show(); return false; }); - self.$element.find('p.oe_mail_msg_p:last').append($('' + record.tr_body_text + 'Show more')); - var new_node = self.$element.find('span.oe_mail_msg_body_short:last'); new_node.find('a:last').click(function() { new_node.hide(); node.show(); return false; }); From 1c100a848cac1939a3fb696c25a13e530e5f9a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 27 Feb 2012 17:21:58 +0100 Subject: [PATCH 07/18] [FIX] Added a class to internal links to delegate an action when clicking bzr revid: tde@openerp.com-20120227162158-q1hyvwxr04scwod7 --- addons/mail/static/src/js/mail.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 3d7bca72190..604f93af2cb 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -10,7 +10,6 @@ openerp.mail = function(session) { /* ThreadDisplay widget: display a thread of comments */ mail.ThreadDisplay = session.web.Widget.extend({ - // QWeb template to use when rendering the object template: 'ThreadDisplay', /** @@ -27,7 +26,6 @@ openerp.mail = function(session) { */ init: function(parent, params) { this._super(parent); - console.log(parent); this.params = params; this.params.limit = this.params.limit || 10; this.params.offset = this.params.offset || 0; @@ -139,7 +137,7 @@ openerp.mail = function(session) { while (regex_res != null) { var login = regex_res[2]; var res_id = 1; - string = string.replace(regex_res[0], '@' + login + ''); + string = string.replace(regex_res[0], '@' + login + ''); regex_res = regex_login.exec(string); } return string; From 83ef71f651885b60ab11da5963b03598ed4a6608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 27 Feb 2012 18:13:23 +0100 Subject: [PATCH 08/18] [REF] Some code cleaning. Hashtag replacement still not working. bzr revid: tde@openerp.com-20120227171323-xvn752llibh66v9w --- addons/mail/static/src/js/mail.js | 100 +++++++++++++++--------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 604f93af2cb..5b83020fdc4 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -31,9 +31,8 @@ openerp.mail = function(session) { this.params.offset = this.params.offset || 0; this.params.records = this.params.records || null; this.params.char_show_more = this.params.char_show_more || 100; - // tmp - this.map_hash = {'res.users': []}; - /* DataSets */ + this.map_hash = {'res.users': {'login': [] }}; + /* define DataSets */ this.ds = new session.web.DataSet(this, this.params.res_model); this.ds_users = new session.web.DataSet(this, 'res.users'); }, @@ -45,12 +44,10 @@ openerp.mail = function(session) { this.$element.find('button.oe_mail_button_comment').bind('click', function () { self.do_comment(); }); /* delegate links */ self.$element.find('div.oe_mail_thread_display').delegate('a.intlink', 'click', function (event) { - var res_model = event.srcElement.dataset.resModel; - var res_id = event.srcElement.dataset.resId; self.do_action({ type: 'ir.actions.act_window', - res_model: res_model, - res_id: parseInt(res_id), + res_model: event.srcElement.dataset.resModel, + res_id: parseInt(event.srcElement.dataset.resId), views: [[false, 'form']] }); }); @@ -81,32 +78,30 @@ openerp.mail = function(session) { display_comments: function (records) { var self = this; /* WIP: map matched regexp -> records to browse with name */ - _(records).each(function (record) { - //self.check_internal_links(record.body_text); - }); - //console.log(this.map_hash); + //_(records).each(function (record) { + //self.do_check_internal_links(record.body_text); + //}); _(records).each(function (record) { if (record.type == 'email') { record.mini_url = ('/mail/static/src/img/email_icon.png'); } else { record.mini_url = self.thread_get_avatar_mini('res.users', 'avatar_mini', record.user_id[0]); } + // body text manipulation record.body_text = self.do_clean_text(record.body_text); - record.tr_body_text = self.truncate_string(record.body_text, self.params.char_show_more); + record.tr_body_text = self.do_truncate_string(record.body_text, self.params.char_show_more); record.body_text = self.do_replace_internal_links(record.body_text); if (record.tr_body_text) record.tr_body_text = self.do_replace_internal_links(record.tr_body_text); + // render $(session.web.qweb.render('ThreadMsg', {'record': record})).appendTo(self.$element.find('div.oe_mail_thread_display')); + // truncated: hide full-text, show summary, add buttons if (record.tr_body_text) { var node = self.$element.find('span.oe_mail_msg_body:last').append(' [ ... Show less]'); self.$element.find('p.oe_mail_msg_p:last').append($('' + record.tr_body_text + ' [ ... Show more]')); var new_node = self.$element.find('span.oe_mail_msg_body_short:last'); node.hide(); - node.find('a:last').click(function() { - node.hide(); new_node.show(); return false; - }); - new_node.find('a:last').click(function() { - new_node.hide(); node.show(); return false; - }); + node.find('a:last').click(function() { node.hide(); new_node.show(); return false; }); + new_node.find('a:last').click(function() { new_node.hide(); node.show(); return false; }); } }); // update offset for "More" buttons @@ -115,7 +110,7 @@ openerp.mail = function(session) { display_current_user: function () { $('
').html( - '' + '' ).appendTo(this.$element.find('div.oe_mail_msg_image')); }, @@ -137,50 +132,57 @@ openerp.mail = function(session) { while (regex_res != null) { var login = regex_res[2]; var res_id = 1; - string = string.replace(regex_res[0], '@' + login + ''); + //var user_loaded = this.ds_users.call('search', [[['login', 'in', [login]]]]).then(function (records) { + //console.log(records); + //if (records) string = string.replace(regex_res[0], '@' + login + ''); + //}); + //$.when(user_loaded).then(function() { + //}); regex_res = regex_login.exec(string); } return string; }, - ///* check for internal links, and map them to limitate number of queries -- WIP, probably not useful */ - //check_internal_links: function(string) { - ///* shortcut to user: @login */ - ////var regex_login = new RegExp(/(^|\s)@(\w*[a-zA-Z_.]+\w*\s)/g); - //var regex_login = new RegExp(/(^|\s)@(\w*)/g); - //var regex_res = regex_login.exec(string); - //while (regex_res != null) { - //var login = regex_res[2]; - //this.map_hash['res.users'].push(login); - //regex_res = regex_login.exec(string); - //} - ///* internal links: #res.model,name */ - //var regex_intlink = new RegExp(/(^|\s)#(\w*[a-zA-Z_]+\w*)\.(\w+[a-zA-Z_]+\w*),(\w+)/g); - //regex_res = regex_intlink.exec(string); - //while (regex_res != null) { - //var res_model = regex_res[2] + '.' + regex_res[3]; - //var res_name = regex_res[4]; - //if (! (res_model in this.map_hash)) { this.map_hash[res_model] = []; } - //this.map_hash[res_model].push(res_name); - //regex_res = regex_intlink.exec(string); - //} - //}, - thread_get_avatar_mini: function(model, field, id) { return this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || ''); }, - - truncate_string: function(string, max_length) { - var string_len = string.length; // TODO: check for whitespaces ? - if (string_len <= max_length) return false; - var new_string = string.slice(0, max_length); - return new_string; + + do_truncate_string: function(string, max_length) { + if (string.length <= max_length) return false; + else return string.slice(0, max_length); }, do_clean_text: function (string) { var html = $('
').text(string.replace(/\s+/g, ' ')).html().replace(new RegExp('<(/)?b\\s*>', 'gi'), '<$1b>'); return html; }, + + /** + * + * var regex_login = new RegExp(/(^|\s)@(\w*[a-zA-Z_.]+\w*\s)/g); + * var regex_login = new RegExp(/(^|\s)@(\w*)/g); + * var regex_intlink = new RegExp(/(^|\s)#(\w*[a-zA-Z_]+\w*)\.(\w+[a-zA-Z_]+\w*),(\w+)/g); + */ + do_check_internal_links: function(string) { + /* shortcut to user: @login */ + var regex_login = new RegExp(/(^|\s)@(\w*)/g); + var regex_res = regex_login.exec(string); + while (regex_res != null) { + var login = regex_res[2]; + this.map_hash['res.users']['login'].push(login); + regex_res = regex_login.exec(string); + } + /* internal links: #res.model,name */ + var regex_intlink = new RegExp(/(^|\s)#(\w*[a-zA-Z_]+\w*)\.(\w+[a-zA-Z_]+\w*),(\w+)/g); + regex_res = regex_intlink.exec(string); + while (regex_res != null) { + var res_model = regex_res[2] + '.' + regex_res[3]; + var res_name = regex_res[4]; + if (! (res_model in this.map_hash)) { this.map_hash[res_model]['name'] = []; } + this.map_hash[res_model]['name'].push(res_name); + regex_res = regex_intlink.exec(string); + } + }, }); From 66f55d4e83f3f5464928bb5f347b37b94e7875db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 09:26:06 +0100 Subject: [PATCH 09/18] [IMP] Wall thread view: lessened size of comment box in threads. bzr revid: tde@openerp.com-20120228082606-bfekwwkemxb0b3xn --- addons/mail/static/src/css/mail.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 653f71fc040..43c9c54afd0 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -20,6 +20,11 @@ margin-left: 5%; } +.oe_mail_wall_thread_content div.oe_mail_thread_act .oe_mail_action_textarea { + width: 100%; + height: 20px; + padding: 2px; +} /* Thread */ @@ -110,7 +115,7 @@ } .oe_mail_action_textarea { - width: 60%; + width: 80%; height: 50px; padding: 5px; } From a32d9d7b892effd23fa8f99114624aecc0fbb892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 09:51:11 +0100 Subject: [PATCH 10/18] [DOC] Added comments in mail.js bzr revid: tde@openerp.com-20120228085111-13kx0t7l7bxmywmq --- addons/mail/static/src/js/mail.js | 54 +++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 5b83020fdc4..a2d8a1faed1 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -294,13 +294,21 @@ openerp.mail = function(session) { /* WallView widget: a wall of messages */ mail.WallView = session.web.Widget.extend({ - // QWeb template to use when rendering the object template: 'Wall', + /** + * + * @param {Object} parent parent + * @param {Object} [params] + * @param {Number} [params.limit=20] number of messages to show and fetch + * @var {Array} sorted_comments records sorted by res_model and res_id + * records.res_model = {res_ids} + * records.res_model.res_id = [records] + */ init: function (parent, params) { this._super(parent); - this.filter_search = params['filter_search']; - this.search = {} + this.params.limit = params.limit || 20; + this.sorted_comments = {}; /* DataSets */ this.ds_msg = new session.web.DataSet(this, 'mail.message'); this.ds_thread = new session.web.DataSet(this, 'mail.thread'); @@ -324,7 +332,13 @@ openerp.mail = function(session) { stop: function () { this._super.apply(this, arguments); }, - + + /** + * + * @param {Number} view_id id of the search view to load + * @param {??} defaults ?? + * @param {Boolean} hidden ?? + */ load_search_view: function (view_id, defaults, hidden) { this.searchview = new session.web.SearchView(this, this.ds_msg, view_id || false, defaults || {}, hidden || false); return this.searchview.appendTo(this.$element.find('div.oe_mail_wall_search')); @@ -350,12 +364,16 @@ openerp.mail = function(session) { this.proxy('display_comments')); return load_res; }, - + + /** + * + * @param {Array} records records to show in threads + */ display_comments: function (records) { this.$element.find('div.oe_mail_wall_threads').empty(); - sorted_records = this.sort_comments(records); + this.sort_comments(records, this.sorted_comments); var self = this; - _(sorted_records).each(function (rec_models, model) { // each model + _(this.sorted_comments).each(function (rec_models, model) { // each model _(rec_models).each(function (record_id, id) { // each record var template = 'WallThreadContainer'; var render_res = session.web.qweb.render(template, { @@ -371,8 +389,15 @@ openerp.mail = function(session) { }); }, - sort_comments: function (records) { - sorted_comments = {}; + /** + * Add records to sorted_comments array + * @param {Array} records records from mail.message + * @param {Array} sorted_comments already sorted comments that will be updated + * @returns {Array} sorted_comments + * sorted_comments.res_model = {res_ids} + * sorted_comments.res_model.res_id = [records] + */ + sort_comments: function (records, sorted_comments) { _(records).each(function (record) { if (! (record.model in sorted_comments)) { sorted_comments[record.model] = {}; } if (! (record.res_id in sorted_comments[record.model])) { @@ -382,12 +407,21 @@ openerp.mail = function(session) { return sorted_comments; }, + /** + * Create a domain to fetch new comments according to + * comment already present in sorted_comments + * @returns {Array} fetch_domain (OpenERP domain style) + */ + get_fetch_domain: function (sorted_comments) { + + }, + do_comment: function () { var body_text = this.$element.find('textarea').val(); return this.ds_users.call('message_append_note', [[this.session.uid], 'Tweet', body_text, type='comment']).then( this.proxy('fetch_comments')); }, - + thread_get_mini: function(model, field, id) { id = id || ''; var url = this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + id; From e291bf11da4540d5eb17824b59a2e85da0d6f3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 09:56:07 +0100 Subject: [PATCH 11/18] [DOC] Added comments in mailL.js (Wall widget) bzr revid: tde@openerp.com-20120228085607-oty29x74cwxy6zdi --- addons/mail/static/src/js/mail.js | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index a2d8a1faed1..156f6ff4590 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -297,7 +297,6 @@ openerp.mail = function(session) { template: 'Wall', /** - * * @param {Object} parent parent * @param {Object} [params] * @param {Number} [params.limit=20] number of messages to show and fetch @@ -334,7 +333,7 @@ openerp.mail = function(session) { }, /** - * + * Loads the mail.message search view * @param {Number} view_id id of the search view to load * @param {??} defaults ?? * @param {Boolean} hidden ?? @@ -343,7 +342,15 @@ openerp.mail = function(session) { this.searchview = new session.web.SearchView(this, this.ds_msg, view_id || false, defaults || {}, hidden || false); return this.searchview.appendTo(this.$element.find('div.oe_mail_wall_search')); }, - + + /** + * Aggregate the domains, contexts and groupbys in parameter + * with those from search form, and then calls fetch_comments + * to actually fetch comments + * @param {Array} domains + * @param {Array} contexts + * @param {Array} groupbys + */ do_searchview_search: function(domains, contexts, groupbys) { var self = this; this.rpc('/web/session/eval_domain_and_context', { @@ -357,7 +364,14 @@ openerp.mail = function(session) { self.fetch_comments(self.search['domain'], self.search['context']); }); }, - + + /** + * Fetches Wall comments (mail.thread.get_pushed_messages) + * @param {Array} domains + * @param {Array} contexts + * @param {Array} groupbys + * @param {Number} limit number of messages to fetch + */ fetch_comments: function (domain, context, offset, limit) { var load_res = this.ds_thread.call('get_pushed_messages', [[this.session.uid], limit = (limit || 100), offset = (offset || 0), domain = (domain || null), context = (context || null) ]).then( @@ -366,7 +380,6 @@ openerp.mail = function(session) { }, /** - * * @param {Array} records records to show in threads */ display_comments: function (records) { From 504e476fc05800249b3cd2cccf31b89b9a32410e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 12:07:40 +0100 Subject: [PATCH 12/18] [IMP] Wall widget: removed unused xml; added more button; added more action (displays more discussions); added comments bzr revid: tde@openerp.com-20120228110740-gcbm02ej6bee4rsl --- addons/mail/static/src/js/mail.js | 79 ++++++++++++++++++++++------- addons/mail/static/src/xml/mail.xml | 13 ++--- 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 156f6ff4590..4a3b92cc895 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -53,7 +53,7 @@ openerp.mail = function(session) { }); /* display user, fetch comments */ this.display_current_user(); - if (this.records) return this.display_comments(this.records); + if (this.params.records) return this.display_comments(this.params.records); else return this.init_comments(); }, @@ -306,7 +306,10 @@ openerp.mail = function(session) { */ init: function (parent, params) { this._super(parent); + this.params = params || {}; this.params.limit = params.limit || 20; + this.params.search = {}; + this.params.domain = []; this.sorted_comments = {}; /* DataSets */ this.ds_msg = new session.web.DataSet(this, 'mail.message'); @@ -324,7 +327,7 @@ openerp.mail = function(session) { self.searchview.on_search.add(self.do_searchview_search); }); /* fetch comments */ - var comments_ready = this.fetch_comments(); + var comments_ready = this.init_comments(); return (search_view_ready && comments_ready); }, @@ -358,10 +361,27 @@ openerp.mail = function(session) { contexts: contexts || [], group_by_seq: groupbys || [] }, function (results) { - self.search['context'] = results.context; - self.search['domain'] = results.domain; - self.search['groupby'] = results.group_by; - self.fetch_comments(self.search['domain'], self.search['context']); + self.params.search['context'] = results.context; + self.params.search['domain'] = results.domain; + self.params.search['groupby'] = results.group_by; + self.init_comments(self.params.search['domain'], self.params.search['context']); + }); + }, + + /** + * Initializes Wall and calls fetch_comments + * @param {Array} domains + * @param {Array} contexts + * @param {Array} groupbys + * @param {Number} limit number of messages to fetch + */ + init_comments: function(domain, context, offset, limit) { + var self = this; + this.params.domain = []; + this.sorted_comments = {}; + this.$element.find('div.oe_mail_wall_threads').empty(); + return this.fetch_comments(domain, context, offset, limit).then(function () { + self.$element.find('button.oe_mail_wall_button_more').bind('click', function () { self.do_more(); }); }); }, @@ -383,10 +403,9 @@ openerp.mail = function(session) { * @param {Array} records records to show in threads */ display_comments: function (records) { - this.$element.find('div.oe_mail_wall_threads').empty(); - this.sort_comments(records, this.sorted_comments); + var sorted_comments = this.sort_comments(records, this.sorted_comments); var self = this; - _(this.sorted_comments).each(function (rec_models, model) { // each model + _(sorted_comments).each(function (rec_models, model) { // each model _(rec_models).each(function (record_id, id) { // each record var template = 'WallThreadContainer'; var render_res = session.web.qweb.render(template, { @@ -394,23 +413,24 @@ openerp.mail = function(session) { 'record_id': id, }); $('
').html(render_res).appendTo(self.$element.find('div.oe_mail_wall_threads')); - self.thread_display = new mail.ThreadDisplay(self, + var thread_display = new mail.ThreadDisplay(self, {'res_model': model, 'res_id': parseInt(id), 'uid': self.session.uid, 'records': record_id} ); - self.thread_display.appendTo(self.$element.find('div.oe_mail_wall_thread_content:last')); + thread_display.appendTo(self.$element.find('div.oe_mail_wall_thread_content:last')); }); }); + $.extend(true, this.sorted_comments, sorted_comments); }, /** * Add records to sorted_comments array * @param {Array} records records from mail.message - * @param {Array} sorted_comments already sorted comments that will be updated - * @returns {Array} sorted_comments - * sorted_comments.res_model = {res_ids} - * sorted_comments.res_model.res_id = [records] + * @returns {Object} sorted_comments: dict + * sorted_comments.res_model = {res_ids} + * sorted_comments.res_model.res_id = [records] */ - sort_comments: function (records, sorted_comments) { + sort_comments: function (records) { + sorted_comments = {} _(records).each(function (record) { if (! (record.model in sorted_comments)) { sorted_comments[record.model] = {}; } if (! (record.res_id in sorted_comments[record.model])) { @@ -423,18 +443,41 @@ openerp.mail = function(session) { /** * Create a domain to fetch new comments according to * comment already present in sorted_comments + * @param {Object} sorted_comments (see sort_comments) * @returns {Array} fetch_domain (OpenERP domain style) */ get_fetch_domain: function (sorted_comments) { - + var domain = []; + _(sorted_comments).each(function (rec_models, model) { //each model + var ids = []; + _(rec_models).each(function (record_id, id) { // each record + ids.push(id); + }); + domain.push('|', ['model', '!=', model], ['res_id', 'not in', ids]); + }); + return domain; }, + /** + * Action: Posts a comment + */ do_comment: function () { var body_text = this.$element.find('textarea').val(); return this.ds_users.call('message_append_note', [[this.session.uid], 'Tweet', body_text, type='comment']).then( this.proxy('fetch_comments')); }, - + + /** + * Action: Shows more discussions + */ + do_more: function () { + var domain = this.get_fetch_domain(this.sorted_comments); + return this.fetch_comments(domain); + }, + + /** + * Tools: get avatar mini (TODO: should be moved in some tools ?) + */ thread_get_mini: function(model, field, id) { id = id || ''; var url = this.session.prefix + '/web/binary/image?session_id=' + this.session.session_id + '&model=' + model + '&field=' + field + '&id=' + id; diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 386197a0fce..b2cc1e8e0c7 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -13,6 +13,11 @@
+
+ +
@@ -25,14 +30,6 @@
- -
- Discussion about document (id: ) -
-
-
-
-
Discussion about document (id: ) From 17d077bb7d9826f581bb7611e2c9a9ce378785df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 12:23:07 +0100 Subject: [PATCH 13/18] [FIX] Fixed bug when posting a comment from the wall (wrong values given through this.proxy, have to check) bzr revid: tde@openerp.com-20120228112307-8mwlrcqx66h07ood --- addons/mail/static/src/js/mail.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 4a3b92cc895..d49b7a0768c 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -464,7 +464,8 @@ openerp.mail = function(session) { do_comment: function () { var body_text = this.$element.find('textarea').val(); return this.ds_users.call('message_append_note', [[this.session.uid], 'Tweet', body_text, type='comment']).then( - this.proxy('fetch_comments')); + //this.proxy('fetch_comments')); + this.init_comments()); }, /** From d682be4242e0782918e176ef2245fb6990e6e304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 15:04:07 +0100 Subject: [PATCH 14/18] [FIX] crm: fixed 2 write calls not using a list of ids, causing issues with mail.thread bzr revid: tde@openerp.com-20120228140407-uwqetqg3tb0d2try --- addons/crm/crm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 7775e442df7..a2751310237 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -267,7 +267,7 @@ class crm_base(object): data = {'state': 'open', 'active': True} if not case.user_id: data['user_id'] = uid - self.write(cr, uid, case.id, data) + self.write(cr, uid, [case.id], data) self._action(cr, uid, cases, 'open') return True @@ -397,7 +397,7 @@ class crm_case(crm_base): data = {'state': 'open', 'active': True } if not case.user_id: data['user_id'] = uid - self.write(cr, uid, case.id, data) + self.write(cr, uid, [case.id], data) self._action(cr, uid, cases, 'open') return True From acf162b951b8293e660ab719e9f4b520ae134f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 15:06:32 +0100 Subject: [PATCH 15/18] [IMP][FIX] creating and updating a record automatically subscribe the user. Fixed message_is_subscriber not calling message_get_subscribers, leading to wrong calculation when message_get_subscribers was overwriten. bzr revid: tde@openerp.com-20120228140632-jd27456g1e9fu056 --- addons/mail/mail_thread.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 1e8d3060313..91a4088c1a0 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -68,6 +68,21 @@ class mail_thread(osv.osv): ), #widget='mail.ThreadView'), } + + #------------------------------------------------------ + # Automatic subscription when creating/reading + #------------------------------------------------------ + + def create(self, cr, uid, vals, context=None): + thread_id = super(mail_thread, self).create(cr, uid, vals, context=context); + self.message_subscribe(cr, uid, [thread_id], [uid], context=context) + return thread_id; + + def write(self, cr, uid, ids, vals, context=None): + write_res = super(mail_thread, self).write(cr, uid, ids, vals, context=context); + if write_res: + self.message_subscribe(cr, uid, ids, [uid], context=context) + return write_res; #------------------------------------------------------ # Generic message api @@ -598,13 +613,10 @@ class mail_thread(osv.osv): return users def message_is_subscriber(self, cr, uid, ids, context=None): - # TODO: use message_get_subscribers ? as all subscriptions are in mail.subscription table, not necessary - subscription_obj = self.pool.get('mail.subscription') - sub_ids = subscription_obj.search(cr, uid, - ['&', '&', ('res_model', '=', self._name), ('res_id', 'in', ids), ('user_id', '=', uid)], context=context) - if len(sub_ids) > 1: - pass # TODO - return True if sub_ids else False + users = self.message_get_subscribers(cr, uid, ids, context=context) + if uid in [user['id'] for user in users]: + return True + return False def message_subscribe(self, cr, uid, ids, user_ids = None, context=None): subscription_obj = self.pool.get('mail.subscription') From 6149b0d9957fcb898eae25b5b8a92c1eca5b9aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 15:07:30 +0100 Subject: [PATCH 16/18] [IMP] hr_holidays: deleted automatic subscription creation, now delegated to mail.thread (user that creates is automatically subscribed) and message_get_subscribers (manager is always considered as subscribed) bzr revid: tde@openerp.com-20120228140730-xke7ys2j2vcx3ruo --- addons/hr_holidays/hr_holidays.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py index 78db0dc7063..f63dcf9632d 100644 --- a/addons/hr_holidays/hr_holidays.py +++ b/addons/hr_holidays/hr_holidays.py @@ -358,12 +358,16 @@ class hr_holidays(osv.osv): # OpenChatter and notifications # ----------------------------- + def message_get_subscribers(self, cr, uid, ids, context=None): + sub_ids = self._message_get_subscribers_ids(cr, uid, ids, context=context); + # add the employee and its manager if specified to the subscribed users + for obj in self.browse(cr, uid, ids, context=context): + if obj.employee_id.parent_id: + sub_ids.append(obj.employee_id.parent_id.user_id.id) + return self.pool.get('res.users').read(cr, uid, sub_ids, context=context) + def create_notificate(self, cr, uid, ids, context=None): for obj in self.browse(cr, uid, ids, context=context): - # add the employee and its manager if specified to the subscribed users - self.message_subscribe(cr, uid, ids, [obj.employee_id.user_id.id], context=context) - if obj.employee_id.parent_id: - self.message_subscribe(cr, uid, ids, [obj.employee_id.parent_id.user_id.id], context=context) self.message_append_note(cr, uid, ids, _('System notification'), _("The %s request '%s' has been created and is waiting confirmation") % ('leave' if obj.type == 'remove' else 'allocation', obj.name), type='notification', context=context) From 9d4afb665974e738fc2854857bcc71c6b3356646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 15:38:30 +0100 Subject: [PATCH 17/18] [FIX][IMP] mail.thread: message_is_subscriber now has an optional user_id parameter, to check a given id instead of uid. message_subscribe now checks if the user to subscribe has not already a subscription for that record. bzr revid: tde@openerp.com-20120228143830-wyiq1glltswzjacs --- addons/mail/mail_thread.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 91a4088c1a0..85c297fb07f 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -612,18 +612,21 @@ class mail_thread(osv.osv): users = self.pool.get('res.users').read(cr, uid, user_ids, fields=['id', 'name', 'avatar_mini'], context=context) return users - def message_is_subscriber(self, cr, uid, ids, context=None): + def message_is_subscriber(self, cr, uid, ids, user_id = None, context=None): users = self.message_get_subscribers(cr, uid, ids, context=context) - if uid in [user['id'] for user in users]: + sub_user_id = uid if user_id is None else user_id + if sub_user_id in [user['id'] for user in users]: return True return False def message_subscribe(self, cr, uid, ids, user_ids = None, context=None): subscription_obj = self.pool.get('mail.subscription') sub_user_ids = [uid] if user_ids is None else user_ids + create_ids = [] for id in ids: - create_ids = [subscription_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': user_id}, context=context) - for user_id in sub_user_ids] + for user_id in sub_user_ids: + if self.message_is_subscriber(cr, uid, [id], user_id=user_id, context=context): continue + create_ids.append(subscription_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': user_id}, context=context)) return create_ids def message_unsubscribe(self, cr, uid, ids, context=None): From 526281d4709456a8159daf03eb51962e158a9d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 28 Feb 2012 16:14:41 +0100 Subject: [PATCH 18/18] [FIX] crm_partner_assign, hr_recruitment: fixed 2 write using an int instead of list bzr revid: tde@openerp.com-20120228151441-kow3r6nn96qn6w4q --- addons/crm_partner_assign/wizard/crm_forward_to_partner.py | 2 +- .../wizard/hr_recruitment_create_partner_job.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/crm_partner_assign/wizard/crm_forward_to_partner.py b/addons/crm_partner_assign/wizard/crm_forward_to_partner.py index 565f99b9db1..97d9ecac787 100644 --- a/addons/crm_partner_assign/wizard/crm_forward_to_partner.py +++ b/addons/crm_partner_assign/wizard/crm_forward_to_partner.py @@ -138,7 +138,7 @@ class crm_lead_forward_to_partner(osv.osv_memory): if email_to not in new_cc: new_cc.append(to) update_vals = {'email_cc' : ', '.join(new_cc) } - lead.write(cr, uid, case.id, update_vals, context=context) + lead.write(cr, uid, [case.id], update_vals, context=context) return res def _get_info_body_text(self, cr, uid, lead, context=None): diff --git a/addons/hr_recruitment/wizard/hr_recruitment_create_partner_job.py b/addons/hr_recruitment/wizard/hr_recruitment_create_partner_job.py index dd1667aecef..ade9ce3deed 100644 --- a/addons/hr_recruitment/wizard/hr_recruitment_create_partner_job.py +++ b/addons/hr_recruitment/wizard/hr_recruitment_create_partner_job.py @@ -68,7 +68,7 @@ class hr_recruitment_partner_create(osv.osv_memory): 'email': case.email_from }, context=context) - case_obj.write(cr, uid, case.id, { + case_obj.write(cr, uid, [case.id], { 'partner_id': partner_id, 'partner_address_id': contact_id }, context=context) @@ -88,4 +88,4 @@ class hr_recruitment_partner_create(osv.osv_memory): hr_recruitment_partner_create() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: