[IMP]mail thread: load only not loaded message

bzr revid: chm@openerp.com-20120928132723-xg2y8j3ebu9a9huv
This commit is contained in:
Christophe Matthieu 2012-09-28 15:27:23 +02:00
parent 96dee3a6b0
commit 20f6a39089
7 changed files with 98 additions and 49 deletions

View File

@ -83,14 +83,14 @@ class mail_notification(osv.Model):
return super(mail_notification, self).create(cr, uid, vals, context=context)
return False
def set_message_read(self, cr, uid, msg_ids, context=None):
def set_message_read(self, cr, uid, msg_ids, read=None, context=None):
if msg_ids == None:
return False
if type(msg_ids) is not list:
msg_ids=[msg_ids]
partner_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).partner_id.id
notif_ids = self.search(cr, uid, [('partner_id', '=', partner_id), ('message_id', 'in', msg_ids)], context=context)
return self.write(cr, uid, notif_ids, {'read': True}, context=context)
return self.write(cr, uid, notif_ids, {'read': read}, context=context)
def get_partners_to_notify(self, cr, uid, partner_ids, message, context=None):
""" Return the list of partners to notify, based on their preferences.

View File

@ -201,7 +201,7 @@ class mail_message(osv.Model):
partner_ids = self.pool.get('res.partner').name_get(cr, uid, [x.id for x in msg.partner_ids], context=context)
except (orm.except_orm, osv.except_osv):
partner_ids = []
return {
'id': msg.id,
'type': msg.type,
@ -302,6 +302,12 @@ class mail_message(osv.Model):
further parents
:return list: list of trees of messages
"""
# don't read the message display by .js, in context message_loaded list
if context and context.get('message_loaded'):
domain += [['id','not in',context.get('message_loaded')]];
limit = limit or self._message_read_limit
context = context or {}
if not ids:
@ -325,13 +331,14 @@ class mail_message(osv.Model):
record_parent['child_ids'].append(record)
record = record_parent
msg = msg.parent_id
if msg.id not in tree:
# if not in record and not in message_loded list
if msg.id not in tree and not(context and context.get('message_loaded') and msg.id in context.get('message_loaded')) :
result.append(record)
tree[msg.id] = record
# Flatten the result
result = self.message_read_tree_flatten(cr, uid, None, result, domain, level, context=context, limit=limit, add_expandable=add_expandable)
return result
result2 = self.message_read_tree_flatten(cr, uid, None, result, domain, level, context=context, limit=limit, add_expandable=add_expandable)
return result2
#------------------------------------------------------
# Email api
@ -483,11 +490,18 @@ class mail_message(osv.Model):
fol_objs = fol_obj.browse(cr, uid, fol_ids, context=context)
extra_notified = set(fol.partner_id.id for fol in fol_objs)
missing_notified = extra_notified - partners_to_notify
missing_notified = missing_notified
if missing_notified:
self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(4, p_id) for p_id in missing_notified]}, context=context)
partners_to_notify |= extra_notified
# # remove uid from partners
self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(3, uid)]}, context=context)
if message.model=="res.partner" and message.res_id==message.author_id.id:
# add myself author if I wrote on my wall
self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(4, message.author_id.id)]}, context=context)
else:
# unless remove myself author
self.write(cr, SUPERUSER_ID, [newid], {'partner_ids': [(3, message.author_id.id)]}, context=context)
self.pool.get('mail.notification').notify(cr, uid, list(partners_to_notify), newid, context=context)
def copy(self, cr, uid, id, default=None, context=None):

View File

