if parent_message and current_level < level:
base_domain += [('parent_id', '=', parent_message['id'])]
elif parent_message:
- base_domain += [('id', 'child_of', parent_message['id'])]
+ base_domain += [('id', 'child_of', parent_message['id']), ('id', '!=', parent_message['id'])]
if domain:
base_domain += domain
extension = { 'type': 'expandable',
}
return extension
- def message_read_tree_flatten(self, cr, uid, parent_message, messages, domain=[], level=0, current_level=0, context=None, limit=None):
+ def message_read_tree_flatten(self, cr, uid, parent_message, messages, domain=[], level=0, current_level=0, context=None, limit=None, add_expandable=True):
""" Given a tree with several roots of following structure :
[ {'id': 1, 'child_ids': [
{'id': 11, 'child_ids': [...] },],
child_ids = msg_dict.pop('child_ids', [])
msg_dict['child_ids'] = []
return [msg_dict] + child_ids
+
context = context or {}
limit = limit or self._message_read_limit
+
# Depth-first flattening
for message in messages:
if message.get('type') == 'expandable':
continue
- message['child_ids'] = self.message_read_tree_flatten(cr, uid, message, message['child_ids'], domain, level, current_level + 1, context=context)
+ message['child_ids'] = self.message_read_tree_flatten(cr, uid, message, message['child_ids'], domain, level, current_level + 1, context=context, limit=limit)
for child in message['child_ids']:
+ if child.get('type') == 'expandable':
+ continue
message['child_nbr'] += child['child_nbr']
# Flatten if above maximum depth
if current_level < level:
return_list = messages
else:
return_list = [flat_message for message in messages for flat_message in _flatten(message)]
+
# Add expandable
return_list = sorted(return_list, key=itemgetter(context.get('sort_key', 'id')), reverse=context.get('sort_reverse', True))
- if current_level == 0:
- expandable = self.message_read_tree_get_expandable(cr, uid, parent_message, return_list and return_list[-1] or parent_message, [], current_level, level, context=context)
- if len(return_list) >= limit:
- print 'we need an expandable here'
- print 'expandable', expandable
- elif current_level <= level:
- expandable = self.message_read_tree_get_expandable(cr, uid, parent_message, return_list and return_list[-1] or parent_message, [], current_level, level, context=context)
- print 'expandable', expandable
+ if return_list and current_level == 0 and add_expandable:
+ expandable = self.message_read_tree_get_expandable(cr, uid, parent_message, return_list and return_list[-1] or parent_message, domain, current_level, level, context=context)
+ return_list.append(expandable)
+ elif return_list and current_level <= level and add_expandable:
+ expandable = self.message_read_tree_get_expandable(cr, uid, parent_message, return_list and return_list[-1] or parent_message, domain, current_level, level, context=context)
+ return_list.append(expandable)
return return_list
- def message_read(self, cr, uid, ids=False, domain=[], level=0, context=None, limit=None, parent_id=False):
+ def message_read(self, cr, uid, ids=False, domain=[], level=0, context=None, parent_id=False, limit=None):
""" Read messages from mail.message, and get back a structured tree
of messages to be displayed as discussion threads. If IDs is set,
fetch these records. Otherwise use the domain to fetch messages.
further parents
:return list: list of trees of messages
"""
- limit = limit or self._message_read_limit
context = context or {}
if not ids:
ids = self.search(cr, uid, domain, context=context, limit=limit)
messages = self.browse(cr, uid, ids, context=context)
+ add_expandable = (len(messages) >= limit)
# key: ID, value: record
tree = {}
tree[msg.id] = record
# Flatten the result
- result = self.message_read_tree_flatten(cr, uid, None, result, domain, level, context=context)
+ result = self.message_read_tree_flatten(cr, uid, None, result, domain, level, context=context, limit=limit, add_expandable=add_expandable)
return result
#------------------------------------------------------
height: 28px;
}
-.openerp div.oe_mail_msg_content {
- position: relative;
- width: 486px;
-}
-
-.openerp div.oe_mail_msg_content > li {
- float: left;
- margin-right: 3px;
-}
-
.openerp div.oe_mail_thread_subthread div.oe_mail_msg_content {
width: 440px;
}
margin: 0 0 4px 0;
}
-.openerp .oe_mail_msg_notification,
-.openerp .oe_mail_msg_comment,
+.openerp .oe_mail_msg_notification,
+.openerp .oe_mail_msg_expandable,
+.openerp .oe_mail_msg_comment,
.openerp .oe_mail_msg_email {
padding: 8px;
background: white;
border-top: 1px solid #ccc;
}
+.openerp div.oe_mail_thread_subthread .oe_mail_msg_expandable,
.openerp div.oe_mail_thread_subthread .oe_mail_msg_comment {
background: #eee;
}
clear: both;
}
-.openerp .oe_mail_msg_content {
+.openerp div.oe_mail_msg_content {
+ float: right;
+ position: relative;
+ width: 486px;
+}
+
+.openerp div.oe_mail_msg_content > li {
float: left;
+ margin-right: 3px;
}
.openerp .oe_mail_msg_content:after {
/**
* ------------------------------------------------------------
- * Sidebar
- * ------------------------------------------------------------
- *
- * Override of sidebar do_attachment_new method, to catch attachments added
- * through the sidebar and show them in the Chatter composition form.
- */
-
- // session.web.Sidebar = session.web.Sidebar.extend({
- // do_attachment_new: function(attachment) {
- // this._super(attachment);
- // var message_ids = this.getParent().fields.message_ids || undefined;
- // if (! message_ids) { return; }
- // var compose_message_widget = message_ids.thread.compose_message_widget;
- // if (! compose_message_widget) { return; }
- // compose_message_widget.attachments.push(attachment);
- // compose_message_widget.display_attachments();
- // },
- // });
-
- /**
- * ------------------------------------------------------------
* ChatterUtils
* ------------------------------------------------------------
*
show_dd_reply_by_email:options.show_dd_reply_by_email != undefined ? options.show_dd_reply_by_email: true,
show_dd_delete: options.show_dd_delete || false,
show_dd_hide: options.show_dd_hide || false,
- show_more: options.show_more || false,
truncate_limit: options.truncate_limit || 250,
}
// datasets and internal vars
bind_events: function() {
var self = this;
// event: click on 'More' at bottom of thread
- this.$el.on('click', 'button.oe_mail_button_more', this.do_message_fetch_more);
+ 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.$el.find('textarea.oe_mail_compose_textarea').keyup(function (event) {
var charCode = (event.which) ? event.which : window.event.keyCode;
'default_parent_id': this.context.default_parent_id,
'default_content_subtype': 'plain'} );
}
- // return this._super(action, on_close);
},
/** Instantiate the composition form, with every parameters in context
message_fetch: function (initial_mode, additional_domain, additional_context) {
var self = this;
// domain and context: options + additional
- fetch_domain = _.flatten([this.domain, additional_domain || []], true)
- fetch_context = _.extend(this.context, additional_context || {})
+ fetch_domain = _.flatten([this.domain, additional_domain || []], true);
+ fetch_context = _.extend({}, this.context, additional_context || {});
// initial mode: try to use message_data or message_ids
if (initial_mode && this.options.message_data) {
return this.message_display(this.options.message_data);
}
message_ids = initial_mode && this.options.message_ids != null && this.options.message_ids || false;
- return this.ds_message.call('message_read', [message_ids, fetch_domain, this.options.thread_level, fetch_context]
+ return this.ds_message.call('message_read', [message_ids, fetch_domain, this.options.thread_level, fetch_context, this.context.default_parent_id || undefined]
).then(this.proxy('message_display'));
},
*/
message_display: function (records) {
var self = this;
- var _expendable = false;
_(records).each(function (record) {
if (record.type == 'expandable') {
- _expendable = true;
- self.update_fetch_more(true);
self.fetch_more_domain = record.domain;
self.fetch_more_context = record.context;
+ var rendered = session.web.qweb.render('mail.thread.message.expandable', {'record': record});
+ $(rendered).appendTo(self.$el.children('div.oe_mail_thread_display:first'));
}
else {
self.display_record(record);
self.thread.appendTo(self.$el.find('div.oe_mail_thread_subthread:last'));
}
});
- if (! _expendable) {
- this.update_fetch_more(false);
- }
},
/** Displays a record and performs some formatting on the record :
vote_node.html(vote_element);
},
- /** Display 'show more' button */
- update_fetch_more: function (new_value) {
- if (new_value) {
- this.$el.find('div.oe_mail_thread_more:last').show();
- } else {
- this.$el.find('div.oe_mail_thread_more:last').hide();
- }
- },
-
display_user_avatar: function () {
var avatar = mail.ChatterUtils.get_image(this.session, 'res.users', 'image_small', this.session.uid);
return this.$el.find('img.oe_mail_icon').attr('src', avatar);
}
return this.ds_thread.call('message_post', [
[this.context.default_res_id], body, false, 'comment', this.context.default_parent_id, undefined]
- ).then(self.message_fetch());
+ ).pipe(self.message_clean()).pipe(self.message_fetch(false));
},
/** Action: 'shows more' to fetch new messages */
- do_message_fetch_more: function () {
+ do_message_fetch_more: function (event) {
+ event.stopPropagation();
+ $(event.srcElement).parents('li').eq(0).remove();
return this.message_fetch(false, this.fetch_more_domain, this.fetch_more_context);
},
-
- // TDE: keep currently because need something similar
- // /**
- // * Create a domain to fetch new comments according to
- // * comment already present in comments_structure
- // * @param {Object} comments_structure (see chatter utils)
- // * @returns {Array} fetch_domain (OpenERP domain style)
- // */
- // get_fetch_domain: function (comments_structure) {
- // var domain = [];
- // var ids = comments_structure.root_ids.slice();
- // var ids2 = [];
- // // must be child of current parent
- // if (this.options.parent_id) { domain.push(['id', 'child_of', this.options.parent_id]); }
- // _(comments_structure.root_ids).each(function (id) { // each record
- // ids.push(id);
- // ids2.push(id);
- // });
- // if (this.options.parent_id != false) {
- // ids2.push(this.options.parent_id);
- // }
- // // must not be children of already fetched messages
- // if (ids.length > 0) {
- // domain.push('&');
- // domain.push('!');
- // domain.push(['id', 'child_of', ids]);
- // }
- // if (ids2.length > 0) {
- // domain.push(['id', 'not in', ids2]);
- // }
- // return domain;
- // },
});
<div class="oe_mail_thread_display">
<!-- contains the threads -->
</div>
- <div class="oe_mail_thread_more">
+<!-- <div class="oe_mail_thread_more">
<button class="oe_mail_button_more" type="button">Load more messages</button>
- </div>
+ </div> -->
</ul>
<!-- default layout -->
</div>
</li>
+ <!-- expandable message layout -->
+ <li t-name="mail.thread.message.expandable" class="oe_mail oe_mail_thread_msg">
+ <div t-attf-class="oe_mail_msg_expandable oe_semantic_html_override">
+ <div class="oe_mail_msg_content">
+ <!-- message itself -->
+ <div class="oe_mail_msg">
+ <div class="oe_mail_msg_body">
+ <a class="oe_mail_fetch_more">Load more messages ...</a>
+ </div>
+ <div class="oe_clear"/>
+ </div>
+ </div>
+ </div>
+ </li>
+
<!--
mail.thread.message.attachments template
Template used to display attachments in a mail.message
group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
def _compare_structures(struct1, struct2, n=0):
- print '%scompare structure' % ('\t' * n)
- self.assertEqual(len(struct1), len(struct2), 'message_read structure number of childs incorrect')
+ # print '%scompare structure' % ('\t' * n)
+ # self.assertEqual(len(struct1), len(struct2), 'message_read structure number of childs incorrect')
for x in range(len(struct1)):
- print '%s' % ('\t' * n), struct1[x]['id'], struct1[x]['child_nbr'], struct2[x]['id'], struct2[x]['child_nbr'], struct1[x].get('subject') or ''
+ if struct1[x].get('type') == 'expandable':
+ continue
+ # print '%s' % ('\t' * n), struct1[x]['id'], struct1[x]['child_nbr'], struct2[x]['id'], struct2[x].get('child_nbr', 'XX'), struct1[x].get('subject') or ''
self.assertEqual(struct1[x]['id'], struct2[x]['id'], 'message_read failure %s' % struct1[x].get('subject'))
_compare_structures(struct1[x]['child_ids'], struct2[x]['child_ids'], n + 1)
- print '%send compare' % ('\t' * n)
+ # print '%send compare' % ('\t' * n)
# ----------------------------------------
# CASE1: Flattening test
]},
]
# Test: completely flat
- new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 0)
+ new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 0, limit=15, add_expandable=False)
_compare_structures(new_tree, new_tree)
self.assertEqual(len(new_tree), 10, 'message_read_tree_flatten wrong in flat')
# Test: 1 thread level
{'id': 4, 'child_ids': []}, {'id': 3, 'child_ids': []},
]},
]
- new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 1)
+ new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 1, limit=15, add_expandable=False)
_compare_structures(new_tree, tree_test)
# Test: 2 thread levels
- new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 2)
+ new_tree = self.mail_message.message_read_tree_flatten(cr, uid, None, copy.deepcopy(tree), [('type', 'in', 'borderlands')], 2, limit=15, add_expandable=False)
_compare_structures(new_tree, tree)
# ----------------------------------------
tree_test = [{'id': msgid6, 'child_ids': []}, {'id': msgid5, 'child_ids': []},
{'id': msgid4, 'child_ids': []}, {'id': msgid3, 'child_ids': []},
{'id': msgid2, 'child_ids': []}, {'id': msgid1, 'child_ids': []}]
- tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], thread_level=0, limit=10)
+ tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], level=0, limit=15)
_compare_structures(tree, tree_test)
# Test: read with 1 level of thread
tree_test = [{'id': msgid4, 'child_ids': [{'id': msgid6, 'child_ids': []}, ]},
{'id': msgid2, 'child_ids': []},
]},
]
- tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], thread_level=1, limit=10)
+ tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], level=1, limit=15)
_compare_structures(tree, tree_test)
# Test: read with 2 levels of thread
tree_test = [{'id': msgid4, 'child_ids': [{'id': msgid6, 'child_ids': []}, ]},
{'id': msgid2, 'child_ids': [{'id': msgid5, 'child_ids': []}, ]},
]},
]
- tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], thread_level=2, limit=10)
+ tree = self.mail_message.message_read(cr, uid, ids=False, domain=[('model', '=', 'mail.group'), ('res_id', '=', self.group_pigs_id)], level=2, limit=15)
_compare_structures(tree, tree_test)
# 2. Test expandables