diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 685f9781cc9..59db6a18bc0 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -700,8 +700,8 @@ class mail_thread(osv.AbstractModel): if not subject and parent_id: parent = mail_message.read(cr, uid, parent_id, ['subject'], context=context) - if not parent['subject'].startswith('Re:') - subject = 'Re: ' + parent['subject'] + if parent['subject'] and not parent['subject'].startswith('Re:'): + subject = 'Re: %s' % 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) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 78aa3e8513d..f98e82481fa 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -130,8 +130,7 @@ openerp.mail = function (session) { */ mail.ThreadComposeMessage = session.web.Widget.extend({ - template: 'mail.compose_message.compact', - // expandable view : 'mail.compose_message' + template: 'mail.compose_message', /** * @param {Object} parent parent @@ -147,7 +146,7 @@ openerp.mail = function (session) { this.context = options.context || {}; this.options = options.options; - this.show_compact_message = this.options.show_compact_message || false; + this.show_compact_message = false; // data of this compose message this.attachment_ids = []; @@ -165,19 +164,10 @@ openerp.mail = function (session) { this.fileupload_id = _.uniqueId('oe_fileupload_temp'); $(window).on(self.fileupload_id, self.on_attachment_loaded); - - this.$render_expandable = false; - this.$render_compact = false; }, start: function () { - this.$render_compact = this.$el; - - if ( this.options.show_compact_message ) { - this.$render_compact.show(); - } else { - this.$render_compact.hide(); - } + this.display_attachments(); this.bind_events(); }, @@ -187,14 +177,14 @@ openerp.mail = function (session) { var self = this; var render = $(session.web.qweb.render('mail.thread.message.attachments', {'widget': self})); if (!this.list_attachment) { - this.$render_expandable.find('.oe_msg_attachment_list').replaceWith( render ); + this.$('.oe_msg_attachment_list').replaceWith( render ); } else { this.list_attachment.replaceWith( render ); } - this.list_attachment = this.$render_expandable.find(".oe_msg_attachments"); + this.list_attachment = this.$(".oe_msg_attachments"); // event: delete an attachment - this.$render_expandable.on('click', '.oe_mail_attachment_delete', self.on_attachment_delete); + this.$el.on('click', '.oe_mail_attachment_delete', self.on_attachment_delete); }, /* when a user click on the upload button, send file read on_attachment_loaded @@ -222,9 +212,9 @@ openerp.mail = function (session) { this.attachment_ids = attachments; // submit file - this.$render_expandable.find('form.oe_form_binary_form').submit(); + this.$('form.oe_form_binary_form').submit(); - this.$render_expandable.find(".oe_attachment_file").hide(); + this.$(".oe_attachment_file").hide(); this.attachment_ids.push({ 'id': 0, @@ -252,9 +242,9 @@ openerp.mail = function (session) { } this.display_attachments(); - var $input = this.$render_expandable.find('input.oe_form_binary_file'); + var $input = this.$('input.oe_form_binary_file'); $input.after($input.clone(true)).remove(); - this.$render_expandable.find(".oe_attachment_file").show(); + this.$(".oe_attachment_file").show(); }, /* unlink the file on the server and reload display @@ -280,24 +270,22 @@ openerp.mail = function (session) { bind_events: function () { var self = this; - this.$render_compact.find('textarea').unbind().on('focus', self.on_compose_expandable); + this.$('textarea.oe_compact').on('focus', self.on_compose_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 ); + // set the function called when attachments are added + this.$el.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('reply')} ); + this.$el.on('click', '.oe_cancel', self.on_cancel ); + this.$el.on('click', '.oe_post', function () {self.on_message_post()} ); + this.$el.on('click', '.oe_full', function () {self.on_compose_fullmail('reply')} ); - // auto close - this.$render_expandable.on('blur', 'textarea', this.on_compose_expandable); + /* stack for don't close the compose form if the user click on a button */ + this.$el.on('mousedown', 'div', function () { self.stay_open = true; }); + this.$('textarea:not(.oe_compact):first').on('focus, mouseup, keydown', function () { self.stay_open = false; }); + this.$('textarea:not(.oe_compact):first').autosize(); - /* stack for don't close the compose form if the user click on a button */ - this.$render_expandable.on('focus, mouseup', 'textarea', function () { self.stay_open = false; }); - this.$render_expandable.on('mousedown', function () { self.stay_open = true; }); - this.$render_expandable.find('textarea').autosize(); - } + // auto close + this.$el.on('blur', 'textarea:not(.oe_compact):first', self.on_compose_expandable); }, on_compose_fullmail: function (default_composition_mode) { @@ -314,7 +302,7 @@ openerp.mail = function (session) { 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_body': mail.ChatterUtils.get_text2html(this.$el ? (this.$el.find('textarea:not(.oe_compact)').val() || '') : ''), 'default_attachment_ids': this.attachment_ids, 'default_partner_ids': [], //partner_ids }; @@ -326,7 +314,7 @@ openerp.mail = function (session) { '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_body': mail.ChatterUtils.get_text2html(this.$el ? (this.$el.find('textarea:not(.oe_compact)').val() || '') : ''), 'default_attachment_ids': this.attachment_ids, 'default_partner_ids': [], //partner_ids }; @@ -343,22 +331,26 @@ openerp.mail = function (session) { }; this.do_action(action); + this.on_cancel(); + }, - if (this.$render_expandable) { - this.on_cancel(); - } + reinit: function() { + var $render = $( session.web.qweb.render('mail.compose_message', {'widget': this}) ); + + $render.insertAfter(this.$el.last()); + this.$el.remove(); + this.$el = $render; + + this.display_attachments(); + this.bind_events(); }, on_cancel: function (event) { if (event) event.stopPropagation(); - this.$render_expandable.find('textarea').val(""); - this.$render_expandable.find('input[data-id]').remove(); - this.attachment_ids=[]; - this.display_attachments(); - this.stay_open = false; - this.on_compose_expandable(); + this.show_composer = false; + this.reinit(); }, /*post a message and fetch the message*/ @@ -366,7 +358,7 @@ openerp.mail = function (session) { var self = this; if (! body) { - var comment_node = this.$render_expandable.find('textarea'); + var comment_node = this.$('textarea:not(.oe_compact)'); var body = comment_node.val(); comment_node.val(''); } @@ -396,70 +388,44 @@ openerp.mail = function (session) { // 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(); + thread.insert_message( message, self.$el ); + if (thread.parent_thread) { + self.$el.remove(); + self.parent_thread.compose_message = null; + } else { + self.on_cancel(); + } //session.web.unblockUI(); }); return true; } }, - /* create the compose on expandable form - */ - instantiate_expandable: function () { - if (!this.$render_expandable) { - this.$render_expandable = $(session.web.qweb.render('mail.compose_message', {'widget': this})); - this.$render_expandable.hide(); - - this.$render_expandable.insertAfter( this.$render_compact ); - this.display_attachments(); - - this.bind_events(); - } - }, - /* convert the compact mode into the compose message */ on_compose_expandable: function (event) { if (event) event.stopPropagation(); - var self = this; - - this.instantiate_expandable(); - - if (this.$render_expandable.is(':hidden')) { - - this.$render_expandable.css('display', ''); - this.$render_compact.hide(); - this.$render_expandable.find('textarea').focus(); - - } else if (!this.stay_open) { - - // do not close the box if there are some text - 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.css('display', ''); - } else { - this.$render_compact.hide(); - } - } - + if (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/)){ + this.show_composer = !this.show_composer || this.stay_open; + this.reinit(); } + this.$('textarea:not(.oe_compact):first').focus(); return true; }, do_hide_compact: function () { - this.$render_compact.hide(); this.show_compact_message = false; + if (!this.show_composer) { + this.reinit(); + } }, 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; + if (!this.show_composer) { + this.reinit(); + } } }); @@ -520,10 +486,10 @@ openerp.mail = function (session) { this.$el.on('click', 'a.oe_msg_fetch_more', this.on_expandable); }, - animated_destroy: function (options) { + animated_destroy: function (fadeTime) { var self=this; //graphic effects - if (options && options.fadeTime) { + if (fadeTime) { self.$el.fadeOut(options.fadeTime, function () { self.destroy(); }); @@ -542,7 +508,7 @@ openerp.mail = function (session) { } this.flag_used = true; - this.animated_destroy({'fadeTime':300}); + this.animated_destroy(300); this.parent_thread.message_fetch(this.domain, this.context); return false; }, @@ -770,10 +736,10 @@ openerp.mail = function (session) { * Fade out the message and his child thread. * Then this object is destroyed. */ - animated_destroy: function (options) { + animated_destroy: function (fadeTime) { var self=this; //graphic effects - if (options && options.fadeTime) { + if (fadeTime) { self.$el.fadeOut(options.fadeTime, function () { self.parent_thread.message_to_expandable(self); }); @@ -791,7 +757,7 @@ openerp.mail = function (session) { event.stopPropagation(); if (! confirm(_t("Do you really want to delete this message?"))) { return false; } - this.animated_destroy({fadeTime:250}); + this.animated_destroy(250); // delete this message and his childs var ids = [this.id].concat( this.get_child_ids() ); this.ds_message.unlink(ids); @@ -807,7 +773,7 @@ openerp.mail = function (session) { if ( (this.to_read && this.options.typeof_thread == 'inbox') || (!this.to_read && this.options.typeof_thread == 'archives')) { - this.animated_destroy({fadeTime:250}); + this.animated_destroy(250); } // if this message is read, all childs message display is read @@ -900,7 +866,7 @@ openerp.mail = function (session) { } else { button.removeClass('oe_starred'); if ( self.options.typeof_thread == 'stared' ) { - self.animated_destroy({fadeTime:250}); + self.animated_destroy(250); } } }); @@ -979,7 +945,7 @@ openerp.mail = function (session) { this.show_compose_message = this.options.show_compose_message && (this.options.show_reply_button > this.thread_level || !this.thread_level); // object compose message - this.ComposeMessage = false; + this.compose_message = false; this.ds_thread = new session.web.DataSetSearch(this, this.context.default_model || 'mail.thread'); this.ds_message = new session.web.DataSetSearch(this, 'mail.message'); @@ -987,29 +953,33 @@ openerp.mail = function (session) { start: function () { this._super.apply(this, arguments); + if (this.show_compose_message) { - this.instantiate_ComposeMessage(); + this.instantiate_compose_message(); } + this.bind_events(); }, /* instantiate the compose message object and insert this on the DOM. * The compose message is display in compact form. */ - instantiate_ComposeMessage: function () { + instantiate_compose_message: function () { // add message composition form view - this.ComposeMessage = new mail.ThreadComposeMessage(this, this, { - 'context': this.context, - 'options': this.options, - }); - - if (this.thread_level) { - this.ComposeMessage.appendTo(this.$el); - } else { - // root view - this.ComposeMessage.prependTo(this.$el); + if (!this.compose_message) { + this.compose_message = new mail.ThreadComposeMessage(this, this, { + 'context': this.context, + 'options': this.options, + }); + if (!this.thread_level) { + // root view + this.compose_message.insertBefore(this.$el); + } else if (this.thread_level > this.options.display_indented_thread) { + this.compose_message.insertAfter(this.$el); + } else { + this.compose_message.appendTo(this.$el); + } } - this.ComposeMessage.do_hide_compact(); }, /* When the expandable object is visible on screen (with scrolling) @@ -1139,24 +1109,24 @@ openerp.mail = function (session) { }, /** - *If ComposeMessage doesn't exist, instantiate the compose message. + *If compose_message doesn't exist, instantiate the compose message. * 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) { - this.instantiate_ComposeMessage(); - this.ComposeMessage.do_hide_compact(); - } - - this.ComposeMessage.on_compose_expandable(); + this.instantiate_compose_message(); + this.compose_message.on_compose_expandable(); }, /** *display the message "there are no message" on the thread */ no_message: function () { - $(session.web.qweb.render('mail.wall_no_message', {})).appendTo(this.$el); + var no_message = $(session.web.qweb.render('mail.wall_no_message', {})); + if (this.options.no_message) { + no_message.html(this.options.no_message); + } + no_message.appendTo(this.$el); }, /** @@ -1231,8 +1201,9 @@ openerp.mail = function (session) { insert_message: function (message, dom_insert_after) { var self=this; - if (this.show_compose_message) { - this.ComposeMessage.do_show_compact(); + if (this.show_compose_message && this.options.show_compact_message) { + this.instantiate_compose_message(); + this.compose_message.do_show_compact(); } this.$('.oe_wall_no_message').remove(); @@ -1244,17 +1215,17 @@ openerp.mail = function (session) { } // check older and newer message for insertion - var parent_newer = false; - var parent_older = false; + var message_newer = false; + var message_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) { - parent_newer = self.messages[i]; + if (!message_newer || message_newer.id > self.messages[i].id) { + message_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) { - parent_older = self.messages[i]; + if (!message_older || message_older.id < self.messages[i].id) { + message_older = self.messages[i]; } } } @@ -1264,14 +1235,13 @@ openerp.mail = function (session) { if (sort) { - if (parent_older) { + if (message_older) { - //warning : insert after the thread of the message ! - message.insertAfter(parent_older.thread ? parent_older.thread.$el : parent_older.$el); + message.insertAfter(message_older.thread.compose_message ? message_older.thread.compose_message.$el : message_older.thread.$el); - } else if (parent_newer) { + } else if (message_newer) { - message.insertBefore(parent_newer.$el); + message.insertBefore(message_newer.$el); } else if (message.id < 0) { @@ -1282,14 +1252,13 @@ openerp.mail = function (session) { message.prependTo(self.$el); } } else { - if (parent_older) { + if (message_older) { - message.insertBefore(parent_older.$el); + message.insertBefore(message_older.$el); - } else if (parent_newer) { + } else if (message_newer) { - //warning : insert after the thread of the message ! - message.insertAfter(parent_newer.thread ? parent_newer.thread.$el : parent_newer.$el); + message.insertAfter(message_newer.thread.compose_message ? message_newer.thread.compose_message.$el : message_newer.thread.$el); } else if (message.id < 0) { @@ -1436,7 +1405,7 @@ openerp.mail = function (session) { * @param {Array} [domain] * @param {Object} [context] context of the thread. It should * contain at least default_model, default_res_id. Please refer to - * the ComposeMessage widget for more information about it. + * the compose_message widget for more information about it. * ... @param {Select} [typeof_thread=(mail|stared|archives|send|other)] * options for destroy message when the user click on a button * @param {Object} [options] @@ -1453,6 +1422,7 @@ openerp.mail = function (session) { * when the user clic on this compact mode, the composer is open *... @param {Array} [message_ids] List of ids to fetch by the root thread. * When you use this option, the domain is not used for the fetch root. + * @param {String} [no_message] Message to display when there are no message */ init: function (parent, options) { this._super(parent); @@ -1469,7 +1439,8 @@ openerp.mail = function (session) { 'show_record_name' : false, 'show_compose_message' : false, 'show_compact_message' : false, - 'message_ids': [] + 'message_ids': [], + 'no_message': false }, options); if (this.display_indented_thread === false) { @@ -1509,10 +1480,11 @@ openerp.mail = function (session) { this.thread.message_fetch(null, null, this.options.message_ids); if (this.options.show_compose_message) { + this.thread.instantiate_compose_message(); if (this.options.show_compact_message) { - this.thread.ComposeMessage.do_show_compact(); + this.thread.compose_message.do_show_compact(); } else { - this.thread.ComposeMessage.do_hide_compact(); + this.thread.compose_message.do_hide_compact(); } } }, @@ -1535,6 +1507,7 @@ openerp.mail = function (session) { * This widget handles the display of messages on a document. Its main * use is to receive a context and a domain, and to delegate the message * fetching and displaying to the Thread widget. + * Use Help on the field to display a custom "no message loaded" */ session.web.form.widgets.add('mail_thread', 'openerp.mail.RecordThread'); mail.RecordThread = session.web.form.AbstractField.extend({ @@ -1589,6 +1562,7 @@ openerp.mail = function (session) { 'show_compose_message': show_compose_message, 'message_ids': message_ids, 'show_compact_message': true, + 'no_message': this.node.attrs.help } ); @@ -1693,7 +1667,7 @@ openerp.mail = function (session) { bind_events: function () { var self=this; - this.$(".oe_write_full").click(function(){ self.root.thread.ComposeMessage.on_compose_fullmail(); }); + this.$(".oe_write_full").click(function(){ self.root.thread.compose_message.on_compose_fullmail(); }); this.$(".oe_write_onwall").click(function(){ self.root.thread.on_compose_message(); }); } }); diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index ae8b622c978..cbd2b263b87 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -13,9 +13,13 @@ an e-mail. It contains by default a textarea, that will be replaced by another composition form in the main wall composition form, or for main thread composition form in document form view. + + mail.compose_message.compact template + This template holds the composition form to write a message, this box is converted into + mail.compose_message when focus on textarea --> -
+
User img
@@ -33,17 +37,10 @@
-
- - - -
+