diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index af4818bcbcd..8269049f917 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -694,7 +694,13 @@ class mail_thread(osv.AbstractModel): # TDE FIXME: body is plaintext: convert it into html # when writing on res.partner, without specific thread_id -> redirect to the user's partner if self._name == 'res.partner' and not thread_id: - thread_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0] + thread_id = self.pool.get('res.users').read(cr, uid, uid, ['partner_id', 'subject'], context=context)['partner_id'][0] + + mail_message = self.pool.get('mail.message') + + if not subject and parent_id: + parent = mail_message.read(cr, uid, parent_id, ['subject'], context=context) + subject = 'Re: ' + parent['subject'] new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, context=context) @@ -702,7 +708,6 @@ class mail_thread(osv.AbstractModel): # Chatter: attachments linked to the document (not done JS-side), load the message if attachments: ir_attachment = self.pool.get('ir.attachment') - mail_message = self.pool.get('mail.message') attachment_ids = ir_attachment.search(cr, SUPERUSER_ID, [('res_model', '=', 'mail.compose.message'), ('res_id', '=', 0), ('create_uid', '=', uid), ('id', 'in', attachments)], context=context) if attachment_ids: ir_attachment.write(cr, SUPERUSER_ID, attachment_ids, {'res_model': self._name, 'res_id': thread_id}, context=context) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 921890926e6..daa8594cba4 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -151,9 +151,11 @@ padding-top: 2px; padding-bottom:6px; } -.openerp .oe_mail .oe_msg_attachments.oe_hidden{ +.openerp .oe_mail .oe_msg_attachments.oe_hidden, +.openerp .oe_mail .oe_msg_images.oe_hidden{ margin:0px; border: none; + display: none; } .openerp .oe_mail .oe_msg_attachments{ margin-bottom: 4px; @@ -311,6 +313,14 @@ border-radius: 2px; } +/* ---------------- MESSAGES BODY ------------------ */ +.openerp .oe_mail .oe_msg_content .oe_blockquote, +.openerp .oe_mail .oe_msg_content blockquote { + padding: 4px; + border-radius: 2px; + border: solid 1px rgba(124,123,173,0.14); +} + /* ----------- FORM INTEGRATION ------------ */ /* Nothing to do yay! */ diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 1779d1a6562..78aa3e8513d 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1,4 +1,4 @@ -openerp.mail = function(session) { +openerp.mail = function (session) { var _t = session.web._t, _lt = session.web._lt; @@ -16,7 +16,9 @@ openerp.mail = function(session) { */ session.web.FormView = session.web.FormView.extend({ - do_action: function(action) { + do_action: function (action) { + console.log(action); + if (action.res_model == 'mail.compose.message') { /* hack for stop context propagation of wrong value * delete this hack when a global method to clean context is create @@ -24,7 +26,7 @@ openerp.mail = function(session) { var context_keys = ['default_template_id', 'default_composition_mode', 'default_use_template', 'default_partner_ids', 'default_model', 'default_res_id', 'default_content_subtype', 'active_id', 'lang', - 'bin_raw', 'tz', 'active_model', 'edi_web_url_view', 'active_ids'] + 'bin_raw', 'tz', 'active_model', 'edi_web_url_view', 'active_ids', 'default_subject'] for (var key in action.context) { if (_.indexOf(context_keys, key) == -1) { action.context[key] = null; @@ -53,7 +55,7 @@ openerp.mail = function(session) { /** *Get an image in /web/binary/image?... */ - get_image: function(session, model, field, id) { + get_image: function (session, model, field, id) { return session.prefix + '/web/binary/image?session_id=' + session.session_id + '&model=' + model + '&field=' + field + '&id=' + (id || ''); }, @@ -85,7 +87,7 @@ openerp.mail = function(session) { * (add

