From 9bd8c00b01e15efde20233787bf5084d0c268482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 1 Jul 2015 16:27:49 +0200 Subject: [PATCH] [IMP] mail: moved methods called by mail_followers.js to controllers, updated their code accordingly. Subtype display in the follower widget has been improved: now displaying correctly subtypes ordered by related model, then internal / not internal, then sequence. --- addons/mail/controllers/main.py | 42 ++++++++++++++++ addons/mail/models/mail_thread.py | 54 +-------------------- addons/mail/static/src/js/mail.js | 5 +- addons/mail/static/src/js/mail_followers.js | 53 ++++++++++---------- addons/mail/tests/test_mail_followers.py | 8 --- 5 files changed, 71 insertions(+), 91 deletions(-) diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py index 4a069cb5428..8b72fc74106 100644 --- a/addons/mail/controllers/main.py +++ b/addons/mail/controllers/main.py @@ -1,4 +1,5 @@ import base64 +from operator import itemgetter import psycopg2 import openerp @@ -42,3 +43,44 @@ class MailController(http.Controller): except psycopg2.Error: pass return True + + @http.route('/mail/read_followers', type='json', auth='user') + def read_followers(self, follower_ids): + result = [] + is_editable = request.env.user.has_group('base.group_no_one') + for follower in request.env['res.partner'].browse(follower_ids): + result.append({ + 'id': follower.id, + 'name': follower.name, + 'is_editable': is_editable, + 'is_uid': request.env.user.partner_id == follower, + }) + return result + + @http.route('/mail/read_subscription_data', type='json', auth='user') + def read_subscription_data(self, res_model, res_id): + """ Computes: + - message_subtype_data: data about document subtypes: which are + available, which are followed if any """ + # find the document followers, update the data + followers = request.env['mail.followers'].search([ + ('partner_id', '=', request.env.user.partner_id.id), + ('res_id', '=', res_id), + ('res_model', '=', res_model), + ]) + + # find current model subtypes, add them to a dictionary + subtypes = request.env['mail.message.subtype'].search(['&', ('hidden', '=', False), '|', ('res_model', '=', res_model), ('res_model', '=', False)]) + subtypes_list = [{ + 'name': subtype.name, + 'res_model': subtype.res_model, + 'sequence': subtype.sequence, + 'default': subtype.default, + 'internal': subtype.internal, + 'followed': subtype.id in followers.mapped('subtype_ids').ids, + 'parent_model': subtype.parent_id and subtype.parent_id.res_model or False, + 'id': subtype.id + } for subtype in subtypes] + subtypes_list = sorted(subtypes_list, key=itemgetter('parent_model', 'res_model', 'internal', 'sequence')) + + return subtypes_list diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index a91b7c18768..09310d47578 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import base64 -from collections import OrderedDict import datetime import dateutil import email @@ -20,7 +19,7 @@ from email.message import Message from email.utils import formataddr from urllib import urlencode -from openerp import _, api, fields, models, SUPERUSER_ID +from openerp import _, api, fields, models from openerp import exceptions from openerp import tools from openerp.addons.mail.models.mail_message import decode @@ -351,57 +350,6 @@ class MailThread(models.AbstractModel): res['arch'] = etree.tostring(doc) return res - @api.model - def read_followers_data(self, follower_ids): - # TDE NOTE: move as controller ? (used in mail_followers.js)$ - # TDE NOTE2: usefull anyway ? - result = [] - is_editable = self.env.user.has_group('base.group_no_one') - for follower in self.env['res.partner'].browse(follower_ids): - is_uid = self.env.user.partner_id.id in follower.ids - data = (follower.id, - follower.name, - {'is_editable': is_editable, 'is_uid': is_uid}, - ) - result.append(data) - return result - - @api.multi - def _get_subscription_data(self, user_pid=None): - # TDE NOTE: move as controller ? (used in mail_followers.js) - """ Computes: - - message_subtype_data: data about document subtypes: which are - available, which are followed if any """ - res = dict((id, dict(message_subtype_data='')) for id in self.ids) - if user_pid is None: - user_pid = self.env.user.partner_id.id - - # find current model subtypes, add them to a dictionary - subtypes = self.env['mail.message.subtype'].search(['&', ('hidden', '=', False), '|', ('res_model', '=', self._name), ('res_model', '=', False)]) - subtype_dict = OrderedDict( - (subtype.name, { - 'default': subtype.default, - 'followed': False, - 'parent_model': subtype.parent_id and subtype.parent_id.res_model or self._name, - 'id': subtype.id - }) for subtype in subtypes) - for res_id in self.ids: - res[res_id]['message_subtype_data'] = subtype_dict.copy() - - # find the document followers, update the data - followers = self.env['mail.followers'].search([ - ('partner_id', '=', user_pid), - ('res_id', 'in', self.ids), - ('res_model', '=', self._name), - ]) - for fol in followers: - thread_subtype_dict = res[fol.res_id]['message_subtype_data'] - for subtype in [st for st in fol.subtype_ids if st.name in thread_subtype_dict]: - thread_subtype_dict[subtype.name]['followed'] = True - res[fol.res_id]['message_subtype_data'] = thread_subtype_dict - - return res - # ------------------------------------------------------ # Automatic log / Tracking # ------------------------------------------------------ diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index f6a7093c246..c6ebe4825eb 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -1,6 +1,7 @@ odoo.define('mail.mail', function (require) { "use strict"; +var ajax = require('web.ajax'); var mail_utils = require('mail.utils'); var core = require('web.core'); var data = require('web.data'); @@ -786,10 +787,10 @@ var MailThread = Attachment.extend ({ } else { var ds_model = new data.DataSetSearch(this, this.model, this.context); - ds_model.call('read_followers_data', [this.follower_ids.slice(0, this.options.followers_limit)]).then(function (records) { + ajax.jsonRpc('/mail/read_followers', 'call', {'follower_ids': this.follower_ids.slice(0, this.options.followers_limit)}).then(function (records) { self.followers_data = []; _.each(records, function(f) { - self.followers_data.push(f[1] + '
'); + self.followers_data.push(f.name + '
'); }); if (self.nb_followers - self.followers_limit > 0) { self.followers_data.push('and ' + self.nb_followers - self.followers_limit + 'more ...
'); diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index db0ae782f94..69b235a7d80 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -1,6 +1,7 @@ odoo.define('mail.mail_followers', function (require) { "use strict"; +var ajax = require('web.ajax'); var mail_utils = require('mail.utils'); var core = require('web.core'); var data = require('web.data'); @@ -191,7 +192,7 @@ var Followers = form_common.AbstractField.extend({ fetch_followers: function (value_) { this.value = value_ || []; - return this.ds_model.call('read_followers_data', [this.value]) + ajax.jsonRpc('/mail/read_followers', 'call', {'follower_ids': this.value}) .then(this.proxy('display_followers'), this.proxy('fetch_generic')) .then(this.proxy('display_buttons')) .then(this.proxy('fetch_subtypes')); @@ -202,7 +203,6 @@ var Followers = form_common.AbstractField.extend({ - then display a generic message about followers */ fetch_generic: function (error, event) { var self = this; - event.preventDefault(); return this.ds_users.call('read', [[session.uid], ['partner_id']]) .then(function (results) { @@ -233,24 +233,24 @@ var Followers = form_common.AbstractField.extend({ /** Display the followers */ display_followers: function (records) { var self = this; - this.message_is_follower = false; this.followers = records || this.followers; // clean and display title var node_user_list = this.$('.o_timeline_follower_list').empty(); this.$('.o_timeline_follower_title').html(this._format_followers(this.followers.length)); - + var user_follower = _.filter(this.followers, function (rec) { return rec['is_uid'];}); + this.message_is_follower = user_follower.length >= 1; + this.follower_id = this.message_is_follower ? user_follower[0]['id'] : undefined; $(qweb.render('mail_followers_add_more', {'widget': self})).appendTo(node_user_list); - self.message_is_follower = _.indexOf(this.followers.map(function(rec) {return rec[2]['is_uid']}), true) != -1; // truncate number of displayed followers _(this.followers).each(function (record) { var partner = { - 'id': record[0], - 'name': record[1], - 'is_uid': record[2]['is_uid'], - 'is_editable': record[2]['is_editable'], - 'avatar_url': mail_utils.get_image(session, 'res.partner', 'image_small', record[0]), + 'id': record['id'], + 'name': record['name'], + 'is_uid': record['is_uid'], + 'is_editable': record['is_editable'], + 'avatar_url': mail_utils.get_image(session, 'res.partner', 'image_small', record['id']), } $(qweb.render('mail_followers_partner', {'record': partner, 'widget': self})) @@ -302,14 +302,16 @@ var Followers = form_common.AbstractField.extend({ this.$('.o_timeline_subtype_list > .dropdown-toggle').attr('disabled', false); } } - var id = this.view.datarecord.id; - this.ds_model.call('message_get_subscription_data', - [[id], user_pid, new data.CompoundContext(this.build_context(), {})]) - .then(function (data) {self.display_subtypes(data, id, dialog);}); + if (this.follower_id) { + return ajax.jsonRpc('/mail/read_subscription_data', 'call', {'res_model': this.view.model, 'res_id': this.view.datarecord.id}) + .then(function (data) { self.display_subtypes(data, dialog); }); + } else { + return $.Deferred().resolve(); + } }, /** Display subtypes: {'name': default, followed} */ - display_subtypes:function (data, id, dialog) { + display_subtypes:function (data, dialog) { var self = this; var $list = this.$('.o_timeline_subtype_list ul'); @@ -320,26 +322,21 @@ var Followers = form_common.AbstractField.extend({ $list = this.$dialog.$el; } - var old_model = ''; - var records = data[id].message_subtype_data; - this.records_length = $.map(records, function(value, index) { return index; }).length; + var old_parent_model = undefined; + this.records_length = $.map(data, function(value, index) { return index; }).length; if (this.records_length > 1) { self.display_followers(); } - _.each(records, function (record, record_name) { - if (old_model != record.parent_model) { - if (old_model != '') { - var $last_separator = $list.find('.oe_subtype').last(); - if ($last_separator) { - $last_separator.addClass('oe_subtype_border'); - } + _.each(data, function (record) { + if (old_parent_model !== record.parent_model && old_parent_model !== undefined) { + var $last_separator = $list.find('.oe_subtype').last(); + if ($last_separator) { + $last_separator.addClass('oe_subtype_border'); } - old_model = record.parent_model; } - - record.name = record_name; + old_parent_model = record.parent_model; record.followed = record.followed || undefined; $(qweb.render('mail_followers_subtype', {'record': record, 'dialog': dialog})) diff --git a/addons/mail/tests/test_mail_followers.py b/addons/mail/tests/test_mail_followers.py index 0c36da2c4f9..fc36a179c3c 100644 --- a/addons/mail/tests/test_mail_followers.py +++ b/addons/mail/tests/test_mail_followers.py @@ -85,11 +85,3 @@ class TestMailFollowers(TestMail): ('partner_id', '=', self.user_employee.partner_id.id)]) self.assertEqual(len(follower), 1) self.assertEqual(follower.subtype_ids, self.mt_mg_nodef | self.mt_al_nodef) - - def test_subscription_data(self): - self.group_pigs.message_subscribe_users(user_ids=[self.user_employee.id]) - subtype_data = self.group_pigs.sudo(self.user_employee)._get_subscription_data()[self.group_pigs.id]['message_subtype_data'] - self.assertEqual(set(subtype_data.keys()), set(['Discussions', 'Note', 'mt_mg_def', 'mt_al_def', 'mt_mg_nodef', 'mt_al_nodef']), 'mail.group available subtypes incorrect') - self.assertTrue(subtype_data['Discussions']['followed']) - self.assertFalse(subtype_data['mt_mg_nodef']['followed']) - self.assertFalse(subtype_data['mt_al_nodef']['followed'])