[IMP] [CLEAN] [WIP] composer: cleaning of the server-side code. It now relies less on context keys and values; some fields have been added to manage the composition mode, model, res_id and message_id as a classic form. Updated form view, with invisible fields, to have those value accessible and modifiable through onchange or through JS. Updated JS-part of the composer to handle the new composer; less options, less logic client-side ! Still not finished, short in time today (have to check mass_mail, templates).
bzr revid: tde@openerp.com-20120822162151-n9o23ik0v45h7v6j
This commit is contained in:
parent
9c3e455799
commit
4e6e86fab5
|
@ -104,87 +104,60 @@ openerp.mail = function(session) {
|
|||
* @param {Object} [options]
|
||||
* @param {String} [options.res_model] res_model of document [REQUIRED]
|
||||
* @param {Number} [options.res_id] res_id of record [REQUIRED]
|
||||
* @param {Number} [options.formatting] true/false, tells whether
|
||||
* we are in advance formatting mode
|
||||
* @param {String} [options.model] mail.compose.message.mode (see
|
||||
* composition wizard)
|
||||
* @param {String} [options.composition_mode] mail.compose.message.mode
|
||||
* (see composition wizard)
|
||||
* @param {Number} [options.msg_id] id of a message in case we are in
|
||||
* reply mode
|
||||
*/
|
||||
init: function(parent, options) {
|
||||
init: function (parent, options) {
|
||||
var self = this;
|
||||
this._super(parent);
|
||||
// options
|
||||
this.options = options || {};
|
||||
this.options.context = options.context || {};
|
||||
this.options.formatting = options.formatting || false;
|
||||
this.options.mode = options.mode || 'comment';
|
||||
this.options.composition_mode = options.composition_mode || 'comment';
|
||||
this.options.form_xml_id = options.form_xml_id || 'email_compose_message_wizard_form_chatter';
|
||||
this.options.form_view_id = false;
|
||||
if (this.options.mode == 'reply') {
|
||||
this.options.active_id = this.options.msg_id;
|
||||
} else {
|
||||
this.options.active_id = this.options.res_id;
|
||||
}
|
||||
this.formatting = false;
|
||||
this.options.form_view_id = options.form_view_id || false;
|
||||
this.options.context = options.context || {};
|
||||
// debug
|
||||
console.groupCollapsed('New ComposeMessage: model', this.options.res_model, ', id', this.options.res_id);
|
||||
console.log('context:', this.options.context);
|
||||
console.groupEnd();
|
||||
},
|
||||
|
||||
/**
|
||||
* Reinitialize the widget field values to the default values. The
|
||||
* purpose is to avoid to destroy and re-build a form view. Default
|
||||
* values are therefore given as for an onchange. */
|
||||
reinit: function() {
|
||||
var self = this;
|
||||
if (! this.form_view) return;
|
||||
var call_defer = this.ds_compose.call('default_get', [['subject', 'body_text', 'body', 'attachment_ids', 'dest_partner_ids'], this.ds_compose.get_context()]).then(
|
||||
function (result) {
|
||||
self.form_view.on_processed_onchange({'value': result}, []);
|
||||
});
|
||||
return call_defer;
|
||||
},
|
||||
|
||||
/**
|
||||
* Override-hack of do_action: clean the form */
|
||||
do_action: function(action, on_close) {
|
||||
// this.init_comments();
|
||||
return this._super(action, on_close);
|
||||
},
|
||||
|
||||
/**
|
||||
* Widget start function
|
||||
* - builds and initializes the form view */
|
||||
start: function() {
|
||||
var self = this;
|
||||
start: function () {
|
||||
this._super.apply(this, arguments);
|
||||
// customize display: add avatar, clean previous content
|
||||
var user_avatar = mail.ChatterUtils.get_image(this.session.prefix, this.session.session_id, 'res.users', 'image_small', this.session.uid);
|
||||
this.$element.find('img.oe_mail_icon').attr('src', user_avatar);
|
||||
this.$element.find('div.oe_mail_msg_content').empty();
|
||||
// create a context for the default_get of the compose form
|
||||
var widget_context = {
|
||||
'active_model': this.options.res_model,
|
||||
'active_id': this.options.active_id,
|
||||
'mail.compose.message.mode': this.options.mode,
|
||||
};
|
||||
var context = _.extend({}, this.options.context, widget_context);
|
||||
// create a context for the dataset and default_get of the wizard
|
||||
var context = this._update_context({});
|
||||
console.log(context);
|
||||
// debugger
|
||||
this.ds_compose = new session.web.DataSetSearch(this, 'mail.compose.message', context);
|
||||
// find the id of the view to display in the chatter form
|
||||
var data_ds = new session.web.DataSetSearch(this, 'ir.model.data');
|
||||
var deferred_form_id = data_ds.call('get_object_reference', ['mail', this.options.form_xml_id]).then( function (result) {
|
||||
if (result) {
|
||||
self.options.form_view_id = result[1];
|
||||
}
|
||||
}).pipe(this.proxy('create_form_view'));
|
||||
return deferred_form_id;
|
||||
return data_ds.call('get_object_reference', ['mail', this.options.form_xml_id]).pipe(this.proxy('create_form_view'));
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a FormView, then append it to the to widget DOM. */
|
||||
create_form_view: function () {
|
||||
/** Update the context of the compose wizard */
|
||||
_update_context: function (dest_context) {
|
||||
_.extend(dest_context, this.options.context, {
|
||||
'default_model': this.options.res_model,
|
||||
'mail.compose.message.mode': this.options.composition_mode
|
||||
});
|
||||
if (this.options.composition_mode == 'comment') {
|
||||
_.extend(dest_context, {'default_res_id': this.options.res_id});
|
||||
}
|
||||
else if (this.options.composition_mode == 'reply') {
|
||||
_.extend(dest_context, {'active_id': this.options.msg_id});
|
||||
}
|
||||
return dest_context
|
||||
},
|
||||
|
||||
/** Create a FormView, then append it to the to widget DOM. */
|
||||
create_form_view: function (form_view_id) {
|
||||
this.options.form_view_id = form_view_id[1] || false;
|
||||
var self = this;
|
||||
// destroy previous form_view if any
|
||||
if (this.form_view) { this.form_view.destroy(); }
|
||||
|
@ -200,12 +173,31 @@ openerp.mail = function(session) {
|
|||
return $.when(this.form_view.appendTo(msg_node)).pipe(function() {
|
||||
self.bind_events();
|
||||
self.form_view.do_show();
|
||||
if (self.options.formatting) { self.toggle_formatting_mode(); }
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this._super.apply(this, arguments);
|
||||
/**
|
||||
* Reinitialize the widget field values to the default values. The
|
||||
* purpose is to avoid to destroy and re-build a form view. Default
|
||||
* values are therefore given as for an on_change. */
|
||||
refresh: function (options_update_values) {
|
||||
var self = this;
|
||||
// debugger
|
||||
this.options = _.extend(this.options, options_update_values);
|
||||
if (! this.form_view) return;
|
||||
this.ds_compose.context = this._update_context(this.ds_compose.context);
|
||||
return this.ds_compose.call('default_get', [
|
||||
['subject', 'body_text', 'body', 'attachment_ids', 'partner_ids', 'composition_mode',
|
||||
'res_model', 'res_id', 'parent_id', 'content_subtype'],
|
||||
this.ds_compose.get_context(),
|
||||
]).then( function (result) { self.form_view.on_processed_onchange({'value': result}, []); });
|
||||
},
|
||||
|
||||
/**
|
||||
* Override-hack of do_action: clean the form */
|
||||
do_action: function(action, on_close) {
|
||||
console.log('compose_message do_action', action, on_close);
|
||||
return this._super(action, on_close);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -213,38 +205,23 @@ openerp.mail = function(session) {
|
|||
* in the function. */
|
||||
bind_events: function() {
|
||||
var self = this;
|
||||
this.$element.find('button.oe_form_button').click(function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
// this.$element.find('button.oe_form_button').click(function (event) {
|
||||
// event.preventDefault();
|
||||
// event.stopPropagation();
|
||||
// });
|
||||
// event: click on 'Formatting' icon-link that toggles the advanced
|
||||
// formatting options for writing a message (subject, body_html)
|
||||
this.$element.on('click', 'button.oe_mail_compose_message_formatting', function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
self.toggle_formatting_mode(event);
|
||||
});
|
||||
// this.$element.on('click', 'button.oe_mail_compose_message_formatting', function (event) {
|
||||
// event.preventDefault();
|
||||
// event.stopPropagation();
|
||||
// self.toggle_formatting_mode(event);
|
||||
// });
|
||||
// event: click on 'Attachment' icon-link that opens the dialog to
|
||||
// add an attachment.
|
||||
this.$element.on('click', 'button.oe_mail_compose_message_attachment', function (event) {
|
||||
event.stopImmediatePropagation();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the formatting mode. */
|
||||
toggle_formatting_mode: function(event) {
|
||||
this.formatting = ! this.formatting;
|
||||
// update context of datasetsearch
|
||||
this.ds_compose.context.formatting = this.formatting;
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the values of the composition form; with possible different
|
||||
* values for body and body_html. */
|
||||
set_body_value: function(body, body_html) {
|
||||
this.form_view.fields.body.set_value(body);
|
||||
this.form_view.fields.body_html.set_value(body_html);
|
||||
},
|
||||
}),
|
||||
|
||||
/**
|
||||
|
@ -398,12 +375,15 @@ openerp.mail = function(session) {
|
|||
});
|
||||
// event: click on "Reply by email" in msg side menu (email style)
|
||||
this.$element.on('click', 'a.oe_mail_msg_reply_by_email', function (event) {
|
||||
console.log('cacaprout');
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
var msg_id = event.srcElement.dataset.msg_id;
|
||||
var formatting = (event.srcElement.dataset.formatting == 'html');
|
||||
if (! msg_id) return false;
|
||||
self.instantiate_composition_form('reply', formatting, msg_id);
|
||||
// self.instantiate_composition_form('reply', formatting, msg_id);
|
||||
console.log('cacaprout2');
|
||||
self.compose_message_widget.refresh({'composition_mode': 'reply', 'msg_id': parseInt(msg_id)});
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -420,15 +400,14 @@ openerp.mail = function(session) {
|
|||
return this._super(action, on_close);
|
||||
},
|
||||
|
||||
/** Instantiate the composition form, with paramteres coming from thread parameters */
|
||||
/** Instantiate the composition form, with parameters coming from thread parameters */
|
||||
instantiate_composition_form: function(mode, formatting, msg_id, context) {
|
||||
if (this.compose_message_widget) {
|
||||
this.compose_message_widget.destroy();
|
||||
}
|
||||
this.compose_message_widget = new mail.ComposeMessage(this, {
|
||||
'extended_mode': false, 'uid': this.options.uid, 'res_model': this.options.context.res_model,
|
||||
'res_id': this.options.context.res_id, 'mode': mode || 'comment', 'msg_id': msg_id,
|
||||
'formatting': formatting || false, 'context': context || false } );
|
||||
'res_model': this.options.context.res_model, 'res_id': this.options.context.res_id,
|
||||
'composition_mode': mode || 'comment', 'msg_id': msg_id, 'context': context || false } );
|
||||
var composition_node = this.$element.find('div.oe_mail_thread_action');
|
||||
composition_node.empty();
|
||||
var compose_done = this.compose_message_widget.appendTo(composition_node);
|
||||
|
|
|
@ -102,15 +102,15 @@
|
|||
<!-- dropdown menu with message options and actions -->
|
||||
<span class="oe_dropdown_toggle oe_dropdown_arrow">
|
||||
<ul class="oe_dropdown_menu">
|
||||
<t t-if="display['show_delete']">
|
||||
<li t-if="record.is_author"><a href="#" class="oe_mail_msg_delete" t-attf-data-id='{record.id}'>Delete</a></li>
|
||||
<t t-if="record.is_author">
|
||||
<li t-if="display['show_delete']"><a href="#" class="oe_mail_msg_delete" t-attf-data-id='{record.id}'>Delete</a></li>
|
||||
</t>
|
||||
<li t-if="display['show_hide']"><a href="#" class="oe_mail_msg_hide" t-attf-data-id='{record.id}'>Hide</a></li>
|
||||
<li t-if="display['show_hide']"><a href="#" class="oe_mail_msg_hide" t-attf-data-id='{record.id}'>Remove notification</a></li>
|
||||
<!-- Uncomment when adding subtype hiding
|
||||
<li t-if="display['show_hide']">
|
||||
<a href="#" class="oe_mail_msg_hide_type" t-attf-data-subtype='{record.subtype}'>Hide '<t t-esc="record.subtype"/>' for this document</a>
|
||||
</li> -->
|
||||
<li><a href="#" t-attf-data-msg_id="{record.id}" t-attf-data-type="{record.type}" t-attf-data-formatting="{record.content_subtype}" class="oe_mail_msg_reply_by_email">Reply by email</a></li>
|
||||
<li><a href="#" t-attf-data-msg_id="{record.id}" class="oe_mail_msg_reply_by_email">Quote and reply</a></li>
|
||||
<li t-if="record.type == 'email'"><a t-attf-href="#model=mail.message&id=#{record.id}" class="oe_mail_msg_details">Details</a></li>
|
||||
</ul>
|
||||
</span>
|
||||
|
|
|
@ -32,81 +32,75 @@ from tools.translate import _
|
|||
EXPRESSION_PATTERN = re.compile('(\$\{.+?\})')
|
||||
|
||||
class mail_compose_message(osv.TransientModel):
|
||||
""" Generic Email composition wizard. This wizard is meant to be inherited
|
||||
at model and view levels to provide specific wizard features.
|
||||
""" Generic message composition wizard. You may inherit from this wizard
|
||||
at model and view levels to provide specific features.
|
||||
|
||||
The behavior of the wizard can be modified through the use of context
|
||||
parameters, among which are:
|
||||
- mail.compose.message.mode:
|
||||
- if set to 'reply', the wizard is a reply to a previous message.
|
||||
It is pre-populated with the original quote
|
||||
- if set to 'comment', it means you are writing a new message to
|
||||
be attached to a document. It is pre-populated with values
|
||||
coming from ``get_value``, related to the document, and that
|
||||
can be overridden to add specific model-related behavior.
|
||||
- if set to 'mass_mail', the wizard is in mass mailing mode where
|
||||
the mail details can contain template placeholders that will be
|
||||
merged with actual data before being sent to each recipient.
|
||||
- active_model: model name of the document to which the mail being
|
||||
composed is related
|
||||
- active_id: id of the document to which the mail being composed is
|
||||
related, or id of the message to which user is replying, in case
|
||||
``mail.compose.message.mode == 'reply'``
|
||||
- active_ids: ids of the documents to which the mail being composed is
|
||||
related, in case ``mail.compose.message.mode == 'mass_mail'``.
|
||||
The behavior of the wizard can be modified through the context key
|
||||
mail.compose.message.mode:
|
||||
- 'reply': reply to a previous message. The wizard is pre-populated
|
||||
via ``get_message_data``.
|
||||
- 'comment': new post on a record. The wizard is pre-populated via
|
||||
``get_record_data``
|
||||
- 'mass_mail': wizard in mass mailing mode where the mail details can
|
||||
contain template placeholders that will be merged with actual data
|
||||
before being sent to each recipient.
|
||||
"""
|
||||
_name = 'mail.compose.message'
|
||||
_inherit = 'mail.message'
|
||||
_description = 'Email composition wizard'
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
""" Overridden to provide specific defaults depending on the context
|
||||
parameters.
|
||||
|
||||
Composition mode
|
||||
- comment: default mode; active_model, active_id = model and ID of a
|
||||
document we are commenting,
|
||||
- mass_mailing mode: active_model, active_id = model and ID of a
|
||||
document we are commenting,
|
||||
- reply: active_id = ID of a mail.message to which we are replying.
|
||||
From this message we can find the related model and res_id,
|
||||
|
||||
:param dict context: several context values will modify the behavior
|
||||
of the wizard, cfr. the class description.
|
||||
""" Handle composition mode. Some details about context keys:
|
||||
- comment: default mode, model and ID of a record the user comments
|
||||
- default_model or active_model
|
||||
- default_res_id or active_id
|
||||
- reply: active_id of a message the user replies to
|
||||
- active_id: ID of a mail.message to which we are replying
|
||||
- message.res_model or default_model
|
||||
- message.res_id or default_res_id
|
||||
- mass_mailing mode: model and IDs of records the user mass-mails
|
||||
- active_ids: record IDs
|
||||
- default_model or active_model
|
||||
"""
|
||||
# get some important values from context
|
||||
if context is None:
|
||||
context = {}
|
||||
compose_mode = context.get('mail.compose.message.mode', 'comment')
|
||||
active_model = context.get('active_model')
|
||||
active_id = context.get('active_id')
|
||||
result = super(mail_compose_message, self).default_get(cr, uid, fields, context=context)
|
||||
|
||||
# get some important values from context
|
||||
composition_mode = context.get('mail.compose.message.mode')
|
||||
model = context.get('default_model', context.get('active_model'))
|
||||
res_id = context.get('default_res_id', context.get('active_id'))
|
||||
active_id = context.get('active_id')
|
||||
active_ids = context.get('active_ids')
|
||||
|
||||
# get default values according to the composition mode
|
||||
vals = {}
|
||||
if compose_mode in ['reply']:
|
||||
vals = self.get_message_data(cr, uid, int(context['active_id']), context=context)
|
||||
elif compose_mode in ['comment', 'mass_mail'] and active_model and active_id:
|
||||
vals = self.get_value(cr, uid, active_model, active_id, context)
|
||||
if composition_mode in ['reply']:
|
||||
vals = self.get_message_data(cr, uid, active_id, context=context)
|
||||
elif composition_mode in ['comment', 'mass_mail'] and model and res_id:
|
||||
vals = self.get_record_data(cr, uid, model, res_id, context=context)
|
||||
else:
|
||||
vals = {'model': model, 'res_id': res_id}
|
||||
if composition_mode:
|
||||
vals['composition_mode'] = composition_mode
|
||||
|
||||
for field in vals:
|
||||
if field in fields:
|
||||
result[field] = vals[field]
|
||||
|
||||
# link to model and record if not done yet
|
||||
if not result.get('model') and active_model:
|
||||
result['model'] = active_model
|
||||
if not result.get('res_id') and active_id:
|
||||
result['res_id'] = active_id
|
||||
return result
|
||||
|
||||
_columns = {
|
||||
'dest_partner_ids': fields.many2many('res.partner',
|
||||
'composition_mode': fields.selection([
|
||||
('comment', 'Comment a document'),
|
||||
('reply', 'Reply to a message'),
|
||||
('mass_mail', 'Mass mailing')
|
||||
], string='Composition mode'),
|
||||
'partner_ids': fields.many2many('res.partner',
|
||||
'mail_compose_message_res_partner_rel',
|
||||
'wizard_id', 'partner_id', 'Destination partners',
|
||||
help="When sending emails through the social network composition wizard"\
|
||||
"you may choose to send a copy of the mail to partners."),
|
||||
'attachment_ids': fields.many2many('ir.attachment','mail_compose_message_ir_attachments_rel',
|
||||
'wizard_id', 'partner_id', 'Additional contacts'),
|
||||
'attachment_ids': fields.many2many('ir.attachment',
|
||||
'mail_compose_message_ir_attachments_rel',
|
||||
'wizard_id', 'attachment_id', 'Attachments'),
|
||||
'auto_delete': fields.boolean('Auto Delete', help="Permanently delete emails after sending"),
|
||||
'filter_id': fields.many2one('ir.filters', 'Filters'),
|
||||
'body_text': fields.text('Plain-text editor body'),
|
||||
'content_subtype': fields.char('Message content subtype', size=32, readonly=1,
|
||||
|
@ -115,46 +109,75 @@ class mail_compose_message(osv.TransientModel):
|
|||
}
|
||||
|
||||
_defaults = {
|
||||
'composition_mode': 'comment',
|
||||
'content_subtype': lambda self,cr, uid, context={}: 'plain',
|
||||
'body_text': lambda self,cr, uid, context={}: '',
|
||||
'body_text': lambda self,cr, uid, context={}: False,
|
||||
'body': lambda self,cr, uid, context={}: '',
|
||||
'subject': lambda self,cr, uid, context={}: False,
|
||||
'partner_ids': [],
|
||||
}
|
||||
|
||||
def get_value(self, cr, uid, model, res_id, context=None):
|
||||
def get_record_data(self, cr, uid, model, res_id, context=None):
|
||||
""" Returns a defaults-like dict with initial values for the composition
|
||||
wizard when sending an email related to the document record
|
||||
identified by ``model`` and ``res_id``.
|
||||
|
||||
The default implementation returns an empty dictionary, and is meant
|
||||
to be overridden by subclasses.
|
||||
|
||||
:param str model: model name of the document record this mail is
|
||||
related to.
|
||||
:param int res_id: id of the document record this mail is related to.
|
||||
:param dict context: several context values will modify the behavior
|
||||
of the wizard, cfr. the class description.
|
||||
:param int res_id: id of the document record this mail is related to
|
||||
"""
|
||||
return {'model': model, 'res_id': res_id}
|
||||
|
||||
def get_message_data(self, cr, uid, message_id, context=None):
|
||||
""" Returns a defaults-like dict with initial values for the composition
|
||||
wizard when replying to the given message (e.g. including the quote
|
||||
of the initial message, and the correct recipients).
|
||||
|
||||
:param int message_id: id of the mail.message to which the user
|
||||
is replying.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
result = {}
|
||||
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
if not message_id:
|
||||
return result
|
||||
|
||||
current_user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
|
||||
message_data = self.pool.get('mail.message').browse(cr, uid, message_id, context=context)
|
||||
|
||||
# create subject
|
||||
re_prefix = _("Re:")
|
||||
reply_subject = tools.ustr(message_data.subject or '')
|
||||
if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)):
|
||||
reply_subject = "%s %s" % (re_prefix, reply_subject)
|
||||
# create the reply in the body
|
||||
reply_header = _('On %(date)s, %(sender_name)s wrote:') % {
|
||||
'date': message_data.date if message_data.date else '',
|
||||
'sender_name': message_data.author_id.name }
|
||||
reply_body = '<div>%s<blockquote>%s</blockquote></div>%s' % (reply_header, message_data.body, current_user.signature)
|
||||
# get partner_ids from original message
|
||||
partner_ids = [partner.id for partner in message_data.partner_ids] if message_data.partner_ids else []
|
||||
|
||||
# update the result
|
||||
result.update({
|
||||
'model': model,
|
||||
'res_id': res_id,
|
||||
'email_from': user.email or tools.config.get('email_from', False),
|
||||
'body': False,
|
||||
'subject': False,
|
||||
'dest_partner_ids': [],
|
||||
'model': message_data.model,
|
||||
'res_id': message_data.res_id,
|
||||
'parent_id': message_data.id,
|
||||
'body': reply_body,
|
||||
'subject': reply_subject,
|
||||
'partner_ids': partner_ids,
|
||||
'content_subtype': 'html',
|
||||
})
|
||||
return result
|
||||
|
||||
def toggle_formatting(self, cr, uid, ids, context=None):
|
||||
def toggle_content_subtype(self, cr, uid, ids, context=None):
|
||||
""" hit toggle formatting mode button: calls onchange_formatting to
|
||||
emulate an on_change, then writes the value to update the form. """
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
content_st_new_value = 'plain' if record.content_subtype == 'html' else 'html'
|
||||
onchange_res = self.onchange_content_subtype(cr, uid, ids, content_st_new_value, record.model, record.res_id, context=context)
|
||||
self.write(cr, uid, [record.id], onchange_res['value'], context=context)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def onchange_content_subtype(self, cr, uid, ids, value, model, res_id, context=None):
|
||||
""" onchange_content_subtype (values: 'plain' or 'html'). This onchange
|
||||
|
@ -164,12 +187,10 @@ class mail_compose_message(osv.TransientModel):
|
|||
This method can be overridden for models that want to have their
|
||||
specific behavior.
|
||||
"""
|
||||
if value == 'plain':
|
||||
return {'value': {'subject': False, 'content_subtype': value}}
|
||||
return {'value': {'content_subtype': value}}
|
||||
|
||||
def onchange_dest_partner_ids(self, cr, uid, ids, value, context=None):
|
||||
""" onchange_dest_partner_ids (value format: [[6, False, [3, 4]]]). The
|
||||
def onchange_partner_ids(self, cr, uid, ids, value, context=None):
|
||||
""" onchange_partner_ids (value format: [[6, False, [3, 4]]]). The
|
||||
basic purpose of this method is to check that destination partners
|
||||
effectively have email addresses. Otherwise a warning is thrown.
|
||||
"""
|
||||
|
@ -189,94 +210,40 @@ class mail_compose_message(osv.TransientModel):
|
|||
}
|
||||
return {'warning': warning, 'value': {}}
|
||||
|
||||
def get_message_data(self, cr, uid, message_id, context=None):
|
||||
""" Returns a defaults-like dict with initial values for the composition
|
||||
wizard when replying to the given message (e.g. including the quote
|
||||
of the initial message, and the correct recipient). It should not be
|
||||
called unless ``context['mail.compose.message.mode'] == 'reply'``.
|
||||
|
||||
:param int message_id: id of the mail.message to which the user
|
||||
is replying.
|
||||
:param dict context: several context values will modify the behavior
|
||||
of the wizard, cfr. the class description.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
result = {}
|
||||
if not message_id:
|
||||
return result
|
||||
|
||||
current_user = self.pool.get('res.users').browse(cr, uid, uid, context)
|
||||
message_data = self.pool.get('mail.message').browse(cr, uid, message_id, context)
|
||||
# Form the subject
|
||||
re_prefix = _("Re:")
|
||||
reply_subject = tools.ustr(message_data.subject or '')
|
||||
if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)):
|
||||
reply_subject = "%s %s" % (re_prefix, reply_subject)
|
||||
|
||||
# Form the bodies (text and html). We use the plain text version of the
|
||||
# original mail, by default, as it is easier to quote than the HTML
|
||||
# version. TODO: make it possible to switch to HTML on the fly
|
||||
|
||||
sent_date = _('On %(date)s, ') % {'date': message_data.date} if message_data.date else ''
|
||||
sender = _('%(sender_name)s wrote:') % {'sender_name': tools.ustr(message_data.email_from or _('You'))}
|
||||
|
||||
body = message_data.body or ''
|
||||
quoted_body = '<blockquote>%s</blockquote>' % (tools.ustr(body)),
|
||||
reply_body = '<br /><br />%s%s<br />%s<br />%s' % (sent_date, sender, quoted_body, current_user.signature)
|
||||
|
||||
# form dest_partner_ids
|
||||
dest_partner_ids = [partner.id for partner in message_data.partner_ids]
|
||||
|
||||
# update the result
|
||||
result.update({
|
||||
'body': reply_body,
|
||||
'subject': reply_subject,
|
||||
'dest_partner_ids': dest_partner_ids,
|
||||
'model': message_data.model or False,
|
||||
'res_id': message_data.res_id or False,
|
||||
})
|
||||
return result
|
||||
|
||||
def send_mail(self, cr, uid, ids, context=None):
|
||||
'''Process the wizard contents and proceed with sending the corresponding
|
||||
email(s), rendering any template patterns on the fly if needed.
|
||||
If the wizard is in mass-mail mode (context['mail.compose.message.mode'] is
|
||||
set to ``'mass_mail'``), the resulting email(s) are scheduled for being
|
||||
sent the next time the mail.message scheduler runs, or the next time
|
||||
``mail.message.process_email_queue`` is called.
|
||||
Otherwise the new message is sent immediately.
|
||||
|
||||
:param dict context: several context values will modify the behavior
|
||||
of the wizard, cfr. the class description.
|
||||
'''
|
||||
""" Process the wizard content and proceed with sending the related
|
||||
email(s), rendering any template patterns on the fly if needed. """
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
formatting = context.get('formatting')
|
||||
# FIXME TODO: mass_mail_mode unused?
|
||||
mass_mail_mode = context.get('mail.compose.message.mode') == 'mass_mail'
|
||||
for wizard in self.browse(cr, uid, ids, context=context):
|
||||
mass_mail_mode = wizard.composition_mode == 'mass_mail'
|
||||
|
||||
for mail_wiz in self.browse(cr, uid, ids, context=context):
|
||||
attachment = {}
|
||||
for attach in mail_wiz.attachment_ids:
|
||||
for attach in wizard.attachment_ids:
|
||||
attachment[attach.datas_fname] = attach.datas and attach.datas or False
|
||||
|
||||
# default values, according to the wizard options
|
||||
subject = mail_wiz.subject if formatting else False
|
||||
# FIXME TODO: partner_ids not used??
|
||||
partner_ids = [partner.id for partner in mail_wiz.dest_partner_ids]
|
||||
body = mail_wiz.body_html if mail_wiz.content_subtype == 'html' else mail_wiz.body
|
||||
subject = wizard.subject if wizard.content_subtype == 'html' else False
|
||||
partner_ids = [partner.id for partner in wizard.partner_ids]
|
||||
body = wizard.body if wizard.content_subtype == 'html' else wizard.body_text
|
||||
|
||||
active_model_pool = self.pool.get('mail.thread')
|
||||
active_id = context.get('default_res_id', False)
|
||||
active_model_pool = self.pool.get(wizard.model if wizard.model else 'mail.thread')
|
||||
|
||||
#TODO: TDE: WIP: have to check for mass mail and templates - no time anymore today
|
||||
if context.get('mail.compose.message.mode') == 'mass_mail' and context.get('default_model', False) and context.get('default_res_id', False):
|
||||
active_model = context.get('default_model', False)
|
||||
active_model_pool = self.pool.get(active_model)
|
||||
subject = self.render_template(cr, uid, subject, active_model, active_id)
|
||||
body = self.render_template(cr, uid, mail_wiz.body_html, active_model, active_id)
|
||||
active_model_pool.message_post(cr, uid, [active_id], body=body, subject=subject, msg_type='comment',
|
||||
attachments=attachment, context=context)
|
||||
body = self.render_template(cr, uid, wizard.body_html, active_model, active_id)
|
||||
|
||||
# determine the ids we are commenting
|
||||
if mass_mail_mode:
|
||||
res_ids = context.get('active_ids', [])
|
||||
else:
|
||||
res_ids = [wizard.res_id]
|
||||
active_model_pool.message_post(cr, uid, res_ids, body=body, subject=subject, msg_type='comment',
|
||||
attachments=attachment, context=context, partner_ids=partner_ids)
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
@ -310,7 +277,7 @@ class mail_compose_message(osv.TransientModel):
|
|||
return template and EXPRESSION_PATTERN.sub(merge, template)
|
||||
|
||||
def dummy(self, cr, uid, ids, context=None):
|
||||
return False
|
||||
|
||||
|
||||
#FIXME: check for models defining '_mail_compose_message'
|
||||
""" TDE: defined to have buttons that do basically nothing. It is
|
||||
currently impossible to have buttons that do nothing special
|
||||
in views (if type not specified, considered as 'object'). """
|
||||
return True
|
||||
|
|
|
@ -38,8 +38,13 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Compose Email" version="7.0" >
|
||||
<group>
|
||||
<field name="composition_mode" colspan="2" nolabel="1" invisible="1"/>
|
||||
<field name="model" colspan="2" nolabel="1" invisible="1"/>
|
||||
<field name="res_id" colspan="2" nolabel="1" invisible="1"/>
|
||||
<field name="parent_id" colspan="2" nolabel="1" invisible="1"/>
|
||||
<!-- truly invisible fields for control and options -->
|
||||
<field name="content_subtype" colspan="2" nolabel="1" invisible="1"/>
|
||||
<!-- visible wizard -->
|
||||
<field name="subject" colspan="2" nolabel="1" placeholder="Subject..."
|
||||
class="oe_mail_compose_message_subject"
|
||||
attrs="{'invisible':[('content_subtype', '=', 'plain')]}"/>
|
||||
|
@ -49,9 +54,9 @@
|
|||
<field name="body" colspan="2" nolabel="1" placeholder="What are you working on ?"
|
||||
class="oe_mail_compose_message_body_html"
|
||||
attrs="{'invisible':[('content_subtype', '=', 'plain')]}"/>
|
||||
<field name="dest_partner_ids" colspan="2" nolabel="1" widget="many2many_tags" placeholder="Add contacts to notify..."
|
||||
<field name="partner_ids" colspan="2" nolabel="1" widget="many2many_tags" placeholder="Add contacts to notify..."
|
||||
context="{'force_create':True}"
|
||||
on_change="onchange_dest_partner_ids(dest_partner_ids)"
|
||||
on_change="onchange_partner_ids(partner_ids)"
|
||||
class="oe_mail_compose_message_partner_ids"/>
|
||||
<field name="attachment_ids" colspan="2" nolabel="1" widget="many2many_tags"
|
||||
placeholder="Add attachments..." invisible="1"
|
||||
|
@ -69,7 +74,7 @@
|
|||
help="Add an attachment"/>
|
||||
<button icon="/mail/static/src/img/formatting.png"
|
||||
class="oe_mail_compose_message_formatting" string=""
|
||||
type="object" name="toggle_formatting"
|
||||
type="object" name="toggle_content_subtype"
|
||||
help="Toggle advanced formatting mode"/>
|
||||
</div>
|
||||
</group>
|
||||
|
|
Loading…
Reference in New Issue