, ) * TDE note : should not be here, but server-side I think ... */ - get_text2html: function(text){ + get_text2html: function (text) { return text .replace(/[\n\r]/g,'
') .replace(/((?:https?|ftp):\/\/[\S]+)/g,'
$1 ') @@ -106,7 +108,7 @@ openerp.mail = function(session) { nb_and += 1; } - for (var k = 0; k < nb_and ; k++){ + for (var k = 0; k < nb_and ; k++) { domain.unshift('&'); } @@ -155,6 +157,7 @@ openerp.mail = function(session) { this.is_private = datasets.is_private || false; this.partner_ids = datasets.partner_ids || []; this.avatar = mail.ChatterUtils.get_image(this.session, 'res.users', 'image_small', this.session.uid); + this.thread_level = datasets.thread_level; this.parent_thread= parent.messages!= undefined ? parent : false; this.ds_attachment = new session.web.DataSetSearch(this, 'ir.attachment'); @@ -167,10 +170,10 @@ openerp.mail = function(session) { this.$render_compact = false; }, - start: function(){ + start: function () { this.$render_compact = this.$el; - if( this.options.show_compact_message ) { + if ( this.options.show_compact_message ) { this.$render_compact.show(); } else { this.$render_compact.hide(); @@ -180,10 +183,10 @@ openerp.mail = function(session) { /* upload the file on the server, add in the attachments list and reload display */ - display_attachments: function(){ + display_attachments: function () { var self = this; var render = $(session.web.qweb.render('mail.thread.message.attachments', {'widget': self})); - if(!this.list_attachment){ + if (!this.list_attachment) { this.$render_expandable.find('.oe_msg_attachment_list').replaceWith( render ); } else { this.list_attachment.replaceWith( render ); @@ -206,9 +209,9 @@ openerp.mail = function(session) { // if the files exits for this answer, delete the file before upload var attachments=[]; - for(var i in this.attachment_ids){ - if((this.attachment_ids[i].filename || this.attachment_ids[i].name) == filename){ - if(this.attachment_ids[i].upload){ + for (var i in this.attachment_ids) { + if ((this.attachment_ids[i].filename || this.attachment_ids[i].name) == filename) { + if (this.attachment_ids[i].upload) { return false; } this.ds_attachment.unlink([this.attachment_ids[i].id]); @@ -237,8 +240,8 @@ openerp.mail = function(session) { /* when the file is uploaded */ on_attachment_loaded: function (event, result) { - for(var i in this.attachment_ids){ - if(this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload) { + for (var i in this.attachment_ids) { + if (this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload) { this.attachment_ids[i]={ 'id': result.id, 'name': result.name, @@ -261,8 +264,8 @@ openerp.mail = function(session) { var attachment_id=$(event.target).data("id"); if (attachment_id) { var attachments=[]; - for(var i in this.attachment_ids){ - if(attachment_id!=this.attachment_ids[i].id){ + for (var i in this.attachment_ids) { + if (attachment_id!=this.attachment_ids[i].id) { attachments.push(this.attachment_ids[i]); } else { @@ -274,18 +277,18 @@ openerp.mail = function(session) { } }, - bind_events: function() { + bind_events: function () { var self = this; this.$render_compact.find('textarea').unbind().on('focus', self.on_compose_expandable); - if(this.$render_expandable){ + if (this.$render_expandable) { // set the function called when attachments are added this.$render_expandable.on('change', 'input.oe_form_binary_file', self.on_attachment_change ); this.$render_expandable.on('click', '.oe_cancel', self.on_cancel ); - this.$render_expandable.on('click', '.oe_post', function(){self.on_message_post()} ); - this.$render_expandable.on('click', '.oe_full', function(){self.on_compose_fullmail()} ); + this.$render_expandable.on('click', '.oe_post', function () {self.on_message_post()} ); + this.$render_expandable.on('click', '.oe_full', function () {self.on_compose_fullmail('reply')} ); // auto close this.$render_expandable.on('blur', 'textarea', this.on_compose_expandable); @@ -297,15 +300,37 @@ openerp.mail = function(session) { } }, - on_compose_fullmail: function(){ + on_compose_fullmail: function (default_composition_mode) { /* TDE note: I think this is not necessary, because * 1/ post on a document: followers added server-side in _notify * 2/ reply to a message: mail.compose.message should add the previous partners */ - var partner_ids=[]; - for(var i in this.partner_ids){ + var partner_ids = []; + for (var i in this.partner_ids) { partner_ids.push(this.partner_ids[i][0]); } + + if (default_composition_mode == 'reply') { + var context = { + 'default_composition_mode': 'reply', + 'default_parent_id': this.id, + 'default_body': mail.ChatterUtils.get_text2html(this.$render_expandable ? (this.$render_expandable.find('textarea').val() || '') : ''), + 'default_attachment_ids': this.attachment_ids, + 'default_partner_ids': [], //partner_ids + }; + } else { + var context = { + 'default_model': this.context.default_model, + 'default_res_model': this.context.default_model, + 'default_res_id': this.context.default_res_id, + 'default_content_subtype': 'html', + 'default_composition_mode': 'comment', + 'default_parent_id': this.id, + 'default_body': mail.ChatterUtils.get_text2html(this.$render_expandable ? (this.$render_expandable.find('textarea').val() || '') : ''), + 'default_attachment_ids': this.attachment_ids, + 'default_partner_ids': [], //partner_ids + }; + } var action = { type: 'ir.actions.act_window', res_model: 'mail.compose.message', @@ -314,26 +339,18 @@ openerp.mail = function(session) { action_from: 'mail.ThreadComposeMessage', views: [[false, 'form']], target: 'new', - context: { - 'default_model': this.context.default_model, - 'default_res_model': this.context.default_model, - 'default_res_id': this.context.default_res_id, - 'default_content_subtype': 'html', - 'default_parent_id': this.id, - 'default_body': mail.ChatterUtils.get_text2html(this.$render_expandable ? (this.$render_expandable.find('textarea').val() || '') : ''), - 'default_attachment_ids': this.attachment_ids, - 'default_partner_ids': partner_ids - }, + context: context, }; + this.do_action(action); - if(this.$render_expandable) { + if (this.$render_expandable) { this.on_cancel(); } }, - on_cancel: function(event){ - if(event) event.stopPropagation(); + on_cancel: function (event) { + if (event) event.stopPropagation(); this.$render_expandable.find('textarea').val(""); this.$render_expandable.find('input[data-id]').remove(); @@ -355,15 +372,15 @@ openerp.mail = function(session) { } var attachments=[]; - for(var i in this.attachment_ids){ - if(this.attachment_ids[i].upload){ + for (var i in this.attachment_ids) { + if (this.attachment_ids[i].upload) { session.web.dialog($('

' + session.web.qweb.render('CrashManager.warning', {message: 'Please, wait while the file is uploading.'}) + '
')); return false; } attachments.push(this.attachment_ids[i].id); } - if(body.match(/\S+/)) { + if (body.match(/\S+/)) { //session.web.blockUI(); this.parent_thread.ds_thread.call('message_post_api', [ this.context.default_res_id, @@ -374,8 +391,13 @@ openerp.mail = function(session) { this.context.default_parent_id, attachments, this.parent_thread.context - ]).then(function(records){ - self.parent_thread.switch_new_message(records); + ]).then(function (record) { + var thread = self.parent_thread; + // create object and attach to the thread object + var message = thread.create_message_object( record[0] ); + // insert the message on dom + thread.insert_message( message, self.thread_level > self.options.display_indented_thread ? self.parent_thread.$el : self.$el ); + // clean compose message self.on_cancel(); //session.web.unblockUI(); }); @@ -385,8 +407,8 @@ openerp.mail = function(session) { /* create the compose on expandable form */ - instantiate_expandable: function() { - if(!this.$render_expandable) { + instantiate_expandable: function () { + if (!this.$render_expandable) { this.$render_expandable = $(session.web.qweb.render('mail.compose_message', {'widget': this})); this.$render_expandable.hide(); @@ -399,26 +421,26 @@ openerp.mail = function(session) { /* convert the compact mode into the compose message */ - on_compose_expandable: function(event){ - if(event) event.stopPropagation(); + on_compose_expandable: function (event) { + if (event) event.stopPropagation(); var self = this; this.instantiate_expandable(); - if(this.$render_expandable.is(':hidden')){ + if (this.$render_expandable.is(':hidden')) { - this.$render_expandable.show(); + this.$render_expandable.css('display', ''); this.$render_compact.hide(); this.$render_expandable.find('textarea').focus(); - } else if(!this.stay_open){ + } else if (!this.stay_open) { // do not close the box if there are some text - if(!this.$render_expandable.find('textarea').val().match(/\S+/)){ + if (!this.$render_expandable.find('textarea').val().match(/\S+/)) { this.$render_expandable.hide(); - if(this.options.show_compact_message && this.show_compact_message) { - this.$render_compact.show(); + if (this.options.show_compact_message && this.show_compact_message) { + this.$render_compact.css('display', ''); } else { this.$render_compact.hide(); } @@ -428,14 +450,14 @@ openerp.mail = function(session) { return true; }, - do_hide_compact: function() { + do_hide_compact: function () { this.$render_compact.hide(); this.show_compact_message = false; }, - do_show_compact: function() { - if(this.options.show_compact_message && (!this.$render_expandable || this.$render_expandable.is(':hidden'))) { - this.$render_compact.show(); + do_show_compact: function () { + if (this.options.show_compact_message && (!this.$render_expandable || this.$render_expandable.is(':hidden'))) { + this.$render_compact.css('display', ''); } this.show_compact_message = true; } @@ -457,13 +479,14 @@ openerp.mail = function(session) { mail.ThreadExpandable = session.web.Widget.extend({ template: 'mail.thread.expandable', - init: function(parent, datasets, options) { + init: function (parent, datasets, context) { this._super(parent); - this.domain = options.domain || []; + this.domain = datasets.domain || []; + this.options = datasets.options; this.context = _.extend({ default_model: 'mail.thread', default_res_id: 0, - default_parent_id: false }, options.context || {}); + default_parent_id: false }, context || {}); // data of this expandable message this.id = datasets.id || -1, @@ -474,11 +497,11 @@ openerp.mail = function(session) { this.type = 'expandable', this.max_limit = this.id < 0 || false, this.flag_used = false, - this.parent_thread= parent.messages!= undefined ? parent : options.options._parents[0]; + this.parent_thread= parent.messages!= undefined ? parent : this.options._parents[0]; }, - start: function() { + start: function () { this._super.apply(this, arguments); this.bind_events(); }, @@ -493,15 +516,15 @@ openerp.mail = function(session) { /** * Bind events in the widget. Each event is slightly described * in the function. */ - bind_events: function() { + bind_events: function () { this.$el.on('click', 'a.oe_msg_fetch_more', this.on_expandable); }, - animated_destroy: function(options) { + animated_destroy: function (options) { var self=this; //graphic effects - if(options && options.fadeTime) { - self.$el.fadeOut(options.fadeTime, function(){ + if (options && options.fadeTime) { + self.$el.fadeOut(options.fadeTime, function () { self.destroy(); }); } else { @@ -513,8 +536,8 @@ openerp.mail = function(session) { * @param {object} mouse envent */ on_expandable: function (event) { - if(event)event.stopPropagation(); - if(this.flag_used) { + if (event)event.stopPropagation(); + if (this.flag_used) { return false } this.flag_used = true; @@ -527,7 +550,7 @@ openerp.mail = function(session) { /** * call on_message_delete on his parent thread */ - destroy: function() { + destroy: function () { this._super(); this.parent_thread.on_message_detroy(this); @@ -572,9 +595,19 @@ openerp.mail = function(session) { *... @param {int} [show_reply_button] number thread level to display the reply button *... @param {int} [show_read_unread_button] number thread level to display the read/unread button */ - init: function(parent, datasets, options) { + init: function (parent, datasets, context) { this._super(parent); + // record domain and context + this.domain = datasets.domain || []; + this.context = _.extend({ + default_model: 'mail.thread', + default_res_id: 0, + default_parent_id: false }, context || {}); + + // record options + this.options = datasets.options; + // data of this message this.id = datasets.id || -1, this.model = datasets.model || false, @@ -596,24 +629,15 @@ openerp.mail = function(session) { this.attachment_ids = datasets.attachment_ids || [], this._date = datasets.date; - // record domain and context - this.domain = options.domain || []; - this.context = _.extend({ - default_model: 'mail.thread', - default_res_id: 0, - default_parent_id: false }, options.context || {}); - - // record options - this.options = options.options; this.show_reply_button = this.options.show_compose_message && this.options.show_reply_button > this.thread_level; this.show_read_unread_button = this.options.show_read_unread_button > this.thread_level; // record options and data - this.parent_thread= parent.messages!= undefined ? parent : options.options._parents[0]; + this.parent_thread= parent.messages!= undefined ? parent : this.options._parents[0]; this.thread = false; - if( this.id > 0 ) { + if ( this.id > 0 ) { this.formating_data(); } @@ -625,7 +649,7 @@ openerp.mail = function(session) { /** *Convert date, timerelative and avatar in displayable data. */ - formating_data: function(){ + formating_data: function () { //formating and add some fields for render this.date = session.web.format_value(this._date, {type:"datetime"}); @@ -639,47 +663,50 @@ openerp.mail = function(session) { var attach = this.attachment_ids[l]; attach['url'] = mail.ChatterUtils.get_attachment_url(this.session, attach); - if((attach.filename || attach.name).match(/[.](jpg|jpg|gif|png|tif|svg)$/i)) { + if ((attach.filename || attach.name).match(/[.](jpg|jpg|gif|png|tif|svg)$/i)) { attach.is_image = true; - - } - if((attach.filename || attach.name).match(/[.](pdf|doc|docx|xls|xlsx|ppt|pptx|psd|tiff|dxf|svg)$/i)) { - attach.is_document = true; - attach.url_escape = encodeURIComponent(attach.url); + attach['url'] = mail.ChatterUtils.get_image(this.session, 'ir.attachment', 'datas', attach.id); } } - }, - start: function() { + start: function () { this._super.apply(this, arguments); this.expender(); - this.$el.hide().fadeIn(750); + this.$el.hide().fadeIn(750, function () {$(this).css('display', '');}); this.resize_img(); this.bind_events(); this.create_thread(); + this.$('.oe_msg_attachments, .oe_msg_images').addClass("oe_hidden"); }, - resize_img: function() { - this.$("img").load(function() { + resize_img: function () { + var resize = function () { var h = $(this).height(); var w = $(this).width(); - if( h > 100 || w >100 ) { + if ( h > 100 || w >100 ) { var ratio = 100 / (h > w ? h : w); $(this).attr("width", parseInt( w*ratio )).attr("height", parseInt( h*ratio )); } - }); + }; + this.$("img").load(resize).each(resize); }, /** * Bind events in the widget. Each event is slightly described * in the function. */ - bind_events: function() { + bind_events: function () { var self = this; // event: click on 'Attachment(s)' in msg - this.$('a.oe_msg_view_attachments:first').on('click', function (event) { - self.$('.oe_msg_attachments:first').toggle(); + this.$('.oe_mail_msg_view_attachments').on('click', function (event) { + var attach = self.$('.oe_msg_attachments:first, .oe_msg_images:first'); + if ( self.$('.oe_msg_attachments:first').hasClass("oe_hidden") ) { + attach.removeClass("oe_hidden"); + } else { + attach.addClass("oe_hidden"); + } + self.resize_img(); }); // event: click on icone 'Read' in header this.$el.on('click', '.oe_read', this.on_message_read_unread); @@ -699,13 +726,13 @@ openerp.mail = function(session) { /** * call the on_compose_message on the thread of this message. */ - on_message_reply:function(event){ + on_message_reply:function (event) { event.stopPropagation(); this.thread.on_compose_message(); return false; }, - expender: function(){ + expender: function () { this.$('.oe_msg_body:first').expander({ slicePoint: this.options.truncate_limit, expandText: 'read more', @@ -720,8 +747,8 @@ openerp.mail = function(session) { * instantiate the thread object of this message. * Each message have only one thread. */ - create_thread: function(){ - if(this.thread){ + create_thread: function () { + if (this.thread) { return false; } /*create thread*/ @@ -743,11 +770,11 @@ openerp.mail = function(session) { * Fade out the message and his child thread. * Then this object is destroyed. */ - animated_destroy: function(options) { + animated_destroy: function (options) { var self=this; //graphic effects - if(options && options.fadeTime) { - self.$el.fadeOut(options.fadeTime, function(){ + if (options && options.fadeTime) { + self.$el.fadeOut(options.fadeTime, function () { self.parent_thread.message_to_expandable(self); }); self.thread.$el.fadeOut(options.fadeTime); @@ -778,13 +805,13 @@ openerp.mail = function(session) { event.stopPropagation(); var self=this; - if( (this.to_read && this.options.typeof_thread == 'inbox') || + if ( (this.to_read && this.options.typeof_thread == 'inbox') || (!this.to_read && this.options.typeof_thread == 'archives')) { this.animated_destroy({fadeTime:250}); } // if this message is read, all childs message display is read - this.ds_notification.call('set_message_read', [ [this.id].concat( this.get_child_ids() ) , this.to_read, this.context]).pipe(function(){ + this.ds_notification.call('set_message_read', [ [this.id].concat( this.get_child_ids() ) , this.to_read, this.context]).pipe(function () { self.$el.removeClass(self.to_read ? 'oe_msg_unread':'oe_msg_read').addClass(self.to_read ? 'oe_msg_read':'oe_msg_unread'); self.to_read = !self.to_read; }); @@ -800,23 +827,23 @@ openerp.mail = function(session) { * private for check the top thread * @return thread object */ - browse_message: function(options){ + browse_message: function (options) { // goto the wall thread for launch browse - if(!options._go_thread_wall) { + if (!options._go_thread_wall) { options._go_thread_wall = true; - for(var i in this.options._parents[0].messages){ + for (var i in this.options._parents[0].messages) { var res=this.options._parents[0].messages[i].browse_message(options); - if(res) return res; + if (res) return res; } } - if(this.id==options.id) + if (this.id==options.id) return this; - for(var i in this.thread.messages){ - if(this.thread.messages[i].thread){ + for (var i in this.thread.messages) { + if (this.thread.messages[i].thread) { var res=this.thread.messages[i].browse_message(options); - if(res) return res; + if (res) return res; } } @@ -826,10 +853,10 @@ openerp.mail = function(session) { /* get all child message id linked. * @return array of id */ - get_child_ids: function(){ + get_child_ids: function () { var res=[] - if(arguments[0]) res.push(this.id); - if(this.thread){ + if (arguments[0]) res.push(this.id); + if (this.thread) { res = res.concat( this.thread.get_child_ids(true) ); } return res; @@ -841,7 +868,7 @@ openerp.mail = function(session) { on_vote: function (event) { event.stopPropagation(); var self=this; - return this.ds_message.call('vote_toggle', [[self.id]]).pipe(function(vote){ + return this.ds_message.call('vote_toggle', [[self.id]]).pipe(function (vote) { self.has_voted = vote; self.vote_nb += self.has_voted ? 1 : -1; self.display_vote(); @@ -866,13 +893,13 @@ openerp.mail = function(session) { event.stopPropagation(); var self=this; var button = self.$('.oe_star:first'); - return this.ds_message.call('favorite_toggle', [[self.id]]).pipe(function(star){ + return this.ds_message.call('favorite_toggle', [[self.id]]).pipe(function (star) { self.is_favorite=star; - if(self.is_favorite){ + if (self.is_favorite) { button.addClass('oe_starred'); } else { button.removeClass('oe_starred'); - if( self.options.typeof_thread == 'stared' ) { + if ( self.options.typeof_thread == 'stared' ) { self.animated_destroy({fadeTime:250}); } } @@ -883,7 +910,7 @@ openerp.mail = function(session) { /** * call on_message_delete on his parent thread */ - destroy: function() { + destroy: function () { this._super(); this.parent_thread.on_message_detroy(this); @@ -926,7 +953,7 @@ openerp.mail = function(session) { * @param {Array} [parents] liked with the parents thread * use with browse, fetch... [O]= top parent */ - init: function(parent, datasets, options) { + init: function (parent, datasets, options) { this._super(parent); this.domain = options.domain || []; this.context = _.extend({ @@ -947,7 +974,7 @@ openerp.mail = function(session) { this.is_private = datasets.is_private || false, this.author_id = datasets.author_id || false, this.thread_level = (datasets.thread_level+1) || 0, - this.partner_ids = _.filter(datasets.partner_ids, function(partner){ return partner[0]!=datasets.author_id[0]; } ) + this.partner_ids = _.filter(datasets.partner_ids, function (partner) { return partner[0]!=datasets.author_id[0]; } ) this.messages = []; this.show_compose_message = this.options.show_compose_message && (this.options.show_reply_button > this.thread_level || !this.thread_level); @@ -958,9 +985,9 @@ openerp.mail = function(session) { this.ds_message = new session.web.DataSetSearch(this, 'mail.message'); }, - start: function() { + start: function () { this._super.apply(this, arguments); - if(this.show_compose_message){ + if (this.show_compose_message) { this.instantiate_ComposeMessage(); } this.bind_events(); @@ -969,14 +996,14 @@ openerp.mail = function(session) { /* instantiate the compose message object and insert this on the DOM. * The compose message is display in compact form. */ - instantiate_ComposeMessage: function(){ + instantiate_ComposeMessage: function () { // add message composition form view this.ComposeMessage = new mail.ThreadComposeMessage(this, this, { 'context': this.context, 'options': this.options, }); - if(this.thread_level){ + if (this.thread_level) { this.ComposeMessage.appendTo(this.$el); } else { // root view @@ -988,17 +1015,17 @@ openerp.mail = function(session) { /* When the expandable object is visible on screen (with scrolling) * then the on_expandable function is launch */ - on_scroll: function(event){ - if(event)event.stopPropagation(); + on_scroll: function (event) { + if (event)event.stopPropagation(); this.$('.oe_msg_expandable:last'); var message = this.messages[this.messages.length-1]; - if(message && message.type=="expandable" && message.max_limit) { + if (message && message.type=="expandable" && message.max_limit) { var pos = message.$el.position(); - if(pos.top){ + if (pos.top) { /* bottom of the screen */ var bottom = $(window).scrollTop()+$(window).height()+200; - if(bottom > pos.top){ + if (bottom > pos.top) { message.on_expandable(); } } @@ -1008,7 +1035,7 @@ openerp.mail = function(session) { /** * Bind events in the widget. Each event is slightly described * in the function. */ - bind_events: function() { + bind_events: function () { var self = this; self.$el.on('click', '.oe_mail_list_recipients .oe_more', self.on_show_recipients); self.$el.on('click', '.oe_mail_compose_textarea .oe_more_hidden', self.on_hide_recipients); @@ -1017,7 +1044,7 @@ openerp.mail = function(session) { /** *show all the partner list of this parent message */ - on_show_recipients: function(){ + on_show_recipients: function () { var p=$(this).parent(); p.find('.oe_more_hidden, .oe_hidden').show(); p.find('.oe_more').hide(); @@ -1026,7 +1053,7 @@ openerp.mail = function(session) { /** *hide a part of the partner list of this parent message */ - on_hide_recipients: function(){ + on_hide_recipients: function () { var p=$(this).parent(); p.find('.oe_more_hidden, .oe_hidden').hide(); p.find('.oe_more').show(); @@ -1035,7 +1062,7 @@ openerp.mail = function(session) { /* get all child message/thread id linked. * @return array of id */ - get_child_ids: function(){ + get_child_ids: function () { var res=[]; _(this.get_childs()).each(function (val, key) { res.push(val.id); }); return res; @@ -1045,12 +1072,12 @@ openerp.mail = function(session) { * @param {int} nb_thread_level, number of traversed thread level for this search * @return array of thread object */ - get_childs: function(nb_thread_level){ + get_childs: function (nb_thread_level) { var res=[]; - if(arguments[1]) res.push(this); - if(isNaN(nb_thread_level) || nb_thread_level>0){ + if (arguments[1]) res.push(this); + if (isNaN(nb_thread_level) || nb_thread_level>0) { _(this.messages).each(function (val, key) { - if(val.thread) { + if (val.thread) { res = res.concat( val.thread.get_childs((isNaN(nb_thread_level) ? undefined : nb_thread_level-1), true) ); } }); @@ -1069,28 +1096,28 @@ openerp.mail = function(session) { * return the top thread (wall) if no thread found * @return thread object */ - browse_thread: function(options){ + browse_thread: function (options) { // goto the wall thread for launch browse - if(!options._go_thread_wall) { + if (!options._go_thread_wall) { options._go_thread_wall = true; return this.options._parents[0].browse_thread(options); } - if(this.id==options.id){ + if (this.id==options.id) { return this; } - if(options.id){ - for(var i in this.messages){ - if(this.messages[i].thread){ + if (options.id) { + for (var i in this.messages) { + if (this.messages[i].thread) { var res=this.messages[i].thread.browse_thread({'id':options.id, '_go_thread_wall':true}); - if(res) return res; + if (res) return res; } } } //if option default_return_top_thread, return the top if no found thread - if(options.default_return_top_thread){ + if (options.default_return_top_thread) { return this; } @@ -1106,8 +1133,8 @@ openerp.mail = function(session) { * private for check the top thread * @return message object */ - browse_message: function(options){ - if(this.options._parents[0].messages[0]) + browse_message: function (options) { + if (this.options._parents[0].messages[0]) return this.options._parents[0].messages[0].browse_message(options); }, @@ -1116,8 +1143,8 @@ openerp.mail = function(session) { * Call the on_compose_expandable method to allow the user to write his message. * (Is call when a user click on "Reply" button) */ - on_compose_message: function(){ - if(!this.ComposeMessage){ + on_compose_message: function () { + if (!this.ComposeMessage) { this.instantiate_ComposeMessage(); this.ComposeMessage.do_hide_compact(); } @@ -1128,7 +1155,7 @@ openerp.mail = function(session) { /** *display the message "there are no message" on the thread */ - no_message: function(){ + no_message: function () { $(session.web.qweb.render('mail.wall_no_message', {})).appendTo(this.$el); }, @@ -1164,35 +1191,32 @@ openerp.mail = function(session) { create_message_object: function (data) { var self = this; - if(data.type=='expandable'){ + var data = _.extend(data, {'thread_level': data.thread_level ? data.thread_level : self.thread_level}); + data.options = _.extend(self.options, data.options); + + if (data.type=='expandable') { var message = new mail.ThreadExpandable(self, data, { - 'domain': data.domain, - 'context': { - 'default_model': data.model || self.context.default_model, - 'default_res_id': data.res_id || self.context.default_res_id, - 'default_parent_id': self.id }, + 'default_model': data.model || self.context.default_model, + 'default_res_id': data.res_id || self.context.default_res_id, + 'default_parent_id': self.id, }); } else { - var message = new mail.ThreadMessage(self, _.extend(data, {'thread_level': data.thread_level ? data.thread_level : self.thread_level}), { - 'domain': data.domain, - 'context': { - 'default_model': data.model, - 'default_res_id': data.res_id, - 'default_parent_id': data.id }, - 'options': _.extend(self.options, data.options) + var message = new mail.ThreadMessage(self, data, { + 'default_model': data.model, + 'default_res_id': data.res_id, + 'default_parent_id': data.id, }); } - // insert the message on dom - self.insert_message( message ); - // check if the message is already create - for(var i in self.messages){ - if(self.messages[i] && self.messages[i].id == message.id){ + for (var i in self.messages) { + if (self.messages[i] && self.messages[i].id == message.id) { self.messages[i].destroy(); } } self.messages.push( message ); + + return message; }, /** @@ -1204,27 +1228,32 @@ openerp.mail = function(session) { * The sort is define by the thread_level (O for newer on top). * @param : {object} ThreadMessage object */ - insert_message: function (message) { + insert_message: function (message, dom_insert_after) { var self=this; - if(this.show_compose_message /*&& - this.options.display_indented_thread >= self.thread_level*/){ + if (this.show_compose_message) { this.ComposeMessage.do_show_compact(); } this.$('.oe_wall_no_message').remove(); + + if (dom_insert_after) { + message.insertAfter(dom_insert_after); + return message + } + // check older and newer message for insertion var parent_newer = false; var parent_older = false; - if(message.id > 0){ - for(var i in self.messages){ - if(self.messages[i].id > message.id){ - if(!parent_newer || parent_newer.id > self.messages[i].id) { + if (message.id > 0) { + for (var i in self.messages) { + if (self.messages[i].id > message.id) { + if (!parent_newer || parent_newer.id > self.messages[i].id) { parent_newer = self.messages[i]; } - } else if(self.messages[i].id > 0 && self.messages[i].id < message.id) { - if(!parent_older || parent_older.id < self.messages[i].id) { + } else if (self.messages[i].id > 0 && self.messages[i].id < message.id) { + if (!parent_older || parent_older.id < self.messages[i].id) { parent_older = self.messages[i]; } } @@ -1240,11 +1269,11 @@ openerp.mail = function(session) { //warning : insert after the thread of the message ! message.insertAfter(parent_older.thread ? parent_older.thread.$el : parent_older.$el); - } else if(parent_newer) { + } else if (parent_newer) { message.insertBefore(parent_newer.$el); - } else if(message.id < 0) { + } else if (message.id < 0) { message.appendTo(self.$el); @@ -1257,12 +1286,12 @@ openerp.mail = function(session) { message.insertBefore(parent_older.$el); - } else if(parent_newer) { + } else if (parent_newer) { //warning : insert after the thread of the message ! message.insertAfter(parent_newer.thread ? parent_newer.thread.$el : parent_newer.$el); - } else if(message.id < 0) { + } else if (message.id < 0) { message.prependTo(self.$el); @@ -1281,14 +1310,17 @@ openerp.mail = function(session) { * Each message is send to his parent object (or parent thread flat mode) for creating the object message. * @param : {Array} datas from calling RPC to "message_read" */ - switch_new_message: function(records) { + switch_new_message: function (records) { var self=this; - _(records).each(function(record){ + _(records).each(function (record) { var thread = self.browse_thread({ 'id': record.ancestor_id, 'default_return_top_thread':true }); - thread.create_message_object( record ); + // create object and attach to the thread object + var message = thread.create_message_object( record ); + // insert the message on dom + thread.insert_message( message ); }); }, @@ -1307,7 +1339,7 @@ openerp.mail = function(session) { */ message_to_expandable: function (message) { - if(!this.thread_level || message.isDestroyed()) { + if (!this.thread_level || message.isDestroyed()) { message.destroy(); return false; } @@ -1327,7 +1359,7 @@ openerp.mail = function(session) { msg_down.domain = ['|','|'].concat( msg_up.domain ).concat( message_dom ).concat( msg_down.domain ); - if( !msg_down.max_limit ){ + if ( !msg_down.max_limit ) { msg_down.nb_messages += 1 + msg_up.nb_messages; } @@ -1351,7 +1383,7 @@ openerp.mail = function(session) { msg_down.domain = ['|'].concat( msg_down.domain ).concat( message_dom ); // it's maybe a message expandable for the max limit read message - if( !msg_down.max_limit ){ + if ( !msg_down.max_limit ) { msg_down.nb_messages++; } @@ -1365,13 +1397,13 @@ openerp.mail = function(session) { 'ancestor_id': message.ancestor_id, 'nb_messages': 1, 'thread_level': message.thread_level, - 'ancestor_id': message.ancestor_id - }, { + 'ancestor_id': message.ancestor_id, 'domain': message_dom, - 'context': { - 'default_model': message.model || this.context.default_model, - 'default_res_id': message.res_id || this.context.default_res_id, - 'default_parent_id': this.id }, + 'options': message.options, + }, { + 'default_model': message.model || this.context.default_model, + 'default_res_id': message.res_id || this.context.default_res_id, + 'default_parent_id': this.id, }); // add object on array and DOM @@ -1440,13 +1472,13 @@ openerp.mail = function(session) { 'message_ids': [] }, options); - if(this.display_indented_thread === false) { + if (this.display_indented_thread === false) { this.display_indented_thread = -1; } - if(this.show_reply_button === false) { + if (this.show_reply_button === false) { this.show_reply_button = -1; } - if(this.show_read_unread_button === false) { + if (this.show_read_unread_button === false) { this.show_read_unread_button = -1; } @@ -1476,8 +1508,8 @@ openerp.mail = function(session) { this.thread.no_message(); this.thread.message_fetch(null, null, this.options.message_ids); - if(this.options.show_compose_message) { - if(this.options.show_compact_message) { + if (this.options.show_compose_message) { + if (this.options.show_compact_message) { this.thread.ComposeMessage.do_show_compact(); } else { this.thread.ComposeMessage.do_hide_compact(); @@ -1485,8 +1517,8 @@ openerp.mail = function(session) { } }, - bind_events: function(){ - if(this.context['typeof_thread']!='other'){ + bind_events: function () { + if (this.context['typeof_thread']!='other') { $(document).scroll( this.thread.on_scroll ); $(window).resize( this.thread.on_scroll ); window.setTimeout( this.thread.on_scroll, 500 ); @@ -1508,23 +1540,23 @@ openerp.mail = function(session) { mail.RecordThread = session.web.form.AbstractField.extend({ template: 'mail.record_thread', - init: function() { + init: function () { this._super.apply(this, arguments); this.options.domain = this.options.domain || []; this.options.context = {'default_model': 'mail.thread', 'default_res_id': false}; }, - start: function() { + start: function () { this._super.apply(this, arguments); // NB: check the actual_mode property on view to know if the view is in create mode anymore this.view.on("change:actual_mode", this, this._check_visibility); this._check_visibility(); }, - _check_visibility: function() { + _check_visibility: function () { this.$el.toggle(this.view.get("actual_mode") !== "create"); }, - render_value: function() { + render_value: function () { var self = this; if (! this.view.datarecord.id || session.web.BufferedDataSet.virtual_id_regex.test(this.view.datarecord.id)) { this.$('oe_mail_thread').hide(); @@ -1543,7 +1575,7 @@ openerp.mail = function(session) { var message_ids = this.getParent().fields.message_ids && this.getParent().fields.message_ids.get_value(); - if(this.root){ + if (this.root) { this.root.destroy(); } // create and render Thread widget @@ -1584,8 +1616,6 @@ openerp.mail = function(session) { * @param {Array} [options.domain] domain on the Wall * @param {Object} [options.context] context, is an object. It should * contain default_model, default_res_id, to give it to the threads. - * @param {Number} [options.thread_level] number of thread levels to display - * 0 being flat. */ init: function (parent, options) { this._super(parent); @@ -1625,7 +1655,7 @@ openerp.mail = function(session) { * @param {Array} contexts * @param {Array} groupbys */ - do_searchview_search: function(domains, contexts, groupbys) { + do_searchview_search: function (domains, contexts, groupbys) { var self = this; this.rpc('/web/session/eval_domain_and_context', { domains: domains || [], @@ -1654,14 +1684,14 @@ openerp.mail = function(session) { 'show_reply_button': 10, 'show_read_unread_button': 11, 'show_compose_message': true, - 'show_compact_message': true, + 'show_compact_message': false, } ); return this.root.replace(this.$('.oe_mail-placeholder')); }, - bind_events: function(){ + bind_events: function () { var self=this; this.$(".oe_write_full").click(function(){ self.root.thread.ComposeMessage.on_compose_fullmail(); }); this.$(".oe_write_onwall").click(function(){ self.root.thread.on_compose_message(); }); @@ -1690,13 +1720,13 @@ openerp.mail = function(session) { }; }, - start: function(parent, params) { + start: function (parent, params) { var self = this; this.$el.on('click', 'button', self.on_compose_message ); this._super(parent, params); }, - on_compose_message: function(event){ + on_compose_message: function (event) { event.stopPropagation(); var action = { type: 'ir.actions.act_window', @@ -1718,7 +1748,7 @@ openerp.mail = function(session) { }); session.web.UserMenu = session.web.UserMenu.extend({ - start: function(parent, params) { + start: function (parent, params) { var render = new session.web.ComposeMessageTopButton(); render.insertAfter(this.$el); this._super(parent, params); diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 8d868241132..ae8b622c978 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -15,7 +15,7 @@ for main thread composition form in document form view. --> -
+
User img
@@ -41,7 +41,7 @@ mail.compose_message when focus on textarea --> -
+