[IMP] mail: hierarchy/flat options

bzr revid: chm@openerp.com-20121016113841-gqgq8oz89yc2gma7
This commit is contained in:
Christophe Matthieu 2012-10-16 13:38:41 +02:00
parent 7084273c5c
commit 0e4fcab679
5 changed files with 114 additions and 55 deletions

View File

@ -260,6 +260,8 @@ class mail_message(osv.Model):
create the expandable message for all parent message read
this function is used by message_read
"""
# sort for group items
tree = sorted(tree, key=lambda k: k['id'])
tree_not = []
# expandable for not show message
@ -323,9 +325,6 @@ class mail_message(osv.Model):
'id': -1
});
result = sorted(result, key=lambda k: k['id'])
return result
def message_read(self, cr, uid, ids=False, domain=[], level=0, context=None, parent_id=False, limit=None):
@ -352,54 +351,58 @@ class mail_message(osv.Model):
tree = []
message_ids = []
record = None
result = []
# select ids
if ids and ids!=[None]:
for msg in self.browse(cr, uid, ids, context=context):
message_ids.append(msg.id)
result = []
for msg in self.browse(cr, uid, message_ids, context=context):
record = self._message_dict_get(cr, uid, msg, context=context)
result.append( record )
if msg.id not in message_ids:
message_ids.append(msg.id)
record = self._message_dict_get(cr, uid, msg, context=context)
result.append( record )
# key: ID, value: tree
if not ids:
ids = self.search(cr, uid, domain, context=context, limit=limit)
for msg in self.browse(cr, uid, ids, context=context):
# if not in tree and not in message_loded list
if msg not in tree and msg.id not in message_loaded_ids :
if msg.id not in message_ids and msg.id not in message_loaded_ids :
message_ids.append(msg.id)
tree.append(msg)
#try to get parent message
try:
parent = msg.parent_id
parent = parent.parent_id
except (orm.except_orm, osv.except_osv):
parent = False
# get all parented message if the user have the access
while parent and parent.id != parent_id:
parent_id = msg.parent_id.id
if msg.parent_id.id not in tree:
if msg.parent_id not in tree and parent_id not in message_loaded_ids:
tree.append(parent)
# if not in tree and not in message_loded list
if parent.id not in message_loaded_ids :
if parent.id not in message_ids and parent.id not in message_loaded_ids :
message_ids.append(parent.id)
#try to get parent message
try:
parent = msg.parent_id
except (orm.except_orm, osv.except_osv):
parent = False
else:
parent = False
result = []
# record the dic of message
for msg in self.browse(cr, uid, message_ids, context=context):
record = self._message_dict_get(cr, uid, msg, context=context)
result.append( record )
# get the child expandable messages for the tree
result = self._message_read_expandable(cr, uid, tree, result, message_loaded_ids, domain, context, parent_id, limit)
result = sorted(result, key=lambda k: k['id'])
return result
def user_free_attachment(self, cr, uid, context=None):

View File

@ -5,35 +5,35 @@
<field name="name">Inbox</field>
<field name="tag">mail.wall</field>
<field name="params" eval="&quot;{'domain': [('notification_ids.partner_id.user_ids', 'in', [uid]),('notification_ids.read', '=', False)],
'context': {'default_model': 'res.partner', 'default_is_private': False} }&quot;"/>
'context': {'default_model': 'res.partner', 'default_is_private': False, 'typeof_thread': 'inbox'} }&quot;"/>
</record>
<record id="action_mail_to_me_feeds" model="ir.actions.client">
<field name="name">To: me</field>
<field name="tag">mail.wall</field>
<field name="params" eval="&quot;{'domain': [('partner_ids.user_ids', 'in', [uid]),('notification_ids.read', '=', False),('create_uid', '!=', uid)],
'context': {'default_model': 'res.partner', 'default_is_private': False} }&quot;"/>
'context': {'default_model': 'res.partner', 'default_is_private': False, 'typeof_thread': 'inbox'} }&quot;"/>
</record>
<record id="action_mail_star_feeds" model="ir.actions.client">
<field name="name">Stared</field>
<field name="tag">mail.wall</field>
<field name="params" eval="&quot;{'domain': [('star_user_ids.user_ids', 'in', [uid])],
'context': {'default_model': 'res.partner', 'default_is_private': False} }&quot;"/>
'context': {'default_model': 'res.partner', 'default_is_private': False, 'typeof_thread': 'stared'} }&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': [('notification_ids.partner_id.user_ids', 'in', [uid]),('notification_ids.read', '=', True)],
'context': {'default_model': 'res.partner', 'default_is_private': False} }&quot;"/>
'context': {'default_model': 'res.partner', 'default_is_private': False, 'typeof_thread': 'archives'} }&quot;"/>
</record>
<record id="action_mail_sent_feeds" model="ir.actions.client">
<field name="name">Sent</field>
<field name="tag">mail.wall</field>
<field name="params" eval="&quot;{'domain': [('create_uid', '=', uid)],
'context': {'default_model': 'res.partner', 'default_is_private': False} }&quot;"/>
'context': {'default_model': 'res.partner', 'default_is_private': False, 'typeof_thread': 'send'} }&quot;"/>
</record>
<!-- MENU -->

View File

@ -137,7 +137,7 @@ openerp.mail = function(session) {
this.options={};
this.options.thread={};
this.options.thread.show_header_compose = options.options.thread.show_header_compose;
this.options.thread.display_on_flat = options.options.thread.display_on_flat;
this.options.thread.display_on_hierarchy = options.options.thread.display_on_hierarchy;
this.options.thread.show_attachment_delete = true;
this.options.thread.show_attachment_link = true;
@ -317,7 +317,7 @@ openerp.mail = function(session) {
this.$('input[data-id]').remove();
//this.attachment_ids=[];
this.display_attachments();
if(!this.options.thread.show_header_compose || !this.options.thread.display_on_flat){
if(!this.options.thread.show_header_compose || !this.options.thread.display_on_hierarchy[0]){
this.$el.hide();
}
},
@ -649,17 +649,15 @@ openerp.mail = function(session) {
*/
on_message_read_unread: function (event) {
event.stopPropagation();
if($(event.srcElement).hasClass("oe_read")) this.animated_destroy({fadeTime:250});
// if this message is read, all childs message display is read
var ids = [this.datasets.id].concat( this.get_child_ids() );
if($(event.srcElement).hasClass("oe_read")) {
this.ds_notification.call('set_message_read', [ids,true]);
this.$el.removeClass("oe_mail_unread").addClass("oe_mail_read");
} else {
this.ds_notification.call('set_message_read', [ids,false]);
this.$el.removeClass("oe_mail_read").addClass("oe_mail_unread");
var read = $(event.srcElement).hasClass("oe_read");
this.$el.removeClass("oe_mail_"+(read?"un":"")+"read").addClass("oe_mail_"+(read?"":"un")+"read");
if( (read && this.options.thread.typeof_thread=='inbox') ||
(!read && this.options.thread.typeof_thread=='archives')) {
this.animated_destroy({fadeTime:250});
}
this.ds_notification.call('set_message_read', [ids,read]);
return false;
},
@ -783,8 +781,13 @@ openerp.mail = function(session) {
* for each click on "show more message"
* @param {Number} [expandable_default_number=5] number message show
* on begin before the first click on "show more message"
* @param {Boolean} [display_on_flat] display all thread
* on the wall thread level (no hierarchy)
* @param {Array [A,B]} [display_on_hierarchy] display the threads on hierarchy
* for the thread level between A and B. -1 for no begin or no end.
* All thread before A are insert in the root thread.
* All thread after B are insert in parent thread on B level.
* @param {Select} [typeof_thread] inbox/archives/stared/sent
* type of thread and option for user application like animate
* destroy for read/unread
* @param {Array} [parents] liked with the parents thread
* use with browse, fetch... [O]= top parent
*/
@ -804,14 +807,15 @@ openerp.mail = function(session) {
'expandable_number': options.options.thread.expandable_number || 5,
'expandable_default_number': options.options.thread.expandable_default_number || 5,
'_expandable_max': options.options.thread.expandable_default_number || 5,
'display_on_flat': options.options.thread.display_on_flat || false,
'display_on_hierarchy': options.options.thread.display_on_hierarchy || [0,-1],
'typeof_thread': options.options.thread.typeof_thread || 'inbox',
'_parents': (options.options.thread._parents != undefined ? options.options.thread._parents : []).concat( [this] )
},
'message' : options.options.message
};
// record options and data
this.parent_linked_message= parent.thread!= undefined ? parent : false ;
this.parent_message= parent.thread!= undefined ? parent : false ;
var param = options.parameters
this.datasets = {};
@ -821,7 +825,7 @@ openerp.mail = function(session) {
this.datasets.parent_id= param.parent_id || false;
this.datasets.is_private = param.is_private || false;
this.datasets.author_id = param.author_id || false;
this.datasets.thread_level = param.thread_level-1 || 0
this.datasets.thread_level = param.thread_level+1 || 0
this.datasets.partner_ids = [];
for(var i in param.partner_ids){
@ -850,7 +854,7 @@ openerp.mail = function(session) {
this.bind_events();
if(this.options.thread._parents[0]==this){
this.on_first_thread();
this.on_root_thread();
}
return display_done && compose_done;
@ -869,7 +873,7 @@ openerp.mail = function(session) {
/* this method is runing for first parent thread
*/
on_first_thread: function(){
on_root_thread: function(){
var self=this;
// fetch and display message, using message_ids if set
this.message_fetch();
@ -883,7 +887,7 @@ openerp.mail = function(session) {
this.ComposeMessage.$el.show();
//this.ComposeMessage.set_free_attachments();
}
this.ComposeMessage.is_private=true;
this.ComposeMessage.datasets.is_private=true;
var button_fetch = $('<button style="display:none;" class="oe_mail_wall_button_fetch"/>').click(function(event){
if(event)event.stopPropagation();
@ -924,10 +928,21 @@ openerp.mail = function(session) {
*/
get_child_ids: function(){
var res=[];
for(var i in this.messages){
if(this.messages[i].thread){
res = res.concat( this.messages[i].get_child_ids(true) );
}
_(this.get_childs()).each(function (val, key) { res.push(val.datasets.id); });
return res;
},
/* get all child message/thread linked
*/
get_childs: function(nb_thread_level){
var res=[];
if(arguments[1]) res.push(this);
if(isNaN(nb_thread_level) || nb_thread_level>0){
_(this.messages).each(function (val, key) {
if(val.thread){
res = res.concat( val.thread.get_childs((isNaN(nb_thread_level) ? null : nb_thread_level-1), true) )
}
});
}
return res;
},
@ -1006,6 +1021,8 @@ openerp.mail = function(session) {
fetch_context = replace_context ? replace_context : this.context;
fetch_context.message_loaded= [this.datasets.id||0].concat( self.options.thread._parents[0].get_child_ids() );
console.log(fetch_domain, 0, fetch_context, this.context.default_parent_id);
return this.ds_message.call('message_read', [ids, fetch_domain, 0, fetch_context, this.context.default_parent_id || undefined]
).then(function (records) { self.switch_new_message(records); });
},
@ -1057,8 +1074,44 @@ openerp.mail = function(session) {
});
}
var thread_messages = (self.options.thread.display_on_flat && self.datasets.thread_level ? self.options.thread._parents[0].messages : []).concat(self.messages);
var thread = (self.options.thread.display_on_flat && self.datasets.thread_level ? self.options.thread._parents[0] : self);
// insert on hierarchy display => insert in self child
var thread_messages = self.messages;
var thread = self;
var flat = false;
var hierarchy = self.options.thread.display_on_hierarchy;
if( hierarchy[0] < 0 ||
hierarchy[0] > self.datasets.thread_level ||
(hierarchy[1]>0 && hierarchy[1] < self.datasets.thread_level) ) {
var flat = true;
if(hierarchy[0]<0){
// all is in flat mode
thread = self.options.thread._parents[0];
var nb_thread_level = null;
} else if(hierarchy[0] > self.datasets.thread_level) {
// list all childs messages for flat display before the hierarchy
thread = self.options.thread._parents[0];
var nb_thread_level = hierarchy[0];
} else if(hierarchy[1] < self.datasets.thread_level) {
// list all childs messages for flat display after the hierarchy
thread = self.options.thread._parents[hierarchy[1]];
var nb_thread_level = hierarchy[1]>0 ? hierarchy[1]-hierarchy[0] : null;
} else {
thread = self.options.thread._parents[0];
var nb_thread_level = null;
}
var thread_messages = [];
_(thread.get_childs( nb_thread_level )).each(function (val, key) { thread_messages.push(val.parent_message); });
}
// check older and newer message for insert
var parent_newer = false;
@ -1075,7 +1128,7 @@ openerp.mail = function(session) {
}
}
var sort = self.datasets.thread_level==0 || (self.options.thread.display_on_flat && self.datasets.thread_level<=1);
var sort = self.datasets.thread_level==0 || (flat && self.datasets.thread_level>=1);
if(parent_older){
if(sort){
@ -1083,15 +1136,13 @@ openerp.mail = function(session) {
} else {
message.insertAfter(parent_older.$el);
}
}
else if(parent_newer){
} else if(parent_newer){
if(sort){
message.insertAfter(parent_newer.$el);
} else {
message.insertBefore(parent_newer.$el);
}
}
else {
} else {
if(sort && message.id > 0){
message.prependTo(thread.list_ul);
} else {
@ -1183,7 +1234,7 @@ openerp.mail = function(session) {
'thread':{
'show_header_compose': show_header_compose,
'use_composer': show_header_compose,
'display_on_flat':true
'display_on_hierarchy':[-1]
},
'message':{
'show_dd_delete': true
@ -1276,13 +1327,18 @@ openerp.mail = function(session) {
* Display the threads
*/
message_render: function (search) {
var domain = this.options.domain.concat(this.search_results['domain']);
var context = _.extend(this.options.context, search&&search.search_results['context'] ? search.search_results['context'] : {});
console.log(context);
this.thread = new mail.Thread(this, {
'domain' : this.options.domain.concat(this.search_results['domain']),
'context' : _.extend(this.options.context, search&&search.search_results['context'] ? search.search_results['context'] : {}),
'domain' : domain,
'context' : context,
'options': {
'thread' :{
'use_composer': true,
'show_header_compose': false,
'typeof_thread': context.typeof_thread || 'inbox',
'display_on_hierarchy': [0,1]
},
'message': {
'show_reply': true,

View File

@ -186,8 +186,8 @@
<ul class="oe_header">
<li class="placeholder-mail-vote"><t t-call="mail.thread.message.vote"/></li>
<li class="placeholder-mail-star"><t t-call="mail.thread.message.star"/></li>
<li t-if="!widget.options.thread.display_on_flat and widget.datasets.read=='unread'" title="Read" class="oe_read"><a class="oe_read oe_e">W</a></li>
<li t-if="!widget.options.thread.display_on_flat and widget.datasets.read=='read'" title="Set back to unread" class="oe_unread"><a class="oe_unread oe_e">h</a></li>
<li t-if="!widget.options.thread.display_on_hierarchy[0] and widget.datasets.read=='unread'" title="Read" class="oe_read"><a class="oe_read oe_e">W</a></li>
<li t-if="!widget.options.thread.display_on_hierarchy[0] and widget.datasets.read=='read'" title="Set back to unread" class="oe_unread"><a class="oe_unread oe_e">h</a></li>
<li title="Quick reply"><a class="oe_reply oe_e">)</a></li>
<t t-if="(widget.datasets.is_author and widget.options.message.show_dd_delete) or widget.datasets.type == 'email'">
<li>
@ -224,7 +224,7 @@
</ul>
<div class="oe_clear"/>
<div class="oe_mail_msg_body">
<t t-if="widget.options.message.show_record_name and widget.datasets.record_name and (!widget.datasets.subject) and !widget.options.thread.thread_level and !widget.options.thread.display_on_flat and widget.datasets.model!='res.partner'">
<t t-if="widget.options.message.show_record_name and widget.datasets.record_name and (!widget.datasets.subject) and !widget.options.thread.thread_level and !widget.options.thread.display_on_hierarchy[0] and widget.datasets.model!='res.partner'">
<a class="oe_mail_action_model" t-attf-href="#model=#{widget.datasets.model}&amp;id=#{widget.res_id}"><t t-raw="widget.datasets.record_name"/></a>
</t>
<t t-raw="widget.datasets.body"/>

View File

@ -16,7 +16,7 @@
<field name="partner_ids" widget="many2many_tags" placeholder="Add contacts to notify..."
context="{'force_email':True}"
on_change="onchange_partner_ids(partner_ids)"/>
<field name="is_private" help="If this message is not private, this message will send to all your followers or all followers of the parented message."/>
<field name="is_private" help="If this message is not private, this message will send to all your followers or all followers of the parented message." invisible="1"/>
</group>
<notebook>
<page string="Body">