diff --git a/addons/base_action_rule/test_models.py b/addons/base_action_rule/test_models.py
index fde48b815ad..5eb0dc1ff8b 100644
--- a/addons/base_action_rule/test_models.py
+++ b/addons/base_action_rule/test_models.py
@@ -30,5 +30,5 @@ class lead_test(osv.Model):
def message_post(self, cr, uid, thread_id, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
pass
- def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
+ def message_subscribe(self, cr, uid, ids, partner_ids=None, channel_ids=None, subtype_ids=None, force=True, context=None):
pass
diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py
index acd1a19f16f..aa89eb6cc90 100644
--- a/addons/calendar/calendar.py
+++ b/addons/calendar/calendar.py
@@ -1395,11 +1395,17 @@ class calendar_event(osv.Model):
del context['default_date']
return super(calendar_event, self).message_post(cr, uid, thread_id, context=context, **kwargs)
- def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
- return super(calendar_event, self).message_subscribe(cr, uid, get_real_ids(ids), partner_ids, subtype_ids=subtype_ids, context=context)
+ def message_subscribe(self, cr, uid, ids, partner_ids=None, channel_ids=None, subtype_ids=None, force=True, context=None):
+ return super(calendar_event, self).message_subscribe(
+ cr, uid, get_real_ids(ids),
+ partner_ids=partner_ids,
+ channel_ids=channel_ids,
+ subtype_ids=subtype_ids,
+ force=force,
+ context=context)
- def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None):
- return super(calendar_event, self).message_unsubscribe(cr, uid, get_real_ids(ids), partner_ids, context=context)
+ def message_unsubscribe(self, cr, uid, ids, partner_ids=None, channel_ids=None, context=None):
+ return super(calendar_event, self).message_unsubscribe(cr, uid, get_real_ids(ids), partner_ids=partner_ids, channel_ids=channel_ids, context=context)
def do_sendmail(self, cr, uid, ids, context=None):
for event in self.browse(cr, uid, ids, context):
diff --git a/addons/hr_evaluation/hr_evaluation.py b/addons/hr_evaluation/hr_evaluation.py
index e9998279379..e7d181f1e2a 100644
--- a/addons/hr_evaluation/hr_evaluation.py
+++ b/addons/hr_evaluation/hr_evaluation.py
@@ -240,8 +240,11 @@ class hr_evaluation(osv.Model):
def write(self, cr, uid, ids, vals, context=None):
if vals.get('employee_id'):
employee_id = self.pool.get('hr.employee').browse(cr, uid, vals.get('employee_id'), context=context)
+ # TDE FIXME: use add_command
if employee_id.parent_id and employee_id.parent_id.user_id:
- vals['message_follower_ids'] = [(4, employee_id.parent_id.user_id.partner_id.id)]
+ message_follower_ids = vals.get('message_follower_ids') or [] # webclient can send None or False
+ message_follower_ids += self.env['mail.followers']._add_follower_command(self._name, ids, {employee_id.parent_id.user_id.partner_id.id: None}, {}, force=True)[0]
+ vals['message_follower_ids'] = message_follower_ids
if 'date' in vals:
new_vals = {'deadline': vals.get('date')}
obj_hr_eval_iterview = self.pool.get('hr.evaluation.interview')
diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py
index 8b72fc74106..a9c6d98eaac 100644
--- a/addons/mail/controllers/main.py
+++ b/addons/mail/controllers/main.py
@@ -48,12 +48,14 @@ class MailController(http.Controller):
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):
+ for follower in request.env['mail.followers'].browse(follower_ids):
result.append({
'id': follower.id,
- 'name': follower.name,
+ 'name': follower.partner_id.name or follower.channel_id.name,
+ 'res_model': 'res.partner' if follower.partner_id else 'mail.channel',
+ 'res_id': follower.partner_id.id or follower.channel_id.id,
'is_editable': is_editable,
- 'is_uid': request.env.user.partner_id == follower,
+ 'is_uid': request.env.user.partner_id == follower.partner_id,
})
return result
diff --git a/addons/mail/data/mail_channel_demo.xml b/addons/mail/data/mail_channel_demo.xml
index d14f65acd9a..3a6fd6bc6ad 100644
--- a/addons/mail/data/mail_channel_demo.xml
+++ b/addons/mail/data/mail_channel_demo.xml
@@ -7,23 +7,14 @@
Best Sales Practices
Discussion about best sales practices and deals.
-
-
-
Board meetings
Board meetings, budgets, strategic plans
-
-
-
R&D
Research and development discussion group
-
-
-
diff --git a/addons/mail/models/mail_followers.py b/addons/mail/models/mail_followers.py
index 59d6d5d4254..2e71ff1433c 100644
--- a/addons/mail/models/mail_followers.py
+++ b/addons/mail/models/mail_followers.py
@@ -23,11 +23,87 @@ class Followers(models.Model):
res_id = fields.Integer(
'Related Document ID', select=1, help='Id of the followed resource')
partner_id = fields.Many2one(
- 'res.partner', string='Related Partner', ondelete='cascade', required=True, select=1)
+ 'res.partner', string='Related Partner', ondelete='cascade', select=1)
+ channel_id = fields.Many2one(
+ 'mail.channel', string='Listener', ondelete='cascade', select=1)
subtype_ids = fields.Many2many(
'mail.message.subtype', string='Subtype',
help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall.")
+ @api.model
+ def _add_follower_command(self, res_model, res_ids, partner_data, channel_data, force=True):
+ """ Please upate me
+ :param force: if True, delete existing followers before creating new one
+ using the subtypes given in the parameters
+ """
+ force_mode = force or (all(data for data in partner_data.values()) and all(data for data in channel_data.values()))
+ generic = []
+ specific = {}
+ existing = {} # {res_id: follower_ids}
+ p_exist = {} # {partner_id: res_ids}
+ c_exist = {} # {channel_id: res_ids}
+
+ followers = self.sudo().search([
+ '&',
+ '&', ('res_model', '=', res_model), ('res_id', 'in', res_ids),
+ '|', ('partner_id', 'in', partner_data.keys()), ('channel_id', 'in', channel_data.keys())])
+
+ if force_mode:
+ followers.unlink()
+ else:
+ for follower in followers:
+ existing.setdefault(follower.res_id, list()).append(follower)
+ if follower.partner_id:
+ p_exist.setdefault(follower.partner_id.id, list()).append(follower.res_id)
+ if follower.channel_id:
+ c_exist.setdefault(follower.channel_id.id, list()).append(follower.res_id)
+
+ default_subtypes = self.env['mail.message.subtype'].search([
+ ('default', '=', True),
+ '|', ('res_model', '=', res_model), ('res_model', '=', False)])
+
+ if force_mode:
+ for pid, data in partner_data.iteritems():
+ if not data:
+ partner_data[pid] = default_subtypes.ids
+ for cid, data in channel_data.iteritems():
+ if not data:
+ channel_data[cid] = default_subtypes.ids
+
+ # create new followers, batch ok
+ gen_new_pids = [pid for pid in partner_data.keys() if pid not in p_exist]
+ gen_new_cids = [cid for cid in channel_data.keys() if cid not in c_exist]
+ for pid in gen_new_pids:
+ generic.append([0, 0, {'res_model': res_model, 'partner_id': pid, 'subtype_ids': [(6, 0, partner_data.get(pid) or default_subtypes.ids)]}])
+ for cid in gen_new_cids:
+ generic.append([0, 0, {'res_model': res_model, 'channel_id': cid, 'subtype_ids': [(6, 0, channel_data.get(cid) or default_subtypes.ids)]}])
+
+ # create new followers, each document at a time because of existing followers to avoid erasing
+ if not force_mode:
+ for res_id in res_ids:
+ command = []
+ doc_followers = existing.get(res_id, list())
+
+ new_pids = set(partner_data.keys()) - set([sub.partner_id.id for sub in doc_followers if sub.partner_id]) - set(gen_new_pids)
+ new_cids = set(channel_data.keys()) - set([sub.channel_id.id for sub in doc_followers if sub.channel_id]) - set(gen_new_cids)
+
+ # subscribe new followers
+ for new_pid in new_pids:
+ command.append((0, 0, {
+ 'res_model': res_model,
+ 'partner_id': new_pid,
+ 'subtype_ids': [(6, 0, partner_data.get(new_pid) or default_subtypes.ids)],
+ }))
+ for new_cid in new_cids:
+ command.append((0, 0, {
+ 'res_model': res_model,
+ 'channel_id': new_cid,
+ 'subtype_ids': [(6, 0, channel_data.get(new_cid) or default_subtypes.ids)],
+ }))
+ if command:
+ specific[res_id] = command
+ return generic, specific
+
#
# Modifying followers change access rights to individual documents. As the
# cache may contain accessible/inaccessible data, one has to refresh it.
@@ -50,7 +126,10 @@ class Followers(models.Model):
self.invalidate_cache()
return res
- _sql_constraints = [('mail_followers_res_partner_res_model_id_uniq', 'unique(res_model,res_id,partner_id)', 'Error, a partner cannot follow twice the same object.')]
+ _sql_constraints = [
+ ('mail_followers_res_partner_res_model_id_uniq', 'unique(res_model,res_id,partner_id)', 'Error, a partner cannot follow twice the same object.'),
+ ('mail_followers_res_channel_res_model_id_uniq', 'unique(res_model,res_id,channel_id)', 'Error, a channel cannot follow twice the same object.'),
+ ]
class Notification(models.Model):
diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py
index 661431f6fc5..ecca6887b38 100644
--- a/addons/mail/models/mail_thread.py
+++ b/addons/mail/models/mail_thread.py
@@ -66,11 +66,16 @@ class MailThread(models.AbstractModel):
_mail_post_access = 'write' # access required on the document to post on it
_mail_mass_mailing = False # enable mass mailing on this model
- message_is_follower = fields.Boolean('Is Follower', compute='_get_followers', search='_search_is_follower')
- message_follower_ids = fields.Many2many(
- comodel_name='res.partner', string='Followers',
- inverse='_set_followers',
- compute='_get_followers', search='_search_followers', type='many2many')
+ message_is_follower = fields.Boolean('Is Follower', compute='_compute_is_follower')
+ message_follower_ids = fields.One2many(
+ 'mail.followers', 'res_id', string='Followers',
+ domain=lambda self: [('res_model', '=', self._name)])
+ message_partner_ids = fields.Many2many(
+ comodel_name='res.partner', string='Followers (Partners)',
+ compute='_get_followers', search='_search_follower_partners')
+ message_channel_ids = fields.Many2many(
+ comodel_name='mail.channel', string='Followers (Channels)',
+ compute='_get_followers', search='_search_follower_channels')
message_ids = fields.One2many(
'mail.message', 'res_id', string='Messages',
domain=lambda self: [('model', '=', self._name)], auto_join=True,
@@ -83,72 +88,45 @@ class MailThread(models.AbstractModel):
'Unread Messages', compute='_get_message_unread',
help="Number of unread messages")
- @api.multi
+ @api.one
+ @api.depends('message_follower_ids')
def _get_followers(self):
- res = dict.fromkeys(self.ids, self.env['res.partner'])
- followers = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('res_id', 'in', self.ids)])
- for follower in followers:
- res[follower.res_id] |= follower.partner_id
- for record in self:
- if not record.id:
- continue
- record.message_follower_ids = res[record.id]
- record.message_is_follower = self.env.user.partner_id in record.message_follower_ids
-
- @api.multi
- def _set_followers(self):
- # read the old set of followers, and determine the new set of followers
- old = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('res_id', 'in', self.ids)]).mapped('partner_id')
- new = self.env['res.partner']
- Partner = self.env['res.partner']
-
- old_style_commands = self._fields['message_follower_ids'].convert_to_write(self.message_follower_ids)
- for command in old_style_commands:
- if command[0] == 0:
- new |= Partner.create(command[2])
- elif command[0] == 1:
- partner = Partner.browse(command[1])
- partner.write(command[2])
- new |= partner
- elif command[0] == 2:
- partner = Partner.browse(command[1])
- new -= partner
- partner.unlink()
- elif command[0] == 3:
- new -= Partner.browse(command[1])
- elif command[0] == 4:
- new |= Partner.browse(command[1])
- elif command[0] == 5:
- new = self.env['res.partner']
- elif command[0] == 6:
- new = self.env['res.partner'].browse(command[2])
-
- # remove partners that are no longer followers
- self.message_unsubscribe((old-new).ids)
- # add new followers
- self.message_subscribe((new-old).ids)
+ self.message_partner_ids = self.message_follower_ids.mapped('partner_id')
+ self.message_channel_ids = self.message_follower_ids.mapped('channel_id')
@api.model
- def _search_followers(self, operator, operand):
+ def _search_follower_partners(self, operator, operand):
"""Search function for message_follower_ids
Do not use with operator 'not in'. Use instead message_is_followers
"""
- # TOFIX make it work with not in
- assert operator != "not in", "Do not search message_follower_ids with 'not in'"
- followers = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('partner_id', operator, operand)])
+ followers = self.env['mail.followers'].sudo().search([
+ ('res_model', '=', self._name),
+ ('partner_id', operator, operand)])
return [('id', 'in', followers.mapped('res_id'))]
@api.model
- def _search_is_follower(self, operator, operand):
- """Search function for message_is_follower"""
- user_pid = self.env.user.partner_id.id
- if (operator == '=' and operand) or (operator == '!=' and not operand): # is a follower
- followers = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('partner_id', '=', user_pid)])
- return [('id', 'in', followers.mapped('res_id'))]
- else: # is not a follower or unknown domain
- followers = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('partner_id', '=', user_pid)])
- return [('id', 'not in', followers.mapped('res_id'))]
+ def _search_follower_channels(self, operator, operand):
+ """Search function for message_follower_ids
+
+ Do not use with operator 'not in'. Use instead message_is_followers
+ """
+ followers = self.env['mail.followers'].sudo().search([
+ ('res_model', '=', self._name),
+ ('channel_id', operator, operand)])
+ return [('id', 'in', followers.mapped('res_id'))]
+
+ @api.multi
+ @api.depends('message_follower_ids')
+ def _compute_is_follower(self):
+ followers = self.env['mail.followers'].sudo().search([
+ ('res_model', '=', self._name),
+ ('res_id', 'in', self.ids),
+ ('partner_id', '=', self.env.user.partner_id.id),
+ ])
+ following_ids = followers.mapped('res_id')
+ for record in self:
+ record.message_is_follower = record.id in following_ids
@api.multi
def _get_message_unread(self):
@@ -188,7 +166,7 @@ class MailThread(models.AbstractModel):
# subscribe uid unless asked not to
if not self._context.get('mail_create_nosubscribe'):
message_follower_ids = values.get('message_follower_ids') or [] # webclient can send None or False
- message_follower_ids.append([4, self.env.user.partner_id.id])
+ message_follower_ids += self.env['mail.followers']._add_follower_command(self._name, [], {self.env.user.partner_id.id: None}, {}, force=True)[0]
values['message_follower_ids'] = message_follower_ids
thread = super(MailThread, self).create(values)
@@ -765,7 +743,7 @@ class MailThread(models.AbstractModel):
obj = record_set[0]
else:
obj = self.env[alias.alias_parent_model_id.model].browse(alias.alias_parent_thread_id)
- if not author_id or author_id not in [fol.id for fol in obj.message_follower_ids]:
+ if not author_id or author_id not in [fol.id for fol in obj.message_partner_ids]:
_warn('alias %s restricted to internal followers, skipping' % alias.alias_name)
_create_bounce_email()
return False
@@ -1296,7 +1274,7 @@ class MailThread(models.AbstractModel):
partner = self.env['res.partner'].sudo().browse([partner_info['partner_id']])[0]
if email and email in [val[1] for val in result[self.ids[0]]]: # already existing email -> skip
return result
- if partner and partner in self.message_follower_ids: # recipient already in the followers -> skip
+ if partner and partner in self.message_partner_ids: # recipient already in the followers -> skip
return result
if partner and partner.id in [val[0] for val in result[self.ids[0]]]: # already existing partner ID -> skip
return result
@@ -1339,8 +1317,8 @@ class MailThread(models.AbstractModel):
followers = self.env['res.partner']
if res_model and res_id:
record = self.env[res_model].browse(res_id)
- if hasattr(record, 'message_follower_ids'):
- followers = record.message_follower_ids
+ if hasattr(record, 'message_partner_ids'):
+ followers = record.message_partner_ids
Partner = self.env['res.partner'].sudo()
partner_ids = []
@@ -1601,16 +1579,18 @@ class MailThread(models.AbstractModel):
return result
@api.multi
- def message_subscribe(self, partner_ids, subtype_ids=None):
+ def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True):
""" Add partners to the records followers. """
# not necessary for computation, but saves an access right check
- if not partner_ids:
+ if not partner_ids and not channel_ids:
return True
+ if partner_ids is None:
+ partner_ids = []
+ if channel_ids is None:
+ channel_ids = []
- Followers = self.env['mail.followers']
- Subtype = self.env['mail.message.subtype']
-
- if set(partner_ids) == set([self.env.user.partner_id.id]):
+ # TDE CHECK THIS
+ if not channel_ids and partner_ids and set(partner_ids) == set([self.env.user.partner_id.id]):
try:
self.check_access_rights('read')
self.check_access_rule('read')
@@ -1620,38 +1600,14 @@ class MailThread(models.AbstractModel):
self.check_access_rights('write')
self.check_access_rule('write')
- existing_pids_dict = dict.fromkeys(self.ids, self.env['res.partner'])
- followers = Followers.sudo().search([
- '&', '&',
- ('res_model', '=', self._name),
- ('res_id', 'in', self.ids),
- ('partner_id', 'in', partner_ids)])
- for follower in followers:
- existing_pids_dict[follower.res_id] |= follower.partner_id
-
- # subtype_ids specified: update already subscribed partners
- if subtype_ids and followers:
- followers.write({'subtype_ids': [(6, 0, subtype_ids)]})
- # subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
- if subtype_ids is None:
- subtype_ids = Subtype.search([
- ('default', '=', True),
- '|',
- ('res_model', '=', self._name),
- ('res_model', '=', False)]).ids
-
- for record in self:
- existing_pids = existing_pids_dict[record.id]
- new_partners = self.env['res.partner'].browse(partner_ids) - existing_pids
-
- # subscribe new followers
- for new_partner in new_partners:
- Followers.sudo().create({
- 'res_model': self._name,
- 'res_id': record.id,
- 'partner_id': new_partner.id,
- 'subtype_ids': [(6, 0, subtype_ids)]})
+ partner_data = dict((pid, subtype_ids) for pid in partner_ids)
+ channel_data = dict((cid, subtype_ids) for cid in channel_ids)
+ gen, part = self.env['mail.followers']._add_follower_command(self._name, self.ids, partner_data, channel_data, force=force)
+ self.sudo().write({'message_follower_ids': gen})
+ for record in self.filtered(lambda self: self.id in part):
+ record.write(part[record.id])
+ self.invalidate_cache()
return True
@api.multi
@@ -1667,13 +1623,13 @@ class MailThread(models.AbstractModel):
return result
@api.multi
- def message_unsubscribe(self, partner_ids):
+ def message_unsubscribe(self, partner_ids=None, channel_ids=None):
""" Remove partners from the records followers. """
# not necessary for computation, but saves an access right check
- if not partner_ids:
+ if not partner_ids and not channel_ids:
return True
user_pid = self.env.user.partner_id.id
- if set(partner_ids) == set([user_pid]):
+ if not channel_ids and set(partner_ids) == set([user_pid]):
self.check_access_rights('read')
self.check_access_rule('read')
else:
@@ -1682,7 +1638,9 @@ class MailThread(models.AbstractModel):
self.env['mail.followers'].sudo().search([
('res_model', '=', self._name),
('res_id', 'in', self.ids),
- ('partner_id', 'in', partner_ids)
+ '|',
+ ('partner_id', 'in', partner_ids or []),
+ ('channel_id', 'in', channel_ids or [])
]).unlink()
@api.model
@@ -1808,7 +1766,7 @@ class MailThread(models.AbstractModel):
for pid, subtypes in new_followers.items():
subtypes = list(subtypes) if subtypes is not None else None
- self.message_subscribe([pid], subtypes)
+ self.message_subscribe([pid], subtype_ids=subtypes)
self._message_auto_subscribe_notify(user_pids)
diff --git a/addons/mail/models/res_users.py b/addons/mail/models/res_users.py
index 34d4d73092a..c3edd006130 100644
--- a/addons/mail/models/res_users.py
+++ b/addons/mail/models/res_users.py
@@ -121,7 +121,7 @@ class Users(models.Model):
def message_update(self, msg_dict, update_vals=None):
return True
- def message_subscribe(self, partner_ids, subtype_ids=None):
+ def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True):
return True
@api.cr_uid_context
diff --git a/addons/mail/security/ir.model.access.csv b/addons/mail/security/ir.model.access.csv
index 701bbffbeca..7193db4a9a2 100644
--- a/addons/mail/security/ir.model.access.csv
+++ b/addons/mail/security/ir.model.access.csv
@@ -7,8 +7,8 @@ access_mail_mail_portal,mail.mail.portal,model_mail_mail,base.group_portal,1,1,1
access_mail_mail_user,mail.mail.user,model_mail_mail,base.group_user,1,1,1,0
access_mail_mail_system,mail.mail.system,model_mail_mail,base.group_system,1,1,1,1
access_mail_followers_all,mail.followers.all,model_mail_followers,,1,0,0,0
-access_mail_followers_portal,mail.followers.portal,model_mail_followers,base.group_portal,1,1,0,0
-access_mail_followers_user,mail.followers.user,model_mail_followers,base.group_user,1,1,0,0
+access_mail_followers_portal,mail.followers.portal,model_mail_followers,base.group_portal,1,1,1,0
+access_mail_followers_user,mail.followers.user,model_mail_followers,base.group_user,1,1,1,0
access_mail_followers_system,mail.followers.system,model_mail_followers,base.group_system,1,1,1,1
access_mail_notification_all,mail.notification.all,model_mail_notification,,1,0,0,0
access_mail_notification_portal,mail.notification.portal,model_mail_notification,base.group_portal,1,1,1,0
diff --git a/addons/mail/security/mail_security.xml b/addons/mail/security/mail_security.xml
index c05d434c789..642975ea7a5 100644
--- a/addons/mail/security/mail_security.xml
+++ b/addons/mail/security/mail_security.xml
@@ -7,17 +7,18 @@
Mail.channel: access only public and joined groups
- ['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.partner_id.id]), '&', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]
+ ['|', '|', ('public', '=', 'public'), ('message_partner_ids', 'in', [user.partner_id.id]), '&', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]
- mail.followers: read and write its own entries
+ mail.followers: write its own entries
[('partner_id', '=', user.partner_id.id)]
+
diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js
index 15584c518b5..7f916dd3df9 100644
--- a/addons/mail/static/src/js/mail_followers.js
+++ b/addons/mail/static/src/js/mail_followers.js
@@ -77,7 +77,7 @@ var Followers = form_common.AbstractField.extend({
self.do_follow();
}
else {
- self.do_unfollow();
+ self.do_unfollow([session.uid]);
}
});
@@ -145,15 +145,10 @@ var Followers = form_common.AbstractField.extend({
},
on_remove_follower: function (event) {
- var partner_id = $(event.target).data('id');
- var name = $(event.target).parent().find("a").html();
- if (confirm(_.str.sprintf(_t("Warning! \n %s won't be notified of any email or discussion on this document. Do you really want to remove him from the followers ?"), name))) {
- var context = new data.CompoundContext(this.build_context(), {});
- return this.ds_model.call('message_unsubscribe', [[this.view.datarecord.id],
- [partner_id],
- context])
- .then(this.proxy('read_value'));
- }
+ var res_model = $(event.target).parent().find('a').data('res-model');
+ var res_id = $(event.target).parent().find('a').data('res-id');
+ if (res_model == 'res.partner') { return this.do_unfollow(undefined, [res_id], undefined); }
+ else { return this.do_unfollow(undefined, undefined, [res_id]); }
},
on_follower_clicked: function (event) {
@@ -245,19 +240,13 @@ var Followers = form_common.AbstractField.extend({
// truncate number of displayed followers
_(this.followers).each(function (record) {
- var partner = {
- '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}))
- .appendTo(node_user_list);
+ $(qweb.render('mail_followers_partner', {
+ 'record': _.extend(record, {'avatar_url': mail_utils.get_image(session, record['res_model'], 'image_small', record['id'])}),
+ 'widget': self})
+ ).appendTo(node_user_list);
// On mouse-enter it will show the edit_subtype pencil.
- if (partner.is_editable) {
+ if (record.is_editable) {
self.$('.o_timeline_follower_list').on('mouseenter mouseleave', function(e) {
self.$('.o_timeline_edit_subtype')
.toggleClass('oe_hidden', e.type == 'mouseleave');
@@ -358,26 +347,33 @@ var Followers = form_common.AbstractField.extend({
$(record).attr('checked', 'checked');
});
},
-
- do_unfollow: function (user_pid) {
- if (confirm(_t("Warning! \nYou won't be notified of any email or discussion on this document. Do you really want to unfollow this document ?"))) {
+
+ do_unfollow: function (user_ids, partner_ids, channel_ids) {
+ if (confirm(_t("Warning! \n If you remove a follower, he won't be notified of any email or discussion on this document. Do you really want to remove this follower ?"))) {
_(this.$('.o_timeline_msg_subtype_check')).each(function (record) {
$(record).attr('checked',false);
});
- var action_unsubscribe = 'message_unsubscribe_users';
this.$('.o_timeline_subtype_list > .dropdown-toggle').attr('disabled', true);
- var follower_ids = [session.uid];
-
- if (user_pid) {
- action_unsubscribe = 'message_unsubscribe';
- follower_ids = [user_pid];
- }
-
var context = new data.CompoundContext(this.build_context(), {});
- return this.ds_model.call(action_unsubscribe, [[this.view.datarecord.id],
- follower_ids, context])
- .then(this.proxy('read_value'));
+
+ if (partner_ids || channel_ids) {
+ return this.ds_model.call(
+ 'message_unsubscribe', [
+ [this.view.datarecord.id],
+ partner_ids,
+ channel_ids,
+ context]
+ ).then(this.proxy('read_value'));
+ }
+ else {
+ return this.ds_model.call(
+ 'message_unsubscribe_users', [
+ [this.view.datarecord.id],
+ user_ids,
+ context]
+ ).then(this.proxy('read_value'));
+ }
}
return false;
},
@@ -404,7 +400,7 @@ var Followers = form_common.AbstractField.extend({
});
if (!checklist.length) {
- if (!this.do_unfollow(user_pid)) {
+ if (!this.do_unfollow(undefined, [user_pid], undefined)) {
$(event.target).attr("checked", "checked");
}
else {
diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml
index e38fa8f480d..dd6d9883abd 100644
--- a/addons/mail/static/src/xml/mail_followers.xml
+++ b/addons/mail/static/src/xml/mail_followers.xml
@@ -42,14 +42,17 @@
-
+ t-att-title="record.name"
+ t-att-data-res-model="record.res_model"
+ t-att-data-res-id="record.res_id"
+ t-att-data-id="record.id">
+
+ title="Remove this follower"/>
@@ -66,7 +69,7 @@