From 20f6a390895502810ac087c51585980aab0e5fc9 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 28 Sep 2012 15:27:23 +0200 Subject: [PATCH] [IMP]mail thread: load only not loaded message bzr revid: chm@openerp.com-20120928132723-xg2y8j3ebu9a9huv --- addons/mail/mail_followers.py | 4 +- addons/mail/mail_message.py | 26 +++++-- addons/mail/mail_message_view.xml | 4 +- addons/mail/mail_thread.py | 8 +- addons/mail/static/src/js/mail.js | 86 +++++++++++++++------- addons/mail/static/src/xml/mail.xml | 10 ++- addons/mail/wizard/mail_compose_message.py | 9 +-- 7 files changed, 98 insertions(+), 49 deletions(-) diff --git a/addons/mail/mail_followers.py b/addons/mail/mail_followers.py index c351e8a5491..7bb97d0c68f 100644 --- a/addons/mail/mail_followers.py +++ b/addons/mail/mail_followers.py @@ -83,14 +83,14 @@ class mail_notification(osv.Model): return super(mail_notification, self).create(cr, uid, vals, context=context) return False - def set_message_read(self, cr, uid, msg_ids, context=None): + def set_message_read(self, cr, uid, msg_ids, read=None, context=None): if msg_ids == None: return False if type(msg_ids) is not list: msg_ids=[msg_ids] partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id notif_ids = self.search(cr, uid, [('partner_id', '=', partner_id), ('message_id', 'in', msg_ids)], context=context) - return self.write(cr, uid, notif_ids, {'read': True}, context=context) + return self.write(cr, uid, notif_ids, {'read': read}, context=context) def get_partners_to_notify(self, cr, uid, partner_ids, message, context=None): """ Return the list of partners to notify, based on their preferences. diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index d211262e2d9..7f2107b58c1 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -201,7 +201,7 @@ class mail_message(osv.Model): partner_ids = self.pool.get('res.partner').name_get(cr, uid, [x.id for x in msg.partner_ids], context=context) except (orm.except_orm, osv.except_osv): partner_ids = [] - + return { 'id': msg.id, 'type': msg.type, @@ -302,6 +302,12 @@ class mail_message(osv.Model): further parents :return list: list of trees of messages """ + + # don't read the message display by .js, in context message_loaded list + if context and context.get('message_loaded'): + domain += [['id','not in',context.get('message_loaded')]]; + + limit = limit or self._message_read_limit context = context or {} if not ids: @@ -325,13 +331,14 @@ class mail_message(osv.Model): record_parent['child_ids'].append(record) record = record_parent msg = msg.parent_id - if msg.id not in tree: + # if not in record and not in message_loded list + if msg.id not in tree and not(context and context.get('message_loaded') and msg.id in context.get('message_loaded')) : result.append(record) tree[msg.id] = record # Flatten the result - result = self.message_read_tree_flatten(cr, uid, None, result, domain, level, context=context, limit=limit, add_expandable=add_expandable) - return result + result2 = self.message_read_tree_flatten(cr, uid, None, result, domain, level, context=context, limit=limit, add_expandable=add_expandable) + return result2 #------------------------------------------------------ # Email api @@ -483,11 +490,18 @@ class mail_message(osv.Model): fol_objs = fol_obj.browse(cr, uid, fol_ids, context=context) extra_notified = set(fol.partner_id.id for fol in fol_objs) missing_notified = extra_notified - partners_to_notify + missing_notified = missing_notified if missing_notified: self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(4, p_id) for p_id in missing_notified]}, context=context) partners_to_notify |= extra_notified - # # remove uid from partners - self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(3, uid)]}, context=context) + + if message.model=="res.partner" and message.res_id==message.author_id.id: + # add myself author if I wrote on my wall + self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(4, message.author_id.id)]}, context=context) + else: + # unless remove myself author + self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(3, message.author_id.id)]}, context=context) + self.pool.get('mail.notification').notify(cr, uid, list(partners_to_notify), newid, context=context) def copy(self, cr, uid, id, default=None, context=None): diff --git a/addons/mail/mail_message_view.xml b/addons/mail/mail_message_view.xml index 0d24e1cc9df..61aa438b06d 100644 --- a/addons/mail/mail_message_view.xml +++ b/addons/mail/mail_message_view.xml @@ -94,14 +94,14 @@ Inbox mail.wall - Archives mail.wall - diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index a65a88f0fbb..07ffba4589c 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -615,6 +615,7 @@ class mail_thread(osv.AbstractModel): """ Post a new message in an existing thread, returning the new mail.message ID. Extra keyword arguments will be used as default column values for the new mail.message record. + Auto link messages for same id and object :param int thread_id: thread ID to post into, or list with one ID :param str body: body of the message, usually raw HTML that will be sanitized @@ -655,11 +656,12 @@ class mail_thread(osv.AbstractModel): else: subtype_id = False + model = context.get('thread_model', self._name) if thread_id else False + messages = self.pool.get('mail.message') + #auto link messages for same id and object - messages = self.pool.get('mail.message') - model = context.get('thread_model', self._name) if thread_id else False - if model != 'res.partner': + if model != 'res.partner' and thread_id: message_ids = messages.search(cr, uid, ['&',('res_id', '=', thread_id),('model','=',model)], context=context) if len(message_ids): parent_id = min(message_ids) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index f2e3990e741..9bfe4c073cf 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -294,7 +294,6 @@ openerp.mail = function(session) { expandable_max: options.expandable_max || 5, not_expendable: options.not_expendable || false, } - // datasets and internal vars this.id= options.id || false; this.top_parent= (options.top_parent && options.top_parent.browse_thread) ? options.top_parent : (parent.browse_thread ? parent : this); @@ -337,28 +336,35 @@ openerp.mail = function(session) { this.$('*').unbind('click'); // event: click on 'More' at bottom of thread this.$el.on('click', 'a.oe_mail_fetch_more', this.do_message_fetch_more); - // event: writing in basic textarea of composition form (quick reply) - this.$('textarea.oe_mail_compose_textarea').keyup(function (event) { - var charCode = (event.which) ? event.which : window.event.keyCode; - if (event.shiftKey && charCode == 13) { this.value = this.value+"\n"; } - else if (charCode == 13) { return self.message_post(); } - }); // event: click on 'Reply' in msg - this.$el.on('click', 'a.oe_mail_msg_reply', function (event) { + this.$el.on('click', 'a.oe_reply', function (event) { var act_dom = $(this).parents('li.oe_mail_thread_msg').eq(0).find('div.oe_mail_thread_action:first'); act_dom.toggle(); }); + // event: writing in basic textarea of composition form (quick reply) + // event: onblur for hide 'Reply' + this.$('textarea.oe_mail_compose_textarea:first') + .keyup(function (event) { + var charCode = (event.which) ? event.which : window.event.keyCode; + if (event.shiftKey && charCode == 13) { this.value = this.value+"\n"; } + else if (charCode == 13) { return self.message_post(); } + }) + .blur(function (event) { + $(this).parents('.oe_mail_thread_action:first').toggle(); + }); // event: click on 'Attachment(s)' in msg this.$el.on('click', 'a.oe_mail_msg_view_attachments', function (event) { var act_dom = $(this).parent().parent().parent().find('.oe_mail_msg_attachments'); act_dom.toggle(); }); // event: click on icone 'Read' in header - this.$el.on('click', 'a.oe_read', this.on_message_read); + this.$el.on('click', 'a.oe_read', this.on_message_read_unread); + // event: click on icone 'UnRead' in header + this.$el.on('click', 'a.oe_unread', this.on_message_read_unread); // event: click on 'Delete' in msg side menu this.$el.on('click', 'a.oe_mail_msg_delete', this.on_message_delete); // event: click on 'Reply by email' in msg side menu - this.$el.on('click', 'a.oe_mail_msg_reply_by_email', function (event) { + this.$el.on('click', 'a.oe_reply_by_email', function (event) { if (! self.compose_message_widget) return true; var msg_id = event.srcElement.dataset.msg_id; if (! msg_id) return false; @@ -373,17 +379,7 @@ openerp.mail = function(session) { on_message_delete: function (event) { if (! confirm(_t("Do you really want to delete this message?"))) { return false; } - var msg_id = event.srcElement.dataset.id; - if (! msg_id) return false; - $(event.srcElement).parents('li.oe_mail_thread_msg').eq(0).remove(); - return this.ds_message.unlink([parseInt(msg_id)]); - }, - /*The selected thread and all childs (messages/thread) became read - * @param {object} mouse envent - */ - on_message_read: function (event) { - //TDE: TODO var source = $(event.srcElement).parents('[data-msg_id]:first'); var msg_id = source.data("msg_id"); var msg_model = source.data("msg_model"); @@ -392,12 +388,29 @@ openerp.mail = function(session) { var thread=this.browse_thread({'id':msg_id, 'model':msg_model}); if(thread){ thread.animated_destroy({fadeTime:250}); + var ids = [thread.id] + // delete this thread and his childs + var ids = ids.concat( thread.get_child_thread_ids() ); + this.ds_message.unlink(ids); + } + }, + /*The selected thread and all childs (messages/thread) became read + * @param {object} mouse envent + */ + on_message_read_unread: function (event) { + var source = $(event.srcElement).parents('[data-msg_id]:first'); + var msg_id = source.data("msg_id"); + var msg_model = source.data("msg_model"); + if (!msg_id || !msg_model) return false; + + var thread=this.browse_thread({'id':msg_id, 'model':msg_model}); + if(thread){ + thread.animated_destroy({fadeTime:250}); var ids = [thread.id] // if this thread is read, all childs thread display is read var ids = ids.concat( thread.get_child_thread_ids() ); - - thread.ds_notification.call('set_message_read', [ids]); + thread.ds_notification.call('set_message_read', [ids,$(event.srcElement).hasClass("oe_read")]); } }, @@ -428,7 +441,7 @@ openerp.mail = function(session) { return this.top_parent.browse_thread(options); } - if(this.id && this.model){ + if(options.id && options.model){ if(this.id==options.id && this.model==options.model) return this; @@ -448,7 +461,7 @@ openerp.mail = function(session) { animated_destroy: function(options) { var self=this; - //graphic effects + //graphic effects if(options.fadeTime) self.$el.parents(".oe_mail_thread_msg:first").fadeOut(options.fadeTime, function(){ self.destroy(); @@ -490,6 +503,7 @@ openerp.mail = function(session) { /** Instantiate the composition form, with every parameters in context or in the widget context. */ instantiate_composition_form: function(context) { + var self=this; if (this.compose_message_widget) { this.compose_message_widget.destroy(); } @@ -498,7 +512,12 @@ openerp.mail = function(session) { }); var composition_node = this.$('div.oe_mail_thread_action'); composition_node.empty(); - var compose_done = this.compose_message_widget.appendTo(composition_node); + var compose_done = this.compose_message_widget.appendTo(composition_node) + .then(function(){ + self.$("button.oe_mail_compose_message_button_send").mouseup(function(){ + self.browse_thread({'top_thread':1}).message_fetch(); + }); + }); return compose_done; }, @@ -524,6 +543,12 @@ openerp.mail = function(session) { // domain and context: options + additional fetch_domain = _.flatten([this.domain, additional_domain || []], true); fetch_context = _.extend({}, this.context, additional_context || {}); + + fetch_context.message_loaded=[]; + self.$("li[data-msg_id][data-msg_model]").each(function(){ + fetch_context.message_loaded.push($(this).data("msg_id")) + }); + // initial mode: try to use message_data or message_ids if (initial_mode && this.options.message_data) { return this.message_display_create_thread(this.options.message_data); @@ -548,6 +573,11 @@ openerp.mail = function(session) { $(rendered).appendTo(self.$el.children('ul.oe_mail_thread_display:first')); } else if(inc<=self.options.expandable_max) { + + //if thread exists, don't create new thread + if(self.browse_thread({'model': record.model,'id': record.id,})) + return false; + /*create thread*/ var thread = new mail.Thread(self, self.domain, { 'default_model': record.model, @@ -558,7 +588,7 @@ openerp.mail = function(session) { 'message_data': record.child_ids, 'thread_level': self.options.thread_level - 1, 'show_header_compose': false, - 'show_reply': self.options.show_reply && self.options.thread_level > 1, + 'show_reply': self.options.show_reply, 'show_reply_by_email': self.options.show_reply_by_email, 'show_dd_hide': self.options.show_dd_hide, 'show_dd_delete': self.options.show_dd_delete, @@ -647,6 +677,8 @@ openerp.mail = function(session) { else $rendered.prependTo(this.$('> ul.oe_mail_thread_display:first')); + $rendered.hide().fadeIn(750); + this.$('> div.oe_mail_msg_body').expander({ slicePoint: this.options.truncate_limit, @@ -882,7 +914,7 @@ openerp.mail = function(session) { { 'thread_level': this.options.thread_level, 'use_composer': true, 'show_reply': this.options.thread_level > 0, - 'show_dd_hide': true + 'show_dd_hide': true, } ); diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 6874687694e..cb342353942 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -112,9 +112,10 @@ @@ -173,6 +174,7 @@ +
  • diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 1ea8383eaea..0e5c65ab3c0 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -217,10 +217,6 @@ class mail_compose_message(osv.TransientModel): def send_mail(self, cr, uid, ids, context=None): """ Process the wizard content and proceed with sending the related email(s), rendering any template patterns on the fly if needed. """ - - print "" - print "send_mail", ids, context - if context is None: context = {} active_ids = context.get('active_ids') @@ -256,7 +252,10 @@ class mail_compose_message(osv.TransientModel): # post process: update attachments, because id is not necessarily known when adding attachments in Chatter self.pool.get('ir.attachment').write(cr, uid, [attach.id for attach in wizard.attachment_ids], {'res_id': wizard.id}, context=context) - return {'type': 'ir.actions.act_window_close'} + if context.get('mail_action_wizard_close'): + return {'type': 'ir.actions.act_window_close'} + else: + return False def render_message(self, cr, uid, wizard, res_id, context=None): """ Generate an email from the template for given (wizard.model, res_id)