From fd2a4139694e2548a6bccb154a6a6c5be6d19b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 4 Sep 2012 15:36:48 +0200 Subject: [PATCH] [FIX] [CLEAN] mail_thread: misc cleanup (comments, vars, typo). Fixed subscriber API. It now handles a read_back key in context to return the new value of the field. The purpose is to use it in mail_followers widget, that behaves asynchronously compared to the form_view, and that need updated values after subscribing a user. Updated mail_followers widget, cleaned its code. Updated mail_group with wrappers on message_subscriber_users, because it was setting user_ids as context. bzr revid: tde@openerp.com-20120904133648-plsziijac64lw4de --- addons/mail/mail_group.py | 17 ++++-- addons/mail/mail_group_view.xml | 5 +- addons/mail/mail_message.py | 2 +- addons/mail/mail_thread.py | 64 +++++++++------------ addons/mail/static/src/js/mail_followers.js | 22 +++---- addons/mail/tests/test_mail.py | 4 +- addons/mail/wizard/mail_compose_message.py | 2 +- 7 files changed, 55 insertions(+), 61 deletions(-) diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index f5769e082a1..fdfeafd4afe 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -44,10 +44,6 @@ class mail_group(osv.Model): def _set_image(self, cr, uid, id, name, value, args, context=None): return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context) - def _get_default_image(self, cr, uid, context=None): - image_path = openerp.modules.get_module_resource('mail', 'static/src/img', 'groupdefault.png') - return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64')) - _columns = { 'description': fields.text('Description'), 'menu_id': fields.many2one('ir.ui.menu', string='Related Menu', required=True, ondelete="cascade"), @@ -89,6 +85,10 @@ class mail_group(osv.Model): ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'group_user') return ref and ref[1] or False + def _get_default_image(self, cr, uid, context=None): + image_path = openerp.modules.get_module_resource('mail', 'static/src/img', 'groupdefault.png') + return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64')) + def _get_menu_parent(self, cr, uid, context=None): ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'mail_group_root') return ref and ref[1] or False @@ -156,3 +156,12 @@ class mail_group(osv.Model): self._subscribe_users(cr, uid, ids, vals.get('group_ids'), context=context) return result + def action_follow(self, cr, uid, ids, context=None): + """ Wrapper because message_subscribe_users take a user_ids=None + that receive the context without the wrapper. """ + return self.message_subscribe_users(cr, uid, ids, context=context) + + def action_unfollow(self, cr, uid, ids, context=None): + """ Wrapper because message_unsubscribe_users take a user_ids=None + that receive the context without the wrapper. """ + return self.message_unsubscribe_users(cr, uid, ids, context=context) diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index acd9f320757..51a7a926dc9 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -33,8 +33,8 @@