@ -94,14 +94,14 @@
<record id="action_mail_inbox_feeds" model="ir.actions.client">
<field name="name">Inbox</field>
<field name="tag">mail.wall</field>
<field name="params" eval="&quot;{'domain': ['&amp;','|','&amp;','&amp;',('notification_ids.partner_id.user_ids', 'in', [uid]),('unread', '=', True),('author_id.user_ids', 'in', [uid]),('type', '=', 'comment'),('unread', '=', True)],
<field name="params" eval="&quot;{'domain': [('notification_ids.partner_id.user_ids', 'in', [uid]),('unread', '=', True)],
'context': {'default_model': 'res.users', 'default_res_id': uid} }&quot;"/>
</record>
<record id="action_mail_archives_feeds" model="ir.actions.client">
<field name="name">Archives</field>
<field name="tag">mail.wall</field>
<field name="params" eval="&quot;{'domain': [('author_id.user_ids', 'in', [uid]),('unread', '=', False)],
<field name="params" eval="&quot;{'domain': [('notification_ids.partner_id.user_ids', 'in', [uid]),('unread', '=', False)],
'context': {'default_model': 'res.users', 'default_res_id': uid} }&quot;"/>
</record>

View File

@ -615,6 +615,7 @@ class mail_thread(osv.AbstractModel):
""" Post a new message in an existing thread, returning the new
mail.message ID. Extra keyword arguments will be used as default
column values for the new mail.message record.
Auto link messages for same id and object
:param int thread_id: thread ID to post into, or list with one ID
:param str body: body of the message, usually raw HTML that will
be sanitized
@ -655,11 +656,12 @@ class mail_thread(osv.AbstractModel):
else:
subtype_id = False
model = context.get('thread_model', self._name) if thread_id else False
messages = self.pool.get('mail.message')
#auto link messages for same id and object
messages = self.pool.get('mail.message')
model = context.get('thread_model', self._name) if thread_id else False
if model != 'res.partner':
if model != 'res.partner' and thread_id:
message_ids = messages.search(cr, uid, ['&',('res_id', '=', thread_id),('model','=',model)], context=context)
if len(message_ids):
parent_id = min(message_ids)

View File

@ -294,7 +294,6 @@ openerp.mail = function(session) {
expandable_max: options.expandable_max || 5,
not_expendable: options.not_expendable || false,
}
// datasets and internal vars
this.id= options.id || false;
this.top_parent= (options.top_parent && options.top_parent.browse_thread) ? options.top_parent : (parent.browse_thread ? parent : this);
@ -337,28 +336,35 @@ openerp.mail = function(session) {
this.$('*').unbind('click');
// event: click on 'More' at bottom of thread
this.$el.on('click', 'a.oe_mail_fetch_more', this.do_message_fetch_more);
// event: writing in basic textarea of composition form (quick reply)
this.$('textarea.oe_mail_compose_textarea').keyup(function (event) {
var charCode = (event.which) ? event.which : window.event.keyCode;
if (event.shiftKey && charCode == 13) { this.value = this.value+"\n"; }
else if (charCode == 13) { return self.message_post(); }
});
// event: click on 'Reply' in msg
this.$el.on('click', 'a.oe_mail_msg_reply', function (event) {
this.$el.on('click', 'a.oe_reply', function (event) {
var act_dom = $(this).parents('li.oe_mail_thread_msg').eq(0).find('div.oe_mail_thread_action:first');
act_dom.toggle();
});
// event: writing in basic textarea of composition form (quick reply)
// event: onblur for hide 'Reply'
this.$('textarea.oe_mail_compose_textarea:first')
.keyup(function (event) {
var charCode = (event.which) ? event.which : window.event.keyCode;
if (event.shiftKey && charCode == 13) { this.value = this.value+"\n"; }
else if (charCode == 13) { return self.message_post(); }
})
.blur(function (event) {
$(this).parents('.oe_mail_thread_action:first').toggle();
});
// event: click on 'Attachment(s)' in msg
this.$el.on('click', 'a.oe_mail_msg_view_attachments', function (event) {
var act_dom = $(this).parent().parent().parent().find('.oe_mail_msg_attachments');
act_dom.toggle();
});
// event: click on icone 'Read' in header
this.$el.on('click', 'a.oe_read', this.on_message_read);
this.$el.on('click', 'a.oe_read', this.on_message_read_unread);
// event: click on icone 'UnRead' in header
this.$el.on('click', 'a.oe_unread', this.on_message_read_unread);
// event: click on 'Delete' in msg side menu
this.$el.on('click', 'a.oe_mail_msg_delete', this.on_message_delete);
// event: click on 'Reply by email' in msg side menu
this.$el.on('click', 'a.oe_mail_msg_reply_by_email', function (event) {
this.$el.on('click', 'a.oe_reply_by_email', function (event) {
if (! self.compose_message_widget) return true;
var msg_id = event.srcElement.dataset.msg_id;
if (! msg_id) return false;
@ -373,17 +379,7 @@ openerp.mail = function(session) {
on_message_delete: function (event) {
if (! confirm(_t("Do you really want to delete this message?"))) { return false; }
var msg_id = event.srcElement.dataset.id;
if (! msg_id) return false;
$(event.srcElement).parents('li.oe_mail_thread_msg').eq(0).remove();
return this.ds_message.unlink([parseInt(msg_id)]);
},
/*The selected thread and all childs (messages/thread) became read
* @param {object} mouse envent
*/
on_message_read: function (event) {
//TDE: TODO
var source = $(event.srcElement).parents('[data-msg_id]:first');
var msg_id = source.data("msg_id");
var msg_model = source.data("msg_model");
@ -392,12 +388,29 @@ openerp.mail = function(session) {
var thread=this.browse_thread({'id':msg_id, 'model':msg_model});
if(thread){
thread.animated_destroy({fadeTime:250});
var ids = [thread.id]
// delete this thread and his childs
var ids = ids.concat( thread.get_child_thread_ids() );
this.ds_message.unlink(ids);
}
},
/*The selected thread and all childs (messages/thread) became read
* @param {object} mouse envent
*/
on_message_read_unread: function (event) {
var source = $(event.srcElement).parents('[data-msg_id]:first');
var msg_id = source.data("msg_id");
var msg_model = source.data("msg_model");
if (!msg_id || !msg_model) return false;
var thread=this.browse_thread({'id':msg_id, 'model':msg_model});
if(thread){
thread.animated_destroy({fadeTime:250});
var ids = [thread.id]
// if this thread is read, all childs thread display is read
var ids = ids.concat( thread.get_child_thread_ids() );
thread.ds_notification.call('set_message_read', [ids]);
thread.ds_notification.call('set_message_read', [ids,$(event.srcElement).hasClass("oe_read")]);
}
},
@ -428,7 +441,7 @@ openerp.mail = function(session) {
return this.top_parent.browse_thread(options);
}
if(this.id && this.model){
if(options.id && options.model){
if(this.id==options.id && this.model==options.model)
return this;
@ -448,7 +461,7 @@ openerp.mail = function(session) {
animated_destroy: function(options) {
var self=this;
//graphic effects
//graphic effects
if(options.fadeTime)
self.$el.parents(".oe_mail_thread_msg:first").fadeOut(options.fadeTime, function(){
self.destroy();
@ -490,6 +503,7 @@ openerp.mail = function(session) {
/** Instantiate the composition form, with every parameters in context
or in the widget context. */
instantiate_composition_form: function(context) {
var self=this;
if (this.compose_message_widget) {
this.compose_message_widget.destroy();
}
@ -498,7 +512,12 @@ openerp.mail = function(session) {
});
var composition_node = this.$('div.oe_mail_thread_action');
composition_node.empty();
var compose_done = this.compose_message_widget.appendTo(composition_node);
var compose_done = this.compose_message_widget.appendTo(composition_node)
.then(function(){
self.$("button.oe_mail_compose_message_button_send").mouseup(function(){
self.browse_thread({'top_thread':1}).message_fetch();
});
});
return compose_done;
},
@ -524,6 +543,12 @@ openerp.mail = function(session) {
// domain and context: options + additional
fetch_domain = _.flatten([this.domain, additional_domain || []], true);
fetch_context = _.extend({}, this.context, additional_context || {});
fetch_context.message_loaded=[];
self.$("li[data-msg_id][data-msg_model]").each(function(){
fetch_context.message_loaded.push($(this).data("msg_id"))
});
// initial mode: try to use message_data or message_ids
if (initial_mode && this.options.message_data) {
return this.message_display_create_thread(this.options.message_data);
@ -548,6 +573,11 @@ openerp.mail = function(session) {
$(rendered).appendTo(self.$el.children('ul.oe_mail_thread_display:first'));
}
else if(inc<=self.options.expandable_max) {
//if thread exists, don't create new thread
if(self.browse_thread({'model': record.model,'id': record.id,}))
return false;
/*create thread*/
var thread = new mail.Thread(self, self.domain,
{ 'default_model': record.model,
@ -558,7 +588,7 @@ openerp.mail = function(session) {
'message_data': record.child_ids,
'thread_level': self.options.thread_level - 1,
'show_header_compose': false,
'show_reply': self.options.show_reply && self.options.thread_level > 1,
'show_reply': self.options.show_reply,
'show_reply_by_email': self.options.show_reply_by_email,
'show_dd_hide': self.options.show_dd_hide,
'show_dd_delete': self.options.show_dd_delete,
@ -647,6 +677,8 @@ openerp.mail = function(session) {
else
$rendered.prependTo(this.$('> ul.oe_mail_thread_display:first'));
$rendered.hide().fadeIn(750);
this.$('> div.oe_mail_msg_body').expander({
slicePoint: this.options.truncate_limit,
@ -882,7 +914,7 @@ openerp.mail = function(session) {
{ 'thread_level': this.options.thread_level,
'use_composer': true,
'show_reply': this.options.thread_level > 0,
'show_dd_hide': true
'show_dd_hide': true,
}
);

View File

@ -112,9 +112,10 @@
<!-- message actions (read/unread, reply, delete...) -->
<ul class="oe_header">
<li t-if="options.thread_level>0"><a class="oe_read oe_e">W<!-- Read/Unread --></a></li>
<li t-if="options.show_reply"><a class="oe_mail_msg_reply oe_e">)</a></li>
<li t-if="options.show_reply_by_email"><a class="oe_mail_msg_reply_by_email oe_e">)</a></li>
<li t-if="options.thread_level>0 and record.unread"><a class="oe_read oe_e">W</a></li>
<li t-if="options.thread_level>0 and !record.unread"><a class="oe_unread oe_e">h</a></li>
<li t-if="options.thread_level>0 and options.show_reply"><a class="oe_reply oe_e">)</a></li>
<li t-if="options.show_reply_by_email"><a class="oe_reply_by_email oe_e">)</a></li>
<li>
<span class="oe_dropdown_toggle">
<a class="oe_e">é</a>
@ -124,7 +125,7 @@
<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 t-if="options.show_dd_reply_by_email"><a class="oe_mail_msg_reply_by_email">Quote and reply</a></li>
<li t-if="options.show_dd_reply_by_email"><a class="oe_reply_by_email">Quote and reply</a></li>
<li t-if="record.type == 'email'"><a class="oe_mail_msg_details" t-attf-href="#model=mail.message&amp;id=#{record.id}" >Details</a></li>
</ul>
</span>
@ -173,6 +174,7 @@
</div>
</div>
</li>
<!-- expandable message layout -->
<li t-name="mail.thread.message.expandable" class="oe_mail oe_mail_thread_msg" t-attf-data-msg_model="{record.model}" t-attf-data-msg_id="{record.id}" data-msg_timestamp="-1">
<div t-attf-class="oe_mail_msg_expandable oe_semantic_html_override">

View File

@ -217,10 +217,6 @@ class mail_compose_message(osv.TransientModel):
def send_mail(self, cr, uid, ids, context=None):
""" Process the wizard content and proceed with sending the related
email(s), rendering any template patterns on the fly if needed. """
print ""
print "send_mail", ids, context
if context is None:
context = {}
active_ids = context.get('active_ids')
@ -256,7 +252,10 @@ class mail_compose_message(osv.TransientModel):
# post process: update attachments, because id is not necessarily known when adding attachments in Chatter
self.pool.get('ir.attachment').write(cr, uid, [attach.id for attach in wizard.attachment_ids], {'res_id': wizard.id}, context=context)
return {'type': 'ir.actions.act_window_close'}
if context.get('mail_action_wizard_close'):
return {'type': 'ir.actions.act_window_close'}
else:
return False
def render_message(self, cr, uid, wizard, res_id, context=None):
""" Generate an email from the template for given (wizard.model, res_id)