[MERGE] mail: varioux fixes and improvements.
Mail: - Chatter widget now checks email address in a given thread that are not linked to any partner; it proposes to create a partner that will be added as follower to the document for each found email address - fixed reload of a posted message - invite wizard now uses the many2many_tags_email widget, to avoid sending invitations to partners not having an email address defined Misc : - note: fixed padding of note leading to ugly display of notes bzr revid: tde@openerp.com-20121221163459-wv0jiss4wplla1yl
This commit is contained in:
+45
-26
@@ -886,9 +886,9 @@ class mail_thread(osv.AbstractModel):
|
||||
|
||||
return mail_message.create(cr, uid, values, context=context)
|
||||
|
||||
def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False,
|
||||
attachment_ids=None, context=None, content_subtype='plaintext',
|
||||
extra_email=[], **kwargs):
|
||||
def message_post_user_api(self, cr, uid, thread_id, body='', parent_id=False,
|
||||
attachment_ids=None, extra_emails=None, content_subtype='plaintext',
|
||||
context=None, **kwargs):
|
||||
""" Wrapper on message_post, used for user input :
|
||||
- mail gateway
|
||||
- quick reply in Chatter (refer to mail.js), not
|
||||
@@ -902,30 +902,41 @@ class mail_thread(osv.AbstractModel):
|
||||
to the related document. Should only be set by Chatter.
|
||||
- extra_email: [ 'Fabien <fpi@openerp.com>', 'al@openerp.com' ]
|
||||
"""
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
mail_message_obj = self.pool.get('mail.message')
|
||||
ir_attachment = self.pool.get('ir.attachment')
|
||||
extra_emails = extra_emails or []
|
||||
|
||||
# 1. Pre-processing: body, partner_ids, type and subtype
|
||||
if content_subtype == 'plaintext':
|
||||
body = tools.plaintext2html(body)
|
||||
# 1.A.1: pre-process partners and incoming extra_emails
|
||||
partner_ids = set([])
|
||||
for email in extra_emails:
|
||||
partner_id = partner_obj.find_or_create(cr, uid, email, context=context)
|
||||
# link mail with this from mail to the new partner id
|
||||
partner_msg_ids = mail_message_obj.search(cr, SUPERUSER_ID, [('email_from', '=', email), ('author_id', '=', False)], context=context)
|
||||
if partner_id and partner_msg_ids:
|
||||
mail_message_obj.write(cr, SUPERUSER_ID, partner_msg_ids, {'email_from': None, 'author_id': partner_id}, context=context)
|
||||
partner_ids.add((4, partner_id))
|
||||
if partner_ids:
|
||||
self.message_subscribe(cr, uid, [thread_id], [item[1] for item in partner_ids], context=context)
|
||||
|
||||
for partner in extra_email:
|
||||
part_ids = self.pool.get('res.partner').search(cr, uid, [('email', '=', partner)], context=context)
|
||||
if not part_ids:
|
||||
part_ids = [self.pool.get('res.partner').name_create(cr, uid, partner, context=context)[0]]
|
||||
self.message_subscribe(cr, uid, [thread_id], part_ids, context=context)
|
||||
|
||||
partner_ids = kwargs.pop('partner_ids', [])
|
||||
# 1.A.2: add recipients of parent message
|
||||
if parent_id:
|
||||
parent_message = self.pool.get('mail.message').browse(cr, uid, parent_id, context=context)
|
||||
partner_ids += [(4, partner.id) for partner in parent_message.partner_ids]
|
||||
parent_message = mail_message_obj.browse(cr, uid, parent_id, context=context)
|
||||
partner_ids |= set([(4, partner.id) for partner in parent_message.partner_ids])
|
||||
# TDE FIXME HACK: mail.thread -> private message
|
||||
if self._name == 'mail.thread' and parent_message.author_id.id:
|
||||
partner_ids.append((4, parent_message.author_id.id))
|
||||
partner_ids.add((4, parent_message.author_id.id))
|
||||
|
||||
message_type = kwargs.pop('type', 'comment')
|
||||
message_subtype = kwargs.pop('subtype', 'mail.mt_comment')
|
||||
# 1.A.3: add specified recipients
|
||||
partner_ids |= set(kwargs.pop('partner_ids', []))
|
||||
|
||||
# 2. Pre-processing: free attachments linked to the model
|
||||
# 1.B: handle body, message_type and message_subtype
|
||||
if content_subtype == 'plaintext':
|
||||
body = tools.plaintext2html(body)
|
||||
msg_type = kwargs.pop('type', 'comment')
|
||||
msg_subtype = kwargs.pop('subtype', 'mail.mt_comment')
|
||||
|
||||
# 2. Pre-processing: attachments
|
||||
# HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
|
||||
if attachment_ids:
|
||||
# TDE FIXME (?): when posting a private message, we use mail.thread as a model
|
||||
@@ -943,13 +954,12 @@ class mail_thread(osv.AbstractModel):
|
||||
ir_attachment.write(cr, SUPERUSER_ID, attachment_ids, {'res_model': model, 'res_id': thread_id}, context=context)
|
||||
else:
|
||||
attachment_ids = []
|
||||
attachment_ids = [(4, id) for id in attachment_ids]
|
||||
|
||||
# 3. Post message
|
||||
new_message_id = self.message_post(cr, uid, thread_id=thread_id, body=body, subject=subject, type=message_type,
|
||||
subtype=message_subtype, parent_id=parent_id, attachment_ids=[(4, id) for id in attachment_ids],
|
||||
context=context, partner_ids=partner_ids, **kwargs)
|
||||
|
||||
return new_message_id
|
||||
return self.message_post(cr, uid, thread_id=thread_id, body=body,
|
||||
type=msg_type, subtype=msg_subtype, parent_id=parent_id,
|
||||
attachment_ids=attachment_ids, partner_ids=partner_ids, context=context, **kwargs)
|
||||
|
||||
#------------------------------------------------------
|
||||
# Followers API
|
||||
@@ -969,7 +979,12 @@ class mail_thread(osv.AbstractModel):
|
||||
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
|
||||
""" Add partners to the records followers. """
|
||||
self.check_access_rights(cr, uid, 'read')
|
||||
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
if set(partner_ids) == set([user_pid]):
|
||||
self.check_access_rights(cr, uid, 'read')
|
||||
else:
|
||||
self.check_access_rights(cr, uid, 'write')
|
||||
|
||||
self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context)
|
||||
# if subtypes are not specified (and not set to a void list), fetch default ones
|
||||
if subtype_ids is None:
|
||||
@@ -991,7 +1006,11 @@ class mail_thread(osv.AbstractModel):
|
||||
|
||||
def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None):
|
||||
""" Remove partners from the records followers. """
|
||||
self.check_access_rights(cr, uid, 'read')
|
||||
user_pid = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'][0]
|
||||
if set(partner_ids) == set([user_pid]):
|
||||
self.check_access_rights(cr, uid, 'read')
|
||||
else:
|
||||
self.check_access_rights(cr, uid, 'write')
|
||||
return self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context)
|
||||
|
||||
def message_subscribe_from_parent(self, cr, uid, ids, updated_fields, context=None):
|
||||
|
||||
@@ -42,8 +42,7 @@ class res_partner_mail(osv.Model):
|
||||
'notification_email_send': lambda *args: 'comment'
|
||||
}
|
||||
|
||||
def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification',
|
||||
subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
|
||||
def message_post(self, cr, uid, thread_id, **kwargs):
|
||||
""" Override related to res.partner. In case of email message, set it as
|
||||
private:
|
||||
- add the target partner in the message partner_ids
|
||||
@@ -58,7 +57,6 @@ class res_partner_mail(osv.Model):
|
||||
partner_ids.append((4, thread_id))
|
||||
kwargs['partner_ids'] = partner_ids
|
||||
thread_id = False
|
||||
return super(res_partner_mail, self).message_post(cr, uid, thread_id, body=body, subject=subject,
|
||||
type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, **kwargs)
|
||||
return super(res_partner_mail, self).message_post(cr, uid, thread_id, **kwargs)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
+11
-17
@@ -116,32 +116,26 @@ class res_users(osv.Model):
|
||||
alias_pool.unlink(cr, uid, alias_ids, context=context)
|
||||
return res
|
||||
|
||||
def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False,
|
||||
attachment_ids=None, context=None, content_subtype='plaintext', **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related partner.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id.
|
||||
We therefore post on the user and redirect on its partner. """
|
||||
def _message_post_get_pid(self, cr, uid, thread_id, context=None):
|
||||
assert thread_id, "res.users does not support posting global messages"
|
||||
if context and 'thread_model' in context:
|
||||
context['thread_model'] = 'res.partner'
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
partner_id = self.browse(cr, uid, thread_id).partner_id.id
|
||||
return self.pool.get('res.partner').message_post_user_api(cr, uid, partner_id, body=body, subject=subject,
|
||||
parent_id=parent_id, attachment_ids=attachment_ids, context=context, content_subtype=content_subtype, **kwargs)
|
||||
return self.browse(cr, uid, thread_id).partner_id.id
|
||||
|
||||
def message_post_user_api(self, cr, uid, thread_id, context=None, **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related partner.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
partner_id = self._message_post_get_pid(cr, uid, thread_id, context=context)
|
||||
return self.pool.get('res.partner').message_post_user_api(cr, uid, partner_id, context=context, **kwargs)
|
||||
|
||||
def message_post(self, cr, uid, thread_id, context=None, **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related partner.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id.
|
||||
We therefore post on the user and redirect on its partner. """
|
||||
assert thread_id, "res.users does not support posting global messages"
|
||||
if context and 'thread_model' in context:
|
||||
context['thread_model'] = 'res.partner'
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
partner_id = self.browse(cr, uid, thread_id).partner_id.id
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
partner_id = self._message_post_get_pid(cr, uid, thread_id, context=context)
|
||||
return self.pool.get('res.partner').message_post(cr, uid, partner_id, context=context, **kwargs)
|
||||
|
||||
def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
|
||||
|
||||
@@ -253,6 +253,19 @@
|
||||
.openerp .oe_mail .oe_msg_composer .oe_msg_attachment_list{
|
||||
display: block;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_composer .oe_emails_from{
|
||||
font-size: 12px;
|
||||
margin-left: 20px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_composer .oe_emails_from label{
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
line-height: 14px;
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_composer .oe_emails_from input{
|
||||
vertical-align: middle;
|
||||
}
|
||||
.openerp .oe_mail .oe_attachment{
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
@@ -465,8 +478,8 @@
|
||||
}
|
||||
.openerp .oe_mail .oe_msg_content .oe_mail_list_recipients{
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
margin: 4px 0 4px 20px;
|
||||
text-indent: -20px;
|
||||
}
|
||||
|
||||
/* ---------------- HIDDEN MESSAGES ------------------ */
|
||||
@@ -578,6 +591,14 @@
|
||||
margin-right:4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.openerp .oe_followers .oe_remove_follower{
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.openerp .oe_followers .oe_show_more{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* ---------------- MESSAGES BODY ------------------ */
|
||||
.openerp .oe_mail .oe_msg_content .oe_blockquote,
|
||||
|
||||
@@ -369,6 +369,7 @@ openerp.mail = function (session) {
|
||||
this._super(parent, datasets, options);
|
||||
this.show_compact_message = false;
|
||||
this.show_delete_attachment = true;
|
||||
this.emails_from = [];
|
||||
},
|
||||
|
||||
start: function () {
|
||||
@@ -478,9 +479,11 @@ openerp.mail = function (session) {
|
||||
this.$('.oe_cancel').on('click', _.bind( this.on_cancel, this) );
|
||||
this.$('.oe_post').on('click', _.bind( this.on_message_post, this) );
|
||||
this.$('.oe_full').on('click', _.bind( this.on_compose_fullmail, this, this.id ? 'reply' : 'comment') );
|
||||
|
||||
|
||||
/* stack for don't close the compose form if the user click on a button */
|
||||
this.$('.oe_msg_footer').on('mousedown', _.bind( function () { this.stay_open = true; }, this));
|
||||
this.$('.oe_msg_left, .oe_msg_center').on('mousedown', _.bind( function () { this.stay_open = true; }, this));
|
||||
this.$('.oe_msg_left, .oe_msg_content').on('mouseup', _.bind( function () { this.$('textarea').focus(); }, this));
|
||||
|
||||
var ev_stay = {};
|
||||
ev_stay.mouseup = ev_stay.keydown = ev_stay.focus = function () { self.stay_open = false; };
|
||||
this.$('textarea:not(.oe_compact)').on(ev_stay);
|
||||
@@ -491,6 +494,8 @@ openerp.mail = function (session) {
|
||||
|
||||
// event: delete child attachments off the oe_msg_attachment_list box
|
||||
this.$(".oe_msg_attachment_list").on('click', '.oe_delete', this.on_attachment_delete);
|
||||
|
||||
this.$(".oe_emails_from").on('change', 'input', this.on_checked_email_from);
|
||||
},
|
||||
|
||||
on_compose_fullmail: function (default_composition_mode) {
|
||||
@@ -559,46 +564,79 @@ openerp.mail = function (session) {
|
||||
}
|
||||
},
|
||||
|
||||
/*post a message and fetch the message*/
|
||||
check_recipient_partners: function (emails) {
|
||||
var self = this;
|
||||
var deferreds = [];
|
||||
var ds_partner = new session.web.DataSetSearch(this, 'res.partner');
|
||||
_.each(emails, function (email) {
|
||||
ds_partner.call('search', [[['email', '=', email]]]).then(function (partner_ids) {
|
||||
if (!partner_ids.length) {
|
||||
var deferred = $.Deferred();
|
||||
var pop = new session.web.form.FormOpenPopup(this);
|
||||
pop.show_element(
|
||||
'res.partner',
|
||||
0,
|
||||
{
|
||||
'default_email': email,
|
||||
'force_email': true,
|
||||
'ref': "compound_context",
|
||||
},
|
||||
{
|
||||
title: _t("Please complete partner's informations"),
|
||||
}
|
||||
);
|
||||
pop.on('write_completed, closed', self, function () {
|
||||
deferred.resolve();
|
||||
});
|
||||
deferreds.push(deferred);
|
||||
}
|
||||
});
|
||||
});
|
||||
return $.when.apply( $, deferreds );
|
||||
},
|
||||
|
||||
on_message_post: function (event) {
|
||||
var self = this;
|
||||
|
||||
var comment_node = this.$('textarea');
|
||||
var body = comment_node.val();
|
||||
|
||||
if (this.do_check_attachment_upload() && (this.attachment_ids.length || body.match(/\S+/))) {
|
||||
//session.web.blockUI();
|
||||
this.parent_thread.ds_thread.call('message_post_user_api', [
|
||||
this.context.default_res_id,
|
||||
body,
|
||||
false,
|
||||
this.context.default_parent_id,
|
||||
_.map(this.attachment_ids, function (file) {return file.id;}),
|
||||
this.parent_thread.context
|
||||
]).done(function (record) {
|
||||
var thread = self.parent_thread;
|
||||
var root = thread == self.options.root_thread;
|
||||
if (self.options.display_indented_thread < self.thread_level && thread.parent_message) {
|
||||
var thread = thread.parent_message.parent_thread;
|
||||
}
|
||||
// create object and attach to the thread object
|
||||
thread.message_fetch([['id', 'child_of', [self.id]]], false, [record], function (arg, data) {
|
||||
var message = thread.create_message_object( data[0] );
|
||||
// insert the message on dom
|
||||
thread.insert_message( message, root ? undefined : self.$el, root );
|
||||
});
|
||||
self.on_cancel();
|
||||
//session.web.unblockUI();
|
||||
});
|
||||
return true;
|
||||
if (this.do_check_attachment_upload() && (this.attachment_ids.length || this.$('textarea').val().match(/\S+/))) {
|
||||
// create list of new partners
|
||||
var extra_email = _.map(_.filter(this.emails_from, function (f) {return f[1]}), function (f) {return f[0]});
|
||||
this.check_recipient_partners(extra_email).done(function () {
|
||||
self.do_send_message_post();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/*do post a message and fetch the message*/
|
||||
do_send_message_post: function () {
|
||||
var self = this;
|
||||
this.parent_thread.ds_thread._model.call('message_post_user_api', [this.context.default_res_id], {
|
||||
'body': this.$('textarea').val(),
|
||||
'subject': false,
|
||||
'parent_id': this.context.default_parent_id,
|
||||
'attachment_ids': _.map(this.attachment_ids, function (file) {return file.id;}),
|
||||
'extra_emails': _.map(_.filter(this.emails_from, function (f) {return f[1]}), function (f) {return f[0]}),
|
||||
'context': this.parent_thread.context,
|
||||
}).done(function (message_id) {
|
||||
var thread = self.parent_thread;
|
||||
var root = thread == self.options.root_thread;
|
||||
if (self.options.display_indented_thread < self.thread_level && thread.parent_message) {
|
||||
var thread = thread.parent_message.parent_thread;
|
||||
}
|
||||
// create object and attach to the thread object
|
||||
thread.message_fetch([["id", "=", message_id]], false, [message_id], function (arg, data) {
|
||||
var message = thread.create_message_object( data[0] );
|
||||
// insert the message on dom
|
||||
thread.insert_message( message, root ? undefined : self.$el, root );
|
||||
});
|
||||
self.on_cancel();
|
||||
});
|
||||
},
|
||||
|
||||
/* convert the compact mode into the compose message
|
||||
*/
|
||||
on_compose_expandable: function (event) {
|
||||
|
||||
if ((!this.stay_open || (event && event.type == 'click')) && (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/))) {
|
||||
this.get_emails_from();
|
||||
if ((!this.stay_open || (event && event.type == 'click')) && (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/) && !this.attachment_ids.length)) {
|
||||
this.show_composer = !this.show_composer || this.stay_open;
|
||||
this.reinit();
|
||||
}
|
||||
@@ -620,6 +658,41 @@ openerp.mail = function (session) {
|
||||
if (!this.show_composer) {
|
||||
this.reinit();
|
||||
}
|
||||
},
|
||||
|
||||
get_emails_from: function () {
|
||||
var self = this;
|
||||
var messages = [];
|
||||
|
||||
if (this.parent_thread.parent_message) {
|
||||
// go to the parented message
|
||||
var message = this.parent_thread.parent_message;
|
||||
var parent_message = message.parent_id ? message.parent_thread.parent_message : message;
|
||||
var messages = [parent_message].concat(parent_message.get_childs());
|
||||
} else if (this.options.emails_from_on_composer) {
|
||||
// get all wall messages if is not a mail.Wall
|
||||
_.each(this.options.root_thread.messages, function (msg) {messages.push(msg); messages.concat(msg.get_childs());});
|
||||
}
|
||||
|
||||
var emails_from = _.map(_.filter(messages,
|
||||
function (thread) {return thread.author_id && !thread.author_id[0];}),
|
||||
function (thread) {return thread.author_id[1];});
|
||||
|
||||
return _.each(emails_from, function (email_from) {
|
||||
if (!_.find(self.emails_from, function (from) {return from[0] == email_from;})) {
|
||||
self.emails_from.push([email_from, true]);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
on_checked_email_from: function (event) {
|
||||
var $input = $(event.target);
|
||||
var email = $input.attr("data");
|
||||
_.each(this.emails_from, function (email_from) {
|
||||
if (email_from[0] == email) {
|
||||
email_from[1] = $input.is(":checked");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -982,9 +1055,11 @@ openerp.mail = function (session) {
|
||||
this.is_private = datasets.is_private || false;
|
||||
this.author_id = datasets.author_id || false;
|
||||
this.thread_level = (datasets.thread_level+1) || 0;
|
||||
this.partner_ids = datasets.partner_ids || [];
|
||||
if (datasets.author_id)
|
||||
this.partner_ids.push(datasets.author_id);
|
||||
datasets.partner_ids = datasets.partner_ids || [];
|
||||
if (datasets.author_id && ! _.contains(datasets.partner_ids, datasets.author_id) && datasets.author_id[0]) {
|
||||
datasets.partner_ids.push(datasets.author_id);
|
||||
}
|
||||
this.partner_ids = datasets.partner_ids;
|
||||
this.messages = [];
|
||||
|
||||
this.options.flat_mode = !!(this.options.display_indented_thread > this.thread_level ? this.options.display_indented_thread - this.thread_level : 0);
|
||||
@@ -1450,6 +1525,7 @@ openerp.mail = function (session) {
|
||||
'message_ids': undefined,
|
||||
'compose_as_todo' : false,
|
||||
'readonly' : false,
|
||||
'emails_from_on_composer': true,
|
||||
}, this.action.params);
|
||||
|
||||
this.action.params.help = this.action.help || false;
|
||||
@@ -1490,7 +1566,7 @@ openerp.mail = function (session) {
|
||||
$(window).resize( _.bind(this.thread.on_scroll, this.thread) );
|
||||
this.$el.resize( _.bind(this.thread.on_scroll, this.thread) );
|
||||
window.setTimeout( _.bind(this.thread.on_scroll, this.thread), 500 );
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1527,6 +1603,10 @@ openerp.mail = function (session) {
|
||||
}
|
||||
|
||||
this.domain = this.node.params && this.node.params.domain || [];
|
||||
|
||||
if (!this.__parentedParent.is_action_enabled('edit')) {
|
||||
this.node.params.show_link = false;
|
||||
}
|
||||
},
|
||||
|
||||
start: function () {
|
||||
@@ -1615,6 +1695,7 @@ openerp.mail = function (session) {
|
||||
'show_record_name': true,
|
||||
'show_compact_message': this.action.params.view_mailbox ? false : 1,
|
||||
'view_inbox': false,
|
||||
'emails_from_on_composer': false,
|
||||
}, this.action.params);
|
||||
},
|
||||
|
||||
|
||||
@@ -26,12 +26,16 @@ openerp_mail_followers = function(session, mail) {
|
||||
this._super.apply(this, arguments);
|
||||
this.image = this.node.attrs.image || 'image_small';
|
||||
this.comment = this.node.attrs.help || false;
|
||||
this.displayed_nb = this.node.attrs.displayed_nb || 10;
|
||||
this.displayed_limit = this.node.attrs.displayed_nb || 10;
|
||||
this.displayed_nb = this.displayed_limit;
|
||||
this.ds_model = new session.web.DataSetSearch(this, this.view.model);
|
||||
this.ds_follow = new session.web.DataSetSearch(this, this.field.relation);
|
||||
this.ds_users = new session.web.DataSetSearch(this, 'res.users');
|
||||
|
||||
this.value = [];
|
||||
this.followers = [];
|
||||
|
||||
this.view_is_editable = this.__parentedParent.is_action_enabled('edit');
|
||||
},
|
||||
|
||||
start: function() {
|
||||
@@ -69,29 +73,47 @@ openerp_mail_followers = function(session, mail) {
|
||||
// event: click on a subtype, that (un)subscribe for this subtype
|
||||
this.$el.on('click', '.oe_subtype_list input', self.do_update_subscription);
|
||||
// event: click on 'invite' button, that opens the invite wizard
|
||||
this.$('.oe_invite').on('click', function (event) {
|
||||
action = {
|
||||
type: 'ir.actions.act_window',
|
||||
res_model: 'mail.wizard.invite',
|
||||
view_mode: 'form',
|
||||
view_type: 'form',
|
||||
views: [[false, 'form']],
|
||||
target: 'new',
|
||||
context: {
|
||||
'default_res_model': self.view.dataset.model,
|
||||
'default_res_id': self.view.datarecord.id,
|
||||
},
|
||||
}
|
||||
self.do_action(action, {
|
||||
on_close: function() {
|
||||
self.read_value();
|
||||
},
|
||||
});
|
||||
this.$('.oe_invite').on('click', self.on_invite_follower);
|
||||
this.$el.on('click', '.oe_remove_follower', self.on_remove_follower);
|
||||
this.$el.on('click', '.oe_show_more', self.on_show_more_followers)
|
||||
},
|
||||
|
||||
on_invite_follower: function (event) {
|
||||
var self = this;
|
||||
var action = {
|
||||
type: 'ir.actions.act_window',
|
||||
res_model: 'mail.wizard.invite',
|
||||
view_mode: 'form',
|
||||
view_type: 'form',
|
||||
views: [[false, 'form']],
|
||||
target: 'new',
|
||||
context: {
|
||||
'default_res_model': this.view.dataset.model,
|
||||
'default_res_id': this.view.datarecord.id,
|
||||
},
|
||||
}
|
||||
this.do_action(action, {
|
||||
on_close: function() {
|
||||
self.read_value();
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
on_show_more_followers: function (event) {
|
||||
this.displayed_nb += this.displayed_limit;
|
||||
this.display_followers(false);
|
||||
},
|
||||
|
||||
on_remove_follower: function (event) {
|
||||
var partner_id = $(event.target).data('id');
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call('message_unsubscribe', [[this.view.datarecord.id], [partner_id], context])
|
||||
.then(this.proxy('read_value'));
|
||||
},
|
||||
|
||||
read_value: function () {
|
||||
var self = this;
|
||||
this.displayed_nb = this.displayed_limit;
|
||||
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) {
|
||||
self.value = results[0].message_follower_ids;
|
||||
self.render_value();
|
||||
@@ -145,20 +167,20 @@ openerp_mail_followers = function(session, mail) {
|
||||
/** Display the followers */
|
||||
display_followers: function (records) {
|
||||
var self = this;
|
||||
records = records || [];
|
||||
this.message_is_follower = this.set_is_follower(records);
|
||||
this.followers = records || this.followers;
|
||||
this.message_is_follower = this.set_is_follower(this.followers);
|
||||
// clean and display title
|
||||
var node_user_list = this.$('.oe_follower_list').empty();
|
||||
this.$('.oe_follower_title').html(this._format_followers(records.length));
|
||||
this.$('.oe_follower_title').html(this._format_followers(this.followers.length));
|
||||
// truncate number of displayed followers
|
||||
truncated = records.splice(0, this.displayed_nb);
|
||||
var truncated = this.followers.slice(0, this.displayed_nb);
|
||||
_(truncated).each(function (record) {
|
||||
record.avatar_url = mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record.id);
|
||||
$(session.web.qweb.render('mail.followers.partner', {'record': record})).appendTo(node_user_list);
|
||||
$(session.web.qweb.render('mail.followers.partner', {'record': record, 'widget': self})).appendTo(node_user_list);
|
||||
});
|
||||
// FVA note: be sure it is correctly translated
|
||||
if (truncated.length < records.length) {
|
||||
$('<div class="oe_partner">And ' + (records.length - truncated.length) + ' more.</div>').appendTo(node_user_list);
|
||||
if (truncated.length < this.followers.length) {
|
||||
$(session.web.qweb.render('mail.followers.show_more', {'number': (this.followers.length - truncated.length)} )).appendTo(node_user_list);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -196,18 +218,23 @@ openerp_mail_followers = function(session, mail) {
|
||||
var subtype_list_ul = this.$('.oe_subtype_list');
|
||||
subtype_list_ul.empty();
|
||||
var records = data[this.view.datarecord.id || this.view.dataset.ids[0]].message_subtype_data;
|
||||
_(records).each(function (record, record_name) {
|
||||
record.name = record_name;
|
||||
record.followed = record.followed || undefined;
|
||||
$(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo( self.$('.oe_subtype_list') );
|
||||
});
|
||||
if (records.length > 1) {
|
||||
_(records).each(function (record, record_name) {
|
||||
record.name = record_name;
|
||||
record.followed = record.followed || undefined;
|
||||
$(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo( self.$('.oe_subtype_list') );
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
do_follow: function () {
|
||||
_(this.$('.oe_msg_subtype_check')).each(function (record) {
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context])
|
||||
.then(this.proxy('read_value'));
|
||||
|
||||
_.each(this.$('.oe_subtype_list input'), function (record) {
|
||||
$(record).attr('checked', 'checked');
|
||||
});
|
||||
this.do_update_subscription();
|
||||
},
|
||||
|
||||
do_unfollow: function () {
|
||||
@@ -229,9 +256,13 @@ openerp_mail_followers = function(session, mail) {
|
||||
}
|
||||
});
|
||||
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], this.message_is_follower ? checklist : undefined, context])
|
||||
.then(this.proxy('read_value'));
|
||||
if (!checklist.length) {
|
||||
this.do_unfollow();
|
||||
} else {
|
||||
var context = new session.web.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], checklist, context])
|
||||
.then(this.proxy('read_value'));
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img>
|
||||
<div class='oe_name'><t t-raw='attachment.name' /></div>
|
||||
</a>
|
||||
<div class='oe_delete oe_e' title="Delete this attachment" t-attf-data-id="{attachment.id}">[</div>
|
||||
<div class='oe_delete oe_e' title="Delete this attachment" t-att-data-id="attachment.id">[</div>
|
||||
<div class='oe_progress_bar'>
|
||||
uploading
|
||||
</div>
|
||||
@@ -91,7 +91,7 @@
|
||||
<img t-att-src="widget.attachments_resize_image(attachment.id, [100,80])"></img>
|
||||
<div class='oe_name'><t t-raw='attachment.name' /></div>
|
||||
</a>
|
||||
<div class='oe_delete oe_e'>[</div>
|
||||
<div class='oe_delete oe_e' title="Delete this attachment" t-att-data-id="attachment.id">[</div>
|
||||
<div class='oe_progress_bar'>
|
||||
uploading
|
||||
</div>
|
||||
@@ -113,19 +113,28 @@
|
||||
<t t-if="!widget.parent_thread.parent_message.record_name">this document</t>
|
||||
</span>
|
||||
</t>
|
||||
<t t-if="!widget.is_private and widget.partner_ids.length"> and </t>
|
||||
<t t-if="!widget.is_private and (widget.partner_ids.length or (widget.author_id and widget.author_id[0]))"> and </t>
|
||||
<t t-set="inc" t-value="0"/>
|
||||
<t t-if="widget.partner_ids.length" t-foreach="widget.partner_ids" t-as="partner">
|
||||
<t t-foreach="widget.partner_ids" t-as="partner">
|
||||
<span t-attf-class="oe_partner_follower #{inc>=3?'oe_hidden':''}"><t t-if="inc" t-raw="', '"/>
|
||||
<a t-if="widget.options.show_link" t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-raw="partner[1]"/></a>
|
||||
<t t-if="!widget.options.show_link" t-raw="partner[1]"/>
|
||||
</span><t t-set="inc" t-value="inc+1"/>
|
||||
</span>
|
||||
<t t-set="inc" t-value="inc+1"/>
|
||||
</t>
|
||||
<t t-if="widget.partner_ids.length>=3">
|
||||
<span class="oe_more">, <a><t t-raw="widget.partner_ids.length-3"/> others...</a></span>
|
||||
<t t-if="widget.partner_ids.length > 3">
|
||||
<span class="oe_more">, <a><t t-raw="widget.partner_ids.length - 3"/> others...</a></span>
|
||||
<a class="oe_more_hidden"><<<</a>
|
||||
</t>
|
||||
</div>
|
||||
<div class="oe_emails_from">
|
||||
<t t-foreach='widget.emails_from' t-as='email_from'>
|
||||
<label title="Add them into recipients and followers">
|
||||
<input type="checkbox" t-att-checked="email_from[1] ? 'checked' : undefind" t-att-data="email_from[0]"/>
|
||||
<t t-raw="email_from[0]"/>
|
||||
</label>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
@@ -232,8 +241,8 @@
|
||||
<t t-if="widget.attachment_ids.length > 0">
|
||||
<div class="oe_msg_attachment_list"></div>
|
||||
</t>
|
||||
<a t-if="widget.author_id and widget.options.show_link" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
|
||||
<span t-if="widget.author_id and !widget.options.show_link"><t t-raw="widget.author_id[1]"/></span>
|
||||
<a t-if="widget.author_id and widget.options.show_link and widget.author_id[0]" t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a>
|
||||
<span t-if="widget.author_id and (!widget.options.show_link or !widget.author_id[0])"><t t-raw="widget.author_id[1]"/></span>
|
||||
<span class='oe_subtle'>•</span>
|
||||
<span t-att-title="widget.date"><t t-raw="widget.timerelative"/></span>
|
||||
<span t-if="!widget.options.readonly" class='oe_subtle'>•</span>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<hr size="2"></hr>
|
||||
<div class='oe_follower_title_box'>
|
||||
<h4 class='oe_follower_title'>Followers</h4>
|
||||
<a href='#' class="oe_invite">Invite others</a>
|
||||
<a t-if="widget.view_is_editable" href='#' class="oe_invite">Add others</a>
|
||||
</div>
|
||||
<div class="oe_follower_list"></div>
|
||||
</div>
|
||||
@@ -32,6 +32,7 @@
|
||||
<div t-name="mail.followers.partner" class='oe_partner'>
|
||||
<img class="oe_mail_thumbnail oe_mail_frame" t-attf-src="{record.avatar_url}"/>
|
||||
<a t-attf-href="#model=res.partner&id=#{record.id}"><t t-raw="record.name"/></a>
|
||||
<span t-if="widget.view_is_editable" class="oe_remove_follower oe_e" title="Remove this follower" t-att-data-id="record.id">X</span>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
@@ -47,4 +48,8 @@
|
||||
</table>
|
||||
</t>
|
||||
|
||||
<t t-name="mail.followers.show_more">
|
||||
<div class="oe_partner oe_show_more">And <t t-raw="number"/> more.</div>
|
||||
</t>
|
||||
|
||||
</template>
|
||||
|
||||
@@ -49,17 +49,6 @@ class invite_wizard(osv.osv_memory):
|
||||
'message': fields.html('Message'),
|
||||
}
|
||||
|
||||
def onchange_partner_ids(self, cr, uid, ids, value, context=None):
|
||||
""" onchange_partner_ids (value format: [[6, 0, [3, 4]]]). The
|
||||
basic purpose of this method is to check that destination partners
|
||||
effectively have email addresses. Otherwise a warning is thrown.
|
||||
"""
|
||||
res = {'value': {}}
|
||||
if not value or not value[0] or not value[0][0] == 6:
|
||||
return
|
||||
res.update(self.pool.get('mail.message').check_partners_email(cr, uid, value[0][2], context=context))
|
||||
return res
|
||||
|
||||
def add_followers(self, cr, uid, ids, context=None):
|
||||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
model_obj = self.pool.get(wizard.res_model)
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
<group>
|
||||
<field name="res_model" invisible="1"/>
|
||||
<field name="res_id" invisible="1"/>
|
||||
<field name="partner_ids" widget="many2many_tags"
|
||||
on_change="onchange_partner_ids(partner_ids)" />
|
||||
<field name="partner_ids" widget="many2many_tags_email"
|
||||
placeholder="Add contacts to notify..."
|
||||
context="{'force_email':True}"/>
|
||||
<field name="message"/>
|
||||
</group>
|
||||
<footer>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.openerp .oe_form .oe_form_field.oe_memo {
|
||||
margin: 0 -16px 0 -16px;
|
||||
margin: 0;
|
||||
padding: 0px;
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
.oe_pad.oe_memo
|
||||
width: auto
|
||||
.oe_form_field.oe_memo
|
||||
margin: 0 -16px 0 -16px
|
||||
margin: 0
|
||||
padding: 0px
|
||||
width: 100%
|
||||
min-height: 200px
|
||||
|
||||
Reference in New Issue
Block a user