@@ -81,7 +81,6 @@
- diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index d22bd4c2e3c..bca46a3c91c 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -135,7 +135,7 @@ class mail_message(osv.Model): _defaults = { 'type': 'email', 'date': lambda *a: fields.datetime.now(), - 'author_id': lambda s,cr,uid,ctx={}: s._get_default_author(cr, uid, ctx), + 'author_id': lambda self,cr,uid,ctx: self._get_default_author(cr, uid, ctx), 'body': '', } diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 6e5f594354a..eda7adb995c 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -158,17 +158,16 @@ class mail_thread(osv.AbstractModel): 'mail_followers', 'res_id', 'partner_id', reference_column='res_model', string='Followers'), 'message_comment_ids': fields.one2many('mail.message', 'res_id', - domain=lambda self: [('model','=',self._name),('type','in',('comment','email'))], - string='Related Messages', - help="All messages related to the current document."), + domain=lambda self: [('model', '=', self._name), ('type', 'in', ('comment', 'email'))], + string='Comments and emails', + help="Comments and emails"), 'message_ids': fields.one2many('mail.message', 'res_id', domain=lambda self: [('model','=',self._name)], - string='Related Messages', - help="All messages related to the current document."), + string='Messages', + help="Messages and communication history"), 'message_unread': fields.function(_get_message_data, fnct_search=_search_unread, - string='Has Unread Messages', type='boolean', - help="When checked, new messages require your attention.", - multi="_get_message_data"), + type='boolean', string='Unread Messages', multi="_get_message_data", + help="If checked new messages require your attention."), 'message_summary': fields.function(_get_message_data, method=True, type='text', string='Summary', multi="_get_message_data", help="Holds the Chatter summary (number of messages, ...). "\ @@ -181,7 +180,7 @@ class mail_thread(osv.AbstractModel): #------------------------------------------------------ def create(self, cr, uid, vals, context=None): - """ Override of create to subscribe the current user. """ + """ Override to subscribe the current user. """ thread_id = super(mail_thread, self).create(cr, uid, vals, context=context) self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context) return thread_id @@ -215,11 +214,8 @@ class mail_thread(osv.AbstractModel): def _message_find_partners(self, cr, uid, message, header_fields=['From'], context=None): """ Find partners related to some header fields of the message. """ s = ', '.join([decode(message.get(h)) for h in header_fields if message.get(h)]) - mails = tools.email_split(s) - result = [] - for email in mails: - result += self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], context=context) - return result + return [partner_id for email in tools.email_split(s) + for partner_id in self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], context=context)] def _message_find_user_id(self, cr, uid, message, context=None): from_local_part = tools.email_split(decode(message.get('From')))[0] @@ -551,16 +547,16 @@ class mail_thread(osv.AbstractModel): #------------------------------------------------------ def log(self, cr, uid, id, message, secondary=False, context=None): - _logger.warning("log() is deprecated. As this module inherit from \ - mail.thread, the message will be managed by this \ - module instead of by the res.log mechanism. Please \ - use the mail.thread OpenChatter API instead of the \ - now deprecated res.log.") + _logger.warning("log() is deprecated. As this module inherit from "\ + "mail.thread, the message will be managed by this "\ + "module instead of by the res.log mechanism. Please "\ + "use mail_thread.message_post() instead of the "\ + "now deprecated res.log.") self.message_post(cr, uid, [id], message, context=context) def message_post(self, cr, uid, thread_id, body='', subject=False, - msg_type='notification', parent_id=False, attachments=None, context=None, **kwargs): - """ Post a new message in an existing message thread, returning the new + type='notification', parent_id=False, attachments=None, context=None, **kwargs): + """ 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. @@ -568,7 +564,7 @@ class mail_thread(osv.AbstractModel): :param str body: body of the message, usually raw HTML that will be sanitized :param str subject: optional subject - :param str msg_type: mail_message.type + :param str type: mail_message.type :param int parent_id: optional ID of parent message in this thread :param tuple(str,str) attachments: list of attachment tuples in the form ``(name,content)``, where content is NOT base64 encoded @@ -601,7 +597,7 @@ class mail_thread(osv.AbstractModel): 'res_id': thread_id or False, 'body': body, 'subject': subject, - 'type': msg_type, + 'type': type, 'parent_id': parent_id, 'attachment_ids': attachment_ids, }) @@ -615,40 +611,37 @@ class mail_thread(osv.AbstractModel): def message_subscribe_users(self, cr, uid, ids, user_ids=None, context=None): """ Wrapper on message_subscribe, using users. If user_ids is not provided, subscribe uid instead. """ - # isinstance: because using message_subscribe_users called in a view set the context as user_ids - if not user_ids or isinstance(user_ids, dict): user_ids = [uid] + if not user_ids: user_ids = [uid] partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)] return self.message_subscribe(cr, uid, ids, partner_ids, context=context) def message_subscribe(self, cr, uid, ids, partner_ids, context=None): """ Add partners to the records followers. - :param partner_ids: a list of partner_ids to subscribe - :param return: new value of followers, for Chatter + :param return: new value of followers if read_back key in context """ self.write(cr, uid, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context) - # TDE: temp, must check followers widget + if context and context.get('read_back'): + return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids] return [] - # return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids] + def message_unsubscribe_users(self, cr, uid, ids, user_ids=None, context=None): """ Wrapper on message_subscribe, using users. If user_ids is not provided, unsubscribe uid instead. """ - # isinstance: because using message_subscribe_users called in a view set the context as user_ids - if not user_ids or isinstance(user_ids, dict): user_ids = [uid] + if not user_ids: user_ids = [uid] partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)] return self.message_unsubscribe(cr, uid, ids, partner_ids, context=context) def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None): """ Remove partners from the records followers. - :param partner_ids: a list of partner_ids to unsubscribe - :param return: new value of followers, for Chatter + :param return: new value of followers if read_back key in context """ self.write(cr, uid, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context) - # TDE: temp, must check followers widget + if context and context.get('read_back'): + return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids] return [] - # return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids] #------------------------------------------------------ # Thread state @@ -679,4 +672,3 @@ class mail_thread(osv.AbstractModel): partner_id = %s ''', (ids, self._name, partner_id)) return True - diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 6125aac12dc..e5d216ed3d2 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -9,7 +9,7 @@ openerp_mail_followers = function(session, mail) { * mail_followers Widget * ------------------------------------------------------------ * - * This widget handles the display of a list of records as a vetical + * This widget handles the display of a list of records as a vertical * list, with an image on the left. The widget itself is a floatting * right-sided box. * This widget is mainly used to display the followers of records @@ -65,25 +65,17 @@ openerp_mail_followers = function(session, mail) { this.$el.find('div.oe_mail_recthread_aside').hide(); return; } - if (this.getParent().fields.message_is_follower === undefined) { - // TDE: TMP, need to change all form views - this.message_is_follower = false; - } - else { - this.message_is_follower = this.getParent().fields.message_is_follower.get_value(); - } return this.fetch_followers(value_); }, fetch_followers: function (value_) { - return this.ds_follow.call('read', [value_ || this.get_value(), ['name']]).then(this.proxy('display_followers')); + return this.ds_follow.call('read', [value_ || this.get_value(), ['name', 'user_ids']]).then(this.proxy('display_followers')); }, - /** - * Display the followers. - * TODO: replace the is_follower check by fields read */ + /** Display the followers, evaluate is_follower directly */ display_followers: function (records) { var self = this; + this.message_is_follower = _.indexOf(_.flatten(_.pluck(records, 'user_ids')), this.session.uid) != -1; var node_user_list = this.$el.find('ul.oe_mail_followers_display').empty(); this.$el.find('div.oe_mail_recthread_followers h4').html(this.options.title + ' (' + records.length + ')'); _(records).each(function (record) { @@ -99,11 +91,13 @@ openerp_mail_followers = function(session, mail) { }, do_follow: function () { - return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id]]).pipe(this.proxy('set_value')); + var context = new session.web.CompoundContext(this.build_context(), {'read_back': true}); + return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], undefined, context]).pipe(this.proxy('set_value')); }, do_unfollow: function () { - return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id]]).pipe(this.proxy('set_value')); + var context = new session.web.CompoundContext(this.build_context(), {'read_back': true}); + return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], undefined, context]).pipe(this.proxy('set_value')); }, }); }; diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py index 9c148647b9b..f8fd02bfb7e 100644 --- a/addons/mail/tests/test_mail.py +++ b/addons/mail/tests/test_mail.py @@ -250,7 +250,7 @@ class test_mail(common.TransactionCase): _attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')] # CASE1: post comment, body and subject specified - msg_id = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body1, subject=_subject, msg_type='comment') + msg_id = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body1, subject=_subject, type='comment') message = self.mail_message.browse(cr, uid, msg_id) mail_ids = self.mail_mail.search(cr, uid, [], limit=1) mail = self.mail_mail.browse(cr, uid, mail_ids[0]) @@ -280,7 +280,7 @@ class test_mail(common.TransactionCase): # CASE2: post an email with attachments, parent_id, partner_ids # TESTS: automatic subject, signature in body_html, attachments propagation - msg_id2 = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body2, msg_type='email', + msg_id2 = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body2, type='email', partner_ids=[(6, 0, [p_d_id])], parent_id=msg_id, attachments=_attachments) message = self.mail_message.browse(cr, uid, msg_id2) mail_ids = self.mail_mail.search(cr, uid, [], limit=1) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 41b10d6d4a3..3c93440642d 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -269,7 +269,7 @@ class mail_compose_message(osv.TransientModel): post_values['attachments'] += new_attachments post_values.update(email_dict) # post the message - active_model_pool.message_post(cr, uid, [res_id], msg_type='comment', context=context, **post_values) + active_model_pool.message_post(cr, uid, [res_id], type='comment', context=context, **post_values) return {'type': 'ir.actions.act_window_close'}